xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。
这个版本,我们新增了很多新特性,不仅增加了对 Vala 和 Metal 语言的编译支持,另外我们还改进了包依赖管理,能够像 npm/package.lock 那样支持对依赖包的锁定和更新,使得用户的项目不会受到上游包仓库的更新变动影响。
此外,我们还提供了一些比较实用的规则, 比如 utils.bin2c 可以让用户方便快速的内嵌一些二进制资源文件到代码中去,以头文件的方式获取相关数据。
项目源码
新特性介绍 新增 Vala 语言支持这个版本,我们已经可以初步支持构建 Vala 程序,只需要应用 add_rules("vala") 规则。
同时,我们需要添加一些依赖包,其中 glib 包是必须的,因为 vala 自身也会用到它。
add_values("vala.packages") 用于告诉 valac,项目需要哪些包,它会引入相关包的 vala api,但是包的依赖集成,还是需要通过 add_requires("lua") 下载集成。
例如:
add_rules("mode.release", "mode.debug") add_requires("lua", "glib") target("test") set_kind("binary") add_rules("vala") add_files("src/*.vala") add_packages("lua", "glib") add_values("vala.packages", "lua")更多例子:Vala examples
新增包依赖锁定支持这个特性类似 npm 的 package.lock, cargo 的 cargo.lock。
比如,我们引用一些包,默认情况下,如果不指定版本,那么 xmake 每次都会自动拉取最新版本的包来集成使用,例如:
add_requires("zlib")但如果上游的包仓库更新改动,比如 zlib 新增了一个 1.2.11 版本,或者安装脚本有了变动,都会导致用户的依赖包发生改变。
这容易导致原本编译通过的一些项目,由于依赖包的变动出现一些不稳定因素,有可能编译失败等等。
为了确保用户的项目每次使用的包都是固定的,我们可以通过下面的配置去启用包依赖锁定。
set_policy("package.requires_lock", true)这是一个全局设置,必须设置到全局根作用域,如果启用后,xmake 执行完包拉取,就会自动生成一个 xmake-requires.lock 的配置文件。
它包含了项目依赖的所有包,以及当前包的版本等信息。
{ __meta__ = { version = "1.0" }, ["macosx|x86_64"] = { ["cmake#31fecfc4"] = { repo = { branch = "master", commit = "4498f11267de5112199152ab030ed139c985ad5a", url = "https://github.com/xmake-io/xmake-repo.git" }, version = "3.21.0" }, ["glfw#31fecfc4"] = { repo = { branch = "master", commit = "eda7adee81bac151f87c507030cc0dd8ab299462", url = "https://github.com/xmake-io/xmake-repo.git" }, version = "3.3.4" }, ["opengl#31fecfc4"] = { repo = { branch = "master", commit = "94d2eee1f466092e04c5cf1e4ecc8c8883c1d0eb", url = "https://github.com/xmake-io/xmake-repo.git" } } } }当然,我们也可以执行下面的命令,强制升级包到最新版本。
$ xmake require --upgrade upgrading packages .. zlib: 1.2.10 -> 1.2.11 1 package is upgraded! option 支持代码片段的运行时检测option 本身有提供 add_csnippets/add_cxxsnippets 两个接口,用于快速检测特定一段 c/c++ 代码是否通过编译,如果编译通过就会启用对应 option 选项。
但之前的版本仅仅只能提供编译期检测,而新版本中,我们还新增了运行时检测支持。
我们可以通过设置 {tryrun = true} 和 {output = true} 两个参数,用于尝试运行检测和捕获输出。
尝试运行检测设置 tryrun 可以尝试运行来检测
option("test") add_cxxsnippets("HAS_INT_4", "return (sizeof(int) == 4)? 0 : -1;", {tryrun = true})如果编译运行通过,test 选项就会被启用。
运行时检测并捕获输出设置 output 也会尝试去检测,并且额外捕获运行的输出内容。
option("test") add_cxxsnippets("INT_SIZE", 'printf("%d", sizeof(int)); return 0;', {output = true, number = true})如果编译运行通过,test 选项就会被启用,同时能获取到对应的输出内容作为 option 的值。
注:设置为捕获输出,当前 option 不能再设置其他 snippets
我们也可以通过 is_config 获取绑定到option的输出。
if is_config("test", "8") tben -- xxx end另外,我们也对 includes("check_csnippets") 的辅助检测接口,也做了改进来支持运行时检测。
includes("check_csnippets.lua") target("test") set_kind("binary") add_files("*.c") add_configfiles("config.h.in") check_csnippets("HAS_INT_4", "return (sizeof(int) == 4)? 0 : -1;", {tryrun = true}) check_csnippets("INT_SIZE", 'printf("%d", sizeof(int)); return 0;', {output = true, number = true}) configvar_check_csnippets("HAS_LONG_8", "return (sizeof(long) == 8)? 0 : -1;", {tryrun = true}) configvar_check_csnippets("PTR_SIZE", 'printf("%d", sizeof(void*)); return 0;', {output = true, number = true})如果启用捕获输出,config.h.in 的 ${define PTR_SIZE} 会自动生成 #define PTR_SIZE 4。
其中,number = true 设置,可以强制作为 number 而不是字符串值,否则默认会定义为 #define PTR_SIZE "4"
快速内嵌二进制资源文件到代码我们可以通过 utils.bin2c 规则,在项目中引入一些二进制文件,并见他们作为 c/c++ 头文件的方式提供开发者使用,获取这些文件的数据。