c++ - cmake boost find_depedency 配置

标签 c++ boost cmake

我在尝试为我的构建生成配置并在使用不同的 boost 组件时使用上游目标时遇到了这个问题。感觉好像我遗漏了什么,甚至可能误解了我应该如何使用 Config.cmake 文件为上游包生成目标。您必须再次指定 find_dependency 似乎...关闭。

在下面的 SomeProjectConfig.cmake 文件中,我必须检查上游包是否加载了 SomeProject 工作所需的目标,如果没有,我需要再次使用必要的组件调用 find boost。

# SomeProjectConfig.cmake.in

# Avoid repeatedly including the targets 
if(NOT TARGET SomeProject::SomeProject)

  # Provide path for package module scripts, CMAKE_CURRENT_LIST_DIR is the
  # directory of the currently executing cmake file. 
  list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})

  include(CMakeFindDependencyMacro)

  # -------------------------------------------------------------------------- 
  # Boost

  # The way I choose to go about it is to simply check if the dependency boost
  # targets are defined - if they are we don't have to do anything and just let
  # everything pass through. However if they are missing we need to set
  # Boost_FOUND back to FALSE so it'll resolve the dependencies...
  list(APPEND SomeProject_Boost_COMPONENTS system thread)
  foreach(_comp ${SomeProject_Boost_COMPONENTS})
    if(NOT TARGET Boost::${_comp})
      set(Boost_FOUND 0)
      break()
    endif()
  endforeach()

  # Additionally we record the BOOST_ROOT - but we try to respect the upstream
  # package if specifies it.
  if(NOT BOOST_ROOT)
    set(BOOST_ROOT "@BOOST_ROOT@"
  endif()

  # We want to handle this quietly, upstream packages might want to include more
  # componentes and if we ask for components first Boost will handle it as if
  # we've already done all the necessary work.
  find_dependency(Boost 1.55 QUIET REQUIRED COMPONENTS ${SomeProject_Boost_COMPONENTS})

  # We can never leave without setting Boost_FOUND to FALSE - if the upstream
  # package has find_package(Boost) after find_package(SomeProject) it'll
  # break if Boost_FOUND is TRUE
  set(Boost_FOUND 0)

  # // Boost
  # -------------------------------------------------------------------------- 

  find_dependency(SomeOtherDependency 1.0 QUIET REQUIRED)

  include("${CMAKE_CURRENT_LIST_DIR}/SomeProjectTargets.cmake")

  # Clean up module path after we're done
  list(REMOVE_AT CMAKE_MODULE_PATH -1)
endif()

如我所见,上面的问题是我们将 Boost_FOUND 设置为 0,从我的角度来看,这真的很难控制,而且我感觉我实际上没有正确理解 Config 包过程。

# CMakeLists.txt upstream
find_package(Boost 1.55 REQUIRED COMPONENTS filesystem)

set(SomePackage_DIR "/path/to/Config/location")
find_package(SomePackage REQUIRED)

add_library(UpstreamTarget SHARED ${sources})
target_link_libraries(UpstreamTarget PUBLIC Boost::filesystem SomeProject::SomeProject)

上面的方法会起作用,但它让我很痒——感觉我做错了。

最佳答案

结果是我使用了 find_dependency 宏,用 find_package 替换它给了我正确的结果,没有变通办法。

如果我们深入研究 CMakeFindDependencyMacro.cmake,就会很清楚问题所在。

macro(find_dependency dep)
  if (NOT ${dep}_FOUND)
  ...

如果已经找到包,它将立即停止执行并且不会附加额外的组件。这意味着您可以在任何其他 find_package(Boost) 上游之前调用 find_package(SomePackage),但反之则不行。

我认为这不是独立包的问题,​​但是一旦您拥有可能需要附加到现有目标的组件,find_dependency 似乎由于 if 语句而中断。从关于 find_dependency 的另一个答案来看它看起来主要用于诊断消息,告诉用户问题来自 *Config.cmake 文件而不是其他任何内容。

为了完整起见,这里是配置文件的一个工作示例,我在其中删除了解决方法:

# SomeProjectConfig.cmake.in

# Avoid repeatedly including the targets 
if(NOT TARGET SomeProject::SomeProject)

  # Provide path for package module scripts, CMAKE_CURRENT_LIST_DIR is the
  # directory of the currently executing cmake file. 
  list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})

  include(CMakeFindDependencyMacro)
  # Additionally we record the BOOST_ROOT - but we try to respect the upstream
  # package if it specifies it.
  if(NOT BOOST_ROOT)
    set(BOOST_ROOT "@BOOST_ROOT@"
  endif()
  find_package(Boost 1.55 QUIET REQUIRED COMPONENTS system thread)
  find_dependency(SomeOtherDependency 1.0 QUIET REQUIRED)

  include("${CMAKE_CURRENT_LIST_DIR}/SomeProjectTargets.cmake")

  # Clean up module path after we're done
  list(REMOVE_AT CMAKE_MODULE_PATH -1)
endif()

关于c++ - cmake boost find_depedency 配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52763112/

相关文章:

c++ - 使用 C++ 线程/boost 线程的有效方法

c++ - 将 Boost 库链接到 Xcode 项目

c++ - 使用非 debian 托管库构建 debian 软件包

c++ - 得到第n大数

c++ - 如何确定通过套接字接收到的(序列化和模板化)对象是什么类型?

android - OpenCV undefined reference `cv::fastFree(void*)'

c++ - 如何在一系列 boost::function 对象上使用 std::for_each ?

cmake - 在 CMake 中为每个开发人员自定义安装输出目录的正确方法是什么?

c++ - 在 CMake 中设置默认编译器

c++ - 来自主线程的信号未到达第二线程 Qt 5 中的插槽