<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 庫的查找 config.m4腳本最多是用于檢查依賴庫是否已安裝. 擴展比如mysql, ldap, gmp以及其他設計為php用戶空間和c庫實現的其他功能之間的粘合層的擴展. 如果它們的依賴庫沒有安裝, 或者安裝的版本太舊, 要么會編譯錯誤, 要么會導致產生的二進制無法運行. ## 頭文件掃描 對依賴庫掃描中最簡單的一步就是檢查你的腳本中的包含文件, 它們將在鏈接時使用. 下面的代碼嘗試在一些常見位置查找zlib.h: ```c PHP_ARG_WITH(zlib,[for zlib Support] [ with-zlib Include ZLIB Support]) if test "$PHP_ZLIB" != "no"; then for i in /usr /usr/local /opt; do if test -f $i/include/zlib/zlib.h; then ZLIB_DIR=$i fi done if test -z "$ZLIB_DIR"; then AC_MSG_ERROR([zlib not installed (http://www.zlib.org)]) fi PHP_ADD_LIBRARY_WITH_PATH(z,$ZLIB_DIR/lib, ZLIB_SHARED_LIBADD) PHP_ADD_INCLUDE($ZLIB_DIR/include) AC_MSG_RESULT([found in $ZLIB_DIR]) AC_DEFINE(HAVE_ZLIB,1,[libz found and included]) PHP_NEW_EXTENSION(zlib, zlib.c, $ext_shared) PHP_SUBST(ZLIB_SHARED_LIBADD) fi ``` config.m4文件很明顯比你迄今為止使用的要大. 幸運的是, 它的語法非常的簡單易懂并且如果你熟悉bash腳本, 對它也就不會陌生. 文件和第5章"你的第一個擴展"中第一次出現的一樣, 都是以PHP_ARG_WITH()宏開始. 這個宏的行為和你用過的PHP_ARG_ENABLE()宏一樣, 不過它將導致./configure時的選項是--with-extname/--without-extname而不再是--enable-extname/--disable-extname. 回顧這些宏, 它們的功能是等同的, 不同僅在于是否讓終端用戶給你的包一些暗示. 你可以在自己創建的私有擴展上使用任意一種方式. 不過, 如果你計劃公開發布, 那就應該知道php正式的編碼標準, 它指出enable/disable用于哪些不需要鏈接外部庫的擴展, with/without則反之. 由于我們這里假設的擴展將鏈接zlib庫, 因此你的config.m4腳本要以查找擴展源代碼中將包含的zlib.h頭文件. 這通過檢查一些標準位置/usr, /usr/local, /opt中include/zlib目錄下的zlib.h完成對其下兩個目錄的定位. 如果找到了zlib.h, 則將基路徑設置到臨時變量ZLIB_DIR中. 一旦循環完成, config.m4腳本檢查ZLIB_DIR是否包含內容來確定是否找到了zlib.h. 如果沒有找到, 則產生一個有意義的錯誤讓用戶知道./configure不能繼續. 此刻, 腳本假設頭文件存在, 對應的庫也必須存在, 因此在下面的兩行使用它修改構建環境, 最終增加-lz -L$ZLIB_DIR/lib到LDFLAGS以及-I$ZLIB_DIR/include到CFLAGS. 最終, 輸出一個確認消息指示zlib安裝已經找到, 并且在編譯期間使用它的路徑. config.m4的其他部分從前面部分的學習中你應該已經熟悉了. 為config.h定義一個#define, 定義擴展并指定它的源代碼文件, 同時標識一個變量完成將擴展附加到構建系統的工作. ## 功能測試 迄今為止, 這個config.m4示例指示查找了需要的頭文件. 盡管這已經夠用了, 但它仍然不能確保產生的二進制正確的進行鏈接, 因為可能不存在匹配的庫文件, 或者版本不正確. 最簡單的檢查zlib.h對應的libz.so庫文件是否存在的方式就是檢查文件是否存在: ```c if ! test -f $ZLIB_DIR/lib/libz.so; then AC_MSG_ERROR([zlib.h found, but libz.so not present!]) fi ``` 當然, 這僅僅是問題的一面. 如果安裝了其他的同名庫但和你要查找的庫不兼容怎么辦呢? 確保你的擴展可以成功編譯的最好方式是測試找到的庫實際編譯所需的內容. 要這樣做就需要在config.m4中PHP_ADD_LIBRARY_WITH_PATH調用之前加入下面代碼: ```c PHP_CHECK_LIBRARY(z, deflateInit,,[ AC_MSG_ERROR([Invalid zlib extension, gzInit() not found]) ],-L$ZLIB_DIR/lib) ``` 這個工具宏將展開輸出一個完整的程序, ./configure將嘗試編譯它. 如果編譯成功, 表示第二個參數定義的符號在第一個參數指定的庫中存在. 成功后, 第三個參數中指定的autoconf腳本將會執行; 失敗后, 第四個參數中指定的autoconf腳本將執行. 在這個例子中, 第三個參數為空, 因為沒有消息就是最好的消息(譯注: 應該是unix哲學之一), 第五個參數也就是左后一個參數, 用于指定額外的編譯器和鏈接器標記, 這里, 使用-L致命了一個額外的用于查找庫的路徑. ## 可選功能 那么現在你已經有正確的庫和頭文件了, 但依賴的是所安裝庫的哪個版本呢? 你可能需要某些功能或排斥某些功能. 由于這種類型的變更通常涉及到某些特定入口點的增加或刪除, 因此可以重用PHP_CHECK_LIBRARY()宏來檢查庫的某些能力. ```c PHP_CHECK_LIBRARY(z, gzgets,[ AC_DEFINE(HAVE_ZLIB_GETS,1,[Having gzgets indicates zlib >= 1.0.9]) ],[ AC_MSG_WARN([zlib < 1.0.9 installed, gzgets() will not be available]) ],-L$ZLIB_DIR/lib) ``` ## 測試實際行為 可能知道某個符號存在也還不能確保你的代碼正確編譯; 某些庫的特定版本可能存在bug需要運行一些測試代碼進行檢查. AC_TRY_RUN()宏可以編譯一個小的源代碼文件為可執行程序并執行. 依賴于傳回給./configure的返回代碼, 你的腳本可以設置可選的#define語句或直接輸出消息(比如如果bug導致不能工作則提示升級)安全退出. 考慮下面的代碼(摘自ext/standard/config.m4): ```c AC_TRY_RUN([ #include <math.h> double somefn(double n) { return floor(n*pow(10,2) + 0.5); } int main() { return somefn(0.045)/10.0 != 0.5; } ],[ PHP_ROUND_FUZZ=0.5 AC_MSG_RESULT(yes) ],[ PHP_ROUND_FUZZ=0.50000000001 AC_MSG_RESULT(no) ],[ PHP_ROUND_FUZZ=0.50000000001 AC_MSG_RESULT(cross compile) ]) AC_DEFINE_UNQUOTED(PHP_ROUND_FUZZ, $PHP_ROUND_FUZZ, [Is double precision imprecise?]) ``` 你可以看到, AC_TRY_RUN()的第一個參數是一塊C語言代碼, 它將被編譯執行. 如果這段代碼的退出代碼是0, 位于第二個參數的autoconf腳本將被執行, 這種情況標識round()函數和期望一樣工作, 返回0.5. 如果代碼塊返回非0值, 位域第三個參數的autoconf腳本將被執行. 第四個參數(最后一個)在php交叉編譯時使用. 這種情況下, 嘗試運行示例代碼是沒有意義的, 因為目標平臺不同于擴展編譯時使用的平臺. ## links * [目錄](<preface.md>) * 17.1 [autoconf](<17.1.md>) * 17.3 [強制模塊依賴](<17.3.md>)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看