Xmake 是一个基于 Lua 的轻量级跨渠道构建东西。

它十分的轻量,没有任何依靠,因为它内置了 Lua 运转时。

它运用 xmake.lua 维护项目构建,比较 makefile/CMakeLists.txt,装备语法愈加简洁直观,对新手十分友爱,短时间内就能快速入门,能够让用户把更多的精力集中在实践的项目开发上。

咱们能够运用它像 Make/Ninja 那样能够直接编译项目,也能够像 CMake/Meson 那样生成工程文件,别的它还有内置的包管理体系来协助用户解决 C/C++ 依靠库的集成运用问题。

现在,Xmake 首要用于 C/C++ 项目的构建,可是一起也支撑其他 native 言语的构建,能够实现跟 C/C++ 进行混合编译,一起编译速度也是十分的快,能够跟 Ninja 相等。

Xmake = Build backend + Project Generator + Package Manager + [Remote|Distributed] Build + Cache

尽管不是很精确,但咱们仍是能够把 Xmake 按下面的方法来理解:

Xmake ≈ Make/Ninja + CMake/Meson + Vcpkg/Conan + distcc + ccache/sccache
  • 项目源码
  • 官方文档
  • 入门课程
Xmake v2.7.7 发布,支持 Haiku 平台,改进 API 检测和 C++ Modules 支持

新特性介绍

支撑 Haiku 体系

Xmake 现在已经彻底能够在 Haiku 体系 上运转,而且咱们对 Xmake 新增了一个 haiku 编译渠道,用于在 Haiku 体系上进行代码编译。

效果如下:

Xmake v2.7.7 发布,支持 Haiku 平台,改进 API 检测和 C++ Modules 支持

改善 C++20 Modules 支撑

最新构建的 clang-17 对 C++20 Modules 做了不少改善,因此咱们在 Xmake 中也针对性地对其进行了更好的适配,而且修正了一些 std modules 相关的问题。

关于 C++ Modules 的完好工程比方,能够看下 C++ Modules Examples。

现在也有一些实践的 C++ Modules 项目已经运用了 Xmake 来构建,例如:

  • async_simple
  • StormKit

改善 API 检测

先前的版别,对 xmake.lua 的装备 API 的传参有效性检测比较弱,只是针对 add_includedirs, add_files 等几个少数的 API 做了检测。

而新版中,咱们新增了一个 xmake check 专门用于检测 API 和代码的插件,能够更好地对用户的装备进行检测,防止用户因为不熟悉 Xmake 导致各种装备值设置不对的问题。

别的,除了手动运转 xmake check 指令来触发检测,Xmake 在编译中,编译失利等各个阶段, 也会及时地主动触发一些惯例 API 和装备的检测,毕竟不是一切用户都知道 xmake check 这个指令的存在。

默许检测一切 API

set_lanuages("c91") -- typo
$ xmake check
./xmake.lua:15: warning: unknown language value 'c91', it may be 'c90'
0 notes, 1 warnings, 0 errors

默许也能够指定检测特定组:

$ xmake check api
$ xmake check api.target

显现详细输出

这会额定供给 note 级别的检测信息。

$ xmake check -v
./xmake.lua:15: warning: unknown language value 'cxx91', it may be 'cxx98'
./src/tbox/xmake.lua:43: note: unknown package value 'mbedtls'
./src/tbox/xmake.lua:43: note: unknown package value 'polarssl'
./src/tbox/xmake.lua:43: note: unknown package value 'openssl'
./src/tbox/xmake.lua:43: note: unknown package value 'pcre2'
./src/tbox/xmake.lua:43: note: unknown package value 'pcre'
./src/tbox/xmake.lua:43: note: unknown package value 'zlib'
./src/tbox/xmake.lua:43: note: unknown package value 'mysql'
./src/tbox/xmake.lua:43: note: unknown package value 'sqlite3'
8 notes, 1 warnings, 0 errors

检测指定的 API

$ xmake check api.target.languages
./xmake.lua:15: warning: unknown language value 'cxx91', it may be 'cxx98'
0 notes, 1 warnings, 0 errors

