91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

編譯PHP擴展的方法是什么

發布時間:2020-09-04 13:58:25 來源:億速云 閱讀:118 作者:小新 欄目:編程語言

小編給大家分享一下編譯PHP擴展的方法是什么,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!

構建PHP擴展

你已經知道如何去編譯PHP本身,下一步我們將編譯外部擴展。我們將討論擴展的構建過程和可用的編譯選項。

載入共享擴展

在前一個章節你已經知道,PHP 擴展既能構建成靜態庫也可以構建成動態庫(.so)。大多數靜態庫是與 PHP 捆綁在一起編譯的,動態庫可以顯式地傳遞參數 --enable-EXTNAME=shared--with-EXTNAME=shared./configure

靜態擴展默認是可用的,動態庫需要增加 extension 或者 zend_extension 的 ini 配置。倆者可以是絕對路徑,也可以是相對路徑。

例如編譯 PHP 擴展用項目的配置項:

~/php-src> ./configure --prefix=$HOME/myphp
                       --enable-debug --enable-maintainer-zts
                       --enable-opcache --with-gmp=shared

這個例子中 opcache 擴展和 GMP 擴展都被編譯為位于 modules/ 目錄中的共享對象。 您可以通過更改extension_dir或通過傳遞絕對路徑來加載:

~/php-src> sapi/cli/php -dzend_extension=`pwd`/modules/opcache.so
                        -dextension=`pwd`/modules/gmp.so
# or
~/php-src> sapi/cli/php -dextension_dir=`pwd`/modules
                        -dzend_extension=opcache.so -dextension=gmp.so

make install 步驟中,這兩個 .so 文件會被移進 PHP 安裝的擴展目錄,你使用 php-config --extension-dir 命令可能可以找到它。對于上面的構建選項,它將是 /home/myuser/myphp/lib/php/extensions/no-debug-non-zts-MODULE_API。這個值也是 extension_dir 配置選項的默認值,所以你無需明確地指定它,就可以直接加載進擴展:

~/myphp> bin/php -dzend_extension=opcache.so -dextension=gmp.so

這給我們留下了一個問題:你應該使用哪種機制?共享對象使你有一個基本的 PHP 二進制文件并通過 php.ini 加載其他擴展。發行版通過原始的 PHP 軟件包和將擴展作為單獨的軟件包分發來利用此功能。另一方面,如果你編譯自己的 PHP 二進制文件,則可能不需要這個,因為你已經知道需要哪些擴展。

根據經驗,你將對 PHP 本身捆綁的擴展使用靜態鏈接,并將共享擴展用于其他地方。原因很簡單,就像你稍后看到的,構建外部擴展為共享對象的更容易(或至少減少了侵入性)。另一個好處是你可以在不用重新構建 PHP 的情況下更新擴展。

注意

如果你需要有關擴展和 Zend 擴展之間差異的信息,你可以查閱專門章節。

從 PECL 安裝擴展

PECL,PHP 擴展社區庫,提供了大量的 PHP 擴展。當擴展從主 PHP 發行版中刪除,它們通常還在 PECL中。同樣,現在與 PHP 捆綁一起的許多擴展以前都是 PECL 擴展。

除非你在 PHP 構建的配置步驟指定 --without-pear,否則 make install 將PECL 作為 PEAR 的一部分下載并安裝。你可以在 $PREFIX/bin 目錄下找到 pecl 腳本。現在安裝擴展很簡單,就像運行 pecl install EXTNAME 一樣,例如:

~/myphp> bin/pecl install apcu

該命令將下載、編譯并安裝 APCu 擴展。結果會是 apcu.so 文件在擴展目錄下,可以通過傳遞 extension=apcu.so 配置選項來加載此文件。

雖然 pecl install 對終端用戶非常方便,但擴展開發人員對它沒什么興趣。在下面,我們將會說明兩種手動構建擴展的方式:通過將其導入主要的 PHP 源碼樹(允許靜態鏈接)或通過外部構建(僅共享)。

添加擴展到 PHP 源碼樹

第三方擴展和捆綁在 PHP 的擴展之間沒有根本上的區別。因此你可以通過復制外部擴展到 PHP 源碼樹,并和通常的構建過程一樣來構建。我們以APCu 作為例子來演示。

