composer run-script 默认无法直接执行 make 命令,因其在非交互式 shell 中运行,path 精简、环境变量不继承,且命令经 sh -c 封装后易因空格、引号或 shell 差异(如 alpine 的 ash)解析失败;makefile 中的 $(pwd)、$(shell ...) 等也常因上下文缺失而失效。

为什么 run-script 不能直接执行 make 命令
默认情况下,composer run-script 启动的是 shell 的非交互模式(non-interactive),且环境变量受限、PATH 精简,make 命令常因找不到可执行文件或缺失 MAKEFLAGS 而失败。更隐蔽的问题是:Composer 会把脚本参数原样拼接进 shell 命令,导致空格、引号、重定向等被错误解析。
- 在
composer.json的scripts中写"build": "make build",实际执行的是sh -c 'make build',而某些系统(如 Alpine)默认用ash,不支持make的某些语法(如.ONESHELL) -
make依赖的环境变量(如CI、COMPOSER_HOME)不会自动继承到子 shell,需显式传递 - 如果 Makefile 里用了
$(shell ...)或$(shell pwd),在 Composer 封装的 shell 中可能返回空或错误路径
如何让 run-script 正确调用 Makefile 目标
关键不是“绕过 Composer”,而是让它成为可控入口:用 sh -c 显式控制 shell 行为,并补全必要上下文。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 在
composer.json中定义脚本时,统一用sh -c包裹,例如:"ci:lint": "sh -c 'make lint'" - 确保
PATH包含make所在路径(多数 CI 环境中是/usr/bin或/bin),可在命令前加export PATH=\"/usr/bin:/bin:$PATH\" && - 若需传递变量,用
sh -c 'make TARGET VAR1=\"$1\" VAR2=\"$2\"' _形式,避免变量被 Composer 提前展开(注意单引号和$1的转义) - Makefile 开头加上
.SHELLFLAGS := -e -c,强制 shell 遇错退出,防止某一步失败后继续执行
Makefile 中哪些写法会导致 run-script 失败
Makefile 本身没问题,但某些惯用写法在 Composer 封装环境下会失效。
-
@echo $(PWD)→ 改用@pwd,因为$(PWD)是 make 内置变量,在某些 make 版本中未初始化;$(shell pwd)更可靠 -
docker build -f Dockerfile .→ 若 CI 环境没装 docker,命令会静默失败;应在 Makefile 中加which docker > /dev/null || (echo \"docker not found\"; exit 1) - 依赖多行命令时不用
\换行,改用; \或拆成多个目标,否则 Composer 的 shell 解析可能中断 - 不要在 Makefile 中写
#!/usr/bin/env bash—— 这不是脚本,是 make 规则,shebang 会被忽略且可能报错
调试 run-script + Makefile 组合的实际技巧
出问题时别只看 Composer 输出,要还原真实执行链路。
- 运行
composer run-script ci:lint --verbose,观察最后一行实际执行的sh -c命令,复制出来手动执行一遍 - 在 Makefile 目标开头加
@set -x; echo "ENV: $$PATH, $$CI, $$(which make)",确认环境是否就绪 - 临时把目标命令替换成
env | sort,检查哪些变量被丢掉了(比如GITHUB_TOKEN在 GitHub Actions 中默认不传给子进程) - 如果用
composer install --no-scripts后再手动composer run-script,注意 autoloader 可能未生成,vendor/autoload.php不可用 —— 这类 PHP 逻辑不应塞进 Makefile
make 总在 $PATH,或 $(CURDIR) 总等于项目根目录。










