composer 不提供跨平台二进制分发能力,所有平台适配需由开发者在 php 入口脚本中通过 php_os_family 判断系统并动态调用对应二进制,且下载与权限设置必须在 post-install-cmd 中完成。

Composer 本身不提供跨平台二进制分发能力,所有“平台适配”必须由你控制脚本行为、资源下载和执行路径——它只负责把 bin 数组里的文件复制/链接到 vendor/bin,其余全是你的事。
bin 字段不支持按系统写不同路径
你在 composer.json 里写 "bin": ["bin/mytool"],Composer 就只会复制这个路径下的文件,不会因为当前是 Windows 就自动切到 bin/mytool.exe,也不会在 macOS 下找 bin/mytool-darwin。所谓“多平台支持”,本质是:你得自己在 bin/mytool 这个 PHP 脚本里做判断。
- 必须用
PHP_OS_FAMILY(不是PHP_OS)识别系统,值为"Linux"、"Windows"、"Darwin" - 不要硬编码路径,比如
/usr/local/bin/chromium或C:\tools\wkhtmltopdf.exe;改用proc_open()+which/where动态查找 - 如果要分发预编译二进制(如
protoc、puppeteer),把它们放在包的resources/下,而不是bin/目录
真正跨平台的入口只能是 PHP 脚本
你不能指望 Composer 把一个 Linux ELF 文件或 Windows PE 文件直接塞进 vendor/bin 并让它跑起来。可行路径只有一条:所有 bin/ 下暴露的入口,必须是带 #!/usr/bin/env php 的 PHP 文件(后缀建议保留 .php),且开头就做平台路由:
<?php if (!isset($_composer_autoload_path)) {
$autoload = __DIR__ . '/../vendor/autoload.php';
if (file_exists($autoload)) {
require $autoload;
}
}
switch (PHP_OS_FAMILY) {
case 'Windows':
exec('mytool-win.exe ' . escapeshellarg($argv[1] ?? ''));
break;
case 'Darwin':
exec('mytool-macos ' . escapeshellarg($argv[1] ?? ''));
break;
default:
exec('mytool-linux ' . escapeshellarg($argv[1] ?? ''));
}
- 别依赖
$_SERVER['OS']或环境变量,它们不可靠;PHP_OS_FAMILY是 PHP 7.2+ 原生、稳定的判断依据 - 确保目标二进制有执行权限(Linux/macOS)或后缀可被识别(Windows 需
.exe或注册了文件类型) - 不要在脚本里写死临时路径,统一用
sys_get_temp_dir()
post-install-cmd 是下载平台专属二进制的唯一可靠时机
Composer 不会帮你下载、校验、解压或替换任何二进制文件。如果你的工具需要 Chromium、wkhtmltopdf 等本地可执行程序,唯一可控的时机是 post-install-cmd 或 post-update-cmd 脚本:
- 在脚本里根据
PHP_OS_FAMILY拼出下载 URL(例如https://github.com/.../mytool-v1.2.0-linux-amd64.tar.gz) - 用
file_get_contents()+gzdecode()或exec('curl | tar -xzf -')解压到resources/bin/ - 最后
chmod +x(Linux/macOS)或确保.exe后缀(Windows) - 不要把下载逻辑塞进
bin/mytool.php—— 那会导致每次运行都重试,且无法离线部署
bin-compat=full 不解决二进制兼容,只解决 PHP 入口加载
设 "bin-compat": "full" 后,Composer 会在 vendor/bin 生成带完整 autoload 加载逻辑的包装器(Linux/macOS 是 PHP 脚本,Windows 是 .bat)。但它完全不管你脚本里 exec() 的那个 mytool-linux 是否真的存在、是否匹配当前 CPU 架构、是否缺失 musl/glibc 依赖。
- 常见失败现象:
Bad CPU type in executable(macOS M1 上跑 x86_64 二进制)、cannot execute binary file: Exec format error(Linux 上跑 Windows EXE) - 这些错误和
bin-compat无关,也和--ignore-platform-reqs无关——后者只跳过 PHP 扩展/版本检查,不重编译、不换二进制 - 验证是否真跨平台:在目标系统上删掉
vendor,重新composer install,再手动进vendor/bin执行对应脚本,看它调用的底层二进制能否./mytool-linux --version
最易被忽略的一点:你写的 bin/mytool.php 在 Windows 上可能被 Git 自动转成 CRLF,导致 #!/usr/bin/env php 失效;而 bin-compat=full 生成的 .bat 又默认调用 php 命令——如果 PATH 里没加 PHP,或者路径含空格(如 C:\Program Files\php),.bat 就会静默失败。这些问题不会报错,只会让你以为“脚本没生效”。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











