xmake v2.6.1 發布,使用 Lua5.4 運行時,Rust 和 C++ 混合編譯支持


xmake 是一個基於 Lua 的輕量級跨平台構建工具,使用 xmake.lua 維護項目構建,相比 makefile/CMakeLists.txt,配置語法更加簡潔直觀,對新手非常友好,短時間內就能快速入門,能夠讓用戶把更多的精力集中在實際的項目開發上。

這個版本,我們正式將默認的 Luajit 運行時切換到 Lua5.4 運行時,並且新增了 Rust 和 C++ 的混合編譯支持,我們也集成了 Cargo 的包管理支持。

另外,我們新增了一個實用的 utils.glsl2spv 規則,用於實現對 glsl shader 的編譯支持,並自動生成對應的 C 代碼頭文件,方便快速內嵌編譯后的 .spv 文件數據到代碼中。

新特性介紹

默認切換到 Lua5.4 運行時

歷經幾個版本的迭代測試,我們在 2.6.1 版本,正式切換到 Lua5.4 運行時。

不過,這對於用戶來說是完全無感知的,基本上沒有任何兼容性問題,因為 xmake 對大部分接口都是封裝過的,完全消除了 Lua 版本間的兼容性問題。

對於構建性能方面,由於構建的性能瓶頸主要來自編譯器,Lua 自身的性能損耗完全可以忽略,而且 xmake 用 c 重寫了 lua 原生的所有 io 接口,並且對耗時的接口都用 c 實現了優化。

因此,通過對比測試,不管是使用 Lua 還是 Luajit,構建項目的耗時基本一致,沒有明顯差異。

為什么要切換?

因為 Luajit 對一些新架構基本不支持,例如:riscv, lonngarch,而且 luajit 作者基本已經不怎么維護它了,一些新架構支持和穩定性修復進展屬於停滯狀態。

為了能夠更好的支持更多的平台,已經獲取更快的迭代維護,我們選擇使用 Lua 會帶來非常多的好處。

添加 Cargo 包依賴

我們在這個版本中,新增了 Cargo 包依賴管理器的支持,不過目前主要用於 Rust 項目。

例子: https://github.com/xmake-io/xmake/tree/dev/tests/projects/rust/cargo_deps

add_rules("mode.release", "mode.debug")
add_requires("cargo::base64 0.13.0")
add_requires("cargo::flate2 1.0.17", {configs = {features = "zlib"}})

target("test")
    set_kind("binary")
    add_files("src/main.rs")
    add_packages("cargo::base64", "cargo::flate2")

Rust 和 C++ 混合編譯

使用 cxxbridge 在 c++ 中調用 rust

例子: cxx_call_rust_library

add_rules("mode.debug", "mode.release")

add_requires("cargo::cxx 1.0")

target("foo")
    set_kind("static")
    add_files("src/foo.rs")
    set_values("rust.cratetype", "staticlib")
    add_packages("cargo::cxx")

target("test")
    set_kind("binary")
    add_rules("rust.cxxbridge")
    add_deps("foo")
    add_files("src/main.cc")
    add_files("src/bridge.rsx")

foo.rs

#[cxx::bridge]
mod foo {
    extern "Rust" {
        fn add(a: i32, b: i32) -> i32;
    }
}

pub fn add(a: i32, b: i32) -> i32 {
    return a + b;
}

我們還需要在 c++ 項目中添加橋接文件 bridge.rsx

#[cxx::bridge]
mod foo {
    extern "Rust" {
        fn add(a: i32, b: i32) -> i32;
    }
}

main.cc

#include <stdio.h>
#include "bridge.rs.h"

int main(int argc, char** argv) {
    printf("add(1, 2) == %d\n", add(1, 2));
    return 0;
}

在 Rust 中調用 C++

例子: rust_call_cxx_library

add_rules("mode.debug", "mode.release")

target("foo")
    set_kind("static")
    add_files("src/foo.cc")

target("test")
    set_kind("binary")
    add_deps("foo")
    add_files("src/main.rs")

main.rs

extern "C" {
	fn add(a: i32, b: i32) -> i32;
}

fn main() {
    unsafe {
	    println!("add(1, 2) = {}", add(1, 2));
    }
}

foo.cc

extern "C" int add(int a, int b) {
    return a + b;
}

新增 glsl shader 編譯規則

