Xmake v2.7.6 釋出,新增 Verilog 和 C++ Modules 分發支援

2023-01-27 21:06:24

Xmake 是一個基於 Lua 的輕量級跨平臺構建工具。

它非常的輕量,沒有任何依賴,因為它內建了 Lua 執行時。

它使用 xmake.lua 維護專案構建,相比 makefile/CMakeLists.txt,設定語法更加簡潔直觀,對新手非常友好,短時間內就能快速入門,能夠讓使用者把更多的精力集中在實際的專案開發上。

我們能夠使用它像 Make/Ninja 那樣可以直接編譯專案,也可以像 CMake/Meson 那樣生成工程檔案,另外它還有內建的包管理系統來幫助使用者解決 C/C++ 依賴庫的整合使用問題。

目前,Xmake 主要用於 C/C++ 專案的構建,但是同時也支援其他 native 語言的構建,可以實現跟 C/C++ 進行混合編譯,同時編譯速度也是非常的快,可以跟 Ninja 持平。

Xmake = Build backend + Project Generator + Package Manager + [Remote|Distributed] Build + Cache

儘管不是很準確,但我們還是可以把 Xmake 按下面的方式來理解:

Xmake ≈ Make/Ninja + CMake/Meson + Vcpkg/Conan + distcc + ccache/sccache

新特性介紹

Verilog 模擬程式支援

iVerilog 模擬器

通過 add_requires("iverilog") 設定,我們能夠自動拉取 iverilog 工具鏈包,然後使用 set_toolchains("@iverilog") 自動繫結工具鏈來編譯工程。

add_requires("iverilog")
target("hello")
    add_rules("iverilog.binary")
    set_toolchains("@iverilog")
    add_files("src/*.v")
設定抽象設定
add_requires("iverilog")
target("hello")
    add_rules("iverilog.binary")
    set_toolchains("@iverilog")
    add_files("src/*.v")
    add_defines("TEST")
    add_includedirs("inc")
    set_languages("v1800-2009")

我們可以通過 set_languages("v1800-2009") 來設定切換 Verilog 的語言標準。

目前支援的一些取值和對映關係如下:

["v1364-1995"] = "-g1995"
["v1364-2001"] = "-g2001"
["v1364-2005"] = "-g2005"
["v1800-2005"] = "-g2005-sv"
["v1800-2009"] = "-g2009"
["v1800-2012"] = "-g2012"
設定自定義 flags
add_requires("iverilog")
target("hello")
    add_rules("iverilog.binary")
    set_toolchains("@iverilog")
    add_files("src/*.v")
    add_values("iverilogs.flags", "-DTEST")
構建工程
$ xmake
checking for iverilog ... iverilog
checking for vvp ... vvp
[ 50%]: linking.iverilog hello.vvp
[100%]: build ok!
執行程式
$ xmake run
hello world!
LXT2 info: dumpfile hello.vcd opened for output.
src/main.v:6: $finish called at 0 (1s)

更多完整例子:iVerilog Examples

Verilator 模擬器

通過 add_requires("verilator") 設定,我們能夠自動拉取 verilator 工具鏈包,然後使用 set_toolchains("@verilator") 自動繫結到工具鏈來編譯工程。

add_requires("verilator")
target("hello")
    add_rules("verilator.binary")
    set_toolchains("@verilator")
    add_files("src/*.v")
    add_files("src/*.cpp")

verilator 工程,我們需要一個額外的 sim_main.cpp 檔案參與編譯,作為程式的入口程式碼。

#include "hello.h"
#include "verilated.h"

int main(int argc, char** argv) {
    VerilatedContext* contextp = new VerilatedContext;
    contextp->commandArgs(argc, argv);
    hello* top = new hello{contextp};
    while (!contextp->gotFinish()) { top->eval(); }
    delete top;
    delete contextp;
    return 0;
}
設定抽象設定
add_requires("verilator")
target("hello")
    add_rules("verilator.binary")
    set_toolchains("@verilator")
    add_files("src/*.v")
    add_defines("TEST")
    add_includedirs("inc")
    set_languages("v1800-2009")

我們可以通過 set_languages("v1800-2009") 來設定切換 Verilog 的語言標準。

