首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >xmake v2.5.7 发布,包依赖锁定和 Vala/Metal 语言编译支持

xmake v2.5.7 发布,包依赖锁定和 Vala/Metal 语言编译支持

作者头像
ruki
发布2021-09-14 14:49:38
5760
发布2021-09-14 14:49:38
举报
文章被收录于专栏:TBOOX开源工程TBOOX开源工程

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++ 头文件的方式提供开发者使用,获取这些文件的数据。

比如,我们可以在项目中,内嵌一些 png/jpg 资源文件到代码中。

target("console")
    set_kind("binart")
    add_rules("utils.bin2c", {extensions = {".png", ".jpg"}})
    add_files("src/*.c")
    add_files("res/*.png", "res/*.jpg")

注:extensions 的设置是可选的,默认后缀名是 .bin

然后,我们就可以通过 #include "filename.png.h" 的方式引入进来使用,xmake 会自动帮你生成对应的头文件,并且添加对应的搜索目录。

static unsigned char g_png_data[] = {
    #include "image.png.h"
};

int main(int argc, char** argv)
{
    printf("image.png: %s, size: %d\n", g_png_data, sizeof(g_png_data));
    return 0;
}

生成头文件内容类似:

cat build/.gens/test/macosx/x86_64/release/rules/c++/bin2c/image.png.h
  0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x78, 0x6D, 0x61, 0x6B, 0x65, 0x21, 0x0A, 0x00

新增 iOS/macOS 应用 Metal 编译支持

我们知道 xcode.application 规则可以编译 iOS/macOS 应用程序,生成 .app/.ipa 程序包,并同时完成签名操作。

不过之前它不支持对带有 .metal 代码的编译,而新版本中,我们新增了 xcode.metal 规则,并默认关联到 xcode.application 规则中去来默认支持 metal 编译。

xmake 会自动编译 .metal 然后打包生成 default.metallib 文件,并且自动内置到 .app/.ipa 里面。

如果用户的 metal 是通过 [_device newDefaultLibrary] 来访问的,那么就能自动支持,就跟使用 xcode 编译一样。

这里是我们提供的一个完整的:项目例子。

add_rules("mode.debug", "mode.release")

target("HelloTriangle")
    add_rules("xcode.application")
    add_includedirs("Renderer")
    add_frameworks("MetalKit")
    add_mflags("-fmodules")
    add_files("Renderer/*.m", "Renderer/*.metal") ------- 添加 metal 文件
    if is_plat("macosx") then
        add_files("Application/main.m")
        add_files("Application/AAPLViewController.m")
        add_files("Application/macOS/Info.plist")
        add_files("Application/macOS/Base.lproj/*.storyboard")
        add_defines("TARGET_MACOS")
        add_frameworks("AppKit")
    elseif is_plat("iphoneos") then
        add_files("Application/*.m")
        add_files("Application/iOS/Info.plist")
        add_files("Application/iOS/Base.lproj/*.storyboard")
        add_frameworks("UIKit")
        add_defines("TARGET_IOS")

比如,在 macOS 上,编译运行后,就会通过 metal 渲染出需要的效果。

如果,我们的项目没有使用默认的 metal library,我们也可以通过上面提到的 utils.bin2c 规则,作为源文件的方式内嵌到代码库中,例如:

add_rules("utils.bin2c", {extensions = ".metal"})
add_files("Renderer/*.metal")

然后代码中,我们就能访问了:

static unsigned char g_metal_data[] = {
    #include "xxx.metal.h"
};

id<MTLLibrary> library = [_device newLibraryWithSource:[[NSString stringWithUTF8String:g_metal_data]] options:nil error:&error];

改进 add_repositories

如果我们通过内置在项目中的本地仓库,我们之前是通过 add_repositories("myrepo repodir") 的方式来引入。

但是,它并不像 add_files() 那样是基于当前 xmake.lua 文件目录的相对目录,也没有路径的自动转换,因此容易遇到找不到 repo 的问题。

因此,我么你改进了下它,可以通过额外的 rootdir 参数指定对应的根目录位置,比如相对当前 xmake.lua 的脚本目录。

add_repositories("myrepo repodir", {rootdir = os.scriptdir()})

os.cp 支持符号链接

之前的版本,os.cp 接口不能很好的处理符号链接的复制,他会自动展开链接,复制实际的文件内容,只会导致复制后,符号链接丢失。

如果想要复制后,原样保留符号链接,只需要设置下参数:{symlink = true}

os.cp("/xxx/symlink", "/xxx/dstlink", {symlink = true})

更方便地编译自动生成的代码

有时候,我们会有这样一个需求,在编译前,自动生成一些源文件参与后期的代码编译。但是由于 add_files 添加的文件在执行编译时候,就已经确定,无法在编译过程中动态添加它们(因为需要并行编译)。

因此,要实现这个需求,我们通常需要自定义一个 rule,然后里面主动调用编译器模块去处理生成代码的编译,对象文件的注入,依赖更新等一系列问题。

这对于 xmake 开发者本身没什么大问题,但是对于用户来说,这还是比较繁琐了,不好上手。

新版本中,我们改进了对 add_files 的支持,并添加了 {always_added = true} 配置来告诉 xmake 我们始终需要添加指定的源文件,即使它还不存在。

这样我们就可以依靠xmake的默认编译过程来编译自动生成的代码了,像这样:

add_rules("mode.debug", "mode.release")

target("autogen_code")
    set_kind("binary")
    add_files("$(buildir)/autogen.cpp", {always_added = true})
    before_build(function (target)
        io.writefile("$(buildir)/autogen.cpp", [[
#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    cout << "hello world!" << endl;
    return 0;
}
        ]])
    end)

都不需要额外的 rule 定义,只需要保证编译顺序,在正确的阶段生成代码文件就可以了。

但是,我们也需要注意,由于当前自动生成的源文件可能还不存在,我们不能在 add_files 里面使用模式匹配,只能显式添加每个源文件路径。

更新内容

新特性

  • #1534: 新增对 Vala 语言的支持
  • #1544: 添加 utils.bin2c 规则去自动从二进制资源文件产生 .h 头文件并引入到 C/C++ 代码中
  • #1547: option/snippets 支持运行检测模式,并且可以获取输出
  • #1567: 新增 xmake-requires.lock 包依赖锁定支持
  • #1597: 支持编译 metal 文件到 metallib,并改进 xcode.application 规则去生成内置的 default.metallib 到 app

改进

  • #1540: 更好更方便地编译自动生成的代码
  • #1578: 改进 add_repositories 去更好地支持相对路径
  • #1582: 改进安装和 os.cp 支持符号链接

Bugs 修复

  • #1531: 修复 targets 加载失败的错误信息提示错误

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 TBOOX开源工程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 新特性介绍
    • 新增 Vala 语言支持
      • 新增包依赖锁定支持
        • option 支持代码片段的运行时检测
          • 尝试运行检测
          • 运行时检测并捕获输出
        • 快速内嵌二进制资源文件到代码
          • 新增 iOS/macOS 应用 Metal 编译支持
            • 改进 add_repositories
              • os.cp 支持符号链接
                • 更方便地编译自动生成的代码
                • 更新内容
                  • 新特性
                    • 改进
                      • Bugs 修复
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档