我需要生成一些具有不同加载地址的目标文件。我还有一个调用objdump
的make目标来向我展示相应的反汇编。
code0:
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE0_RELOC) $@.S -o $@.o
objcopy -O binary $@.o --only-section=.text $@.bin
code1:
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE1_RELOC) $@.S -o $@.o
objcopy -O binary $@.o --only-section=.text $@.bin
dump: dump_code0 dump_code1
dump_code0: code0.bin
objdump $< -D > $<.decomp
dump_code1: code1.bin
objdump $< -D > $<.decomp
这会失败,因为code.bin
没有目标,但目标dump_code
取决于code.bin
存在。为了防止它混淆(即使用依赖code0
,然后生成code0.bin
)我认为创建一个%.bin
目标会更容易创建与之关联的相应二进制文件每个目标文件(因为在所有code*
目标中也存在此代码的重复。此目标将成为每个code*
目标的依赖项。但是,这需要(或至少我认为确实如此)需要动态分配依赖关系。我尝试过这样的东西不起作用:
%.bin: $(basename $@)
objcopy -O binary $(basename $@).o --only-section=.text $@.bin
code0: code0.bin
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE0_RELOC) $@.S -o $@.o
逻辑是,code0.bin
等依赖项会导致此目标以code0
的单一有效依赖关系执行,以首先构建目标文件。
我可能误解了%
字符如何用于通配符制作目标。 basename
的第一次使用是评估为空(第二次使用),因此目标没有依赖关系。在调用时对依赖关系树进行一次评估确实有意义,但我希望能够提供更具动态性的功能。
这可以在Make中完成吗?
答案 0 :(得分:1)
您正在寻找的可能是Static Pattern Rules,您可以使用它来重做您的第一次尝试:
code0:
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE0_RELOC) $@.S -o $@.o
objcopy -O binary $@.o --only-section=.text $@.bin
为:
code0.o code1.o: code%.o: code%.S
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE$*_RELOC) $< -o $@
code0.bin code1.bin: %.bin: %.o
objcopy -O binary $< --only-section=.text $@
看原理?第一个规则的配方中的$*
被静态模式规则的匹配词干(在我们的例子中为数字)所取代。这可行,但特定于模式的变量可能更容易理解和维护:
# Default code reloc option
CODE_RELOC := default_code_reloc_option
# code1-specific code reloc option, if different from default
code1.o: CODE_RELOC := code1_code_reloc_option
code0.o code1.o: %.o: %.S
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE_RELOC) $< -o $@
第一个makefile的最后一部分也可以使用静态模式规则和虚假目标。类似的东西:
.PHONY: dump dump_code0 dump_code1
dump: dump_code0 dump_code1
dump_code0 dump_code1: dump_%: %.bin.decomp
code0.bin.decomp code1.bin.decomp: %.bin.decomp: %.bin
objdump $< -D > $@
最后,我们可以使用更多制作技巧(发现源文件,模式替换)来进一步自动化:
CODES := $(wildcard *.S)
OBJS := $(patsubst %.S,%.o,$(CODES))
BINS := $(patsubst %.S,%.bin,$(CODES))
DECS := $(patsubst %.S,%.bin.decomp,$(CODES))
DUMPS := $(patsubst %.S,dump_%,$(CODES))
# Default code reloc option
CODE_RELOC := default_code_reloc_option
# code1-specific code reloc option, if different from default
code1.o: CODE_RELOC := code1_code_reloc_option
.PHONY: dump $(DUMPS)
dump: $(DUMPS)
$(DUMPS): dump_%: %.bin.decomp
$(DECS): %.bin.decomp: %.bin
objdump $< -D > $@
$(BINS): %.bin: %.o
objcopy -O binary $< --only-section=.text $@
$(OBJS): %.o: %.S
gcc -m32 $(CFLAGS) -Wl,$(LDFLAGS),-Ttext=$(CODE_RELOC) $< -o $@
.PHONY: clean
clean:
rm -f $(OBJS) $(BINS) $(DECS)
clean
目标是奖励礼物。
所有这一切都优于您尝试使用非真实文件的目标。在这里,文件依赖于其他文件,除了虚假目标,它们只是真实目标文件的一种简写。这100%符合make的理念:表达文件间依赖性,以便比较文件时间戳并决定什么是最新的以及必须重建的内容。当很多目标已经是最新的时,可以节省大量资金。
第二个优点是表达所有文件间依赖性是并行安全的。如果您使用以下命令在此makefile上运行make:
make -j 8
(假设您的计算机上有大约8个核心),您可以期望加速因子为8.如果您只有两个源文件,那就不多了,但如果您有数百个源文件则非常有趣......