• 【原创】在Windows系统中使用VC9、VC11编译32位、64位PHP及其扩展


    项目中需要使用runkit模块实现AOP,但是团队成员的开发环境都是Windows,而runkit模块官方没有提供Windows环境下的dll扩展,只能自己编译。

    下面是编译过程的分类总结。(操作系统环境为Windows 10 64位中文旗舰版)

    • PHP的编译版本
      这里的版本指的不是PHP的发行版本,如5.3、7.0,而是指编译时所使用的编译器、程序架构和是否为线程安全。
      这些信息可以在phpinfo中打印出来。

      上图中所使用的PHP,是使用Miscrosoft Visual 2012中的MSVC11编译的,程序架构为x86(即32位),非线程安全(NTS)。

      上图中的PHP,是使用Miscrosoft Visual 2012中的MSVC11编译的,程序架构为x64(即64位),线程安全(TS)。

      上图略有不同,没有专门的列表项说明编译器版本、程序架构,只能从编译时的配置中看到相关信息。这里的PHP,是使用Miscrosoft Visual 6中的MSVC6编译的,程序架构为x86(即32位),线程安全(Thread Safety = enabled)。

      最后这一张,是使用Miscrosoft Visual 2008中的MSVC9编译的,程序架构为x86(即32位),线程安全(TS)。
      本文只讨论MSVC9和MSVC11编译两种情况。
    • 准备PHP-SDK和PHP源码
      以下步骤无论编译哪种版本的PHP,都是必须的。
      • 下载PHP-SDK:
        下载地址在http://windows.php.net/downloads/php-sdk/中可以找到,下载其中的php-sdk-binary-tools-20110915.zip
      • 解压到C:php-sdk文件夹
      • 打开命令行,执行如下命令:

        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
        会在c:php-sdk文件夹下生成phpdev文件夹,其中包含vc6、vc8、vc9子文件夹。
        如果使用MSVC11编译PHP,就复制c:php-sdkphpdevvc9到c:php-sdkphpdevvc11。
        如果使用MSVC14编译PHP,就复制c:php-sdkphpdevvc9到c:php-sdkphpdevvc14。

      • 下载相应版本的PHP的编译时依赖包,下载地址见http://windows.php.net/downloads/php-sdk/
        将其解压至相应编译文件夹下的x86或x64文件夹下,覆盖其中的deps文件夹。注意要与要编译的PHP发行版本和程序架构一致,如编译php5.4.x的32位版本则解压deps-5.4-vc9-x86.7z,如编译php5.5.x的64位版本则解压deps-5.6-vc11-x64.7z,依此类推。
        php5.4.x和php5.3.x通常需要使用vc9编译,因此其依赖文件解压到c:php-sdkphpdevvc9x86或c:php-sdkphpdevvc9x64。
        php5.5.x和php5.6.x通常需要使用vc11编译,因此其依赖文件解压到c:php-sdkphpdevvc11x86或c:php-sdkphpdevvc11x64。
        而php7.0.x则需要vc14编译,因此其依赖文件解压到c:php-sdkphpdevvc14x86或c:php-sdkphpdevvc14x64。
      • 下载所需要的PHP源文件,下载地址在http://windows.php.net/download/http://php.net/downloads.phphttp://php.net/releases/http://windows.php.net/downloads/releases/archives/几处都可以找到。
        将其解压制相应的编译文件夹下。
        例如:
        php-5.4.45.tar.gz解压到c:php-sdkphpdevvc9x86php-5.4.45或c:php-sdkphpdevvc9x64php-5.4.45下,以分别编译其32位和64位版本。
        php-5.6.16.tar.gz则解压到c:php-sdkphpdevvc11x86php-5.6.16或c:php-sdkphpdevvc11x64php-5.6.16下。
        php-7.0.3.tar.gz解压到c:php-sdkphpdevvc11x86php-5.6.16或c:php-sdkphpdevvc11x64php-7.0.3下。
      • 如果是编译PHP扩展,则到相应的地址下载源码,本文是以runkit为例,下载地址在http://pecl.php.net/package/runkit
        将下载到的源码解压到PHP源码的ext文件夹下,本例是分别解压到c:php-sdkphpdevvc9x86php-5.4.45ext unkit、c:php-sdkphpdevvc9x64php-5.4.45ext unkit、c:php-sdkphpdevvc11x86php-5.6.16ext unkit、c:php-sdkphpdevvc11x64php-5.6.16ext unkit、c:php-sdkphpdevvc9x86php-7.0.3ext unkit、c:php-sdkphpdevvc9x64php-7.0.3ext unkit。
    • 准备编译环境:

    下面是具体的编译步骤,有些内容会出现重复,是为了让偷懒的同学按图索骥,有样学样:)

    • 使用MSVC9编译PHP5.4.33的32位版(本例为编译runkit.dll)
      • 安装Windows SDK 6.1,注意安装时选择x86编译器。
      • 将下载的php-sdk-binary-tools-20110915.zip解压到c:php-sdk。
      • 打开Windows命令行,输入如下命令:
        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
      • 将下载的php-5.4.45.tar.gz解压到c:php-sdkphpdevvc9x86php-5.4.45。
      • 将下载的deps-5.4-vc9-x86.7z解压到c:php-sdkphpdevvc9x86deps覆盖原deps文件夹。
      • 将下载的http://pecl.php.net/get/runkit-1.0.4.tgz解压到c:php-sdkphpdevvc9x86php-5.4.45ext文件夹,注意文件夹的名称不要带版本号,本例应为runkit,而非runkit-1.0.4。
      • 在c:php-sdkphpdevvc9x86下建立obj文件夹,用于存放最终的php.exe及相关的dll文件。
      • 点击开始菜单,选择Microsoft Windows SDK V6.1>CMD Shell,启动编译命令行。
      • 输入如下指令:
        setenv /x86 /xp /release(此行命令执行成功,命令行的文字将变为绿色)
        cd c:php-sdk
        binphpsdk_setvars.bat
        cd phpdevvc9x86php-5.4.45
        buildconf
        configure --disable-all --enable-cli --enable-runkit=shared --enable-object-out-dir=..obj
        如需编译非线程安全版 (nts版),将上面最后一行换成
        configure --disable-all --enable-cli --enable-runkit=shared --disable-zts --enable-object-out-dir=..obj
        最终执行
        nmake
      • 在obj中有Release(线程安全版-ts版)或Release_nts(非线程安全版-nts版)文件夹,其中的php.exe及php-runkit.dll即为编译结果。
      • 将php-runkit.dll文件放入PHP安装文件夹的ext文件夹中,修改php.ini,加入extension=php_runkit.dll,重新启动PHP服务即可。
    • 使用MSVC9编译PHP5.4.33的64位版(本例为编译runkit.dll)
      • 安装Windows SDK 6.1,注意安装时选择x86编译器。
      • 将下载的php-sdk-binary-tools-20110915.zip解压到c:php-sdk。
      • 打开Windows命令行,输入如下命令:
        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
      • 将下载的php-5.4.45.tar.gz解压到c:php-sdkphpdevvc9x64php-5.4.45。
      • 将下载的deps-5.4-vc9-x86.7z解压到c:php-sdkphpdevvc9x64deps覆盖原deps文件夹。
      • 将下载的http://pecl.php.net/get/runkit-1.0.4.tgz解压到c:php-sdkphpdevvc9x64php-5.4.45ext文件夹,注意文件夹的名称不要带版本号,本例应为runkit,而非runkit-1.0.4。
      • 在c:php-sdkphpdevvc9x64下建立obj文件夹,用于存放最终的php.exe及相关的dll文件。
      • 点击开始菜单,选择Microsoft Windows SDK V6.1>CMD Shell,启动编译命令行。
      • 输入如下指令:与上面编译32位程序明显不同的是,不需要执行 setenv /x86 /xp /release
        cd c:php-sdk
        binphpsdk_setvars.bat
        cd phpdevvc9x64php-5.4.45
        buildconf
        configure --disable-all --enable-cli --enable-runkit=shared --enable-object-out-dir=..obj
        如需编译非线程安全版 (nts版),将上面最后一行换成
        configure --disable-all --enable-cli --enable-runkit=shared --disable-zts --enable-object-out-dir=..obj
        最终执行
        nmake
      • 在obj中有Release(线程安全版-ts版)或Release_nts(非线程安全版-nts版)文件夹,其中的php.exe及php-runkit.dll即为编译结果。
      • 将php-runkit.dll文件放入PHP安装文件夹的ext文件夹中,修改php.ini,加入extension=php_runkit.dll,重新启动PHP服务即可。
    • 使用MSVC11编译PHP5.6.16的32位版(本例为编译runkit.dll)
      • 安装Visual Studio 2012 Express for Windows Desktop
      • 将下载的php-sdk-binary-tools-20110915.zip解压到c:php-sdk。
      • 打开Windows命令行,输入如下命令:
        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
      • 将下载的php-5.6.16.tar.gz解压到c:php-sdkphpdevvc11x86php-5.6.16。
      • 将下载的deps-5.6-vc11-x86.7z解压到c:php-sdkphpdevvc11x86deps覆盖原deps文件夹。
      • 将下载的http://pecl.php.net/get/runkit-1.0.4.tgz解压到c:php-sdkphpdevvc11x86php-5.6.16ext文件夹,注意文件夹的名称不要带版本号,本例应为runkit,而非runkit-1.0.4。
      • 在c:php-sdkphpdevvc11x86下建立obj文件夹,用于存放最终的php.exe及相关的dll文件。
      • 点击开始菜单,选择Microsoft Visual Studio 2012>Visual Studio Tools>VS2012 x86 Native Tools Command Prompt,启动编译命令行。
      • 输入如下指令:
        cd c:php-sdk
        binphpsdk_setvars.bat
        cd phpdevvc11x86php-5.6.16
        buildconf
        configure --disable-all --enable-cli --enable-runkit=shared --enable-object-out-dir=..obj
        如需编译非线程安全版 (nts版),将上面最后一行换成
        configure --disable-all --enable-cli --enable-runkit=shared --disable-zts --enable-object-out-dir=..obj
        最终执行
        nmake
      • 在obj中有Release(线程安全版-ts版)或Release_nts(非线程安全版-nts版)文件夹,其中的php.exe及php-runkit.dll即为编译结果。
      • 将php-runkit.dll文件放入PHP安装文件夹的ext文件夹中,修改php.ini,加入extension=php_runkit.dll,重新启动PHP服务即可。
    • 使用MSVC11编译PHP5.6.16的64位版(本例为编译runkit.dll)
      • 安装Visual Studio 2012 Express for Windows Desktop
      • 将下载的php-sdk-binary-tools-20110915.zip解压到c:php-sdk。
      • 打开Windows命令行,输入如下命令:
        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
      • 将下载的php-5.6.16.tar.gz解压到c:php-sdkphpdevvc11x64php-5.6.16。
      • 将下载的deps-5.6-vc11-x64.7z解压到c:php-sdkphpdevvc11x64deps覆盖原deps文件夹。
      • 将下载的http://pecl.php.net/get/runkit-1.0.4.tgz解压到c:php-sdkphpdevvc11x64php-5.6.16ext文件夹,注意文件夹的名称不要带版本号,本例应为runkit,而非runkit-1.0.4。
      • 在c:php-sdkphpdevvc11x64下建立obj文件夹,用于存放最终的php.exe及相关的dll文件。
      • 点击开始菜单,选择Microsoft Visual Studio 2012>Visual Studio Tools>VS2012 x64 Cross Tools Command Prompt,启动编译命令行。
      • 输入如下指令:
        cd c:php-sdk
        binphpsdk_setvars.bat
        cd phpdevvc11x64php-5.6.16
        buildconf
        configure --disable-all --enable-cli --enable-runkit=shared --enable-object-out-dir=..obj
        如需编译非线程安全版 (nts版),将上面最后一行换成
        configure --disable-all --enable-cli --enable-runkit=shared --disable-zts --enable-object-out-dir=..obj
        最终执行
        nmake
      • 在obj中有Release(线程安全版-ts版)或Release_nts(非线程安全版-nts版)文件夹,其中的php.exe及php-runkit.dll即为编译结果。
      • 将php-runkit.dll文件放入PHP安装文件夹的ext文件夹中,修改php.ini,加入extension=php_runkit.dll,重新启动PHP服务即可。
    • 使用MSVC14编译PHP7.0.3的32位版(本例为编译runkit.dll)
      • 安装Visual Studio 2015 Community
      • 将下载的php-sdk-binary-tools-20110915.zip解压到c:php-sdk。
      • 打开Windows命令行,输入如下命令:
        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
      • 将下载的php-7.0.3.tar.gz解压到c:php-sdkphpdevvc14x86php-7.0.3。
      • 将下载的deps-7.0-vc14-x86.7z解压到c:php-sdkphpdevvc14x86deps覆盖原deps文件夹。
      • 将下载的http://pecl.php.net/get/runkit-1.0.4.tgz解压到c:php-sdkphpdevvc14x86php-7.0.3ext文件夹,注意文件夹的名称不要带版本号,本例应为runkit,而非runkit-1.0.4。
      • 在c:php-sdkphpdevvc14x86下建立obj文件夹,用于存放最终的php.exe及相关的dll文件。
      • 点击开始菜单,选择Visual Studio 2015>VS2015 x64 X86 兼容工具命令行,启动编译命令行。
      • 输入如下指令:
        cd c:php-sdk
        binphpsdk_setvars.bat
        cd phpdevvc14x86php-7.0.3
        buildconf
        configure --disable-all --enable-cli --enable-runkit=shared --enable-object-out-dir=..obj
        如需编译非线程安全版 (nts版),将上面最后一行换成
        configure --disable-all --enable-cli --enable-runkit=shared --disable-zts --enable-object-out-dir=..obj
        最终执行
        nmake
      • 在obj中有Release(线程安全版-ts版)或Release_nts(非线程安全版-nts版)文件夹,其中的php.exe及php-runkit.dll即为编译结果。
      • 将php-runkit.dll文件放入PHP安装文件夹的ext文件夹中,修改php.ini,加入extension=php_runkit.dll,重新启动PHP服务即可。
    • 使用MSVC14编译PHP7.0.3的64位版(本例为编译runkit.dll)
      • 安装Visual Studio 2015 Community
      • 将下载的php-sdk-binary-tools-20110915.zip解压到c:php-sdk。
      • 打开Windows命令行,输入如下命令:
        cd c:php-sdk
        binphpsdk_buildtree.bat phpdev
      • 将下载的php-7.0.3.tar.gz解压到c:php-sdkphpdevvc14x64php-7.0.3。
      • 将下载的deps-7.0-vc14-x64.7z解压到c:php-sdkphpdevvc14x64deps覆盖原deps文件夹。
      • 将下载的http://pecl.php.net/get/runkit-1.0.4.tgz解压到c:php-sdkphpdevvc14x64php-7.0.3ext文件夹,注意文件夹的名称不要带版本号,本例应为runkit,而非runkit-1.0.4。
      • 在c:php-sdkphpdevvc14x64下建立obj文件夹,用于存放最终的php.exe及相关的dll文件。
      • 点击开始菜单,选择Visual Studio 2015>VS2015 x86 X64 兼容工具命令行,启动编译命令行。
      • 输入如下指令:
        cd c:php-sdk
        binphpsdk_setvars.bat
        cd phpdevvc14x64php-7.0.3
        buildconf
        configure --disable-all --enable-cli --enable-runkit=shared --enable-object-out-dir=..obj
        如需编译非线程安全版 (nts版),将上面最后一行换成
        configure --disable-all --enable-cli --enable-runkit=shared --disable-zts --enable-object-out-dir=..obj
        最终执行
        nmake
      • 在obj中有Release(线程安全版-ts版)或Release_nts(非线程安全版-nts版)文件夹,其中的php.exe及php-runkit.dll即为编译结果。
      • 将php-runkit.dll文件放入PHP安装文件夹的ext文件夹中,修改php.ini,加入extension=php_runkit.dll,重新启动PHP服务即可。

    可能遇到的问题:

    • 如果遇到There is no script engine for file extension ".js"错误,说明Windows的jscript引擎没有正确注册,可按如下步骤解决:
      • 以管理员身份打开命令行:
      • 执行如下指令:

        regsvr32 %WINDIR%System32jscript.dll
        regsvr32 %WINDIR%SysWOW64jscript.dll

      • 生成一个jscript.reg的文件,内容如下:

        Windows Registry Editor Version 5.00

        [HKEY_CLASSES_ROOT.js]
        @="jsfile"

        [HKEY_CLASSES_ROOT.jsPersistentHandler]
        @="{5e941d80-bf96-11cd-b579-08002b30bfeb}"

        [HKEY_CLASSES_ROOTJSFile]
        "FriendlyTypeName"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,
          00,6f,00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,
          32,00,5c,00,77,00,73,00,68,00,65,00,78,00,74,00,2e,00,64,00,6c,00,6c,00,2c,
          00,2d,00,34,00,38,00,30,00,34,00,00,00

        [HKEY_CLASSES_ROOTJSFileScriptEngine]
        @="JScript"

        [HKEY_CLASSES_ROOTJSFileScriptHostEncode]
        @="{85131630-480C-11D2-B1F9-00C04F86C324}"

        [HKEY_CLASSES_ROOTJSFileShell]
        @="Open"

        [HKEY_CLASSES_ROOTJSFileShellOpenCommand]
        @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,
          00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,57,00,53,00,
          63,00,72,00,69,00,70,00,74,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,00,31,
          00,22,00,20,00,25,00,2a,00,00,00

        [HKEY_CLASSES_ROOTJSFileShellOpen2]
        @=hex(2):4f,00,70,00,65,00,6e,00,20,00,26,00,77,00,69,00,74,00,68,00,20,00,43,
          00,6f,00,6d,00,6d,00,61,00,6e,00,64,00,20,00,50,00,72,00,6f,00,6d,00,70,00,
          74,00,00,00
        "MUIVerb"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,
          6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,
          00,77,00,73,00,68,00,65,00,78,00,74,00,2e,00,64,00,6c,00,6c,00,2c,00,2d,00,
          34,00,35,00,31,00,31,00,00,00

        [HKEY_CLASSES_ROOTJSFileShellOpen2Command]
        @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,
          00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,43,00,53,00,
          63,00,72,00,69,00,70,00,74,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,00,31,
          00,22,00,20,00,25,00,2a,00,00,00

        [HKEY_CLASSES_ROOTJSFileShellPrintCommand]
        @=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,
          00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,4e,00,6f,00,
          74,00,65,00,70,00,61,00,64,00,2e,00,65,00,78,00,65,00,20,00,2f,00,70,00,20,
          00,25,00,31,00,00,00

        [HKEY_CLASSES_ROOTJSFileShellExDropHandler]
        @="{60254CA5-953B-11CF-8C96-00AA00B8708C}"

        [HKEY_CLASSES_ROOTJSFileShellExPropertySheetHandlersWSHProps]
        @="{60254CA5-953B-11CF-8C96-00AA00B8708C}"

        [HKEY_CLASSES_ROOTJScript]
        @="JScript Language"

        [HKEY_CLASSES_ROOTJScriptCLSID]
        @="{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}"

        [HKEY_CLASSES_ROOTJScriptOLEScript]

      • 双击该文件,点击确定,将其导入注册表即可。
    • 如果在使用MSVC9编译32位PHP时,遇到Checking for cl.exe ... <not found>错误,就表示在安装Windows SDK 6.1时,忘记选择x86编译器。

    PS:

    • 以上的步骤中,其实有很多是不需要按部就班的,尤其是文件夹结构。c:php-sdk,其实可以放在任意盘符下。只要在开始编译前,执行一上:x:php-sdkinphp-setvars.bat就可以了(x:为php-sdk所在盘符)。
    • phpdev及其下的各级文件夹也是不需要的,尤其是x86和x64文件夹,并不是放错了就不行的,那只是方便辨识最后编译的结果。只要将deps和php源码放在同一个文件夹下,比如在d:建立php-source文件夹,其下放置desp、obj和php-5.6.16子文件夹(嗯,obj放哪儿也无所谓,在编译时直接将输出结果的位置指向到obj就行了),进入php-5.6.16文件夹进行编译即可。

    实践过程中,主要参考如下三篇文章,仅向原作者致谢:

  • 相关阅读:
    wcdb中使用rowid做查询条件
    [转载]Linux下断开SSH连接后,让程序继续在后台执行
    Mac OS X wants to use the “system” keychain 的解决方案
    wcdb的主键和唯一性
    type(),dir(),getattr(),hasattr(), isinstance()用法
    获取昨天日期
    二分法
    三次握手和四次挥手
    py2和py3之间的不同
    flask 接收参数小坑
  • 原文地址:https://www.cnblogs.com/matchless/p/5170785.html
Copyright © 2020-2023  润新知