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