# 5.2 編譯我們的擴展
我們已經在上一節準備好了需要編譯的源文件,接下來需要的便是把它們編譯成目標文件了。因為在*nix平臺和win平臺下的編譯步驟有些差異,所以這個地方需要分成兩塊介紹,很不幸,win部分還沒有整理,請隨時關注本項目。
### 在*nix下編譯
第一步:我們需要根據config.m4文件生成一個configure腳本、Makefile等文件,這一步有phpize來幫我們做:
````c
$ phpize
PHP Api Version: 20041225
Zend Module Api No: 20050617
Zend Extension Api No: 220050617
````
The extra 2 at the start of Zend Extension Api No isn't a typo; it corresponds to the Zend Engine 2 version and is meant to keep this API number greater than its ZE1 counterpart.
現在查看一下我們擴展所在的目錄,會發現多了許多文件。phpize程序根據config.m4里的信息生成了許多編譯php擴展必須的文件,比如生成makefiles等,這為我們省了很多的麻煩。 接下來我們運行./configure腳本,這里我們并不需要再注明enable-maintainer-zts、enable-debug等參數,phpize程序會自動的去已經編譯完成的php核心里獲取這幾個參數的值。 接下來就像我們安裝其它程序一樣執行make; make test;即可,如果沒有錯誤,那么在module文件夾下面便會生成我們的目標文件 —— walu.so。
### 在windows平臺下編譯
The config.m4 file you created earlier was actually specific to the *nix build. In order to make your extension compile under Windows, you'll need to create a separatebut similarconfiguration file for it.
Add config.w32 with the following contents to your ext/sample directory:
````c
ARG_ENABLE("sample", "enable sample extension", "no");
if (PHP_SAMPLE != "no") {
EXTENSION("sample", "sample.c");
}
````
As you can see, this file bears a resemblance on a high level to config.m4. The option is declared, tested, and conditionally used to enable the build of your extension.
Now you'll repeat a few of the steps you performed in Chapter 4, "Setting Up a Build Environment," when you built the PHP core. Start by opening up a build window from the Start menu by selecting All Programs, Microsoft Platform SDK for Windows Server 2003 SP1, Open Build Environment Window, Windows 2000 Build Environment, Set Windows 2000 Build Environment (Debug), and running the C:\Program Files\Microsoft Visual Studio 8\VC\bin\vcvars32.bat batch file.
Remember, your installation might require you to select a different build target or run a slightly different batch file. Refer to the notes in the corresponding section of Chapter 4 to refresh your memory.
Again, you'll want to go to the root of your build directory and rebuild the configure script.
````c
C:\Program Files\Microsoft Platform SDK> cd \PHPDEV\php-5.1.0
C:\PHPDEV\php-5.1.0> buildconf.bat
Rebuilding configure.js
Now run 'cscript /nologo configure.js help'
````
This time, you'll run the configure script with an abridged set of options. Because you'll be focusing on just your extension and not the whole of PHP, you can leave out options pertaining to other extensions; however, unlike the Unix build, you do need to include the enable-debug switch explicitly even though the core build already has it.
The only crucial switch you'll need hereapart from debug of courseis enable-sample=shared. The shared option is required here because configure.js doesn't know that you're planning to build sample as a loadable extension. Your configure line should therefore look something like this:
````c
C:\PHPDEV\php-5.1.0> cscript /nologo configure.js \
enable-debug enable-sample=shared
````
Recall that enable-maintainer-zts is not required here as all Win32 builds assume that ZTS must be enabled. Options relating to SAPIssuch as embedare also not required here as the SAPI layer is independent from the extension layer.
Lastly, you're ready to build the extension. Because this build is based from the coreunlike the Unix extension build, which was based from the extensionyou'll need to specify the target name in your build line.
````c
C:\PHPDEV\php-5.1.0> nmake php_sample.dll
````
Once compilation is complete, you should have a working php_sample.dll binary ready to be used in the next step. Remember, because this book focuses on *nix development, the extension will be referred to as sample.so rather than php_sample.dll in all following text.
Loading an Extension Built as a Shared Module
### 加載擴展
為了使PHP能夠找到需要的擴展文件,我們需要把編譯好的so文件或者dll文件復制到PHP的擴展目錄下,它的地址我們可以通過phpinfo()輸出的信息找到,也可以在php.ini文件里進行配置找到并配置,名稱為:extension_dir的值。默認情況下,php.ini文件位于/usr/local/lib/php.ini或者C:\windows\php.ini(現在由于fastcgi模式居多,在win平臺上php.ini越來越多的直接存在于php-cgi.exe程序所在目錄下)。如果找不到,我們可以通過php -i 命令或者<?php phpinfo();來查看當前加載的php.ini文件位置。
一旦我們設置了extension_dir,便可以在我們的web文件中引用我們的擴展了,我們可以通過dl命令來將我們的擴展加載到內存中來。
````php
<?php
dl('sample.so');
var_dump(get_loaded_extensions());
?>
````
如果在輸出中我們沒有找到walu.so,那肯定是哪里出問題了。這時候我們需要根據程序的輸出信息去查找錯誤。
上面這樣每次使用擴展都需要先dl一下真是太麻煩了,其實我們有更好的辦法讓php運行時自動加載我們的擴展。那就是在php.ini里這樣配置:
````c
extension_dir=/usr/local/lib/php/modules/
extension=walu.so
````
這樣只要我們把walu.so這個文件放置在extension_dir配置的目錄下,php就會在每次啟動的時候自動加載了。這樣我們就可以像我們平時使用curl、Mysql擴展一樣直接使用,而不用麻煩的調用dl函數了。
備注: 以下的章節我們都默認使用上面的這種方式來加載我們的擴展,而不是調用dl函數。
## links
* 5.1 [一個擴展的基本結構](<5.1.md>)
* 5.3 [靜態編譯](<5.3.md>)
- about
- 開始閱讀
- 目錄
- 1 PHP的生命周期
- 1.讓我們從SAPI開始
- 2.PHP的啟動與終止
- 3.PHP的生命周期
- 4.線程安全
- 5.小結
- 2 PHP變量在內核中的實現
- 1. 變量的類型
- 2. 變量的值
- 3. 創建PHP變量
- 4. 變量的存儲方式
- 5. 變量的檢索
- 6. 類型轉換
- 7. 小結
- 3 內存管理
- 1. 內存管理
- 2. 引用計數
- 3. 總結
- 4 動手編譯PHP
- 1. 編譯前的準備
- 2. PHP編譯前的config配置
- 3. Unix/Linux平臺下的編譯
- 4. 在Win32平臺上編譯PHP
- 5. 小結
- 5 Your First Extension
- 1. 一個擴展的基本結構
- 2. 編譯我們的擴展
- 3. 靜態編譯
- 4. 編寫函數
- 5. 小結
- 6 函數返回值
- 1. 一個特殊的參數:return_value
- 2. 引用與函數的執行結果
- 3. 小結
- 7 函數的參數
- 1. zend_parse_parameters
- 2. Arg Info 與類型綁定
- 3. 小結
- 8 使用HashTable與{數組}
- 1. 數組(C中的)與鏈表
- 2. 操作HashTable的API
- 3. 在內核中操作PHP語言中數組
- 4. 小結
- 9 PHP中的資源類型
- 1. 復合類型的數據——{資源}
- 2. Persistent Resources
- 3. {資源}自有的引用計數
- 4. 小結
- 10 PHP中的面向對象(一)
- 1. zend_class_entry
- 2. 定義一個類
- 3. 定義一個接口
- 4. 類的繼承與接口的實現
- 5. 小結
- 11 PHP中的面向對象(二)
- 1. 生成對象的實例與調用方法
- 2. 讀寫對象的屬性
- 3. 小結
- 12 啟動與終止的那點事
- 2. 小結
- 1. 關于生命周期
- 2. MINFO與phpinfo
- 3. 常量
- 4. PHP擴展中的全局變量
- 5. PHP語言中的超級全局變量
- 6. 小結
- 13 INI設置
- 1. 聲明和訪問ini設置
- 2. 小結
- 2. 小結
- 14 流式訪問
- 1. 概覽
- 2. 打開流
- 3. 訪問流
- 4. 靜態資源操作
- 5. 小結
- 15 流的實現
- 1. php流的表象之下
- 2. 包裝器操作
- 3. 實現一個包裝器
- 4. 操縱
- 5. 檢查
- 6. 小結
- 16 有趣的流
- 1. 上下文
- 2. 過濾器
- 3. 小結
- 17 配置和鏈接
- 1. autoconf
- 2. 庫的查找
- 3. 強制模塊依賴
- 4. Windows方言
- 5. 小結
- 18 擴展生成
- 1. ext_skel
- 2. PECL_Gen
- 3. 小結
- 19 設置宿主環境
- 1. 嵌入式SAPI
- 2. 構建并編譯一個宿主應用
- 3. 通過嵌入包裝重新創建cli
- 4. 老技術新用
- 5. 小結
- 20 高級嵌入式
- 1. 回調到php中
- 2. 錯誤處理
- 3. 初始化php
- 4. 覆寫INI_SYSTEM和INI_PERDIR選項
- 5. 捕獲輸出
- 6. 同時擴展和嵌入
- 7. 小結
- 約定