首先,你要把擴展的源代碼放到 PHP 源碼樹的 ext/EXTNAME 目錄。如果擴展可通過 Git 獲得,就像從 ext/ 中克隆倉庫一樣簡單:

~/php-src/ext> git clone https://github.com/krakjoe/apcu.git

或者你也可以下載源碼壓縮包并解壓它:

/tmp> wget http://pecl.php.net/get/apcu-4.0.2.tgz
/tmp> tar xzf apcu-4.0.2.tgz
/tmp> mkdir ~/php-src/ext/apcu
/tmp> cp -r apcu-4.0.2/. ~/php-src/ext/apcu

該擴展會包含一個 config.m4 文件,該文件指定autoconf文件使用的特定擴展構建指令。 為了將它們包含在 /configure 腳本,你必須再次運行 ./buildconf。為了確保配置文件已經重新生成,建議事先刪除它:

~/php-src> rm configure && ./buildconf --force

現在你可以使用 ./config.nice 腳本將 APCu 添加到你的現有配置,或者從全新的配置行開始:

~/php-src> ./config.nice --enable-apcu
# or
~/php-src> ./configure --enable-apcu # --other-options

最后,運行 make -jN 執行實際的構建。由于我們沒有使用 --enable-apcu=shared,該擴展已經靜態鏈接到 PHP 庫,即不需要額外的操作即可使用它。顯然,你也可以使用 make install 去安裝最后的二進制文件。

使用 phpize 構建擴展

還可以通過使用構建 PHP章節提及到的 phpize 腳本與 PHP 分開構建。

phpize 的作用與 ./buildconf 用于 PHP 構建的腳本相似:第一,通過$PREFIX/lib/php/build 復制文件導入 PHP 構建系統到你的擴展中。這些文件是 acinclude.m4(PHP 的 M4宏)、phpize.m4(它會在你的擴展中重命名為 configure.in 并包含主要的構建說明)和 run-tests.php

然后 phpize 將調用 autoconf 生成 ./configure 文件,該文件可以自定義擴展構建。注意,沒必要傳遞 --enable-apcu 給它,因為這是隱式假定的。相反,你應該使用 --with-php-config 指定你的 php-config 腳本路徑:

/tmp/apcu-4.0.2> ~/myphp/bin/phpize
Configuring for:
PHP Api Version:         20121113
Zend Module Api No:      20121113
Zend Extension Api No:   220121113

/tmp/apcu-4.0.2> ./configure --with-php-config=$HOME/myphp/bin/php-config
/tmp/apcu-4.0.2> make -jN && make install

當你構建擴展時,你應該總是指定 --with-php-config 選項(除非你只有一個全局的 PHP 安裝),否則 ./configure 無法確定要構建的 PHP 版本和標志。指定 php-config 腳本也確保了 make install 將移動生成的 .so 文件(可以在 modules/ 目錄找到)到正確的擴展目錄。

由于在 phpize 階段還復制了 run-tests.php 文件,因此你可以使用 make test(或顯示調用 run-tests)運行擴展測試。

刪除已編譯對象的 make clean 也是可用的,并且允許你增量構建失敗時強制重新構建擴展。 另外 phpize 提供了一個清理選項 phpize --clean。該命令將刪除所有 phpize 導入的文件和通過 /configure 腳本生成的文件。

顯示關于擴展的信息

PHP CLI 二進制文件提供了幾個選項來顯示關于擴展的信息。你已經知道 -m,該命令會列出所有已經下載的擴展。你可以利用它來確定擴展是否正確下載了:

~/myphp/bin> ./php -dextension=apcu.so -m | grep apcu
apcu

還有其他一些以 --r 開頭的參數都是具有 Reflection 功能。例如,你可以使用 --ri 去顯示擴展的配置:

~/myphp/bin> ./php -dextension=apcu.so --ri apcu
apcu

APCu Support => disabled
Version => 4.0.2
APCu Debugging => Disabled
MMAP Support => Enabled
MMAP File Mask =>
Serialization Support => broken
Revision => $Revision: 328290 $
Build Date => Jan  1 2014 16:40:00

