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

mat*_*ule 3 makefile g++

我很难找到关于makefiles的任何信息,这是真正的初学者级别.即使是问题,这里的问题也是使用一些我不理解的符号来呈现的$(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
Run Code Online (Sandbox Code Playgroud)

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

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

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

bla*_*ost 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/*
Run Code Online (Sandbox Code Playgroud)

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

all: build/cpptest

.PHONY: all
Run Code Online (Sandbox Code Playgroud)

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

第三个目标:

build:
    @echo "building directory $@"
    mkdir -p $@
Run Code Online (Sandbox Code Playgroud)

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

 echo "building directory build"
 building directory build
Run Code Online (Sandbox Code Playgroud)

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

第四个目标:

build/cpptest: build/main.o | build
    @echo building $@
    g++ -o $@ $^
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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