CMake already supports the most basic use of module
, which is good, but the module
itself doesn't seem to be ready, or rather the large number of libraries consisting of header files + source files
is not ready.
Here is a minimal example for MSVC
:
cmake_minimum_required(VERSION 3.25)
if (CMAKE_VERSION VERSION_LESS "3.26")
# 3.25
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
elseif (CMAKE_VERSION VERSION_LESS "3.27")
# 3.26
set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
else ()
message(FATAL_ERROR "See `https://github.com/Kitware/CMake/blob/v${CMAKE_VERSION}/Help/dev/experimental.rst`.")
endif (CMAKE_VERSION VERSION_LESS "3.26")
# turn on the dynamic depends for ninja
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)
project(test)
set(TEMP_CXX_MODULE_PATH ${CMAKE_BINARY_DIR}/temp_module)
if (NOT DEFINED ENV{VCToolsInstallDir})
message(FATAL_ERROR "Unable to find path to VC Tools in environment variables!")
endif (NOT DEFINED ENV{VCToolsInstallDir})
if (NOT EXISTS $ENV{VCToolsInstallDir})
message(FATAL_ERROR "Invalid VC Tools installation path!")
else ()
message(STATUS "Found VC Tools in: [$ENV{VCToolsInstallDir}]")
endif (NOT EXISTS $ENV{VCToolsInstallDir})
if (NOT EXISTS $ENV{VCToolsInstallDir}modules/std.ixx)
message(FATAL_ERROR "Cannot find std.ixx! Please check MSVC version(${CMAKE_CXX_COMPILER_VERSION})!")
else()
message(STATUS "Found module std.ixx in: [$ENV{VCToolsInstallDir}modules\\std.ixx]")
endif (NOT EXISTS $ENV{VCToolsInstallDir}modules/std.ixx)
add_executable(${PROJECT_NAME} main.cpp)
target_compile_features(
${PROJECT_NAME}
PUBLIC
cxx_std_23
)
set_target_properties(
${PROJECT_NAME}
PROPERTIES
CXX_STANDARD_REQUIRED ON
)
configure_file(
$ENV{VCToolsInstallDir}modules/std.ixx
${TEMP_CXX_MODULE_PATH}/std.ixx
COPYONLY
)
target_compile_options(
${PROJECT_NAME}
PRIVATE
/Wv:18
)
target_sources(
${PROJECT_NAME}
PRIVATE
FILE_SET module_files
TYPE CXX_MODULES
BASE_DIRS "${PROJECT_SOURCE_DIR}"
FILES
${TEMP_CXX_MODULE_PATH}/std.ixx
${PROJECT_SOURCE_DIR}/src/m1.ixx
${PROJECT_SOURCE_DIR}/src/m2.ixx
)
target_sources(
${PROJECT_NAME}
PUBLIC
FILE_SET header_files
TYPE HEADERS
BASE_DIRS "${PROJECT_SOURCE_DIR}"
FILES
${PROJECT_SOURCE_DIR}/src/test_header.hpp
)
File test_header.hpp
:
#include <concepts>
namespace test {
template<typename T>
concept no_matter_what_is = std::move_constructible<T>;
}
File m1.ixx
:
module;
#include <src/test_header.hpp>
export module m1;
export namespace test_m1 {
// Additionally, when a module-import-declaration in a module unit of some module M imports another module unit U of M,
// it also imports all translation units imported by non-exported module-import-declarations in the module unit purview of U.
template<test::no_matter_what_is T>
class M1 {};
// template<typename T>
// class M1_OK {};
// template<typename T>
// using M1 = M1_OK<T>;
}// namespace test_m1
File m2.ixx
:
export module m2;
import m1;
// for `std::move_constructible`
import std;
export namespace test_m2 {
// Error: error C7570: 'std::move_constructible': variable template has already been defined
template<std::move_constructible T>
class M2 : public test_m1::M1<T> {
};
}// namespace test_m2
File main.cpp
:
import std;
import m1;
import m2;
int main() {
test_m1::M1<int> m1{};
test_m2::M2<int> m2{};
return 0;
}
Output
:
C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Tools\MSVC\14.36.32323\include\concepts(116): error C7570: 'std::move_constructible': variable template has already been defined
The redefinition may be caused by a conflict between #include <concepts>
in test_header.hpp
and in import std;
, but I pessimistically think that this form of implicit export (I mean std::move_constructible
been exported due to the test_m1::M1
in module m1
) is inevitable, which means that to use the module
, all unready
third-party libraries must be discarded.
import std;
to work. However with 17.5 I have noticed that however you include/import something you need to be consistant about it. That said you may be able to get away with usingimport <concepts>;
or the flags that does that for you automagically – Lowpitchedimport <concepts>
, I mean, there are countless third-party libraries here, and you want to use them, but once youinclude
their files, you will face this problem. – Pampuch