C++ 20 Modules Update

Changing extension or adding -x c++ options solves this problem, but now I am getting linker errors:

[build] /usr/local/bin/g++ -DENABLE_TESTS -I/home/pkoziol/repos/aoc22/src/…/include/aoc22 -isystem /home/pkoziol/repos/aoc22/tests/Catch2/src/catch2/… -isystem /home/pkoziol/repos/aoc22/builds/dev_ninja_gcc/tests/Catch2/generated-includes -g -std=c++20 -fmodules-ts -x c++ -Wall -Wextra -Wpedantic -Werror -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual -Wconversion -Wsign-conversion -Wmisleading-indentation -Wnull-dereference -Wdouble-promotion -Wformat=2 -Wimplicit-fallthrough -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wuseless-cast /home/pkoziol/repos/aoc22/src/day8.cpp -MT src/CMakeFiles/aoc22.dir/day8.cpp.o.ddi -MD -MF src/CMakeFiles/aoc22.dir/day8.cpp.o.ddi.d -fdeps-file=src/CMakeFiles/aoc22.dir/day8.cpp.o.ddi -fdeps-target=src/CMakeFiles/aoc22.dir/day8.cpp.o

[build] /usr/bin/ld: /lib/x86_64-linux-gnu/crt1.o: in function `_start’:

[build] (.text+0x1b): undefined reference to `main’

So two issues here:
–the test targets are built first, before catch2 and the lib itself it seems
–the main is somehow not being found

The non-module branch builds ok with the same gcc

Where is main defined and how is it added to your target?

Its included by every test executable.

How is it included? And can you show the add_library or target_sources call which adds that source to the target?

Example tests which includes it

The test executables are added here:

add_executable(${TEST_NAME} ${TEST_NAME}.cpp)

The CMake looks OK. Can you diff the link lines with and without modules on the executables? Or the symbols in the objects. There has to be some difference…

Probably better to move this to an issue on the repo and bring the result back here instead of hijacking the topic.

Can you provide an example of how this should be specified please, because it’s not obvious to me.

Here’s my attempt:

target_sources(discovery_win32
        PUBLIC
        FILE_SET cxx_modules TYPE CXX_MODULES
        FILES
        "platform.win32.ixx" "platform.win32-window.ixx"
        PRIVATE
        "platform.win32-window.cpp")
C:\Dev\Personal\Discovery\out\build\x64-debug\Discovery\EXEC : CMake error : Output platform\win32\CMakeFiles\discovery_win32.dir\platform.win32-window.cpp.obj provides the `platform.win32:window` module but it is not found in a `FILE_SET` of type `CXX_MODULES`
  ninja: build stopped: subcommand failed

I tried changing the name to be the project name (since custom targets are not allowed for FILE_SET CXX_MODULES, but that did not work either:

target_sources("${PROJECT_NAME}"
        PUBLIC
        FILE_SET CXX_MODULES FILES
        "platform.win32.ixx"
        "platform.win32-window.ixx"
        PRIVATE
        "platform.win32-window.cpp"
)

Subtle and perhaps not the most obvious. I appreciate this is very new, but perhaps a few examples would help. The example from the CMake blog is a bit too basic.

cmake_minimum_required(VERSION 3.28)
project(std_module_example CXX)

# Turning off extensions avoids and issue with the clang 16 compiler
# clang 17 and greater can avoid this setting
set(CMAKE_CXX_EXTENSIONS OFF)
# Set the version of C++ for the project
set(CMAKE_CXX_STANDARD 20)
# Create a library
add_library(foo)
# Add the module file to the library
target_sources(foo
  PUBLIC
    FILE_SET CXX_MODULES FILES
      foo.cxx
)
# Create an executable
add_executable(hello main.cxx)
# Link to the library foo
target_link_libraries(hello foo)

Could @ben.boeckel provide some clarification?

I suspect that platform.win32-window.cpp has:

module platform.win32:window;

at the top. If this is an implementation unit, it must be:

module platform.win32;

regardless of what partition the declaration(s) of what it is implementing.

1 Like

That was exactly my problem. Thank you for helping me to understand how to split modules into multiple partitions.

Does that mean that any change to a module implementation unit cause the recompilation of the consumers of the module ?

EDIT: I was trying with gcc trunk and seeing this but with clang instead it seems to work.

Ideally, no. Consumers will need relinked as the object code has changed, but the implementation file should have no effect on BMI-producing files (just like a change to a .cxx shouldn’t make includers of the corresponding .h file care). If you see discrepancies, please file bugs with example code.