Xmake v3.1.0 Released, Plugin Distribution and Binary Asset Transform
In this release, we reworked the xmake plugin manager. Plugins can now be installed from repositories such as xmake-repo just like packages, and also from git urls and local directories, with a unified listing of built-in, installed and available plugins.
Additionally, we added check_alignof / configvar_check_alignof type alignment detection, a transform config for the utils.bin2c / utils.bin2obj rules to preprocess embedded binary assets, a new batchcmds:call interface, unified --format=json output for xmake show, multiple target names for build / clean / install and friends, builtin-variable expansion in xpack install file lists, and gcc-16 toolchain support.
New Features
Reworked Plugin Manager and Repository Distribution
Distributing an xmake plugin used to mean asking users to copy the plugin directory into ~/.xmake/plugins/ by hand, or to clone the repository themselves. In this release we rewrote the xmake plugin command: installing, removing and listing plugins now all go through a single entry point, and the installation reuses xmake's package installation flow.
Installing plugins from repositories
Plugins are described as packages in a repository, using the same directory layout as packages, i.e. <repodir>/plugins/<first-letter>/<name>/xmake.lua:
-- plugins/h/hello/xmake.lua
package("hello")
set_kind("plugin")
set_description("say hello from hello")
set_sourcedir(path.join(os.scriptdir(), "src"))The src directory holds the plugin implementation itself, i.e. the familiar xmake.lua + main.lua pair:
-- plugins/h/hello/src/xmake.lua
task("hello")
set_category("plugin")
on_run("main")
set_menu {usage = "xmake hello", description = "say hello"}-- plugins/h/hello/src/main.lua
function main()
print("hello xmake!")
endFor plugins whose sources live directly in the repository, on_install can be omitted — xmake copies the plugin directory into ~/.xmake/plugins/<name> by default. And since a plugin is really just a package of the plugin kind, it also gets all the usual package capabilities: add_urls, add_versions, add_deps, custom on_install / on_test, and so on.
To install, just pass the plugin name and xmake will look it up across all configured repositories:
$ xmake plugin --install helloOr specify explicitly which repository to install from:
$ xmake plugin --install xmake-repo@helloInstalling from git urls and local directories
Besides repositories, --install also accepts git urls, with a github: shortcut and an optional #branch suffix:
$ xmake plugin --install https://github.com/myrepo/hello-world
$ xmake plugin --install github:myrepo/hello-world
$ xmake plugin --install github:myrepo/hello-world#devAnd when developing a plugin locally, just pass its directory:
$ xmake plugin --install /tmp/my-pluginListing, removing and clearing
xmake plugin --list now groups built-in plugins, installed plugins, and plugins that are available in repositories but not installed yet, each with its description:
$ xmake plugin --list
the built-in plugins:
project Generate the project file.
pack Pack binary installation packages.
...
the installed plugins:
hello say hello from hello
available in configured repositories:
world say hello from world (run xmake plugin --install world to install)Removing and clearing:
$ xmake plugin --remove hello
$ xmake plugin --clearalignof Type Alignment Detection
We added two new detection interfaces, check_alignof and configvar_check_alignof, to probe the alignment of a given type on the target platform. They work exactly like the existing check_sizeof.
includes("@builtin/check")
target("test")
set_kind("binary")
add_files("src/*.c")
check_alignof("LONG_ALIGN", "long")
check_alignof("STRING_ALIGN", "std::string", {includes = "string"})This defines macros such as LONG_ALIGN=8. To write the result into config.h instead, use configvar_check_alignof:
target("test")
set_kind("binary")
add_files("src/*.c")
add_configfiles("config.h.in")
configvar_check_alignof("ALIGNOF_LONG", "long")// config.h.in
#define ALIGNOF_LONG ${ALIGNOF_LONG}Internally the check snippet picks alignof / _Alignof / __alignof / __alignof__ based on the compiler and language standard, so pre-C11 C code and MSVC work as well. The result is extracted from a marker string embedded in the compiled artifact rather than by running the program, so it also works when cross-compiling.
Binary Asset Transform for bin2c / bin2obj
The utils.bin2c and utils.bin2obj rules gained a transform config, which lets you preprocess the content of a binary file before it is embedded into the program — to compress, encrypt or obfuscate it, for example.
add_rules("mode.debug", "mode.release")
target("test")
set_kind("binary")
add_rules("utils.bin2c")
add_files("src/*.c")
add_files("src/asset.bin", {transform = function (inputfile, outputfile, opt)
local data = io.readfile(inputfile, {encoding = "binary"})
io.writefile(outputfile, data:reverse(), {encoding = "binary"})
end})transform can also be the path of a lua script file, so that the transform step is preserved when exporting the project to vs/cmake and other generators:
target("test")
set_kind("binary")
add_rules("utils.bin2obj")
add_files("src/*.c")
add_files("src/asset.bin", {transform = path.join(os.projectdir(), "transform.lua")})-- transform.lua
function main(inputfile, outputfile)
local data = io.readfile(inputfile, {encoding = "binary"})
io.writefile(outputfile, data:reverse(), {encoding = "binary"})
endBesides the per-file config, transform can also be set at the rule level so that it applies to every binary file handled by that rule:
add_rules("utils.bin2c", {transform = path.join(os.projectdir(), "transform.lua")})The transformed file is written under target:autogenfile(...) and tracked by the dependency system, so it is only regenerated when the source file or the transform script actually changes.
batchcmds:call
Along with the transform support, we added a batchcmds:call interface that registers a plain lua function as a build command inside on_buildcmd_file and other batchcmds contexts, instead of spawning a subprocess through os.execv.
rule("myrule")
on_buildcmd_file(function (target, batchcmds, sourcefile, opt)
batchcmds:call(function (inputfile, outputfile, opt)
io.writefile(outputfile, io.readfile(inputfile))
end, {sourcefile, target:autogenfile(sourcefile)}, {name = "myrule/copy", target = target})
end)The given function is forked into the current sandbox before running, so import(), os.*, io.* and the other sandbox interfaces are available inside its body as usual. The first argument of batchcmds:call can also be the path of a lua script file, in which case it is equivalent to batchcmds:lua(...).
Note that a raw lua function cannot be exported by the vs/cmake project generators — they skip it with a warning. So if your rule needs to support project generation, prefer the script file form.
Unified Output Format for xmake show
The --json flag of xmake show only applied to some kinds of information. In this release the output format is unified behind --format, and -l/--list output now supports JSON too:
# plain text (default)
$ xmake show -l targets
$ xmake show -l targets --format=plain
# json output
$ xmake show -l targets --format=json
["app","core","ui"]--format currently accepts plain, json and dot, where dot only applies to --info=depgraph:
$ xmake show --info=depgraph --format=json
$ xmake show --info=depgraph --format=dotIf an unsupported format is passed for list information, xmake now raises an error instead of silently falling back to plain text. The old --json flag still works but is deprecated in favor of --format=json.
Multiple Target Names for Commands
The build, clean, install, uninstall, package and format commands now accept several target names at once, so there is no need to invoke them repeatedly:
$ xmake build target1 target2 target3
$ xmake clean target1 target2
$ xmake install target1 target2
$ xmake uninstall target1 target2Duplicated names are deduplicated automatically, and unknown target names are all checked up front, with suggestions for the closest matching target names.
Builtin Variables in xpack Install Files
add_installfiles and add_sourcefiles in xpack now expand builtin variables in their paths, so $(projectdir), $(builddir) and xpack's own values such as $(version) can be used directly.
xpack("test")
set_formats("zip")
add_targets("demo")
add_installfiles("$(projectdir)/assets/(**.png)", {prefixdir = "share"})
add_sourcefiles("$(projectdir)/src/(**.c)")Previously these paths were passed verbatim to the file matcher, so paths containing builtin variables could not be resolved. The expansion happens before the (...) root-directory marker is parsed, so the builtin-variable syntax and xmake's path grouping syntax coexist correctly.
gcc-16 Toolchain
A new gcc-16 toolchain was added, so you can switch to the gcc 16 compiler directly:
$ xmake f --toolchain=gcc-16
$ xmakeImproved Static libc++ Runtime Links for clang
When using set_runtimes("c++_static") with clang, xmake used to pass -static-libstdc++. That flag only pulls in libc++.a and not libc++abi.a, leaving symbols such as typeinfo and __cxa_* undefined and breaking the link — a problem that became especially visible with C++ modules, which reference more of libc++.
In this release, xmake asks clang for the absolute paths of libc++.a and libc++abi.a via -print-file-name (including per-target runtime directories such as lib/<target-triple>/), then disables the driver's automatic C++ runtime with -nostdlib++ and links both archives explicitly, wrapping them in --start-group / --end-group on non-Apple platforms to resolve their mutual references.
The C++ link order was adjusted accordingly: target.runtimes moved from the very front to after the user links and before the syslinks, so that the explicitly linked static runtime archives can resolve the symbols from the object files.
target("test")
set_kind("binary")
add_files("src/*.cpp")
set_runtimes("c++_static")
set_toolchains("clang")If the two static archives cannot be located, or the compiler does not support -nostdlib++, xmake falls back to the previous -static-libstdc++ behavior.
SSL Fallback on Download Failures
If a package download fails because of SSL/TLS certificate verification (common on some corporate networks or with outdated system certificates), xmake now prints a warning and retries once with certificate verification disabled.
warning: download failed due to ssl certificate verification, retrying with ssl verification disabled ..This fallback is only enabled for package files, resource files and patch files, because all of them are verified by their sha256 checksum afterwards, so it does not weaken security. To always disable certificate verification, xmake g --insecure-ssl=y is still available.
Changelog
New features
- #7558: Add
check_alignof/alignofdetection support - #7587: Support
xmake show --format=json - #7607: Support passing multiple target names to
build/cleanand other commands - #7634: Add filter support for xpack
- #7654: Add
batchcmds:calland lua-file transform support forbin2obj/bin2c - #7680: Rework
xmake pluginto install plugins from repositories (repo@nameor name), git urls (github:user/repo[#branch]) and local directories using the packages-styleplugins/<first-letter>/<name>layout, and list built-in / installed / available plugins with their descriptions - Add gcc-16 toolchain support
Changes
- #7562: Improve nuget version handling
- #7564: Improve vcpkg dependency info in
find_package - #7582: Support
set_encodingsand filter output for nvcc - #7609: Use
FormatMessageWfor Windows system error messages - #7614: Improve
cargopackage installation - #7619: Work around clangd drive-letter casing issue
- #7620: Improve cl flag detection and output handling on vs2015
- #7625: Improve verilator rules
- #7629: vsxmake: support custom source types in the solution explorer and nonetype targets
- #7630: Add
add_toolsetapi checker - #7637: Improve readline / curses options for mingw
- #7648: Improve error tips
- #7655: Improve bin2obj object-flag detection and add ppc / mips support
- #7657: Update NDK sdkver for riscv64
- #7666: Improve vcpkg package discovery
- #7672: Add fallback download support
- #7688: Improve static libc++ runtime links for clang
- #7689: Rewrite
xmake plugin --installto install plugins from xmake-repo aspluginkind packages, reusing the package installation flow - #7693: Replace the deprecated tbox interfaces
- Improve elf rpath cleaning and package path handling
- Add xcodebuild detection
- Update the bundled tbox
Bugs fixed
- #7561: Fix
-flto=thinregression for clang-cl - #7563: Fix crash in
containsand improve PCH for C++ std modules - #7580: Fix the format plugin when the header path is already absolute
- #7581: Fix missing paren in package loading
- #7583: Fix splitting global flags for cmake packages
- #7599: Fix gzip / tar detection on OpenBSD
- #7600: Fix enabling the build cache memcache
- #7601: Fix verilator to always define
TRACE - #7602: Fix package load memcache
- #7603: Fix
rmdirvia tbox update - #7604: Fix rpath cleaning for elf
- #7608: Fix typos and format command menus
- #7611: Fix cache environment variable handling (#7576)
- #7622: Fix default maintainer for deb packaging
- #7627: Fix PATH handling in debuild
- #7631: Fix PATH handling when installing deb packages
- #7633: Fix pkg-config path for BSD in the Meson backend
- #7640: Improve emcc detection with a fallback search
- #7644: Fix stack buffer overflow for long paths in path translation
- #7645: Fix removing read-only directories
- #7659: Fix emcc detection for
.exe/.baton Windows - #7661: Revert static libc++ link for clang
- #7668: Fix passing paths to cmake
- #7671: Fix tbox bugs
- #7674: Fix Mach host send-right leaks on macOS
- #7676: Fix masm symbol flags for embed / edit levels
- #7679: Fix
set_pcheaderfor msvc in C mode - #7684: Fix wrong Lua stack index in
process.open - #7685: Fix engine resource leaks
- #7687: Fix the ninja generator to emit build edges for
win.sdk.resourcesource batches (#7682) - #7692: Fix dependency order for
build.c++.modules.tryreuse - Fix trybuild for scons