如何學習 PHP 源碼 - 從編譯開始

PHP Mailing Lists 上這兩天有個好玩兒的問題:Introduction to the PHP source code,大概就是有人想知道如何學習 PHP 源碼,但是這種事情不是應該本身去發掘的嗎?php

上面是玩笑話,如今我也說說如何學習 PHP 解釋器的源碼。html

首選你要知道的是 PHP 解釋器源碼的 github 地址:https://github.com/php/php-src ,話說回來還有人不知道嗎?這裏有幾乎全部 PHP 的代碼提交記錄、pull requests 和一些 issue 等。node

建立編譯腳本或者發佈包

從 Branch 中選擇一個版本 tag,和每次 PHP 發佈出來的版本就是一致的。也許你會發現你想編譯的的時候缺找不到 configure 文件,可是有 configure.in 文件。這時候須要先執行的是 buildconf(若是是在 Windows 下面能夠執行 buildconf.bat,不過我歷來沒有嘗試過在 Windows 下面編譯 PHP,因此具體的步驟我就不清楚了)。buildconf 自己是個簡單的 shell 腳本,你能夠用記事本打開看看它(最終的執行文件在 build 目錄裏,這個目錄裏有一些與編譯有關的文件)。git

這裏面涉及到一個系列的編譯工具:Autotools。若是你有興趣,能夠簡單的瞭解一下,沒有興趣的話也不用多考慮,由於這些工具絕大多數 Linux 系統上都是已經存在的。github

若是你想將 Github 上的 PHP 源碼作成一個可發佈的源碼包,你能夠看看 makedist 這個文件,它也是一個 shell 腳本(實際上源碼裏幾乎全部跟編譯相關的腳本都是 shell 腳本)。可是若是想直接執行者這個腳本,你可能會收到缺乏如下組件的提示:re2cBison。仔細看 makedist 的文件,裏面有調用 genfiles 這個腳本的語句,上面兩個工具就是在 genfiles 的腳本里被調用的。shell

re2c 和 Bison 分別是 PHP 用到的詞法解析器和語法分析器。在 genfiles 這個文件中能夠看到它們的調用實際上是在 Makefile.frag 中寫着,分別經過 zend_language_scanner.lzend_language_parser.y 生成相應的 C 語言文件(這個應該不少地方都有提到過)。api

編譯解釋器並初始化

到了編譯環節,編譯以前須要先經過 configure 文件生成 Makefile 而後執行 make,因此 gcc 天然是必不可少的。configure 文件自己也是一個 shell 腳本,你也能夠簡單閱讀一下它的內容。不過既然它是由 autoconfconfigure.in 中生成的,也許直接查看 configure.in 會更輕鬆一些。服務器

到這裏總結一下就是:拋開一些核心擴展額依賴(好比 xml,ssl 等),編譯 PHP 的先決條件是機器上有 Autotools 的工具(automake,autoconf 等),須要安裝 re2c 和 Bison,固然還有編譯工具(gcc)。php-fpm

也許你們都知道,使用 configure 生成 Makefile 的時候能夠經過 --prefix 參數指定目錄,同時也能夠選擇編譯哪些核心模塊。至於哪些模塊會被默認集成而哪些不會,這些自己是寫在每一個擴展的 config.m4 (也有幾個是被命名爲 config0.m4 或 config9.m4)文件裏的的,全都經過一些 --enable--disable--with--without 的選項來控制。工具

編譯的也與你採用的 Web 服務器有關,這涉及到你須要使用哪一個 sapi,若是是 Apache,也許須要指定 --with-apxs2 的參數,若是是 Nginx,php-fpm 在默認條件下是會被編譯的,但能夠指定 php-fpm 的執行組和用戶,不過這個是能夠在編譯完成後在配置中修改的。

編譯完成以後還有一些事情須要考慮,最基本的問題是 PHP 的配置文件的問題,還有一個是若是使用的是 php-fpm,如何更便捷的控制它的啓動、中止以及重啓等。

在 PHP 源碼根中已經準備了兩份配置文件的模板:php.ini-developmentphp.ini-production。顯然是分別用於開發環境和生產環境的,將其中一個複製到配置文件目錄並重命名爲 php.ini 便可(若是你不知道配置文件的目錄在哪裏,可使用 php --ini 命令查看)。而後也能夠根據你的須要修改它。

至於 php-fpm 的控制腳本,源碼中自己也是有提供的,在 sapi/fpm 目錄下。這個目錄下的幾個文件中有 php-fpm 配置文件的模板,也有稍微修改便可放到服務器 /etc/init.d 目錄下用於控制 php-fpm 的 startstoprestartreload 動做的腳本,如今的版本中也提供了用於 systemd 的 service 文件。

擴展編譯

若是 PHP 編譯完成以後,發現還須要一些沒有編譯進去的核心擴展或者第三方擴展,你能夠單獨編譯它們。

擴展編譯的整個過程一共四句命令:

  1. phpize

  2. ./configure

  3. make

  4. make install

phpize 命令是用來準備 PHP 擴展庫的編譯環境的。在執行 phpize 的時候,若是有多個版本的 PHP,用哪一個就要選哪一個。這個命令和編譯後的 php 的二進制文件在同一個目錄中,也是一個 shell 腳本。

執行 configure 的時候,若是當前 $PATH 中找不到 php-config 或者有多個版本的 PHP 時,也須要經過 --with-php-config 的指令來指定 php-config 的目錄。php-config 是一個用於獲取所安裝的 PHP 配置的信息,它也同樣是和 php 的二進制文件在同一個目錄的 shell 腳本。

phpize 和 php-config 的源碼生成文件都是在 scripts 目錄下。

全部工做完成以後,就能夠愉快的使用你本身定製的 PHP 了。

原文地址:http://0x1.im

相關文章
相關標籤/搜索