Issue
I am trying to join two paths together:
SET(CMAKE_INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}/inkscape")
but a string concatenation does not really do it when CMAKE_INSTALL_LIBDIR
contains an absolute path.
Is there a CMake function that takes multiple path arguments and joins relative paths right of the rightmost absolute path to the absolute path, like Python’s os.path.join
does?
Examples from Python interpreter showing desired behaviour:
>>> from os.path import join
>>> join("/foo/bar", "/baz/qux")
'/baz/qux'
>>> join("foo/bar", "/baz/qux")
'/baz/qux'
>>> join("/foo/bar", "./baz/qux")
'/foo/bar/./baz/qux'
>>> join("/foo/bar", "../baz/qux")
'/foo/bar/../baz/qux'
>>> join("./foo/bar", "baz/qux")
'./foo/bar/baz/qux'
I need to handle both the cases where the prefix is absolute (e.g. CMAKE_INSTALL_PREFIX
), and where it is relative (e.g. $ORIGIN/..
or ${prefix}
often needed for pkg-config
files). And orthogonally, I need to handle both Linux distributions that use relative CMAKE_INSTALL_LIBDIR
, and those that use an absolute one.
Solution
September 2020: cmake_path
command has just been merged: https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5158
I have sent an example implementation to the upstream issue. It supports multiple arguments like the Python’s os.path.join
and works on Linux at least:
# Modelled after Python’s os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}")
foreach(current_segment IN LISTS ARGN)
if(NOT ("${current_segment}" STREQUAL ""))
if(IS_ABSOLUTE "${current_segment}")
set(temp_path "${current_segment}")
else()
set(temp_path "${temp_path}/${current_segment}")
endif()
endif()
endforeach()
set(${joined_path} "${temp_path}" PARENT_SCOPE)
endfunction()
It would still be nice if CMake supported such essential functionality out of the box.
Answered By - Jan Tojnar