MAKE:编译所有文件一次AND生成目标文件到不同的目录

时间:2015-11-19 13:38:52

标签: c gcc makefile

我有一个项目,其中包含许多不同文件夹位置的源文件。出于某种原因,我的Makefile可以执行以下操作之一,但不能同时执行以下操作(这是我真正想要的): -

1)将所有文件编译到一个单独的目录

2)执行编译ONCE,gcc只需要调用一次,因为这会显着缩短编译时间。

这是一个可以实现选项1的代码片段: -

INCLDDIRS := "The needed include directories"
CFLAGS = "some c flags"
C_SOURCE = "Many many source files in different directories"
C_SOURCE_NAMES = $(notdir $(C_SOURCE))
OBJECT_DIRECTORY = ObjDir
C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_NAMES:.c=.o) )

all: $(OBJECT_DIRECTORY) $(C_OBJECTS)

$(OBJECT_DIRECTORY):
    mkdir ObjDir

$(OBJECT_DIRECTORY)/%.o:%.c
    $(CC) $(CFLAGS) $(INCLDDIRS) -c -o $@ $<

由于某种原因,上面分别编译每个c源文件并生成一个目标文件(即为所有源文件调用gcc)。这不是我想要的。但是,至少所有生成的文件都位于ObjDir

这是用于实现选项2的代码片段: -

INCLDDIRS := "The needed iclude directories"
CFLAGS = "some c flags"
C_SOURCE = "Many many source files in different directories"
C_SOURCE_NAMES = $(notdir $(C_SOURCE))
OBJECT_DIRECTORY = ObjDir
C_OBJECTS = $(OBJECT_DIRECTORY)/*.o

all: $(OBJECT_DIRECTORY) $(C_OBJECTS)

$(OBJECT_DIRECTORY):
    mkdir ObjDir

$(C_OBJECTS): (C_SOURCE)
    $(CC) $(CFLAGS) $(INCLDDIRS) -c $(C_SOURCE)

对于上面的代码片段,所有文件都编译一次(即gcc只调用一次),但目标文件生成在与Makefile相同的位置,而不是生成单独的目录。我不想在文件生成后将文件复制,因为这不是更清晰的解决方案。

我的问题是: 我需要对Makefile做什么才能进行一次编译,并将目标文件生成到一个单独的目录中?

1 个答案:

答案 0 :(得分:3)

你想要的makefile看起来像这样。

INCLDDIRS := "The needed include directories"
CFLAGS = "some c flags"
C_SOURCE = "Many many source files in different directories"
C_SOURCE_NAMES = $(notdir $(C_SOURCE))
OBJECT_DIRECTORY = ObjDir
BINARY := your_binary

all: $(BINARY)

$(OBJECT_DIRECTORY):
        mkdir $@

$(OBJECT_DIRECTORY/$(BINARY): $(C_SOURCE) | $(OBJECT_DIRECTORY)
        $(CC) $(CFLAGS) $(INCLDDIRS) -o $@ $^

它使用order-only prerequisite作为输出目录(因此make知道首先创建它但不将其视为导致重建)。

它将源文件列为输出二进制文件的先决条件,并在编译行中全部使用它们。

此makefile的主要问题是,对任何源文件的更改将导致每个源文件从头开始重新编译。就增量工作而言,这是相当低效的。 (这就是为什么默认的想法是使用中间对象文件。你可以用一些从清洁速度到增量速度的交换。)

第二个makefile无法正常工作的原因是,在一个干净的目录中,C_OBJECTS变量没有值。您的通配符$(OBJECT_DIRECTORY)/*.o不匹配任何内容。

那说它也是不正确的,因为它列出了每个源文件作为每个目标文件的先决条件,这完全没有问题。