假设我有四个独立的项目。其中三个是库Common
,Foo
和Bar
,其中一个是可执行文件App
。 Foo
和Bar
都取决于公共库,App
取决于Foo
和Bar
。此外,其中一些项目有一些脚本需要运行以生成一些头文件和源文件。
现在我有很多这样的电话:
if (NOT TARGET common)
add_subdirectory(${common_lib_directory})
endif()
但这并不是一个合适的解决方案。如果我没有把它包裹在那里,如果后卫,那么就会出现错误,因为它试图不止一次地构建Common
。如果每个项目的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.
答案 0 :(得分:1)
如果您有这样紧密相关的项目,那么最佳决策似乎是在每个项目开始时使用 guard来重新包含。可以使用return command轻松实现此类保护,{{3}}从当前执行的add_subdirectory()
调用返回:
<强>富/的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)