CMake:如何避免在接口目标属性中获得绝对路径?

CMake:如何避免在接口目标属性中获得绝对路径?,cmake,Cmake,一般问题: 我在我的INTERFACE\u LINK\u库和INTERFACE\u INCLUDE\u目录属性中获取目标的绝对路径,这是一个问题,因为这些变量是通过install(EXPORT)导出的,如果重新定位,这将意味着麻烦。我将这些绝对路径的起源追溯到find_package命令,该命令(对于某些但不是所有的包)使用绝对路径设置变量,如Boost_库。当它们与target\u link\u libraries命令一起使用时,它们最终会出现在界面\u link\u libraries中 Q

一般问题: 我在我的
INTERFACE\u LINK\u库
INTERFACE\u INCLUDE\u目录
属性中获取目标的绝对路径,这是一个问题,因为这些变量是通过
install(EXPORT)
导出的,如果重新定位,这将意味着麻烦。我将这些绝对路径的起源追溯到
find_package
命令,该命令(对于某些但不是所有的包)使用绝对路径设置变量,如
Boost_库。当它们与
target\u link\u libraries
命令一起使用时,它们最终会出现在
界面\u link\u libraries

Q:如何最好地避免导出的目标属性受到绝对路径的污染

简单的解决方案显然是用一些只命名库(硬编码)的字符串覆盖相应的变量,但我想应该有更好的方法

具体问题(示例):请参阅


编辑: My(modified)
Mapgrapher config.cmake.in
(注意:您可以忽略与
ceres
相关的内容,因为这不会给我带来麻烦,即使它在提示中放置了abs路径):

如何最好地避免导出的目标属性受到绝对路径的污染

隐藏导入目标后面的绝对路径:

# Express an external library via IMPORTED target
add_library(lib_external IMPORTED)
set_target_properties(lib_external PROPERTIES
  IMPORTED_LOCATION "${XXX_LIBRARY} (some absolute path)"
  INTERFACE_INCLUDE_DIRECTORIES "${XXX_INCLUDE_DIRECTORIES} (some absolute path)"
)

# Use external library via the target created
target_link_libraries(my_lib lib_external)
这样,
my_lib
的配置文件将只包含导入库的名称,而不包含其属性

在项目的配置文件中,您只需要创建具有相同名称的导入目标,并根据当前计算机(使用项目的位置)填充其属性

find_package
对于大多数现代软件包(包括Boost),它已经返回导入的目标。在项目的配置文件中,您可以使用该文件,该文件在当前计算机上发现包并再次创建导入的目标

对于
find_package
仅返回
XXX_库
XXX_INCLUDE_目录
变量的旧包,您可以手动创建导入的目标。在项目的配置文件中,您也可以使用
查找依赖项
,然后再次手动创建导入的目标


使用
find_dependency
宏时,请记住传递与传递到项目的
CMakeLists.txt
中的
find_包()相同的参数。这主要是关于
组件
参数和变量,如
Boost\u USE\u STATIC\u LIBS
,这会影响包搜索

如果要指定
版本
要求,则此要求应表示目标计算机上的库与实际构建项目的库的二进制兼容性


HINST
路径
不太可能需要将
find_包
的选项传输到
find_依赖项
:在目标计算机上处理对
find_依赖项的调用,这些路径可能与生成计算机上的路径不同。

安装(导出)
那么您是否按照中的广告使用了
构建界面
安装界面
?请显示代码-您的
target\u link\u库
行是什么样子的?代码:据我所知,至少
INSTALL\u接口
是按照广告使用的。原始
magrapher config.cmake
有行
include(${magrapher\u cmake\u DIR}/magraphertargets.cmake”)
,其中包括为导出目标生成的CMake文件。我在你的配置文件中看不到那一行。我复制它时掉了那一行。现在我更正了它。如果我理解正确,如果find脚本已经定义了导入的目标(像boost一样),您建议只使用例如
target\u link\u库(${PROJECT\u NAME}PUBLIC boost::boost)
correct?不幸的是,执行此操作时会出现未定义的符号错误。此外,如果我尝试上面的解决方案,例如使用lua(它不附带导入的目标),我最终会在导出的
接口链接链接链接库中使用
lib\u external
,这对消费项目(下游)没有任何好处,我想
目标链接链接链接链接库(${project\u NAME}PUBLIC Boost::Boost)
是包含Boost的正确方法。请注意,有几个导入的目标具有
Boost::
前缀。很可能,当出现“undefined symbols”错误时,您忘记了链接其中的一些符号?使用
Boost
Lua
都可以在导出文件中导入目标。在项目的配置文件中解析(创建)这些目标时,这不是问题。CMake对打包有很好的描述:。在这里,他们描述了一个使用
Stats
外部库的
grampingstats
项目的示例。为攀登状态
项目生成的包是完全可重新定位的。我建议在为您的项目准备包文件时遵循这个例子。是的,我的错,我认为
Boost::Boost
将涵盖所有lib。现在我可以编译库本身,但在下游项目中使用库时仍然存在问题:与库关联的
Config.cmake
文件现在导出,例如
Boost::iostreams
,作为
接口链接库
属性的一部分,下游库未正确使用该属性(它在链接器语句中出现为
-lBoost::iostreams
,这会导致错误ofc)。这是下游cmake的问题,它应该替换属性中的字符串,还是字符串在属性中是错误的?应该生成该字符串的不是cmake
# Express an external library via IMPORTED target
add_library(lib_external IMPORTED)
set_target_properties(lib_external PROPERTIES
  IMPORTED_LOCATION "${XXX_LIBRARY} (some absolute path)"
  INTERFACE_INCLUDE_DIRECTORIES "${XXX_INCLUDE_DIRECTORIES} (some absolute path)"
)

# Use external library via the target created
target_link_libraries(my_lib lib_external)