无法找出具有复杂依赖项的Makefile

无法找出具有复杂依赖项的Makefile,makefile,gnu-make,Makefile,Gnu Make,我手头有一项任务,我的源文件位于: apps/$(APP_NAME)/$(APP_ENV)/$(APP_NAME).yml 然后我需要将这些文件处理为: .output/$(APP_NAME)/$(APP_ENV).yml 我无法为我的APP_名称是动态的且来自的Makefile整理规则 APP_NAMES=$(shell ls -1 $(APP_DIRS)) 我能做到这一点没有问题: OUTPUT_DIR:=.output APPS_DIR:=apps $(OUTPUT_DIR)/app

我手头有一项任务,我的源文件位于:

apps/$(APP_NAME)/$(APP_ENV)/$(APP_NAME).yml
然后我需要将这些文件处理为:

.output/$(APP_NAME)/$(APP_ENV).yml
我无法为我的APP_名称是动态的且来自的Makefile整理规则

APP_NAMES=$(shell ls -1 $(APP_DIRS))
我能做到这一点没有问题:

OUTPUT_DIR:=.output
APPS_DIR:=apps
$(OUTPUT_DIR)/app1/prod.yml: $(APPS_DIR)/app1/prod/app1.yml
    $(eval APP_ENV=$(patsubst %.yml, %, $(patsubst $(OUTPUT_DIR)/%, %, $@)))
    $(eval APP=$(dir $(APP_ENV)))
    $(eval ENV=$(notdir $(APP_ENV)))
    mkdir -p $(dir $@)
    my_process --app=$(APP) --environment=$(ENV) --apps-dir=$(APPS_DIR) > $@

但是,我无法创建隐式动态规则。

模式规则只能出现一次%,但您的案例需要两次

我会尝试使用宏动态生成必要的规则,然后$eval它们。如果我正确理解您的需求,那么此makefile应该可以:

makefile中的第一条规则是默认规则 冒牌货:全部 全部: 输出目录:=.OUTPUT 应用程序目录:=应用程序 设置为解决方案的固定列表-可以是动态的 来源_YMLS:=\ $APPS_DIR/test1/prod/test1.yml\ $APPS_DIR/test1/env1/test1.yml\ $APPS_DIR/test1/env2/test1.yml\ $APPS_DIR/test2/stage/test2.yml\ $APPS_DIR/test2/env3/test2.yml\ $APPS_DIR/test2/env4/test2.yml\ 输出符号:= 输出目录:= $1:源文件名$APPS_DIR///.yml 定义生成规则 _输入部分:=$subst/,$patsubst$APPS\u DIR/%,%,$1 _应用程序名称:=$$word 1,$$\u输入\u部分 _应用程序环境:=$$word 2,$$\u输入\u部分 _output\u dir:=$output\u dir/$$\u app\u name _output\u yml:=$$\u output\u dir/$$\u app\u env.yml 配方评估的目标特定变量 $$\u输出\u yml:\u应用程序\u名称:=$$\u应用程序\u名称 $$\u输出\u yml:\u应用程序\u环境:=$$\u应用程序\u环境 为什么myprocess不直接使用$$<??? 注意:>$$@注释仅用于测试 $$\u output\u yml:$1 |$$\u output\u dir @echo my_进程-app=$$\u app_name-environment=$$\u app_env-apps dir=$apps_dir>$$@ 输出\u目录+=$$\u输出\u目录 输出\u YMLS+=$$\u输出\u yml _输入部件:= _应用程序名称:= _应用程序环境:= _输出目录:= _输出_yml:= 恩德夫 为输出yml文件生成规则 $eval\ $foreach\u f,$SOURCE\u YMLS\ $call generate\u yml\u规则,$\u f\ \ 删除重复目录 输出目录:=$sort$OUTPUT目录 $info OUTPUT\u DIRS'$OUTPUT\u DIRS' $info OUTPUT\u YMLS'$OUTPUT\u YMLS' 全部:$OUTPUT_YMLS @回音完成 $OUTPUT_DIRS:|$OUTPUT_DIR $OUTPUT\u DIRS$OUTPUT\u DIR: mkdir-p$@ 如果我们在eval前面预先添加了信息,那么我们将生成的代码仅显示摘录:

