xmake入門,構建專案原來可以如此簡單

ruki發表於2019-03-01

前言

在開發xmake之前,我一直在使用gnumake/makefile來維護個人C/C++專案,一開始還好,然而等專案越來越龐大後,維護起來就非常吃力了,後續也用過一陣子automake系列工具,並不是很好用。

由於C/C++程式的構建過程比較繁瑣,如果不借助IDE工具,很難快速構建一個新的C/C++程式,想要跨平臺構建就更加麻煩了。

雖然IDE很好用,也很強大,但是還是有很多不足的地方,例如:

  • 跨平臺開發支援不完善
  • 自身環境不一定跨平臺
  • 過於臃腫
  • 不利於服務端自動化部署構建
  • 不夠靈活,定製化配置構建過程有侷限性

當然如果你熟悉makefile的話,也可以手敲makefile,不過不同平臺用的make也不相同,比如: gnumake, nmake等,導致makefile語法存在差異性,無法做到一致性編譯,而且對開發者有一定的使用門檻。

在win上使用gnumake還得裝cygwin,mingw-msys等環境,也非常麻煩,折騰完環境就得半天時間。

目前已經有了很多現代化的構建工具,方便開發者構建和維護C/C++專案,例如:cmake, scons, premake, bazel, gn, gyp等等。

其中很多隻能生成對應的IDE工程,然後再通過對應IDE來維護和構建,這種只是解決了C/C++專案的一致性維護問題,但是構建方式不一致,因此還是沒解決之前列舉的大部分不足點,也無法直接快速構建。

而cmake, scons雖然很強大,但是cmake語法怪異不直觀,本人實在是不習慣,scons使用還需要依賴python,py2/py3的問題折騰起來也比較蛋疼。

鑑於此,我採用了lua來描述工程,利用lua的輕量,簡潔,靈活,跨平臺等特性,來解決上述遇到的各種問題,使用xmake將會帶來不一樣的構建體驗:

  • 輕量,跨平臺,無依賴,無需額外安裝python等第三方環境,直接內建lua執行時,一個安裝包(或者命令)直接搞定
  • 工程描述直觀簡潔,更符合使用者正常的思維習慣
  • 支援直接構建,強大的命令列工具,終端使用者的福音,裝逼使用者必備
  • vscode, idea, clion, sublime, vim等編輯器外掛支援
  • 智慧檢測支援,簡化使用者編譯配置過程
  • 外掛支援,靈活的使用者可擴充套件性
  • vcproj等IDE專案檔案生成也支援的哦
  • 更多隱藏特性等你來體驗
xmake-compilation

快速上手

不會寫makefile?沒關係,直接在原始碼目錄執行以下命令即可直接編譯:

xmake
複製程式碼

xmake會自動掃描在當前目錄下的原始碼結構,生成一個xmake.lua工程描述檔案,然後嘗試直接編譯。

想要直接執行編譯後的可執行程式,簡單,直接敲:

$ xmake run
複製程式碼

更多相關資訊,請參考文章: xmake新增智慧程式碼掃描編譯模式,無需手寫任何make檔案

快速入門

如果想要更進一步描述工程,調整原始碼結構,新增一些編譯選項什麼的,還是需要維護一個名叫xmake.lua的工程描述檔案,類似makefile, cmakelist.txt,但是其語法和api經過不斷地改進簡化,已經相當易用。

最簡單的描述例子只需要三行:

target("test")
    set_kind("binary")
    add_files("src/*.c")
複製程式碼

就可以構建一個可執行程式,編譯所有在src目錄下的c原始檔。

然後直接執行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也加進去。

xmake提供的add_files是非常強大的,我們還可以再新增一批檔案的同時,指定排除某些檔案,例如:

add_files("src/**.cpp|test.cpp|arm/*.cpp")
複製程式碼

上述描述,在遞迴新增原始檔的同時,排除掉了test.cpp以及arm目錄下的原始檔。

更多add_files用法,請參考文件:add_files介面使用文件

使用演示

命令列下的使用過程,大家可以通過一個視訊直觀的體驗下:


xmake入門,構建專案原來可以如此簡單

建立工程

更加省事的方式就是通過上節所說傻瓜式操作方式,自動生成一個xmake.lua,然後在這基礎下修修改改就行了。

當然如果沒有現成原始碼,想從新工程建立開始編譯,那麼可以使用xmake提供的工程模板進行建立:

$ xmake create test
複製程式碼

預設建立一個名為test的c可執行專案,原始碼結構如下:

.
├── src
│   └── main.c
└── xmake.lua
複製程式碼

當然你也可以選擇語言和模板型別:

$ xmake create -l c++ -t shared test
複製程式碼

上述命令建立了一個c++動態庫專案,就這麼簡單。

執行和除錯

編譯完的可執行程式,直接敲xmake run就能執行,xmake會自動找到對應的target目標檔案,你也可以傳遞引數給程式。

如果有多個target目標,你可以指定需要執行的target名,例如:

$ xmake run test
複製程式碼

想要快速除錯程式?加上-d引數即可

