How to use a module BMI built outside of CMake to build module and executable

I’m on Ubuntu 24.04 with both GCC and Clang. I can build modules from the command line, with CMake, and inside CLion. I’m working to include “print” from the std but not the entire std. It builds on the command line to create BMI-appropriate directories for the compilers. CMake doesn’t support building the system headers except when it is experimental. This is going into a conference talk, so I don’t want to use experimental.

During configuration, I am building the BMI for GCC and Clang with an execute_process. I hoped to keep the artifacts in the parent directory so subdirectories could access them as necessary, which works with Clang.



# Detect the compiler
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    set(ExtBMIDir ${CMAKE_CURRENT_SOURCE_DIR}/pcm_cache)
    file(MAKE_DIRECTORY ${ExtBMIDir})

    set(BMI_COMMAND clang++ -std=c++23 -fmodule-header=system -xc++-header print -o ${ExtBMIDir}/print.pcm)
    set(PrintBMI ${ExtBMIDir}/print.pcm)

elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")

    set(BMI_COMMAND g++ -std=c++23 -fmodules-ts -xc++-system-header print -o print.gcm)

else()
    message(FATAL_ERROR "Unsupported compiler: ${CMAKE_CXX_COMPILER_ID}")
endif()


# Execute the command during configuration
execute_process(
    COMMAND ${BMI_COMMAND}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    RESULT_VARIABLE BMI_BUILD_RESULT
    ERROR_VARIABLE BMI_BUILD_ERROR
)

if(NOT BMI_BUILD_RESULT EQUAL 0)
    message(FATAL_ERROR "Failed to generate print BMI ${BMI_BUILD_ERROR}")
endif()

The current CMake file builds the program with Clang but not with GCC. GCC cannot find the gcm file. GCC doesn’t support -fmodule-file= so those lines should be commented out for GCC. I’ll work out how to change compiler options once it works.

The is in gcm.cache directory. The error is:

error: failed to read compiled module: No such file or directory
note: compiled module file is ‘gcm.cache/./usr/include/c++/14/print.gcm’

which is the path in the local directory for the file: gcm.cache/usr/include/c++/14/print.gcm. Since that is a relative path is CMake looking for it in the build directory.

cmake_minimum_required(VERSION 3.28.3)

project(Arabian.Mau LANGUAGES CXX)
set(module_name arabian.mau)

include(../CMakeBuildPrint.txt)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_SCAN_FOR_MODULES ON)

add_executable(${PROJECT_NAME} main.cpp)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_23)

add_library(${module_name})
target_compile_features(${module_name} PRIVATE cxx_std_23)
set(CMAKE_CXX_HEADER_UNITS ON)

target_sources(${module_name}
               PUBLIC
               FILE_SET cxx_modules TYPE CXX_MODULES
               FILES ${PROJECT_NAME}.cppm
               FILES
               PRIVATE ${module_name}.cpp
)

target_compile_options(${module_name} PRIVATE  -fmodule-file=${PrintBMI})
target_compile_options(${PROJECT_NAME} PRIVATE -fmodule-file=${PrintBMI})

target_link_libraries(${PROJECT_NAME} ${module_name})

see https://www.kitware.com/import-std-in-cmake-3-30/

Thanks for the reply. I updated my question in part because I made progress using Clang but not GCC. I don’t want to do import std,' just print.`

CMake does not support using BMI files made outside of its control. You can probably stitch together flags to make it work, but it’s not a supported configuration.

Header units are not yet supported by CMake; there’s no set milestone for such support either. All I can say is that it is more-or-less blocked on the majority of open area:cxxmodules issues on the CMake repository.

To what end?

I’m trying to find the options to make it work with GCC. I’d like to include it in my book as a workaround or be able to definitely state it can’t be done with the current version and GCC. I have it working for Clang with CMake because I can specify the path to the pcm.

This might be as easy as getting the path to the gcm_cache directory correct. It might mean creating a module map with the path.

Thanks for your help.

@bill.hoffman

CMake is already going to use -fmodule-mapper=, so unless GCC supports multiple such flags, anything is going to conflict with CMake there.