静态库和生成的标头中的循环依赖关系

Job*_*Job 5 c++ cmake

假设我有一个项目,它创建了两个静态库目标(foobar),它们之间存在循环依赖关系.CMake明确允许这个,它通常工作正常,因为构建这些库的顺序无关紧要.

但是,如果这两个库都生成了作为其接口一部分的头文件(Foo.hppfor foo,Bar.hppfor bar),则可能会出现问题,因为标头的生成通常是作为构建库的一部分(例如,via add_custom_targetadd_dependencies)完成的.也就是说,建筑foo将产生Foo.hpp但也需要Bar.hpp建造bar需求Foo.hpp......

我找到了解决这个问题的方法,初看起来似乎很完美.它包括使用生成标头add_custom_command,然后使用标头将标头添加到PUBLIC目标源target_sources.这样,目标本身及其依赖项将对标头具有文件级依赖性,这将在正确的时间触发自定义命令.

这是我的解决方案的MWE:

cmake_minimum_required(VERSION 3.5)
project(Foo)

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Foo.hpp
    COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/Foo.hpp
    COMMENT "Generating Foo.hpp"
)

add_library(foo STATIC Foo.cpp)
target_include_directories(foo PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_sources(foo PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/Foo.hpp)
target_link_libraries(foo bar)

add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Bar.hpp
    COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/Bar.hpp
    COMMENT "Generating Bar.hpp"
)

add_library(bar STATIC Bar.cpp)
target_include_directories(bar PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_sources(bar PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/Bar.hpp)
target_link_libraries(bar foo)
Run Code Online (Sandbox Code Playgroud)

问题是自定义命令仅在从同一目录引用其输出时才起作用(这是记录的).如果我拆,我的项目,并将foobar在不同的目录,我的解决方案上面的不工作了.

所以我的问题是:有没有更好的方法来处理生成的静态库头之间的循环依赖?

sta*_*all 0

如果我拆分我的项目并将 foo 和 bar 放在不同的目录中,我上面的解决方案将不再起作用。

你把他们分开是什么意思?您可以将目标的源文件放在专用子目录中,并仍然在同一个 CMake“子目录”中定义它们的目标。

cmake_minimum_required(VERSION 3.5)
project(Foo)

add_custom_command(
    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Foo/Foo.hpp"
    COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/Foo/Foo.hpp"
    COMMENT "Generating Foo.hpp"
    VERBATIM
)

add_library(foo STATIC Foo/Foo.cpp)
target_include_directories(foo PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_sources(foo PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/Foo/Foo.hpp)
target_link_libraries(foo bar)

add_custom_command(
    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Bar/Bar.hpp"
    COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/Bar/Bar.hpp"
    COMMENT "Generating Bar.hpp"
    VERBATIM
)

add_library(bar STATIC Bar/Bar.cpp)
target_include_directories(bar PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_sources(bar PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/Bar/Bar.hpp)
target_link_libraries(bar foo)
Run Code Online (Sandbox Code Playgroud)

如果您的意思是要在这些专用子目录中定义目标,您不能这样做:

# :/CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(Foo)
add_subdirectory(Foo)
add_subdirectory(Bar)

# :/Foo/CMakeLists.txt
add_custom_command(
    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Foo/Foo.hpp"
    COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/Foo/Foo.hpp"
    COMMENT "Generating Foo.hpp"
    VERBATIM
)
add_library(foo STATIC Foo.cpp)
target_include_directories(foo PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_sources(foo PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/Foo/Foo.hpp)
target_link_libraries(foo bar)

# :/Bar/CMakeLists.txt
add_custom_command(
    OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Bar/Bar.hpp"
    COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/Bar/Bar.hpp"
    COMMENT "Generating Bar.hpp"
    VERBATIM
)
add_library(bar STATIC Bar.cpp)
target_include_directories(bar PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
target_sources(bar PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/Bar/Bar.hpp)
target_link_libraries(bar foo)
Run Code Online (Sandbox Code Playgroud)