Skip to content

xmake v2.6.1 released, Switch to Lua5.4 runtime, Support Rust and Cplusplus mixed compilation

ruki edited this page Dec 3, 2021 · 2 revisions

Xmake is a lightweight cross-platform build tool based on Lua. It uses xmake.lua to maintain project builds. Compared with makefile/CMakeLists.txt, the configuration syntax is more Concise and intuitive, it is very friendly to novices, and you can get started quickly in a short time, allowing users to focus more on actual project development.

In this version, we have added a lot of heavyweight new features, such as: Nim language project build support, Keil MDK, Circle and Wasi toolchain support.

In addition, we have made major improvements to C++20 Modules, not only supporting the latest gcc-11, clang and msvc compilers, but also automatic analysis of inter-module dependencies to achieve maximum parallel compilation support.

Finally, there is a more useful feature that is Unity Build support, through which we can greatly improve the compilation speed of C++ code.

New feature introduction

Switch to Lua5.4 runtime by default

After several versions of iterative testing, we officially switched to the Lua5.4 runtime in version 2.6.1.

However, this is completely unaware to users, and basically there is no compatibility problem, because xmake encapsulates most of the interfaces, which completely eliminates the compatibility problem between Lua versions.

In terms of build performance, because the performance bottleneck of the build mainly comes from the compiler, the performance loss of Lua itself is completely negligible, and xmake rewrites all lua native io interfaces with c, and optimizes the time-consuming interfaces with c .

Therefore, through comparative tests, whether it is using Lua or Luajit, the time-consuming to build the project is basically the same, and there is no significant difference.

Why switch?

Because Luajit basically does not support some new architectures, such as: riscv, lonngarch, and the author of luajit has basically not maintained it, some new architecture support and stability repair progress is in a stagnant state.

In order to be able to better support more platforms and have obtained faster iterative maintenance, we choose to use Lua will bring many benefits.

Add Cargo package dependency

In this version, we have added support for the Cargo package dependency manager, but it is currently mainly used in Rust projects.

Example: 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 and C++ mixed compilation

Use cxxbridge to call rust in c++

Example: 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;
}

We also need to add the bridge file bridge.rsx to the c++ project

#[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;
}

Calling C++ in Rust

Example: 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;
}

Added glsl shader compilation rules

We have added a new compilation rule of utils.glsl2spv, which can introduce glsl shader files such as *.vert/*.frag into the project, and then realize automatic compilation to generate *.spv files.

In addition, we also support binary embedding spv file data in the form of C/C++ header file, which is convenient for program use.

Compile and generate spv file

xmake will automatically call glslangValidator or glslc to compile shaders to generate .spv files, and then output them to the specified {outputdir = "build"} directory.

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")

Note that the add_packages("glslang") here is mainly used to import and bind the glslangValidator in the glslang package to ensure that xmake can always use it.

Of course, if you have already installed it on your own system, you don’t need to bind this package additionally, but I still recommend adding it.

Compile and generate c/c++ header files

We can also use the bin2c module internally to generate the corresponding binary header file from the compiled spv file, which is convenient for direct import in user code. We only need to enable {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")

Then we can introduce in the code like this:

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"
};

Similar to the usage of bin2c rules, see the complete example: glsl2spv example

Improve C++ Modules construction

In the last version, we refactored the C++20 Modules build support, and in this version, we continue to improve it.

For the msvc compiler, we have been able to import the std standard library module in the module. In addition, we have fixed the problem that the module import compilation fails when there are dependencies between multiple targets.

Improve MDK program build configuration

In the last version, we added support for building MDK programs. It should be noted that when some mdk programs currently use the microlib library to run, it requires the compiler to add the __MICROLIB macro definition, and the linker to add -- library_type=microlib and other configurations.

In this version, we can directly set to the microlib runtime library through set_runtimes("microlib"), and all relevant options can be set automatically.

Console Program

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

Static library program

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

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

Improve OpenMP project configuration

We have also improved the configuration of the openmp project, which is more simplified and unified. We no longer need to configure additional rules. The same effect can be achieved only through a common openmp package.

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

In the previous version, we need to configure this way, and by comparison, we can see that the new configuration is more concise.

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

Changelog

New features

  • #1799: Support mixed rust & c++ target and cargo dependences
  • Add utils.glsl2spv rules to compile .vert/.frag shader files to spirv file and binary c header file

Changes

  • Switch to Lua5.4 runtime by default
  • #1776: Improve system::find_package, support to find package from envs
  • #1786: Improve apt:find_package, support to find alias package
  • #1819: Add precompiled header to cmake generator
  • Improve C++20 module to support std libraries for msvc
  • #1792: Add custom command in vs project generator
  • #1835: Improve MDK program supports and add set_runtimes("microlib")
  • #1858: Improve to build c++20 modules with libraries
  • Add $XMAKE_BINARY_REPO and $XMAKE_MAIN_REPO repositories envs
  • #1865: Improve openmp projects
  • #1845: Install pdb files for static library

Bugs Fixed

  • Fix semver to parse build string with zero prefix
  • #50: Fix rule and build bpf program errors
  • #1610: Fix xmake f --menu not responding in vscode and support ConPTY terminal virtkeys
Clone this wiki locally