前言
在開發(fā)xmake之前,我一直在使用gnumake/makefile來維護(hù)個人C/C++項(xiàng)目,一開始還好,然而等項(xiàng)目越來越龐大后,維護(hù)起來就非常吃力了,后續(xù)也用過一陣子automake系列工具,并不是很好用。
由于C/C++程序的構(gòu)建過程比較繁瑣,如果不借助IDE工具,很難快速構(gòu)建一個新的C/C++程序,想要跨平臺構(gòu)建就更加麻煩了。
雖然IDE很好用,也很強(qiáng)大,但是還是有很多不足的地方,例如:
- 跨平臺開發(fā)支持不完善
- 自身環(huán)境不一定跨平臺
- 過于臃腫
- 不利于服務(wù)端自動化部署構(gòu)建
- 不夠靈活,定制化配置構(gòu)建過程有局限性
當(dāng)然如果你熟悉makefile的話,也可以手敲makefile,不過不同平臺用的make也不相同,比如: gnumake, nmake等,導(dǎo)致makefile語法存在差異性,無法做到一致性編譯,而且對開發(fā)者有一定的使用門檻。
在win上使用gnumake還得裝cygwin,mingw-msys等環(huán)境,也非常麻煩,折騰完環(huán)境就得半天時間。
目前已經(jīng)有了很多現(xiàn)代化的構(gòu)建工具,方便開發(fā)者構(gòu)建和維護(hù)C/C++項(xiàng)目,例如:cmake, scons, premake, bazel, gn, gyp等等。
其中很多只能生成對應(yīng)的IDE工程,然后再通過對應(yīng)IDE來維護(hù)和構(gòu)建,這種只是解決了C/C++項(xiàng)目的一致性維護(hù)問題,但是構(gòu)建方式不一致,因此還是沒解決之前列舉的大部分不足點(diǎn),也無法直接快速構(gòu)建。
而cmake, scons雖然很強(qiáng)大,但是cmake語法怪異不直觀,本人實(shí)在是不習(xí)慣,scons使用還需要依賴python,py2/py3的問題折騰起來也比較蛋疼。
鑒于此,我采用了lua來描述工程,利用lua的輕量,簡潔,靈活,跨平臺等特性,來解決上述遇到的各種問題,使用xmake將會帶來不一樣的構(gòu)建體驗(yàn):
- 輕量,跨平臺,無依賴,無需額外安裝python等第三方環(huán)境,直接內(nèi)置lua運(yùn)行時,一個安裝包(或者命令)直接搞定
- 工程描述直觀簡潔,更符合用戶正常的思維習(xí)慣
- 支持直接構(gòu)建,強(qiáng)大的命令行工具,終端用戶的福音,裝逼用戶必備
- vscode, idea, clion, sublime, vim等編輯器插件支持
- 智能檢測支持,簡化用戶編譯配置過程
- 插件支持,靈活的用戶可擴(kuò)展性
- vcproj等IDE項(xiàng)目文件生成也支持的哦
- 更多隱藏特性等你來體驗(yàn)

