正确设置已安装软件包的导入cmake目标的位置

Bru*_*ams 8 cmake

我希望能够从已安装的库中导入目标,但是使用时:

install(TARGETS
        foobar
        EXPORT foobarLibTargets
        LIBRARY DESTINATION lib)
Run Code Online (Sandbox Code Playgroud)

cmake生成一个包含绝对路径的foob​​arLibTargets.cmake

set_target_properties(foobar PROPERTIES
        IMPORTED_LOCATION_NOCONFIG "/where/I/happened/to/build/libfoobar.so"
        IMPORTED_SONAME_NOCONFIG "libfoobar.so"
)
Run Code Online (Sandbox Code Playgroud)

这样,使用从安装中导入的目标的构建将由于路径不存在而失败。

问:如何获取正确的相对位置?

这等效于:

set_target_properties(foobar PROPERTIES
                      IMPORTED_LOCATION_NOCONFIG "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so")
Run Code Online (Sandbox Code Playgroud)

如果我看另一个工作类似但可行的项目,它有:

set_target_properties(foobar PROPERTIES
         IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libfoobar.so"
         IMPORTED_SONAME_RELEASE "libfoobar.so"
)
Run Code Online (Sandbox Code Playgroud)

以下是一些重现此问题的示例文件:

CMakeLists.txt:

cmake_minimum_required(VERSION 3.7)
project(FOOBAR VERSION 1.2.3)
set(VERSION 1.2.3)

set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/")
set(CMAKE_INSTALL_PREFIX "/opt/foobar" CACHE PATH "Install path prefix" FORCE)

add_library(foobar SHARED
  foobar.cpp
)

set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
set(CPACK_PACKAGE_NAME "foobar")

set(CPACK_PACKAGE_VERSION ${VERSION})
set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")

include(CPack)

# Indicate the content of the distribution pakcages
install(FILES
  ${CMAKE_SOURCE_DIR}/foobar.h
  DESTINATION include
)
install(TARGETS
  foobar
  EXPORT foobarLibTargets
  LIBRARY DESTINATION lib)

include(CMakePackageConfigHelpers)
set(ConfigFileInstallDir lib/cmake/foobar)
set(INCLUDE_INSTALL_DIR include)
set(LIBRARY_INSTALL_DIR lib)
message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
configure_package_config_file(foobarConfig.cmake.in
     "${CMAKE_BINARY_DIR}/foobarConfig.cmake"
    INSTALL_DESTINATION "${ConfigFileInstallDir}"
    PATH_VARS INCLUDE_INSTALL_DIR LIBRARY_INSTALL_DIR)
write_basic_package_version_file(
   "${CMAKE_BINARY_DIR}/foobarConfigVersion.cmake"
   VERSION "${VERSION}"
   COMPATIBILITY ExactVersion)
export(EXPORT foobarLibTargets
       FILE "${CMAKE_CURRENT_BINARY_DIR}/foobarLibTargets.cmake")
install(EXPORT foobarLibTargets
        FILE foobarTargets.cmake
        DESTINATION lib/cmake)
install(FILES
   "${CMAKE_CURRENT_BINARY_DIR}/foobarConfig.cmake"
   "${CMAKE_CURRENT_BINARY_DIR}/foobarConfigVersion.cmake"
   "${CMAKE_CURRENT_BINARY_DIR}/foobarLibTargets.cmake"
    DESTINATION "${ConfigFileInstallDir}")
Run Code Online (Sandbox Code Playgroud)

foob​​arConfig.cmake.in:

set(FOOBAR_VERSION @VERSION@)

@PACKAGE_INIT@

