我有一个头文件列表,我想使用 Makefile 一次性编译它们。但是,其中一些文件在汇编中具有外部定义的函数。如果是这种情况,则.s
目录中有一个同名(但扩展名为)的文件./asm
。例如,如果./r1.hpp
需要将汇编文件链接到其中,则也会有./asm/r1.s
。因此,我想出了以下 Makefile:
CXXFLAGS := @compile_flags.txt
SRC_FILE:= ./test.cpp
HDR_DIRS:= $(wildcard ./v[0-9]*)
.PHONY: help clean $(HDR_DIRS)
.DEFAULT_GOAL := help
help:
@echo "Please specify a target to run."
%.o: %.s
as $< -o $@
# rule 1
%.out: %.hpp ./asm/%.o $(SRC_FILE)
g++ $(CXXFLAGS) $(SRC_FILE) $(word 2, $^) -o $@ -I. -include $<
# rule 2
%.out: %.hpp $(SRC_FILE)
g++ $(CXXFLAGS) $(SRC_FILE) -o $@ -I. -include $<
$(HDR_DIRS): %:
$(MAKE) $(patsubst %.hpp,%.out,$(wildcard $@/r[0-9]*.hpp))
clean:
@if [ -z "$(DIR)" ]; then \
echo "Error: DIR is not specified. Please set DIR to the target directory."; \
exit 1; \
fi; \
echo "Cleaning files in $(DIR) ..."
@rm -f $(DIR)/*.out $(DIR)/asm/*.o
在这里,如果可能的话,我希望rule1
应用,rule2
如果没有相应的程序集文件(意味着该.s
文件不需要链接它)。但是,rule2
无论我尝试什么,总是被调用。我设法让它工作的唯一方法是将其更改.out
为rule1
,.obj
但我需要相同的扩展名才能进行进一步处理。我还希望将.s
文件作为依赖项进行跟踪,因为它们可以更改,然后需要重新编译文件。
我怎样才能实现这个目标?
注意:我也尝试过使用条件依赖性:
%.out: %.hpp $(wildcard $(patsubst %.hpp,%.s,$(dir $<)asm/$(notdir $<)))
@echo $(word 2, $^)
但是这个通配符总是扩展为空字符串,我不明白为什么。
版本为:
GNU Make 4.4.1.
这不会起作用:
因为 make 在解析 makefile 时会立即扩展先决条件列表中的函数和变量,但自动变量直到 make 决定需要重建目标并想要调用配方时才会设置。这意味着
$<
在调用函数时不会设置自动变量patsubst
,因此它会扩展为空字符串。如果您希望配方取决于
.s
文件,那么为什么不将其添加到模式规则中?如果您这样写,那么我认为它会起作用:如果您使用,它不起作用的原因
%.o
是,如果有多个模式“相等”匹配,make 总是选择需要最少工作量的模式。在您的示例中,规则 2 需要的工作较少,因为它不需要构建目标文件。如果您使用源文件,那么工作量相等,应该使用第一个匹配的配方。您可以
make
生成一个 makefile,该 makefile 明确覆盖适用于此情况的一般规则。但是,这可能是一个比解决这个问题所需的更大的工具。