-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
/
Copy pathFindOpenMPMacOS.cmake
124 lines (118 loc) · 4.43 KB
/
FindOpenMPMacOS.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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()