Skip to content

门泊吴船亦已谋

使用 xmake 管理 C++ 项目

受够了 CMake 的折磨,用了 xmake 之后我的心中只剩下感恩。

还是先贴一个比较完善的模板项目。

Xmake Template

实际上 xmake 跟 CMake 还是非常相似的,但是它更加简洁,而且功能可能也比 CMake 更强大。 作者也对这个项目充满了热情,前景还是比较好的。

另外提一嘴之前一段神奇的事情。我那个时候给嵌入式写了一个库。因为依赖问题非常操蛋,不得已试了一下 xmake。实际上我对它的交叉编译是没有信心的。结果我查完文档,直接一行命令直接配好了甲方给的工具链,然后直接给他构建好,我当时直接一个感动直接两只眼睛直接流下热泪。

因为 xmake 的设计跟 CMake 极为类似,所以 CMake 用户过渡到 xmake 是非常丝滑的。 本文也会少说点废话,直接贴代码。

项目

配置项目名和项目版本。

set_project("Demo")
set_version("0.0.1", {build = "%Y%m%d%H%M"})

指定 xmake 版本

指定构建工具的版本是一个好习惯。

set_xmakever("2.6.1")

指定语言标准

如果当前没有目标,那就会全局配置。

set_languages("cxx20")

也可以同时指定 C++ 和 C 的标准

set_languages("c99", "cxx11")

目标

跟 CMake 里的目标一样,xmake 中每个目标也是一个相对独立的构建单元。 一个目标的构建结果可以是一个可执行文件或一个类库。

可执行文件目标就可以长这样。

target("Hello")
    set_kind("binary")
    add_files("Hello.cpp")

静态类的目标就会长这样。

target("HelloLib")
    set_kind("static")
    add_files("src/*.cpp")
    add_includedirs("include", { public = true })
    add_headerfiles("include/(HelloLib/*.h)")

注意, add_includedirs 是用于添加头文件搜索路径,而 add_headerfiles 则是需要安装的头文件。

目标依赖

如果需要 Hello 目标依赖 HelloLib 这个类库目标并暴露类库的公有头文件,那就可以这样写。

target("Hello")
    set_kind("binary")
    add_deps("Protocon")
    add_files("Hello.cpp")

包依赖

包是可以用 xmake 管理的外部库。 可以在 xrepo 上查看其文档与仓库中目前所有的包。

作为示例,我们导入 gtest 并使用它来给 HelloLib 做单元测试。

首先我们在项目中添加需要依赖的 gtest 这个包。 同样的,指定版本号是一个好习惯。

add_requires("gtest 1.11.0")

其次定义一个 Tests 的可执行文件目标。 其中我们用 set_default 把这个目标设为非默认目标,这样就把这个测试跟类库本身区分开。 链接到我们需要测试的 HelloLib。 添加测试的源文件。 在 Windows 下我们需要特判一下加一个链接器标记,因为我们不想手写 main 函数,直接用 gtest 的类库里提供的。 用 add_package 把 gtest 这个包链接到我们的 Tests 目标上。

target("Tests")
    set_kind("binary")
    set_default(false)
    add_deps("HelloLib")
    add_files("*.cpp")
    if is_plat("windows") then
        add_ldflags("/subsystem:console")
    end
    add_packages("gtest")

然后正常写测试就行了。

#include <gtest/gtest.h>

TEST(TestSimple, HelloWorldOk) {
    EXPECT_EQ(1 + 1, 2);
}

接下来我们敲这个命令直接构建所有的目标并确认下载安装所需的 gtest 依赖包。

$ xmake -ay

最后敲这个命令跑我们的测试。

$ xmake r Tests