我希望能够从已安装的库中导入目标,但在使用时:
install(TARGETS
foobar
EXPORT foobarLibTargets
LIBRARY DESTINATION lib)
cmake生成一个包含绝对路径的foobarLibTargets.cmake:
set_target_properties(foobar PROPERTIES
IMPORTED_LOCATION_NOCONFIG "/where/I/happened/to/build/libfoobar.so"
IMPORTED_SONAME_NOCONFIG "libfoobar.so"
)
这样,使用从安装中导入的目标的构建将失败,因为该路径不存在。
Q :我如何才能让它使用正确的相对位置?
这相当于:
set_target_properties(foobar PROPERTIES
IMPORTED_LOCATION_NOCONFIG "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so")
如果我看另一个项目,它做了类似的事情,但工作正常,它有:
set_target_properties(foobar PROPERTIES
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libfoobar.so"
IMPORTED_SONAME_RELEASE "libfoobar.so"
)
以下是重现该问题的一些示例文件:
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}")
foobarConfig.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"
#)
foobar.h:
void hello();
foobar.cpp:
#include <iostream>
void hello() {
std::cerr << "hello world\n";
}
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}")
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
cat foobar-gen
的输出为:
<TARGET_FILE:foobar>=/where/I/happened/to/build/libfoobar.so
我希望它是:
<TARGET_FILE:foobar>=/where/I/actually/installed/libfoobar.so
如果我取消对解决方法的注释,它就会变成这样。有什么方法可以避免这种变通方法吗?
相关的问题- Strange issue with variables in a config-file cmake package -有类似的代码,既重现了这个问题,又在上面添加了另一个问题。
发布于 2019-05-15 01:37:25
只有在检测了cmake本身的源代码之后,我才最终能够追踪到它。
export和install命令都能够为目标生成cmake文件。导出命令,例如:
export(EXPORT foobarLibTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/foobarLibTargets.cmake")
创建引用生成树的Targets.cmake。
安装命令,例如:
install(EXPORT foobarLibTargets
FILE foobarTargets.cmake
DESTINATION lib/cmake)
创建引用可重定位安装位置的Targets.cmake。
这基本上就是@J-Christophe所说的安装了两个文件,但拿错了一个文件的意思。
我错误地认为install命令只负责安装文件,export命令只负责生成文件。
现在documentation变得有意义了
导出(导出命名空间)
此命令创建的文件特定于构建树,不应安装。请参见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"
)
https://stackoverflow.com/questions/56135785
复制相似问题