MacOS10.15編譯安裝PHP詳細手冊

這篇文章更多是提醒自己,同時希望對遇到類似問題的人有所幫助。文中基本上把我遇到的問題都羅列出來了,但前後次序各有不同。我是在執行phpize的時候發現的問題,所以先解決MacOS10.15的SIP和根目錄寫權限的問題,然後再重新編譯PHP,安裝apache。這篇文章沒有解決編譯覆蓋MacOS內置PHP的問題,我應該會另外寫一篇文章解專門說明如何操作。

一、安裝phpize的依賴庫

執行 phpize 的時候報了以下錯誤,表明缺少了必要的依賴庫:

Configuring for:
PHP Api Version:          20180731
Zend Module Api No:       20180731
Zend Extension Api No:    320180731
Cannot find autoconf. Please check your autoconf installation and the  $PHP_AUTOCONF  environment variable is set correctly and then rerun this script.

這是由於phpize所依賴的autoconf庫沒有正確安裝導致的,按下面的步驟安裝依賴的軟件即可解決,此處應當注意使用軟件的最新版本。也可以通過brew命令進行安裝,此時就只要安裝autoconf即可。

wget http://ftp.gnu.org/gnu/m4/m4-1.4.9.tar.gz
tar -zvxf m4-1.4.9.tar.gz
cd m4-1.4.9/
./configure 
sudo make && make install

cd ../

wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.62.tar.gz
tar -zvxf autoconf-2.62.tar.gz
cd autoconf-2.62/
./configure 
sudo make && make install

注意:若要卸載使用 make install 命令安裝的軟件,可以執行 make uninstall 命令進行卸載。但由於需要讀取原始 ./configure信息,因此必須在源碼目錄中進行操作,因此建議保留原始的源碼目錄以便必要時使用。

二、安裝Homebrew

當需要在MacOS上安裝各種擴展的時候,推薦使用Homebrew,Homebrew是MacOS上的命令行模式下的軟件管理工具,與Fedora操作系統上的dnf命令類似。Homebrew 的安裝非常簡單,在安裝前,需要確認XCode或者Command Line Tools for Xcode是否安裝,但我並不使用Xcode這個龐然大物來編碼,所以只需安裝 Command Line Tools for Xcode 即可,在終端鍵入以下代碼完成安裝:

xcode-select --install

在終端執行下面的命令進行安裝(注意不要有換行):

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install"

但是,這條命令執行時下載的速度非常慢,此時可以下載這個bash命令文件,修改裏面的軟件源的位置爲國內的軟件源,以提高下載速度,詳細過程如下:

下載官網提供的安裝腳本,保存爲本地brew_install文件:

curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install >> brew_install

打開brew_install文件,更改腳本中的資源鏈接爲清華大學的鏡像,修改語句:

BREW_REPO = "https://github.com/Homebrew/brew".freeze

爲:

BREW_REPO = "https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git".freeze

當然也可以換成別的軟件源,修改之後執行:

/usr/bin/ruby brew_install

安裝成功之後執行下面的命令檢查是否安裝成功:

brew -v

成功安裝brew之後,對於phpize所依賴的autoconf軟件庫就無需通過編譯源碼的方式安裝,只要通過下面的命令即可完成安裝:

sudo brew install autoconf

例如在對php執行configure命令時,發現缺少zlib庫,則可以通過下面的命令安裝zlib庫,安裝成功後再次執行configure命令:

brew install zlib

注:上面安裝autoconf的命令執行依然很慢,可爲brew添加清華大學鏡像源:

echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles' >> 
~/.bash_profile
source ~/.bash_profile

下面列出brew命令的常見用法 

用brew命令搜索軟件:

brew search autoconf

 用brew安裝軟件

brew install autoconf

查看軟件信息

brew info autoconf

更新某一軟件

brew upgrade autoconf

卸載軟件

brew remove autoconf

刪除程序,和upgrade一樣,單個軟件刪除和所有程序刪除

brew cleanup autoconf
brew cleanup

查看哪些軟件可以升級

