[CI] Stop vendoring libomp.dylib in MacOS Python wheels (#10440)
This commit is contained in:
committed by
GitHub
parent
b9e5229ff2
commit
8689f0b562
124
cmake/FindOpenMPMacOS.cmake
Normal file
124
cmake/FindOpenMPMacOS.cmake
Normal file
@@ -0,0 +1,124 @@
|
||||
# Find OpenMP library on MacOS
|
||||
# Automatically handle locating libomp from the Homebrew package manager
|
||||
|
||||
# lint_cmake: -package/consistency
|
||||
|
||||
macro(find_openmp_macos)
|
||||
if(NOT APPLE)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() must only be used on MacOS")
|
||||
endif()
|
||||
find_package(OpenMP)
|
||||
if(NOT OpenMP_FOUND)
|
||||
# Try again with extra path info. This step is required for libomp 15+ from Homebrew,
|
||||
# as libomp 15.0+ from brew is keg-only
|
||||
# See https://github.com/Homebrew/homebrew-core/issues/112107#issuecomment-1278042927.
|
||||
execute_process(COMMAND brew --prefix libomp
|
||||
OUTPUT_VARIABLE HOMEBREW_LIBOMP_PREFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(OpenMP_C_FLAGS
|
||||
"-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PREFIX}/include")
|
||||
set(OpenMP_CXX_FLAGS
|
||||
"-Xpreprocessor -fopenmp -I${HOMEBREW_LIBOMP_PREFIX}/include")
|
||||
set(OpenMP_C_LIB_NAMES omp)
|
||||
set(OpenMP_CXX_LIB_NAMES omp)
|
||||
set(OpenMP_omp_LIBRARY ${HOMEBREW_LIBOMP_PREFIX}/lib/libomp.dylib)
|
||||
find_package(OpenMP REQUIRED)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Patch libxgboost.dylib so that it depends on @rpath/libomp.dylib instead of
|
||||
# /opt/homebrew/opt/libomp/lib/libomp.dylib or other hard-coded paths.
|
||||
# Doing so enables XGBoost to interoperate with multiple kinds of OpenMP
|
||||
# libraries. See https://github.com/microsoft/LightGBM/pull/6391 for detailed
|
||||
# explanation. Adapted from https://github.com/microsoft/LightGBM/pull/6391
|
||||
# by James Lamb.
|
||||
# MacOS only.
|
||||
function(patch_openmp_path_macos target target_default_output_name)
|
||||
if(NOT APPLE)
|
||||
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() must only be used on MacOS")
|
||||
endif()
|
||||
# Get path to libomp found at build time
|
||||
get_target_property(
|
||||
__OpenMP_LIBRARY_LOCATION
|
||||
OpenMP::OpenMP_CXX
|
||||
INTERFACE_LINK_LIBRARIES
|
||||
)
|
||||
# Get the base name of the OpenMP lib
|
||||
# Usually: libomp.dylib, libgomp.dylib, or libiomp.dylib
|
||||
get_filename_component(
|
||||
__OpenMP_LIBRARY_NAME
|
||||
${__OpenMP_LIBRARY_LOCATION}
|
||||
NAME
|
||||
)
|
||||
# Get the directory containing the OpenMP lib
|
||||
get_filename_component(
|
||||
__OpenMP_LIBRARY_DIR
|
||||
${__OpenMP_LIBRARY_LOCATION}
|
||||
DIRECTORY
|
||||
)
|
||||
# Get the name of the XGBoost lib, e.g. libxgboost
|
||||
get_target_property(
|
||||
__LIBXGBOOST_OUTPUT_NAME
|
||||
${target}
|
||||
OUTPUT_NAME
|
||||
)
|
||||
if(NOT __LIBXGBOOST_OUTPUT_NAME)
|
||||
set(__LIBXGBOOST_OUTPUT_NAME "${target_default_output_name}")
|
||||
endif()
|
||||
|
||||
# Get the file name of the XGBoost lib, e.g. libxgboost.dylib
|
||||
if(CMAKE_SHARED_LIBRARY_SUFFIX_CXX)
|
||||
set(
|
||||
__LIBXGBOOST_FILENAME_${target} "${__LIBXGBOOST_OUTPUT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX_CXX}"
|
||||
CACHE INTERNAL "Shared library filename ${target}"
|
||||
)
|
||||
else()
|
||||
set(
|
||||
__LIBXGBOOST_FILENAME_${target} "${__LIBXGBOOST_OUTPUT_NAME}.dylib"
|
||||
CACHE INTERNAL "Shared library filename ${target}"
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "Creating shared lib for target ${target}: ${__LIBXGBOOST_FILENAME_${target}}")
|
||||
|
||||
# Override the absolute path to OpenMP with a relative one using @rpath.
|
||||
#
|
||||
# This also ensures that if a libomp.dylib has already been loaded, it'll just use that.
|
||||
if(KEEP_BUILD_ARTIFACTS_IN_BINARY_DIR)
|
||||
set(__LIB_DIR ${xgboost_BINARY_DIR}/lib)
|
||||
else()
|
||||
set(__LIB_DIR ${xgboost_SOURCE_DIR}/lib)
|
||||
endif()
|
||||
add_custom_command(
|
||||
TARGET ${target}
|
||||
POST_BUILD
|
||||
COMMAND
|
||||
install_name_tool
|
||||
-change
|
||||
${__OpenMP_LIBRARY_LOCATION}
|
||||
"@rpath/${__OpenMP_LIBRARY_NAME}"
|
||||
"${__LIBXGBOOST_FILENAME_${target}}"
|
||||
WORKING_DIRECTORY ${__LIB_DIR}
|
||||
)
|
||||
message(STATUS
|
||||
"${__LIBXGBOOST_FILENAME_${target}}: "
|
||||
"Replacing hard-coded OpenMP install_name with '@rpath/${__OpenMP_LIBRARY_NAME}'..."
|
||||
)
|
||||
# Add RPATH entries to ensure the loader looks in the following, in the following order:
|
||||
#
|
||||
# - /opt/homebrew/opt/libomp/lib (where 'brew install' / 'brew link' puts libomp.dylib)
|
||||
# - ${__OpenMP_LIBRARY_DIR} (wherever find_package(OpenMP) found OpenMP at build time)
|
||||
#
|
||||
# Note: This list will only be used if libomp.dylib isn't already loaded into memory.
|
||||
# So Conda users will likely use ${CONDA_PREFIX}/libomp.dylib
|
||||
execute_process(COMMAND brew --prefix libomp
|
||||
OUTPUT_VARIABLE HOMEBREW_LIBOMP_PREFIX
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set_target_properties(
|
||||
${target}
|
||||
PROPERTIES
|
||||
BUILD_WITH_INSTALL_RPATH TRUE
|
||||
INSTALL_RPATH "${HOMEBREW_LIBOMP_PREFIX}/lib;${__OpenMP_LIBRARY_DIR}"
|
||||
INSTALL_RPATH_USE_LINK_PATH FALSE
|
||||
)
|
||||
endfunction()
|
||||
Reference in New Issue
Block a user