summaryrefslogtreecommitdiffstats
path: root/Modules/Internal/CPack/CPackDeb.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/Internal/CPack/CPackDeb.cmake')
-rw-r--r--Modules/Internal/CPack/CPackDeb.cmake101
1 files changed, 94 insertions, 7 deletions
diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake
index 5a78e3f..d4a47e4 100644
--- a/Modules/Internal/CPack/CPackDeb.cmake
+++ b/Modules/Internal/CPack/CPackDeb.cmake
@@ -56,6 +56,65 @@ function(extract_so_info shared_object libname version)
endif()
endfunction()
+#extract RUNPATH and RPATH for given shared object or executable
+function(extract_runpath_and_rpath shared_object_or_executable runpath rpath)
+ if(CPACK_READELF_EXECUTABLE)
+ execute_process(COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object_or_executable}"
+ WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}"
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE output
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(result EQUAL 0)
+ string(REGEX MATCH "\\(?RUNPATH\\)?[^\n]*\\[([^\n]+)\\]" found_runpath "${output}")
+ string(REPLACE ":" ";" found_runpath "${CMAKE_MATCH_1}")
+ list(REMOVE_DUPLICATES found_runpath)
+ string(REGEX MATCH "\\(?RPATH\\)?[^\n]*\\[([^\n]+)\\]" found_rpath "${output}")
+ string(REPLACE ":" ";" found_rpath "${CMAKE_MATCH_1}")
+ list(REMOVE_DUPLICATES found_rpath)
+ set(${runpath} "${found_runpath}" PARENT_SCOPE)
+ set(${rpath} "${found_rpath}" PARENT_SCOPE)
+ else()
+ message(WARNING "Error running readelf for \"${shared_object_or_executable}\"")
+ endif()
+ else()
+ message(FATAL_ERROR "Readelf utility is not available.")
+ endif()
+endfunction()
+
+#sanitizes the given directory name if required
+function(get_sanitized_dirname dirname outvar)
+ # NOTE: This pattern has to stay in sync with the 'prohibited_chars' variable
+ # defined in the C++ function `CPackGenerator::GetSanitizedDirOrFileName`!
+ set(prohibited_chars_pattern "[<]|[>]|[\"]|[/]|[\\]|[|]|[?]|[*]|[`]")
+ if("${dirname}" MATCHES "${prohibited_chars_pattern}")
+ string(MD5 santized_dirname "${dirname}")
+ set(${outvar} "${sanitized_dirname}" PARENT_SCOPE)
+ else()
+ set(${outvar} "${dirname}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+#retrieve packaging directories of components the current component depends on
+# Note: May only be called from within 'cpack_deb_prepare_package_var'!
+function(get_packaging_dirs_of_dependencies outvar)
+ if(CPACK_DEB_PACKAGE_COMPONENT)
+ if(NOT DEFINED WDIR OR NOT DEFINED _local_component_name)
+ message(FATAL_ERROR "CPackDeb: Function '${CMAKE_CURRENT_FUNCTION}' not called from correct function scope!")
+ endif()
+ set(result_list)
+ foreach(dependency_name IN LISTS CPACK_COMPONENT_${_local_component_name}_DEPENDS)
+ get_sanitized_dirname("${dependency_name}" dependency_name)
+ cmake_path(APPEND_STRING WDIR "/../${dependency_name}" OUTPUT_VARIABLE dependency_packaging_dir)
+ cmake_path(NORMAL_PATH dependency_packaging_dir)
+ list(APPEND result_list "${dependency_packaging_dir}")
+ endforeach()
+ set(${outvar} "${result_list}" PARENT_SCOPE) # Set return variable.
+ else()
+ set(${outvar} "" PARENT_SCOPE) # Clear return variable.
+ endif()
+endfunction()
+
function(cpack_deb_check_description SUMMARY LINES RESULT_VARIABLE)
set(_result TRUE)
@@ -310,16 +369,44 @@ function(cpack_deb_prepare_package_vars)
set(IGNORE_MISSING_INFO_FLAG "--ignore-missing-info")
endif()
- if(CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS)
+ # Add -l option if the tool supports it?
+ if(DEFINED SHLIBDEPS_EXECUTABLE_VERSION AND SHLIBDEPS_EXECUTABLE_VERSION VERSION_GREATER_EQUAL 1.17.0)
unset(PRIVATE_SEARCH_DIR_OPTIONS)
- # Add -l option if the tool supports it
- if(DEFINED SHLIBDEPS_EXECUTABLE_VERSION AND SHLIBDEPS_EXECUTABLE_VERSION VERSION_GREATER_EQUAL 1.17.0)
- foreach(dir IN LISTS CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS)
- list(APPEND PRIVATE_SEARCH_DIR_OPTIONS "-l${dir}")
+
+ # Use directories provided via CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS
+ if(NOT "${CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS}" STREQUAL "")
+ foreach(path IN LISTS CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS)
+ cmake_path(NORMAL_PATH path) # Required for dpkg-shlibdeps!
+ list(APPEND PRIVATE_SEARCH_DIR_OPTIONS "-l${path}")
endforeach()
- else()
- message(WARNING "CPackDeb: dkpg-shlibdeps is too old. \"CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS\" is therefore ignored.")
endif()
+
+ # Use directories extracted from RUNPATH/RPATH
+ get_packaging_dirs_of_dependencies(deps_packaging_dirs)
+ foreach(exe IN LISTS CPACK_DEB_BINARY_FILES)
+ cmake_path(GET exe PARENT_PATH exe_dir)
+ extract_runpath_and_rpath(${exe} runpath rpath)
+ # If RUNPATH is available, RPATH will be ignored. Therefore we have to do the same here!
+ if (NOT "${runpath}" STREQUAL "")
+ set(selected_rpath "${runpath}")
+ else()
+ set(selected_rpath "${rpath}")
+ endif()
+ foreach(search_path IN LISTS selected_rpath)
+ if ("${search_path}" MATCHES "^[$]ORIGIN" OR "${search_path}" MATCHES "^[$][{]ORIGIN[}]")
+ foreach(deps_pkgdir IN LISTS deps_packaging_dirs)
+ string(REPLACE "\$ORIGIN" "${deps_pkgdir}/${exe_dir}" path "${search_path}")
+ string(REPLACE "\${ORIGIN}" "${deps_pkgdir}/${exe_dir}" path "${path}")
+ cmake_path(NORMAL_PATH path) # Required for dpkg-shlibdeps!
+ list(APPEND PRIVATE_SEARCH_DIR_OPTIONS "-l${path}")
+ endforeach()
+ endif()
+ endforeach()
+ endforeach()
+
+ list(REMOVE_DUPLICATES PRIVATE_SEARCH_DIR_OPTIONS)
+ elseif(NOT "${CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS}" STREQUAL "")
+ message(WARNING "CPackDeb: dkpg-shlibdeps is too old. \"CPACK_DEBIAN_PACKAGE_SHLIBDEPS_PRIVATE_DIRS\" is therefore ignored.")
endif()
# Execute dpkg-shlibdeps