Xmake is a lightweight cross-platform build tool based on Lua. We have done a detailed introduction to Xmake and build system in previous articles. Introduction: C/C++ build system, I use xmake.
If you already have a general understanding of Xmake, you will know that it is not only a build tool, but also has built-in support for C/C++ package management. We can also understand Xmake as:
Xmake = Build backend + Project Generator + Package Manager
After several years of continuous iteration, Xmake’s support for C/C++ package management has been continuously improved, and many useful package management features have been added. Therefore, in this article, we will make some summaries on it, hoping to help everyone.
The ecology of C++ is very complex, and there are certain historical reasons for this. In any case, the official does not provide native package management support. For our developers, it is somewhat inconvenient to use third-party C++ dependent libraries.
In fact, there are already many powerful C/C++ package managers, the most well-known and most used are: vcpkg, conan, conda, etc. Although they are very powerful, they have a common problem: The build system doesn’t have built-in support for them.
Since CMake does not provide built-in support for them, it is very cumbersome to use them in CMake to integrate dependencies, and the way of integration and use is inconsistent.
To use conan to integrate C/C++ packages in CMake, we need to provide additional CMake Wrapper scripts and inject them into our own projects in a similar way as plug-ins.
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
Now, we can inherit all the configuration of an existing package through the set_base
interface, and then rewrite part of the configuration on this basis.
This is usually in the user’s own project, it is more useful to modify the built-in package of the official repository of xmake-repo, such as: repairing and changing urls, modifying the version list, Install logic and more.
For example, modify the url of the built-in zlib package to switch to your own zlib source address.
package("myzlib")
set_base("zlib")
set_urls("https://github.com/madler/zlib.git")
package_end()
add_requires("myzlib", {system = false, alias = "zlib"})
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("zlib")
We can also use it to simply add an alias package.
package("onetbb")
set_base("tbb")
We can install the tbb package through add_requires("onetbb")
integration, but the package name is different.
Previously, we limited the toolchains that can only be installed under the cross platform to switch packages. In the new version, we can support the switchover of toolchains under more platforms.
E.g:
$ xrepo install --toolchains=clang zlib
We can quickly switch to the clang toolchain to compile and install the zlib library on platforms such as linux.
We can also switch them in the xmake.lua configuration file.
add_requires("zlib", {configs = {toolchains = "gcc-11"}})
The zlib packages installed by different tool chains will be stored in different directories without interfering with each other, and there will be no link compatibility problems caused by compiler differences.
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
This version mainly adds the following features:
The rest are mainly some scattered functional improvements and Bugs fixes. You can see the details of the update at the end of the following. Some major changes will be explained one by one below.
In the new version, Xmake adds vcpkg manifest mode support, through which we can support the version selection of vcpkg package, for example:
add_requires("vcpkg::zlib 1.2.11+10")
add_requires("vcpkg::fmt >=8.0.1", {configs = {baseline = "50fd3d9957195575849a49fa591e645f1d8e7156"}})
add_requires("vcpkg::libpng", {configs = {features = {"apng"}}})
target("test")
set_kind("binary")
add_files("src/*.cpp")
add_packages("vcpkg::zlib", "vcpkg::fmt", "vcpkg::libpng")
However, the version selection of vcpkg is still quite limited. It must be hard-coded to specify the baseline, and version semantic selection such as <=1.0
, 1.x
is not supported, but it is better than the previous version that cannot be selected.
CMake wrapper for Xrepo C and C++ package manager.
This allows using CMake to build your project, while using Xrepo to manage dependent packages. This project is partially inspired by cmake-conan.
Example use cases for this project:
Xrepo official repository: xmake-repo
xrepo.cmake provides xrepo_package
function to manage packages.
xrepo_package(
"foo 1.2.3"
[CONFIGS feature1=true,feature2=false]
[MODE debug|release]
[OUTPUT verbose|diagnosis|quiet]
[DIRECTORY_SCOPE]
)
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
There are two major new features in this version:
Run all tests
The rest are mainly scattered function improvements and bugs fixes. You can see the details of the update content at the end of the following. Some of the larger changes will be explained one by one below.
Xmake may be the first third-party build tool that provides built-in support for Linux kernel driver development.
Although there are also instructions on how CMake configures and builds Linux drivers on the Internet, most of them use add_custom_command
to customize various commands, and then execute echo
to splice and generate Linux Makefile files by themselves.
In other words, it is actually a build that relies on the Makefile of the Linux kernel source code to execute, so if you want to add some compilation configuration and macro definitions yourself, it will be very troublesome.
With Xmake, we can provide more flexible configurability, simpler configuration files, and features such as one-click compilation, automatic dependency pull integration, automatic download and integration of Linux kernel source code, and cross-compilation of kernel drivers.
We intuitively feel it through one of the simplest character drivers.
First, we prepare a Hello World driver code, for example:
add_requires("linux-headers", {configs = {driver_modules = true}})
target("hello")
add_rules("platform.linux.driver")
add_files("src/*.c")
add_packages("linux-headers")
set_license("GPL-2.0")
Its configuration is very simple. You only need to configure the linux-headers package that supports the module, and then apply the platform.linux.driver
build rule.
Then directly execute the xmake command, compile with one key, and generate the kernel driver module hello.ko.
$ xmake
[20%]: ccache compiling.release src/add.c
[20%]: ccache compiling.release src/hello.c
[60%]: linking.release build/linux/x86_64/release/hello.ko
[100%]: build ok!
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.
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.
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.
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")
Example: cxx_call_rust_library