如何在Makefile中编写生成可执行文件的通用规则?
Makefile通用可执行编译模式问题排查与解决
问题背景
原Makefile包含重复的编译规则:
test_variance : test_variance.o $(CPP) -o test_variance.exe $(CFLAGS) test_variance.o $(LIBDIR) $(LIBS) test_variance_incremental: test_variance_incremental.o $(CPP) -o test_variance_incremental.exe $(CFLAGS) test_variance_incremental.o $(LIBDIR) $(LIBS) test_hyper: test_hyper.o $(CPP) -o test_hyper.exe $(CFLAGS) test_hyper.o $(LIBDIR) $(LIBS) test_hyper.o: test_hyper.cpp $(CPP) $(CFLAGS) $(INCLUDES) -c test_hyper.cpp test_variance_incremental.o: test_variance_incremental.cpp $(CPP) $(CFLAGS) $(INCLUDES) -c test_variance_incremental.cpp test_variance.o : test_variance.cpp $(CPP) $(CFLAGS) $(INCLUDES) -c test_variance.cpp
已用模式规则简化目标文件编译:
%.o: %.cpp $(CPP) $(CFLAGS) $(INCLUDES) -c $<
尝试用以下写法简化可执行文件编译,但Make提示“没有输入文件”:
TARGETS = test_variance test_variance_incremental test_hyper $(TARGETS): $@.o $(CPP) -o $@.exe $^ $(CFLAGS) $(LIBDIR) $(LIBS)
错误原因
$@是自动变量,仅在规则的命令部分有效,不能用在依赖列表中。Make解析依赖时,$@还未被替换为具体目标名,导致依赖被识别为无效的$@.o,找不到对应的输入文件。
解决方法
方法1:使用静态模式规则
静态模式规则可以为一组目标指定统一的依赖和命令,适合你的场景:
TARGETS = test_variance test_variance_incremental test_hyper $(TARGETS): %: %.o $(CPP) -o $@.exe $^ $(CFLAGS) $(LIBDIR) $(LIBS)
%是通配符,匹配TARGETS中的每个目标,自动关联对应的%.o依赖- 命令部分的
$@会被替换为当前目标名,$^代表所有依赖(即对应的.o文件)
方法2:直接为可执行文件写模式规则(可选)
如果你的可执行文件命名规则是%.exe对应%.o,也可以直接写模式规则,无需单独定义TARGETS:
%.exe: %.o $(CPP) -o $@ $^ $(CFLAGS) $(LIBDIR) $(LIBS)
之后执行make test_variance.exe、make test_hyper.exe即可编译对应的可执行文件,或者搭配all: $(addsuffix .exe, $(TARGETS))实现批量编译。
内容的提问来源于stack exchange,提问作者sicheng mao
相关产品推荐
相关产品推荐

