1 # See for https://openmp.llvm.org/SupportAndFAQ.html for instructions on how
2 # to build offload with CMake.
4 cmake_minimum_required(VERSION 3.20.0)
5 set(LLVM_SUBPROJECT_TITLE "liboffload")
7 if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
8 set(OPENMP_STANDALONE_BUILD TRUE)
9 project(offload C CXX ASM)
11 set(OPENMP_STANDALONE_BUILD FALSE)
14 # Check that the library can actually be built.
15 if(APPLE OR WIN32 OR WASM)
16 message(WARNING "libomptarget cannot be built on Windows and MacOS X!")
18 elseif(NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
19 message(WARNING "Host compiler must support C++17 to build libomptarget!")
21 elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
22 message(WARNING "libomptarget on 32-bit systems is not supported!")
26 if(OPENMP_STANDALONE_BUILD)
27 set(OFFLOAD_LIBDIR_SUFFIX "" CACHE STRING
28 "Suffix of lib installation directory, e.g. 64 => lib64")
29 set(OFFLOAD_INSTALL_LIBDIR "lib${OFFLOAD_LIBDIR_SUFFIX}" CACHE STRING
30 "Path where built offload libraries should be installed.")
32 # When building in tree we install the runtime according to the LLVM settings.
33 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
34 set(OFFLOAD_INSTALL_LIBDIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING
35 "Path where built offload libraries should be installed.")
37 set(OFFLOAD_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}" CACHE STRING
38 "Path where built offload libraries should be installed.")
42 set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
44 # Add path for custom modules
45 list(INSERT CMAKE_MODULE_PATH 0
46 "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
47 "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
48 "${LLVM_COMMON_CMAKE_UTILS}/Modules"
51 if (OPENMP_STANDALONE_BUILD)
52 # CMAKE_BUILD_TYPE was not set, default to Release.
53 if (NOT CMAKE_BUILD_TYPE)
54 set(CMAKE_BUILD_TYPE Release)
57 # Group common settings.
58 set(OPENMP_ENABLE_WERROR FALSE CACHE BOOL
59 "Enable -Werror flags to turn warnings into errors for supporting compilers.")
60 set(OPENMP_LIBDIR_SUFFIX "" CACHE STRING
61 "Suffix of lib installation directory, e.g. 64 => lib64")
62 # Do not use OPENMP_LIBDIR_SUFFIX directly, use OPENMP_INSTALL_LIBDIR.
63 set(OPENMP_INSTALL_LIBDIR "lib${OPENMP_LIBDIR_SUFFIX}")
65 # Group test settings.
66 set(OPENMP_TEST_C_COMPILER ${CMAKE_C_COMPILER} CACHE STRING
67 "C compiler to use for testing OpenMP runtime libraries.")
68 set(OPENMP_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE STRING
69 "C++ compiler to use for testing OpenMP runtime libraries.")
70 set(OPENMP_TEST_Fortran_COMPILER ${CMAKE_Fortran_COMPILER} CACHE STRING
71 "FORTRAN compiler to use for testing OpenMP runtime libraries.")
72 set(OPENMP_LLVM_TOOLS_DIR "" CACHE PATH "Path to LLVM tools for testing.")
74 set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")
75 set(CMAKE_CXX_STANDARD_REQUIRED NO)
76 set(CMAKE_CXX_EXTENSIONS NO)
78 set(OPENMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR})
79 # If building in tree, we honor the same install suffix LLVM uses.
80 set(OPENMP_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}")
83 set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
84 set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++)
86 set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe)
87 set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++.exe)
92 set(OPENMP_TEST_Fortran_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang)
94 set(OPENMP_TEST_Fortran_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang.exe)
97 # Set fortran test compiler if flang is found
98 if (EXISTS "${OPENMP_TEST_Fortran_COMPILER}")
99 message("Using local flang build at ${OPENMP_TEST_Fortran_COMPILER}")
101 unset(OPENMP_TEST_Fortran_COMPILER)
104 # If not standalone, set CMAKE_CXX_STANDARD but don't set the global cache value,
105 # only set it locally for OpenMP.
106 set(CMAKE_CXX_STANDARD 17)
107 set(CMAKE_CXX_STANDARD_REQUIRED NO)
108 set(CMAKE_CXX_EXTENSIONS NO)
111 # Set the path of all resulting libraries to a unified location so that it can
112 # be used for testing.
113 set(LIBOMPTARGET_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
114 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBOMPTARGET_LIBRARY_DIR})
115 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBOMPTARGET_LIBRARY_DIR})
116 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBOMPTARGET_LIBRARY_DIR})
118 if(NOT LLVM_LIBRARY_OUTPUT_INTDIR)
119 set(LIBOMPTARGET_INTDIR ${LIBOMPTARGET_LIBRARY_DIR})
121 set(LIBOMPTARGET_INTDIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
124 # Get dependencies for the different components of the project.
125 include(LibomptargetGetDependencies)
127 # Set up testing infrastructure.
128 include(OpenMPTesting)
130 check_cxx_compiler_flag(-Werror=global-constructors OFFLOAD_HAVE_WERROR_CTOR)
132 # LLVM source tree is required at build time for libomptarget
133 if (NOT LIBOMPTARGET_LLVM_INCLUDE_DIRS)
134 message(FATAL_ERROR "Missing definition for LIBOMPTARGET_LLVM_INCLUDE_DIRS")
137 if(DEFINED LIBOMPTARGET_BUILD_CUDA_PLUGIN OR
138 DEFINED LIBOMPTARGET_BUILD_AMDGPU_PLUGIN)
139 message(WARNING "Option removed, use 'LIBOMPTARGET_PLUGINS_TO_BUILD' instead")
142 set(LIBOMPTARGET_ALL_PLUGIN_TARGETS amdgpu cuda host)
143 set(LIBOMPTARGET_PLUGINS_TO_BUILD "all" CACHE STRING
144 "Semicolon-separated list of plugins to use: cuda, amdgpu, host or \"all\".")
146 if(LIBOMPTARGET_PLUGINS_TO_BUILD STREQUAL "all")
147 set(LIBOMPTARGET_PLUGINS_TO_BUILD ${LIBOMPTARGET_ALL_PLUGIN_TARGETS})
150 if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux" AND
151 "host" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
152 message(STATUS "Not building host plugin: only Linux systems are supported")
153 list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "host")
155 if(NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$"
156 AND CMAKE_SYSTEM_NAME MATCHES "Linux"))
157 if("amdgpu" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
158 message(STATUS "Not building AMDGPU plugin: only support AMDGPU in "
159 "Linux x86_64, ppc64le, or aarch64 hosts")
160 list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "amdgpu")
162 if("cuda" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
163 message(STATUS "Not building CUDA plugin: only support CUDA in "
164 "Linux x86_64, ppc64le, or aarch64 hosts")
165 list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "cuda")
168 message(STATUS "Building the offload library with support for "
169 "the \"${LIBOMPTARGET_PLUGINS_TO_BUILD}\" plugins")
171 set(LIBOMPTARGET_DLOPEN_PLUGINS "${LIBOMPTARGET_PLUGINS_TO_BUILD}" CACHE STRING
172 "Semicolon-separated list of plugins to use 'dlopen' for runtime linking")
174 set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS "")
175 foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD)
176 set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS
177 "${LIBOMPTARGET_ENUM_PLUGIN_TARGETS}PLUGIN_TARGET(${plugin})\n")
179 string(STRIP ${LIBOMPTARGET_ENUM_PLUGIN_TARGETS} LIBOMPTARGET_ENUM_PLUGIN_TARGETS)
181 ${CMAKE_CURRENT_SOURCE_DIR}/include/Shared/Targets.def.in
182 ${CMAKE_CURRENT_BINARY_DIR}/include/Shared/Targets.def
185 include_directories(${LIBOMPTARGET_LLVM_INCLUDE_DIRS})
187 # This is a list of all the targets that are supported/tested right now.
188 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} aarch64-unknown-linux-gnu")
189 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} aarch64-unknown-linux-gnu-LTO")
190 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} amdgcn-amd-amdhsa")
191 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64le-ibm-linux-gnu")
192 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64le-ibm-linux-gnu-LTO")
193 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64-ibm-linux-gnu")
194 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64-ibm-linux-gnu-LTO")
195 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} x86_64-unknown-linux-gnu")
196 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} x86_64-unknown-linux-gnu-LTO")
197 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda")
198 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda-LTO")
199 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda-JIT-LTO")
200 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} s390x-ibm-linux-gnu")
201 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} s390x-ibm-linux-gnu-LTO")
202 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} riscv64-unknown-linux-gnu")
203 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} riscv64-unknown-linux-gnu-LTO")
205 # Once the plugins for the different targets are validated, they will be added to
206 # the list of supported targets in the current system.
207 set (LIBOMPTARGET_SYSTEM_TARGETS "")
208 set (LIBOMPTARGET_TESTED_PLUGINS "")
210 # Check whether using debug mode. In debug mode, allow dumping progress
211 # messages at runtime by default. Otherwise, it can be enabled
212 # independently using the LIBOMPTARGET_ENABLE_DEBUG option.
213 string( TOLOWER "${CMAKE_BUILD_TYPE}" LIBOMPTARGET_CMAKE_BUILD_TYPE)
214 if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
215 option(LIBOMPTARGET_ENABLE_DEBUG "Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1" ON)
217 option(LIBOMPTARGET_ENABLE_DEBUG "Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1" OFF)
219 if(LIBOMPTARGET_ENABLE_DEBUG)
220 add_definitions(-DOMPTARGET_DEBUG)
223 # No exceptions and no RTTI, except if requested.
224 set(offload_compile_flags -fno-exceptions)
225 if(NOT LLVM_ENABLE_RTTI)
226 set(offload_compile_flags ${offload_compile_flags} -fno-rtti)
228 if(OFFLOAD_HAVE_WERROR_CTOR)
229 list(APPEND offload_compile_flags -Werror=global-constructors)
232 # TODO: Consider enabling LTO by default if supported.
233 # https://cmake.org/cmake/help/latest/module/CheckIPOSupported.html can be used
234 # to test for working LTO. However, before CMake 3.24 this will test the
235 # default linker and ignore options such as LLVM_ENABLE_LLD. As a result, CMake
236 # would test whether LTO works with the default linker but build with another one.
237 # In a typical scenario, libomptarget is compiled with the in-tree Clang, but
238 # linked with ld.gold, which requires the LLVMgold plugin, when it actually
239 # would work with the lld linker (or also fail because the system lld is too old
240 # to understand opaque pointers). Using gcc as the compiler would pass the test, but fail
241 # when linking with lld since does not understand gcc's LTO format.
242 set(LIBOMPTARGET_USE_LTO FALSE CACHE BOOL "Use LTO for the offload runtimes if available")
243 if (LIBOMPTARGET_USE_LTO)
244 # CMake sets CMAKE_CXX_COMPILE_OPTIONS_IPO depending on the compiler and is
245 # also what CheckIPOSupported uses to test support.
246 list(APPEND offload_compile_flags ${CMAKE_CXX_COMPILE_OPTIONS_IPO})
247 list(APPEND offload_link_flags ${CMAKE_CXX_COMPILE_OPTIONS_IPO})
250 if(OPENMP_STANDALONE_BUILD)
251 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
253 OUTPUT_STRIP_TRAILING_WHITESPACE
254 COMMAND ${CMAKE_CXX_COMPILER} --print-resource-dir
255 RESULT_VARIABLE COMMAND_RETURN_CODE
256 OUTPUT_VARIABLE COMPILER_RESOURCE_DIR
260 set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
261 set(LIBOMP_OMPT_SUPPORT FALSE)
264 LIBOMP_OMP_TOOLS_INCLUDE_DIR
268 ${COMPILER_RESOURCE_DIR}/include
269 ${CMAKE_INSTALL_PREFIX}/include
272 if(LIBOMP_OMP_TOOLS_INCLUDE_DIR)
273 set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
274 set(LIBOMP_OMPT_SUPPORT TRUE)
277 # LLVM_LIBRARY_DIRS set by find_package(LLVM) in LibomptargetGetDependencies
283 ${CMAKE_INSTALL_PREFIX}/lib
289 macro(pythonize_bool var)
297 if(OPENMP_STANDALONE_BUILD OR TARGET omp)
298 # Check LIBOMP_HAVE_VERSION_SCRIPT_FLAG
299 include(LLVMCheckCompilerLinkerFlag)
301 llvm_check_compiler_linker_flag(C "-Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/../openmp/runtime/src/exports_test_so.txt" LIBOMP_HAVE_VERSION_SCRIPT_FLAG)
305 # OMPT support for libomptarget
306 # Follow host OMPT support and check if host support has been requested.
307 # LIBOMP_HAVE_OMPT_SUPPORT indicates whether host OMPT support has been implemented.
308 # LIBOMP_OMPT_SUPPORT indicates whether host OMPT support has been requested (default is ON).
309 # LIBOMPTARGET_OMPT_SUPPORT indicates whether target OMPT support has been requested (default is ON).
310 set(OMPT_TARGET_DEFAULT FALSE)
311 if ((LIBOMP_HAVE_OMPT_SUPPORT) AND (LIBOMP_OMPT_SUPPORT) AND (NOT WIN32))
312 set (OMPT_TARGET_DEFAULT TRUE)
314 set(LIBOMPTARGET_OMPT_SUPPORT ${OMPT_TARGET_DEFAULT} CACHE BOOL "OMPT-target-support?")
315 if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT))
316 add_definitions(-DOMPT_SUPPORT=1)
317 message(STATUS "OMPT target enabled")
319 set(LIBOMPTARGET_OMPT_SUPPORT FALSE)
320 message(STATUS "OMPT target disabled")
323 pythonize_bool(LIBOMPTARGET_OMPT_SUPPORT)
325 if(${LLVM_LIBC_GPU_BUILD})
326 set(LIBOMPTARGET_HAS_LIBC TRUE)
328 set(LIBOMPTARGET_HAS_LIBC FALSE)
330 set(LIBOMPTARGET_GPU_LIBC_SUPPORT ${LIBOMPTARGET_HAS_LIBC} CACHE BOOL
331 "Libomptarget support for the GPU libc")
332 pythonize_bool(LIBOMPTARGET_GPU_LIBC_SUPPORT)
334 set(LIBOMPTARGET_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
335 set(LIBOMPTARGET_BINARY_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include)
336 message(STATUS "OpenMP tools dir in libomptarget: ${LIBOMP_OMP_TOOLS_INCLUDE_DIR}")
337 if(LIBOMP_OMP_TOOLS_INCLUDE_DIR)
338 include_directories(${LIBOMP_OMP_TOOLS_INCLUDE_DIR})
341 set(LIBOMPTARGET_LLVM_LIBRARY_DIR "${LLVM_LIBRARY_DIR}" CACHE STRING
342 "Path to folder containing llvm library libomptarget.so")
343 set(LIBOMPTARGET_LLVM_LIBRARY_INTDIR "${LIBOMPTARGET_INTDIR}" CACHE STRING
344 "Path to folder where intermediate libraries will be output")
346 # Build offloading plugins and device RTLs if they are available.
347 add_subdirectory(plugins-nextgen)
348 add_subdirectory(DeviceRTL)
349 add_subdirectory(tools)
351 # Build target agnostic offloading library.
352 add_subdirectory(src)
355 add_subdirectory(test)
357 # Add unit tests if GMock/GTest is present
358 if (EXISTS ${LLVM_THIRD_PARTY_DIR}/unittest)
359 if (NOT TARGET llvm_gtest)
360 add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest)
362 add_subdirectory(unittests)