構(gòu)建系統(tǒng)(build system)是用來從源代碼生成用戶可以使用的目標(biāo)(targets)的自動(dòng)化工具,目標(biāo)可以包括庫、可執(zhí)行文件、或者生成的腳本等等。
當(dāng)前主流的編譯基礎(chǔ)工具是makefile,當(dāng)時(shí)makefile有缺點(diǎn):
- 大型工程手寫makefile費(fèi)事費(fèi)力
- makefile隱式規(guī)則影響構(gòu)建效率
所以,又出現(xiàn)了很多新的構(gòu)建工具來解決這兩個(gè)問題,如
CMake, XMake, qmake, Scons, Ninja, Meson, Bazel等等。
這些構(gòu)建工具的使用,我們舉例并使用下。
代碼見 https://gitee.com/style7en/build-system。
假設(shè)我們的目錄如下,main.c需要使用hello.c中的函數(shù)hello():
app/
├── hello
│ ├── hello.c
│ └── hello.h
└── main.c
其中,hello.c內(nèi)容為
#include <stdio.h>
int hello(void)
{
printf("hello, world!\n");
return 0;
}
hello.h內(nèi)容為
#ifndef HELLO_H_
#define HELLO_H_
int hello(void);
#endif
main.c內(nèi)容為
#include "hello.h"
int main(void)
{
hello();
return 0;
}
Shell
如果不用任何構(gòu)建工具,直接使用最原始的構(gòu)建腳本,內(nèi)容如下,執(zhí)行如下腳本,會(huì)在當(dāng)前目錄生成可執(zhí)行程序app
#!/bin/bash
gcc -c main.c -I hello
gcc -c hello/hello.c
gcc main.o hello.o -o app
Makefile
一個(gè)工程中的源文件不計(jì)其數(shù),其按類型、功能、模塊分別放在若干個(gè)目錄中,makefile定義了一系列的規(guī)則來指定哪些文件需要先編譯,哪些文件需要后編譯,哪些文件需要重新編譯,甚至于進(jìn)行更復(fù)雜的功能操作,因?yàn)?makefile就像一個(gè)Shell腳本一樣,也可以執(zhí)行操作系統(tǒng)的命令。
上述工程的makefile文件如下,使用make命令執(zhí)行,會(huì)在當(dāng)前目錄生成可執(zhí)行程序app
app: main.o hello.o
gcc main.o hello.o -o app
main.o: main.c
gcc -c main.c -I hello
hello.o: hello/hello.c
gcc -c hello/hello.c
clean:
rm -rf main.o hello.o app
或者進(jìn)階版
TARGET = app
SRCS = main.c hello/hello.c
INC = -Ihello
OJBS = $(SRCS:.c=.o)
$(TARGET): $(OJBS)
echo $(OJBS)
$(CC) -o $@ $^
%.o: %.c
$(CC) $(INC) -o $@ -c $<
clean:
rm -rf $(TARGET) $(OJBS)
CMake
CMake是一個(gè)跨平臺(tái)的安裝(編譯)工具,可以用簡(jiǎn)單的語句來描述所有平臺(tái)的安裝(編譯過程)。他能夠輸出各種各樣的makefile或者project文件,能測(cè)試編譯器所支持的C++特性,類似UNIX下的automake。 CMake 的組態(tài)檔取名為 CMakeLists.txt,Cmake 并不直接建構(gòu)出最終的軟件,而是產(chǎn)生標(biāo)準(zhǔn)的建構(gòu)檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建構(gòu)方式使用。
如下為當(dāng)前目錄下CMakeLists.txt文件內(nèi)容
cmake_minimum_required(VERSION 2.8)
project(app)
set(hello hello/hello.c hello/hello.h)
include_directories(hello)
add_executable(app main.c ${hello})
執(zhí)行命令
mkdir build && cd build
cmake .. # 在build目錄下生成makefile
make # 在build目錄生成可執(zhí)行程序app
以上是老版本CMake的寫法,CMake 3.xx版本增加了模塊化target的寫法,推薦使用。
XMake
XMake 是一個(gè)基于 Lua 的輕量級(jí)跨平臺(tái)構(gòu)建工具,使用 xmake.lua 維護(hù)項(xiàng)目構(gòu)建,相比 makefile/cmake,配置語法更加簡(jiǎn)潔直觀,對(duì)新手非常友好,短時(shí)間內(nèi)就能快速入門,能夠讓用戶把更多的精力集中在實(shí)際的項(xiàng)目開發(fā)上。
xmake.lua可通過xmake命令生成,更加靈活的配置修要手動(dòng)修改,內(nèi)容如下
target("app")
set_kind("binary")
add_files("main.c")
add_files("hello/hello.c")
add_includedirs("hello")
有了xmake.lua后,執(zhí)行命令
xmake # 編譯
xmake run app # 運(yùn)行
xmake run -d app # gdb調(diào)試
Scons
Scons是一個(gè)開放源碼、以Python語言編碼的自動(dòng)化構(gòu)建工具,可用來替代make編寫復(fù)雜的makefile。并且scons是跨平臺(tái)的,只要
Scons腳本寫的好,可以在Linux和Windows下隨意編譯。
SCons 的設(shè)計(jì)目標(biāo)就是讓開發(fā)人員更容易、更可靠和更快速的建造軟件。
上述工程,需要在工程目錄創(chuàng)建一個(gè)SConstruct文件,內(nèi)容如下
Program(
target = "app",
source = ["main.c", "hello/hello.c"],
CPPPATH = ["hello"]
)
然后在命令行執(zhí)行
scons # 編譯
scons -c # 清除編譯結(jié)果
Ninja
Ninja 是Google的一名程序員推出的注重速度的構(gòu)建工具,一般在Unix/Linux上的程序通過make/makefile來構(gòu)建編譯,而Ninja通過將編譯任務(wù)并行組織,大大提高了構(gòu)建速度,Ninja的定位非常清晰,就是達(dá)到更快的構(gòu)建速度。
如上工程,ninja編譯需要build.ninja文件。如果有CMakeLists.txt,可通過 cmake -G Ninja 生成,沒有的話,可以手寫一個(gè),內(nèi)容如下
ninja_required_version = 1.5
# 編譯
rule cc
command = gcc -c -Ihello $in -o $out
description = compiling $in to $out ...
build main.o: cc main.c
build hello.o: cc hello/hello.c
# 鏈接
rule link
command = gcc $in -o $out
description = linking $in to $out ...
build app: link main.o hello.o
然后在命令行執(zhí)行
ninja # 編譯
ninja -t clean # 清除編譯結(jié)果
Meson
Meson(The Meson Build System)是個(gè)項(xiàng)目構(gòu)建系統(tǒng),如Makefile,automake,CMake等等。Meson是一個(gè)Python實(shí)現(xiàn)的開源項(xiàng)目,編譯需要Ninja命令, 其思想是,開發(fā)人員花費(fèi)在構(gòu)建調(diào)試上的每一秒都是浪費(fèi),同樣等待構(gòu)建過程直到真正開始編譯都是不值得的。
Meson需要meson.build文件,手動(dòng)編輯,內(nèi)容如下
project('app', 'c')
src = ['main.c', 'hello/hello.c']
inc = 'hello'
executable('app', src, include_directories: inc)
然后在命令行執(zhí)行
meson _build # 生成_build(這里加下劃線是為了與cmake的build區(qū)分下)目錄,下面有build.ninja
ninja -C _build # 編譯
當(dāng)前很多開源軟件構(gòu)建工具已經(jīng)轉(zhuǎn)meson了,以前的開源軟件按照老套路./configure && make && sudo make install 要換成meson build && ninja -C build && sudo ninja -C build install了。
其他
當(dāng)然,還有Bazel,Buck,qmake,Autotools等構(gòu)建系統(tǒng),就不一一示范了。