brew outdated

查看已經安裝的軟件列表

brew list

三、升級到OSX10.15後phpize找不到php.h文件

當系統升級到OSX10.15後,再次在php的某個ext擴展目錄中執行phpize命令時,會發生找不到php.h頭文件的錯誤,詳細錯誤信息如下:

grep: /usr/include/php/main/php.h: No such file or directory
grep: /usr/include/php/Zend/zend_modules.h: No such file or directory
grep: /usr/include/php/Zend/zend_extensions.h: No such file or directory
Configuring for:
PHP Api Version:
Zend Module Api No:
Zend Extension Api No: 

出現這個錯誤的原因是Apple用SIP提高了系統安全性,禁止用戶(包括su用戶)操作如/usr目錄的系統目錄。又因反對/usr/include與sdk不同移除了/usr/include目錄,所以無法直接在/usr目錄下創建include目錄或軟連接。並且OSX10.15沒有像OSX10.14一樣提供頭文件安裝包,即使執行下面的命令:

xcode-select --install

安裝了Xcode command line tools的情況下,依然沒有/usr/include目錄,還是無法使用phpize命令。且由於缺少頭文件安裝包,以下命令也無法正確執行:

cd /Library/Developer/CommandLineTools/Packages/
open macOS_SDK_headers_for_macOS_10.14.pkg

最終的解決辦法是進入恢復模式禁用SIP,修改系統目錄的寫入權限,在/usr目錄建立include的軟連接,指向Xcode command line tools內的usr/include目錄,這裏要注意指向與操作系統匹配的MacOS.sdk版本。具體操作如下:

重啓電腦按下Command+R,點亮屏幕後就開始按,直到出現蘋果標誌。進入恢復模式後,依次選擇菜單欄上的“實用工具” => “終端”,打開終端界面,執行:

csrutil disable

執行後會輸出:

Successfully disabled System Integrity Protection. Please restart the machine for the changes to take effect.

重啓系統進入正常模式,執行下面的命令確認SIP已成功禁用:

csrutil status
System Integrity Protection status: disabled.

禁用SIP後,使用下面的命令,修改根目錄的寫入權限:

sudo mount -uw /

此時/usr目錄已經有了寫入權限,上面的修改命令僅在本次重新啓動之前有效,重啓之後會回到只讀模式,除非再次執行該命令。

根目錄有了寫入權限後,就能在/usr目錄下建立include的軟件連接,但是需要注意從MacOS-10.15開始,MacOS.sdk在/Library/Developer/CommandLineTools/ SDKs/目錄中,因此需要使用下面的命令建立軟連接(以下爲一行代碼,沒有回車):

sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/ /usr

成功創建軟連接後,繼續在php源碼/ext目錄下的某個擴展目錄中執行phpize命令就能看到正確的信息,執行結果如下:

phpize
Configuring for:
PHP Api Version:         20180731
Zend Module Api No:      20180731
Zend Extension Api No:   320180731

此時爲MacOS內置的PHP安裝擴展就沒有問題了,但我仍然計劃下載一份PHP源碼,手動編譯安裝!下載源碼,並解壓保存在/usr/local/src/php-7.3.8目錄,然後開始編譯。

四、編譯PHP7.3.8

編譯的重點是設置編譯參數,這裏參考了一份7.2的編譯參數,再結合MacOS內置PHP的編譯參數,修改出一份集成了freetype的編譯參數:

這是用於參考的PHP7.2編譯參數:

