I’ve been trying to find some way to detect if the current generators and/or compiler supports c++ modules. Right now, I just have a giant set of "if"s, but given that cmake will bark at me that Visual Studio 2019 generator doesn’t support modules, it seems like I ought to be an if for that?
Looking to start transitioning to using modules for a mid-large (~2m 1st loc, 20k cmake 1st, ~6.8m 3rd loc, ~45k cmake) codebase that is routinely constrained by portability across 10+ platforms; I have a working solution but it’s definitely not something I would put into long-term production. 2am-pager-duty me would disapprove.
I have something similar but since we have to target variations of Linux, Android, Windows, MacOS, iOS, tvOS, watchOS, Xbox, Playstation, Switch, and some others, multiple architectures and simulators, it’s just a couple hundred lines longer So for the moment, instead, I’m using this stub just to experiment with our codebase and shelved the original.
But CMake clearly knows that Visual Studio 16 2019 generator can’t do it:
if (CMAKE_CXX_STANDARD GREATER_EQUAL 20 AND MSVC_VERSION GREATER_EQUAL 1930)
set (NUO_CXX_MODULES_AVAILABLE YES)
endif ()
if (NUO_CXX_MODULES_AVAILABLE)
message (STATUS "-- Optional C++ modules available")
endif ()
function (NUO_ENABLE_OPTIONAL_CXX_MODULES)
# args_MODULE_FILES is set to indicate that this is a module provider,
# vs a consumer.
# e.g
# NUO_ENABLE_OPTIONAL_CXX_MODULES(TARGET NuoProcess EXPORTS YES IMPORTS NO)
# Use "MODULE_FILES" to specify which .ixx files to use as module definitions.
cmake_parse_arguments (
args
""
"TARGET;EXPORTS;IMPORTS"
"MODULE_FILES"
${ARGN}
)
# TODO: Make messages 'VERBOSE' when we start to use this more commonly
set (MESSAGE_LEVEL STATUS)
# check for unused arguments
if (args_UNPARSED_ARGUMENTS)
message (FATAL_ERROR "NUO_ENABLE_CXX_MODULES: Unrecognized arguments: ${args_UNPARSED_ARGUMENTS}")
endif ()
if (NOT args_TARGET)
message (FATAL_ERROR "NUO_ENABLE_CXX_MODULES: Missing required argument: TARGET")
endif ()
if (NOT NUO_CXX_MODULES_AVAILABLE)
message (${MESSAGE_LEVEL} "-- Non-module flavor of ${args_TARGET}")
return ()
endif ()
if (args_EXPORTS AND NOT args_MODULE_FILES)
set (args_MODULE_FILES "${CMAKE_CURRENT_LIST_DIR}/${args_TARGET}.ixx")
if (NOT EXISTS ${args_MODULE_FILES})
message (FATAL_ERROR "NUO_ENABLE_CXX_MODULES: Default Module file not found: ${args_MODULE_FILES}")
endif ()
endif ()
if (args_MODULE_FILES AND NOT args_EXPORTS)
message (FATAL_ERROR "NUO_ENABLE_CXX_MODULES: Module files specified without EXPORTS YES")
endif ()
message (${MESSAGE_LEVEL} "-- Enabling C++ modules for target ${args_TARGET}: IMPORTS=${args_IMPORTS}, EXPORTS=${args_EXPORTS}")
# Tell the code, with a #define.
if (args_EXPORTS)
target_compile_definitions (${args_TARGET} PRIVATE -DNUO_CXX_MODULES_ENABLED=1)
endif ()
if (args_IMPORTS)
target_compile_definitions (${args_TARGET} PRIVATE -DNUO_CXX_IMPORTS_ENABLED=1)
endif ()
# Allow the module to use other modules.
if (args_IMPORTS)
set_target_properties (${args_TARGET} PROPERTIES CMAKE_CXX_SCAN_FOR_MODULES ON)
endif ()
# If this is an module provider, add the module definitions as sources.
if (args_MODULE_FILES)
target_sources (
${args_TARGET}
PUBLIC
FILE_SET cxx_modules TYPE CXX_MODULES
FILES ${args_MODULE_FILES}
)
endif ()
endfunction()
BTW, isn’t “CMAKE_CXX_MODULE_STD” supposed to be “1”? Or is that just for CMake 4? As in, it’s an integer revision number for the module standard that cmake itself is implementing?