set_and_check(FOOBAR_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(FOOBAR_LIBRARY "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so")
set_and_check(FOOBAR_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@")
include("${CMAKE_CURRENT_LIST_DIR}/foobarLibTargets.cmake")

# workaround - correct absolute path in the above
# this shouldn't be necessary (hence this question)
#set_target_properties(foobar PROPERTIES
#  IMPORTED_LOCATION_NOCONFIG "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so"
#)
Run Code Online (Sandbox Code Playgroud)

foob​​ar.h:

void hello();
Run Code Online (Sandbox Code Playgroud)

foob​​ar.cpp:

#include <iostream>

void hello() {
   std::cerr << "hello world\n";
}
Run Code Online (Sandbox Code Playgroud)

useFoo.cmake(使用已安装的库的示例项目的CMakeLists.txt):

cmake_minimum_required(VERSION 3.7)
project(useFoo VERSION 1.2.3)
set(VERSION 1.2.3)

find_package(foobar)
file(GENERATE OUTPUT foobar-gen CONTENT "<TARGET_FILE:foobar>=$<TARGET_FILE:foobar>\n")

message(STATUS "FOOBAR_LIBRARY_DIR=${FOOBAR_LIBRARY_DIR}")
message(STATUS "FOOBAR_INCLUDE_DIR=${FOOBAR_INCLUDE_DIR}")
Run Code Online (Sandbox Code Playgroud)

build.sh(生成并使用安装包):

#!/bin/sh

rm -rf target
mkdir target
cd target
cmake .. &&
make &&
cpack -G TGZ
if [ $? -ne 0 ]; then
   echo "doh!"
   exit 1
fi

cd ..
rm -rf install
mkdir install
cd install
tar -xvzf ../target/foobar-1.2.3.tar.gz
cp ../useFoo.cmake CMakeLists.txt
export CMAKE_PREFIX_PATH=`pwd`/opt/foobar/lib/cmake:`pwd`/opt/foobar/lib/cmake/foobar
cmake .
if [ $? -ne 0 ]; then
   echo "doh!"
   exit 1
fi
cat foobar-gen
Run Code Online (Sandbox Code Playgroud)

输出cat foobar-gen为:

<TARGET_FILE:foobar>=/where/I/happened/to/build/libfoobar.so
Run Code Online (Sandbox Code Playgroud)

我希望它是:

<TARGET_FILE:foobar>=/where/I/actually/installed/libfoobar.so
Run Code Online (Sandbox Code Playgroud)

如果取消对解决方法的评论,它将变成哪种。 有没有一种方法可以避免该替代方法?

相关的问题- 配置文件cmake包中的变量出现奇怪的问题 -具有相似的代码,既可以重现此问题,又可以在上面添加另一个问题。

J-C*_*phe 5

主要问题是这两个文件foobarLibTargets.cmakefoobarTargets.cmake都已安装,但选择了错误的文件。

您将在下面找到一个改进的项目以及更好地组织构建系统的注释。

ChangeLog 总结编辑

  • 2019-05-25
    • 创建 GitHub 项目以简化重用和适配。见https://github.com/jcfr/stackoverflow-56135785-answer
    • 将项目和源目录重命名为foobarto FooBarLib,相应地更新 Suggestions 部分
    • 提升 build.sh
    • 更新的建议(CPACK_PACKAGING_INSTALL_PREFIX应该是绝对的)
    • 转速:
      • 添加对使用构建 RPM 包的支持 make package
      • 更新build.sh以显示 RPM 包的内容

评论

  • 应该生成两个配置文件:
    • 一个用于构建树:这允许您的项目用户直接针对您的项目进行构建并导入目标
    • 一个用于安装树(最终也被打包)
  • 不要强行取值 CMAKE_INSTALL_PREFIX
  • CPACK_PACKAGING_INSTALL_PREFIX 不应设置为绝对目录
  • 为了一致性起见,使用foobarTargets代替foobarLibTargets
  • <projecname_uc>下面使用的占位符对应于大写的项目名称(ABC而不是abc
  • 要允许在与其他项目一起供应商化时配置您的项目,请更喜欢带有<projecname_uc>_. 这意味着<projecname_uc>_INSTALL_LIBRARY_DIR优于LIBRARY_INSTALL_DIR.
  • 要允许项目的用户配置*_INSTALL_DIR变量,请将它们包装起来if(DEFINED ...)
  • 始终如一地使用变量(例如,LIBRARY_INSTALL_DIR应始终使用而不是lib
  • 更喜欢命名变量<projecname_uc>_INSTALL_*_DIR而不是<projecname_uc>_*_INSTALL_DIR,这样在阅读代码时更容易知道变量的用途。
  • 由于版本已经与项目相关联,因此无需设置VERSION变量。相反,您可以使用PROJECT_VERSIONFOOBAR_VERSION
  • 如果开始一个新项目,请选择最新的 CMake 版本。CMake 3.13 而不是 CMake 3.7
  • 引入变量 <projecname_uc>_INSTALL_CONFIG_DIR
  • <project_name>Targets.cmake不应使用 安装install(FILES ...),它已与安装规则关联
  • 有条件设置CMAKE_INSTALL_RPATH,只在Linux上有效
  • <project_name>Config.cmake.in
    • 无需设置FOOBAR_LIBRARY,此信息已与导出的foobar目标相关联
    • FOOBAR_LIBRARY_DIR 也不需要,这个信息已经与导出的foobar目标相关联
    • target_include_directories应该使用该命令而不是设置 FOOBAR_INCLUDE_DIR
    • 删除设置FOOBAR_VERSION,生成版本文件已经负责设置版本。
  • 在为目标声明安装规则时,始终指定 ARCHIVE、LIBRARY 和 RUNTIME。避免切换库类型时出现问题。少一件事要考虑。
  • 始终使用您的安装规则指定组件。它允许您的项目用户有选择地安装它的一部分,仅开发组件或仅运行时组件,...
  • 初始化CMAKE_BUILD_TYPE也很重要,它确保生成的目标文件与配置相关联(而不是后缀-noconfig.cmake

建议的更改

一般来说,我建议有一个源树、一个构建树和一个安装树。下面发布的文件采用以下布局:

./build.sh

./FooBarLib/FooBarLibConfig.cmake.in
./FooBarLib/CMakeLists.txt
./FooBarLib/foobar.cpp
./FooBarLib/foobar.h

./FooBarLib-build

./FooBarLib-install

./useFoo/CMakeLists.txt
./useFoo-build
Run Code Online (Sandbox Code Playgroud)
  • 编译文件
#!/bin/bash

set -xeu
set -o pipefail

script_dir=$(cd $(dirname $0) || exit 1; pwd)

project_name=FooBarLib
archive_name=${project_name}

# cleanup ${project_name}-build
cd $script_dir
rm -rf ${project_name}-build
mkdir ${project_name}-build
cd ${project_name}-build

# configure, build and package ${project_name}
cmake ../${project_name}
make
make package # equivalent to running "cpack -G TGZ" and "cmake -G RPM"

# extract ${project_name} archive
cd $script_dir
rm -rf ${project_name}-install
mkdir ${project_name}-install
cd ${project_name}-install
tar -xvzf ../${project_name}-build/${archive_name}-1.2.3.tar.gz

# cleanup useFoo-build
cd $script_dir
rm -rf useFoo-build
mkdir useFoo-build
cd useFoo-build

cpack_install_prefix=/opt

# configure useFoo
cmake -D${project_name}_DIR=$script_dir/${project_name}-install${cpack_install_prefix}/lib/cmake/${project_name}/ ../useFoo

cat foobar-gen

# display content of RPM. If command "rpmbuild" is available, RPM package is expected.
if command -v rpmbuild &> /dev/null; then
  rpm -qlp $script_dir/${project_name}-build/${archive_name}-1.2.3.rpm
fi
Run Code Online (Sandbox Code Playgroud)
  • FooBarLib/CMakeLists.txt
cmake_minimum_required(VERSION 3.13)

project(FooBarLib VERSION 1.2.3)

if(UNIX AND NOT APPLE)
  set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/")
endif()

#------------------------------------------------------------------------------
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to 'Release' as none was specified.")
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
  mark_as_advanced(CMAKE_BUILD_TYPE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

#------------------------------------------------------------------------------
# This variable controls the prefix used to generate the following files:
#  <export_config_name>ConfigVersion.cmake
#  <export_config_name>Config.cmake
#  <export_config_name>Targets.cmake
# and it also used to initialize FOOBARLIB_INSTALL_CONFIG_DIR value.
set(export_config_name ${PROJECT_NAME})

#------------------------------------------------------------------------------
if(NOT DEFINED FOOBARLIB_INSTALL_INCLUDE_DIR)
  set(FOOBARLIB_INSTALL_INCLUDE_DIR include)
endif()

if(NOT DEFINED FOOBARLIB_INSTALL_BIN_DIR)
  set(FOOBARLIB_INSTALL_BIN_DIR bin)
endif()

if(NOT DEFINED FOOBARLIB_INSTALL_LIBRARY_DIR)
  set(FOOBARLIB_INSTALL_LIBRARY_DIR lib)
endif()

if(NOT DEFINED FOOBARLIB_INSTALL_CONFIG_DIR)
  set(FOOBARLIB_INSTALL_CONFIG_DIR ${FOOBARLIB_INSTALL_LIBRARY_DIR}/cmake/${export_config_name})
endif()

#------------------------------------------------------------------------------
set(headers
  foobar.h
  )

# Install rule for headers
install(
  FILES ${headers}
  DESTINATION ${FOOBARLIB_INSTALL_INCLUDE_DIR}
  COMPONENT Development
  )

#------------------------------------------------------------------------------
add_library(foobar SHARED
  foobar.cpp
  )

target_include_directories(foobar
  PUBLIC
    $<BUILD_INTERFACE:${FooBarLib_SOURCE_DIR}>
    $<INSTALL_INTERFACE:${FOOBARLIB_INSTALL_INCLUDE_DIR}>
  )

install(
  TARGETS foobar
  EXPORT ${export_config_name}Targets
  ARCHIVE DESTINATION ${FOOBARLIB_INSTALL_LIBRARY_DIR} COMPONENT Development
  LIBRARY DESTINATION ${FOOBARLIB_INSTALL_LIBRARY_DIR} COMPONENT RuntimeLibraries
  RUNTIME DESTINATION ${FOOBARLIB_INSTALL_BIN_DIR} COMPONENT RuntimeLibraries
  )

#------------------------------------------------------------------------------
# Configure <export_config_name>ConfigVersion.cmake common to build and install tree
include(CMakePackageConfigHelpers)
set(config_version_file ${PROJECT_BINARY_DIR}/${export_config_name}ConfigVersion.cmake)
write_basic_package_version_file(
  ${config_version_file}
  VERSION "${FooBarLib_VERSION}"
  COMPATIBILITY ExactVersion
  )

#------------------------------------------------------------------------------
# Export '<export_config_name>Targets.cmake' for a build tree
export(
  EXPORT ${PROJECT_NAME}Targets
  FILE "${CMAKE_CURRENT_BINARY_DIR}/${export_config_name}Targets.cmake"
  )

# Configure '<export_config_name>Config.cmake' for a build tree
set(build_config ${CMAKE_BINARY_DIR}/${export_config_name}Config.cmake)
configure_package_config_file(
  ${export_config_name}Config.cmake.in 
  ${build_config}
  INSTALL_DESTINATION "${PROJECT_BINARY_DIR}"
  )

#------------------------------------------------------------------------------
# Export '<export_config_name>Targets.cmake' for an install tree
install(
  EXPORT ${export_config_name}Targets
  FILE ${export_config_name}Targets.cmake
  DESTINATION ${FOOBARLIB_INSTALL_CONFIG_DIR}
  )

set(install_config ${PROJECT_BINARY_DIR}/CMakeFiles/${export_config_name}Config.cmake)
configure_package_config_file(
  ${export_config_name}Config.cmake.in 
  ${install_config}
  INSTALL_DESTINATION ${FOOBARLIB_INSTALL_CONFIG_DIR}
  )

# Install config files
install(
  FILES ${config_version_file} ${install_config}
  DESTINATION "${FOOBARLIB_INSTALL_CONFIG_DIR}"
  )

#------------------------------------------------------------------------------
# Generate package

set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0)
set(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")

# Setting this variable also impacts the layout of TGZ.
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt")

# Setting CPACK_SOURCE_* and CPACK_GENERATOR allow to have "make package" generates
# the expected archive.

# Disable source generator enabled by default
set(CPACK_SOURCE_TBZ2 OFF CACHE BOOL "Enable to build TBZ2 source packages" FORCE)
set(CPACK_SOURCE_TGZ  OFF CACHE BOOL "Enable to build TGZ source packages" FORCE)
set(CPACK_SOURCE_TZ OFF CACHE BOOL "Enable to build TZ source packages" FORCE)

# Select generators
if(UNIX AND NOT APPLE)
  set(CPACK_GENERATOR "TGZ")
  find_program(RPMBUILD_PATH rpmbuild)
  if(RPMBUILD_PATH)
    list(APPEND CPACK_GENERATOR "RPM")
  endif()
elseif(APPLE)
  # ...
endif()

include(CPack)
Run Code Online (Sandbox Code Playgroud)
  • FooBarLib/FooBarLibConfig.cmake.in
@PACKAGE_INIT@

set(export_config_name "@export_config_name@")

set_and_check(${export_config_name}_TARGETS "${CMAKE_CURRENT_LIST_DIR}/${export_config_name}Targets.cmake")

include(${${export_config_name}_TARGETS})
Run Code Online (Sandbox Code Playgroud)
  • useFoo/CMakeLists.txt
cmake_minimum_required(VERSION 3.13)

project(useFoo VERSION 1.2.3)

find_package(FooBarLib REQUIRED)

file(GENERATE OUTPUT foobar-gen CONTENT "<TARGET_FILE:foobar>=$<TARGET_FILE:foobar>\n")

get_target_property(foobar_INCLUDE_DIR foobar INTERFACE_INCLUDE_DIRECTORIES)
message(STATUS "foobar_INCLUDE_DIR=${foobar_INCLUDE_DIR}")

get_target_property(imported_location foobar IMPORTED_LOCATION_RELEASE)
get_filename_component(foobar_LIBRARY_DIR ${imported_location} DIRECTORY)
message(STATUS "foobar_LIBRARY_DIR=${foobar_LIBRARY_DIR}")
Run Code Online (Sandbox Code Playgroud)

build.sh 的输出

./build.sh 
+ set -o pipefail
+++ dirname ./build.sh
++ cd .
++ pwd
+ script_dir=/tmp/stackoverflow-56135785-answer
+ project_name=FooBarLib
+ archive_name=FooBarLib
+ cd /tmp/stackoverflow-56135785-answer
+ rm -rf FooBarLib-build
+ mkdir FooBarLib-build
+ cd FooBarLib-build
+ cmake ../FooBarLib
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Setting build type to 'Release' as none was specified.
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/stackoverflow-56135785-answer/FooBarLib-build
+ make
Scanning dependencies of target foobar
[ 50%] Building CXX object CMakeFiles/foobar.dir/foobar.cpp.o
[100%] Linking CXX shared library libfoobar.so
[100%] Built target foobar
+ make package
[100%] Built target foobar
Run CPack packaging tool...
CPack: Create package using TGZ
CPack: Install projects
CPack: - Run preinstall target for: FooBarLib
CPack: - Install project: FooBarLib
CPack: Create package
CPack: - package: /tmp/stackoverflow-56135785-answer/FooBarLib-build/FooBarLib-1.2.3.tar.gz generated.
CPack: Create package using RPM
CPack: Install projects
CPack: - Run preinstall target for: FooBarLib
CPack: - Install project: FooBarLib
CPack: Create package
-- CPackRPM:Debug: Using CPACK_RPM_ROOTDIR=/tmp/stackoverflow-56135785-answer/FooBarLib-build/_CPack_Packages/Linux/RPM
CPackRPM: Will use GENERATED spec file: /tmp/stackoverflow-56135785-answer/FooBarLib-build/_CPack_Packages/Linux/RPM/SPECS/foobarlib.spec
CPack: - package: /tmp/stackoverflow-56135785-answer/FooBarLib-build/FooBarLib-1.2.3.rpm generated.
+ cd /tmp/stackoverflow-56135785-answer
+ rm -rf FooBarLib-install
+ mkdir FooBarLib-install
+ cd FooBarLib-install
+ tar -xvzf ../FooBarLib-build/FooBarLib-1.2.3.tar.gz
opt/
opt/include/
opt/include/foobar.h
opt/lib/
opt/lib/libfoobar.so
opt/lib/cmake/
opt/lib/cmake/FooBarLib/
opt/lib/cmake/FooBarLib/FooBarLibTargets.cmake
opt/lib/cmake/FooBarLib/FooBarLibTargets-release.cmake
opt/lib/cmake/FooBarLib/FooBarLibConfigVersion.cmake
opt/lib/cmake/FooBarLib/FooBarLibConfig.cmake
+ cd /tmp/stackoverflow-56135785-answer
+ rm -rf useFoo-build
+ mkdir useFoo-build
+ cd useFoo-build
+ cpack_install_prefix=/opt
+ cmake -DFooBarLib_DIR=/tmp/stackoverflow-56135785-answer/FooBarLib-install/opt/lib/cmake/FooBarLib/ ../useFoo
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- foobar_INCLUDE_DIR=/tmp/stackoverflow-56135785-answer/FooBarLib-install/opt/include
-- foobar_LIBRARY_DIR=/tmp/stackoverflow-56135785-answer/FooBarLib-install/opt/lib
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/stackoverflow-56135785-answer/useFoo-build
+ cat foobar-gen
<TARGET_FILE:foobar>=/tmp/stackoverflow-56135785-answer/FooBarLib-install/opt/lib/libfoobar.so
+ command -v rpmbuild
+ rpm -qlp /tmp/stackoverflow-56135785-answer/FooBarLib-build/FooBarLib-1.2.3.rpm
/opt
/opt/include
/opt/include/foobar.h
/opt/lib
/opt/lib/cmake
/opt/lib/cmake/FooBarLib
/opt/lib/cmake/FooBarLib/FooBarLibConfig.cmake
/opt/lib/cmake/FooBarLib/FooBarLibConfigVersion.cmake
/opt/lib/cmake/FooBarLib/FooBarLibTargets-release.cmake
/opt/lib/cmake/FooBarLib/FooBarLibTargets.cmake
/opt/lib/libfoobar.so
Run Code Online (Sandbox Code Playgroud)


Bru*_*ams 2

只有在检测了 cmake 本身的源代码之后,我才终于能够找到它。

导出和安装命令都能够为目标生成 cmake 文件。导出命令例如:

export(EXPORT foobarLibTargets
       FILE "${CMAKE_CURRENT_BINARY_DIR}/foobarLibTargets.cmake")
Run Code Online (Sandbox Code Playgroud)

创建引用构建树的 Targets.cmake。

安装命令例如:

install(EXPORT foobarLibTargets
        FILE foobarTargets.cmake
        DESTINATION lib/cmake)
Run Code Online (Sandbox Code Playgroud)

创建引用可重定位安装位置的 Targets.cmake。

这本质上就是 @J-Christophe 所说的安装了两个文件而选择了错误的文件的意思。

我错误地认为安装命令只负责安装文件,而导出命令只负责生成文件。

文档现在有意义

导出(导出[命名空间][文件])

此命令创建的文件特定于构建树,切勿安装。请参阅 install(EXPORT) 命令以从安装树导出目标。

我之前的解决方法不再需要了。作为参考,这是在包的 Config.cmake 中显式设置正确的位置,如下所示:

set(FOOBAR_VERSION @VERSION@)

@PACKAGE_INIT@

set_and_check(FOOBAR_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
set_and_check(FOOBAR_LIBRARY "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so")
set_and_check(FOOBAR_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@")
include("${CMAKE_CURRENT_LIST_DIR}/foobarLibTargets.cmake")

# workaround - correct absolute path in the above
# this shouldn't be necessary!
set_target_properties(foobar PROPERTIES
                      IMPORTED_LOCATION_NOCONFIG  "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so"
)
Run Code Online (Sandbox Code Playgroud)