我有一个尝试执行以下操作的makefile:使用.c和.s扩展名识别当前目录下的所有文件(包括所有子目录),为每个文件编译一个非链接的目标文件并将其放入进入目录。所有C文件最终都在objects / c中,所有汇编文件最终都在objects / ass中。
makefile在第一次执行时始终按预期工作(所有命令都按正确的顺序调用),并且不会产生错误。
然而,如果我再次打电话给make,有一半时间我会“为'全部'做点什么。”这是您所期望的,因为没有文件被修改过。但另一半时间,make是选择一个随机的汇编文件并编译该文件。也就是说,如果我继续做“make”,我有时会编译file1.s有时是file2.s。并且它在组装文件之间随机交换添加无限(它永远不会达到“无所事事”)状态。
如何展示非确定性行为?
这是我可以制作的最小的makefile,它可以重现错误:
SRC_C = $(wildcard *.c) $(wildcard **/*.c)
SRC_ASS = $(wildcard *.s) $(wildcard **/*.s)
OBJECTS_C = $(addprefix $(OBJECT_DIR)c/, $(notdir $(SRC_C:.c=.o)))
OBJECTS_ASS = $(addprefix $(OBJECT_DIR)ass/, $(notdir $(SRC_ASS:.s=.o)))
OBJECTS = $(OBJECTS_C) $(OBJECTS_ASS)
OBJECT_DIR = objects/
all: $(OBJECTS)
%/:
mkdir $@
$(OBJECTS_C): $(OBJECT_DIR) $(OBJECT_DIR)c/
arm-none-eabi-gcc -O0 -march=armv8-a $(wildcard */$(@F:.o=.c)) -nostartfiles -c -o $@
$(OBJECTS_ASS): $(OBJECT_DIR) $(OBJECT_DIR)ass/
arm-none-eabi-as -march=armv8-a $(wildcard */$(@F:.o=.s)) -c -o $@
.PHONY: clean
clean:
rm -rf $(OBJECT_DIR)
答案 0 :(得分:3)
这里有很多错误。
最大的概念是:通过将所有目标文件展平到一个目录中,无法使用模式规则表达正确的依赖关系,因此您的目标文件并不真正依赖于它们各自的源文件。我要说:不要那样做!拥有对象目录很好,但它们应该镜像源树的目录结构。
进一步的错误:
find
而不是文体改进:
:=
?=
分配影响构建过程的变量,以便用户可以在命令行覆盖它们CC
,AS
,CROSS_COMPILE
.PHONY
。应用了这些更改的Makefile如下所示:
OBJECT_DIR ?= objects
C_OBJECT_DIR ?= $(OBJECT_DIR)/c
AS_OBJECT_DIR ?= $(OBJECT_DIR)/ass
SRC_C:= $(shell find -name \*.c)
SRC_ASS:= $(shell find -name \*.s)
OBJECTS_C:= $(addprefix $(C_OBJECT_DIR)/, $(SRC_C:.c=.o))
OBJECTS_ASS:= $(addprefix $(AS_OBJECT_DIR)/, $(SRC_ASS:.s=.o))
OBJECTS:= $(OBJECTS_C) $(OBJECTS_ASS)
OUTDIRS:= $(sort $(dir $(OBJECTS)))
CROSS_COMPILE ?= arm-none-eabi-
CC ?= gcc
AS ?= as
CFLAGS ?= -O0 -march=armv8-a -nostartfiles
ASFLAGS ?= -march=armv8-a
all: $(OBJECTS)
$(OUTDIRS):
$(foreach _dir,$@,mkdir -p $(_dir);)
$(C_OBJECT_DIR)/%.o: %.c | $(OUTDIRS)
$(CROSS_COMPILE)$(CC) -c -o $@ $(CFLAGS) $<
$(AS_OBJECT_DIR)/%.o: %.s | $(OUTDIRS)
$(CROSS_COMPILE)$(AS) -c -o $@ $(ASFLAGS) $<
clean:
rm -rf $(OBJECT_DIR)
.PHONY: all clean
请注意,缺少一件重要的事情:自动依赖。使用此Makefile,每个目标文件都依赖于其各自的源文件,但完全错过了包含的任何头文件。对于除了简单玩具之外的任何东西,你应该补充一点,google for&#34; gnu make gcc automatic dependencies&#34;或类似的东西(不是此问题的范围)。