Skip to content

Commit

Permalink
Patch libxgboost.dylib to use @rpath/libomp.dylib
Browse files Browse the repository at this point in the history
  • Loading branch information
hcho3 committed Jun 18, 2024
1 parent ebfbdc4 commit 67a08d3
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,13 @@ if(JVM_BINDINGS)
xgboost_target_defs(xgboost4j)
endif()

if(USE_OPENMP AND APPLE)
patch_openmp_path_macos(xgboost libxgboost)
if(JVM_BINDINGS)
patch_openmp_path_macos(xgboost4j libxgboost4j)
endif()
endif()

if(KEEP_BUILD_ARTIFACTS_IN_BINARY_DIR)
set_output_directory(xgboost ${xgboost_BINARY_DIR}/lib)
else()
Expand Down
90 changes: 90 additions & 0 deletions cmake/FindOpenMPMacOS.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Find OpenMP library on MacOS
# Automatically handle locating libomp from the Homebrew package manager
function(find_openmp_macos)
if(NOT APPLE)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() must only be used on MacOS")
Expand All @@ -20,3 +22,91 @@ function(find_openmp_macos)
find_package(OpenMP REQUIRED)
endif()
endfunction()

# 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 ${__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.
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
install_name_tool
-change
${__OpenMP_LIBRARY_LOCATION}
"@rpath/${__OpenMP_LIBRARY_NAME}"
"${__LIBXGBOOST_FILENAME_${target}}"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT
"${__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
set_target_properties(
${target}
PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "/opt/homebrew/opt/libomp/lib;${__OpenMP_LIBRARY_DIR}"
INSTALL_RPATH_USE_LINK_PATH FALSE
)
endfunction()

0 comments on commit 67a08d3

Please sign in to comment.