目前支援的一些取值和對映關係如下:

-- Verilog
["v1364-1995"] = "+1364-1995ext+v",
["v1364-2001"] = "+1364-2001ext+v",
["v1364-2005"] = "+1364-2005ext+v",
-- SystemVerilog
["v1800-2005"] = "+1800-2005ext+v",
["v1800-2009"] = "+1800-2009ext+v",
["v1800-2012"] = "+1800-2012ext+v",
["v1800-2017"] = "+1800-2017ext+v",
設定自定義 flags
add_requires("verilator")
target("hello")
    add_rules("verilator.binary")
    set_toolchains("@verilator")
    add_files("src/*.v")
    add_files("src/*.cpp")
    add_values("verilator.flags", "--trace", "--timing")
構建工程
$ xmake
[  0%]: compiling.verilog src/main.v
[ 15%]: cache compiling.release /Users/ruki/.xmake/packages/v/verilator/2023.1.10/cd2268409c1d44799288c7759b3cbd56/share/verilator/include/verilated.cpp
[ 15%]: cache compiling.release build/.gens/hello/macosx/x86_64/release/rules/verilator/hello___024root__Slow.cpp
[ 15%]: cache compiling.release build/.gens/hello/macosx/x86_64/release/rules/verilator/hello___024root__DepSet_h9053a130__0__Slow.cpp
[ 15%]: cache compiling.release build/.gens/hello/macosx/x86_64/release/rules/verilator/hello.cpp
[ 15%]: cache compiling.release /Users/ruki/.xmake/packages/v/verilator/2023.1.10/cd2268409c1d44799288c7759b3cbd56/share/verilator/include/verilated_threads.cpp
[ 15%]: cache compiling.release build/.gens/hello/macosx/x86_64/release/rules/verilator/hello__Syms.cpp
[ 15%]: cache compiling.release build/.gens/hello/macosx/x86_64/release/rules/verilator/hello___024root__DepSet_h07139e86__0.cpp
[ 15%]: cache compiling.release src/sim_main.cpp
[ 15%]: cache compiling.release build/.gens/hello/macosx/x86_64/release/rules/verilator/hello___024root__DepSet_h9053a130__0.cpp
[ 84%]: linking.release hello
[100%]: build ok!
執行程式
$ xmake run
ruki-2:hello ruki$ xmake run
hello world!
- src/main.v:4: Verilog $finish

更多完整例子:Verilator

支援 C++ Module 分發

非常感謝 Arthapz 在新版本中繼續幫忙改進了 xmake 對 C++ Modules 的支援。

現在,我們可以將 C++ Modules 做成包進行分發,然後在其他專案中進行快速整合和複用。

它是基於 p2473r1 中對模組分發的設計草案做的一個原型實現。

製作分發 C++ Modules 包

我們先使用 xmake.lua 維護模組的構建,並通過指定 {install = true},來告訴 xmake 哪些模組檔案需要安裝對外分發。

add_rules("mode.release", "mode.debug")
set_languages("c++20")

target("foo")
    set_kind("static")
    add_files("*.cpp")
    add_files("*.mpp", { install = true })

然後,我們把它做成包,可以提交到 xmake-repo 倉庫,當然也可以直接做成本地包,或者私有倉庫包。

這裡,為了方便測試驗證,我們僅僅通過 set_sourcedir 將它做成本地包。

package("foo")
    set_sourcedir(path.join(os.scriptdir(), "src"))
    on_install(function(package)
        import("package.tools.xmake").install(package, {})
    end)

整合 C++ Modules 包

然後,我們通過 add_requires("foo") 的包整合介面,對 C++ Modules 包進行快速整合使用。

由於 foo 的模組包,我們放在私有倉庫中定義,所以我們通過 add_repositories("my-repo my-repo") 引入自己的包倉庫。

如果,包已經提交到 xmake-repo 官方倉庫,就不需要額外設定它。

add_rules("mode.release", "mode.debug")
set_languages("c++20")

add_repositories("my-repo my-repo")
add_requires("foo", "bar")

target("packages")
    set_kind("binary")
    add_files("src/*.cpp")
    add_packages("foo", "bar")
    set_policy("build.c++.modules", true)

