将 FetchContent_Declare 与共享库一起使用时出现问题

Problem using FetchContent_Declare together with shared library

我在将 FetchContent_Declare 与共享库一起使用时遇到问题。我正在尝试应用模块化设计(而不是创建一个包含 20 个模块的大型存储库,我正在为每个模块分配一个专用存储库)。我正在尝试使用 FetchContent_Declare 以便将 link 相关模块组合在一起(我不喜欢 git-子模块,因为这些需要用户手动初始化它们)。我遇到的问题是项目 fetched 通过提到的函数生成的 DLL 没有被复制到父项目的二进制输出。这里有一个依赖关系图,使它更清楚。

Repo A:
- bin
- bin-etc
- lib
- include
    - project_a
        .. header files ..
- src
   - CMakeLists.txt : 1
   .. source files ..
- CMakeLists.txt : 2

Repo B: Includes A
- bin
- bin-etc
- lib
- output
    .. cmake files are built from here .. 
    - _deps
        - project_a-src
            - bin 
                .. here the DLL file is being generated .. 
- include
    - project_a
        .. header files ..
- src
   - CMakeLists.txt : 3
   .. source files ..
- CMakeLists.txt : 4

正在 ./output/_deps/project_a-src/bin 而不是 ./bin 中生成 DLL 文件。

这是我的 CMakeLists.txt 文件:

# CMakeLists.txt : 1
cmake_minimum_required(VERSION 3.16)

set(PROJECTNAME project_a)
set(PROJECTDIR "${CMAKE_CURRENT_SOURCE_DIR}")

file(GLOB_RECURSE inc "${CMAKE_CURRENT_SOURCE_DIR}/../include/*.hpp")
file(GLOB_RECURSE src "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")

source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" FILES ${inc})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${src})

if (MSVC)
    add_compile_options(/W3) # warning level 3
    add_compile_options(/MP) # Multi-processor compilation
endif()

add_library(
    ${PROJECTNAME}
    SHARED
    ${inc}
    ${src}
    )

target_include_directories(${PROJECTNAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include/")
# CMakeLists.txt : 2 and 4

cmake_minimum_required(VERSION 3.16)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

set(CMAKE_SYSTEM_VERSION 10.0.19041.0)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin-etc")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")

project(project_a LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED)

add_subdirectory(src)

# CMakeLists.txt : 3
cmake_minimum_required(VERSION 3.16)

set(PROJECTNAME project_b)
set(PROJECTDIR "${CMAKE_CURRENT_SOURCE_DIR}")

file(GLOB_RECURSE inc "${CMAKE_CURRENT_SOURCE_DIR}/../include/*.hpp")
file(GLOB_RECURSE inc_src "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp")
file(GLOB_RECURSE src "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")

source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" FILES ${inc})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${inc_src})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${src})

if (MSVC)
    add_compile_options(/W3) # warning level 3
    add_compile_options(/MP) # Multi-processor compilation
endif()

add_library(
    ${PROJECTNAME}
    SHARED
    ${inc}
    ${inc_src}
    ${src}
    )

target_include_directories(${PROJECTNAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../include/")

include(FetchContent)

FetchContent_Declare(project_a
        GIT_REPOSITORY <REPO LINK>
        GIT_TAG master)

FetchContent_MakeAvailable(project_a)

target_link_libraries(${PROJECTNAME} project_a)

这个问题的解决方案是什么?我应该使用另一种方法进行这样的设计吗?添加一个简单的 copy 命令来创建正确的解决方案吗?

CMAKE_RUNTIME_OUTPUT_DIRECTORY这样的变量会影响所有进一步创建的库的输出目录...除非变量已更改

CMakeLists.txt(2) 中的 project_a

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")

无条件地,所以它改变了变量,即使它被构建为一个子项目(使用FetchContent)。

一般来说,根 CMakeLists.txt 中的任何项目都可以检查它是否实际上是 顶级项目 。并仅在以下情况下执行一些设置:

cmake_minimum_required(VERSION 3.21)

project(project_a LANGUAGES CXX)

if (PROJECT_IS_TOP_LEVEL)
  # Do global settings only if we are top-level project.
  set_property(GLOBAL PROPERTY USE_FOLDERS ON)

  set(CMAKE_SYSTEM_VERSION 10.0.19041.0)

  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin-etc")
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib")
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin")
endif()

# Other settings are treated as project-specific,
# so could be done in "subproject mode" too.
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED)

add_subdirectory(src)

注意,那个变量 PROJECT_IS_TOP_LEVEL appears only in CMake 3.21. For detect, whether the project is top-level in older CMake versions, consult that question and its answers: How to detect if current scope has a parent in CMake?