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


    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
    ", 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 加载失败的错误信息提示错误
  • 相关阅读:
    Java 默认修饰符
    大学生职业规划到底应该规划什么?
    IT就业攻略:看准趋势 选对行业
    积极推动校企深度合作 做好产学结合示范工作
    强化工程实践能力 提升就业核心竞争力
    大学生就业:以“硬”实力实现“软”着陆
    使用IDEA 创建SpringBoot项目
    项目记录随笔
    全国城市数据库sql
    xp win7共享
  • 原文地址:https://www.cnblogs.com/tboox/p/15202142.html
Copyright © 2020-2023  润新知