I would like to be able to import targets from an installed library but
when using:
install(TARGETS
foobar
EXPORT foobarLibTargets
LIBRARY DESTINATION lib)
cmake generates a foobarLibTargets.cmake containing an absolute path:
set_target_properties(foobar PROPERTIES
IMPORTED_LOCATION_NOCONFIG "/where/I/happened/to/build/libfoobar.so"
IMPORTED_SONAME_NOCONFIG "libfoobar.so"
)
Such that a build using the imported target from the installation will fail as the path does not exist.
Q How can I get it to use the correct relative location instead?
This would be equivalent to:
set_target_properties(foobar PROPERTIES
IMPORTED_LOCATION_NOCONFIG "@PACKAGE_LIBRARY_INSTALL_DIR@/libfoobar.so")
If I look at another project which does something similar but works it has:
set_target_properties(foobar PROPERTIES
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libfoobar.so"
IMPORTED_SONAME_RELEASE "libfoobar.so"
)
Here are some example files that reproduce the issue:
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
";
}
useFoo.cmake (a CMakeLists.txt for an example project using the installed library):
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>
")
message(STATUS "FOOBAR_LIBRARY_DIR=${FOOBAR_LIBRARY_DIR}")
message(STATUS "FOOBAR_INCLUDE_DIR=${FOOBAR_INCLUDE_DIR}")
build.sh (build and use the installation package):
#!/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
The output of cat foobar-gen
is:
<TARGET_FILE:foobar>=/where/I/happened/to/build/libfoobar.so
I would like it to be:
<TARGET_FILE:foobar>=/where/I/actually/installed/libfoobar.so
Which it becomes if I uncomment the workaround.
Is there a way which avoids the workaround?
The related question - Strange issue with variables in a config-file cmake package - has similar code which both reproduces this issue and adds another one on top.
See Question&Answers more detail:
os