Xmake is a lightweight modern C/C++ project build tool based on Lua. Its main features are: easy to use syntax, more readable project maintenance, and a consistent build experience across platforms.
This article mainly explains the installation process of xmake under various platforms.
Usually we only need to install the script with a one-click installation script.
Bash <(curl -fsSL https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh)
Bash <(wget https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.sh -O -)
Invoke-Expression (Invoke-Webrequest 'https://raw.githubusercontent.com/tboox/xmake/master/scripts/get.ps1' -UseBasicParsing).Content
Note: If the ps script execution prompt fails, you can try to execute in administrator mode.
This version mainly improves stream/stdio read and write, character set encoding and other operations, and reconstructs the entire atomic operation implementation, adding a c11-style atomic api for finer-grained control.
tb_stream_init_from_sock_ref()
to open a given socket as streamc++ modules have been officially included in the c++20 draft, and msvc and clang have been basically implemented on modules-ts Support, as c++20’s footsteps are getting closer and closer to us, xmake has also begun to support c++modules in advance.
At present xmake has fully supported the implementation of the modules-ts of msvc/clang. For gcc, since its cxx-modules branch is still under development, it has not officially entered the master. I have read the changelog inside, and the related flags are still in the process. Constantly changing, I feel that it has not stabilized, so I have not supported it yet.
For more information about xmake’s progress on c++modules: https://github.com/xmake-io/xmake/pull/569
I will not talk about the introduction of c++modules. This is mainly about how to build a c++modules project under xmake. Let’s look at a simple example:
target("hello")
set_kind("binary")
add_files("src/*.cpp", "src/*.mpp")
The above is a description of the xmake.lua that supports building c++modules files, where hello.mpp
is the module file:
#include <cstdio>
export module hello;
using namespace std;
export namespace hello {
void say(const char* str) {
printf("%s\n", str);
}
}
Main.cpp is the main program that uses the hello module:
import hello;
int main() {
hello::say("hello module!");
return 0;
}
Next we execute xmake to build this program:
ruki:hello ruki$ xmake
[0%]: ccache compiling.release src/hello.mpp
[50%]: ccache compiling.release src/main.cpp
[100%]: linking.release hello
build ok!
This version provides a new vs project generation plugin (thanks to @OpportunityLiu for its contribution), which is quite different from the previous plugin processing mode for generating vs. The vs project is to open all the source files and hand them over to vs to handle the compilation.
In addition, we rewrote the entire luajit io runtime to better support the unicode character set, especially the support for Chinese characters on Windows.
Finally, the new version began to try to install the lua bitcode script directly, to reduce the size of the installation package (controlled within 2.4M), improve the efficiency of xmake boot load.
The original vs build plugin does not support xmake’s rules. Because xmake’s rules use a lot of custom scripts like on_build
, they can’t be expanded, so projects like qt, wdk can’t support exporting to vs. compile.
Therefore, in order to solve this problem, the new version of the vs. build plugin performs the compile operation by directly calling the xmake command under vs, and also supports intellsence and definition jumps, as well as breakpoint debugging.
The specific use is similar to the old version:
$ xmake project -k [vsxmake2010|vsxmake2013|vsxmake2015|..] -m "debug;release"
If no version is specified, xmake will automatically detect the current version of vs to generate:
$ xmake project -k vsxmake -m "debug;release"
Xmake integrates built-in remote package dependency management. Users simply add the packages and versions they need to the project, and then automatically download and integrate the corresponding packages into the project, and compile and link.
For example:
add_requires("libuv master", "ffmpeg", "zlib 1.20.*")
add_requires("tbox >1.6.1", {optional = true, debug = true})
add_requires("boost", {alias = "boost_context", configs = {context = true}})
target("test")
set_kind("binary")
add_files("src/*.c")
add_packages("libuv", "ffmpeg", "tbox", "boost_context", "zlib")
Xmake’s package repository was designed with semantic version support and cross-platform support for dependencies. As long as the package itself supports the platform, it can be integrated, such as zlib package, used in xmake, iphoneos, android and mingw. All platforms are fully available.
Users only need to simply cut the build platform:
xmake f -p iphoneos -a arm64
xmake
note: try installing these packages (pass -y to skip confirm)?
in xmake-repo:
-> zlib 1.2.11
please input: y (y/n)
=> download https://downloads.sourceforge.net/project/libpng/zlib/1.2.11/zlib-1.2.11.tar.gz .. ok
=> install zlib 1.2.11 .. ok
You can download the corresponding package in the ‘add_requires` for the iphoneos platform. The ultimate goal of xmake is to create a cross-platform package repository. Users no longer need to find the c/c++ library, and then study the migration of various platforms. You need to simply add the package dependencies, which can be easily used on all platforms.
Of course, the current xmake official warehouse is still in the early stage of development, there are still few packages, and the supported platforms are not perfect. Therefore, here I briefly introduce how users can make and upload their own c/c++ packages. And how to submit it to our warehouse (you can also build your own private warehouse), I hope that interested partners can help to contribute a small amount of effort to jointly build and build a c/c++ dependency package ecosystem.
Before making our own package, we need to understand the structure of the next package repository, whether it is the official package repository or the self-built private package repository, the structure is the same:
xmake-repo
- packages
- t/tbox/xmake.lua
- z/zlib/xmake.lua
Through the above structure, you can see that each package will have a xmake.lua to describe its installation rules, and according to the z/zlib
two-level sub-category storage, convenient for quick retrieval.
The description rules for the package are basically done in its xmake.lua, which is similar to the xmake.lua description in the project project. The difference is that the description field only supports package()
.
However, in the project xmake.lua, you can also directly add package()
to the built-in package description, and even the package warehouse is saved, sometimes it will be more convenient.
First, let’s take a look at zlib’s description rules first. This rule can be found at xmake-repo/z/zlib/xmake.lua.
package("zlib")
set_homepage("http://www.zlib.net")
set_description("A Massively Spiffy Yet Delicately Unobtrusive Compression Library")
set_urls("http://zlib.net/zlib-$(version).tar.gz",
"https://downloads.sourceforge.net/project/libpng/zlib/$(version)/zlib-$(version).tar.gz")
add_versions("1.2.10", "8d7e9f698ce48787b6e1c67e6bff79e487303e66077e25cb9784ac8835978017")
add_versions("1.2.11", "c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1")
on_install("windows", function (package)
io.gsub("win32/Makefile.msc", "%-MD", "-" .. package:config("vs_runtime"))
os.vrun("nmake -f win32\\Makefile.msc zlib.lib")
os.cp("zlib.lib", package:installdir("lib"))
os.cp("*.h", package:installdir("include"))
end)
on_install("linux", "macosx", function (package)
import("package.tools.autoconf").install(package, {"--static"})
end)
on_install("iphoneos", "android@linux,macosx", "mingw@linux,macosx", function (package)
import("package.tools.autoconf").configure(package, {host = "", "--static"})
io.gsub("Makefile", "\nAR=.-\n", "\nAR=" .. (package:build_getenv("ar") or "") .. "\n")
io.gsub("Makefile", "\nARFLAGS=.-\n", "\nARFLAGS=cr\n")
io.gsub("Makefile", "\nRANLIB=.-\n", "\nRANLIB=\n")
os.vrun("make install -j4")
end)
on_test(function (package)
assert(package:has_cfuncs("inflate", {includes = "zlib.h"}))
end)
This package rule adds installation rules to windows, linux, macosx, iphoneos, mingw and other platforms. Basically, it has achieved full platform coverage, and even some cross-compilation platforms, which is a typical example.
Of course, some packages rely on source code implementation and are not completely cross-platform, so you only need to set the installation rules for the platforms it supports.