如何在Makefile的遍历循环中添加条件分支逻辑
在Makefile中遍历项目并根据名称执行差异化操作
你想要遍历PROJECTS变量里的每个项目,对simulation和webhook执行特定操作,其他项目执行另一个操作对吧?这里有两种可行的实现方式,刚好覆盖你提到的两种思路:
方式一:使用Shell循环(你尝试的方向)
你写的代码其实已经很接近了,这种方式利用Shell的for+case语法来做条件判断,在Makefile里需要注意转义字符的处理,避免被Makefile提前解析变量。完整的可运行示例如下:
PROJECTS = auth core-connect customization forward hook simulation webhook # 假设RUN_7和RUN_8是你预先定义好的命令,比如对应不同PHP版本的执行入口 RUN_7 = docker exec -it api_php7_1 bash -c RUN_8 = docker exec -it api_php8_0 bash -c composer-install: for var in $(PROJECTS); do \ case $$var in \ simulation|webhook) $(RUN_8) "composer install -n --working-dir=apps/$$var" ;; \ *) $(RUN_7) "composer install -n --working-dir=apps/$$var" ;; \ esac; \ done
关键注意点:
- 变量引用要用
$$var而不是$var,因为$在Makefile里有特殊含义,$$会被解析为Shell里的单个$ - 每行Shell命令结尾要用
\来告诉Makefile这行命令还没结束,下一行是延续 case分支里的命令结尾要用;;来标记分支结束,最后整个case块要用esac闭合
方式二:使用Makefile原生函数(贴合你提到的foreach需求)
如果你更倾向于用Makefile的foreach语法结合原生条件判断,可以用if+filter函数来实现,不需要依赖Shell语法:
PROJECTS = auth core-connect customization forward hook simulation webhook RUN_7 = docker exec -it api_php7_1 bash -c RUN_8 = docker exec -it api_php8_0 bash -c composer-install: $(foreach var,$(PROJECTS),\ $(if $(filter $(var),simulation webhook),\ $(RUN_8) "composer install -n --working-dir=apps/$(var)";,\ $(RUN_7) "composer install -n --working-dir=apps/$(var)";\ )\ )
语法说明:
$(filter $(var),simulation webhook):检查当前项目var是否在simulation webhook列表中,如果是则返回项目名称,否则返回空字符串$(if condition, then-command, else-command):如果condition不为空(即项目是目标项目),执行then-command,否则执行else-commandforeach会遍历PROJECTS里的每个项目,把生成的命令依次展开执行
两种方式各有优劣:Shell循环更适合复杂的多分支判断,可读性强;Makefile原生函数的方式更贴合Makefile的语法风格,不需要处理Shell转义的细节,你可以根据自己的习惯选择~
内容的提问来源于stack exchange,提问作者Mitsukk
相关产品推荐
相关产品推荐

