Reputation: 395
General problem:
I get absolute paths in my INTERFACE_LINK_LIBRARIES
and INTERFACE_INCLUDE_DIRECTORIES
properties for a target, which is a problem because these variables get exported via the install(EXPORT)
, which will mean trouble if anything is relocated. I traced the origin of these absolute paths back to the find_package
command, which (for some but not all packages) sets variables like Boost_LIBRARIES
with absolute paths. When they are used with e.g. the target_link_libraries
command, they end up in the INTERFACE_LINK_LIBRARIES
.
Q: How do I best avoid the exported target properties from being poluted with absolute paths?
The trivial solution is obviously to just overwrite the respective variables with some strings that only name the libraries (hardcoded), but I guess there should be a better way.
Specific problem (Example): see https://github.com/cartographer-project/cartographer/issues/1688
EDIT:
My (modified) cartographer-config.cmake.in
(note: you can ignore the stuff associated to ceres
, since that does not give me trouble, eventhough it places an abs path in the hint):
# 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")
Upvotes: 1
Views: 1643
Reputation: 65996
How do I best avoid the exported target properties from being poluted with absolute paths?
Hide absolute paths behind the IMPORTED target:
# 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)
Such way, the config file for my_lib
will contain only the name of the IMPORTED library, but not its properties.
In the config file for your project you just need to create IMPORTED target with the same name and fill its properties according to the current machine (where your project is used).
find_package
for most of modern packages (including Boost) already returns an IMPORTED target. In the configuration file for your project you may use find_dependency, which discovers the package on the current machine and creates an IMPORTED target again.
For old packages, which find_package
just returns XXX_LIBRARIES
and XXX_INCLUDE_DIRECTORIES
variables, you may create the IMPORTED target manually. In the configuration file for your project you may use find_dependency
too, and again create IMPORTED target manually.
When use find_dependency
macro, remember to pass the same parameters which you have passed to the find_package()
in the project's CMakeLists.txt
. This is primary about COMPONENTS
parameter and variables like Boost_USE_STATIC_LIBS
, which affects on the package searching.
If you want to specify VERSION
requirement, then this requirement should express binary compatibility of the library on the target machine with the library against which the project has been actually built.
HINST
and PATHS
options for find_package
are unlikely needed to be transferred to the find_dependency
: call to the find_dependency
is processed on the target machine, which paths could be different from ones on the build machine.
Upvotes: 2