-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refine rpath fixup to inspect already existing rpaths #36056
Changes from all commits
921afab
ccac791
f864724
df653e0
9095755
ce7ff23
ca4fa57
2b2cb39
52b16cd
c4c7179
2fbead5
9e2360d
0d84b70
bf77727
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -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") | ||||
# If this fails, the file is not an elf | ||||
execute_process( | ||||
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() | ||||
|
||||
# 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() | ||||
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 | ||||
) | ||||
|
||||
# If this fails, the file is not an elf | ||||
execute_process( | ||||
COMMAND "${PATCHELF}" --set-rpath "${rpath}" "${elf_file}" | ||||
COMMAND "${PATCHELF}" --set-rpath "${new_rpath}" "${elf_file}" | ||||
OUTPUT_QUIET | ||||
ERROR_VARIABLE set_rpath_error | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Or keep the error check in case patchelf for some reason couldn't fix our binary for some reason. |
||||
) | ||||
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() |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -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) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
or
Suggested change
Otherwise I don't see how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I was assuming it would be fixed to not apply to static triplets in my comment. |
||||||||||
z_vcpkg_fixup_rpath_in_dir() | ||||||||||
endif() | ||||||||||
include("${SCRIPTS}/build_info.cmake") | ||||||||||
endif() | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Neumann-A I may be overlooking the obvious: Is there a reason why each line occurs twice? AFAICS they cannot match twice. Every match inserts
$ORIGIN
, and then it cannot have a second insertion.