用 GNU make 编译

介绍

GNU Make(样式为 make)是一个专门用于执行 shell 命令自动化的程序。GNU Make 是属于 Make 系列的一个特定程序。在类 Unix 和类似 POSIX 的操作系统中仍然很受欢迎,包括那些源自 Linux 内核,Mac OS X 和 BSD 的操作系统。

GNU Make 特别值得注意的是附加到 GNU 项目,GNU 项目附加到流行的 GNU / Linux 操作系统。GNU Make 还具有在各种版本的 Windows 和 Mac OS X 上运行的兼容版本。它也是一个非常稳定的版本,具有历史意义,仍然很受欢迎。出于这些原因,GNU Make 经常与 C 和 C++一起教授。

基本规则

要使用 make 进行编译,请在项目目录中创建 Makefile。你的 Makefile 可以像下面这样简单:

Makefile 文件

# Set some variables to use in our command
# First, we set the compiler to be g++
CXX=g++

# Then, we say that we want to compile with g++'s recommended warnings and some extra ones.
CXXFLAGS=-Wall -Wextra -pedantic

# This will be the output file
EXE=app

SRCS=main.cpp

# When you call `make` at the command line, this "target" is called.
# The $(EXE) at the right says that the `all` target depends on the `$(EXE)` target.
# $(EXE) expands to be the content of the EXE variable
# Note: Because this is the first target, it becomes the default target if `make` is called without target
all: $(EXE)

# This is equivalent to saying
# app: $(SRCS)
# $(SRCS) can be separated, which means that this target would depend on each file.
# Note that this target has a "method body": the part indented by a tab (not four spaces).
# When we build this target, make will execute the command, which is:
# g++ -Wall -Wextra -pedantic -o app main.cpp
# I.E. Compile main.cpp with warnings, and output to the file ./app
$(EXE): $(SRCS)
    @$(CXX) $(CXXFLAGS) -o $@ $(SRCS)

# This target should reverse the `all` target. If you call
# make with an argument, like `make clean`, the corresponding target
# gets called.
clean:
    @rm -f $(EXE)

注意:确保压痕带有标签,而不是四个空格。否则,你会收到 Makefile:10: *** missing separator. Stop. 的错误

要从命令行运行此命令,请执行以下操作:

$ cd ~/Path/to/project
$ make
$ ls
app  main.cpp  Makefile

$ ./app
Hello World!

$ make clean
$ ls
main.cpp  Makefile

增量构建

当你开始拥有更多文件时,make 会变得更有用。如果你编辑了 a.cpp 而不是 b.cpp 怎么?重新编译 b.cpp 会花费更多时间。

使用以下目录结构:

.
+-- src
|   +-- a.cpp
|   +-- a.hpp
|   +-- b.cpp
|   +-- b.hpp
+-- Makefile

这将是一个很好的 Makefile:

Makefile 文件

CXX=g++
CXXFLAGS=-Wall -Wextra -pedantic
EXE=app

SRCS_GLOB=src/*.cpp
SRCS=$(wildcard $(SRCS_GLOB))
OBJS=$(SRCS:.cpp=.o)

all: $(EXE)

$(EXE): $(OBJS)
    @$(CXX) -o $@ $(OBJS)

depend: .depend

.depend: $(SRCS)
    @-rm -f ./.depend
    @$(CXX) $(CXXFLAGS) -MM $^>>./.depend

clean:
    -rm -f $(EXE)
    -rm $(OBJS)
    -rm *~
    -rm .depend

include .depend

再看一下标签。这个新的 Makefile 确保你只重新编译已更改的文件,从而最大限度地缩短编译时间。

文档

有关 make 的更多信息,请参阅自由软件基金会的官方文档stackoverflow 文档dmckee 关于 stackoverflow 的详细解答