$ xmake run -d test
複製程式碼

xmake預設會去找系統自帶的偵錯程式,然後載入執行,windows上使用vsjitdebugger,linux上gdb,macos上lldb,當然你也可以隨意切換到其他偵錯程式。

配合debug模式編譯,就能做到使用xmake進行原始碼除錯。

視覺化配置和構建

xmake提倡使用命令列的方式來操作,用習慣後效率非常高,而且在windows上,即使沒有cygwin,也可以直接在cmd下正常執行。

當然,並不是所有使用者習慣命令列,因此xmake也提供了編輯器外掛,與各大編輯器進行整合,例如:

xmake-vscode外掛

xmake入門,構建專案原來可以如此簡單

xmake-idea外掛

xmake入門,構建專案原來可以如此簡單

xmake-sublime外掛

xmake入門,構建專案原來可以如此簡單

xmake-tui介面

除了編輯器外掛,xmake甚至自己封裝實現了一整套跨平臺tui字元介面庫,然後仿kconfig/menuconf的介面風格,實現了一個類似的視覺化字元介面選單配置。

這個不需要額外的外掛,只需要在終端下執行:

$ xmake f --menu
複製程式碼

就可以顯示選單配置介面進行編譯配置,配置完即可根據當前配置進行編譯,效果如下:

xmake入門,構建專案原來可以如此簡單

定製化編譯

想要更加靈活的編譯配置?那就得要修改xmake.lua啦,不過還是很簡單的。

新增編譯選項

target("test")
    set_kind("binary")
    add_files("src/*.c")
    if is_mode("debug") then
       add_cxflags("-DDEBUG")
    end
複製程式碼

上面程式碼中,add_cxflags介面就是同時配置C/C++程式碼的編譯選項,並且只在debug模式下生效,也就是執行下面命令的時候:

$ xmake f -m debug
$ xmake
複製程式碼

使用內建選項

像新增巨集定義,設定警告級別,優化級別,標頭檔案搜尋目錄什麼的,完全沒必要使用原始的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")
複製程式碼

跟剛才的配置不同的是,此處設定放在了target的上面,此處不屬於target域,是root全域性設定,會影響下面的所有target目標程式的編譯設定,這樣可以簡化配置,避免冗餘。

靈活的指令碼控制

對於高階使用者,構建需求複雜多變,xmake也提供了對應解決方案,各個構建階段都可以靈活定製:

target("test")
    set_kind("binary")
    add_files("src/*.c")

    after_build(function (target)
        os.exec("file %s", target:targetfile())
    end)
複製程式碼

上述程式碼在編譯程式結束後,執行file命令檢視目標程式相關資訊,目前xmake可以在build, clean, run, install, uninstall等各個階段的前後插入自定義的指令碼,也可以直接內建action,例如: on_install會覆蓋內建的安裝邏輯,提供給使用者足夠的靈活性。

方便的多目標依賴

很多時候,一個專案會有多個target目標程式,之間存在依賴關係,例如: 一個可執行程式hello,依賴一個靜態庫libtest.a,我們只需要通過add_deps將兩個target做個關聯就行了,libtest.a的搜尋目錄,標頭檔案目錄設定什麼的都不需要關心,xmake會自動處理:

target("test")
    set_kind("static")
    add_files("src/test/*.c")

target("hello")
    add_deps("test")  --新增依賴
    set_kind("binary")
    add_files("src/hello/*.c")
複製程式碼

預編譯標頭檔案支援

xmake支援通過預編譯標頭檔案去加速c/c++程式編譯,目前支援的編譯器有:gcc, clang和msvc。

target("test")
    -- ...
    set_pcxxheader("header.h")
複製程式碼

各大編譯器對預編譯頭的處理方式存在很大差異,而xmake將其差異性隱藏了起來,提供一致性的描述設定,簡化使用者在跨平臺編譯時候的處理,
具體關於編譯器對預編譯標頭檔案的處理,可參考相關文章:不同編譯器對預編譯標頭檔案的處理

自定義編譯規則

xmake不僅原生內建支援多種語言檔案的構建,而且還可以通過自定義構建規則,讓使用者自己來實現複雜的未知檔案構建。

我們可以通過預先設定規則支援的檔案字尾,來擴充套件其他檔案的構建支援:

-- 定義一個markdown檔案的構建規則
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目標支援markdown檔案的構建規則
    add_rules("markdown")

    -- 新增markdown檔案的構建
    add_files("src/*.md")
    add_files("src/*.markdown")
複製程式碼

我們也可以指定某些零散的其他檔案作為markdown規則來處理:

target("test")
    -- ...
    add_files("src/test/*.md.in", {rule = "markdown"})
複製程式碼

注:通過add_files("*.md", {rule = "markdown"})方式指定的規則,優先順序高於add_rules("markdown")設定的規則。

IDE工程檔案生成

xmake提供了豐富的外掛擴充套件,其中vcproj, makefile等工程檔案的生成就是作為外掛提供,使用起來也非常簡單:

$ xmake project -k vs2017 -m "debug,release"
複製程式碼