Directive => Local Value => Master Value
apc.enabled => On => On
apc.shm_segments => 1 => 1
apc.shm_size => 32M => 32M
apc.entries_hint => 4096 => 4096
apc.gc_ttl => 3600 => 3600
apc.ttl => 0 => 0
# ...

--re 參數列出擴展添加的所有初始設置、常數、函數和類:

~/myphp/bin> ./php -dextension=apcu.so --re apcu
Extension [ <persistent> extension #27 apcu version 4.0.2 ] {
  - INI {
    Entry [ apc.enabled <SYSTEM> ]
      Current = '1'
    }
    Entry [ apc.shm_segments <SYSTEM> ]
      Current = '1'
    }
    # ...
  }

  - Constants [1] {
    Constant [ boolean APCU_APC_FULL_BC ] { 1 }
  }

  - Functions {
    Function [ <internal:apcu> function apcu_cache_info ] {

      - Parameters [2] {
        Parameter #0 [ <optional> $type ]
        Parameter #1 [ <optional> $limited ]
      }
    }
    # ...
  }
}

--re 參數僅適用普通擴展,Zend 擴展使用 --rz 代替。 你可以在 opcache 上嘗試:

~/myphp/bin> ./php -dzend_extension=opcache.so --rz "Zend OPcache"
Zend Extension [ Zend OPcache 7.0.3-dev Copyright (c) 1999-2013 by Zend Technologies <http://www.zend.com/> ]

如你所見, 該命令沒有顯示有用的信息。因為 opcache 同時注冊了普通擴展和 Zend 擴展, 前者包含所有初始配置、常量和函數。因此在這個特殊的案例中,你仍然需要使用 --re。其他 Zend 擴展通過 --rz 可得到信息。

擴展 API 兼容性

擴展對5個主要因素非常敏感。如果它們不合適,則該擴展將不會加載到 PHP中,并將無用:

  • PHP Api 版本
  • Zend 模塊 Api 編號
  • Zend 擴展 Api 編號
  • 調試模式
  • 線程安全

phpize 工具可讓你回想它們的一些信息。所以,如果你在調試模式下構建 PHP,并試圖加載和使用非調試模式構建的擴展,那它將無法工作。其他檢查也一樣。

PHP Api 版本 是內部 API 版本號,Zend 模塊 Api 編號Zend 擴展 Api 編號 分別與 PHP 擴展和 Zend 擴展 API 有關。

那些編號隨后作為 C 宏傳遞給正在構建的擴展,以便它本身可以檢查那些參數,并在 C 預處理器  #ifdef 的基礎上采用不同的代碼路徑。當那些編號作為宏傳給擴展代碼,它們會被寫在擴展結構中,以便你每次嘗試在 PHP 二進制文件中加載該擴展時,都將對照 PHP 二進制文件本身的編號進行檢查。如果不匹配,那么該擴展不會被加載,并顯示一條錯誤信息。

如果我們看一下擴展的 C 結構,它看起來像這樣:

zend_module_entry foo_module_entry = {
    STANDARD_MODULE_HEADER,
    "foo",
    foo_functions,
    PHP_MINIT(foo),
    PHP_MSHUTDOWN(foo),
    NULL,
    NULL,
    PHP_MINFO(foo),
    PHP_FOO_VERSION,
    STANDARD_MODULE_PROPERTIES
};

至今,對我們來說有趣的是 STANDARD_MODULE_HEADER 宏。如果我們擴展它,我們可以看到:

#define STANDARD_MODULE_HEADER_EX sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
#define STANDARD_MODULE_HEADER STANDARD_MODULE_HEADER_EX, NULL, NULL

注意 ZEND_MODULE_API_NOZEND_DEBUGUSING_ZTS 是如何使用的。

如果查看 PHP 擴展的默認目錄,它應該像 no-debug-non-zts-20090626。如你所料,該目錄由不同的部分組成:調試模式,其次是線程安全信息,然后是Zend 模塊 Api 編號。所以默認情況下,PHP 試圖幫你瀏覽擴展。

注意

通常,當你成為一位內部開發人員或擴展開發人員,必須使用調試參數,并且如果必須處理 Windows 平臺,線程也會顯示出來。你可以針對那些參數的多種情況多次編譯同一擴展。
記住,每次新的 PHP 主要/次要版本都會更改參數,比如 PHP Api 版本,這就是為什么你需要針對新的 PHP 版本重新編譯的原因。

> /path/to/php70/bin/phpize -v
Configuring for:
PHP Api Version:         20151012
Zend Module Api No:      20151012
Zend Extension Api No:   320151012

> /path/to/php71/bin/phpize -v
Configuring for:
PHP Api Version:         20160303
Zend Module Api No:      20160303
Zend Extension Api No:   320160303

> /path/to/php56/bin/phpize -v
Configuring for:
PHP Api Version:         20131106
Zend Module Api No:      20131226
Zend Extension Api No:   220131226

注意

Zend 模塊 Api 編號 本身是使用 年 月 日 的日期格式構建。這是 API 更改和并被標記的日期。Zend 擴展 Api 編號 是 Zend 版本,其次是 Zend 模塊 Api 編號

注意

數字太多?是的,一個 API 編號綁定一個 PHP 版本,對任何人來說都足夠了,并且可以簡化對 PHP 的理解。不幸的是,除了 PHP 版本本身,還增加了3種不同的 API 編號。你應該找哪一個?答案是任何一個:當 PHP 版本演變時,它們三種同時演變。由于歷史原因,我們有三種不同編號。

但是,你是一位 C開發人員,不是嗎?為什么不根據這些數字構建一個“兼容的”頭文件?我們在我們的擴展中使用了類似這些:

#include "php.h"
#include "Zend/zend_extensions.h"

#define PHP_5_5_X_API_NO            220121212
#define PHP_5_6_X_API_NO            220131226

#define PHP_7_0_X_API_NO            320151012
#define PHP_7_1_X_API_NO            320160303
#define PHP_7_2_X_API_NO            320160731

#define IS_PHP_72          ZEND_EXTENSION_API_NO == PHP_7_2_X_API_NO
#define IS_AT_LEAST_PHP_72 ZEND_EXTENSION_API_NO >= PHP_7_2_X_API_NO

#define IS_PHP_71          ZEND_EXTENSION_API_NO == PHP_7_1_X_API_NO
#define IS_AT_LEAST_PHP_71 ZEND_EXTENSION_API_NO >= PHP_7_1_X_API_NO

#define IS_PHP_70          ZEND_EXTENSION_API_NO == PHP_7_0_X_API_NO
#define IS_AT_LEAST_PHP_70 ZEND_EXTENSION_API_NO >= PHP_7_0_X_API_NO

#define IS_PHP_56          ZEND_EXTENSION_API_NO == PHP_5_6_X_API_NO
#define IS_AT_LEAST_PHP_56 (ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO && ZEND_EXTENSION_API_NO < PHP_7_0_X_API_NO)

#define IS_PHP_55          ZEND_EXTENSION_API_NO == PHP_5_5_X_API_NO
#define IS_AT_LEAST_PHP_55 (ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO && ZEND_EXTENSION_API_NO < PHP_7_0_X_API_NO)

#if ZEND_EXTENSION_API_NO >= PHP_7_0_X_API_NO
#define IS_PHP_7 1
#define IS_PHP_5 0
#else
#define IS_PHP_7 0
#define IS_PHP_5 1
#endif

看見了?

或者更簡單(更好)的是使用 PHP_VERSION_ID ,這你可能更熟悉:

#if PHP_VERSION_ID >= 50600

看完了這篇文章,相信你對編譯PHP擴展的方法是什么有了一定的了解,想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

青田县| 遵义县| 莲花县| 张家界市| 平舆县| 射洪县| 贵港市| 珠海市| 承德县| 家居| 长寿区| 顺昌县| 房山区| 海南省| 襄樊市| 英吉沙县| 洱源县| 金阳县| 南京市| 泾源县| 克什克腾旗| 平罗县| 酉阳| 嘉荫县| 祁东县| 新竹县| 宣武区| 桦川县| 集贤县| 宁武县| 佛学| 科技| 阜城县| 崇信县| 富民县| 招远市| 穆棱市| 怀柔区| 永州市| 垣曲县| 蕲春县|