Skip to content
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

[vcpkg-scripts] Fix rpath fixup; add test #37964

Merged
merged 9 commits into from
Apr 23, 2024
Merged
52 changes: 25 additions & 27 deletions scripts/cmake/z_vcpkg_fixup_rpath.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,47 @@ function(z_vcpkg_calculate_corrected_rpath)
"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/")
file(RELATIVE_PATH relative_from_packages "${CURRENT_PACKAGES_DIR}" "${arg_ELF_FILE_DIR}")
if("${relative_from_packages}/" MATCHES "^debug/|^(manual-tools|tools)/[^/]*/debug/")
dg0yt marked this conversation as resolved.
Show resolved Hide resolved
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")
file(RELATIVE_PATH relative_to_lib "${arg_ELF_FILE_DIR}" "${current_prefix}/lib")
# compute path relative to prefix
file(RELATIVE_PATH relative_to_prefix "${elf_file_dir}" "${current_prefix}")
file(RELATIVE_PATH relative_to_prefix "${arg_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")
if(NOT "${arg_ORG_RPATH}" STREQUAL "")
cmake_path(CONVERT "${arg_ORG_RPATH}" TO_CMAKE_PATH_LIST rpath_norm)

# pattern matching helpers
list(TRANSFORM rpath_norm PREPEND "::")
list(TRANSFORM rpath_norm APPEND "/")

string(REPLACE "::${arg_ELF_FILE_DIR}/" "::\$ORIGIN/" rpath_norm "${rpath_norm}")
# Remove unnecessary up/down ; don't use normalize $ORIGIN/../ will be removed otherwise
list(TRANSFORM rpath_norm REPLACE "/lib/pkgconfig/../.." "")
string(REPLACE "/lib/pkgconfig/../../" "/" rpath_norm "${rpath_norm}")
# 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}/")
string(REPLACE "::${current_prefix}/lib/" "::\$ORIGIN/${relative_to_lib}/" rpath_norm "${rpath_norm}")
string(REPLACE "::${current_installed_prefix}/lib" "::\$ORIGIN/${relative_to_lib}/" rpath_norm "${rpath_norm}")
# 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}/")
string(REPLACE "::${current_prefix}/" "::\$ORIGIN/${relative_to_prefix}/" rpath_norm "${rpath_norm}")
string(REPLACE "::${current_installed_prefix}/" "::\$ORIGIN/${relative_to_prefix}/" rpath_norm "${rpath_norm}")

if(NOT X_VCPKG_RPATH_KEEP_SYSTEM_PATHS)
list(FILTER rpath_norm INCLUDE REGEX "::\\\$ORIGIN.+") # Only keep paths relativ to ORIGIN
endif()

# 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}")

if(NOT X_VCPKG_RPATH_KEEP_SYSTEM_PATHS)
list(FILTER rpath_norm INCLUDE REGEX "\\\$ORIGIN.+") # Only keep paths relativ to ORIGIN
endif()
# remove pattern matching helpers
list(TRANSFORM rpath_norm REPLACE "^::" "")
list(TRANSFORM rpath_norm REPLACE "/\$" "")
endif()

if(NOT relative_to_lib STREQUAL "")
Expand Down Expand Up @@ -110,7 +108,7 @@ function(z_vcpkg_fixup_rpath_in_dir)

get_filename_component(elf_file_dir "${elf_file}" DIRECTORY)

