假设我有四个独立的项目。三是图书馆、Common
, Foo
, and Bar
,其中之一是可执行文件,App
. Both Foo
and Bar
依赖于公共库,并且App
依赖于取决于Foo
and Bar
。此外,其中一些项目有一些脚本需要运行来生成一些头文件和源文件。
现在我有一堆这样的电话:
if (NOT TARGET common)
add_subdirectory(${common_lib_directory})
endif()
但这感觉不是正确的解决方案。如果我不将其包装在 if 保护中,则会出现错误,因为它尝试构建Common
不止一次。将 if 守卫放入每个项目的 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)
守卫是因为如果我不这样做,我就会收到如下错误:
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.
如果您有如此紧密联系的项目,最好的决定似乎是使用防止重新包含在每个项目开始时。这种保护可以很容易地使用返回命令 https://cmake.org/cmake/help/v3.0/command/return.html,从当前执行返回add_subdirectory()
call:
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)
...
所以任何项目都可以使用不受保护的 add_subdirectory()
要求包括给定的一个:
应用程序/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)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)