动态目标与依赖场景下的GNU Makefile编写问题求助
解决GNU Make中目标专属变量的依赖解析问题
基础需求解决方案
你的问题核心在于Makefile的变量展开时机:普通变量在Make读取Makefile时就会展开,而目标专属变量(如tgt_d : CONFIG = Debug)只有在处理对应目标时才会生效。之前的写法中,${MAKEFILE_DIR}在读取阶段就被展开为空,导致依赖变成build_dir//makefile。
要解决这个问题,需要结合.SECONDEXPANSION和延迟展开语法(用$$代替$),让依赖中的变量在目标上下文里才展开:
.SECONDEXPANSION: # 为每个目标绑定专属配置 tgt_d : CONFIG = Debug tgt_r : CONFIG = Release # 定义目标专属的Makefile目录 tgt_d tgt_r : MAKEFILE_DIR = build_dir/$$(CONFIG) # 二次展开后,依赖中的$$(MAKEFILE_DIR)会替换为目标的专属变量值 tgt_d tgt_r : use_make-$$(CONFIG) # 为不同配置定义独立的use_make目标 use_make-% : build_dir/%/makefile @echo "local makefile using $$(ls -l $<)" # 生成对应配置的Makefile build_dir/%/makefile : @mkdir -p $$(dir $@) @echo "create makefile for $* config" > $@
运行验证:
make tgt_d
会生成build_dir/Debug/makefile,并正确输出对应文件的信息。
扩展到多目标(支持多个项目)
如果要支持多个协同构建的项目(比如Eclipse多项目),可以用模式规则结合自动变量来通用化:
.SECONDEXPANSION: # 定义所有项目和配置组合 PROJECTS := core utils ui CONFIGS := Debug Release # 生成所有目标:<project>-<config> ALL_TARGETS := $(foreach proj,$(PROJECTS),$(foreach cfg,$(CONFIGS),$(proj)-$(cfg))) # 默认目标 all : $(ALL_TARGETS) # 为每个目标绑定项目和配置信息 $(PROJECTS)-% : PROJECT = $$(firstword $$(subst -, ,$$@)) $(PROJECTS)-% : CONFIG = $$(lastword $$(subst -, ,$$@)) # 每个项目-配置目标依赖对应的use_make目标 $(PROJECTS)-% : use_make-$$(PROJECT)-$$(CONFIG) # 通用的use_make目标,依赖项目+配置的Makefile use_make-% : build_dir/$$(subst use_make-,,$$@)/makefile @echo "Building project $$(firstword $$(subst -, ,$$*)) with $$(lastword $$(subst -, ,$$*)) config using $<" # 通用生成Makefile规则,支持任意项目和配置 build_dir/%/makefile : @mkdir -p $$(dir $@) @echo "Project: $$(firstword $$(subst /, ,$$*))" > $@ @echo "Config: $$(lastword $$(subst /, ,$$*))" >> $@ @echo "Generated Makefile content" >> $@
说明:
ALL_TARGETS自动生成所有项目+配置的组合目标(比如core-Debug、ui-Release)- 用
subst和firstword/lastword从目标名中提取项目和配置信息 $<自动引用依赖的Makefile路径,%匹配模式中的通配部分,实现完全通用化- 运行
make core-Debug会生成build_dir/core/Debug/makefile并执行构建逻辑
内容的提问来源于stack exchange,提问作者Yonatan.Lehman
相关产品推荐
相关产品推荐

