章 53. 編譯問題

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

1. 我用匿名 CVS 得到了最新版的 PHP,但是裡面沒有 configure 腳本!
2. 我在配置 PHP 和 Apache 一起工作時遇到了問題。說沒找到 httpd.h,但這個檔案明明就在那裡!
3. 當運行 PHP 配置時(./configure),遇到類似如下的問題:
4. 當試圖啟動 Apache 時,得到類似如下錯誤訊息:
5. 當運行 configure 時,報告說找不到標頭檔或 GD 庫或 gdbm,或其它的什麼包!
6. 當編譯 language-parser.tab.c 檔案時,報錯說 yytname undeclared
7. 當我運行 make 時,看上去一切標準,可當連線最後的程式時報告說找不到某些檔案而失敗了。
8. 當連線 PHP 時,報告說有一些未定義的引用。
9. 我不知道怎樣把 PHP 和 Apache 1.3 一起編譯。
10. 我按照所有的步驟在 UNIX 下安裝了PHP 的 Apache 模組版本,但我的 PHP 腳本被顯示在瀏覽器中或是提示儲存此檔案。
11. 說要用:--activate-module=src/modules/php4/libphp4.a,但是此檔案根本不存在,於是我改成了 --activate-module=src/modules/php4/libmodphp4.a,結果不行。怎麼回事?
12. 當我用 --activate-module=src/modules/php4/libphp4.a 試著把 PHP 編譯成 Apache 的靜態模組時,報告說我的編譯器不服從 ANSI 標準。
13. 當我用 --with-apxs 編譯 PHP 時得到奇怪的錯誤訊息。
14. make 的過程中,在 microtime 中出錯,還有很多 RUSAGE_ 之類的東西。
15. 當帶 MySQL 編譯 PHP 時,可以正確地運行配置,但是在 make 的過程中出現了類似以下的錯誤訊息: ext/mysql/libmysql/my_tempnam.o(.text+0x46): In function my_tempnam': /php4/ext/mysql/libmysql/my_tempnam.c:103: the use of tempnam' is dangerous, better use mkstemp',這是怎麼回事
16. 我想升級我的 PHP。上哪裡找到我用來配置目前的 PHP 的 ./configure 的參數呢?
17. 和 GD 庫一起編譯 PHP 時,要麼給出一個奇怪的編譯錯誤,要麼在運行時出現 segfaults。
18. 當編譯 PHP 時我看到一些隨機的錯誤,好像死了。我用的是 Solaris,不知道有沒有關係。

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. 當運行 PHP 配置時(./configure),遇到類似如下的問題:

checking lex output file root... ./configure: lex: command not found
       configure: error: cannot find output from lex; giving up

請認真閱讀 PHP 的安裝說明,並注意要編譯 PHP 需要同時安裝 flex 和 bison。根據設定的不同,可以從原始碼編譯 bison 和 flex,要麼通過已編譯好的發行包,例如 RPM。

4. 當試圖啟動 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 手冊

5. 當運行 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

6. 當編譯 language-parser.tab.c 檔案時,報錯說 yytname undeclared

需要更新 Bison 的版本。最新版本在 http://www.gnu.org/software/bison/bison.html

7. 當我運行 make 時,看上去一切標準,可當連線最後的程式時報告說找不到某些檔案而失敗了。

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

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

看看連線的這一行指令,確認所有適當的庫都內含在最後了。通常可能漏掉了「-ldl」和你內含的任何資料庫支援所需要的庫。

若果和 Apache 1.2.x 一起連線,記得把適當的訊息新增到配置檔的 EXTRA_LIBS 這一行並重新運行 Apache 的配置腳本了嗎?更多訊息參見發行包中的 INSTALL 檔案。

一些人也報告說在和 Apache 連線時他們不得不緊接著 libphp4.a 之後加上「-ldl」。

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

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

  • http://www.apache.org/dist/httpd/ 下載最新版的 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 檔案。

10. 我按照所有的步驟在 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 中增加一個明顯的語法錯誤或是其它明顯修改,這可以告訴你是否讀取了正確的檔案。

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

注意 libphp4.a 檔案本來就不該存在,apache 程式將建立它!

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

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

13. 當我用 --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 指令。

14. 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
若果出現錯誤,那你就知道標頭檔壞了。

15. 當帶 MySQL 編譯 PHP 時,可以正確地運行配置,但是在 make 的過程中出現了類似以下的錯誤訊息: ext/mysql/libmysql/my_tempnam.o(.text+0x46): In function my_tempnam': /php4/ext/mysql/libmysql/my_tempnam.c:103: the use of tempnam' is dangerous, better use mkstemp',這是怎麼回事

首先,我們需要認識到這只是個警示,而非致命錯誤。由於這條訊息通常是在 make 的最後輸出的,所以看起來它可能像是一個致命錯誤,但實際上不是。當然,若果將編譯器設定成遇見警示訊息時停止,則這也可以算是致命錯誤。另外值得一提的是,MySQL 的支援是預設開啟的。

注: 自 PHP 4.3.2 起,你將在編譯(make)結束後看到下面的文字:

Build complete.
        (It is safe to ignore warnings about tempnam and tmpnam).

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

要麼在你現用的的 PHP 的安裝目錄檢視 config.nice 檔案,若果沒有,只要運行此腳本:
<?php phpinfo(); ?>
在輸出的頂端顯示了用來配置此 PHP 的 ./configure 參數。

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

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

18. 當編譯 PHP 時我看到一些隨機的錯誤,好像死了。我用的是 Solaris,不知道有沒有關係。

當編譯 PHP 時使用非 GNU 的工具會導致問題。確保使用 GNU 工具來確保能夠正確編譯 PHP。例如,在 Solaris 下面不論使用 SunOS BSD 相容或是 Solaris 版本的 sed 都不行,但是使用 GNU 或是 Sun POSIX (xpg4) 版本的 sed 就可以。關聯連線:GNU sedGNU flexGNU bison