如何使用makefile将.o和.exe文件放在/ build /目录中

时间:2017-06-22 18:11:56

标签: makefile g++

我很难找到关于makefile的任何信息,这些信息是真正的初学者级别。即使是问题here,也会使用一些我不理解的符号来呈现,例如$(CC) $(INC) $< $(CFLAGS) -o $(BIN)$@ $(LIBS)。那让我失望了。

我的makefile如下所示:

cpptest: main.o
    g++ -o cpptest main.o

main.o: main.cpp
    g++ -c main.cpp

clean:
    rm cpptest main.o

这是我知道如何处理makefile的全部限制。它可以工作,但将main.o和cpptest.exe文件放入项目根目录。

我想将main.o文件和cpptest.exe文件放入/ build /目录。但是,如果我在每个main.o和每个cpptest之前放置./build/,则对象文件将出现在项目根目录中,并且exe文件根本不会出现。

我正在使用Windows上的Sublime Text 3来构建这个东西,这是值得的。

1 个答案:

答案 0 :(得分:5)

稍微好一点的解决方案如下:注意,我正在做一些时髦的事情,但我会在路上解释

all: build/cpptest

.PHONY: all

build:
    @echo "building directory $@"
    mkdir -p $@

build/cpptest: build/main.o | build
    @echo building $@
    g++ -o $@ $^

build/main.o: main.cpp | build
    @echo building $@
    g++ -o $@ -c $^

clean:
    @echo cleaning...
    rm -f build/*

好的,让我们看看第一个和第二个目标:

all: build/cpptest

.PHONY: all

我创建了一个名为all的默认目标。这是一个虚拟目标(它实际上并没有构建一个名为all的文件),因此我将all标记为虚假,使其成为.PHONY的依赖项。 (这基本上告诉make如果已经存在名为all的新文件,则不要忽略all规则。 all没有配方,因此除了导致其依赖关系被创建外,它不会做任何事情。这可能看起来有点复杂,但它是makefile中的标准做法,因为它使您可以按照您认为有用的任何顺序自由组织下面的规则。

第三个目标:

build:
    @echo "building directory $@"
    mkdir -p $@

对于第一个目标build,这是您正在创建的目录的名称。 build是目标,它没有依赖关系,并且有两个配方行。第一个配方行以@开头。这只是意味着在运行之前不要打印配方。如果您没有这个,您的输出将如下所示:

 echo "building directory build"
 building directory build

哪个很难看。 @只有在行的开头才会这样做。您会注意到后面的行$@。这是不同的。它是一个扩展为目标名称的变量(在本例中为build)。在适当的时候使用这个变量是一个好习惯,因为它将在以后简化更复杂的makefile。 build目标的第二个配方创建目录。

第四个目标:

build/cpptest: build/main.o | build
    @echo building $@
    g++ -o $@ $^

这表示build/cpptest依赖于build/main.obuild(即,在完成其他两个操作之前不要开始构建这些内容)。一个大空洞:注意|之前的build符号。这使它成为仅限订单的依赖项。这意味着如果build目录已存在且其时间戳比build/cpptest更新,则不要认为build/cpptest已过期(不重建它)。另一方面,另一个依赖项build/main.o位于|符号的左侧。这告诉make如果build/main.o不存在,或者如果它比build/cpptest更新,那么make应该重建build/cpptest

我们需要| build(仅限订单依赖项)的原因是每次添加新文件时都会更新目录的日期。因此,build将始终具有比build/cpptest更新的时间戳。这种情况属于高级makefile,但是这是正确的方法,所以我想我会在这里展示它。

正如@Felix指出的那样,在所有版本的make中都没有order-only(GNU make确实支持它)。

对于食谱,我使用了$@变量和$^变量。 $^表示所有非顺序依赖项(在这种情况下为main.cpp)。这些在规则运行之前进行了扩展。

你可以更进一步,使它真正正确(例如定义一个$(objs)变量等),这使得makefile在将来更容易维护,但这有望为你提供一个良好的开端