Header-only libraries and C++20 modules

When installing a header-only library with a C++20 module interface, with something like:

add_library(mylib)
target_sources(mylib
    PUBLIC
        FILE_SET CXX_MODULES FILES mylib.cppm
        FILE_SET HEADERS FILES mylib.h
)
install(TARGETS mylib
    EXPORT mylib-targets
    FILE_SET CXX_MODULES
        DESTINATION lib/cmake/mylib/module
    FILE_SET HEADERS DESTINATION .
)

CMake will build and install a static or shared library, which seems just unnecessary, as the modules will be built again by the consumer. I’ve tried building an INTERFACE library, instead, but target_sources refuses to add a CXX_MODULES fileset with INTERFACE scope.

Is there a way to do this cleanly?

@ben.boeckel

Modules have module initializer symbols that need to be provided once to be reliable (the ODR applies here). Providing it in a library is the reliable way to do this.

The BMIs will be built again, but not object files.

Sorry if it’s a dumb question, but what is a “module initializer symbol”? I can’t find any reference to the term in clang/MSVC docs or in the standard.

The new rule is that all global initializers required by module A will be called before those of module B if B contains import A. This is implemented by making a symbol for export module M; that is called for any import M; statement.