-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Fix osx-dynamic install names for updated dependent shared library ids #39889
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
Changes from all commits
bfeaae4
5cfdd84
99ccc90
f9dfb06
95ed519
2bbba3b
2f70113
f41bc39
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 |
|---|---|---|
|
|
@@ -30,6 +30,15 @@ function(z_vcpkg_calculate_corrected_macho_rpath) | |
| set("${arg_OUT_NEW_RPATH_VAR}" "${new_rpath}" PARENT_SCOPE) | ||
| endfunction() | ||
|
|
||
| function(z_vcpkg_regex_escape) | ||
| cmake_parse_arguments(PARSE_ARGV 0 "arg" | ||
| "" | ||
| "STRING;OUT_REGEX_ESCAPED_STRING_VAR" | ||
| "") | ||
| string(REGEX REPLACE "([][+.*()^])" "\\\\\\1" regex_escaped "${arg_STRING}") | ||
| set("${arg_OUT_REGEX_ESCAPED_STRING_VAR}" "${regex_escaped}" PARENT_SCOPE) | ||
| endfunction() | ||
|
|
||
| function(z_vcpkg_fixup_macho_rpath_in_dir) | ||
| # We need to iterate through everything because we | ||
| # can't predict where a Mach-O file will be located | ||
|
|
@@ -95,6 +104,8 @@ function(z_vcpkg_fixup_macho_rpath_in_dir) | |
| continue() | ||
| endif() | ||
|
|
||
| list(APPEND macho_executables_and_shared_libs "${macho_file}") | ||
|
|
||
| get_filename_component(macho_file_dir "${macho_file}" DIRECTORY) | ||
| get_filename_component(macho_file_name "${macho_file}" NAME) | ||
|
|
||
|
|
@@ -106,15 +117,40 @@ function(z_vcpkg_fixup_macho_rpath_in_dir) | |
| if("${file_type}" STREQUAL "shared") | ||
| # Set the install name for shared libraries | ||
| execute_process( | ||
| COMMAND "${install_name_tool_cmd}" -id "@rpath/${macho_file_name}" "${macho_file}" | ||
| COMMAND "${otool_cmd}" -D "${macho_file}" | ||
| OUTPUT_VARIABLE get_id_ov | ||
| RESULT_VARIABLE get_id_rv | ||
| ) | ||
| if(NOT get_id_rv EQUAL 0) | ||
| message(FATAL_ERROR "Could not obtain install name id from '${macho_file}'") | ||
| endif() | ||
| set(macho_new_id "@rpath/${macho_file_name}") | ||
| message(STATUS "Setting install name id of '${macho_file}' to '@rpath/${macho_file_name}'") | ||
| execute_process( | ||
| COMMAND "${install_name_tool_cmd}" -id "${macho_new_id}" "${macho_file}" | ||
| OUTPUT_QUIET | ||
| ERROR_VARIABLE set_id_error | ||
| RESULT_VARIABLE set_id_exit_code | ||
| ) | ||
| message(STATUS "Set install name id of '${macho_file}' to '@rpath/${macho_file_name}'") | ||
| if(NOT "${set_id_error}" STREQUAL "") | ||
| if(NOT "${set_id_error}" STREQUAL "" AND NOT set_id_exit_code EQUAL 0) | ||
| message(WARNING "Couldn't adjust install name of '${macho_file}': ${set_id_error}") | ||
| continue() | ||
| endif() | ||
|
|
||
| # otool -D <macho_file> typically returns lines like: | ||
|
|
||
| # <macho_file>: | ||
| # <id> | ||
|
|
||
| # But also with ARM64 binaries, it can return: | ||
| # <macho_file> (architecture arm64): | ||
| # <id> | ||
|
|
||
| # Either way we need to remove the first line and trim the trailing newline char. | ||
| string(REGEX REPLACE "[^\n]+:\n" "" get_id_ov "${get_id_ov}") | ||
| string(REGEX REPLACE "\n.*" "" get_id_ov "${get_id_ov}") | ||
| list(APPEND adjusted_shared_lib_old_ids "${get_id_ov}") | ||
| list(APPEND adjusted_shared_lib_new_ids "${macho_new_id}") | ||
| endif() | ||
|
|
||
| # List all existing rpaths | ||
|
|
@@ -151,14 +187,57 @@ function(z_vcpkg_fixup_macho_rpath_in_dir) | |
| COMMAND "${install_name_tool_cmd}" ${rpath_args} "${macho_file}" | ||
| OUTPUT_QUIET | ||
| ERROR_VARIABLE set_rpath_error | ||
| RESULT_VARIABLE set_rpath_exit_code | ||
| ) | ||
|
|
||
| if(NOT "${set_rpath_error}" STREQUAL "") | ||
| if(NOT "${set_rpath_error}" STREQUAL "" AND NOT set_rpath_exit_code EQUAL 0) | ||
| message(WARNING "Couldn't adjust RPATH of '${macho_file}': ${set_rpath_error}") | ||
| continue() | ||
| endif() | ||
|
|
||
| message(STATUS "Adjusted RPATH of '${macho_file}' to '${new_rpath}'") | ||
| endforeach() | ||
| endforeach() | ||
|
|
||
| # Check for dependent libraries in executables and shared libraries that | ||
| # need adjusting after id change | ||
| list(LENGTH adjusted_shared_lib_old_ids last_adjusted_index) | ||
| if(NOT last_adjusted_index EQUAL 0) | ||
| math(EXPR last_adjusted_index "${last_adjusted_index} - 1") | ||
| foreach(macho_file IN LISTS macho_executables_and_shared_libs) | ||
| execute_process( | ||
| COMMAND "${otool_cmd}" -L "${macho_file}" | ||
| OUTPUT_VARIABLE get_deps_ov | ||
| RESULT_VARIABLE get_deps_rv | ||
| ) | ||
| if(NOT get_deps_rv EQUAL 0) | ||
| message(FATAL_ERROR "Could not obtain dependencies list from '${macho_file}'") | ||
| endif() | ||
| # change adjusted_shared_lib_old_ids[i] -> adjusted_shared_lib_new_ids[i] | ||
| foreach(i RANGE ${last_adjusted_index}) | ||
dcyruschow-cat marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| list(GET adjusted_shared_lib_old_ids ${i} adjusted_old_id) | ||
BillyONeal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| z_vcpkg_regex_escape( | ||
| STRING "${adjusted_old_id}" | ||
| OUT_REGEX_ESCAPED_STRING_VAR regex | ||
| ) | ||
| if(NOT get_deps_ov MATCHES "[ \t]${regex} ") | ||
| continue() | ||
| endif() | ||
| list(GET adjusted_shared_lib_new_ids ${i} adjusted_new_id) | ||
|
|
||
| # Replace the old id with the new id | ||
| execute_process( | ||
| COMMAND "${install_name_tool_cmd}" -change "${adjusted_old_id}" "${adjusted_new_id}" "${macho_file}" | ||
| OUTPUT_QUIET | ||
| ERROR_VARIABLE change_id_error | ||
|
Member
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. Check exit code? (Or COMMAND_ERROR_IS_FATAL ?)
Contributor
Author
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. Sorry I'm new to using
Member
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. To be honest I haven't used I don't know what My comment is more like 'some of these commands' exit code is being checked and some of them aren't being checked, it seems like they should all be checked unless there is a specific reason not to'
Contributor
Author
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. applied |
||
| RESULT_VARIABLE change_id_exit_code | ||
| ) | ||
| if(NOT "${change_id_error}" STREQUAL "" AND NOT change_id_exit_code EQUAL 0) | ||
| message(WARNING "Couldn't adjust dependent shared library install name in '${macho_file}': ${change_id_error}") | ||
| continue() | ||
| endif() | ||
| message(STATUS "Adjusted dependent shared library install name in '${macho_file}' (From '${adjusted_old_id}' -> To '${adjusted_new_id}')") | ||
| endforeach() | ||
| endforeach() | ||
| endif() | ||
| endfunction() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| set(VCPKG_POLICY_EMPTY_INCLUDE_FOLDER enabled) | ||
| vcpkg_check_linkage(ONLY_DYNAMIC_LIBRARY) | ||
|
|
||
| vcpkg_cmake_configure( | ||
| SOURCE_PATH "${CURRENT_PORT_DIR}/project" | ||
| OPTIONS_RELEASE | ||
| -DTEST_STRING=release | ||
| OPTIONS_DEBUG | ||
| -DTEST_STRING=debug | ||
| ) | ||
| vcpkg_cmake_install() | ||
|
|
||
| function(make_rpath_absolute lib_dir) | ||
| string(REPLACE "/" "_" logname "make_rpath_absolute-${lib_dir}") | ||
| vcpkg_execute_required_process( | ||
| COMMAND "install_name_tool" -id ${CURRENT_INSTALLED_DIR}/${lib_dir}/librpath-macho-backend-lib++.dylib ${CURRENT_PACKAGES_DIR}/${lib_dir}/librpath-macho-backend-lib++.dylib | ||
| WORKING_DIRECTORY "${CURRENT_PACKAGES_DIR}" | ||
| LOGNAME "${logname}-id" | ||
| ) | ||
|
|
||
| vcpkg_execute_required_process( | ||
| COMMAND "install_name_tool" -change @rpath/librpath-macho-backend-lib++.dylib ${CURRENT_INSTALLED_DIR}/${lib_dir}/librpath-macho-backend-lib++.dylib ${CURRENT_PACKAGES_DIR}/${lib_dir}/librpath-macho-test-lib.dylib | ||
| WORKING_DIRECTORY "${CURRENT_PACKAGES_DIR}" | ||
| LOGNAME "${logname}-change" | ||
| ) | ||
| endfunction() | ||
|
|
||
| if(NOT VCPKG_BUILD_TYPE) | ||
| vcpkg_copy_tools(TOOL_NAMES rpath-macho-test-tool | ||
| SEARCH_DIR "${CURRENT_PACKAGES_DIR}/debug/bin" | ||
| DESTINATION "${CURRENT_PACKAGES_DIR}/debug/tools/${PORT}" | ||
| ) | ||
| vcpkg_copy_tools(TOOL_NAMES rpath-macho-test-tool | ||
| SEARCH_DIR "${CURRENT_PACKAGES_DIR}/debug/bin" | ||
| DESTINATION "${CURRENT_PACKAGES_DIR}/manual-tools/${PORT}/debug" | ||
| ) | ||
| vcpkg_copy_tools(TOOL_NAMES rpath-macho-test-tool | ||
| SEARCH_DIR "${CURRENT_PACKAGES_DIR}/debug/bin" | ||
| DESTINATION "${CURRENT_PACKAGES_DIR}/tools/${PORT}/debug" | ||
| ) | ||
| make_rpath_absolute("debug/lib") | ||
| endif() | ||
| make_rpath_absolute("lib") | ||
| vcpkg_copy_tools(TOOL_NAMES rpath-macho-test-tool DESTINATION "${CURRENT_PACKAGES_DIR}/manual-tools/${PORT}") | ||
| vcpkg_copy_tools(TOOL_NAMES rpath-macho-test-tool AUTO_CLEAN) | ||
| file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/copyright" "This test port is part of vcpkg.") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| cmake_minimum_required(VERSION 3.7) | ||
| project(rpath-macho-test CXX) | ||
|
|
||
| set(TEST_STRING "" CACHE STRING "") | ||
|
|
||
| set(CMAKE_SKIP_INSTALL_RPATH TRUE) | ||
|
|
||
| add_library(rpath-macho-backend-lib++ transitive.cpp) | ||
| target_compile_definitions(rpath-macho-backend-lib++ PRIVATE "TEST_STRING=\"${TEST_STRING}\"") | ||
|
|
||
| add_library(rpath-macho-test-lib lib.cpp) | ||
| target_link_libraries(rpath-macho-test-lib PRIVATE rpath-macho-backend-lib++) | ||
|
|
||
| add_executable(rpath-macho-test-tool main.cpp) | ||
| target_link_libraries(rpath-macho-test-tool PRIVATE rpath-macho-test-lib) | ||
|
|
||
| install(TARGETS rpath-macho-backend-lib++ rpath-macho-test-lib rpath-macho-test-tool) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| extern const char* getTestStringBackend(); | ||
|
|
||
| const char* getTestString() | ||
| { | ||
| return getTestStringBackend(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #include <stdio.h> | ||
|
|
||
| extern const char* getTestString(); | ||
|
|
||
| int main() | ||
| { | ||
| puts(getTestString()); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| const char* getTestStringBackend() | ||
| { | ||
| return TEST_STRING; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "name": "rpath-macho-test-binaries", | ||
| "version-string": "ci", | ||
| "description": "Provides installed binaries for rpath macho fixup test", | ||
| "supports": "native & osx", | ||
| "dependencies": [ | ||
| { | ||
| "name": "vcpkg-cmake", | ||
| "host": true | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| set(VCPKG_POLICY_EMPTY_PACKAGE enabled) | ||
|
|
||
| foreach(dir IN ITEMS tools/rpath-macho-test-binaries manual-tools/rpath-macho-test-binaries) | ||
| string(REPLACE "/" "_" logname "execute-rel-${dir}") | ||
| vcpkg_execute_required_process( | ||
| COMMAND "${CURRENT_INSTALLED_DIR}/${dir}/rpath-macho-test-tool" | ||
| WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" | ||
| OUTPUT_VARIABLE output | ||
| OUTPUT_STRIP_TRAILING_WHITESPACE | ||
| LOGNAME "${logname}" | ||
| ) | ||
| if(NOT output STREQUAL "release") | ||
| message(SEND_ERROR "${dir}: $Actual: '${output}', expected: 'release'") | ||
| endif() | ||
| endforeach() | ||
|
|
||
| if(NOT VCPKG_BUILD_TYPE) | ||
| foreach(dir IN ITEMS tools/rpath-macho-test-binaries/debug manual-tools/rpath-macho-test-binaries/debug debug/tools/rpath-macho-test-binaries) | ||
| string(REPLACE "/" "_" logname "execute-dbg-${dir}") | ||
| vcpkg_execute_required_process( | ||
| COMMAND "${CURRENT_INSTALLED_DIR}/${dir}/rpath-macho-test-tool" | ||
| WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" | ||
| OUTPUT_VARIABLE output | ||
| OUTPUT_STRIP_TRAILING_WHITESPACE | ||
| LOGNAME "${logname}" | ||
| ) | ||
| if(NOT output STREQUAL "debug") | ||
| message(SEND_ERROR "${dir}: Actual: '${output}', expected: 'debug'") | ||
| endif() | ||
| endforeach() | ||
| endif() | ||
|
|
||
| function(check_proper_rpath macho_lib) | ||
| vcpkg_execute_required_process( | ||
| COMMAND "otool" "-L" "${macho_lib}" | ||
| WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" | ||
| OUTPUT_VARIABLE output | ||
| OUTPUT_STRIP_TRAILING_WHITESPACE | ||
| LOGNAME "${logname}" | ||
| ) | ||
|
|
||
| set(found_rpath_backend_lib OFF) | ||
|
|
||
| string(REPLACE "\n" ";" output_lines "${output}") | ||
| # Ignore first line, it contains the path to the lib which we are checking | ||
| list(REMOVE_AT output_lines 0) | ||
| foreach(line IN LISTS output_lines) | ||
| if("${line}" MATCHES "\\s+/.*librpath-macho-backend-lib\\+\\+\\.dylib") | ||
| message(SEND_ERROR "${line} contains an absolute path") | ||
| endif() | ||
| if("${line}" MATCHES "@rpath/librpath-macho-backend-lib\\+\\+.dylib") | ||
| set(found_rpath_backend_lib ON) | ||
| endif() | ||
| endforeach() | ||
|
|
||
| if(NOT found_rpath_backend_lib) | ||
| message(SEND_ERROR "@rpath/librpath-macho-backend-lib++.dylib not found in ${output}") | ||
| endif() | ||
| endfunction() | ||
|
|
||
| check_proper_rpath("${CURRENT_INSTALLED_DIR}/lib/librpath-macho-test-lib.dylib") | ||
| check_proper_rpath("${CURRENT_INSTALLED_DIR}/debug/lib/librpath-macho-test-lib.dylib") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "name": "rpath-macho-test", | ||
| "version-string": "ci", | ||
| "description": "Test rpath macho fixup", | ||
| "dependencies": [ | ||
| "rpath-macho-test-binaries" | ||
| ] | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.