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?
Note that Visual Studio keeps changing how this works, I will try and update the answer as things progress.
As a prerequisite you need to 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 needs to be to Yes
and will then automatically build the standard library modules on /std:c++latest
as part of your project build.
This option used to be activated by default, but Visual Studio recently changed that default to No
, so you now need to activate that option manually. 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.