使用gcc编译器时,它将一步链接和编译.但是,将源文件转换为目标文件然后在最后链接它们似乎是惯用的.对我来说,这似乎是不必要的.这不仅会使您的目录与一堆目标文件混乱,而且当您可以简单地将所有源文件添加到编译器时,它会使Makefile复杂化.例如,我认为这很简单:
.PHONY: all
SOURCES = $(wildcard *.cpp)
all: default
default:
g++ $(SOURCES) -o test
Run Code Online (Sandbox Code Playgroud)
整齐地成为:
g++ main.cpp test.cpp -o test
Run Code Online (Sandbox Code Playgroud)
但是,使用模式规则的更复杂的Makefile会使每个文件的输出混乱.例如:
.PHONY: all
SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
%.o: %.cpp
g++ -c -o $@ $<
all: default
default: $(OBJECTS)
g++ -o test $^
clean:
rm -rf *.o
g++ -c -o main.o main.cpp
g++ -c -o test.o test.cpp
g++ -o test main.o test.o
Run Code Online (Sandbox Code Playgroud)
对我来说,这似乎是不必要的复杂和容易出错.那么这种做法的原因是什么?
我不知道有什么方法可以在 GNU Make 中以编程方式定义目标。这怎么可能?
有时可以使用替代方法离开。然而,在 Makefile 中以编程方式定义目标的能力对于使用make. 在 FreeBSD 的构建系统或诸如BSD Owl 之类的Makefile 库中可以找到复杂生成规则的示例
shell 脚本和 Makefile 之间的主要区别是:
在 Makefile 中,程序的状态由命令行和文件系统给出,因此可以在作业中断后恢复作业。当然,这需要正确地编写 Makefile,但即使这相当困难,也比使用 shell 脚本实现类似的效果要容易得多。
在 Makefile 中,用建议或钩子装饰一个过程是非常容易的,而这在 shell 脚本中基本上是不可能的。
例如,一个非常简单且有用的模式如下:
build: pre-build
build: do-build
build: post-build
Run Code Online (Sandbox Code Playgroud)
这将build目标呈现为三个目标的组合,一个包含实际指令do-build,另外两个是钩子,在 之前和之后执行do-build。许多为 BSD Make 编写的构建系统都使用这种模式,顺便说一下,它允许以编程方式定义目标,以便可以批量编写:
.for _target in configure build test install
.if !target(${_target})
${_target}: pre-${_target}
${_target}: do-${_target}
${_target}: post-${_target}
.endif
.endfor
Run Code Online (Sandbox Code Playgroud)
.if/.endif块引入的条件使用户能够使用自己对 any 的定义${_target}。
GNU Make 的那个片段的翻译是什么?