PHP 扩展未加载的原因可能有很多,但直接指出原因(和修复)并不总是那么容易,因为从源代码编译到显示之间存在差距phpinfo()
然后最后错过了扩展很大。
首先获取真正的错误信息
减少故障排除距离的一种方法是查看 PHP 是否可以加载扩展and如果没有,则显示错误消息。
A common test for that is to use the CLI SAPI (PHP on the commandlineDocs https://www.php.net/manual/en/features.commandline.php) as it allows to reduce and easier control the PHP runtime environment while being compatible with the extension.
要启动 PHP,请使用default配置(无.ini
文件),仅加载单个扩展二进制文件来测试并显示配置信息,运行:
$ php -n -d extension=gmp.so -i
Excerpt from OptionsDocs https://www.php.net/manual/en/features.commandline.options.php, also there is php --help
:
-n No php.ini file will be used
-d foo[=bar] Define INI entry foo with value 'bar'
-i PHP information
这应该会引发错误(在标准错误的终端中显示)或显示在 PHP 信息输出中加载的扩展(在标准输出上)。
或者,要减少输出并仅检查错误,请使用以下命令执行空 PHP 语句-r
命令行开关:
-r <code> Run PHP <code> without using script tags <?..?>
具有相关 GMP 扩展的示例:
$ php -n -d extension=gmp.so -r ';'
这将退出非零(退出状态) 如果加载扩展时出现问题,并且标准错误上显示错误消息and如果可以加载扩展,将以零状态退出:
$ php -n -d extension=gmp.so -r ';'
PHP Warning: PHP Startup: Unable to load dynamic library 'gmp.so' (tried: /Applications/MAMP/bin/php/php7.3.27/lib/php/extensions/no-debug-non-zts-20180731/gmp.so (dlopen(/Applications/MAMP/bin/php/php7.3.27/lib/php/extensions/no-debug-non-zts-20180731/gmp.so, 9): no suitable image found. Did find:
/Applications/MAMP/bin/php/php7.3.27/lib/php/extensions/no-debug-non-zts-20180731/gmp.so: mach-o, but wrong architecture
/Applications/MAMP/bin/php/php7.3.27/lib/php/extensions/no-debug-non-zts-20180731/gmp.so: mach-o, but wrong architecture), /Applications/MAMP/bin/php/php7.3.27/lib/php/extensions/no-debug-non-zts-20180731/gmp.so.so (dlopen(/Applications/MAMP/bin/php/php7.3.27/lib/php/extensions/no-debug-non-zts-20180731/gmp.so.so, 9): image not found)) in Unknown on line 0
$ echo $?
254
如示例所示,错误已经出现在“PHP 启动”中,这是 PHP 发出诊断消息加载扩展的典型阶段。
Dlopen 9:找不到合适的图像:mach-o,但架构错误
上面的错误消息表明 a) PHP 首先无法加载扩展(作为动态库, .so
文件,一个共享对象文件,即编译后的扩展名)和 b)它无法加载,因为没有合适的图像被找到:
PHP 警告:PHP 启动:无法加载动态库“gmp.so”(尝试过:<path>
(dlopen(<path>
, 9): 没有找到合适的图像。是否发现:<path>
:mach-o,但是错误的架构...),<path>
(dlopen(<path>.so
, 9): 未找到图像)) 在第 0 行未知中
这意味着该文件在磁盘上可用(可以打开),但图像不合适,这意味着它与体系结构不匹配。
(尝试中有一些噪音gmp.so.so
这是由 php 完成的,所以可以通过-d extension=gmp
无需扩展即可直接工作,例如在 php-.ini
在 *nix (.so
)或窗口(.dll
)。这部分可以忽略,即“找不到图像”,因为文件不存在,这是预期的)
它必须与 PHP 本身具有相同的架构,因为 PHP 已经在运行并且想要加载二进制扩展 - 它们需要适合。
要获取 PHP 的体系结构,请找到 PHP 命令:
$ which php
/Applications/MAMP/bin/php/php7.3.27/bin/php
这是 php 二进制文件的绝对路径。有了它,现在可以file(1)
实用程序来获取有关它的更多信息:
$ file /Applications/MAMP/bin/php/php7.3.27/bin/php
/Applications/MAMP/bin/php/php7.3.27/bin/php: Mach-O 64-bit executable x86_64
(或致电$ file "$(which php)"
用于同时运行)
它显示了 php 二进制文件信息,包括。这x86_64
最后的架构:
Mach-O 64 位可执行文件 x86_64
作为共享对象图像来加载(编译后的php扩展gmp.so
file)也需要匹配一下,同理file(1)
实用程序可用于已编译的扩展.so
以同样的方式归档。
然后比较应该显示出差异。
有了这些信息,最终就可以使用适当的架构来编译扩展。
结束语:
关于 Apple Silicon M1,我对编译并不是特别深入,它的架构和其他人可以更好地说明这一点。据我所知,你通过运行brew来管理它arch(1)
实用程序设置架构arch -x86_64 <command>
to x86_64
。在 Apple Silicon 上,这可能需要更多工具,即Rosetta.
这似乎是 M1 用户博客中常见的内容(via 奥斯汀·卡梅伦 2020 年 11 月 https://austencam.com/posts/setting-up-an-m1-mac-for-laravel-development-with-homebrew-php-mysql-valet-and-redis)但这完全不是我的系统。
根据我自己的理解,应该可以使用编译器标志或在配置行上设置架构,通常就是这样。
由于brew具有如何在系统上编译扩展的信息(酿造配方,此处为 gmp https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/gmp.rb)也许最直接的方法是使用它并在正确的架构下运行安装。
需要注意的是,您需要在(?)正确的体系结构中使用arch(1)
实用程序以及(和brew安装)。