Makefile:I 更改了objs的目录,但每次都会编译所有文件

Makefile:I changed the directory of objs ,but all the files are compiled everytime

我想将所有生成的.o文件保存在文件夹$(BUILD_DIR).

虽然我没有编辑任何苍蝇,但所有的src文件都会重新编译。

感谢@JohnBollinger 的建议。我创建了一个新项目来测试这个问题。

我的测试项目目录树:

/test
   /app
      main.c
      Makefile
   /build_dir
      Makefile
   /bin
   Makefile


这是我的顶级 Makefile


TOPDIR := $(PWD)
CROSS_COMPILE :=


AS      = $(CROSS_COMPILE)as
LD      = $(CROSS_COMPILE)ld
CC      = $(CROSS_COMPILE)gcc
CPP     = $(CC) -E
AR      = $(CROSS_COMPILE)ar
NM      = $(CROSS_COMPILE)nm
STRIP       = $(CROSS_COMPILE)strip
OBJCOPY     = $(CROSS_COMPILE)objcopy
OBJDUMP     = $(CROSS_COMPILE)objdump

MARCH :=x86

SZ = $(CROSS_COMPILE)size

OPT = -O0
CFLAGS+= $(C_INCLUDES)
CFLAGS+= -g -gdwarf-2
CFLAGS+= $(OPT)

TARGET = test-$(MARCH)
BUILD_DIR = $(TOPDIR)/build_dir
BIN_DIR = $(TOPDIR)/bin


SUBDIRS = $(TOPDIR)/app \

export  CC CPP LD MARCH CFLAGS LDFLAGS TARGET CROSS_COMPILE
export BUILD_DIR BIN_DIR TOPDIR LINK_SCRIPT
export CPU ARCH MARCH BOARD

ALL:$(SUBDIRS)
    $(OBJCOPY) -O binary -S $(BIN_DIR)/$(TARGET).elf $(BIN_DIR)/$(TARGET).bin
    @echo  "3[32mbuild success 3[0m"




$(SUBDIRS):ECHO
    @make clean
    @-mkdir -p bin
    @for dir in $(SUBDIRS); do \
    echo -------------------compiling $$dir ------------------;\
    make -C $$dir || exit "$$?";\
    done
    @make -C $(BUILD_DIR)


ECHO:

.PHONY : clean ALL
clean:
    -rm $(BUILD_DIR)/*.o 
    -rm $(BIN_DIR)/*

这是我在应用程序目录中的 Makefile:

objs += $(BUILD_DIR)/main.o

all:$(objs)

$(BUILD_DIR)/%.o:%.c
    $(CC) $(CFLAGS) -c -o $@ $< -MD -MF $@.d

.PHONY: all

我试过 make -d,发现:

 Considering target file '/home/alan/Desktop/test/build_dir/main.o'.
   File '/home/alan/Desktop/test/build_dir/main.o' does not exist.
   ...
   No need to remake target 'main.c'.
   Finished prerequisites of target file '/home/alan/Desktop/test/build_dir/main.o'.
  Must remake target '/home/alan/Desktop/test/build_dir/main.o'.

实际上:

alan@alan-PC:~/Desktop/test/build_dir$ ls
main.o  main.o.d  Makefile

main.o存在!

为什么make认为它不存在?

要理解make 问题,通常只需要注意make 是运行ning 的命令即可。如果不正确,请找出原因。

你的问题就在这里:

$(SUBDIRS):ECHO
        @make clean
        ...

所以你对每个子目录做的第一件事就是运行 make clean。这当然会删除所有目标文件:

clean:
        -rm $(BUILD_DIR)/*.o 
        -rm $(BIN_DIR)/*

所以 make 当然必须重建它们。如果您检查 make 打印的输出,您会看到这些删除所有目标文件的命令,并且您会知道为什么 make 总是重建所有目标文件。

另请注意,您应该永远不要 调用带有文字字符串make 的sub-make。您应该始终使用变量 $(MAKE)(如果您愿意,也可以使用 ${MAKE}:同样的事情)。

旧答案

这个:

SOURCES  =$(wildcard *.c) 
objs += $(patsubst %.c,$(BUILD_DIR)/$(MARCH)-%.o,$(SOURCES))

假设 BUILD_DIR 设置为 objMARCH 设置为 x86_64。假设有一个文件 foo.c。我们得到这个:

SOURCES = foo.c
objs = obj/x86_64-foo.o

现在您已经定义了这条规则:

all: obj/x86_64-foo.o

obj/%.o:%.c
        $(CC) $(CFLAGS) -c -o $@ $< -MD -MF $@.d

这是行不通的,因为目标和先决条件中的 % 必须相同。在这里,目标的 %x86_64-foo 匹配,因此此规则仅在文件 x86_64-foo.c 存在时匹配,据推测它不存在。

除了“不知道如何构建目标 obj/x86_64-foo.o”之外,我实际上并不知道你是如何从这个 makefile 中得到任何东西的给你。

如果您改为这样编写规则:

$(BUILD_DIR)/$(MARCH)-%.o : %.c
        $(CC) $(CFLAGS) -c -o $@ $< -MD -MF $@.d

那么应该可以了。