快速上手
不會寫makefile?沒關(guān)系,直接在源碼目錄運(yùn)行以下命令即可直接編譯:
xmake
xmake會自動掃描在當(dāng)前目錄下的源碼結(jié)構(gòu),生成一個xmake.lua工程描述文件,然后嘗試直接編譯。
想要直接運(yùn)行編譯后的可執(zhí)行程序,簡單,直接敲:
$ xmake run
更多相關(guān)信息,請參考文章: xmake新增智能代碼掃描編譯模式,無需手寫任何make文件
快速入門
如果想要更進(jìn)一步描述工程,調(diào)整源碼結(jié)構(gòu),添加一些編譯選項(xiàng)什么的,還是需要維護(hù)一個名叫xmake.lua的工程描述文件,類似makefile, cmakelist.txt,但是其語法和api經(jīng)過不斷地改進(jìn)簡化,已經(jīng)相當(dāng)易用。
最簡單的描述例子只需要三行:
target("test")
set_kind("binary")
add_files("src/*.c")
就可以構(gòu)建一個可執(zhí)行程序,編譯所有在src目錄下的c源文件。
然后直接執(zhí)行xmake即可編譯。
add_files()支持通配符文件模式匹配,并且支持.c, .cpp, .go, .d, .m, .mm, .S, .swift, .rc, .rs等各種native語言的代碼文件,大部分都能支持混編。
我們甚至可以添加.a和.o, .obj文件到add_files(),例如:
target("test")
set_kind("static")
add_files("src/*.c")
add_files("lib/libxxx.a", "obj/bbb.o")
上述描述會編譯生成一個libtest.a庫,在編譯歸檔的時候,會自動將libxxx.a庫反解出來,合并到libtest.a中去,并且同時將bbb.o也加進(jìn)去。
xmake提供的add_files是非常強(qiáng)大的,我們還可以再添加一批文件的同時,指定排除某些文件,例如:
add_files("src/**.cpp|test.cpp|arm/*.cpp")
上述描述,在遞歸添加源文件的同時,排除掉了test.cpp以及arm目錄下的源文件。
更多add_files用法,請參考文檔:add_files接口使用文檔
使用演示
命令行下的使用過程,大家可以通過一個視頻直觀的體驗(yàn)下:
創(chuàng)建工程
更加省事的方式就是通過上節(jié)所說傻瓜式操作方式,自動生成一個xmake.lua,然后在這基礎(chǔ)下修修改改就行了。
當(dāng)然如果沒有現(xiàn)成源碼,想從新工程創(chuàng)建開始編譯,那么可以使用xmake提供的工程模板進(jìn)行創(chuàng)建:
$ xmake create test
默認(rèn)創(chuàng)建一個名為test的c可執(zhí)行項(xiàng)目,源碼結(jié)構(gòu)如下:
.
├── src
│ └── main.c
└── xmake.lua
當(dāng)然你也可以選擇語言和模板類型:
$ xmake create -l c++ -t shared test
上述命令創(chuàng)建了一個c++動態(tài)庫項(xiàng)目,就這么簡單。
運(yùn)行和調(diào)試
編譯完的可執(zhí)行程序,直接敲xmake run就能運(yùn)行,xmake會自動找到對應(yīng)的target目標(biāo)文件,你也可以傳遞參數(shù)給程序。
如果有多個target目標(biāo),你可以指定需要運(yùn)行的target名,例如:
$ xmake run test
想要快速調(diào)試程序?加上-d參數(shù)即可
$ xmake run -d test
xmake默認(rèn)會去找系統(tǒng)自帶的調(diào)試器,然后加載運(yùn)行,windows上使用vsjitdebugger,linux上gdb,macos上lldb,當(dāng)然你也可以隨意切換到其他調(diào)試器。
配合debug模式編譯,就能做到使用xmake進(jìn)行源碼調(diào)試。
可視化配置和構(gòu)建
xmake提倡使用命令行的方式來操作,用習(xí)慣后效率非常高,而且在windows上,即使沒有cygwin,也可以直接在cmd下正常運(yùn)行。
當(dāng)然,并不是所有用戶習(xí)慣命令行,因此xmake也提供了編輯器插件,與各大編輯器進(jìn)行集成,例如:
xmake-vscode插件

xmake-idea插件
[站外圖片上傳中...(image-8fbf21-1522240153002)]
xmake-sublime插件

