能否使用Makefile的define定义目标及编译规则实现跨文件复用?
问题原因
你遇到的问题是变量展开时机不对导致的:
你直接在子Makefile中写$(CC_OBJ_COMPILE)时,Make会在解析这行代码的瞬间就把CC_OBJ_COMPILE变量内部的内容全部展开,此时还没有匹配到任何编译规则,$@、$<这类仅在规则上下文才会赋值的自动变量自然是空值。
修复方案
你只需要调整两处配置即可实现规则复用:
- 公共Makefile调整
保持依赖相关变量和规则模板的定义即可,如果你的Make版本较低,建议去掉define后面的=,老版本Make不支持该语法:
# automatic prerequisite generation DEPFLAGS = -MT "$@" -MMD -MP -MF "$(@:.o=.d)" CC_WRITE_DEP = $(CC) $(CFLAGS) -c "$<" -o "$@" $(DEPFLAGS) CXX_WRITE_DEP = $(CXX) $(CXXFLAGS) -c "$<" -o "$@" $(DEPFLAGS) define CC_OBJ_COMPILE %.o: %.c $(CC_WRITE_DEP) endef define CXX_OBJ_COMPILE %.o: %.cpp $(CXX_WRITE_DEP) endef
- 子目录Makefile调整
不要直接展开规则模板变量,而是用eval函数将模板内容作为Makefile语法重新解析:
# common compile options common := common/Makefile -include $(common) # 用eval解析规则模板 $(eval $(CC_OBJ_COMPILE)) $(eval $(CXX_OBJ_COMPILE)) # automatic dependency tracking deps = $(objs:.o=.d) -include $(deps)
原理说明
eval函数会把传入的字符串内容当作完整的Makefile代码重新执行解析,这时候定义的模式规则会被正确识别,规则内命令中的变量会延迟到规则实际匹配执行时才展开,就能正常获取到$@、$<等自动变量的值了。
内容的提问来源于stack exchange,提问作者seasia
相关产品推荐
相关产品推荐

