当尝试为我的构建生成配置并在使用不同的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)
上面的方法可以工作,但是会给我带来严重的瘙痒-感觉我做错了。
答案 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()