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
设置为 obj
,MARCH
设置为 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
那么应该可以了。
我想将所有生成的.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
设置为 obj
,MARCH
设置为 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
那么应该可以了。