Xmake 采用 .mpp
作为默认的模块扩展名,但是也同时支持 .ixx
, .cppm
, .mxx
等扩展名。
目前 xmake 已经完整支持 gcc11/clang/msvc 的 C++20 Modules 构建支持,并且能够自动分析模块间的依赖关系,实现最大化并行编译。
set_languages("c++20")
target("class")
set_kind("binary")
add_files("src/*.cpp", "src/*.mpp")
更多例子见:C++ Modules
Cpp-Only 工程
v2.7.1 版本对 C++20 模块的实现进行了重构和升级,新增了对 Headerunits 的支持,我们可以在模块中引入 Stl 和 用户头文件模块。
相关的补丁见:#2641。
注:通常我们至少需要添加一个 .mpp
文件,才能开启 C++20 modules 编译,如果只有 cpp 文件,默认是不会开启模块编译的。
但是,如果我们仅仅只是想在 cpp 文件中使用模块的 Headerunits 特性,比如引入一些 stl Headerunits 在 cpp 中使用, 那么我们也可以通过设置 set_policy("build.c++.modules", true)
来强行开启 C++ Modules 编译,例如:
add_rules("mode.debug", "mode.release")
target("test")
set_kind("binary")
add_files("src/*.cpp")
set_languages("c++20")
set_policy("build.c++.modules", true)
模块的分发和集成
分发 C++ Modules 包
我们先使用 xmake.lua 维护模块的构建,并通过指定 {install = true}
,来告诉 xmake 哪些模块文件需要安装对外分发。
add_rules("mode.release", "mode.debug")
set_languages("c++20")
target("foo")
set_kind("static")
add_files("*.cpp")
add_files("*.mpp", { install = true })
然后,我们把它做成包,可以提交到 xmake-repo 仓库,当然也可以直接做成本地包,或者私有仓库包。
这里,为了方便测试验证,我们仅仅通过 set_sourcedir
将它做成本地包。
package("foo")
set_sourcedir(path.join(os.scriptdir(), "src"))
on_install(function(package)
import("package.tools.xmake").install(package, {})
end)
集成 C++ Modules 包
然后,我们通过 add_requires("foo")
的包集成接口,对 C++ Modules 包进行快速集成使用。
由于 foo 的模块包,我们放在私有仓库中定义,所以我们通过 add_repositories("my-repo my-repo")
引入自己的包仓库。
如果,包已经提交到 xmake-repo 官方仓库,就不需要额外配置它。
add_rules("mode.release", "mode.debug")
set_languages("c++20")
add_repositories("my-repo my-repo")
add_requires("foo", "bar")
target("packages")
set_kind("binary")
add_files("src/*.cpp")
add_packages("foo", "bar")
set_policy("build.c++.modules", true)
集成好包后,我们就可以执行 xmake
命令,一键下载、编译、集成 C++ Modules 包来使用。
$ xmake
checking for platform ... linux
checking for architecture ... x86_64
note: install or modify (m) these packages (pass -y to skip confirm)?
in my-repo:
-> foo latest
-> bar latest
please input: y (y/n/m)
=> install bar latest .. ok
=> install foo latest .. ok
[ 0%]: generating.module.deps src/main.cpp
[ 0%]: generating.module.deps /mnt/xmake/tests/projects/c++/modules/packages/build/.packages/b/bar/latest/4e0143c97b65425b855ad5fd03038b6a/modules/bar/bar.mpp
[ 0%]: generating.module.deps /mnt/xmake/tests/projects/c++/modules/packages/build/.packages/f/foo/latest/4e0143c97b65425b855ad5fd03038b6a/modules/foo/foo.mpp
[ 14%]: compiling.module.release bar
[ 14%]: compiling.module.release foo
[ 57%]: compiling.release src/main.cpp
[ 71%]: linking.release packages
[100%]: build ok!
注:每个包安装后,会在包路径下,存储维护模块的 meta-info 文件,这是 p2473r1.pdf
中约定的一种格式规范,也许它不是最终的标准,但这并不影响我们现在去使用模块的分发。
$ cat ./build/.packages/f/foo/latest/4e0143c97b65425b855ad5fd03038b6a/modules/foo/foo.mpp.meta-info
{"_VENDOR_extension":{"xmake":{"name":"foo","file":"foo.mpp"}},"definitions":{},"include_paths":{}}
完整的例子工程见:C++ Modules 包分发例子工程
支持 C++23 Std Modules
Arthapz 也帮忙改进了对 C++23 Std Modules 的支持。
add_rules("mode.debug", "mode.release")
set_languages("c++latest")
target("mod")
set_kind("static")
add_files("src/*.cpp")
add_files("src/*.mpp", {public = true})
target("stdmodules")
set_kind("binary")
add_files("test/*.cpp")
add_deps("mod")
export module my_module;
import std;
export auto my_sum(std::size_t a, std::size_t b) -> std::size_t;
module my_module;
import std;
auto my_sum(std::size_t a, std::size_t b) -> std::size_t { return a + b; }