整合好包後,我們就可以執行 xmake 命令,一鍵下載、編譯、整合 C++ Modules 包來使用。

$ xmake
checking for platform ... linux
checking for architecture ... x86_64
note: install or modify (m) these packages (pass -y to skip confirm)?
in my-repo:
  -> foo latest
  -> bar latest
please input: y (y/n/m)

  => install bar latest .. ok
  => install foo latest .. ok
[  0%]: generating.module.deps src/main.cpp
[  0%]: generating.module.deps /mnt/xmake/tests/projects/c++/modules/packages/build/.packages/b/bar/latest/4e0143c97b65425b855ad5fd03038b6a/modules/bar/bar.mpp
[  0%]: generating.module.deps /mnt/xmake/tests/projects/c++/modules/packages/build/.packages/f/foo/latest/4e0143c97b65425b855ad5fd03038b6a/modules/foo/foo.mpp
[ 14%]: compiling.module.release bar
[ 14%]: compiling.module.release foo
[ 57%]: compiling.release src/main.cpp
[ 71%]: linking.release packages
[100%]: build ok!

注:每個包安裝後,會在包路徑下,儲存維護模組的 meta-info 檔案,這是 p2473r1.pdf 中約定的一種格式規範,也許它不是最終的標準,但這並不影響我們現在去使用模組的分發。

$ cat ./build/.packages/f/foo/latest/4e0143c97b65425b855ad5fd03038b6a/modules/foo/foo.mpp.meta-info
{"_VENDOR_extension":{"xmake":{"name":"foo","file":"foo.mpp"}},"definitions":{},"include_paths":{}}

完整的例子工程見:C++ Modules 包分發例子工程

支援 C++23 Std Modules

Arthapz 也幫忙改進了對 C++23 Std Modules 的支援。

目前三個編譯器對它的支援進展:

Msvc

最新 Visual Studio 17.5 preview 已經支援,並且非標準的 ifc std modules 將被廢棄。

對於標準的 C++23 std modules,我們是這麼引入的。

import std;

而對於 ifc std modules,我們需要這麼寫:

import std.core;

它不是 C++23 標準,僅僅 msvc 提供,對其他編譯器並不相容,以後新版本 msvc 中也會逐步廢棄。
因此新版本 Xmake 將僅僅 C++23 std modules,不再支援廢棄的 ifc std modules。

Clang

目前最新的 clang 似乎也還沒完全支援 C++23 std modules,當前還是 draft patch 狀態,#D135507

但是,Xmake 也對它進行了支援,如果大家想要嚐鮮,可以自行合入這個 patch,然後使用 xmake 來測試。

另外,低版本的 clang 也有對非標準的 std modules 做了實驗性支援。

我們還是可以在低版本 clang 中嘗試性使用 xmake 來構建 std modules,儘管它可能還只是個玩具(會遇到很多問題)。

相關討論見:#3255

Gcc

目前還不支援。

Xrepo 自動補全支援

之前,我們僅僅支援 xmake 命令的不全,新版本中,我們還支援了 xrepo install 命令的不全,
可以自動搜尋 xmake-repo 倉庫的包,來不全我們的安裝命令。

非常感謝 @glcraft 的貢獻。

$ xrepo install libp
libpaper          libpfm            libpng            libpqxx           libpthread-stubs
libpcap           libplist          libpq             libpsl

更新內容

新特性

  • #3228: C++ modules 的安裝釋出,以及從包中匯入 C++ modules 支援
  • #3257: 增加對 iverilog 和 verilator 的支援
  • 支援 xp 和 vc6.0
  • #3214: xrepo install 的自動補全支援

改進

  • #3255: 改進 clang libc++ 模組支援
  • 支援使用 mingw 編譯 xmake
  • 改進 xmake 在 win xp 上的相容性
  • 如果外部依賴被啟用,切換 json 模組到純 lua 實現,移除對 lua-cjson 的依賴

Bugs 修復

  • #3229: 修復 vs2015 下找不到 rc.exe 問題
  • #3271: 修復支援帶有空格的宏定義
  • #3273: 修復 nim 連結錯誤
  • #3286: 修復 compile_commands 對 clangd 的支援