评估输入零件:=test1产品test1.yml _应用程序名称:=$word 1,$\u输入\u部分 _app_env:=$word 2,$\u input\u parts _output\u dir:=.output/$\u app\u name _output\u yml:=$\u output\u dir/$\u app\u env.yml 配方评估的目标特定变量 $\输出\u yml:\应用程序\u名称:=$\应用程序\u名称 $\u输出\u yml:\u应用程序\u环境:=$\u应用程序\u环境 为什么myprocess不直接使用$<??? 注意:>$@注释仅用于测试 $\u output\u yml:apps/test1/prod/test1.yml$\u output\u dir @echo my_进程-app=$\u app_name-environment=$\u app_env-apps dir=apps>$@ 输出目录+=$\u输出目录 输出\u YMLS+=$\u输出\u yml _输入部件:= _应用程序名称:= _应用程序环境:= _输出目录:= _输出_yml:= _输入部分:=test1 env1 test1.yml _应用程序名称:=$word 1,$\u输入\u部分 _app_env:=$word 2,$\u input\u parts _output\u dir:=.output/$\u app\u name _output\u yml:=$\u output\u dir/$\u app\u env.yml 配方评估的目标特定变量 $\输出\u yml:\应用程序\u名称:=$\应用程序\u名称 $\u输出\u yml:\u应用程序\u环境:=$\u应用程序\u环境 为什么myprocess不直接使用$<??? 注意:>$@注释仅用于测试 $\u output\u yml:apps/test1/env1/test1.yml$\u output\u dir @echo my_进程-app=$\u app_name-environment=$\u app_env-apps dir=apps>$@ 输出目录+=$\u输出目录 输出\u YMLS+=$\u输出\u yml _输入部件:= ... 依此类推其他4个源文件。。。 用echo注释掉测试运行myprocess,以显示正在发生的情况:

$make OUTPUT_DIRS'.OUTPUT/test1.OUTPUT/test2' OUTPUT_YMLS'.OUTPUT/test1/prod.yml.OUTPUT/test1/env1.yml.OUTPUT/test1/env2.yml.OUTPUT/test2/stage.yml.OUTPUT/test2/env3.yml.OUTPUT/test2/env4.yml' mkdir-p.output mkdir-p.output/test1 my_进程-app=test1-environment=prod-apps dir=apps my_进程-app=test1-environment=env1-apps dir=apps my_进程-app=test1-environment=env2-apps dir=apps mkdir-p.output/test2 my_进程-app=test2-environment=stage-apps dir=apps my_进程-app=test2-environment=env3-apps dir=apps my_进程-app=test2-environment=env4-apps dir=apps 完成
模式规则一次只能处理一个通配符。你想做的事是可以做到的,但这很棘手。你说APP_NAME来自对ls的呼叫;APP_ENV从何而来?APP_ENV combo基本上是从目标路径中以APP_NAME/ENV的形式提取该对,该对由代码dir/notdir part进一步分解。由于单个通配符的限制,您不能使用模式规则执行此操作。使用$foreach。。。要生成一组显式规则,我需要迭代所有APP_NAME和相应的APP_ENV组合。例如,app1可以有prod、env1、env2,app2可以有stage、env3、env4环境。在上面的代码中,你会如何反应呢?我仍然在剖析你的回答
s可能遗漏了澄清的明显原因。我已经更新了我的答案谢谢!明天我将验证这一点,看看它如何适合我的环境!:忍不住插上上面的代码,稍加修改,使之与我的环境保持一致,并按预期工作。这太棒了!