C++ 如何使用c++;使用CMake的20个模块?
并且已经支持未完成的C++20标准。 我可以用CMake或其他构建系统构建基于模块的项目吗?如何构建C++ 如何使用c++;使用CMake的20个模块?,c++,cmake,c++20,c++-modules,C++,Cmake,C++20,C++ Modules,并且已经支持未完成的C++20标准。 我可以用CMake或其他构建系统构建基于模块的项目吗?如何构建 我试过了,它支持模块,而且运行得很好,但我对它的依赖关系管理有一个疑问(UPD:问题已经解决)。我找不到对模块的Cmake支持。下面是一个如何使用clang的模块的示例。我正在使用Mac,这个例子在我的系统上运行正常。我花了很长时间才弄明白这一点,所以不确定这在linux或Windows中有多普遍 文件driver.cxx中的源代码 import hello; int main() { say_
我试过了,它支持模块,而且运行得很好,但我对它的依赖关系管理有一个疑问(UPD:问题已经解决)。我找不到对模块的Cmake支持。下面是一个如何使用clang的模块的示例。我正在使用Mac,这个例子在我的系统上运行正常。我花了很长时间才弄明白这一点,所以不确定这在linux或Windows中有多普遍 文件driver.cxx中的源代码
import hello;
int main() { say_hello("Modules"); }
文件hello.cxx中的源代码
#include <iostream>
module hello;
void say_hello(const char *n) {
std::cout << "Hello, " << n << "!" << std::endl;
}
要用上面的源文件编译代码,这里是终端上的命令行
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
并且在下一次编译时有一个干净的开始
rm -f *.o
rm -f hello
rm -f hello.pcm
预期产量
./hello
Hello, Modules!
希望这对您有所帮助。CMake目前不支持C++20模块 另见。请注意,与插入新的编译器选项相比,支持模块需要构建系统提供更多的支持。它从根本上改变了在构建过程中必须处理源文件之间依赖关系的方式:在预模块世界中,所有cpp源文件都可以以任何顺序独立构建。模块不再适用,这不仅对CMake本身有影响,而且对下游构建系统也有影响 看看这本书,看看那些血淋淋的细节。从构建系统的角度来看,Fortran模块的行为与C++20模块非常相似
更新:CMake 3.20引入了对带有忍者生成器的模块的实验支持(并且仅适用于忍者)。有关详细信息,请参阅。在这个阶段,这个特性仍然是高度实验性的,不打算用于生产。无论如何,如果你想玩这个游戏,你真的应该同时阅读和来了解你正在进入的领域。CMake目前不支持C++20模块,就像其他人所说的那样。然而,Fortran的模块支持非常相似,也许可以很容易地将其更改为支持C++20中的模块
现在,也许我有一个简单的方法来修改它以直接支持C++20。不确定。如果您解决了拉请求,则值得探索和执行拉请求。这在Linux Manjaro(与Arch相同)上有效,但在任何Unix操作系统上都应该有效。当然,您需要使用新的clang进行构建(使用clang-10进行测试) helloworld.cpp:
export module helloworld;
import <cstdio>;
export void hello() { puts("Hello world!"); }
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)
假设您使用的是gcc 11,即使没有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})
一些解释:
iostream
不考虑下面的<代码>主体.CPP < /代码>:
导入mymod;
int main(){
helloModule();
}
和mymod.cpp
:
模块;
导出模块mymod;
进口;
导出无效helloModule(){
std::您可能会使用设置和CMake if语句的组合来检查Clang或MSVC,然后根据您的编译器添加适当的编译器标志。我尝试使用Clang和-std=c++2a-fmodules ts
进行编译,结果显示致命错误:未找到模块“VulkanRender”。我如何告诉Clang我的模块在哪里我尝试了BuffD2,我回答了我的问题。所有的东西都很好。这是一个很好的答案——但不是这个问题。你可以考虑制定一个问题(“使用模块来构建C++程序的简单例子?”)模块,并将其与此答案一起发布。在过去18个月内有什么变化吗?@Lothar MSVC现在在版本16.8及更高版本上发布了一个比以前功能更强的模块实现。但是,该版本目前仍在预览中,无法在主发布渠道上获得。目前还不清楚是否实现了该版本Automation已经提供了与CMake进行适当构建系统集成所需的一切。一般来说,由于该功能对整个构建过程的深刻影响,我预计这将需要几年时间(!)在将此问题解决到可以将其用于生产性代码库的级别之前。为什么需要将helloworld.cpp
添加到main
可执行文件的源中?需要创建对象文件(.o)使用CMake,您可能会添加另一个函数,该函数将从模块cpp文件创建对象库,并将它们添加到可执行文件,但这超出了本答案的范围。
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)
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})
error: import "/usr/include/c++/11/iostream" has CRC mismatch