./configure --prefix=/usr/local/php/7.2 \
--with-config-file-path=/usr/local/etc/php/7.2 \
--with-config-file-scan-dir=/usr/local/etc/php/7.2/conf.d \
--enable-fpm \
--with-fpm-user=www \
--with-fpm-group=www \
--with-mysqli \
--with-pdo-mysql \
--with-iconv-dir=/usr/local \
--enable-short-tags \
--with-zlib \
--with-libxml-dir=/usr/bin/xml2-config \
--enable-xml \
--disable-rpath \
--enable-bcmath \
--enable-sysvsem \
--enable-inline-optimization \
--with-curl \
--enable-mbregex \
--enable-mbstring \
--with-mcrypt-dir=/usr/local/Cellar/mcrypt/2.6.8/ \
--with-gd \
--with-openssl=/usr/local/opt/openssl \
--with-mhash \
--enable-pcntl \
--enable-sockets \
--with-xmlrpc \
--enable-zip \
--enable-soap \
--without-pear \
--disable-fileinfo \
--enable-maintainer-zts \
--enable-mysqlnd \
--with-freetype-dir=/usr/local/Cellar/freetype/2.9.1/

這是MacOS內置PHP7.3.8的編譯參數:

./configure --prefix=/usr \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--disable-dependency-tracking \
--sysconfdir=/private/etc \
--with-libdir=lib \
--enable-cli \
--with-iconv=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-config-file-path=/etc \
--with-libxml-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-openssl=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr/local/libressl \
--with-kerberos=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-zlib=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-bcmath \
--with-bz2=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-calendar \
--disable-cgi \
--with-curl=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-dba \
--with-ndbm=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-exif \
--enable-fpm \
--enable-ftp \
--with-gd \
--with-freetype \
--with-png \
--with-jpeg \
--enable-gd-native-ttf \
--with-icu-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-ldap=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-ldap-sasl=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-libedit=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-mbstring \
--enable-mbregex \
--with-mysqli=mysqlnd \
--without-pcre-jit \
--with-pdo-pgsql=/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.15.xctoolchain/usr/local/bin \
--with-pgsql=/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.15.xctoolchain/usr/local/bin \
--without-pear \
--with-pear=no \
--with-pdo-mysql=mysqlnd \
--with-mysql-sock=/var/mysql/mysql.sock \
--disable-phpdbg \
--with-readline=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-shmop \
--with-snmp=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-soap \
--enable-sockets \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--with-tidy=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--enable-wddx \
--with-xmlrpc \
--with-iconv-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-xsl=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/usr \
--with-apxs2=/Applications/Xcode.app/Contents/Developer/Toolchains/OSX10.15.xctoolchain/usr/local/bin/apxs \
YACC=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison

經過多次嘗試,包括進入恢復模式用SIP,都未能覆蓋內置PHP,只能將PHP編譯安裝到其他目錄,調整後的編譯參數爲:

./configure --prefix=/usr/local/php-7.3.8 \
--with-apxs2=/usr/local/opt/apache2/bin/apxs \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--sysconfdir=/private/etc \
--with-libdir=lib \
--enable-cli \
--with-config-file-path=/etc \
--with-libxml-dir=/usr/bin/xml2-config \
--with-openssl=/usr/local/opt/openssl \
--with-zlib=/usr/local/opt/zlib \
--enable-bcmath \
--enable-calendar \
--disable-cgi \
--with-curl=/usr/local/opt/curl \
--enable-dba \
--enable-exif \
--enable-fpm \
--enable-ftp \
--with-gd \
--with-freetype-dir=/usr/local/opt/freetype \
--with-png-dir=/usr/local/opt/libpng \
--with-jpeg-dir=/usr/local/opt/libjpeg \
--enable-mbstring \
--enable-mbregex \
--with-mysqli=mysqlnd \
--without-pcre-jit \
--without-pear \
--with-pear=no \
--with-pdo-mysql=mysqlnd \
--with-mysql-sock=/var/mysql/mysql.sock \
--disable-phpdbg \
--enable-shmop \
--enable-soap \
--enable-sockets \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--with-xmlrpc \
--with-iconv=/usr/local/opt/libiconv

若在執行configure命令過程中出現缺庫問題,可以通過brew命令進行安裝,brew命令的詳細使用方法參考二部分。

執行make命令編譯PHP源碼時,發生以下錯誤,錯誤消息:

Undefined symbols for architecture x86_64

