From 278aa59dcd091d9337937bab92fe68cad1dc3e85 Mon Sep 17 00:00:00 2001 From: Michael Witten <mfwitten@gmail.com> Date: Fri, 8 Mar 2024 19:34:15 +0000 Subject: [PATCH] build: Tell cmake to set 'rpath' so the installed 'cmark' can find 'libcmark.so' Before this commit, the 'cmark' executable didn't inform the dynamic linker where to look for the 'libcmark' shared object; this becomes an irritation when 'libcmark' is installed in an unorthodox location: $ ldd /path/to/installed/files/bin/cmark linux-gate.so.1 (0xb7ed7000) libcmark.so.0.31.0 => not found libc.so.6 => /usr/lib/libc.so.6 (0xb7cf3000) /lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xb7ed8000) Because of this commit, the 'cmark' executable's 'rpath' setting (or equivalent) is set upon installation, thereby providing the required search directory: $ ldd /path/to/installed/files/bin/cmark linux-gate.so.1 (0xb7ef2000) libcmark.so.0.31.0 => /path/to/installed/files/lib/libcmark.so.0.31.0 (0xb7e95000) libc.so.6 => /usr/lib/libc.so.6 (0xb7cbc000) /lib/ld-linux.so.2 => /usr/lib/ld-linux.so.2 (0xb7ef3000) There is some intelligence behind whether 'rpath' is set at all: * If a shared object (e.g., 'libcmark') is going to be installed in a standard location, then such location is not added to 'rpath'. * A non-standard installation will cause 'rpath' to include at least the following path provided by cmake: "${CMAKE_INSTALL_PREFIX_FULL_LIBDIR}" * Also, cmake has been instructed to append any non-standard path to 'rpath' if cmake is aware of an external dependency from such a path. Of course, this will only help on a system that supports an 'rpath' feature known to cmake; for example, Windows has no such feature, and so all of this will presumably be ignored when building under that system. --- CMakeLists.txt | 5 ++++- cmake/modules/SetRPATH.cmake | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 cmake/modules/SetRPATH.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index ce54658c8..054f8d43c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,9 @@ project(cmark LANGUAGES C CXX VERSION 0.31.0) +list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) + if(CMAKE_BUILD_TYPE MATCHES "asan|ubsan") - list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules) include(FindAsan) endif() @@ -69,6 +70,8 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) set(CMAKE_INCLUDE_CURRENT_DIR ON) +include(SetRPATH) + # Check integrity of node structure when compiled as debug add_compile_options($<$<CONFIG:Debug>:-DCMARK_DEBUG_NODES>) diff --git a/cmake/modules/SetRPATH.cmake b/cmake/modules/SetRPATH.cmake new file mode 100644 index 000000000..818a0cd03 --- /dev/null +++ b/cmake/modules/SetRPATH.cmake @@ -0,0 +1,15 @@ +set(CMAKE_SKIP_BUILD_RPATH FALSE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + +# Append non-standard external dependency directories +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +# CMake 3.25 has a better scoping solution: 'block()' +function(SetRPATH) + set(p "${CMAKE_INSTALL_FULL_LIBDIR}") + list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${p}" i) + if("${i}" STREQUAL "-1") + set(CMAKE_INSTALL_RPATH "${p}" PARENT_SCOPE) + endif() +endfunction() +SetRPATH()