我們新增了一個 utils.glsl2spv 編譯規則,可以在項目中引入 *.vert/*.frag 等 glsl shader 文件,然后實現自動編譯生成 *.spv 文件。

另外,我們還支持以 C/C++ 頭文件的方式,二進制內嵌 spv 文件數據,方便程序使用。

編譯生成 spv 文件

xmake 會自動調用 glslangValidator 或者 glslc 去編譯 shaders 生成 .spv 文件,然后輸出到指定的 {outputdir = "build"} 目錄下。

add_rules("mode.debug", "mode.release")

add_requires("glslang", {configs = {binaryonly = true}})

target("test")
    set_kind("binary")
    add_rules("utils.glsl2spv", {outputdir = "build"})
    add_files("src/*.c")
    add_files("src/*.vert", "src/*.frag")
    add_packages("glslang")

注,這里的 add_packages("glslang") 主要用於引入和綁定 glslang 包中的 glslangValidator,確保 xmake 總歸能夠使用它。

當然,如果用戶自己系統上已經安裝了它,也可以不用額外綁定這個包,不過我還是建議添加一下。

編譯生成 c/c++ 頭文件

我們也可以內部借助 bin2c 模塊,將編譯后的 spv 文件生成對應的二進制頭文件,方便用戶代碼中直接引入,我們只需要啟用 {bin2c = true}。:w

add_rules("mode.debug", "mode.release")

add_requires("glslang", {configs = {binaryonly = true}})

target("test")
    set_kind("binary")
    add_rules("utils.glsl2spv", {bin2c = true})
    add_files("src/*.c")
    add_files("src/*.vert", "src/*.frag")
    add_packages("glslang")

然后我們可以在代碼這么引入:

static unsigned char g_test_vert_spv_data[] = {
    #include "test.vert.spv.h"
};

static unsigned char g_test_frag_spv_data[] = {
    #include "test.frag.spv.h"
};

跟 bin2c 規則的使用方式類似,完整例子見:glsl2spv example

改進 C++ Modules 構建

上個版本,我們重構了 C++20 Modules 構建支持,而在這個版本中,我們繼續對它做了改進。

對於 msvc 編譯器,我們已經能夠在模塊中導入 std 標准庫模塊,另外,我們修復了多個 target 之間存在依賴時,模塊導入編譯失敗的問題。

改進 MDK 程序構建配置

上個版本,我們新增了 MDK 程序的構建支持,需要注意的是,目前一些 mdk 程序都使用了 microlib 庫運行時,它需要編譯器加上 __MICROLIB 宏定義,鏈接器加上 --library_type=microlib 等各種配置。

而在這個版本中,我們可以通過 set_runtimes("microlib") 直接設置到 microlib 運行時庫,可以自動設置上所有相關選項。

控制台程序

target("hello")
    add_deps("foo")
    add_rules("mdk.console")
    add_files("src/*.c", "src/*.s")
    add_includedirs("src/lib/cmsis")
    set_runtimes("microlib")

靜態庫程序

add_rules("mode.debug", "mode.release")

target("foo")
    add_rules("mdk.static")
    add_files("src/foo/*.c")
    set_runtimes("microlib")

改進 OpenMP 項目配置

我們也改進了 openmp 項目的配置,更加簡化和統一,我們不再需要額外配置 rules,僅僅通過一個通用的 openmp 包就可以實現相同的效果。

add_requires("openmp")
target("loop")
    set_kind("binary")
    add_files("src/*.cpp")
    add_packages("openmp")

在之前的版本,我們需要這么配置,對比一下,就能看出新的配置更加的簡潔。

add_requires("libomp", {optional = true})
target("loop")
    set_kind("binary")
    add_files("src/*.cpp")
    add_rules("c++.openmp")
    add_packages("libomp")

更新內容

新特性

  • #1799: 支持混合 Rust 和 C++ 程序,以及集成 Cargo 依賴庫
  • 添加 utils.glsl2spv 規則去編譯 .vert/.frag shader 文件生成 spirv 文件和二進制 C 頭文件

改進

  • 默認切換到 Lua5.4 運行時
  • #1776: 改進 system::find_package,支持從環境變量中查找系統庫
  • #1786: 改進 apt:find_package,支持查找 alias 包
  • #1819: 添加預編譯頭到 cmake 生成器
  • 改進 C++20 Modules 為 msvc 支持 std 標准庫
  • #1792: 添加自定義命令到 vs 工程生成器
  • #1835: 改進 MDK 程序構建支持,增加 set_runtimes("microlib")
  • #1858: 改進構建 c++20 modules,修復跨 target 構建問題
  • 添加 $XMAKE_BINARY_REPO 和 $XMAKE_MAIN_REPO 倉庫設置環境變量
  • #1865: 改進 openmp 工程
  • #1845: 為靜態庫安裝 pdb 文件

Bugs 修復

  • 修復語義版本中解析帶有 0 前綴的 build 字符串問題
  • #50: 修復 rule 和構建 bpf 程序 bug
  • #1610: 修復 xmake f --menu 在 vscode 終端下按鍵無響應,並且支持 ConPTY 終端虛擬按鍵


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM