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
In the new version, we have added native tool chain support for Hongmeng system and implemented a new native Lua module import support. In addition, we have also made a lot of optimizations to the build speed, and the effect is very obvious.
We have added native toolchain compilation support for the Hongmeng OS platform:
$ xmake f -p harmony
xmake will also automatically detect the default SDK path. Of course, we can also specify the Harmony SDK path.
$ xmake f -p Harmony --sdk=/Users/ruki/Library/Huawei/Sdk/...
We know that in xmake, you can import some lua modules through the import interface for use in the script domain. However, if the operation of some modules is time-consuming, then lua implementation is not an ideal choice. Therefore, in the new version, we have added support for the native lua module, which can be implemented through native to achieve speed-up optimization. Moreover, importing and using the module is as simple as the lua module.
When using native modules, xmake will perform two stages of compilation. First, it will automatically compile the native module, and then import the module into lua as a library or binary. For users, they only need to call import to import.
The advantage of the dynamic library module is that it not only achieves performance acceleration through native, but also avoids the creation of additional sub-processes for each call, making it more lightweight and further improving the speed.
We can first define a dynamic library module, which fully supports all C APIs of Lua, so we can also directly introduce some third-party open source Lua native modules for use.
Here we also have a complete example of importing the lua-cjson module for reference: native_module_cjson
First, we first implement the shared native code, so the interface is exported through the lua API.
./modules/foo/foo.c
#include <xmi.h>
static int c_add(lua_State* lua) {
int a = lua_tointeger(lua, 1);
int b = lua_tointeger(lua, 2);
lua_pushinteger(lua, a + b);
return 1;
}
static int c_sub(lua_State* lua) {
int a = lua_tointeger(lua, 1);
int b = lua_tointeger(lua, 2);
lua_pushinteger(lua, a - b);
return 1;
}
int luaopen(foo, lua_State* lua) {
//Collect add and sub
static const luaL_Reg funcs[] = {
{"add", c_add},
{"sub", c_sub},
{NULL, NULL}
};
lua_newtable(lua);
// pass function list
luaL_setfuncs(lua, funcs, 0);
return 1;
}
Notice here that we have included an interface header file of xmi.h
. In fact, we can also directly introduce lua.h
and luaconf.h
. The effect is the same, but it will provide better cross-platform performance. , it will automatically handle the differences between lua/luajit and versions internally.
Then, we configure add_rules("modules.shared")
to compile as a shared native module without introducing any other dependencies.
Even Lua dependencies do not need to be introduced, because the xmake main program has exported all Lua interfaces and can be used directly, so the entire module is very lightweight.
./modules/foo/xmake.lua
add_rules("mode.debug", "mode.release")
target("foo")
-- Specify the target as the library lua module
add_rules("module.shared")
add_files("foo.c")
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
In the new version, we have added cosmocc tool chain support. Using it, we can compile once and run everywhere. In addition, we also refactored the implementation of C++ Modules and solved many C++ Modules-related problems.
The cosmocc tool chain is the compilation tool chain provided by the cosmopolitan project. Programs compiled using this tool chain can be compiled once and run anywhere.
In the new version, we also support this tool chain, which can compile programs under macosx/linux/windows, and can also support automatic downloading of the cosmocc tool chain.
For users, they only need to configure the xmake.lua project file and then execute the xmake
command to achieve one-click compilation and run it everywhere.
The content of xmake.lua is as follows. This is the most basic construction configuration of the hello world terminal program.
add_rules("mode.debug", "mode.release")
add_requires("cosmocc")
target("test")
set_kind("binary")
add_files("src/*.c")
set_toolchains("@cosmocc")
Then, we execute the xmake command, which will first download the integrated cosmocc tool chain, and then use this tool chain to compile the program.
ruki:console$ xmake
checking for platform... linux
checking for architecture ...x86_64
note: install or modify (m) these packages (pass -y to skip confirm)?
in xmake-repo:
-> cosmocc 3.2.4
please input: y (y/n/m)
=> install cosmocc 3.2.4 .. ok
[25%]: cache compiling.release src/main.c
[50%]: linking.release test
[100%]: build ok, spent 1.548s
ruki:console$ xmake run
hello world
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
Before introducing new features, there is good news to tell you that the previous version of Xmake was included in the debian repository, and recently Xmake has entered the Fedora official repository. You can install Xmake directly on Fedora 39 through the following command.
$ sudo dnf install xmake
Many thanks to @topazus @mochaaP for their contribution to Xmake. For related information, see: #941.
Next, let’s introduce the heavyweight feature brought by the new version: XPack.
It is similar to CMake’s CPack command, which can quickly package user projects to generate installation packages in various formats.
Currently Xmake’s XPack already supports packaging in the following formats:
In addition to the above-mentioned supported packaging formats, package formats such as deb are also being gradually supported, and users can also configure and generate custom package format files.
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
Before introducing new features, we have good news to tell you that Xmake has recently entered Debian’s official repository: https://packages.debian.org/sid/xmake,
When Ubuntu 24.04 is released in April next year, we should be able to quickly install Xmake directly through the apt install xmake
command.
I would also like to thank @Lance Lin for his help. He helped us maintain and upload the Xmake package to the Debian repository throughout the whole process. Thank you very much!
Next, let’s introduce some changes introduced in version 2.8.5. This version brings many new features, especially support for link sorting, link groups, and support for xmake test
built-in unit tests.
In addition, we have also added build support for the Apple XROS platform, which can be used to build programs on Apple’s new VisionOS. We also provide a more flexible and versatile check_sizeof
detection interface for quickly detecting the size of types.
This is a requirement that has existed for more than two years and is mainly used to adjust the link order within the target.
Since xmake provides add_links
, add_deps
, add_packages
, add_options
interfaces, you can configure links in targets, dependencies, packages and options, although the link order of add_links
itself can be adjusted according to the order of addition.
However, the link order between links, deps and packages can only be generated in a fixed order and cannot be adjusted flexibly. This is a bit inadequate for some complex projects.
In this version, we have completely solved this problem and added the add_linkorders
interface, which can be used to configure various link orders introduced by targets, dependencies, packages, options, and link groups.
For more details and background, see: #1452
In order to more flexibly adjust the various link orders within the target, we can implement it through the new interface add_linkorders
, for example:
add_links("a", "b", "c", "d", "e")
-- e -> b -> a
add_linkorders("e", "b", "a")
--e->d
add_linkorders("e", "d")
add_links is the configured initial link order, and then we configure two local link dependencies e -> b -> a
and e -> d
through add_linkorders.
xmake will internally generate a DAG graph based on these configurations, and use topological sorting to generate the final link sequence and provide it to the linker.
Of course, if there is a circular dependency and a cycle is created, it will also provide warning information.
In addition, we can also solve the problem of circular dependencies by configuring link groups through add_linkgroups
.
And add_linkorders
can also sort link groups.
add_links("a", "b", "c", "d", "e")
add_linkgroups("c", "d", {name = "foo", group = true})
add_linkorders("e", "linkgroup::foo")
If we want to sort link groups, we need to give each link group a name, {name = "foo"}
, and then we can reference the configuration through linkgroup::foo
in add_linkorders
.
We can also sort links and frameworks for macOS/iPhoneOS.
add_links("a", "b", "c", "d", "e")
add_frameworks("Foundation", "CoreFoundation")
add_linkorders("e", "framework::CoreFoundation")
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
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.
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.