如何在Makefile中指定多目标?GNU Make 4.3使用问题求助
我来帮你拆解下问题所在,以及对应的解决办法~
首先,你遇到的问题和用的&:语法直接相关——这是GNU Make 4.3新增的**联合目标(Joined Targets)**特性,它的设计逻辑是:把多个目标绑定成一个整体,只要这个整体里有任意一个目标的修改时间晚于依赖文件,make就会认为整个目标组都已经是最新状态,不会执行规则。这就是为什么你删除sayhello.s后,因为hellomain.s还存在且比源文件新,make就直接返回“up to date”了。
解决方案
根据你的需求(缺失哪个汇编文件就重建哪个,或者只要有缺失就都重建),这里提供几种可行的方案:
1. 为每个目标写独立规则(最直观)
把两个汇编文件的生成规则分开,让它们各自对应自己的源文件,这样make会单独检查每个目标的状态:
src_prefix = ../../src/hello/ hellomain.s: $(src_prefix)hellomain.c gcc -S $< -o $@ sayhello.s: $(src_prefix)sayhello.c gcc -S $< -o $@ .PHONY: clean clean : -rm hellomain.s sayhello.s
这里用了Make的自动变量:$<代表规则中的第一个依赖文件,$@代表当前目标文件,让规则更简洁通用。
2. 使用普通多目标规则(适合需要同时生成两个文件的场景)
如果你希望只要有一个目标缺失或者源文件更新,就重新生成两个汇编文件,可以去掉&:,用普通的多目标规则:
src_prefix = ../../src/hello/ hellomain.s sayhello.s: $(src_prefix)hellomain.c $(src_prefix)sayhello.c gcc -S $(src_prefix)hellomain.c -o hellomain.s gcc -S $(src_prefix)sayhello.c -o sayhello.s .PHONY: clean clean : -rm hellomain.s sayhello.s
这种情况下,只要两个目标中有一个需要更新(比如缺失或者源文件修改了),make就会执行一次命令,同时生成两个文件。
3. 使用模式规则(最优雅的通用方案)
如果你的源文件和目标文件命名有规律(比如.c文件对应同名的.s文件),模式规则会是最灵活的选择:
src_prefix = ../../src/hello/ %.s: $(src_prefix)%.c gcc -S $< -o $@ .PHONY: clean clean : -rm hellomain.s sayhello.s
这个规则会自动匹配所有.s目标,找到对应的src_prefix下的.c源文件,哪个目标缺失就重建哪个,后续新增类似的目标也不需要修改规则。
补充说明
联合目标(&:)并不是错误的语法,但它的适用场景是多个目标必须同时生成,且只要有一个存在且最新就不需要重新构建的情况(比如编译生成可执行文件和对应的调试符号文件),显然和你当前的需求不匹配。
内容的提问来源于stack exchange,提问作者cmpltrtok