xmake-tui界面
除了編輯器插件,xmake甚至自己封裝實(shí)現(xiàn)了一整套跨平臺tui字符界面庫,然后仿kconfig/menuconf的界面風(fēng)格,實(shí)現(xiàn)了一個類似的可視化字符界面菜單配置。
這個不需要額外的插件,只需要在終端下執(zhí)行:
$ xmake f --menu
就可以顯示菜單配置界面進(jìn)行編譯配置,配置完即可根據(jù)當(dāng)前配置進(jìn)行編譯,效果如下:
[站外圖片上傳中...(image-2b6975-1522240153002)]
定制化編譯
想要更加靈活的編譯配置?那就得要修改xmake.lua啦,不過還是很簡單的。
添加編譯選項(xiàng)
target("test")
set_kind("binary")
add_files("src/*.c")
if is_mode("debug") then
add_cxflags("-DDEBUG")
end
上面代碼中,add_cxflags接口就是同時配置C/C++代碼的編譯選項(xiàng),并且只在debug模式下生效,也就是執(zhí)行下面命令的時候:
$ xmake f -m debug
$ xmake
使用內(nèi)置選項(xiàng)
像添加宏定義,設(shè)置警告級別,優(yōu)化級別,頭文件搜索目錄什么的,完全沒必要使用原始的add_cxflags接口,xmake有提供更加方便的接口,更加智能化的處理來簡化配置,也更加通用跨平臺,例如:
add_defines("DEBUG")
set_optimize("fast")
set_warnings("all", "error")
target("test")
set_kind("binary")
add_files("src/*.c")
target("test2")
set_kind("binary")
add_files("src2/*.c")
跟剛才的配置不同的是,此處設(shè)置放在了target的上面,此處不屬于target域,是root全局設(shè)置,會影響下面的所有target目標(biāo)程序的編譯設(shè)置,這樣可以簡化配置,避免冗余。
靈活的腳本控制
對于高端用戶,構(gòu)建需求復(fù)雜多變,xmake也提供了對應(yīng)解決方案,各個構(gòu)建階段都可以靈活定制:
target("test")
set_kind("binary")
add_files("src/*.c")
after_build(function (target)
os.exec("file %s", target:targetfile())
end)
上述代碼在編譯程序結(jié)束后,執(zhí)行file命令查看目標(biāo)程序相關(guān)信息,目前xmake可以在build, clean, run, install, uninstall等各個階段的前后插入自定義的腳本,也可以直接內(nèi)置action,例如: on_install會覆蓋內(nèi)置的安裝邏輯,提供給用戶足夠的靈活性。
方便的多目標(biāo)依賴
很多時候,一個項(xiàng)目會有多個target目標(biāo)程序,之間存在依賴關(guān)系,例如: 一個可執(zhí)行程序hello,依賴一個靜態(tài)庫libtest.a,我們只需要通過add_deps將兩個target做個關(guān)聯(lián)就行了,libtest.a的搜索目錄,頭文件目錄設(shè)置什么的都不需要關(guān)心,xmake會自動處理:
target("test")
set_kind("static")
add_files("src/test/*.c")
target("hello")
add_deps("test") --添加依賴
set_kind("binary")
add_files("src/hello/*.c")
預(yù)編譯頭文件支持
xmake支持通過預(yù)編譯頭文件去加速c/c++程序編譯,目前支持的編譯器有:gcc, clang和msvc。
target("test")
-- ...
set_pcxxheader("header.h")
各大編譯器對預(yù)編譯頭的處理方式存在很大差異,而xmake將其差異性隱藏了起來,提供一致性的描述設(shè)置,簡化用戶在跨平臺編譯時候的處理,
具體關(guān)于編譯器對預(yù)編譯頭文件的處理,可參考相關(guān)文章:不同編譯器對預(yù)編譯頭文件的處理
自定義編譯規(guī)則
xmake不僅原生內(nèi)置支持多種語言文件的構(gòu)建,而且還可以通過自定義構(gòu)建規(guī)則,讓用戶自己來實(shí)現(xiàn)復(fù)雜的未知文件構(gòu)建。
我們可以通過預(yù)先設(shè)置規(guī)則支持的文件后綴,來擴(kuò)展其他文件的構(gòu)建支持:
-- 定義一個markdown文件的構(gòu)建規(guī)則
rule("markdown")
set_extensions(".md", ".markdown")
on_build(function (target, sourcefile)
os.cp(sourcefile, path.join(target:targetdir(), path.basename(sourcefile) .. ".html"))
end)
target("test")
set_kind("binary")
-- 使test目標(biāo)支持markdown文件的構(gòu)建規(guī)則
add_rules("markdown")
-- 添加markdown文件的構(gòu)建
add_files("src/*.md")
add_files("src/*.markdown")
我們也可以指定某些零散的其他文件作為markdown規(guī)則來處理:
target("test")
-- ...
add_files("src/test/*.md.in", {rule = "markdown"})
注:通過add_files("*.md", {rule = "markdown"})方式指定的規(guī)則,優(yōu)先級高于add_rules("markdown")設(shè)置的規(guī)則。
IDE工程文件生成
xmake提供了豐富的插件擴(kuò)展,其中vcproj, makefile等工程文件的生成就是作為插件提供,使用起來也非常簡單:
$ xmake project -k vs2017 -m "debug,release"
即可生成帶有debug, release兩種編譯模式的vc工程,同時支持x86和x64。
生成的工程目錄結(jié)構(gòu)會根據(jù)添加的所有源文件的目錄結(jié)構(gòu),自動分析生成直觀的文件樹,方便vs去瀏覽查看。
makefile的生成如下:
$ xmake project -k makefile
后續(xù)會陸續(xù)更多其他工程文件,也歡迎大家來貢獻(xiàn)哦。
靈活簡單的插件擴(kuò)展
上節(jié)的IDE工程文件生成,在xmake中就是作為插件來提供,這樣更加方便擴(kuò)展,也能讓用戶快速定制自己的插件,只需要定義個task插件任務(wù)就行了:
-- 定義一個名叫hello的插件任務(wù)
task("hello")
-- 設(shè)置類型為插件
set_category("plugin")
-- 插件運(yùn)行的入口
on_run(function ()
print("hello xmake!")
end)
-- 設(shè)置插件的命令行選項(xiàng),這里沒有任何參數(shù)選項(xiàng),僅僅顯示插件描述
set_menu {
-- usage
usage = "xmake hello [options]"
-- description
, description = "Hello xmake!"
-- options
, options = {}
}
上述代碼就是一個最為簡單的hello xmake!插件,運(yùn)行$xmake hello就可看到執(zhí)行輸出,set_menu用于配置插件命令行選項(xiàng),這個不設(shè)置就是內(nèi)部task,無法在命令行下調(diào)用。
更加詳細(xì)的插件說明以及內(nèi)置插件列表可參考文檔:插件手冊
查找依賴包
xmake參考了cmake對于find_*系列接口的設(shè)計(jì),實(shí)現(xiàn)在項(xiàng)目中動態(tài)的查找和添加包依賴。
target("test")
set_kind("binary")
add_files("*.c")
on_load(function (target)
import("lib.detect.find_package")
target:add(find_package("zlib"))
end)
上述描述代碼,通過lib.detect.find_package來查找包,如果找到zlib包,則將links, includedirs和linkdirs等信息添加到target中去。
交互式命令執(zhí)行(REPL)
有時候在交互模式下,運(yùn)行命令更加的方便測試和驗(yàn)證一些模塊和api,也更加的靈活,不需要再去額外寫一個腳本文件來加載,不過我一般用來做計(jì)算器用用(好吧。。)
# 不帶任何參數(shù)執(zhí)行,就可以進(jìn)入
$ xmake lua
>
# 進(jìn)行表達(dá)式計(jì)算
> 1 + 2
3
# 賦值和打印變量值
> a = 1
> a
1
# 多行輸入和執(zhí)行
> for _, v in pairs({1, 2, 3}) do
>> print(v)
>> end
1
2
3
我們也能夠通過 import 來導(dǎo)入擴(kuò)展模塊:
> task = import("core.project.task")
> task.run("hello")
hello xmake!
編譯環(huán)境支持
當(dāng)前xmake的最新版本已經(jīng)支持很多sdk環(huán)境的集成編譯,例如:
- [x] Visual Studio編譯環(huán)境
- [x] mingw編譯環(huán)境
- [x] cygwin編譯環(huán)境
- [x] Android NDK編譯環(huán)境
- [x] Xcode編譯環(huán)境(支持iPhoneos/Macosx構(gòu)建)
- [x] 系統(tǒng)gcc/clang編譯環(huán)境
- [x] 交叉工具鏈編譯環(huán)境
- [x] Cuda編譯環(huán)境
- [ ] Qt編譯環(huán)境(正在支持中)
- [ ] Windows WDK編譯環(huán)境(正在支持中)
FAQ
xmake有哪些用途?
- 跨平臺維護(hù)和編譯C/C++項(xiàng)目
- CI上部署自動化構(gòu)建
- 開源代碼的快速移植
- 臨時的測試代碼編寫和快速運(yùn)行
- 與自己喜歡的編輯器集成,打造屬于自己的C/C++開發(fā)環(huán)境
- 與其他native語言的混合編譯
- 嵌入式開發(fā)下的交叉編譯
- 提升逼格
對于第三點(diǎn)的用途,我平常用的最多,因?yàn)槲医?jīng)常需要移植第三方的開源項(xiàng)目,它們使用的構(gòu)建工具各不相同,有automake,cmake等等,其支持的構(gòu)建平臺力度也都不相同,經(jīng)常會遇到需要的平臺不支持的問題。
沒辦法,只好自己敲makefile來移植代碼,然后適配自己需要支持的那些平臺,還有交叉工具鏈,很蛋疼,自從寫了xmake后,我現(xiàn)在平常移植代碼方便了很多,效率提升非常明顯。
怎樣看實(shí)時編譯警告信息?
為了避免刷屏,在構(gòu)建時候,默認(rèn)是不實(shí)時輸出警告信息的,如果想要看的話可以加上-w選項(xiàng)啟用編譯警告輸出就行了。
$ xmake [-w|--warning]
怎樣看詳細(xì)的編譯參數(shù)信息?
請加上 -v 或者 --verbose 選項(xiàng)重新執(zhí)行xmake后,獲取更加詳細(xì)的輸出信息
例如:
$ xmake [-v|--verbose]
如果加上 --backtrace 選項(xiàng)也可以獲取出錯時的xmake的調(diào)試棧信息
$ xmake -v --backtrace

快速安裝
最后我們講下,如何安裝xmake,通常只需要一個腳本命令就能搞定。
一鍵安裝腳本
bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
windows安裝包
對于windows用戶,提供了安裝包來快速安裝,可到Github Releases上下載對應(yīng)版本。
更加詳細(xì)的安裝過程,見相關(guān)文檔: 安裝說明
結(jié)語
xmake還有很多非常有用的特性,例如:編譯器特性檢測、豐富的模塊庫、依賴包管理、自定義選項(xiàng)等等,一篇文章講不完這么多,大家有興趣的話,可以去官方文檔里面看看,還有很多隱藏特性等著你哦。
原文出處:http://tboox.org/cn/2018/03/26/build-project-so-simply/
