xmake 是一個基於 Lua 的輕量級跨平臺構建工具,使用 xmake.lua 維護項目構建,相比 makefile/CMakeLists.txt,配置語法更加簡潔直觀,對新手很是友好,短期內就能快速入門,可以讓用戶把更多的精力集中在實際的項目開發上。android
這是 xmake 在今年的首個版本,也是徹底適配支持 Apple Silicon (macOS ARM) 設備的首個版本。c++
這個版本,咱們主要改進了對 C/C++ 依賴包的集成支持,更加的穩定,而且可以更加靈活的實現定製化配置編譯。git
另外,咱們還重點改進 vs/vsxmake 兩個vs工程生成器插件,修復了不少細節問題,而且對子工程分組
也作了支持,如今能夠生成相似下圖的工程結構。github
關於 Zig 方面,0.7.1 版本修復了不少我以前反饋的問題,如今 xmake 也已經能夠很好的支持對 zig 項目的編譯。web
同時,咱們還新開發了一個 luarocks=build-xmake 插件去用 xmake 替換 luarocks 內置的構建系統。macos
最後,在這個版本中,咱們繼續改進了 xmake f --menu
圖形化配置菜單,徹底支持鼠標操做和滾動支持,也對 utf8 作了支持。windows
儘管以前的版本,咱們能夠經過 add_requires("libpng", {configs = {shared = true}})
的方式來定義和配置依賴包。xcode
可是,若是用戶項目的工程龐大,依賴包很是多,且每一個包都須要不一樣的編譯配置參數,那麼配置起來仍是會很是繁瑣,而且具備侷限性,好比沒法改寫內部的子依賴包配置。bash
所以,咱們新增了 add_requireconfs
去更靈活方便的配置每一個包的配置以及它的子依賴,下面咱們重點介紹幾種用法:markdown
這是基本用法,好比咱們已經經過 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,增長了對鼠標的支持,以及部分組件的滾動支持,咱們能夠再圖形化配置中,更加靈活方便的配置編譯選項。
以前的版本中,xmake 提供的 os.execv/os.runv 等進程執行接口,僅僅只支持 stdout/stderr 輸出重定向,可是並不支持 stdin 輸入重定向,所以在這個版本中,咱們對其也作了支持。
使用方式以下:
os.execv("foo", {"arg1", "arg2"}, {stdin = "/tmp/a"})
複製代碼
咱們能夠執行進程的時候,將 /tmp/a 文件做爲重定向輸入,固然咱們還能夠傳遞 {stdout = "/tmp/out"}
等做爲重定向輸出。
咱們新增了一個接口 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 設置到二級分組中去。
若是以爲每次經過 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 工程相關的問題,好比:intellisense 提示改進,路徑被截斷的問題修復,全面支持遠程依賴包
xmake 改進了內部的 winos 模塊,新增了一些接口來更加方便的訪問註冊表,獲取 windows 上的註冊表配置。
支持經過模式匹配的方式,遍歷獲取註冊表鍵路徑列表,*
爲單級路徑匹配,**
爲遞歸路徑匹配。
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
複製代碼
支持經過模式匹配的方式,獲取指定鍵路徑的值名列表,;
以後的就是指定的鍵名模式匹配字符串。
local valuepaths = winos.registry_values("HKEY_LOCAL_MACHINE\\SOFTWARE\\xx\\AeDebug;Debug*")
for _, valuepath in ipairs(valuepaths) do
print(winos.registry_query(valuepath))
end
複製代碼
獲取指定註冊表建路徑下的值,若是沒有指定值名,那麼獲取鍵路徑默認值
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")
複製代碼
在上個版本中,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 是 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 規則文件。
很是感謝 @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 下頭文件依賴編譯偶爾失效問題。
add_rules("plugin.vsxmake.autoupdate")
xmake f --vs_runtime=MT
和 set_runtimes("MT")
去更方便的對 target 和 package 進行設置add_requireconfs()
接口去重寫依賴包的配置luarocks.module
構建規則xmake f --menu
增長 utf8 支持set_arch()
設置