Xmake is a lightweight cross-platform build utility based on Lua.
It is very lightweight and has no dependencies because it has a built-in Lua runtime.
It uses xmake.lua to maintain project builds and its configuration syntax is very simple and readable.
We can use it to build project directly like Make/Ninja, or generate project files like CMake/Meson, and it also has a built-in package management system to help users solve the integrated use of C/C++ dependent libraries.
Xmake = Build backend + Project Generator + Package Manager + [Remote|Distributed] Build + Cache
Although not very precise, we can still understand Xmake in the following way:
Xmake ≈ Make/Ninja + CMake/Meson + Vcpkg/Conan + distcc + ccache/sccache
Introduction of new features
In the new version, we have added breakpoint debugging support for Xmake’s own source code, which can help contributors to get familiar with xmake’s source code more quickly, and also help users to debug and analyse their own project’s configure scripts.
In addition, the number of packages in our xmake-repo repository is about to exceed 1100, with more than 100 packages added in just one month, thanks to @star-hengxing’s contribution.
At the same time, we focused on improving build support for Wasm and Qt6 for wasm.
Breakpoint Debugging Xmake
In version 2.8.3, we added Lua breakpoint debugging support, with VSCode-EmmyLua plugin, we can easily debug Xmake source code in VSCode breakpoints.
First of all, we need to install VSCode-EmmyLua plugin in VSCode’s plugin market, and then run the following command to update the xmake-repo repository to keep it up-to-date.
$ xrepo update-repo
!> Xmake also needs to be kept up to date.
Then, execute the following command in your own project directory:
$ xrepo env -b emmylua_debugger -- xmake build
The xrepo env -b emmylua_debugger
is used to bind the EmmyLua debugger plugin environment, and the arguments after --
are the actual xmake commands we need to debug.
Usually we just debug the xmake build
build, but if you want to debug other commands, you can tweak it yourself, for example, if you want to debug the xmake install -o /tmp
install command, you can change it to:
$ xrepo env -b emmylua_debugger -- xmake install -o /tmp
After executing the above command, it will not exit immediately, it will remain in a waiting debugging state, possibly without any output.
At this point, instead of exiting it, let’s go ahead and open VSCode and open Xmake’s Lua script source directory in VSCode.
That is, this directory: Xmake Lua Scripts, which we can download locally or directly open the lua script directory in the Xmake installation directory.
Then switch to VSCode’s debugging tab and click RunDebug
-> Emmylua New Debug
to connect to our xmake build
command debugger and start debugging.
As you can see below, the default start breakpoint will automatically break inside debugger:_start_emmylua_debugger
, and we can click on the single-step to jump out of the current function, which will take us to the main entry.
Then set your own breakpoint and click Continue to Run to break to the code location you want to debug.
We can also set breakpoints in our project’s configuration scripts, which also allows us to quickly debug our own configuration scripts, not just Xmake’s own source code.
Remote debugging xmake
Version 2.8.3 now supports remote debugging, but this feature is mainly for the author, because the author’s development computer is a mac, but sometimes he still needs to be able to debug xmake source scripts on windows.
But debugging in a virtual machine is too laggy, not good experience, and the author’s own computer does not have enough disk space, so I usually connect to a separate windows host to debug xmake source code remotely.
Let’s start the remote compilation service on the windows machine:
$ xmake service
Then locally, open the project directory where you want to build, make a remote connection, and then run xmake service --sync --xmakesrc=
to synchronise the local source:
$ xmake service --connect
$ xmake service --sync --xmakesrc=~/projects/personal/xmake/xmake/
$ xmake build
$ xmake run
This way, we can modify the xmake script source locally, sync it to a remote windows machine, and then execute the xmake build command remotely to get the corresponding debug output and analyse the build behaviour.
We can also pull the remote files back to the local machine for analysis with the xmake service --pull=
command.
Note: See Remote Build Documentation for a detailed description of remote build features.
Support for Cppfront programmes
We have also added a new build rule to support the compilation of cppfront programs:
add_rules("mode.debug", "mode.release")
add_requires("cppfront")
target("test")
add_rules("cppfront")
set_kind("binary")
add_files("src/*.cpp2")
add_packages("cppfront")
Added utils.hlsl2spv build rule
We’ve already provided the utils.glsl2spv
rule to support the compilation and use of glsl, but now we’ve added the utils.hlsl2spv
rule to support the compilation of hlsl.
add_rules("mode.debug", "mode.release")
add_requires("glslang", {configs = {binaryonly = true}})
target("test")
set_kind("binary")
add_rules("utils.hlsl2spv", {bin2c = true})
add_files("src/*.c")
add_files("src/*.hlsl", "src/*.hlsl")
add_packages("directxshadercompiler")
For a detailed description of this rule, see the documentation: utils.glsl2spv, both are used in a similar way and principle.
Add lib.lua.package module.
Xmake restricts access to native lua modules and interfaces by default, and this module is mainly used to open up some of the APIs provided by lua to be used on demand.
Currently, it only provides the package.loadlib
interface for loading lua modules from the native so/dylib/dll dynamic library.
This is typically used in high-performance scenarios.
import("lib.lub.package")
local script = package.loadlib("/xxx/libfoo.so", "luaopen_mymodule")
local mymodule = script()
mymodule.hello()
Improved Address sanitizer support
Address Sanitizer (ASan) is a fast memory error detection tool that is built-in by the compiler, and normally we need to configure -fsanitize-address
in both compilation and linking flags to enable it properly.
In previous versions, we supported this by configuring add_rules("mode.asan")
and then xmake f -m asan
to switch build modes.
But there are a few problems with this:
- it doesn’t work on dependent packages
- you need to switch build modes
- asan and ubsan cannot be detected at the same time.
Therefore, in the new version, we have switched to using policy to support them better.
We can quickly enable it globally by turning on the build.sanitizer.address
policy, which will enable compiled applications to support ASan detection directly.
For example, we can enable it from the command line:
$ xmake f --policies=build.sanitizer.address
It can also be enabled globally via the interface configuration:
set_policy("build.sanitizer.address", true)
Of course, we can also enable it for a specific target individually, and if we configure it globally, we can enable it for all dependent packages at the same time.
set_policy("build.sanitizer.address", true)
add_requires("zlib")
add_requires("libpng")
It is equivalent to setting the asan configuration for each package in turn.
add_requires("zlib", {configs = {asan = true}})
add_requires("libpng", {configs = {asan = true}})
Alternatively, we can have multiple sanitizer detections in effect at the same time, for example:
set_policy("build.sanitizer.address", true)
set_policy("build.sanitizer.undefined", true)
or
$ xmake f --policies=build.sanitizer.address,build.sanitizer.undefined
In addition to Asan, we provide other similar policies for detecting threads, memory leaks, and so on.
- build.sanitizer.thread
- build.sanitizer.memory
- build.sanitizer.leak
- build.sanitizer.undefined
Autobuild before running
We have added a new run.atuobuild
policy to adjust the behaviour of xmake run
. By default, running xmake run
does not automatically build the target application, but prompts the user to build it manually if the application has not yet been compiled.
By turning on this policy, we can automatically build the target program before running it.
$ xmake f --policies=run.autobuild
$ xmake run
If you want this policy to take effect globally, you can turn it on globally.
$ xmake g --policies=run.autobuild
Shallow build of a specified target
When we specify to rebuild a target, if it has a lot of dependent targets, then they are usually all rebuilt.
$ xmake --rebuild foo
rebuild foo
rebuild foo.dep1
rebuild foo.dep2
...
This can be very slow for large projects with a lot of target dependencies, and can mean that half of the project has to be rebuilt.
In the new version, we’ve added a --shallow
parameter to tell Xmake to only rebuild the specified target, and not to rebuild all of its dependencies.
$ xmake --rebuild --shallow foo
only rebuild foo
Improved warning settings
The set_warnings
interface has new extra
and pedantic
settings and supports combining multiple warning values.
set_warnings("all", "extra")
set_warnings("pedantic")
Improving Wasm Builds
Now we can pull the emscripten toolchain ourselves and use it to build wasm programs automatically with the following configuration.
if is_plat("wasm") then
add_requires("emscripten")
set_toolchains("emcc@emscripten")
end
Simply just run
$ xmake f -p wasm
$ xmake
to build the wasm application, so you don’t have to manually install emscripten yourself, which is much more convenient.
We also have good support for Qt6 for wasm.
Changelog
New features
- #4122: Support Lua Debugger (EmmyLua)
- #4132: Support cppfront
- #4147: Add hlsl2spv rule
- #4226: Support sanitizers for package and policy
- Add lib.lua.package module
- Add
run.autobuild
policy - Add global policies
xmake g --policies=
Changes
- #4119: Improve to support emcc toolchain and emscripten package
- #4154: Add
xmake -r --shallow target
to rebuild target without deps - Add global ccache storage directory
- #4137: Support Qt6 for Wasm
- #4173: Add recheck argument to on_config
- #4200: Improve remote build to support debugging xmake source code.
- #4209: Add extra and pedantic warnings