章 49. 編譯問題

本節匯集了大多數編譯時出現的常見錯誤。

1. 我用匿名 CVS 得到了最新版的 PHP,但是裡面沒有 configure 腳本!
2. 我在配置 PHP 和 Apache 一起工作時遇到了問題。說沒找到 httpd.h,但這個文件明明就在那裡!
3. 當我試圖啟動 Apache 時,我得到如下錯誤訊息:
4. 當我執行 configure 時,報告說找不到頭文件或 GD 庫或 gdbm,或其它的什麼包!
5. 當編譯 language-parser.tab.c 文件時,報錯說 yytname undeclared
6. 當我執行 make 時,看上去一切正常,可當連接最後的程序時報告說找不到某些文件而失敗了。
7. 當連接 PHP 時,報告說有一些未定義的引用。
8. 我不知道怎樣把 PHP 和 Apache 1.3 一起編譯。
9. 我按照所有的步驟在 UNIX 下安裝了PHP 的 Apache 模塊版本,但我的 PHP 腳本被顯示在瀏覽器中或者提示保存此文件。
10. 說要用:--activate-module=src/modules/php4/libphp4.a,但是此文件根本不存在,於是我改成了 --activate-module=src/modules/php4/libmodphp4.a,結果不行。怎麼回事?
11. 當我用 --activate-module=src/modules/php4/libphp4.a 試著把 PHP 編譯成 Apache 的靜態模塊時,報告說我的編譯器不服從 ANSI 標準。
12. 當我用 --with-apxs 編譯 PHP 時得到奇怪的錯誤訊息。
13. make 的過程中,在 microtime 中出錯,還有很多 RUSAGE_ 之類的東西。
14. 我想升級我的 PHP。上哪裡找到我用來配置目前的 PHP 的 ./configure 的參數呢?
15. 和 GD 庫一起編譯 PHP 時,要麼給出一個奇怪的編譯錯誤,要麼在執行時出現 segfaults。

1. 我用匿名 CVS 得到了最新版的 PHP,但是裡面沒有 configure 腳本!

你必須安裝有 GNU 的 autoconf 包,這樣才可以從 configure.in 產生 configure 腳本。從 CVS 得到源程序後只要在最高層的目錄中執行 ./buildconf 即可。(同樣,除非你用了 --enable-maintainer-mode 選項來執行 configure,否則即使 configure.in 文件更新了,configure 腳本也不會自動重新產生。所以當你發現 configure.in 文件更新了時要確保手工重新產生 configure 腳本。有一個症狀是在 configure 之後或者執行 config.status 時在 Makefile 中尋找類似 @VARIABLE@ 的東西。)

2. 我在配置 PHP 和 Apache 一起工作時遇到了問題。說沒找到 httpd.h,但這個文件明明就在那裡!

你需要告訴 configure/setup 腳本你的 Apache 源程序最上層的目錄位置。這意味著你需要這樣指定 --with-apache=/path/to/apache不是這樣 --with-apache=/path/to/apache/src

3. 當我試圖啟動 Apache 時,我得到如下錯誤訊息:

fatal: relocation error: file /path/to/libphp4.so:
       symbol ap_block_alarms: referenced symbol not found

該錯誤通常在 Apache 的核心程序被編譯為共享用途的 DSO 庫時發生。請嘗試重新配置 Apache,確保至少使用了如下參數:

--enable-shared=max --enable-rule=SHARED_CORE

如果您需要更多訊息,請閱讀 Apache 的頂級 INSTALL 文件或者 Apache 的 DSO 手冊

4. 當我執行 configure 時,報告說找不到頭文件或 GD 庫或 gdbm,或其它的什麼包!

你可以通過指定附加的選項讓 configure 腳本在非標準的路徑中尋找頭文件和庫並傳遞給 C 預處理器和連接器,例如:
CPPFLAGS=-I/path/to/include LDFLAGS=-L/path/to/library ./configure
如果你用 csh 的變種作為你的登陸 shell(為什麼?),那就是:
env CPPFLAGS=-I/path/to/include LDFLAGS=-L/path/to/library ./configure

