CMake 多配置生成器使用错误的构建目录

Posted

技术标签:

【中文标题】CMake 多配置生成器使用错误的构建目录【英文标题】:CMake multi-config generators use wrong build directory 【发布时间】:2021-01-08 17:55:15 【问题描述】:

我遇到了与 CMake 中的多配置生成器相关的问题。 任务很简单:我只想将一些文件(glsl 着色器)复制到运行时目录中(以便在运行时读取可执行文件)。

我有以下目标层次结构:我有(DLL)目标和可执行文件,将由用户创建。然后库与可执行文件链接。这就是问题所在。 我使用了以下代码:

configure_file("$SHADER_SRC" "$CMAKE_RUNTIME_OUTPUT_DIR/shaders/$SHADER_OUTPUT_FILENAME" COPYONLY)

它会产生类似的构建树:

二进制目录 BUILD_TYPE(例如,调试) 斌 着色器 我的文件在这里。工作正常 其他目标

它适用于单一配置生成器。 但是当我开始使用Visual Studio 16 2019 多配置生成器时,会发生以下情况:

二进制目录 BUILD_TYPE 斌 着色器 我的文件在这里。工作正常 BUILD_TYPE 其他目标 可执行文件不再看到着色器,因为它们位于错误的目录中。 如何解决这个问题?

附: 我也用过add_custom_command 版本:

set(SHADER_OUTPUT_FILENAME "$CMAKE_RUNTIME_OUTPUT_DIRECTORY/shaders/$SHADER_FILENAME")
    
add_custom_command(
            TARGET $LIBRARY_TARGET_NAME PRE_BUILD
            WORKING_DIRECTORY "$CMAKE_CURRENT_SOURCE_DIR"
            COMMENT "Copying shader ($SHADER_FILENAME) to build directory..."
            BYPRODUCTS "$SHADER_OUTPUT_FILENAME"

            COMMAND $CMAKE_COMMAND -E copy
                    $SHADER_SRC # Shader file in source directory
                    $SHADER_OUTPUT_FILENAME # Shader file that I need in build directory

            VERBATIM
    )

【问题讨论】:

请创建一个minimal reproducible example,即一个完整的最小CmakeLists.txt,可用于与所需(最小)输入文件一起重现问题。 【参考方案1】:
if(UNIX)
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_INSTALL_LIBDIR)
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_INSTALL_LIBDIR)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_INSTALL_BINDIR)
  # for multi-config build system (e.g. xcode, ninja-multiconfig)
  foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
    string(TOUPPER $OUTPUTCONFIG OUTPUTCONFIG)
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_$OUTPUTCONFIG $CMAKE_BINARY_DIR/$OUTPUTCONFIG/$CMAKE_INSTALL_LIBDIR)
    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_$OUTPUTCONFIG $CMAKE_BINARY_DIR/$OUTPUTCONFIG/$CMAKE_INSTALL_LIBDIR)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_$OUTPUTCONFIG $CMAKE_BINARY_DIR/$OUTPUTCONFIG/$CMAKE_INSTALL_BINDIR)
  endforeach()
else()
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_INSTALL_BINDIR)
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_INSTALL_BINDIR)
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $CMAKE_BINARY_DIR/$CMAKE_INSTALL_BINDIR)
  # for multi-config builds (e.g. msvc)
  foreach(OUTPUTCONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
    string(TOUPPER $OUTPUTCONFIG OUTPUTCONFIG)
    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_$OUTPUTCONFIG $CMAKE_BINARY_DIR/$OUTPUTCONFIG/$CMAKE_INSTALL_BINDIR)
    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_$OUTPUTCONFIG $CMAKE_BINARY_DIR/$OUTPUTCONFIG/$CMAKE_INSTALL_BINDIR)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_$OUTPUTCONFIG $CMAKE_BINARY_DIR/$OUTPUTCONFIG/$CMAKE_INSTALL_BINDIR)
  endforeach()
endif()

【讨论】:

没有这个“ifs”有没有办法做到这一点?

以上是关于CMake 多配置生成器使用错误的构建目录的主要内容,如果未能解决你的问题,请参考以下文章

CMake:如何添加仅针对一种配置执行的自定义命令?

CMake可以生成配置文件吗?

初见 cmake

gcov 与 CMake 使用单独的构建目录

Android NDK开发CMake构建工具使用

项目构建工具CMake、GYP、GN