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.c
和 swig.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_urls
和 add_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.autoconf
和 package.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_macros
和 configvar_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++latest
和clatest
配置值 - #1720: 增加
save_scope
和restore_scope
去修复check_xxx
相干接口 - #1726: 改良 compile_commands 生成器去反对 nvcc
Bugs 修复
- #1671: 修复装置预编译包后,*.cmake 外面的一些不正确的绝对路径
- #1689: 修复 vsxmake 插件的 unicode 字符显示和加载问题