英文:
How to use CMake to build a project with C++23 standard library module(import std)?
问题
As we know, C++23支持标准库模块。直到2023年5月,MSVC支持它,但我们需要手动添加标准库模块,如Microsoft博客所述。
但在CMake项目中如何使用import std
呢?MS博客没有提到。并且这些文件无法工作(std.ifc
文件来自Microsoft博客教程:cl /std:c++latest /EHsc /nologo /W4 /MTd /c "%VCToolsInstallDir%\modules\std.ixx"
(在msvc x64本机控制台中使用))。
CMakeList.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.26)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${CMAKE_PROJECT_NAME})
set(CMAKE_CXX_STANDARD 23)
project(1-1)
add_executable(${CMAKE_PROJECT_NAME})
target_sources(${CMAKE_PROJECT_NAME}
PUBLIC
FILE_SET all_my_modules TYPE CXX_MODULES FILES
main.cpp
std.ifc
)
main.cpp
import std;
using namespace std;
int main(){
cout<<"Hello\n";
}
MSVC显示:
[build] main.cpp(1,11): error C2230: Could not find module "std"
[build] main.cpp(5,5): error C2065: "cout" : Undeclared identifier
我可以复制%VCToolsInstallDir\modules\std.ixx
到项目文件夹并将std.ifc
更改为std.ixx
,但是否有更加优雅的方法来避免每次构建std模块?我认为这是因为.ifc
不是源文件,如何在CMake中处理它?
英文:
As we know, C++23 support Standard Library Modules. Until May 2023, MSVC support it but we need add Standard Library Modules manually as Microsoft blog mentioned.
But how to use import std
in CMake project? The MS blog doesn't mentioned it. And these files can't work.(The std.ifc
file is obtained from microsoft blog tutorial:cl /std:c++latest /EHsc /nologo /W4 /MTd /c "%VCToolsInstallDir%\modules\std.ixx"
(use in msvc x64 native console))
CMakeList.txt
CMAKE_MINIMUM_REQUIRED(VERSION 3.26)
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${CMAKE_PROJECT_NAME})
set(CMAKE_CXX_STANDARD 23)
project(1-1)
add_executable(${CMAKE_PROJECT_NAME})
target_sources(${CMAKE_PROJECT_NAME}
PUBLIC
FILE_SET all_my_modules TYPE CXX_MODULES FILES
main.cpp
std.ifc
)
main.cpp
import std;
using namespace std;
int main(){
cout<<"Hello\n";
}
And MSVC shows:
[build] main.cpp(1,11): error C2230: Could not find module "std"
[build] main.cpp(5,5): error C2065: "cout" : Undeclared identifier
I can use copy %VCToolsInstallDir\modules\std.ixx
to project folder and change std.ifc
to std.ixx
, but is there a more elegant way to achieve it to avoid building std module every time? I think it's because .ifc
is not a source file,how to deal with it in CMake?
答案1
得分: 3
使用Visual Studio 17.6.0,这变得非常简单。只需将 CMAKE_CXX_STANDARD
设置为使用C++23:
[...]
set(CMAKE_CXX_STANDARD 23)
add_executable(demo)
target_sources(demo
PRIVATE
demo.cpp
)
这将将VS配置属性 C/C++->Language->C++ Language Standard
设置为 /std:c++latest
。Visual Studio 17.6 现在还提供了一个属性 C/C++->Language->Build ISO C++23 Standard Library Modules
,默认设置为 Yes
并将自动在项目构建中作为 /std:c++latest
构建标准库模块。因此不再需要特殊处理。
CMake 目前正在考虑提供一个控制此属性的选项。
对于较旧版本的Visual Studio,您需要在导入之前自行编译名为 std
的模块。
由于CMake目前不支持导入预编译模块,因此使一切正常运行的最简单方法是简单地在项目中包含标准库的主模块接口。
请确保首先阅读此答案,以了解CMake中C++20模块的当前先决条件和限制。
CMakeLists.txt
[...]
add_executable(demo)
file(COPY
# 不要在实际项目中硬编码路径,
# 但你明白意思
"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.36.32532/modules/std.ixx"
DESTINATION
${PROJECT_BINARY_DIR}/stdxx
)
target_sources(demo
PRIVATE
FILE_SET CXX_MODULES FILES
${PROJECT_BINARY_DIR}/stdxx/std.ixx
PRIVATE
demo.cpp
)
demo.cpp
import std;
int main()
{
std::cout << "Hello World\n";
}
CMake rightly prevents you from including module sources outside of your source tree in the build. So we will copy the module interface file to our binary tree for building.
As usual, having the same primary module interface appear more than once in a program is not allowed. Structure your build accordingly so that you don't accidentally end up with std.ixx
being compiled twice.
英文:
With Visual Studio version 17.6.0 this became very straightforward. Simply set CMAKE_CXX_STANDARD
to use C++23:
[...]
set(CMAKE_CXX_STANDARD 23)
add_executable(demo)
target_sources(demo
PRIVATE
demo.cpp
)
This will set the VS configuration property C/C++->Language->C++ Language Standard
to /std:c++latest
. Visual Studio 17.6 now also provides a property C/C++->Language->Build ISO C++23 Standard Library Modules
which by default is set to Yes
and will automatically build the standard library modules on /std:c++latest
as part of your project build. So no special handling is required anymore.
CMake is currently considering to provide an option for controlling this property.
For older versions of Visual Studio, you will have to compile the std
named module yourself before importing it.
Since CMake does not support importing pre-compiled modules at the moment, the easiest way to get things running is therefore to simply include the primary module interface for the standard library in your project.
Be sure to first read this answer to understand the current prerequisites and limitations of the C++20 modules in CMake.
CMakeLists.txt
[...]
add_executable(demo)
file(COPY
# you don't want to hardcode the path here in a real-world project,
# but you get the idea
"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.36.32532/modules/std.ixx"
DESTINATION
${PROJECT_BINARY_DIR}/stdxx
)
target_sources(demo
PRIVATE
FILE_SET CXX_MODULES FILES
${PROJECT_BINARY_DIR}/stdxx/std.ixx
PRIVATE
demo.cpp
)
demo.cpp
import std;
int main()
{
std::cout << "Hello World\n";
}
CMake rightfully prevents you from including module sources outside of your source tree in the build. So we will copy the module interface file to our binary tree for building.
As usual, having the same primary module interface appear more than once in a program is not allowed. Structure your build accordingly so that you don't accidentally end up with std.ixx
being compiled twice.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论