CMake无法构建C++23分区模块(GCC/Clang命令行可正常构建)
C++23分区模块CMake构建失败排查与解决
环境
- Ubuntu 24.04
- Clang 19、GCC 14
- CLion 2024.3.4
问题现象
作为演讲和书籍示例的C++23分区模块(包含MIU文件与实现文件)无法通过CMake构建,但非分区模块示例可正常构建。CMake执行构建时出现如下错误:
cmake -E cmake_ninja_dyndep --tdi=Javanese/CMakeFiles/javanese.dir/CXXDependInfo.json --lang=CXX --modmapfmt=gcc --dd=Javanese/CMakeFiles/javanese.dir/CXX.dd @Javanese/CMakeFiles/javanese.dir/CXX.dd.rsp CMake Error: Output Javanese/CMakeFiles/javanese.dir/balinese.cpp.o provides the `Javanese:Balinese` module but it is not found in a `FILE_SET` of type `CXX_MODULES` ninja: build stopped: cannot make progress due to previous errors.
但直接使用Clang或GCC命令行可正常编译运行,Clang编译命令及输出如下:
+ clang++ -std=c++23 --precompile Balinese.cppm -o bin/Javanese-Balinese.pcm + clang++ -std=c++23 --precompile -fprebuilt-module-path=bin Javanese.cppm -o bin/Javanese.pcm + clang++ -std=c++23 -c -fprebuilt-module-path=bin Javanese.cppm -o bin/Javanese.o + clang++ -std=c++23 -c -fprebuilt-module-path=bin javanese.cpp -o bin/javanese.o + clang++ -std=c++23 -c -fprebuilt-module-path=bin balinese.cpp -o bin/balinese.o + clang++ -std=c++23 -r bin/Javanese.o bin/javanese.o bin/balinese.o -o bin/Javanese.Module.o + clang++ -std=c++23 -c -fprebuilt-module-path=bin main.cpp -o bin/main.o + clang++ -std=c++23 bin/Javanese.Module.o bin/main.o -o bin/main + bin/main Kucing jawa ngomong 'mbelong' Balinese anak kucing says 'meong'
相关配置与代码文件
父目录CMakeLists.txt
cmake_minimum_required(VERSION 3.30.5) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # must appear before project() set(CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS "/usr/bin/clang-scan-deps") endif () project(pragmatic_modules LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_SCAN_FOR_MODULES ON) set(CMAKE_CXX_EXTENSIONS OFF) # other subdirectories add_subdirectory(Javanese)
Javanese目录CMakeLists.txt(原错误版本)
cmake_minimum_required(VERSION 3.30.5) project(Javanese LANGUAGES CXX) set(module_name javanese) add_executable(${PROJECT_NAME} main.cpp) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) target_link_libraries(${PROJECT_NAME} ${module_name}) add_library(${module_name}) target_compile_features(${module_name} PUBLIC cxx_std_23) target_sources(${module_name} PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES Balinese.cppm ${PROJECT_NAME}.cppm PRIVATE ${module_name}.cpp balinese.cpp )
分区模块MIU文件Balinese.cppm
module; export module Javanese:Balinese; namespace Balinese { export void meong(); }
分区模块实现文件balinese.cpp
module; #include <print> module Javanese:Balinese; namespace Balinese { auto meong() -> void { std::println("Balinese anak kucing says 'meong'"); } }
问题原因
CMake处理C++23模块时,要求所有模块单元(包括分区模块的实现单元)都必须被包含在CXX_MODULES类型的FILE_SET中。原配置里,balinese.cpp作为Javanese:Balinese分区模块的实现单元,被错误放在PRIVATE源文件列表中,而非FILE_SET cxx_modules的FILES集合内,导致CMake扫描模块依赖时无法识别该文件属于已声明的模块集合,从而抛出错误。
解决方案
修改Javanese目录下的CMakeLists.txt,将balinese.cpp移至FILE_SET cxx_modules的FILES列表中;如果javanese.cpp是主模块的实现单元,同样需要移入该集合:
cmake_minimum_required(VERSION 3.30.5) project(Javanese LANGUAGES CXX) set(module_name javanese) add_executable(${PROJECT_NAME} main.cpp) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23) target_link_libraries(${PROJECT_NAME} ${module_name}) add_library(${module_name}) target_compile_features(${module_name} PUBLIC cxx_std_23) target_sources(${module_name} PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES Balinese.cppm ${PROJECT_NAME}.cppm balinese.cpp ${module_name}.cpp )
调整后CMake可正确识别所有模块单元,完成依赖扫描与构建。
内容的提问来源于stack exchange,提问作者Rud48
相关产品推荐
相关产品推荐