检测编译 flags

$ xmake check
./xmake.lua:10: warning: clang: unknown c compiler flag '-Ox'
0 notes, 1 warnings, 0 errors

检测 includedirs

除了 includedirs,还有 linkdirs 等路径都会去检测。

$ xmake check
./xmake.lua:11: warning: includedir 'xxx' not found
0 notes, 1 warnings, 0 errors

支撑检测工程代码(clang-tidy)

显现 clang-tidy 检测列表

$ xmake check clang.tidy --list
Enabled checks:
    clang-analyzer-apiModeling.StdCLibraryFunctions
    clang-analyzer-apiModeling.TrustNonnull
    clang-analyzer-apiModeling.google.GTest
    clang-analyzer-apiModeling.llvm.CastValue
    clang-analyzer-apiModeling.llvm.ReturnValue
    ...

检测一切 targets 中的源码

$ xmake check clang.tidy
1 error generated.
Error while processing /private/tmp/test2/src/main.cpp.
/tmp/test2/src/main.cpp:1:10: error: 'iostr' file not found [clang-diagnostic-error]
#include <iostr>
         ^~~~~~~
Found compiler error(s).
error: execv(/usr/local/opt/llvm/bin/clang-tidy -p compile_commands.json /private/tmp/test2/src
/main.cpp) failed(1)

指定检测类型

咱们能够在 --check= 中指定需求检测的类型,具体用法能够参考 clang-tidy--check= 参数,彻底一致的。

$ xmake check clang.tidy --checks="*"
6 warnings and 1 error generated.
Error while processing /private/tmp/test2/src/main.cpp.
/tmp/test2/src/main.cpp:1:10: error: 'iostr' file not found [clang-diagnostic-error]
#include <iostr>
         ^~~~~~~
/tmp/test2/src/main.cpp:3:1: warning: do not use namespace using-directives; use using-declarat
ions instead [google-build-using-namespace]
using namespace std;
^
/tmp/test2/src/main.cpp:3:17: warning: declaration must be declared within the '__llvm_libc' na
mespace [llvmlibc-implementation-in-namespace]
using namespace std;
                ^
