-
-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Expand file tree
/
Copy pathFindOpenMPMacOS.cmake
More file actions
144 lines (136 loc) · 5.22 KB
/
FindOpenMPMacOS.cmake
File metadata and controls
144 lines (136 loc) · 5.22 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# Find OpenMP library on MacOS
# Prefer libomp from the active Conda environment and fall back to Homebrew.
# lint_cmake: -package/consistency
macro(find_openmp_macos)
if(NOT APPLE)
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() must only be used on MacOS")
endif()
if(DEFINED ENV{CONDA_PREFIX} AND EXISTS "$ENV{CONDA_PREFIX}/lib/libomp.dylib")
set(CONDA_LIBOMP_PREFIX "$ENV{CONDA_PREFIX}")
set(OpenMP_C_FLAGS
"-Xpreprocessor -fopenmp -I${CONDA_LIBOMP_PREFIX}/include")
set(OpenMP_CXX_FLAGS
"-Xpreprocessor -fopenmp -I${CONDA_LIBOMP_PREFIX}/include")
set(OpenMP_C_LIB_NAMES omp)
set(OpenMP_CXX_LIB_NAMES omp)
set(OpenMP_omp_LIBRARY ${CONDA_LIBOMP_PREFIX}/lib/libomp.dylib)
find_package(OpenMP)
endif()
if(NOT OpenMP_FOUND)
find_package(OpenMP)
endif()
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/lightgbm-org/LightGBM/pull/6391 for detailed
# explanation. Adapted from https://github.com/lightgbm-org/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:
#
# - $CONDA_PREFIX/lib (when building inside a Conda environment)
# - /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(__OPENMP_RPATHS "${HOMEBREW_LIBOMP_PREFIX}/lib;${__OpenMP_LIBRARY_DIR}")
if(DEFINED ENV{CONDA_PREFIX} AND EXISTS "$ENV{CONDA_PREFIX}/lib/libomp.dylib")
set(__OPENMP_RPATHS "$ENV{CONDA_PREFIX}/lib;${__OPENMP_RPATHS}")
endif()
set_target_properties(
${target}
PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "${__OPENMP_RPATHS}"
INSTALL_RPATH_USE_LINK_PATH FALSE
)
endfunction()