V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
waruqi
V2EX  ›  程序员

xmake v2.5.8 发布,新增 Pascal/Swig 程序和 Lua53 运行时支持

  •  
  •   waruqi ·
    waruqi · 56 天前 · 699 次点击
    这是一个创建于 56 天前的主题,其中的信息可能已经有所发展或是发生改变。

    xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt ,配置语法更加简洁直观,对新手非常友好,短时间内就能快速入门,能够让用户把更多的精力集中在实际的项目开发上。

    这个版本,我们主要增加了对 Pascal 语言项目和 Swig 模块的构建支持,而对于上个版本新增的 Vala 语言支持,我们也做了进一步改进,增加了对动态库和静态库的构建支持。

    除此之外,xmake 现在也已经支持了可选的 Lua5.3 运行时,提供更好的跨平台支持能力,目前 xmake 已经能够在 LoongArch 架构上正常运行。

    新特性介绍

    Pascal 语言支持

    目前,我们可以使用跨平台的 Free pascal 工具链 fpc 去编译构建 Pascal 程序,例如:

    控制台程序

    add_rules("mode.debug", "mode.release")
    target("test")
        set_kind("binary")
        add_files("src/*.pas")
    

    动态库程序

    add_rules("mode.debug", "mode.release")
    target("foo")
        set_kind("shared")
        add_files("src/foo.pas")
    
    target("test")
        set_kind("binary")
        add_deps("foo")
        add_files("src/main.pas")
    

    我们也可以通过 add_fcflags() 接口添加 Pascal 代码相关的编译选项。

    更多例子见:Pascal examples

    Vala 库编译支持

    上个版本,我们新增了对 Vala 语言的支持,但是之前只能支持控制台程序的编译,无法生成库文件。而这个版本中,我们额外增加了对静态库和动态库的编译支持。

    静态库程序

    我们能够通过 add_values("vala.header", "mymath.h") 设置导出的接口头文件名,通过 add_values("vala.vapi", "mymath-1.0.vapi") 设置导出的 vapi 文件名。

    add_rules("mode.release", "mode.debug")
    
    add_requires("glib")
    
    target("mymath")
        set_kind("static")
        add_rules("vala")
        add_files("src/mymath.vala")
        add_values("vala.header", "mymath.h")
        add_values("vala.vapi", "mymath-1.0.vapi")
        add_packages("glib")
    
    target("test")
        set_kind("binary")
        add_deps("mymath")
        add_rules("vala")
        add_files("src/main.vala")
        add_packages("glib")
    

    动态库程序

    add_rules("mode.release", "mode.debug")
    
    add_requires("glib")
    
    target("mymath")
        set_kind("shared")
        add_rules("vala")
        add_files("src/mymath.vala")
        add_values("vala.header", "mymath.h")
        add_values("vala.vapi", "mymath-1.0.vapi")
        add_packages("glib")
    
    target("test")
        set_kind("binary")
        add_deps("mymath")
        add_rules("vala")
        add_files("src/main.vala")
        add_packages("glib")
    

    更多例子见:Vala examples

    Swig 模块支持

    我们提供了 swig.cswig.cpp 规则,可以对指定的脚本语言,调用 swig 程序生成 c/c++ 模块接口代码,然后配合 xmake 的包管理系统实现完全自动化的模块和依赖包整合。

    相关 issues: #1622

    Lua/C 模块

    add_rules("mode.release", "mode.debug")
    add_requires("lua")
    
    target("example")
        add_rules("swig.c", {moduletype = "lua"})
        add_files("src/example.i", {swigflags = "-no-old-metatable-bindings"})
        add_files("src/example.c")
        add_packages("lua")
    

    其中,swigflags 可以设置传递一些 swig 特有的 flags 选项。

    Python/C 模块

    add_rules("mode.release", "mode.debug")
    add_requires("python 3.x")
    
    target("example")
        add_rules("swig.c", {moduletype = "python"})
        add_files("src/example.i", {scriptdir = "share"})
        add_files("src/example.c")
        add_packages("python")
    

    如果设置了 scriptdir,那么我们执行安装的时候,会将对应模块的 python wrap 脚本安装到指定目录。

    Python/C++ 模块

    add_rules("mode.release", "mode.debug")
    add_requires("python 3.x")
    
    target("example")
        add_rules("swig.cpp", {moduletype = "python"})
        add_files("src/example.i", {scriptdir = "share"})
        add_files("src/example.cpp")
        add_packages("python")
    

    Lua5.3 运行时支持

    xmake 之前一直使用的 Luajit 作为默认的运行时,因为当初考虑到 Luajit 相对更加快速,并且固定的 lua 5.1 语法更加适合 xmake 内部实现的需要。

    但是考虑到 Luajit 的更新不给力,作者维护不是很积极,并且它的跨平台性比较差,对于一些新出的架构,比如:Loongarch,riscv 等支持不及时,这多少限制了 xmake 的平台支持力度。

    为此,新版本中,我们也将 Lua5.3 作为可选的运行时内置了进来,我们只需要通过下面的命令编译安装 xmake,就可以从 Luajit 切换到 Lua5.3 运行时:

    Linux/macOS

    $ make RUNTIME=lua
    

    Windows

    $ cd core
    $ xmake f --runtime=lua
    $ xmake
    

    目前,当前版本还是默认采用的 luajit 运行时,用户可以根据自己的需求切换到 Lua5.3 运行时,但这对于用户的项目 xmake.lua 配置脚本几乎没有任何兼容性影响。

    因为 xmake 的配置接口都已经做了一层的抽象封装,一些 Luajit/Lua5.3 存在兼容性差异的原生接口是不会开放给用户使用的,所以对项目构建来说,是完全无感知的。

    唯一的区别就是,带有 Lua5.3 的 xmake 支持更多的平台和架构。

    性能对比

    我做过一些基础构建测试,不管是启动时间,构建性能还是内存占用,Lua5.3 和 Luajit 的 xmake 都几乎没有任何差别。因为对于构建系统,主要的性能瓶颈是在编译器上,自身脚本的损耗占比是非常小的。

    而且 xmake 内部的一些底层 Lua 模块,比如 io,字符编码,字符串操作等,都自己用 c 代码全部重写过的,完全不依赖特定的 Lua 运行时引擎。

    是否会考虑默认切换到 Lua?

    由于我们刚刚支持 Lua5.3,尽管目前测试下来已经比较稳定,但是为了确保用户环境不受到任何影响,我们还需要再观察一段时间,短期还是默认使用 Luajit 。

    等到 2.6.1 版本开始,我们会全面开始切换到 Lua5.3 作为默认的运行时环境,大家有兴趣的话,也可以线帮忙测试下,如果遇到问题,欢迎到 issues 上反馈。

    LoongArch 架构支持

    由于我们增加了 Lua5.3 运行时支持,所以现在我们已经可以支持再 LoongArch 架构上运行 xmake,并且所有测试例子都已经测试通过。

    Lua 5.4

    目前,我们对 Lua 5.4 还保持观望状态,如果后面等 lua5.4 稳定了,我们也会尝试考虑继续升级到 Lua5.4 。

    第三方源码混合编译支持

    集成 CMake 代码库

    新版本中,我们已经能够通过 xmake 的包模式直接集成自己项目中带有 CMakeLists.txt 的代码库,而不是通过远程下载安装。

    相关 issues: #1714

    例如,我们有如下项目结构:

    ├── foo
    │   ├── CMakeLists.txt
    │   └── src
    │       ├── foo.c
    │       └── foo.h
    ├── src
    │   └── main.c
    ├── test.lua
    └── xmake.lua
    

    foo 目录下是一个使用 cmake 维护的静态库,而根目录下使用了 xmake 来维护,我们可以在 xmake.lua 中通过定义 package("foo") 包来描述如何构建 foo 代码库。

    add_rules("mode.debug", "mode.release")
    
    package("foo")
        add_deps("cmake")
        set_sourcedir(path.join(os.scriptdir(), "foo"))
        on_install(function (package)
            local configs = {}
            table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release"))
            table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF"))
            import("package.tools.cmake").install(package, configs)
        end)
        on_test(function (package)
            assert(package:has_cfuncs("add", {includes = "foo.h"}))
        end)
    package_end()
    
    add_requires("foo")
    
    target("demo")
        set_kind("binary")
        add_files("src/main.c")
        add_packages("foo")
    

    其中,我们通过 set_sourcedir() 来设置 foo 包的代码目录位置,然后通过 import 导入 package.tools.cmake 辅助模块来调用 cmake 构建代码,xmake 会自动获取生成的 libfoo.a 和对应的头文件。

    !> 如果仅仅本地源码集成,我们不需要额外设置 add_urlsadd_versions

    关于包的配置描述,详情见:包描述说明

    定义完包后,我们就可以通过 add_requires("foo")add_packages("foo") 来集成使用它了,就跟集成远程包一样的使用方式。

    另外,on_test 是可选的,如果想要严格检测包的编译安装是否成功,可以在里面做一些测试。

    完整例子见:Library with CMakeLists

    集成 autoconf 代码库

    我们也可以使用 package.tools.autoconf 来本地集成带有 autoconf 维护的第三方代码库。

    package("pcre2")
    
        set_sourcedir(path.join(os.scriptdir(), "3rd/pcre2"))
    
        add_configs("jit", {description = "Enable jit.", default = true, type = "boolean"})
        add_configs("bitwidth", {description = "Set the code unit width.", default = "8", values = {"8", "16", "32"}})
    
        on_load(function (package)
            local bitwidth = package:config("bitwidth") or "8"
            package:add("links", "pcre2-" .. bitwidth)
            package:add("defines", "PCRE2_CODE_UNIT_WIDTH=" .. bitwidth)
            if not package:config("shared") then
                package:add("defines", "PCRE2_STATIC")
            end
        end)
    
        on_install("macosx", "linux", "mingw", function (package)
            local configs = {}
            table.insert(configs, "--enable-shared=" .. (package:config("shared") and "yes" or "no"))
            table.insert(configs, "--enable-static=" .. (package:config("shared") and "no" or "yes"))
            if package:debug() then
                table.insert(configs, "--enable-debug")
            end
            if package:config("pic") ~= false then
                table.insert(configs, "--with-pic")
            end
            if package:config("jit") then
                table.insert(configs, "--enable-jit")
            end
            local bitwidth = package:config("bitwidth") or "8"
            if bitwidth ~= "8" then
                table.insert(configs, "--disable-pcre2-8")
                table.insert(configs, "--enable-pcre2-" .. bitwidth)
            end
            import("package.tools.autoconf").install(package, configs)
        end)
    
        on_test(function (package)
            assert(package:has_cfuncs("pcre2_compile", {includes = "pcre2.h"}))
        end)
    

    package.tools.autoconfpackage.tools.cmake 模块都是可以支持 mingw/cross/iphoneos/android 等交叉编译平台和工具链的,xmake 会自动传递对应的工具链进去,用户不需要做任何其他事情。

    集成其他构建系统

    我们还支持集成 Meson/Scons/Make 等其他构建系统维护的代码库,仅仅只需要导入对应的构建辅助模块,这里就不一一细讲了,我们可以进一步查阅文档:集成本地第三方源码库

    改进编译器特性检测

    在之前的版本中,我们可以通过 check_features 辅助接口来检测指定的编译器特性,比如:

    includes("check_features.lua")
    
    target("test")
        set_kind("binary")
        add_files("*.c")
        add_configfiles("config.h.in")
        configvar_check_features("HAS_CONSTEXPR", "cxx_constexpr")
        configvar_check_features("HAS_CONSEXPR_AND_STATIC_ASSERT", {"cxx_constexpr", "c_static_assert"}, {languages = "c++11"})
    

    config.h.in

    ${define HAS_CONSTEXPR}
    ${define HAS_CONSEXPR_AND_STATIC_ASSERT}
    

    config.h

    /* #undef HAS_CONSTEXPR */
    #define HAS_CONSEXPR_AND_STATIC_ASSERT 1
    

    如果当前 cxx_constexpr 特性支持,就会在 config.h 中启用 HAS_CONSTEXPR 宏。

    新增 C/C++ 标准支持检测

    2.5.8 之后,我们继续新增了对 cstd 和 c++ std 版本检测支持,相关 issues: #1715

    例如:

    configvar_check_features("HAS_CXX_STD_98", "cxx_std_98")
    configvar_check_features("HAS_CXX_STD_11", "cxx_std_11", {languages = "c++11"})
    configvar_check_features("HAS_CXX_STD_14", "cxx_std_14", {languages = "c++14"})
    configvar_check_features("HAS_CXX_STD_17", "cxx_std_17", {languages = "c++17"})
    configvar_check_features("HAS_CXX_STD_20", "cxx_std_20", {languages = "c++20"})
    configvar_check_features("HAS_C_STD_89", "c_std_89")
    configvar_check_features("HAS_C_STD_99", "c_std_99")
    configvar_check_features("HAS_C_STD_11", "c_std_11", {languages = "c11"})
    configvar_check_features("HAS_C_STD_17", "c_std_17", {languages = "c17"})
    

    新增编译器内置宏检测

    我们还能检测编译器存在一些内置的宏定义,比如:__GNUC__ 等,我们可以通过 check_macrosconfigvar_check_macros 辅助脚本来检测它们是否存在。

    相关 issues: #1715

    -- 检测宏是否定义
    configvar_check_macros("HAS_GCC", "__GNUC__")
    -- 检测宏没有被定义
    configvar_check_macros("NO_GCC", "__GNUC__", {defined = false})
    -- 检测宏条件
    configvar_check_macros("HAS_CXX20", "__cplusplus >= 202002L", {languages = "c++20"})
    

    增加对 Qt 4.x 的支持

    除了 Qt 5.x 和 6.x,我们对于一些基于 Qt 4.x 的老项目,xmake 也增加了支持。

    增加对 Android NDK r23 的支持

    由于 google 对 Android NDK 的一些结构改动,导致 r23 影响了 xmake 对 android 项目部分编译特性的支持,在这个版本中,我们也做了修复。

    修复 vsxmake 插件 Unicode 编码问题

    另外,如果基于 Unicode 作为项目目录,那么生成的 vsxmake 项目会收到影响,导致 vs 项目编译和访问上存在很多问题,我们也在新版本中做了修复。

    更新内容

    新特性

    • #388: Pascal 语言支持,可以使用 fpc 来编译 free pascal
    • #1682: 添加可选的额 lua5.3 运行时替代 luajit,提供更好的平台兼容性。
    • #1622: 支持 Swig
    • #1714: 支持内置 cmake 等第三方项目的混合编译
    • #1715: 支持探测编译器语言标准特性,并且新增 check_macros 检测接口
    • xmake 支持在 Loongarch 架构上运行

    改进

    • #1618: 改进 vala 支持构建动态库和静态库程序
    • 改进 Qt 规则去支持 Qt 4.x
    • 改进 set_symbols("debug") 支持 clang/windows 生成 pdb 文件
    • #1638: 改进合并静态库
    • 改进 on_load/after_load 去支持动态的添加 target deps
    • #1675: 针对 mingw 平台,重命名动态库和导入库文件名后缀
    • #1694: 支持在 set_configvar 中定义一个不带引号的字符串变量
    • 改进对 Android NDK r23 的支持
    • set_languages 新增 c++latestclatest 配置值
    • #1720: 添加 save_scoperestore_scope 去修复 check_xxx 相关接口
    • #1726: 改进 compile_commands 生成器去支持 nvcc

    Bugs 修复

    • #1671: 修复安装预编译包后,*.cmake 里面的一些不正确的绝对路径
    • #1689: 修复 vsxmake 插件的 unicode 字符显示和加载问题
    4 条回复    2021-10-10 11:46:16 +08:00
    jedrek
        1
    jedrek  
       56 天前
    挺不错的, 比 CMake 好使. 啥时候更新 CLion 插件支持就好了
    waruqi
        2
    waruqi  
    OP
       55 天前
    @jedrek 已经更新了,clion 上可以下载使用
    airqj
        3
    airqj  
       55 天前
    现在已经用不到了 支持:)
    victorbian
        4
    victorbian  
       54 天前
    看起来很不错啊,牛逼
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2231 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 02:48 · PVG 10:48 · LAX 18:48 · JFK 21:48
    ♥ Do have faith in what you're doing.