C++20 module problems

Hi, now Fedora 40 was shipped with CMAKE >= 3.28 I thought it’s time to use the C++20 modules feature. But I am having problems to use it.

First after some research I found out it is not allowed any more to use e.g.
“-fmodules-ts” compiler switches for clang. This is because it would enable a non-standard modules implementation. Good to know.

Second I found out I had to modify my CMakeLists.txt like

target_sources(
	${CMAKE_PROJECT_NAME}
	PUBLIC
		${SOURCES}
		${HEADERS}
	PUBLIC
	FILE_SET CXX_MODULES
		FILES
			${MODULES}
)

Good to know also. With this I can use modules in my application and compile it. But now I am having several libraries this application is using. So I thought to use a module for testing purposes in one of the libs also. But there are two problems I am facing. I can compile the lib without problems but if it comes to compile the application depending on it I get the following error message:

“fatal error: module ‘XXXX’ not found”

Ok, so I thought maybe throwing all .pcm files in one folder “Modules” and provide the compiler switch

-fprebuilt-module-path="${PROJECT_PATH}/Modules""

But this feels somehow wrong and surely is non standard c++ conform. It’s clang specific. So I thought there must be a standard way of doing so?

Also there is another problem related to this. I can specify the folder for the lookup of the pcm files. But how the hell one can tell CMAKE to but the pcm files to it? For now the pcm files are put in the “…/CMakeFiles/objlib.dir” folder.

And finally if the paths in the target_sources FILES section containing “…” like “My/Path/…/…/to/the/file.ixx”. There appears an error:

CMake Error in CMakeLists.txt:
  Target "objlib" has source file

    /My/Path/../../../to/File.ixx

  in a "FILE_SET TYPE CXX_MODULES" but it is not scheduled for compilation.

Without the “…/…/” it compiles.

So how to avoid these problems? What is the CMAKE way to do it correctly? Or is it still in 2024 that C++ modules are broken?

This was fixed, I believe, in this MR which should be in 3.28.4; this patch version is not yet in Fedora it seems.

Can you provide the full definition (values of variables, all related target_* commands, etc.) of your target and the application? This usually means that the module is not PUBLIC in the linked-to target or there is a missing target_link_libraries() between the targets.

Good to know it was fixed already. Hopefully Fedora will use the newer version soon.

The Application’s CMakeLists.txt file looks like:

file(GLOB SOURCES “.c" ".cpp”)
file(GLOB HEADERS “.h" ".hpp”)
file(GLOB MODULES “.m" ".mpp” “.cxx" ".ixx” “*.cppm”)

add_executable(${CMAKE_PROJECT_NAME})

target_sources(
${CMAKE_PROJECT_NAME}
PUBLIC
${SOURCES}
${HEADERS}
PUBLIC
FILE_SET CXX_MODULES
FILES
${MODULES}
)

target_compile_features(${CMAKE_PROJECT_NAME} PUBLIC cxx_std_20)

target_link_libraries(
${CMAKE_PROJECT_NAME}
PUBLIC
${MyLibA}

${MyLibN})

The lib’s CMakeLists.txt files look like:

file(GLOB_RECURSE SOURCES “${PATH}/.cpp")
file(GLOB_RECURSE HEADERS "${PATH}/
.hpp”)
file(GLOB_RECURSE MODULES “${PATH}/*.ixx”)

add_library(objlib OBJECT)

target_sources(
objlib
PUBLIC
${SOURCES}
${HEADERS}
PUBLIC
FILE_SET CXX_MODULES
BASE_DIRS
${SOURCE_PATH}
FILES
${MODULES}
)

target_compile_features(objlib PUBLIC cxx_std_20)

set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)

add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
set_target_properties(MyLib_shared PROPERTIES PREFIX “${OUTPUT_NAME_PREFIX}”)
set_target_properties(MyLib_shared PROPERTIES OUTPUT_NAME “${CMAKE_PROJECT_NAME}${OUTPUT_NAME_SUFFIX}”)

add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)
set_target_properties(MyLib_static PROPERTIES PREFIX “${OUTPUT_NAME_PREFIX}”)
set_target_properties(MyLibA_static PROPERTIES OUTPUT_NAME “${CMAKE_PROJECT_NAME}${OUTPUT_NAME_SUFFIX}”)

But the libs are build separately from the application and I can’t think of a way the application could know where the pcm files are. My folder structure is like:

Project

  • Bin
    • Debug
      • MyLibA.a
      • MyLibA.so
      • MyLibN.a
      • MyLibN.so
  • Builds
    • MyApplication/Debug/CMakeFiles
    • MyLibA/Debug/CMakeFiles
    • MyLibN/Debug/CMakeFiles
  • Sources
    • MyLibA
    • MyLibN
  • Modules

Each lib and the application have their own workspace within the “Builds” folder. But the application knows only the “Sources” folders for the libs header files plus the “Bin” folder where the binaries are placed. But the application knows nothing about the workspaces of the libs inside the Builds folder where also the .pcm files are located.

So like I said before. If I copy the lib’s pcm files manually to e.g. the “Modules” folder and use the compiler argument…

-fprebuilt-module-path=“${PROJECT_PATH}/Modules”"

…the application can see the pcm files. So how to handle these .pcm files with CMake?

I could solve the problem finally. I remembered to have read that these .pcm files are highly CPU spezfic and are not intended for exchange with a lib. But if these files are necessary to use the lib there was only one way that the application has to recreate these .pcm files (a second time) for itself. And this worked now.

But the next problem is coming. Now it seems includes in an .ixx file are not really visible for example for derived classes and thus one needs to add these includes again an again. But still investigating on this.