mirror of
https://github.com/microsoft/vcpkg.git
synced 2025-01-19 05:53:03 +08:00
Refine rpath fixup to inspect already existing rpaths (#36056)
Reason: ``` -- Adjusting original rpath of: '/mnt/e/all/vcpkg/installed/x64-linux-release/lib/pkgconfig/../../lib/intel64/' -- Fixed rpath in: '/mnt/e/all/vcpkg/packages/numpy_x64-linux-release/lib/python3.11/site-packages/numpy/linalg/lapack_lite.cpython-311-x86_64-linux-gnu.so' ('$ORIGIN:$ORIGIN/../../../../:$ORIGIN/../../../../intel64/') ``` needed `$ORIGIN/../../../../intel64/` in there which came from a pc file via `-Wl,-rpath='${libdir}'` --------- Co-authored-by: Osyotr <Osyotr@users.noreply.github.com>
This commit is contained in:
parent
002c5b0659
commit
2ac6ba173b
@ -1,3 +1,65 @@
|
||||
function(z_vcpkg_calculate_corrected_rpath)
|
||||
cmake_parse_arguments(PARSE_ARGV 0 "arg"
|
||||
""
|
||||
"ELF_FILE_DIR;ORG_RPATH;OUT_NEW_RPATH_VAR"
|
||||
"")
|
||||
|
||||
set(elf_file_dir "${arg_ELF_FILE_DIR}")
|
||||
set(org_rpath "${arg_ORG_RPATH}")
|
||||
|
||||
set(current_prefix "${CURRENT_PACKAGES_DIR}")
|
||||
set(current_installed_prefix "${CURRENT_INSTALLED_DIR}")
|
||||
if(elf_file_dir MATCHES "debug/")
|
||||
set(current_prefix "${CURRENT_PACKAGES_DIR}/debug")
|
||||
set(current_installed_prefix "${CURRENT_INSTALLED_DIR}/debug")
|
||||
endif()
|
||||
|
||||
# compute path relative to lib
|
||||
file(RELATIVE_PATH relative_to_lib "${elf_file_dir}" "${current_prefix}/lib")
|
||||
# compute path relative to prefix
|
||||
file(RELATIVE_PATH relative_to_prefix "${elf_file_dir}" "${current_prefix}")
|
||||
|
||||
set(rpath_norm "")
|
||||
if(NOT org_rpath STREQUAL "")
|
||||
cmake_path(CONVERT "${org_rpath}" TO_CMAKE_PATH_LIST rpath_norm)
|
||||
list(TRANSFORM rpath_norm REPLACE "${elf_file_dir}" "\$ORIGIN")
|
||||
# Remove unnecessary up/down ; don't use normalize $ORIGIN/../ will be removed otherwise
|
||||
list(TRANSFORM rpath_norm REPLACE "/lib/pkgconfig/../.." "")
|
||||
# lib relative corrections
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_prefix}/lib/?" "\$ORIGIN/${relative_to_lib}/")
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_installed_prefix}/lib/?" "\$ORIGIN/${relative_to_lib}/")
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_prefix}/lib/?" "\$ORIGIN/${relative_to_lib}/")
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_installed_prefix}/lib/?" "\$ORIGIN/${relative_to_lib}/")
|
||||
# prefix relativ
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_prefix}" "\$ORIGIN/${relative_to_prefix}/")
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_installed_prefix}" "\$ORIGIN/${relative_to_prefix}/")
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_prefix}" "\$ORIGIN/${relative_to_prefix}/")
|
||||
list(TRANSFORM rpath_norm REPLACE "${current_installed_prefix}" "\$ORIGIN/${relative_to_prefix}/")
|
||||
|
||||
# Path normalization
|
||||
list(TRANSFORM rpath_norm REPLACE "/+" "/")
|
||||
list(TRANSFORM rpath_norm REPLACE "/^" "")
|
||||
|
||||
# duplication removal
|
||||
list(REMOVE_ITEM rpath_norm "\$ORIGIN")
|
||||
list(REMOVE_ITEM rpath_norm "\$ORIGIN/${relative_to_lib}")
|
||||
list(REMOVE_DUPLICATES rpath_norm)
|
||||
|
||||
if(NOT X_VCPKG_RPATH_KEEP_SYSTEM_PATHS)
|
||||
list(FILTER rpath_norm INCLUDE REGEX "\\\$ORIGIN.+") # Only keep paths relativ to ORIGIN
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT relative_to_lib STREQUAL "")
|
||||
list(PREPEND rpath_norm "\$ORIGIN/${relative_to_lib}")
|
||||
endif()
|
||||
list(PREPEND rpath_norm "\$ORIGIN") # Make ORIGIN the first entry
|
||||
list(TRANSFORM rpath_norm REPLACE "/$" "")
|
||||
cmake_path(CONVERT "${rpath_norm}" TO_NATIVE_PATH_LIST new_rpath)
|
||||
|
||||
set("${arg_OUT_NEW_RPATH_VAR}" "${new_rpath}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(z_vcpkg_fixup_rpath_in_dir)
|
||||
vcpkg_find_acquire_program(PATCHELF)
|
||||
|
||||
@ -21,37 +83,41 @@ function(z_vcpkg_fixup_rpath_in_dir)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE elf_files LIST_DIRECTORIES FALSE "${folder}/*")
|
||||
list(FILTER elf_files EXCLUDE REGEX "\\\.(cpp|cc|cxx|c|hpp|h|hh|hxx|inc|json|toml|yaml|man|m4|ac|am|in|log|txt|pyi?|pyc|pyx|pxd|pc|cmake|f77|f90|f03|fi|f|cu|mod|ini|whl|cat|csv|rst|md|npy|npz|template|build)$")
|
||||
list(FILTER elf_files EXCLUDE REGEX "/(copyright|LICENSE|METADATA)$")
|
||||
|
||||
foreach(elf_file IN LISTS elf_files)
|
||||
if(IS_SYMLINK "${elf_file}")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
get_filename_component(elf_file_dir "${elf_file}" DIRECTORY)
|
||||
|
||||
set(current_prefix "${CURRENT_PACKAGES_DIR}")
|
||||
if(elf_file_dir MATCHES "debug/")
|
||||
set(current_prefix "${CURRENT_PACKAGES_DIR}/debug")
|
||||
endif()
|
||||
|
||||
# compute path relative to lib
|
||||
file(RELATIVE_PATH relative_to_lib "${elf_file_dir}" "${current_prefix}/lib")
|
||||
if(relative_to_lib STREQUAL "")
|
||||
set(rpath "\$ORIGIN")
|
||||
else()
|
||||
set(rpath "\$ORIGIN:\$ORIGIN/${relative_to_lib}")
|
||||
endif()
|
||||
|
||||
# If this fails, the file is not an elf
|
||||
execute_process(
|
||||
COMMAND "${PATCHELF}" --set-rpath "${rpath}" "${elf_file}"
|
||||
COMMAND "${PATCHELF}" --print-rpath "${elf_file}"
|
||||
OUTPUT_VARIABLE readelf_output
|
||||
ERROR_VARIABLE read_rpath_error
|
||||
)
|
||||
string(REPLACE "\n" "" readelf_output "${readelf_output}")
|
||||
if(NOT "${read_rpath_error}" STREQUAL "" OR "${readelf_output}" STREQUAL "")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
get_filename_component(elf_file_dir "${elf_file}" DIRECTORY)
|
||||
|
||||
Z_vcpkg_calculate_corrected_rpath(
|
||||
ELF_FILE_DIR "${elf_file_dir}"
|
||||
ORG_RPATH "${readelf_output}"
|
||||
OUT_NEW_RPATH_VAR new_rpath
|
||||
)
|
||||
|
||||
execute_process(
|
||||
COMMAND "${PATCHELF}" --set-rpath "${new_rpath}" "${elf_file}"
|
||||
OUTPUT_QUIET
|
||||
ERROR_VARIABLE set_rpath_error
|
||||
)
|
||||
if("${set_rpath_error}" STREQUAL "")
|
||||
message(STATUS "Fixed rpath: ${elf_file} (${rpath})")
|
||||
endif()
|
||||
|
||||
message(STATUS "Adjusted RPATH of '${elf_file}' (From '${org_rpath}' -> To '${new_rpath}')")
|
||||
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
z_vcpkg_fixup_rpath_in_dir()
|
||||
|
@ -87,6 +87,8 @@ include("${SCRIPTS}/cmake/z_vcpkg_get_cmake_vars.cmake")
|
||||
include("${SCRIPTS}/cmake/z_vcpkg_prettify_command_line.cmake")
|
||||
include("${SCRIPTS}/cmake/z_vcpkg_setup_pkgconfig_path.cmake")
|
||||
|
||||
include("${SCRIPTS}/cmake/z_vcpkg_fixup_rpath.cmake")
|
||||
|
||||
function(debug_message)
|
||||
if(PORT_DEBUG)
|
||||
z_vcpkg_function_arguments(ARGS)
|
||||
@ -169,8 +171,8 @@ if(CMD STREQUAL "BUILD")
|
||||
|
||||
include("${CURRENT_PORT_DIR}/portfile.cmake")
|
||||
if(DEFINED PORT)
|
||||
if(VCPKG_FIXUP_ELF_RPATH)
|
||||
include("${SCRIPTS}/cmake/z_vcpkg_fixup_rpath.cmake")
|
||||
if(VCPKG_FIXUP_ELF_RPATH OR VCPKG_TARGET_IS_LINUX)
|
||||
z_vcpkg_fixup_rpath_in_dir()
|
||||
endif()
|
||||
include("${SCRIPTS}/build_info.cmake")
|
||||
endif()
|
||||
|
@ -47,11 +47,12 @@ endif()
|
||||
|
||||
set(missing "")
|
||||
foreach(variable IN LISTS variables)
|
||||
list(POP_BACK "${variable}" program)
|
||||
set(var_contents "${${variable}}")
|
||||
list(POP_BACK var_contents program)
|
||||
if(NOT EXISTS "${program}")
|
||||
list(APPEND missing "${variable}: ${program}")
|
||||
endif()
|
||||
list(POP_FRONT "${variable}" interpreter)
|
||||
list(POP_FRONT var_contents interpreter)
|
||||
if(interpreter AND NOT EXISTS "${interpreter}")
|
||||
list(APPEND missing "${variable} (interpreter): ${interpreter}")
|
||||
endif()
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vcpkg-find-acquire-program",
|
||||
"version-string": "0",
|
||||
"port-version": 1,
|
||||
"port-version": 2,
|
||||
"description": "Test port to exercise vcpkg_find_acquire_program",
|
||||
"supports": "native"
|
||||
}
|
||||
|
89
scripts/test_ports/vcpkg-fix-rpath/portfile.cmake
Normal file
89
scripts/test_ports/vcpkg-fix-rpath/portfile.cmake
Normal file
@ -0,0 +1,89 @@
|
||||
set(VCPKG_POLICY_EMPTY_PACKAGE enabled)
|
||||
|
||||
|
||||
# Simple replacement and outside path test
|
||||
set(elf_dir "${CURRENT_PACKAGES_DIR}/lib")
|
||||
set(test_rpath "${CURRENT_PACKAGES_DIR}/lib:/usr/lib/")
|
||||
set(expected "$ORIGIN")
|
||||
|
||||
z_vcpkg_calculate_corrected_rpath(
|
||||
ELF_FILE_DIR "${elf_dir}"
|
||||
ORG_RPATH "${test_rpath}"
|
||||
OUT_NEW_RPATH_VAR new_rpath
|
||||
)
|
||||
|
||||
if(NOT "x${new_rpath}x" STREQUAL "x${expected}x")
|
||||
message(FATAL_ERROR "--- Calculated rpath does not agree with expected rpath: '${new_rpath}' != '${expected}' ")
|
||||
else()
|
||||
message(STATUS "--- Calculated rpath agrees with expected rpath: '${new_rpath}' ")
|
||||
endif()
|
||||
|
||||
# Simple pkgconfig path and outside path test
|
||||
set(elf_dir "${CURRENT_PACKAGES_DIR}/lib/")
|
||||
set(test_rpath "${CURRENT_INSTALLED_DIR}/lib/pkgconfig/../../lib:/usr/lib/")
|
||||
set(expected "$ORIGIN")
|
||||
|
||||
z_vcpkg_calculate_corrected_rpath(
|
||||
ELF_FILE_DIR "${elf_dir}"
|
||||
ORG_RPATH "${test_rpath}"
|
||||
OUT_NEW_RPATH_VAR new_rpath
|
||||
)
|
||||
|
||||
if(NOT "x${new_rpath}x" STREQUAL "x${expected}x")
|
||||
message(FATAL_ERROR "--- Calculated rpath does not agree with expected rpath: '${new_rpath}' != '${expected}' ")
|
||||
else()
|
||||
message(STATUS "--- Calculated rpath agrees with expected rpath: '${new_rpath}' ")
|
||||
endif()
|
||||
|
||||
# elf dir in subdir
|
||||
set(elf_dir "${CURRENT_PACKAGES_DIR}/lib/somesubdir")
|
||||
set(test_rpath "${CURRENT_INSTALLED_DIR}/lib/pkgconfig/../../lib:/usr/lib/")
|
||||
set(expected "$ORIGIN:$ORIGIN/..")
|
||||
|
||||
z_vcpkg_calculate_corrected_rpath(
|
||||
ELF_FILE_DIR "${elf_dir}"
|
||||
ORG_RPATH "${test_rpath}"
|
||||
OUT_NEW_RPATH_VAR new_rpath
|
||||
)
|
||||
|
||||
if(NOT "x${new_rpath}x" STREQUAL "x${expected}x")
|
||||
message(FATAL_ERROR "--- Calculated rpath does not agree with expected rpath: '${new_rpath}' != '${expected}' ")
|
||||
else()
|
||||
message(STATUS "--- Calculated rpath agrees with expected rpath: '${new_rpath}' ")
|
||||
endif()
|
||||
|
||||
# Getting more complex
|
||||
set(elf_dir "${CURRENT_PACKAGES_DIR}/plugins/notlib/extrasubdir")
|
||||
set(test_rpath "${CURRENT_PACKAGES_DIR}/lib/pkgconfig/../../lib/someotherdir2:${CURRENT_INSTALLED_DIR}/lib/pkgconfig/../../someotherdir1:/usr/lib/")
|
||||
set(expected "$ORIGIN:$ORIGIN/../../../lib:$ORIGIN/../../../lib/someotherdir2:$ORIGIN/../../../someotherdir1")
|
||||
|
||||
z_vcpkg_calculate_corrected_rpath(
|
||||
ELF_FILE_DIR "${elf_dir}"
|
||||
ORG_RPATH "${test_rpath}"
|
||||
OUT_NEW_RPATH_VAR new_rpath
|
||||
)
|
||||
|
||||
if(NOT "x${new_rpath}x" STREQUAL "x${expected}x")
|
||||
message(FATAL_ERROR "--- Calculated rpath does not agree with expected rpath: '${new_rpath}' != '${expected}' ")
|
||||
else()
|
||||
message(STATUS "--- Calculated rpath agrees with expected rpath: '${new_rpath}' ")
|
||||
endif()
|
||||
|
||||
|
||||
set(X_VCPKG_RPATH_KEEP_SYSTEM_PATHS ON)
|
||||
# Simple replacement and outside path test
|
||||
set(elf_dir "${CURRENT_PACKAGES_DIR}/lib")
|
||||
set(test_rpath "${CURRENT_PACKAGES_DIR}/lib:/usr/lib/")
|
||||
set(expected "$ORIGIN:/usr/lib")
|
||||
|
||||
z_vcpkg_calculate_corrected_rpath(
|
||||
ELF_FILE_DIR "${elf_dir}"
|
||||
ORG_RPATH "${test_rpath}"
|
||||
OUT_NEW_RPATH_VAR new_rpath
|
||||
)
|
||||
|
||||
if(NOT "x${new_rpath}x" STREQUAL "x${expected}x")
|
||||
message(FATAL_ERROR "--- Calculated rpath does not agree with expected rpath: '${new_rpath}' != '${expected}' ")
|
||||
else()
|
||||
message(STATUS "--- Calculated rpath agrees with expected rpath: '${new_rpath}' ")
|
||||
endif()
|
6
scripts/test_ports/vcpkg-fix-rpath/vcpkg.json
Normal file
6
scripts/test_ports/vcpkg-fix-rpath/vcpkg.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "vcpkg-fix-rpath",
|
||||
"version-date": "2024-02-10",
|
||||
"description": "Test port to check the string replacement in z_vcpkg_fixup_rpath",
|
||||
"supports": "native & linux"
|
||||
}
|
Loading…
Reference in New Issue
Block a user