c++visual-studiocmakec++20c++-modules

Add C++20 module dependency for Visual Studio project using CMake


I have a static library A that has a dependency to another static library B with a C++20-module. In order to be able to import the module from B in A, I have to add the module ifc-file to the "Additional Module Dependencies" in the project settings in Visual Studio, otherwise the msvc compiler doesn't recognize the module:

Visual Studio Project Configuration

Is there some way to add a module dependency like this within a CMake script, so that the ifc-file doesn't have to be added by the user manually?


Solution

  • This ended up working for me:

    target_compile_options(${PROJ_NAME} PRIVATE /reference E:/projects/glm_cxxmodule_build/glm_module.dir/RelWithDebInfo/glm.cppm.ifc)
    

    Unfortunately it gets tricky if you want to add multiple modules. Visual Studio expects the module paths to be separated by a semicolon, but that doesn't work through CMake:

    target_compile_options(${PROJ_NAME} PRIVATE /reference E:/projects/glm_cxxmodule_build/glm_module.dir/RelWithDebInfo/glm.cppm.ifc;E:/projects/glm_cxxmodule_build/glm_module.dir/RelWithDebInfo/glm.cppm2.ifc)
    

    This will cause only the first module to be added to the project and the second will be ignored.

    I did end up finding a workaround. You can escape the semicolon with three slashes:

    target_compile_options(${PROJ_NAME} PRIVATE /reference E:/projects/glm_cxxmodule_build/glm_module.dir/RelWithDebInfo/glm.cppm.ifc\\\;E:/projects/glm_cxxmodule_build/glm_module.dir/RelWithDebInfo/glm.cppm2.ifc)
    

    In Visual Studio the paths will be separated with "%3B" instead of an actual semicolon: Visual Studio Project Configuration Panel

    Messy, but it works! At least until a better solution is added to CMake.

    Here's my final solution using a list:

    if (MSVC)
      set(
        MODULE_LIST
        C:/path/to/first/module.ixx.ifc
        C:/path/to/second/module.ixx.ifc
      )
      string (REPLACE ";" "\\\;" MODULE_LIST_STR "${MODULE_LIST}")
      target_compile_options(${PROJ_NAME} PRIVATE /reference ${MODULE_LIST_STR})
    endif()