5. 當編譯 language-parser.tab.c 文件時,報錯說 yytname undeclared

你需要更新 Bison 的版本。最新版本在 ftp://ftp.gnu.org/pub/gnu/bison/

6. 當我執行 make 時,看上去一切正常,可當連接最後的程序時報告說找不到某些文件而失敗了。

一些舊版本的 make 沒有正確將 functions 目錄下編譯後的文件放到同一個目錄下。試試執行 cp *.o functions 然後再執行 make 看看有沒有什麼幫助。如果成功了,那你確實需要更新到最新版的 GNU make。

7. 當連接 PHP 時,報告說有一些未定義的引用。

看看連接的這一行命令,確認所有適當的庫都包括在最後了。你通常可能漏掉了“ldl”和你包括的任何資料庫支援所需要的庫。

如果你和 Apache 1.2.x 一起連接,記得把適當的訊息增加到配置文件的 EXTRA_LIBS 這一行並重新執行 Apache 的配置腳本了嗎?更多訊息參見發行包中的 INSTALL 文件。

一些人也報告說在和 Apache 連接時他們不得不在 libphp4.a 之後立即加上“ldl”。

8. 我不知道怎樣把 PHP 和 Apache 1.3 一起編譯。

這其實很簡單。小心地照著以下步驟來:

  • http://www.apache.org/dist/ 下載最新版的 Apache 1.3。

  • 解壓縮到某處,例如 /usr/local/src/apache-1.3

  • 編譯 PHP,先執行 ./configure --with-apache=/<path>/apache-1.3(用你 apache-1.3 所在的真實路徑替換掉 <path>。)

  • 輸入 make 接著是 make install 來編譯 PHP 並把必要的文件拷貝到 Apache 的源程序目錄樹中。

  • 改變當前目錄到 /<path>/apache-1.3/src 目錄並編輯 Configuration 文件。增加這一行:AddModule modules/php4/libphp4.a

  • 輸入 ./Configure 接著是 make

  • 你現在應該有一個包括 PHP 支援的 httpd 可執行程序了!

注意:你也可以用新的 Apache ./configure 腳本。參見 Apache 發行包中 README.configure 文件中的說明。也看看 PHP 發行包中的 INSTALL 文件。

9. 我按照所有的步驟在 UNIX 下安裝了PHP 的 Apache 模塊版本,但我的 PHP 腳本被顯示在瀏覽器中或者提示保存此文件。

這說明 PHP 模塊出於某些原因沒有被呼叫。在尋求更多幫助前先檢查三件事:

  • 確認你執行的 httpd 程序就是你剛剛編譯的新 httpd 程序。執行: /path/to/binary/httpd -l

    如果你沒看到 mod_php4.c 被列出來那你就沒有執行對程序。找到並正確安裝程序。

  • 確認你在 Apache .conf 文件中加入了正確的 Mime 型別。應該是: AddType application/x-httpd-php3 .php3(PHP 3)

    或者 AddType application/x-httpd-php .php(PHP 4)

    也確認 AddType 這一行沒有隱藏在 <Virtualhost> 或者 <Directory> 塊中,這可能會造成你的測試腳本所在位置沒有被應用到此設置。

  • 最後,Apache 1.2 和 Apache 1.3 之間預定配置文件的位置改變了。你要確認你增加 AddType 行的文件就是實際上用的。你可以在你的 httpd.conf 中增加一個明顯的語法錯誤或者其它明顯修改,這可以告訴你是否讀取了正確的文件。

10. 說要用:--activate-module=src/modules/php4/libphp4.a,但是此文件根本不存在,於是我改成了 --activate-module=src/modules/php4/libmodphp4.a,結果不行。怎麼回事?

