xref: /llvm-project/offload/CMakeLists.txt (revision bdf727065b581c45b68a81090272f497f1ce5485)
1# See for https://openmp.llvm.org/SupportAndFAQ.html for instructions on how
2# to build offload with CMake.
3
4cmake_minimum_required(VERSION 3.20.0)
5set(LLVM_SUBPROJECT_TITLE "liboffload")
6
7if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
8  set(OPENMP_STANDALONE_BUILD TRUE)
9  project(offload C CXX ASM)
10else()
11  set(OPENMP_STANDALONE_BUILD FALSE)
12endif()
13
14# Check that the library can actually be built.
15if(APPLE OR WIN32 OR WASM)
16  message(WARNING "libomptarget cannot be built on Windows and MacOS X!")
17  return()
18elseif(NOT "cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
19  message(WARNING "Host compiler must support C++17 to build libomptarget!")
20  return()
21elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
22  message(WARNING "libomptarget on 32-bit systems is not supported!")
23  return()
24endif()
25
26if(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.")
31else()
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.")
36  else()
37    set(OFFLOAD_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}" CACHE STRING
38      "Path where built offload libraries should be installed.")
39  endif()
40endif()
41
42set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
43
44# Add path for custom modules
45list(INSERT CMAKE_MODULE_PATH 0
46  "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
47  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
48  "${CMAKE_CURRENT_SOURCE_DIR}/../runtimes/cmake/Modules"
49  "${LLVM_COMMON_CMAKE_UTILS}"
50  "${LLVM_COMMON_CMAKE_UTILS}/Modules"
51  )
52
53if (OPENMP_STANDALONE_BUILD)
54  # CMAKE_BUILD_TYPE was not set, default to Release.
55  if (NOT CMAKE_BUILD_TYPE)
56    set(CMAKE_BUILD_TYPE Release)
57  endif()
58
59  # Group common settings.
60  set(OPENMP_ENABLE_WERROR FALSE CACHE BOOL
61    "Enable -Werror flags to turn warnings into errors for supporting compilers.")
62  set(OPENMP_LIBDIR_SUFFIX "" CACHE STRING
63    "Suffix of lib installation directory, e.g. 64 => lib64")
64  # Do not use OPENMP_LIBDIR_SUFFIX directly, use OPENMP_INSTALL_LIBDIR.
65  set(OPENMP_INSTALL_LIBDIR "lib${OPENMP_LIBDIR_SUFFIX}")
66
67  # Used by llvm_add_tool() and tests.
68  set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR})
69
70  # Group test settings.
71  set(OPENMP_TEST_C_COMPILER ${CMAKE_C_COMPILER} CACHE STRING
72    "C compiler to use for testing OpenMP runtime libraries.")
73  set(OPENMP_TEST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE STRING
74    "C++ compiler to use for testing OpenMP runtime libraries.")
75  set(OPENMP_TEST_Fortran_COMPILER ${CMAKE_Fortran_COMPILER} CACHE STRING
76    "FORTRAN compiler to use for testing OpenMP runtime libraries.")
77  set(OPENMP_LLVM_TOOLS_DIR "" CACHE PATH "Path to LLVM tools for testing.")
78
79  set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to")
80  set(CMAKE_CXX_STANDARD_REQUIRED NO)
81  set(CMAKE_CXX_EXTENSIONS NO)
82else()
83  set(OPENMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR})
84  # If building in tree, we honor the same install suffix LLVM uses.
85  set(OPENMP_INSTALL_LIBDIR "lib${LLVM_LIBDIR_SUFFIX}")
86
87  if (NOT MSVC)
88    set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang)
89    set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++)
90  else()
91    set(OPENMP_TEST_C_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe)
92    set(OPENMP_TEST_CXX_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++.exe)
93  endif()
94
95  # Check for flang
96  if (NOT MSVC)
97    set(OPENMP_TEST_Fortran_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang)
98  else()
99    set(OPENMP_TEST_Fortran_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/flang.exe)
100  endif()
101
102  # Set fortran test compiler if flang is found
103  if (EXISTS "${OPENMP_TEST_Fortran_COMPILER}")
104    message("Using local flang build at ${OPENMP_TEST_Fortran_COMPILER}")
105  else()
106    unset(OPENMP_TEST_Fortran_COMPILER)
107  endif()
108
109  # If not standalone, set CMAKE_CXX_STANDARD but don't set the global cache value,
110  # only set it locally for OpenMP.
111  set(CMAKE_CXX_STANDARD 17)
112  set(CMAKE_CXX_STANDARD_REQUIRED NO)
113  set(CMAKE_CXX_EXTENSIONS NO)
114endif()
115
116# Set the path of all resulting libraries to a unified location so that it can
117# be used for testing.
118set(LIBOMPTARGET_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
119set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBOMPTARGET_LIBRARY_DIR})
120set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBOMPTARGET_LIBRARY_DIR})
121set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBOMPTARGET_LIBRARY_DIR})
122
123if(NOT LLVM_LIBRARY_OUTPUT_INTDIR)
124  set(LIBOMPTARGET_INTDIR ${LIBOMPTARGET_LIBRARY_DIR})
125else()
126  set(LIBOMPTARGET_INTDIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
127endif()
128
129# Get dependencies for the different components of the project.
130include(LibomptargetGetDependencies)
131
132# Set up testing infrastructure.
133include(OpenMPTesting)
134
135include(CheckCXXCompilerFlag)
136check_cxx_compiler_flag(-Werror=global-constructors OFFLOAD_HAVE_WERROR_CTOR)
137
138# LLVM source tree is required at build time for libomptarget
139if (NOT LIBOMPTARGET_LLVM_INCLUDE_DIRS)
140  message(FATAL_ERROR "Missing definition for LIBOMPTARGET_LLVM_INCLUDE_DIRS")
141endif()
142
143if(DEFINED LIBOMPTARGET_BUILD_CUDA_PLUGIN OR
144   DEFINED LIBOMPTARGET_BUILD_AMDGPU_PLUGIN)
145  message(WARNING "Option removed, use 'LIBOMPTARGET_PLUGINS_TO_BUILD' instead")
146endif()
147
148set(LIBOMPTARGET_ALL_PLUGIN_TARGETS amdgpu cuda host)
149set(LIBOMPTARGET_PLUGINS_TO_BUILD "all" CACHE STRING
150    "Semicolon-separated list of plugins to use: cuda, amdgpu, host or \"all\".")
151
152if(LIBOMPTARGET_PLUGINS_TO_BUILD STREQUAL "all")
153  set(LIBOMPTARGET_PLUGINS_TO_BUILD ${LIBOMPTARGET_ALL_PLUGIN_TARGETS})
154endif()
155
156if(NOT CMAKE_SYSTEM_NAME MATCHES "Linux" AND
157   "host" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
158  message(STATUS "Not building host plugin: only Linux systems are supported")
159  list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "host")
160endif()
161if(NOT (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(ppc64le)|(aarch64)$"
162        AND CMAKE_SYSTEM_NAME MATCHES "Linux"))
163  if("amdgpu" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
164    message(STATUS "Not building AMDGPU plugin: only support AMDGPU in "
165                   "Linux x86_64, ppc64le, or aarch64 hosts")
166    list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "amdgpu")
167  endif()
168  if("cuda" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
169    message(STATUS "Not building CUDA plugin: only support CUDA in "
170                   "Linux x86_64, ppc64le, or aarch64 hosts")
171    list(REMOVE_ITEM LIBOMPTARGET_PLUGINS_TO_BUILD "cuda")
172  endif()
173endif()
174message(STATUS "Building the offload library with support for "
175               "the \"${LIBOMPTARGET_PLUGINS_TO_BUILD}\" plugins")
176
177set(LIBOMPTARGET_DLOPEN_PLUGINS "${LIBOMPTARGET_PLUGINS_TO_BUILD}" CACHE STRING
178    "Semicolon-separated list of plugins to use 'dlopen' for runtime linking")
179
180set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS "")
181foreach(plugin IN LISTS LIBOMPTARGET_PLUGINS_TO_BUILD)
182  set(LIBOMPTARGET_ENUM_PLUGIN_TARGETS
183      "${LIBOMPTARGET_ENUM_PLUGIN_TARGETS}PLUGIN_TARGET(${plugin})\n")
184endforeach()
185string(STRIP ${LIBOMPTARGET_ENUM_PLUGIN_TARGETS} LIBOMPTARGET_ENUM_PLUGIN_TARGETS)
186configure_file(
187  ${CMAKE_CURRENT_SOURCE_DIR}/include/Shared/Targets.def.in
188  ${CMAKE_CURRENT_BINARY_DIR}/include/Shared/Targets.def
189)
190
191include_directories(${LIBOMPTARGET_LLVM_INCLUDE_DIRS})
192
193# This is a list of all the targets that are supported/tested right now.
194set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} aarch64-unknown-linux-gnu")
195set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} aarch64-unknown-linux-gnu-LTO")
196set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} amdgcn-amd-amdhsa")
197set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64le-ibm-linux-gnu")
198set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64le-ibm-linux-gnu-LTO")
199set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64-ibm-linux-gnu")
200set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} powerpc64-ibm-linux-gnu-LTO")
201set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} x86_64-unknown-linux-gnu")
202set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} x86_64-unknown-linux-gnu-LTO")
203set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda")
204set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda-LTO")
205set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} nvptx64-nvidia-cuda-JIT-LTO")
206set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} s390x-ibm-linux-gnu")
207set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} s390x-ibm-linux-gnu-LTO")
208set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} riscv64-unknown-linux-gnu")
209set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} riscv64-unknown-linux-gnu-LTO")
210set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} loongarch64-unknown-linux-gnu")
211set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} loongarch64-unknown-linux-gnu-LTO")
212
213# Once the plugins for the different targets are validated, they will be added to
214# the list of supported targets in the current system.
215set (LIBOMPTARGET_SYSTEM_TARGETS "")
216set (LIBOMPTARGET_TESTED_PLUGINS "")
217
218# Check whether using debug mode. In debug mode, allow dumping progress
219# messages at runtime by default. Otherwise, it can be enabled
220# independently using the LIBOMPTARGET_ENABLE_DEBUG option.
221string( TOLOWER "${CMAKE_BUILD_TYPE}" LIBOMPTARGET_CMAKE_BUILD_TYPE)
222if(LIBOMPTARGET_CMAKE_BUILD_TYPE MATCHES debug)
223  option(LIBOMPTARGET_ENABLE_DEBUG "Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1" ON)
224else()
225  option(LIBOMPTARGET_ENABLE_DEBUG "Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1" OFF)
226endif()
227if(LIBOMPTARGET_ENABLE_DEBUG)
228  add_definitions(-DOMPTARGET_DEBUG)
229endif()
230
231# No exceptions and no RTTI, except if requested.
232set(offload_compile_flags -fno-exceptions)
233if(NOT LLVM_ENABLE_RTTI)
234  set(offload_compile_flags ${offload_compile_flags} -fno-rtti)
235endif()
236if(OFFLOAD_HAVE_WERROR_CTOR)
237  list(APPEND offload_compile_flags -Werror=global-constructors)
238endif()
239
240# TODO: Consider enabling LTO by default if supported.
241# https://cmake.org/cmake/help/latest/module/CheckIPOSupported.html can be used
242# to test for working LTO. However, before CMake 3.24 this will test the
243# default linker and ignore options such as LLVM_ENABLE_LLD. As a result, CMake
244# would test whether LTO works with the default linker but build with another one.
245# In a typical scenario, libomptarget is compiled with the in-tree Clang, but
246# linked with ld.gold, which requires the LLVMgold plugin, when it actually
247# would work with the lld linker (or also fail because the system lld is too old
248# to understand opaque pointers). Using gcc as the compiler would pass the test, but fail
249# when linking with lld since does not understand gcc's LTO format.
250set(LIBOMPTARGET_USE_LTO FALSE CACHE BOOL "Use LTO for the offload runtimes if available")
251if (LIBOMPTARGET_USE_LTO)
252  # CMake sets CMAKE_CXX_COMPILE_OPTIONS_IPO depending on the compiler and is
253  # also what CheckIPOSupported uses to test support.
254  list(APPEND offload_compile_flags ${CMAKE_CXX_COMPILE_OPTIONS_IPO})
255  list(APPEND offload_link_flags ${CMAKE_CXX_COMPILE_OPTIONS_IPO})
256endif()
257
258if(OPENMP_STANDALONE_BUILD)
259  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
260    execute_process(
261      OUTPUT_STRIP_TRAILING_WHITESPACE
262      COMMAND ${CMAKE_CXX_COMPILER} --print-resource-dir
263      RESULT_VARIABLE COMMAND_RETURN_CODE
264      OUTPUT_VARIABLE COMPILER_RESOURCE_DIR
265    )
266  endif()
267
268  set(LIBOMP_HAVE_OMPT_SUPPORT FALSE)
269  set(LIBOMP_OMPT_SUPPORT FALSE)
270
271  find_path (
272    LIBOMP_OMP_TOOLS_INCLUDE_DIR
273    NAMES
274      omp-tools.h
275    HINTS
276    ${COMPILER_RESOURCE_DIR}/include
277    ${CMAKE_INSTALL_PREFIX}/include
278  )
279
280  if(LIBOMP_OMP_TOOLS_INCLUDE_DIR)
281    set(LIBOMP_HAVE_OMPT_SUPPORT TRUE)
282    set(LIBOMP_OMPT_SUPPORT TRUE)
283  endif()
284
285  # LLVM_LIBRARY_DIRS set by find_package(LLVM) in LibomptargetGetDependencies
286  find_library (
287    LIBOMP_STANDALONE
288    NAMES
289      omp
290    HINTS
291      ${CMAKE_INSTALL_PREFIX}/lib
292      ${LLVM_LIBRARY_DIRS}
293    REQUIRED
294  )
295
296  find_path (
297    LIBOMP_INCLUDE_DIR
298    NAMES
299      omp.h
300    HINTS
301    ${COMPILER_RESOURCE_DIR}/include
302    ${CMAKE_INSTALL_PREFIX}/include
303  )
304
305  get_filename_component(LIBOMP_LIBRARY_DIR ${LIBOMP_STANDALONE} DIRECTORY)
306
307  set(OPENMP_TEST_FLAGS "" CACHE STRING
308    "Extra compiler flags to send to the test compiler.")
309  set(OPENMP_TEST_OPENMP_FLAGS ${OPENMP_TEST_COMPILER_OPENMP_FLAGS} CACHE STRING
310    "OpenMP compiler flag to use for testing OpenMP runtime libraries.")
311  set(LIBOMPTARGET_OPENMP_HEADER_FOLDER "${LIBOMP_INCLUDE_DIR}" CACHE STRING
312    "Path to folder containing omp.h")
313  set(LIBOMPTARGET_OPENMP_HOST_RTL_FOLDER "${LIBOMP_LIBRARY_DIR}" CACHE STRING
314    "Path to folder containing libomp.so, and libLLVMSupport.so with profiling enabled")
315endif()
316
317macro(pythonize_bool var)
318if (${var})
319  set(${var} True)
320else()
321  set(${var} False)
322endif()
323endmacro()
324
325if(OPENMP_STANDALONE_BUILD OR TARGET omp)
326  # Check LIBOMP_HAVE_VERSION_SCRIPT_FLAG
327  include(LLVMCheckCompilerLinkerFlag)
328  if(NOT APPLE)
329    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)
330  endif()
331endif()
332
333# OMPT support for libomptarget
334# Follow host OMPT support and check if host support has been requested.
335# LIBOMP_HAVE_OMPT_SUPPORT indicates whether host OMPT support has been implemented.
336# LIBOMP_OMPT_SUPPORT indicates whether host OMPT support has been requested (default is ON).
337# LIBOMPTARGET_OMPT_SUPPORT indicates whether target OMPT support has been requested (default is ON).
338set(OMPT_TARGET_DEFAULT FALSE)
339if ((LIBOMP_HAVE_OMPT_SUPPORT) AND (LIBOMP_OMPT_SUPPORT) AND (NOT WIN32))
340  set (OMPT_TARGET_DEFAULT TRUE)
341endif()
342set(LIBOMPTARGET_OMPT_SUPPORT ${OMPT_TARGET_DEFAULT} CACHE BOOL "OMPT-target-support?")
343if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT))
344  add_definitions(-DOMPT_SUPPORT=1)
345  message(STATUS "OMPT target enabled")
346else()
347  set(LIBOMPTARGET_OMPT_SUPPORT FALSE)
348  message(STATUS "OMPT target disabled")
349endif()
350
351pythonize_bool(LIBOMPTARGET_OMPT_SUPPORT)
352
353if(${LLVM_LIBC_GPU_BUILD})
354  set(LIBOMPTARGET_HAS_LIBC TRUE)
355else()
356  set(LIBOMPTARGET_HAS_LIBC FALSE)
357endif()
358set(LIBOMPTARGET_GPU_LIBC_SUPPORT ${LIBOMPTARGET_HAS_LIBC} CACHE BOOL
359    "Libomptarget support for the GPU libc")
360pythonize_bool(LIBOMPTARGET_GPU_LIBC_SUPPORT)
361
362set(LIBOMPTARGET_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
363set(LIBOMPTARGET_BINARY_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include)
364message(STATUS "OpenMP tools dir in libomptarget: ${LIBOMP_OMP_TOOLS_INCLUDE_DIR}")
365if(LIBOMP_OMP_TOOLS_INCLUDE_DIR)
366  include_directories(${LIBOMP_OMP_TOOLS_INCLUDE_DIR})
367endif()
368
369set(LIBOMPTARGET_LLVM_LIBRARY_DIR "${LLVM_LIBRARY_DIR}" CACHE STRING
370  "Path to folder containing llvm library libomptarget.so")
371set(LIBOMPTARGET_LLVM_LIBRARY_INTDIR "${LIBOMPTARGET_INTDIR}" CACHE STRING
372  "Path to folder where intermediate libraries will be output")
373
374# Build offloading plugins and device RTLs if they are available.
375add_subdirectory(plugins-nextgen)
376add_subdirectory(DeviceRTL)
377add_subdirectory(tools)
378
379# Build target agnostic offloading library.
380add_subdirectory(src)
381
382add_subdirectory(tools/offload-tblgen)
383add_subdirectory(liboffload)
384
385# Add tests.
386add_subdirectory(test)
387
388# Add unit tests if GMock/GTest is present
389if (EXISTS ${LLVM_THIRD_PARTY_DIR}/unittest)
390  if (NOT TARGET llvm_gtest)
391    add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest)
392  endif()
393  add_subdirectory(unittests)
394endif()
395