2017-05-25 41 views
1

我有一个正在尝试执行以下操作的生成文件:使用.c和.s扩展名标识当前目录(包括所有子目录)下的所有文件,为每个文件编译非链接对象文件并将其放入一个目录。所有的C文件都以对象/ c结尾,所有的程序集文件都以对象/驴结尾。为什么makefile表现出非确定性行为?

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 [email protected] 

$(OBJECTS_C): $(OBJECT_DIR) $(OBJECT_DIR)c/ 
    arm-none-eabi-gcc -O0 -march=armv8-a $(wildcard */$(@F:.o=.c)) -nostartfiles -c -o [email protected] 

$(OBJECTS_ASS): $(OBJECT_DIR) $(OBJECT_DIR)ass/ 
    arm-none-eabi-as -march=armv8-a $(wildcard */$(@F:.o=.s)) -c -o [email protected] 

.PHONY: clean 
clean: 
    rm -rf $(OBJECT_DIR) 
+0

使用'--trace'开关(假设为GNU make)让'make'显示其逻辑以决定是否重建 –

+0

如果您遇到问题,请尝试生成一个实际显示问题的最小生成文件 –

+0

根据跟踪,第一次成功编译后再次编译的原因是由于目录对象? – Makogan

回答

3

您在这里有许多错误。

最大的是概念性的:通过将所有目标文件压扁成一个目录,使用模式规则无法表达适当的依赖关系,因此目标文件并不依赖于它们各自的源文件。我会说:不要那样做!拥有对象目录很好,但它们应该镜像源代码树的目录结构。

而且错误:

  • 直接取决于目录。这不会按预期工作,如目录中所述,目录应始终为仅订单相关性
  • Make不支持递归通配符 - 如果您真的需要它,可以编写自己的函数,或者假设您总是建立在* nix上,只需拨打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,[email protected],mkdir -p $(_dir);) 

$(C_OBJECT_DIR)/%.o: %.c | $(OUTDIRS) 
    $(CROSS_COMPILE)$(CC) -c -o [email protected] $(CFLAGS) $< 

$(AS_OBJECT_DIR)/%.o: %.s | $(OUTDIRS) 
    $(CROSS_COMPILE)$(AS) -c -o [email protected] $(ASFLAGS) $< 

clean: 
    rm -rf $(OBJECT_DIR) 

.PHONY: all clean 

注意,缺少一个重要的事情:自动依赖。使用这个Makefile,每个目标文件都依赖于它的源文件,但是完全没有包含任何头文件。除了一个简单的玩具之外,你应该补充说,谷歌的“GNU make gcc自动依赖”或类似的东西(不是这个问题的范围)。

相关问题