gpt4 book ai didi

cmake - 将 CMake 与具有钻石依赖项的库一起使用

转载 作者:行者123 更新时间:2023-12-04 18:02:16 28 4
gpt4 key购买 nike

假设我有四个独立的项目。三是图书馆,Common , Foo , 和 Bar ,其中之一是可执行文件,App .两者 FooBar依赖于公共(public)库,并且 App取决于 FooBar .此外,其中一些项目有一些脚本需要运行以生成一些头文件和源文件。

现在我有一堆这样的电话:

if (NOT TARGET common)
add_subdirectory(${common_lib_directory})
endif()

但这并不是正确的解决方案。如果我不将它包装在 if guard 中,则会出现错误,因为它会尝试构建 Common不止一次。将 if guards 放入每个项目的 CMakeLists 中似乎也不正确。我应该写 Find<Library>每个库的脚本?我尝试寻找有关如何设置 CMakeLists 文件的示例或最佳实践,但我能找到的唯一示例要么太琐碎,要么涵盖完全不同的用例。


在评论中要求我发布一些代码。这或多或少是我的 CMakeLists.txt 文件的样子:

cmake_minimum_required(VERSION 2.8.12)

project(app)

# Temporary files (like object files) created while compiling projects.
set(tmp_dir ${CMAKE_BINARY_DIR}/obj)

# Directory which contains the source for 3rd party libraries.
if(NOT DEFINED dependencies_root)
get_filename_component(
dependencies_root "${CMAKE_CURRENT_SOURCE_DIR}/../../../../external"
REALPATH)
endif()

set(dependencies_foo_dir "${dependencies_root}/foo"
CACHE PATH "Directory containing the foo library.")
set(dependencies_bar_dir "${dependencies_root}/bar"
CACHE PATH "Directory containing the bar library.")

if(NOT TARGET foo)
add_subdirectory("${dependencies_foo_dir}" ${tmp_dir}/foo)
endif()

if(NOT TARGET bar)
add_subdirectory("${dependencies_bar_dir}" ${tmp_dir}/bar)
endif()

include_directories(${dependencies_foo_dir}/include)
include_directories(${foo_generated_include_dir})

include_directories(${dependencies_bar_dir}/include)
include_directories(${bar_generated_include_dir})

set(app_srcs ...)

add_executable(app ${app_SRCS})

target_link_libraries(app foo bar common)

如前所述,我有 if (NOT TARGET blah) 的原因guards 是因为如果我不这样做,我会得到这样的错误:

CMake Error at /path/to/my/project/CMakeLists.txt:267 (add_library):
add_library cannot create target "blah" because another target with the
same name already exists. The existing target is a static library created
in source directory
"/path/to/blah".
See documentation for policy CMP0002 for more details.

最佳答案

如果您有如此紧密相关的项目,最好的决定似乎是在每个项目开始时避免重新包含。使用 return command 可以很容易地实现这种保护,从当前执行的 add_subdirectory() 调用返回:

Foo/CMakeLists.txt:

if(DEFINED Foo_GUARD)
if(NOT Foo_GUARD STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
return() # Project has been already included by someone else
endif()
else()
set(Foo_GUARD ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "Foo guard")
endif()

project(Foo)

...

因此任何项目都可以使用未 protected add_subdirectory() 调用包含给定的项目:

App/CMakeLists.txt:

...
# Need *Foo* functionality? Simply include it!
add_subdirectory("${dependencies_foo_dir}" ${tmp_dir}/foo)

可以将 guard 实现为一个宏,将其放入库中并在您的每个项目中使用它:

cmake/utils.cmake:

macro(project_guarded name)
if(DEFINED ${name}_GUARD)
if(NOT ${name}_GUARD STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
return() # return() *doesn't* terminate a macro!
endif()
else()
set(${name}_GUARD ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "${name} guard")
endif()
project(${name})
endmacro()

宏的使用很简单:

project_guarded(Foo)

关于cmake - 将 CMake 与具有钻石依赖项的库一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33086122/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com