注意 libphp4.a 文件本來就不該存在,apache 進程將創建它!

11. 當我用 --activate-module=src/modules/php4/libphp4.a 試著把 PHP 編譯成 Apache 的靜態模塊時,報告說我的編譯器不服從 ANSI 標準。

這是一個 Apache 誤報的錯誤訊息,在更新的版本中已經修正了。

12. 當我用 --with-apxs 編譯 PHP 時得到奇怪的錯誤訊息。

這裡要檢查三件事。首先,出於某些原因當 Apache 產生 apxs Perl 腳本時,有時沒有正確的編譯和標記變數就結束了。找到你的 apxs 腳本(用命令 which apxs),有時會在 /usr/local/apache/bin/apxs 或者 /usr/sbin/apxs。打開並檢查類似如下的行:
my $CFG_CFLAGS_SHLIB  = ' ';          # substituted via Makefile.tmpl
my $CFG_LD_SHLIB      = ' ';          # substituted via Makefile.tmpl
my $CFG_LDFLAGS_SHLIB = ' ';          # substituted via Makefile.tmpl
如果你看到這幾行,那問題就在這裡。它們可能包含了僅僅空格或者其它不正確的值,例如“q()”。改成這樣:
my $CFG_CFLAGS_SHLIB  = '-fpic -DSHARED_MODULE'; # substituted via Makefile.tmpl
my $CFG_LD_SHLIB      = 'gcc';                   # substituted via Makefile.tmpl
my $CFG_LDFLAGS_SHLIB = q(-shared);              # substituted via Makefile.tmpl
第二個可能的問題僅可能在在 Red Hat 6.1 和 6.2 中發生。Red Hat 發行的 apxs 腳本壞了。查找這一行:
my $CFG_LIBEXECDIR    = 'modules';         # substituted via APACI install
如果你看到上面這一行,改成這樣:
my $CFG_LIBEXECDIR    = '/usr/lib/apache'; # substituted via APACI install
最後,如果你重新配置或者重裝了 Apache,在 ./configure 之後和 make 之前增加一個 make clean 命令。

13. make 的過程中,在 microtime 中出錯,還有很多 RUSAGE_ 之類的東西。

如果 make 時遇到類似這樣的問題:
microtime.c: In function `php_if_getrusage':
microtime.c:94: storage size of `usg' isn't known
microtime.c:97: `RUSAGE_SELF' undeclared (first use in this function)
microtime.c:97: (Each undeclared identifier is reported only once
microtime.c:97: for each function it appears in.)
microtime.c:103: `RUSAGE_CHILDREN' undeclared (first use in this function)
make[3]: *** [microtime.lo] Error 1
make[3]: Leaving directory `/home/master/php-4.0.1/ext/standard'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/home/master/php-4.0.1/ext/standard'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/master/php-4.0.1/ext'
make: *** [all-recursive] Error 1

你的系統壞了。你需要安裝一個符合你的 glibc 的 glibc-devel 包來修複 /usr/include 中的文件。這和 PHP 絕對沒有任何關係。要証實這一點,試試這個簡單的測試:
$ cat >test.c <<X
#include <sys/resource.h>
X
$ gcc -E test.c >/dev/null
如果出現錯誤,那你就知道頭文件壞了。

14. 我想升級我的 PHP。上哪裡找到我用來配置目前的 PHP 的 ./configure 的參數呢?

要麼在你當前的 PHP 的安裝目錄查看 config.nice 文件,如果沒有,只要執行此腳本:
<?php phpinfo(); ?>
在輸出的頂端顯示了用來配置此 PHP 的 ./configure 參數。

15. 和 GD 庫一起編譯 PHP 時,要麼給出一個奇怪的編譯錯誤,要麼在執行時出現 segfaults。

確保你的 GD 庫和 PHP 在連接時使用了用同樣的支援庫(例如 libpng)。