-
Notifications
You must be signed in to change notification settings - Fork 6.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixup Macho-O rpath for osx-dynamic (#39313)
- Loading branch information
Showing
13 changed files
with
377 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
function(z_vcpkg_calculate_corrected_macho_rpath) | ||
cmake_parse_arguments(PARSE_ARGV 0 "arg" | ||
"" | ||
"MACHO_FILE_DIR;OUT_NEW_RPATH_VAR" | ||
"") | ||
|
||
if(DEFINED arg_UNPARSED_ARGUMENTS) | ||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION} was passed extra arguments: ${arg_UNPARSED_ARGUMENTS}") | ||
endif() | ||
|
||
set(current_prefix "${CURRENT_PACKAGES_DIR}") | ||
set(current_installed_prefix "${CURRENT_INSTALLED_DIR}") | ||
file(RELATIVE_PATH relative_from_packages "${CURRENT_PACKAGES_DIR}" "${arg_MACHO_FILE_DIR}") | ||
if("${relative_from_packages}/" MATCHES "^debug/" OR "${relative_from_packages}/" MATCHES "^(manual-)?tools/.*/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 "${arg_MACHO_FILE_DIR}" "${current_prefix}/lib") | ||
# remove trailing slash | ||
string(REGEX REPLACE "/+$" "" relative_to_lib "${relative_to_lib}") | ||
|
||
if(NOT relative_to_lib STREQUAL "") | ||
set(new_rpath "@loader_path/${relative_to_lib}") | ||
else() | ||
set(new_rpath "@loader_path") | ||
endif() | ||
|
||
set("${arg_OUT_NEW_RPATH_VAR}" "${new_rpath}" 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 | ||
file(GLOB root_entries LIST_DIRECTORIES TRUE "${CURRENT_PACKAGES_DIR}/*") | ||
|
||
# Skip some folders for better throughput | ||
list(APPEND folders_to_skip "include") | ||
list(JOIN folders_to_skip "|" folders_to_skip_regex) | ||
set(folders_to_skip_regex "^(${folders_to_skip_regex})$") | ||
|
||
find_program( | ||
install_name_tool_cmd | ||
NAMES install_name_tool | ||
DOC "Absolute path of install_name_tool cmd" | ||
REQUIRED | ||
) | ||
|
||
find_program( | ||
otool_cmd | ||
NAMES otool | ||
DOC "Absolute path of otool cmd" | ||
REQUIRED | ||
) | ||
|
||
find_program( | ||
file_cmd | ||
NAMES file | ||
DOC "Absolute path of file cmd" | ||
REQUIRED | ||
) | ||
|
||
foreach(folder IN LISTS root_entries) | ||
if(NOT IS_DIRECTORY "${folder}") | ||
continue() | ||
endif() | ||
|
||
get_filename_component(folder_name "${folder}" NAME) | ||
if(folder_name MATCHES "${folders_to_skip_regex}") | ||
continue() | ||
endif() | ||
|
||
file(GLOB_RECURSE macho_files LIST_DIRECTORIES FALSE "${folder}/*") | ||
list(FILTER macho_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 macho_files EXCLUDE REGEX "/(copyright|LICENSE|METADATA)$") | ||
|
||
foreach(macho_file IN LISTS macho_files) | ||
if(IS_SYMLINK "${macho_file}") | ||
continue() | ||
endif() | ||
|
||
# Determine if the file is a Mach-O executable or shared library | ||
execute_process( | ||
COMMAND "${file_cmd}" -b "${macho_file}" | ||
OUTPUT_VARIABLE file_output | ||
OUTPUT_STRIP_TRAILING_WHITESPACE | ||
) | ||
if(file_output MATCHES ".*Mach-O.*shared library.*") | ||
set(file_type "shared") | ||
elseif(file_output MATCHES ".*Mach-O.*executable.*") | ||
set(file_type "executable") | ||
else() | ||
debug_message("File `${macho_file}` reported as `${file_output}` is not a Mach-O file") | ||
continue() | ||
endif() | ||
|
||
get_filename_component(macho_file_dir "${macho_file}" DIRECTORY) | ||
get_filename_component(macho_file_name "${macho_file}" NAME) | ||
|
||
z_vcpkg_calculate_corrected_macho_rpath( | ||
MACHO_FILE_DIR "${macho_file_dir}" | ||
OUT_NEW_RPATH_VAR new_rpath | ||
) | ||
|
||
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}" | ||
OUTPUT_QUIET | ||
ERROR_VARIABLE set_id_error | ||
) | ||
message(STATUS "Set install name id of '${macho_file}' (To '@rpath/${macho_file_name}')") | ||
if(NOT "${set_id_error}" STREQUAL "") | ||
message(WARNING "Couldn't adjust install name of '${macho_file}': ${set_id_error}") | ||
continue() | ||
endif() | ||
endif() | ||
|
||
# Clear all existing rpaths | ||
execute_process( | ||
COMMAND "${otool_cmd}" -l "${macho_file}" | ||
OUTPUT_VARIABLE get_rpath_ov | ||
RESULT_VARIABLE get_rpath_rv | ||
) | ||
|
||
if(NOT get_rpath_rv EQUAL 0) | ||
message(FATAL_ERROR "Could not obtain rpath list from '${macho_file}'") | ||
endif() | ||
# Extract the LC_RPATH load commands and extract the paths | ||
string(REGEX REPLACE "[^\n]+cmd LC_RPATH\n[^\n]+\n[^\n]+path ([^\n]+) \\(offset[^\n]+\n" "rpath \\1\n" get_rpath_ov "${get_rpath_ov}") | ||
string(REGEX MATCHALL "rpath [^\n]+" get_rpath_ov "${get_rpath_ov}") | ||
string(REGEX REPLACE "rpath " "" rpath_list "${get_rpath_ov}") | ||
|
||
foreach(rpath IN LISTS rpath_list) | ||
execute_process( | ||
COMMAND "${install_name_tool_cmd}" -delete_rpath "${rpath}" "${macho_file}" | ||
OUTPUT_QUIET | ||
ERROR_VARIABLE delete_rpath_error | ||
) | ||
message(STATUS "Remove RPATH from '${macho_file}' ('${rpath}')") | ||
endforeach() | ||
|
||
# Set the new rpath | ||
execute_process( | ||
COMMAND "${install_name_tool_cmd}" -add_rpath "${new_rpath}" "${macho_file}" | ||
OUTPUT_QUIET | ||
ERROR_VARIABLE set_rpath_error | ||
) | ||
|
||
if(NOT "${set_rpath_error}" STREQUAL "") | ||
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() | ||
endfunction() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
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() | ||
if(NOT VCPKG_BUILD_TYPE) | ||
vcpkg_copy_tools(TOOL_NAMES rpath-test-tool | ||
SEARCH_DIR "${CURRENT_PACKAGES_DIR}/debug/bin" | ||
DESTINATION "${CURRENT_PACKAGES_DIR}/tools/${PORT}/debug" | ||
) | ||
endif() | ||
vcpkg_copy_tools(TOOL_NAMES rpath-test-tool AUTO_CLEAN) | ||
file(WRITE "${CURRENT_PACKAGES_DIR}/share/${PORT}/copyright" "This test port is part of vcpkg.") |
12 changes: 12 additions & 0 deletions
12
scripts/test_ports/rpath-test-binaries/project/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
cmake_minimum_required(VERSION 3.7) | ||
project(rpath-test CXX) | ||
|
||
set(TEST_STRING "" CACHE STRING "") | ||
|
||
add_library(rpath-test-lib lib.cpp) | ||
target_compile_definitions(rpath-test-lib PRIVATE "TEST_STRING=\"${TEST_STRING}\"") | ||
|
||
add_executable(rpath-test-tool main.cpp) | ||
target_link_libraries(rpath-test-tool PRIVATE rpath-test-lib) | ||
|
||
install(TARGETS rpath-test-lib rpath-test-tool) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const char* getTestString() | ||
{ | ||
return TEST_STRING; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "rpath-test-binaries", | ||
"version-string": "ci", | ||
"description": "Provides installed binaries for rpath fixup test", | ||
"supports": "native & !windows", | ||
"dependencies": [ | ||
{ | ||
"name": "vcpkg-cmake", | ||
"host": true | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
set(VCPKG_POLICY_EMPTY_PACKAGE enabled) | ||
|
||
vcpkg_execute_in_download_mode( | ||
COMMAND "${CURRENT_INSTALLED_DIR}/tools/rpath-test-binaries/rpath-test-tool" | ||
WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" | ||
OUTPUT_VARIABLE output | ||
OUTPUT_STRIP_TRAILING_WHITESPACE | ||
) | ||
if(NOT output STREQUAL "release") | ||
message(SEND_ERROR "Actual: '${output}', expected: 'release'") | ||
endif() | ||
|
||
if(NOT VCPKG_BUILD_TYPE) | ||
vcpkg_execute_in_download_mode( | ||
COMMAND "${CURRENT_INSTALLED_DIR}/tools/rpath-test-binaries/debug/rpath-test-tool" | ||
WORKING_DIRECTORY "${CURRENT_BUILDTREES_DIR}" | ||
OUTPUT_VARIABLE output | ||
OUTPUT_STRIP_TRAILING_WHITESPACE | ||
) | ||
if(NOT output STREQUAL "debug") | ||
message(SEND_ERROR "Actual: '${output}', expected: 'debug'") | ||
endif() | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "rpath-test", | ||
"version-string": "ci", | ||
"description": "Test rpath fixup", | ||
"dependencies": [ | ||
"rpath-test-binaries" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
scripts/test_ports/unit-test-cmake/test-z_vcpkg_calculate_corrected_rpath_macho.cmake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# z_vcpkg_calculate_corrected_macho_rpath_macho(...) | ||
|
||
block(SCOPE_FOR VARIABLES) | ||
|
||
set(CURRENT_PACKAGES_DIR "/P") | ||
set(CURRENT_INSTALLED_DIR "/I") | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/lib") | ||
]] out [[@loader_path]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/plugins/group") | ||
]] out [[@loader_path/../../lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/debug/lib") | ||
]] out [[@loader_path]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/debug/plugins/group") | ||
]] out [[@loader_path/../../lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/tools/port") | ||
]] out [[@loader_path/../../lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/tools/port/bin") | ||
]] out [[@loader_path/../../../lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/tools/port/debug") | ||
]] out [[@loader_path/../../../debug/lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/tools/port/debug/bin") | ||
]] out [[@loader_path/../../../../debug/lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/manual-tools/port") | ||
]] out [[@loader_path/../../lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/manual-tools/port/bin") | ||
]] out [[@loader_path/../../../lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/manual-tools/port/debug") | ||
]] out [[@loader_path/../../../debug/lib]]) | ||
|
||
unit_test_check_variable_equal([[ | ||
z_vcpkg_calculate_corrected_macho_rpath(OUT_NEW_RPATH_VAR "out" MACHO_FILE_DIR "/P/manual-tools/port/debug/bin") | ||
]] out [[@loader_path/../../../../debug/lib]]) | ||
|
||
endblock() |
Oops, something went wrong.