首页 > 解决方案 > CMake:如何避免在 INTERFACE 目标属性中获取绝对路径?

问题描述

一般问题: 我在目标INTERFACE_LINK_LIBRARIESINTERFACE_INCLUDE_DIRECTORIES属性中获得了绝对路径,这是一个问题,因为这些变量是通过 导出的install(EXPORT),如果重新定位任何东西,这将意味着麻烦。我将这些绝对路径的起源追溯到find_package命令,该命令(对于某些但不是所有包)设置变量Boost_LIBRARIES,如绝对路径。当它们与例如target_link_libraries命令一起使用时,它们最终以INTERFACE_LINK_LIBRARIES.

问:如何最好地避免导出的目标属性被绝对路径污染?

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

具体问题(示例):https://github.com/cartographer-project/cartographer/issues/1688


编辑: 我的(修改后的)cartographer-config.cmake.in (注意:你可以忽略与 相关的东西ceres,因为这不会给我带来麻烦,即使它在提示中放置了一个 abs 路径):

# Copyright 2016 The Cartographer Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#  Usage from an external project:
#    In your CMakeLists.txt, add these lines:
#
#    find_package(cartographer REQUIRED)
#    target_link_libraries(MY_TARGET_NAME PUBLIC cartographer)

@PACKAGE_INIT@

set_and_check(CARTOGRAPHER_CMAKE_DIR "@PACKAGE_CARTOGRAPHER_CMAKE_DIR@")

find_dependency(Boost)
find_dependency(Lua)

set(CERES_DIR_HINTS @Ceres_DIR@)

if (cartographer_FIND_QUIETLY)
   find_package(Ceres QUIET HINTS ${CERES_DIR_HINTS})
elseif (cartographer_FIND_REQUIRED)
   find_package(Ceres REQUIRED HINTS ${CERES_DIR_HINTS})
else ()
   find_package(Ceres HINTS ${CERES_DIR_HINTS})
endif()

include("${CARTOGRAPHER_CMAKE_DIR}/CartographerTargets.cmake")                                                                                  

标签: cmake

解决方案


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

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

# 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将只包含 IMPORTED 库的名称,而不包含其属性。

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

find_package对于大多数现代包(包括 Boost)已经返回一个 IMPORTED 目标。在您的项目的配置文件中,您可以使用find_dependency,它会发现当前机器上的包并再次创建一个 IMPORTED 目标。

对于find_package只返回XXX_LIBRARIES和变量的旧包,您可以手动XXX_INCLUDE_DIRECTORIES创建 IMPORTED 目标。在您的项目的配置文件中,您也可以使用,然后再次手动创建 IMPORTED 目标。find_dependency


使用find_dependency宏时,请记住传递find_package()在项目的CMakeLists.txt. 这是关于COMPONENTS参数和变量(如)的主要内容Boost_USE_STATIC_LIBS,它会影响包搜索。

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

HINSTPATHS选项find_package不太可能需要转移到find_dependency:调用find_dependency目标机器上处理,这些路径可能与构建机器上的不同。


推荐阅读