/tmp/test2/src/main.cpp:5:5: warning: declaration must be declared within the '__llvm_libc' nam
espace [llvmlibc-implementation-in-namespace]
int main(int argc, char **argv) {
    ^
/tmp/test2/src/main.cpp:5:5: warning: use a trailing return type for this function [modernize-u
se-trailing-return-type]
int main(int argc, char **argv) {
~~~ ^
auto                            -> int
/tmp/test2/src/main.cpp:5:14: warning: parameter 'argc' is unused [misc-unused-parameters]
int main(int argc, char **argv) {
             ^~~~
              /*argc*/
/tmp/test2/src/main.cpp:5:27: warning: parameter 'argv' is unused [misc-unused-parameters]
int main(int argc, char **argv) {
                          ^~~~
                           /*argv*/
Found compiler error(s).
error: execv(/usr/local/opt/llvm/bin/clang-tidy --checks=* -p compile_commands.json /private/tm
p/test2/src/main.cpp) failed(1)

检测指定 target 的代码

$ xmake check clang.tidy [targetname]

检测给定的源文件列表

$ xmake check clang.tidy -f src/main.c
$ xmake check clang.tidy -f 'src/*.c:src/**.cpp'

设置 .clang-tidy 装备文件

$ xmake check clang.tidy --configfile=/tmp/.clang-tidy

创立 .clang-tidy 装备文件

$ xmake check clang.tidy --checks="*" --create
$ cat .clang-tidy
---
Checks:          'clang-diagnostic-*,clang-analyzer-*,*'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle:     none
User:            ruki
CheckOptions:
  - key:             readability-suspicious-call-argument.PrefixSimilarAbove
    value:           '30'
  - key:             cppcoreguidelines-no-malloc.Reallocations
    value:           '::realloc'

改善 target 装备来历剖析

咱们改善了 xmake show -t target 指令对 target 信息的展示,新增了装备来历剖析,而且精简了一些相对冗余的信息。

咱们能够用它更好地排查定位自己装备的一些 flags 实践来自那一行装备。

显现效果如下:

$ xmake show -t tbox
The information of target(tbox):
    at: /Users/ruki/projects/personal/tbox/src/tbox/xmake.lua
    kind: static
    targetfile: build/macosx/x86_64/release/libtbox.a
    rules:
      -> mode.release -> ./xmake.lua:26
      -> mode.debug -> ./xmake.lua:26
      -> utils.install.cmake_importfiles -> ./src/tbox/xmake.lua:15
      -> utils.install.pkgconfig_importfiles -> ./src/tbox/xmake.lua:16
    options:
      -> object -> ./src/tbox/xmake.lua:53
      -> charset -> ./src/tbox/xmake.lua:53
      -> database -> ./src/tbox/xmake.lua:53
    packages:
      -> mysql -> ./src/tbox/xmake.lua:43
      -> sqlite3 -> ./src/tbox/xmake.lua:43
    links:
      -> pthread -> option(__keyword_thread_local) -> @programdir/includes/check_csnippets.lua:100
    syslinks:
      -> pthread -> ./xmake.lua:71
      -> dl -> ./xmake.lua:71
      -> m -> ./xmake.lua:71
      -> c -> ./xmake.lua:71
    defines:
      -> __tb_small__ -> ./xmake.lua:42
      -> __tb_prefix__="tbox" -> ./src/tbox/xmake.lua:19
      -> _GNU_SOURCE=1 -> option(__systemv_semget) -> @programdir/includes/check_cfuncs.lua:104
    cxflags:
      -> -Wno-error=deprecated-declarations -> ./xmake.lua:22
      -> -fno-strict-aliasing -> ./xmake.lua:22
      -> -Wno-error=expansion-to-defined -> ./xmake.lua:22
      -> -fno-stack-protector -> ./xmake.lua:51
    frameworks:
      -> CoreFoundation -> ./src/tbox/xmake.lua:38
      -> CoreServices -> ./src/tbox/xmake.lua:38
    mxflags:
      -> -Wno-error=deprecated-declarations -> ./xmake.lua:23
      -> -fno-strict-aliasing -> ./xmake.lua:23
      -> -Wno-error=expansion-to-defined -> ./xmake.lua:23
    includedirs:
      -> src -> ./src/tbox/xmake.lua:26
      -> build/macosx/x86_64/release -> ./src/tbox/xmake.lua:27
    headerfiles:
      -> src/(tbox/**.h)|**/impl/**.h -> ./src/tbox/xmake.lua:30
      -> src/(tbox/prefix/**/prefix.S) -> ./src/tbox/xmake.lua:31
      -> build/macosx/x86_64/release/tbox.config.h -> ./src/tbox/xmake.lua:34
    files:
      -> src/tbox/*.c -> ./src/tbox/xmake.lua:56
      -> src/tbox/hash/bkdr.c -> ./src/tbox/xmake.lua:57
      -> src/tbox/hash/fnv32.c -> ./src/tbox/xmake.lua:57
    compiler (cc): /usr/bin/xcrun -sdk macosx clang
      -> -Qunused-arguments -target x86_64-apple-macos12.6 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk
    linker (ar): /usr/bin/xcrun -sdk macosx ar
      -> -cr
    compflags (cc):
      -> -Qunused-arguments -target x86_64-apple-macos12.6 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk -Wall -Werror -Oz -std=c99 -Isrc -Ibuild/macosx/x86_64/release -D__tb_small__ -D__tb_prefix__=\"tbox\" -D_GNU_SOURCE=1 -framework CoreFoundation -framework CoreServices -Wno-error=deprecated-declarations -fno-strict-aliasing -Wno-error=expansion-to-defined -fno-stack-protector
    linkflags (ar):
      -> -cr

改善包的下载装备

假如有些包的 url 下载,需求设置特定 http headers 去鉴权后,才干经过下载,能够经过这个战略来指定。

这通常用于一些公司内部的私有库房包的维护。

package("xxx")
    set_policy("package.download.http_headers", "TEST1: foo", "TEST2: bar")

咱们也能够设置指定的 urls 的 http headers:

package("zlib")
    add_urls("https://github.com/madler/zlib/archive/$(version).tar.gz", {
        http_headers = {"TEST1: foo", "TEST2: bar"}
    })

改善 dlang 东西链支撑

先前的版别,Xmake 只是供给了 dlang 这一个东西链,内部会主动取查找 dmd, ldc2, gdc 来适配挑选能够获取到的 dlang 编译器去编译项目。

可是这种方法,对用户而言,无法愈加灵敏地去挑选指定的编译器,假如一起安装了 dmd, ldc2,那么 Xmake 总是会优先运用 dmd 作为 dlang 的编译器。

因此,新版别中,xmake 额定供给了三个独立的东西链能够独自挑选需求的 dlang 编译器。

比方,运转下面的指令,就能够快速切换到 ldc2 编译器去编译项目。

$ xmake f --toolchain=ldc
$ xmake

除了 ldc 东西链,还有 dmd, gdc 这两个东西链能够独自挑选运用。

而且,咱们还改善了 dmd/ldc2 的编译优化选项装备,使得出产的 dlang 二进制程序愈加的小而快。

支撑外置构建目录装备

现有的内置构建目录形式

Xmake 现在供给的构建目录形式,归于内置构建目录,也便是假如咱们在当时工程根目录下运转 xmake 指令,就会主动生成 build 目录,而且 .xmake 用于存放一些装备缓存。

- projectdir (workdir)
  - build (generated)
  - .xmake (generated)
  - src
  - xmake.lua
$ cd projectdir
$ xmake

当然,咱们能够经过 xmake f -o ../build 去装备修改构建目录,可是 .xmake 目录仍是在工程源码目录下。

$ cd projectdir
$ xmake f -o ../build

这关于一些喜爱彻底代码目录坚持完好洁净的用户而言,可能并不喜爱这种方法。

新的外置构建目录形式

因此,新版别中,Xmake 供给了别的一种构建目录装备方法,也便是外置目录构建(类似 CMake)。

比方,咱们想运用下面这种目录结构去构建项目,总是坚持源码目录洁净。

- workdir
  - build (generated)
  - .xmake (generated)
- projectdir
  - src
  - xmake.lua

咱们只需求进入需求存储 build/.xmake 目录的工作目录下,然后运用 xmake f -P [projectdir] 装备指令去指定源码根目录即可。

$ cd workdir
$ xmake f -P ../projectdir
$ xmake

装备完成后,源码根目录就被彻底记住了,后面的任何构建指令,都不需求再去设置它,就跟之前一样运用就行。

比方,构建,重建,运转或许安装等指令,跟之前的运用彻底一致,用户感觉不到任何差异。

$ xmake
$ xmake run
$ xmake --rebuild
$ xmake clean
$ xmake install

咱们同样能够运用 -o/--buildir 参数去独自设置构建目录到其他地方,例如设置成下面这个结构。

- build (generated)
- workdir
  - .xmake (generated)
- projectdir
  - src
  - xmake.lua
$ cd workdir
$ xmake f -P ../projectdir -o ../build

更新内容

新特性

  • 增加 Haiku 支撑
  • #3326: 增加 xmake check 去检测工程代码 (clang-tidy) 和 API 参数装备
  • #3332: 在包中装备增加自定义 http headers

改善

  • #3318: 改善 dlang 东西链
  • #2591: 改善 target 装备来历剖析
  • 为 dmd/ldc2 改善 strip/optimization
  • #3342: 改善装备构建目录,支撑外置目录构建,坚持源码目录愈加洁净
  • #3373: 为 clang-17 改善 std 模块支撑

Bugs 修正

  • #3317: 针对 Qt 工程,修正 lanuages 设置
  • #3321: 修正隔天 configfiles 从头生成导致重编问题
  • #3296: 修正 macOS arm64 上构建失利

Xmake v2.7.7 发布,支撑 Haiku 渠道,改善 API 检测和 C++ Modules 支撑 (tboox.org)