cmake boost find_depedency配置

时间:2018-10-11 14:52:48

标签: c++ boost cmake

当尝试为我的构建生成配置并在使用不同的Boost COMPONENTS时消耗上游目标时,我遇到了这个问题。感觉就像我遗漏了一些东西,或者甚至误解了我本应如何使用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)

上面的方法可以工作,但是会给我带来严重的瘙痒-感觉我做错了。

1 个答案:

答案 0 :(得分:0)

原来是我使用find_dependency宏,将其替换为find_package给了我正确的结果,而没有解决方法。

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

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

如果已找到该程序包,它将在此处停止执行,并且不会附加其他组件。这意味着您可以在其他任何上游find_package(SomePackage)之前先进行find_package(Boost)调用,但反之则不能。

对于独立的软件包,我不认为这是个问题,但是一旦有了组件,您可能需要将它们附加到已经存在的目标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()