發生這個錯誤的原因是不能使用系統自動生成的 -liconv 擴展庫,須使用brew安裝的擴展庫。用brew安裝擴展庫時,會同時在/usr/local/opt目錄中創建軟連接到對應的安裝目錄,因此只要把PHP源碼目錄中由configure由命令生成的Makefile文件裏面所有的 -liconv 都替換爲以下內容即可:

/usr/local/opt/libiconv/lib/libiconv.dylib

替換之後的擴展庫參數設置類似於:

EXTRA_LIBS = -lcrypto -lssl -lcrypto -lresolv -lpng -lz -ljpeg -lcrypto -lssl -lcrypto -lz -lcrypto -lssl -lcrypto -lm -lxml2 -lz -licucore -lm -lcurl -lldap -lz -lxml2 -lz -licucore -lm -lfreetype -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm /usr/local/opt/libiconv/lib/libiconv.dylib

類似地,如果編譯時OpenSSL擴展庫出現問題,也可以用這個方法替換,只是替換的庫對應地改爲:-lcrypto和 -lssl。

再次執行編譯前建議先清理然後編譯(注意:上面的編譯選項中多了--with-apxs2選項,實際上無法順利完成編譯,具體原因請繼續向下閱讀):

make clean
make

順利通過編譯後使用下面的命令完成安裝:

sudo make install

若要停止運行PHP,可執行以下的命令:

ps -eaf |grep "php-fpm" | grep -v "grep"| awk '{print $2}'|xargs kill -9

五、編譯PHP的libphp7.so文件

上面的編譯選項無法通過編譯是由於系統中沒有apxs,無法配置--with-apxs2選項,也就無法生成so文件,因此要執行下面的命令重新安裝apache2:

brew install apache2

brew把所有關於apache的依賴軟件都安裝了一套,這樣我的電腦上就有了兩套httpd服務軟件,但是配置的監聽端口不同,可同時啓動運行。受到brew設置環境變量的影響,現在如果直接使用apachectl重啓或停止服務,對應的命令已經不是默認內置的httpd服務,而變成了剛剛由brew安裝的httpd服務。which命令執行結果:

which apachectl
/usr/local/bin/apachectl

而系統自帶的httpd服務命令應該位於:

/usr/sbin/apachectl

這是在/etc/paths環境變量配置文件中目錄配順序和apachectl名稱衝突而導致的結果。/etc/paths配置文件的內容爲:

/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

這裏簡單地把/usr/loacl/bin目錄中的apachectl重命名爲apachectl2,這樣就避免了衝突。可執行以下命令停用新安裝的httpd服務:

sudo apachectl2 stop

新安裝的這個apache2僅用於編譯生成libphp7.so文件,繼續沿用MacOS自帶的httpd提供Web服務。

安裝apache2後,在/usr/local/opt/apache2/bin目錄內已經有了apxs程序,此時增加--with-apxs2編譯選項,再次執行make命令編譯php-7.3.8後,會在apxs程序對應的httpd的lib/httpd/modules目錄中生成libphp7.so文件。

另外,libphp7.so文件在php-7.3.8(源碼)/libs目錄中有一份副本,php可執行程序在php-7.3.8(源碼)/sapi/cli目錄中有一份副本。

最後使用如下命令修改httpd的配置文件:

sudo vi /etc/apache2/httpd.conf

修改引用libphp7.so文件的位置,註釋原始版本,使用剛剛編譯生成的版本:

#LoadModule php7_module libexec/apache2/libphp7.so
LoadModule php7_module /usr/local/lib/httpd/modules/libphp7.so

六、寫在最後

升級到最新的MacOS-10.15.1後發現,系統內置的PHP也已經升級到PHP-7.3.9,但是GD庫依然不支持freetype,因此在MacOS上另外再安裝一套PHP在所難免。

同時也發現MacOS系統封閉非常嚴重,從10.11開始變得越來越嚴重,儘管Apple稱這是爲了系統安全,避免/usr/include與sdk不一致,但是對於開發者來說,系統幾乎沒有提供多少可直接使用的第三方開發工具,只要不是Apple提供的,幾乎都要重新安裝。實際上這些內置開發工具,不如沒有來的簡單。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章