Z_vcpkg_calculate_corrected_rpath(
z_vcpkg_calculate_corrected_rpath(
ELF_FILE_DIR "${elf_file_dir}"
ORG_RPATH "${readelf_output}"
OUT_NEW_RPATH_VAR new_rpath
Expand Down
3 changes: 3 additions & 0 deletions scripts/test_ports/unit-test-cmake/portfile.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,9 @@ endif()
if("fixup-pkgconfig" IN_LIST FEATURES)
include("${CMAKE_CURRENT_LIST_DIR}/test-vcpkg_fixup_pkgconfig.cmake")
endif()
if("fixup-rpath" IN_LIST FEATURES)
include("${CMAKE_CURRENT_LIST_DIR}/test-z_vcpkg_calculate_corrected_rpath.cmake")
endif()

if(Z_VCPKG_UNIT_TEST_HAS_ERROR)
_message(FATAL_ERROR "At least one test failed")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# z_vcpkg_calculate_corrected_rpath(...)

block(SCOPE_FOR VARIABLES)

set(CURRENT_PACKAGES_DIR "/P")
set(CURRENT_INSTALLED_DIR "/I")

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/lib")
]] out [[$ORIGIN]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/plugins/group")
]] out [[$ORIGIN:$ORIGIN/../../lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/debug/lib")
]] out [[$ORIGIN]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/debug/plugins/group")
]] out [[$ORIGIN:$ORIGIN/../../lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/tools/port")
]] out [[$ORIGIN:$ORIGIN/../../lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/tools/port/bin")
]] out [[$ORIGIN:$ORIGIN/../../../lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/tools/port/debug")
]] out [[$ORIGIN:$ORIGIN/../../../debug/lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/tools/port/debug/bin")
]] out [[$ORIGIN:$ORIGIN/../../../../debug/lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/manual-tools/port")
]] out [[$ORIGIN:$ORIGIN/../../lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/manual-tools/port/bin")
]] out [[$ORIGIN:$ORIGIN/../../../lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/manual-tools/port/debug")
]] out [[$ORIGIN:$ORIGIN/../../../debug/lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "" ELF_FILE_DIR "/P/manual-tools/port/debug/bin")
]] out [[$ORIGIN:$ORIGIN/../../../../debug/lib]])

# ORG_RPATH
set(X_VCPKG_RPATH_KEEP_SYSTEM_PATHS 1)
set(CURRENT_PACKAGES_DIR "/cxx/P")
set(CURRENT_INSTALLED_DIR "/cxx/I")

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/opt/lib:/usr/local/lib" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN:/opt/lib:/usr/local/lib]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/cxx/I/lib" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/cxx/P/lib" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/cxx/I/foo/lib/pkgconfig/../../bar" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

set(X_VCPKG_RPATH_KEEP_SYSTEM_PATHS 0)
set(CURRENT_PACKAGES_DIR "/cxx/P")
set(CURRENT_INSTALLED_DIR "/cxx/I")

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/opt/lib:/usr/local/lib" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/cxx/I/foo/bar" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/cxx/P/foo/bar" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/cxx/I/foo/lib/pkgconfig/../../bar" ELF_FILE_DIR "/cxx/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

# https://github.com/microsoft/vcpkg/issues/37984
set(CURRENT_PACKAGES_DIR "/c++/P")
set(CURRENT_INSTALLED_DIR "/c++/I")

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/c++/I/foo/bar" ELF_FILE_DIR "/c++/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/c++/P/foo/bar" ELF_FILE_DIR "/c++/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

set(CURRENT_PACKAGES_DIR "/(c)/P")
set(CURRENT_INSTALLED_DIR "/(c)/I")

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/(c)/I/foo/bar" ELF_FILE_DIR "/(c)/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])

unit_test_check_variable_equal([[
z_vcpkg_calculate_corrected_rpath(OUT_NEW_RPATH_VAR "out" ORG_RPATH "/(c)/P/foo/bar" ELF_FILE_DIR "/(c)/P/lib")
]] out [[$ORIGIN:$ORIGIN/../foo/bar]])


endblock()
8 changes: 8 additions & 0 deletions scripts/test_ports/unit-test-cmake/vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"default-features": [
"backup-restore-env-vars",
"fixup-pkgconfig",
{
"name": "fixup-rpath",
"platform": "!windows"
},
"function-arguments",
"host-path-list",
"list",
Expand All @@ -21,6 +25,10 @@
"fixup-pkgconfig": {
"description": "Test the vcpkg_fixup_pkgconfig function"
},
"fixup-rpath": {
"description": "Test the rpath fixup function",
"supports": "!windows"
},
"function-arguments": {
"description": "Test the z_vcpkg_function_arguments function"
},
Expand Down