使用 CMake 的实验性模块依赖扫描构建 C++ 模块

问题描述

CMake 具有实验性的 C++20 模块依赖项扫描 (!5562)。我尝试使用 CMake 3.20、g++-11 和 ninja-1.10 来构建带有模块的项目。

// main.cpp
import mod;
int main() { return 0; }
// mod.ixx
export module mod;
export void f() {}

CMakeLists.txt 是对 https://gitlab.kitware.com/ben.boeckel/cmake/blob/cpp-modules/Modules/Compiler/GNU-CXX.cmake

的改编
cmake_minimum_required(VERSION 3.20)
project(simple)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)

string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
        "<CMAKE_CXX_COMPILER> <DEFInes> <INCLUDES> <FLAGS> -E -x c++ <SOURCE>"
        " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
        " -fmodules-ts -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT>"
        " -fdep-format=trtbd")

set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")

set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG
        " -fmodules-ts -fmodule-mapper=<MODULE_MAP_FILE>"
        " -fdep-format=trtbd -x c++")

set(CMAKE_CXX_FLAGS "-fmodules-ts")
add_executable(simple main.cpp mod.ixx)

但是 CMake 和 ninja 不构建项目:

$ mkdir build && cd build
$ cmake -DCMAKE_CXX_COMPILER=<path to g++-11>/g++-11 -G Ninja ..

-- The C compiler identification is GNU 10.3.1
-- The CXX compiler identification is GNU 11.1.0
-- Detecting C compiler ABI info
...
-- Detecting CXX compile features - done
-- Configuring done 
-- Generating done
-- Build files have been written to: <...>

$ ninja

<...>/g++-11 -fmodules-ts -std=gnu++20 -MD -MT <...>/main.cpp.o 
    -MF <...>/main.cpp.o.d -o <...>/main.cpp.o -c ../main.cpp
In module imported at ../main.cpp:1:1:
mod: error: Failed to read compiled module: No such file or directory
mod: note: compiled module file is ‘gcm.cache/mod.gcm’
mod: note: imports must be built before being imported
mod: Fatal error: returning to the gate for a mechanical issue
compilation terminated.
ninja: build stopped: subcommand Failed.

此处评分最高的答案(来自 ComicSansMS)说我们可以使用实验功能来构建 C++20 模块: How to use c++20 modules with CMake?

CMake 是否可以自动扫描模块依赖并构建项目?

解决方法

GCC + CMake 的模块系统在这一点上非常具有实验性,在我看来,现在不值得篡改。我花了大约一个小时试图让它自动扫描,但我认为文档还没有完整说明如果可能的话。我需要查看非官方文档的 github 问题,看看是否有办法。就目前而言,我认为没有办法做到这一点。

您最好的选择是使用 Visual C++ 的模块系统,因为它们的 C++20 实现是功能完整的(没有最终的 ABI 实现)。我已经使用过它,除了内部编译错误之外,它对于我的测试项目来说足够稳定。那些是由于复杂的 constevals 而通过简化它们来缓解的。我确定其他复杂的模块代码也存在同样的问题,因此请注意它是否符合您的项目目标。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...