xmake 是一個基於 Lua 的輕量級跨平臺構建工具,使用 xmake.lua 維護項目構建,相比 makefile/CMakeLists.txt,配置語法更加簡潔直觀,對新手非常友好,短時間內就能快速入門,能夠讓用戶把更多的精力集中在實際的項目開發上。
這是 xmake 在今年的首個版本,也是完全適配支持 Apple Silicon (macOS ARM) 設備的首個版本。
這個版本,我們主要改進了對 C/C++ 依賴包的集成支持,更加的穩定,並且能夠更加靈活的實現定製化配置編譯。
另外,我們還重點改進 vs/vsxmake 兩個vs工程生成器插件,修復了很多細節問題,並且對子工程分組
也做了支持,現在可以生成類似下圖的工程結構。
關於 Zig 方面,0.7.1 版本修復了很多我之前反饋的問題,現在 xmake 也已經可以很好的支持對 zig 項目的編譯。
同時,我們還新開發了一個 luarocks=build-xmake 插件去用 xmake 替換 luarocks 內置的構建系統。
最後,在這個版本中,我們繼續改進了 xmake f --menu
圖形化配置菜單,完全支持鼠標操作和滾動支持,也對 utf8 做了支持。
項目源碼
官方文檔
入門課程
新特性介紹
新增 add_requireconfs 改進包配置
儘管之前的版本,我們可以通過 add_requires("libpng", {configs = {shared = true}})
的方式來定義和配置依賴包。
但是,如果用戶項目的工程龐大,依賴包非常多,且每個包都需要不同的編譯配置參數,那麼配置起來還是會非常繁瑣,並且具有侷限性,比如無法改寫內部的子依賴包配置。
因此,我們新增了 add_requireconfs
去更靈活方便的配置每個包的配置以及它的子依賴,下面我們重點介紹幾種用法:
擴充指定包的配置
這是基本用法,比如我們已經通過 add_requires("zlib")
聲明瞭一個包,想要在後面對這個 zlib 的配置進行擴展,改成動態庫編譯,可以通過下面的方式配置。
add_requires("zlib")
add_requireconfs("zlib", {configs = {shared = true}})
它等價於
add_requires("zlib", {configs = {shared = true}})
設置通用的默認配置
上面的用法,我們還看不出有什麼實際用處,但如果依賴多了就能看出效果了,比如下面這樣:
add_requires("zlib", {configs = {shared = true}})
add_requires("pcre", {configs = {shared = true}})
add_requires("libpng", {configs = {shared = true}})
add_requires("libwebp", {configs = {shared = true}})
add_requires("libcurl", {configs = {shared = false}})
是不是非常繁瑣,如果我們用上 add_requireconfs
來設置默認配置,就可以極大的簡化成下面的配置:
add_requireconfs("*", {configs = {shared = true}})
add_requires("zlib")
add_requires("pcre")
add_requires("libpng")
add_requires("libwebp")
add_requires("libcurl", {configs = {shared = false}})
上面的配置,我們通過 add_requireconfs("*", {configs = {shared = true}})
使用模式匹配的方式,設置所有的依賴包默認走動態庫編譯安裝。
但是,我們又通過 add_requires("libcurl", {configs = {shared = false}})
將 libcurl 進行了特殊配置,強制走靜態庫編譯安裝。
最終的配置結果爲:zlib/pcre/libpng/libwebp 是 shared 庫,libcurl 是靜態庫。
我們通過模式匹配的方式,可以將一些每個包的常用配置都放置到統一的 add_requireconfs
中去預先配置好,極大簡化每個 add_requires
的定義。
!> 默認情況下,對於相同的配置,xmake 會優先使用 add_requires 中的配置,而不是 add_requireconfs。
如果 add_requires("zlib 1.2.11")
中設置了版本,就會優先使用 add_requires 的配置,完全忽略 add_requireconfs 裏面的版本配置,當然我們也可以通過 override 來完全重寫 add_requires
中指定的版本。
add_requires("zlib 1.2.11")
add_requireconfs("zlib", {override = true, version = "1.2.10"})
改寫包依賴配置
其實 add_requireconfs
最大的用處是可以讓用戶改寫安裝包的特定依賴包的配置。
什麼意思呢,比如我們項目中集成使用 libpng 這個包,並且使用了動態庫版本,但是 libpng 內部依賴的 zlib 庫其實還是靜態庫版本。
add_requires("libpng", {configs = {shared = true}})
那如果我們想讓 libpng 依賴的 zlib 包也改成動態庫編譯,應該怎麼配置呢?這就需要 add_requireconfs
了。
add_requires("libpng", {configs = {shared = true}})
add_requireconfs("libpng.zlib", {configs = {shared = true}})
通過 libpng.zlib
依賴路徑的寫法,指定內部某個依賴,改寫內部依賴配置。
如果依賴路徑很深,比如 foo -> bar -> xyz
的依賴鏈,我們可以寫成:foo.bar.xyz
我們也可以改寫 libpng 依賴的內部 zlib 庫版本:
add_requires("libpng")
add_requireconfs("libpng.zlib", {version = "1.2.10"})
級聯依賴的模式匹配
如果一個包的依賴非常多,且依賴層次也很深,怎麼辦呢,比如 libwebp 這個包,它的依賴有:
libwebp
- libpng
- zlib
- cmake
- libjpeg
- libtiff
- zlib
- giflib
- cmake
如果我想改寫 libwebp 裏面的所有的依賴庫都加上特定配置,那麼挨個配置,就會非常繁瑣,這個時候就需要 add_requireconfs()
的遞歸依賴模式匹配來支持了。
add_requires("libwebp")
add_requireconfs("libwebp.**|cmake", {configs = {cxflags = "-DTEST"}})
上面的配置,我們將 libwebp 中所以的庫依賴就額外加上了 -DTEST
來編譯,但是 cmake 依賴屬於構建工具依賴,我們可以通過 |xxx
的方式排除它。
這裏的模式匹配寫法,與 add_files()
非常類似。
我們在給幾個例子,比如這回我們只改寫 libwebp 下單級的依賴配置,啓用調試庫:
add_requires("libwebp")
add_requireconfs("libwebp.*|cmake", {debug = true})
圖形化配置支持鼠標和滾動操作
我們升級了 xmake 所使用的 tui 組件庫:LTUI,增加了對鼠標的支持,以及部分組件的滾動支持,我們可以再圖形化配置中,更加靈活方便的配置編譯選項。
stdin 重定向輸入支持
之前的版本中,xmake 提供的 os.execv/os.runv 等進程執行接口,僅僅只支持 stdout/stderr 輸出重定向,但是並不支持 stdin 輸入重定向,因此在這個版本中,我們對其也做了支持。
使用方式如下:
os.execv("foo", {"arg1", "arg2"}, {stdin = "/tmp/a"})
我們可以執行進程的時候,將 /tmp/a 文件作爲重定向輸入,當然我們還可以傳遞 {stdout = "/tmp/out"}
等作爲重定向輸出。
vs 工程分組支持
我們新增了一個接口 set_group
,來對每個 target 進行分組支持,此接口目前僅用於 vs/vsxmake 工程生成,對 vs 工程內部子工程目錄樹按指定結構分組展示,不過後續也可能對其他模塊增加分組支持。
比如對於下面的分組配置:
add_rules("mode.debug", "mode.release")
target("test1")
set_kind("binary")
add_files("src/*.cpp")
set_group("group1")
target("test2")
set_kind("binary")
add_files("src/*.cpp")
set_group("group1")
target("test3")
set_kind("binary")
add_files("src/*.cpp")
set_group("group1/group2")
target("test4")
set_kind("binary")
add_files("src/*.cpp")
set_group("group3/group4")
target("test5")
set_kind("binary")
add_files("src/*.cpp")
target("test6")
set_kind("binary")
add_files("src/*.cpp")
生成的 vs 工程目錄結構效果如下:
其中 set_group("group1/group2")
可以將 target 設置到二級分組中去。
vs 工程自動更新規則
如果覺得每次通過 xmake project -k vsxmake
命令來生成和更新 vs 工程很繁瑣,我們現在可以通過在 xmake.lua 中配置 plugin.vsxmake.autoupdate
規則來實現自動更新。
用戶可以在 vs 工程中每次執行構建後,如果文件列表或者 xmake.lua 有改動,vs 工程都會自動更新。
add_rules("plugin.vsxmake.autoupdate")
target("test")
set_kind("binary")
add_files("src/*.c")
vs/vsxmake 工程插件改進
除了上面提到的分組支持和自動更新,這個版本中,我們還修復了不少 vs 工程相關的問題,比如:intellisense 提示改進,路徑被截斷的問題修復,全面支持遠程依賴包
改進 windows 註冊表支持
xmake 改進了內部的 winos 模塊,新增了一些接口來更加方便的訪問註冊表,獲取 windows 上的註冊表配置。
winos.registry_keys
獲取註冊表建列表
支持通過模式匹配的方式,遍歷獲取註冊表鍵路徑列表,*
爲單級路徑匹配,**
爲遞歸路徑匹配。
local keypaths = winos.registry_keys("HKEY_LOCAL_MACHINE\\SOFTWARE\\*\\Windows NT\\*\\CurrentVersion\\AeDebug")
for _, keypath in ipairs(keypaths) do
print(winos.registry_query(keypath .. ";Debugger"))
end
winos.registry_values
獲取註冊表值名列表
支持通過模式匹配的方式,獲取指定鍵路徑的值名列表,;
之後的就是指定的鍵名模式匹配字符串。
local valuepaths = winos.registry_values("HKEY_LOCAL_MACHINE\\SOFTWARE\\xx\\AeDebug;Debug*")
for _, valuepath in ipairs(valuepaths) do
print(winos.registry_query(valuepath))
end
winos.registry_query
獲取註冊表建值
獲取指定註冊表建路徑下的值,如果沒有指定值名,那麼獲取鍵路徑默認值
local value, errors = winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug")
local value, errors = winos.registry_query("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug;Debugger")
Zig 項目構建支持
在上個版本中,xmake 已經對 zig 進行了實驗性支持,但是期間也躺了不少坑,尤其是 windows/macos 上構建中遇到了不少問題。
然後在最新的 zig 0.7.1 中,已經將我遇到的大部分問題都修復了,現在 xmake 已經可以很好的支持 zig 項目編譯。
我們可以通過下面的命令,快速創建一個 Zig 空工程:
$ xmake create -l zig console
xmake.lua 內容如下:
add_rules("mode.debug", "mode.release")
target("console")
set_kind("binary")
add_files("src/*.zig")
可以看到,其實配置方式跟 C/C++ 並沒有什麼不同,由於 Zig 和 C 有很好的二進制兼容,因此我們也可以使用 add_requires
來給 zig 項目添加 C/C++ 包的遠程依賴支持。
然後執行 xmake 就可以完成編譯了。
$ xmake
然後繼續運行 run 命令,就可以直接執行 zig 程序,輸出運行結果。
$ xmake run
Hello world!
我們還可以很方便的實現 C 和 Zig 的混合編譯支持,只需要添加上對應的 C 代碼文件就可以了。
add_rules("mode.debug", "mode.release")
target("console")
set_kind("binary")
add_files("src/*.zig", "src/*.c")
完整代碼例子見:Zig with C
Luarocks 插件
luarocks 是 lua 的一個包管理工具,提供了各種 lua 模塊的安裝集成,不過它本身在對 lua c 模塊進行構建是採用的內建的構建機制。
比如在它的 rockspec 文件中通過 builtin 構建類型來描述常用 lua c 模塊的構建:
build = {
type = "builtin",
modules = {
["module.hello"] = {
sources = "src/test.c"
}
},
copy_directories = {}
}
這對於小模塊而言,並沒有什麼問題,但如果模塊的 c 代碼結構比較複雜,它內置的構建規則還是有很多的侷限性,並不靈活,另外切換 msvc / mingw 工具鏈以及參數配置什麼的都不夠靈活。
因此,xmake 提供了 luarocks=build-xmake 插件去替換 luarocks 內置的構建系統,替換方式也很簡單,只需要將 builtin 構建類型改成 xmake,並加上 luarocks-build-xmake 依賴就行了。
dependencies = {
"lua >= 5.1",
"luarocks-build-xmake"
}
build = {
type = "xmake",
modules = {
["module.hello"] = {
sources = "src/test.c"
}
},
copy_directories = {}
}
但是這樣還是很繁瑣,還是要基於 rockspec 文件中 modules 中的源文件列表來描述規則,然後 luarocks-build-xmake 會自動根據配置生成 xmake.lua 來完成構建。
不過既然用了 xmake,那麼自己的 lua 模塊,完全可以用 xmake.lua 來維護,這樣構建配置就更加靈活了,因此我們只需要下面這樣就行了。
dependencies = {
"lua >= 5.1",
"luarocks-build-xmake"
}
build = {
type = "xmake",
copy_directories = {}
}
只需要設置當前切換到 xmake 編譯,完全使用 lua 模塊項目內置的 xmake.lua 規則文件。
支持在 windows 安裝部署 Qt 程序
非常感謝 @SirLynix 的貢獻,xmake 已經可以支持在 windows 上部署安裝 Qt 應用程序。
我們只需要正常維護一個 Qt 程序,例如:
add_rules("mode.debug", "mode.release")
target("demo")
add_rules("qt.quickapp")
add_headerfiles("src/*.h")
add_files("src/*.cpp")
add_files("src/qml.qrc")
然後,我們只需要執行下面的編譯安裝命令,xmake 就會自動調用 windeployqt.exe 程序去安裝部署我們的 Qt 應用。
$ xmake
$ xmake install -o d:\installdir
相關補丁:#1145
另外,在之前的版本中,xmake 也已經支持對 macOS 和 android 版本的 Qt 程序進行部署打包,每次只需要正常的編譯命令,就可以生成 QT .app/.apk 安裝包。
$ xmake f -p android --ndk=/xxx/android-ndk-r20b --sdk=/xxx
$ xmake
一些問題修復
我們還修復了不少用戶反饋的問題,這裏我們介紹一些比較重要的 bug 修復,例如:
我們修復了 add_defines("TEST=\"hello world\"")
中內部帶有空的雙引號問題,之前編譯會出錯。
另外我們改進了 vstudio 環境的查找和支持,解決了用戶 home 目錄和環境變量中帶有中文導致的編譯失敗問題。
我們也改進了 llvm 工具鏈,解決了 macOS 下如果沒有安裝 xcode 的情況下,使用 llvm 工具鏈缺少 isysroot 配置問題,以及 msvc 下頭文件依賴編譯偶爾失效問題。
更新內容
新特性
#1035: 圖形配置菜單完整支持鼠標事件,並且新增滾動欄
#1098: 支持傳遞 stdin 到 os.execv 進行輸入重定向
#1079: 爲 vsxmake 插件添加工程自動更新插件,
add_rules("plugin.vsxmake.autoupdate")
添加
xmake f --vs_runtime=MT
和set_runtimes("MT")
去更方便的對 target 和 package 進行設置#1032: 支持枚舉註冊表 keys 和 values
#1026: 支持對 vs/vsmake 工程增加分組設置
#1178: 添加
add_requireconfs()
接口去重寫依賴包的配置#1043: 爲 luarocks 模塊添加
luarocks.module
構建規則#1190: 添加對 Apple Silicon (macOS ARM) 設備的支持
#1145: 支持在 windows 上安裝部署 Qt 程序, 感謝 @SirLynix
改進
#1072: 修復並改進 cl 編譯器頭文件依賴信息
針對 ui 模塊和
xmake f --menu
增加 utf8 支持改進 zig 語言在 macOS 上的支持
#1135: 針對特定 target 改進多平臺多工具鏈同時配置支持
#1153: 改進 llvm 工具鏈,針對 macos 上編譯增加 isysroot 支持
#1071: 改進 vs/vsxmake 生成插件去支持遠程依賴包
改進 vs/vsxmake 工程生成插件去支持全局的
set_arch()
設置#1164: 改進 vsxmake 插件調試加載 console 程序
#1179: 改進 llvm 工具鏈,添加 isysroot
Bugs 修復
#1091: 修復不正確的繼承鏈接依賴
#1105: 修復 vsxmake 插件 c++ 語言標準智能提示錯誤
#1132: 修復 vsxmake 插件中配置路徑被截斷問題
#1142: 修復安裝包的時候,出現git找不到問題
修復在 macOS Big Sur 上 macos.version 問題
#1084: 修復
add_defines()
中帶有雙引號和空格導致無法正確處理宏定義的問題#1195: 修復 unicode 編碼問題,改進 vs 環境查找和進程執行
關注公衆號
TBOOX開源工程
專注C跨平臺開發解決方案
長按二維碼關注
本文分享自微信公衆號 - TBOOX開源工程(tboox-os)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。