Bla*_*aze 8 c++ cmake c++20 c++-modules
Clang和MSVC已经支持来自未完成的C ++ 20标准的Modules TS。我可以使用CMake或其他构建系统来构建基于模块的项目吗?
Com*_*sMS 18
CMake 目前不支持 C++20 模块。
另请参阅CMake 问题跟踪器中的相关问题。请注意,与插入新的编译器选项相比,支持模块需要来自构建系统的更多支持。它从根本上改变了在构建过程中必须如何处理源文件之间的依赖关系:在预模块世界中,所有 cpp 源文件都可以按任何顺序独立构建。使用不再正确的模块,这不仅对 CMake 本身有影响,而且对下游构建系统也有影响。
查看CMake Fortran 模块论文以了解详细信息。从构建系统的角度来看,Fortran 模块的行为与 C++20 模块非常相似。
更新: CMake 3.20 引入了对带有 Ninja Generator 的模块的实验性支持(并且仅适用于 Ninja)。详细信息可以在相应的拉取请求中找到。在此阶段,此功能仍处于高度试验阶段,不打算用于生产用途。如果你无论如何都打算玩这个,你真的应该阅读Fortran 模块文件和依赖格式文件来了解你正在进入的内容。
and*_*eee 15
假设您使用 gcc 11 和 Makefile 生成器,即使没有 CMake 对 C++20 的支持,以下代码也应该可以工作:
cmake_minimum_required(VERSION 3.19) # Lower versions should also be supported
project(cpp20-modules)
# Add target to build iostream module
add_custom_target(std_modules ALL
COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules"
COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# Function to set up modules in GCC
function (prepare_for_module TGT)
target_compile_options(${TGT} PUBLIC -fmodules-ts)
set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20)
set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF)
add_dependencies(${TGT} std_modules)
endfunction()
# Program name and sources
set (TARGET prog)
set (SOURCES main.cpp)
set (MODULES mymod.cpp)
# Setup program modules object library
set (MODULE_TARGET prog-modules)
add_library(${MODULE_TARGET} OBJECT ${MODULES})
prepare_for_module(${MODULE_TARGET})
# Setup executable
add_executable(${TARGET} ${SOURCES})
prepare_for_module(${TARGET})
# Add modules to application using object library
target_link_libraries(${TARGET} PRIVATE ${MODULE_TARGET})
Run Code Online (Sandbox Code Playgroud)
一些解释:
iostream在这里添加。不考虑以下情况main.cpp:
cmake_minimum_required(VERSION 3.19) # Lower versions should also be supported
project(cpp20-modules)
# Add target to build iostream module
add_custom_target(std_modules ALL
COMMAND ${CMAKE_COMMAND} -E echo "Building standard library modules"
COMMAND g++ -fmodules-ts -std=c++20 -c -x c++-system-header iostream
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
# Function to set up modules in GCC
function (prepare_for_module TGT)
target_compile_options(${TGT} PUBLIC -fmodules-ts)
set_property(TARGET ${TGT} PROPERTY CXX_STANDARD 20)
set_property(TARGET ${TGT} PROPERTY CXX_EXTENSIONS OFF)
add_dependencies(${TGT} std_modules)
endfunction()
# Program name and sources
set (TARGET prog)
set (SOURCES main.cpp)
set (MODULES mymod.cpp)
# Setup program modules object library
set (MODULE_TARGET prog-modules)
add_library(${MODULE_TARGET} OBJECT ${MODULES})
prepare_for_module(${MODULE_TARGET})
# Setup executable
add_executable(${TARGET} ${SOURCES})
prepare_for_module(${TARGET})
# Add modules to application using object library
target_link_libraries(${TARGET} PRIVATE ${MODULE_TARGET})
Run Code Online (Sandbox Code Playgroud)
和mymod.cpp:
import mymod;
int main() {
helloModule();
}
Run Code Online (Sandbox Code Playgroud)
使用上面的内容CMakeLists.txt,您的示例应该可以正常编译(已在 Ubuntu WSL 中使用 gcc 1.11.0 成功测试)。
更新:
有时更改CMakeLists.txt并重新编译时,可能会遇到错误
error: import "/usr/include/c++/11/iostream" has CRC mismatch
Run Code Online (Sandbox Code Playgroud)
可能的原因是每个新模块都会尝试构建标准库模块,但我不确定。不幸的是,我没有找到合适的解决方案(如果gcm.cache您想添加新的标准模块,则在目录已存在的情况下避免重建是不好的,并且按模块执行此操作是维护噩梦)。我的 Q&D 解决方案是删除${CMAKE_BINARY_DIR}/gcm.cache并重建模块。不过,我很高兴能得到更好的建议。
war*_*tua 13
这适用于 Linux Manjaro(与 Arch 相同),但应该适用于任何 Unix 操作系统。当然,您需要使用新的 clang 进行构建(使用 clang-10 进行测试)。
你好世界.cpp:
export module helloworld;
import <cstdio>;
export void hello() { puts("Hello world!"); }
Run Code Online (Sandbox Code Playgroud)
主.cpp:
import helloworld; // import declaration
int main() {
hello();
}
Run Code Online (Sandbox Code Playgroud)
CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(main)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(PREBUILT_MODULE_PATH ${CMAKE_BINARY_DIR}/modules)
function(add_module name)
file(MAKE_DIRECTORY ${PREBUILT_MODULE_PATH})
add_custom_target(${name}.pcm
COMMAND
${CMAKE_CXX_COMPILER}
-std=c++20
-stdlib=libc++
-fmodules
-c
${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}
-Xclang -emit-module-interface
-o ${PREBUILT_MODULE_PATH}/${name}.pcm
)
endfunction()
add_compile_options(-fmodules)
add_compile_options(-stdlib=libc++)
add_compile_options(-fbuiltin-module-map)
add_compile_options(-fimplicit-module-maps)
add_compile_options(-fprebuilt-module-path=${PREBUILT_MODULE_PATH})
add_module(helloworld helloworld.cpp)
add_executable(main
main.cpp
helloworld.cpp
)
add_dependencies(main helloworld.pcm)
Run Code Online (Sandbox Code Playgroud)
小智 1
我找不到 Cmake 对模块的支持。以下是如何使用 clang 使用模块的示例。我使用的是 Mac,这个示例在我的系统上运行正常。我花了很长时间才弄清楚这一点,所以不确定这在 Linux 或 Windows 中有多普遍。
文件driver.cxx中的源代码
import hello;
int main() { say_hello("Modules"); }
Run Code Online (Sandbox Code Playgroud)
源代码位于文件 hello.cxx 中
#include <iostream>
module hello;
void say_hello(const char *n) {
std::cout << "Hello, " << n << "!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
源代码位于文件 hello.mxx 中
export module hello;
export void say_hello (const char* name);
Run Code Online (Sandbox Code Playgroud)
要使用上述源文件编译代码,这里是终端上的命令行
clang++ \
-std=c++2a \
-fmodules-ts \
--precompile \
-x c++-module \
-Xclang -fmodules-embed-all-files \
-Xclang -fmodules-codegen \
-Xclang -fmodules-debuginfo \
-o hello.pcm hello.mxx
clang++ -std=c++2a -fmodules-ts -o hello.pcm.o -c hello.pcm
clang++ -std=c++2a -fmodules-ts -x c++ -o hello.o \
-fmodule-file=hello.pcm -c hello.cxx
clang++ -std=c++2a -fmodules-ts -x c++ -o driver.o \
-fmodule-file=hello=hello.pcm -c driver.cxx
clang++ -o hello hello.pcm.o driver.o hello.o
Run Code Online (Sandbox Code Playgroud)
并在下一次编译时干净地开始
rm -f *.o
rm -f hello
rm -f hello.pcm
Run Code Online (Sandbox Code Playgroud)
预期产出
./hello
Hello, Modules!
Run Code Online (Sandbox Code Playgroud)
希望这会有所帮助,一切顺利。
| 归档时间: |
|
| 查看次数: |
657 次 |
| 最近记录: |