用 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 的詳細解答