即可生成帶有debug, release兩種編譯模式的vc工程,同時支援x86和x64。

生成的工程目錄結構會根據新增的所有原始檔的目錄結構,自動分析生成直觀的檔案樹,方便vs去瀏覽檢視。

makefile的生成如下:

$ xmake project -k makefile
複製程式碼

後續會陸續更多其他工程檔案,也歡迎大家來貢獻哦。

靈活簡單的外掛擴充套件

上節的IDE工程檔案生成,在xmake中就是作為外掛來提供,這樣更加方便擴充套件,也能讓使用者快速定製自己的外掛,只需要定義個task外掛任務就行了:

-- 定義一個名叫hello的外掛任務
task("hello")

    -- 設定型別為外掛
    set_category("plugin")

    -- 外掛執行的入口
    on_run(function ()
        print("hello xmake!")
    end)

    -- 設定外掛的命令列選項,這裡沒有任何引數選項,僅僅顯示外掛描述
    set_menu {
                -- usage
                usage = "xmake hello [options]"

                -- description
            ,   description = "Hello xmake!"

                -- options
            ,   options = {}
            } 
複製程式碼

上述程式碼就是一個最為簡單的hello xmake!外掛,執行$xmake hello就可看到執行輸出,set_menu用於配置外掛命令列選項,這個不設定就是內部task,無法在命令列下呼叫。

更加詳細的外掛說明以及內建外掛列表可參考文件:外掛手冊

查詢依賴包

xmake參考了cmake對於find_*系列介面的設計,實現在專案中動態的查詢和新增包依賴。

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中去。

互動式命令執行(REPL)

有時候在互動模式下,執行命令更加的方便測試和驗證一些模組和api,也更加的靈活,不需要再去額外寫一個指令碼檔案來載入,不過我一般用來做計算器用用(好吧。。)

# 不帶任何引數執行,就可以進入
$ xmake lua
>

# 進行表示式計算
> 1 + 2
3

# 賦值和列印變數值
> a = 1
> a
1

# 多行輸入和執行
> for _, v in pairs({1, 2, 3}) do
>> print(v)
>> end
1
2
3
複製程式碼

我們也能夠通過 import 來匯入擴充套件模組:

> task = import("core.project.task")
> task.run("hello")
hello xmake!
複製程式碼

編譯環境支援

當前xmake的最新版本已經支援很多sdk環境的整合編譯,例如:

  • [x] Visual Studio編譯環境
  • [x] mingw編譯環境
  • [x] cygwin編譯環境
  • [x] Android NDK編譯環境
  • [x] Xcode編譯環境(支援iPhoneos/Macosx構建)
  • [x] 系統gcc/clang編譯環境
  • [x] 交叉工具鏈編譯環境
  • [x] Cuda編譯環境
  • [ ] Qt編譯環境(正在支援中)
  • [ ] Windows WDK編譯環境(正在支援中)

FAQ

xmake有哪些用途?

  1. 跨平臺維護和編譯C/C++專案
  2. CI上部署自動化構建
  3. 開原始碼的快速移植
  4. 臨時的測試程式碼編寫和快速執行
  5. 與自己喜歡的編輯器整合,打造屬於自己的C/C++開發環境
  6. 與其他native語言的混合編譯
  7. 嵌入式開發下的交叉編譯
  8. 提升逼格

對於第三點的用途,我平常用的最多,因為我經常需要移植第三方的開源專案,它們使用的構建工具各不相同,有automake,cmake等等,其支援的構建平臺力度也都不相同,經常會遇到需要的平臺不支援的問題。

沒辦法,只好自己敲makefile來移植程式碼,然後適配自己需要支援的那些平臺,還有交叉工具鏈,很蛋疼,自從寫了xmake後,我現在平常移植程式碼方便了很多,效率提升非常明顯。

怎樣看實時編譯警告資訊?

為了避免刷屏,在構建時候,預設是不實時輸出警告資訊的,如果想要看的話可以加上-w選項啟用編譯警告輸出就行了。

$ xmake [-w|--warning] 
複製程式碼

怎樣看詳細的編譯引數資訊?

請加上 -v 或者 --verbose 選項重新執行xmake後,獲取更加詳細的輸出資訊

例如:

$ xmake [-v|--verbose] 
複製程式碼

如果加上 --backtrace 選項也可以獲取出錯時的xmake的除錯棧資訊

$ xmake -v --backtrace
複製程式碼
xmake-verbose

快速安裝

最後我們講下,如何安裝xmake,通常只需要一個指令碼命令就能搞定。

一鍵安裝指令碼

bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
複製程式碼

windows安裝包

對於windows使用者,提供了安裝包來快速安裝,可到Github Releases上下載對應版本。

更加詳細的安裝過程,見相關文件: 安裝說明

結語

xmake還有很多非常有用的特性,例如:編譯器特性檢測、豐富的模組庫、依賴包管理、自定義選項等等,一篇文章講不完這麼多,大家有興趣的話,可以去官方文件裡面看看,還有很多隱藏特性等著你哦。

原文出處:tboox.org/cn/2018/03/…

相關文章