https://github.com/Meinersbur updated https://github.com/llvm/llvm-project/pull/121782
>From a3037ab5557dcc4a4deb5bb40f801ca9770e3854 Mon Sep 17 00:00:00 2001 From: Michael Kruse <llvm-proj...@meinersbur.de> Date: Mon, 6 Jan 2025 16:44:08 +0100 Subject: [PATCH 1/2] Add FLANG_RT_ENABLE_STATIC and FLANG_RT_ENABLE_SHARED --- flang-rt/CMakeLists.txt | 30 ++ flang-rt/cmake/modules/AddFlangRT.cmake | 291 ++++++++++++------ .../cmake/modules/AddFlangRTOffload.cmake | 8 +- flang-rt/cmake/modules/GetToolchainDirs.cmake | 254 +++++++-------- flang-rt/lib/flang_rt/CMakeLists.txt | 20 +- flang-rt/test/CMakeLists.txt | 2 +- flang-rt/test/lit.cfg.py | 2 +- 7 files changed, 366 insertions(+), 241 deletions(-) diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt index 7b3d22e454a108..7effa6012a078f 100644 --- a/flang-rt/CMakeLists.txt +++ b/flang-rt/CMakeLists.txt @@ -113,6 +113,15 @@ cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR) cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH) # Determine subdirectories for build output and install destinations. +# FIXME: For the libflang_rt.so, the toolchain resource lib dir is not a good +# destination because it is not a ld.so default search path. +# The machine where the executable is eventually executed may not be the +# machine where the Flang compiler and its resource dir is installed, so +# setting RPath by the driver is not an solution. It should belong into +# /usr/lib/<triple>/libflang_rt.so, like e.g. libgcc_s.so. +# But the linker as invoked by the Flang driver also requires +# libflang_rt.so to be found when linking and the resource lib dir is +# the only reliable location. get_toolchain_library_subdir(toolchain_lib_subdir) extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}") extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}") @@ -130,6 +139,27 @@ cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH) option(FLANG_RT_INCLUDE_TESTS "Generate build targets for the flang-rt unit and regression-tests." "${LLVM_INCLUDE_TESTS}") +option(FLANG_RT_ENABLE_STATIC "Build Flang-RT as a static library." ON) +if (WIN32) + # Windows DLL currently not implemented. + set(FLANG_RT_ENABLE_SHARED OFF) +else () + # TODO: Enable by default to increase test coverage, and which version of the + # library should be the user's choice anyway. + # Currently, the Flang driver adds `-L"libdir" -lflang_rt` as linker + # argument, which leaves the choice which library to use to the linker. + # Since most linkers prefer the shared library, this would constitute a + # breaking change unless the driver is changed. + option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." OFF) +endif () +if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED) + message(FATAL_ERROR " + Must build at least one type of library + (FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both) + ") +endif () + + set(FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT "" CACHE STRING "Compile Flang-RT with GPU support (CUDA or OpenMP)") set_property(CACHE FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT PROPERTY STRINGS "" diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake index 1f8b5111433825..5f493a80c35f20 100644 --- a/flang-rt/cmake/modules/AddFlangRT.cmake +++ b/flang-rt/cmake/modules/AddFlangRT.cmake @@ -16,7 +16,8 @@ # STATIC # Build a static (.a/.lib) library # OBJECT -# Create only object files without static/dynamic library +# Always create an object library. +# Without SHARED/STATIC, build only the object library. # INSTALL_WITH_TOOLCHAIN # Install library into Clang's resource directory so it can be found by the # Flang driver during compilation, including tests @@ -44,17 +45,73 @@ function (add_flangrt_library name) ") endif () - # Forward libtype to add_library - set(extra_args "") - if (ARG_SHARED) - list(APPEND extra_args SHARED) + # Internal names of libraries. If called with just single type option, use + # the default name for it. Name of targets must only depend on function + # arguments to be predictable for callers. + set(name_static "${name}.static") + set(name_shared "${name}.shared") + set(name_object "obj.${name}") + if (ARG_STATIC AND NOT ARG_SHARED) + set(name_static "${name}") + elseif (NOT ARG_STATIC AND ARG_SHARED) + set(name_shared "${name}") + elseif (NOT ARG_STATIC AND NOT ARG_SHARED AND ARG_OBJECT) + set(name_object "${name}") + elseif (NOT ARG_STATIC AND NOT ARG_SHARED AND NOT ARG_OBJECT) + # Only one of them will actually be built. + set(name_static "${name}") + set(name_shared "${name}") + endif () + + # Determine what to build. If not explicitly specified, honor + # BUILD_SHARED_LIBS (e.g. for unittest libraries). If can build static and + # shared, use ENABLE_STATIC/ENABLE_SHARED setting. + if (ARG_STATIC AND ARG_SHARED) + set(build_static ${FLANG_RT_ENABLE_STATIC}) + set(build_shared ${FLANG_RT_ENABLE_SHARED}) + else () + set(build_static ${ARG_STATIC}) + set(build_shared ${ARG_SHARED}) endif () - if (ARG_STATIC) - list(APPEND extra_args STATIC) + if (NOT ARG_STATIC AND NOT ARG_SHARED AND NOT ARG_OBJECT) + if (BUILD_SHARED_LIBS) + set(build_shared ON) + else () + set(build_static ON) + endif () endif () + + # Build an object library if building multiple libraries at once or if + # explicitly requested. + set(build_object OFF) if (ARG_OBJECT) - list(APPEND extra_args OBJECT) + set(build_object ON) + elseif (build_static AND build_shared) + set(build_object ON) + endif () + + # srctargets: targets that contain source files + # libtargets: static/shared if they are built + # alltargets: any add_library target added by this function + set(srctargets "") + set(libtargets "") + set(alltargets "") + if (build_static) + list(APPEND srctargets "${name_static}") + list(APPEND libtargets "${name_static}") + list(APPEND alltargets "${name_static}") endif () + if (build_shared) + list(APPEND srctargets "${name_shared}") + list(APPEND libtargets "${name_shared}") + list(APPEND alltargets "${name_shared}") + endif () + if (build_object) + set(srctargets "${name_object}") + list(APPEND alltargets "${name_object}") + endif () + + set(extra_args "") if (ARG_EXCLUDE_FROM_ALL) list(APPEND extra_args EXCLUDE_FROM_ALL) endif () @@ -62,113 +119,145 @@ function (add_flangrt_library name) # Also add header files to IDEs to list as part of the library. set_source_files_properties(${ARG_ADDITIONAL_HEADERS} PROPERTIES HEADER_FILE_ONLY ON) - add_library(${name} ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS}) + # Create selected library types. + if (build_object) + add_library("${name_object}" OBJECT ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS}) + set_target_properties(${name_object} PROPERTIES + POSITION_INDEPENDENT_CODE ON + FOLDER "Flang-RT/Object Libraries" + ) - if (ARG_INSTALL_WITH_TOOLCHAIN) - set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Toolchain Libraries") - elseif (ARG_OBJECT) - set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Object Libraries") - else () - set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Libraries") + # Replace arguments for the libraries we are going to create. + set(ARG_ADDITIONAL_HEADERS "") + set(ARG_UNPARSED_ARGUMENTS "$<TARGET_OBJECTS:${name_object}>") + endif () + if (build_static) + add_library("${name_static}" STATIC ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS}) + endif () + if (build_shared) + add_library("${name_shared}" SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS}) endif () - # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else. - target_compile_features(${name} PRIVATE cxx_std_17) + foreach (tgtname IN LISTS libtargets) + if (NOT WIN32) + # Use same stem name for .a and .so. Common in UNIX environments. + # Not possible in Windows environments. + set_target_properties(${tgtname} PROPERTIES OUTPUT_NAME "${name}") + endif () - # Use compiler-specific options to disable exceptions and RTTI. - if (LLVM_COMPILER_IS_GCC_COMPATIBLE) - target_compile_options(${name} PRIVATE - $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables> - ) - elseif (MSVC) - target_compile_options(${name} PRIVATE - $<$<COMPILE_LANGUAGE:CXX>:/EHs-c- /GR-> - ) - elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL") - target_compile_options(${name} PRIVATE - $<$<COMPILE_LANGUAGE:CXX>:-qnoeh -qnortti> - ) - endif () + if (ARG_INSTALL_WITH_TOOLCHAIN) + set_target_properties(${tgtname} PROPERTIES FOLDER "Flang-RT/Toolchain Libraries") + else () + set_target_properties(${tgtname} PROPERTIES FOLDER "Flang-RT/Libraries") + endif () + endforeach () - # Also for CUDA source when compiling with FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT=CUDA - if (CMAKE_CUDA_COMPILER_ID MATCHES "NVIDIA") - # Assuming gcc as host compiler. - target_compile_options(${name} PRIVATE - $<$<COMPILE_LANGUAGE:CUDA>:--no-exceptions -Xcompiler -fno-rtti -Xcompiler -fno-unwind-tables -Xcompiler -fno-asynchronous-unwind-tables> - ) - else () - # Assuming a clang-compatible CUDA compiler. - target_compile_options(${name} PRIVATE - $<$<COMPILE_LANGUAGE:CUDA>:-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables> - ) - endif () + # Define how to compile and link the library. + # Some conceptionally only apply to ${srctargets} or ${libtargets}, but we + # apply them to ${alltargets}. In worst case, they are ignored by CMake. + foreach (tgtname IN LISTS alltargets) + # Minimum required C++ version for Flang-RT, even if CMAKE_CXX_STANDARD is defined to something else. + target_compile_features(${tgtname} PRIVATE cxx_std_17) + + # Use compiler-specific options to disable exceptions and RTTI. + if (LLVM_COMPILER_IS_GCC_COMPATIBLE) + target_compile_options(${tgtname} PRIVATE + $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables> + ) + elseif (MSVC) + target_compile_options(${tgtname} PRIVATE + $<$<COMPILE_LANGUAGE:CXX>:/EHs-c- /GR-> + ) + elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL") + target_compile_options(${tgtname} PRIVATE + $<$<COMPILE_LANGUAGE:CXX>:-qnoeh -qnortti> + ) + endif () - # Flang-RT's public headers - target_include_directories(${name} PRIVATE "${FLANG_RT_SOURCE_DIR}/include") + # Also for CUDA source when compiling with FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT=CUDA + if (CMAKE_CUDA_COMPILER_ID MATCHES "NVIDIA") + # Assuming gcc as host compiler. + target_compile_options(${tgtname} PRIVATE + $<$<COMPILE_LANGUAGE:CUDA>:--no-exceptions -Xcompiler -fno-rtti -Xcompiler -fno-unwind-tables -Xcompiler -fno-asynchronous-unwind-tables> + ) + else () + # Assuming a clang-compatible CUDA compiler. + target_compile_options(${tgtname} PRIVATE + $<$<COMPILE_LANGUAGE:CUDA>:-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables> + ) + endif () - # For ISO_Fortran_binding.h to be found by the runtime itself (Accessed as #include "flang/ISO_Fortran_binding.h") - # User applications can use #include <ISO_Fortran_binding.h> - target_include_directories(${name} PRIVATE "${FLANG_SOURCE_DIR}/include") + # Flang-RT's public headers + target_include_directories(${tgtname} PRIVATE "${FLANG_RT_SOURCE_DIR}/include") - # For Flang-RT's configured config.h to be found - target_include_directories(${name} PRIVATE "${FLANG_RT_BINARY_DIR}") + # For ISO_Fortran_binding.h to be found by the runtime itself (Accessed as #include "flang/ISO_Fortran_binding.h") + # User applications can use #include <ISO_Fortran_binding.h> + target_include_directories(${tgtname} PRIVATE "${FLANG_SOURCE_DIR}/include") - # Disable libstdc++/libc++ assertions, even in an LLVM_ENABLE_ASSERTIONS - # build, to avoid an unwanted dependency on libstdc++/libc++.so. - if (FLANG_RT_SUPPORTS_UNDEFINE_FLAG) - target_compile_options(${name} PUBLIC -U_GLIBCXX_ASSERTIONS) - target_compile_options(${name} PUBLIC -U_LIBCPP_ENABLE_ASSERTIONS) - endif () + # For Flang-RT's configured config.h to be found + target_include_directories(${tgtname} PRIVATE "${FLANG_RT_BINARY_DIR}") - # Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI - # should only depend on msvcrt/ucrt. LLVM still emits libgcc/compiler-rt - # functions in some cases like 128-bit integer math (__udivti3, __modti3, - # __fixsfti, __floattidf, ...) that msvc does not support. We are injecting a - # dependency to Compiler-RT's builtin library where these are implemented. - if (MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") - if (FLANG_RT_BUILTINS_LIBRARY) - target_compile_options(${name} PRIVATE "$<$<COMPILE_LANGUAGE:CXX,C>:-Xclang>" "$<$<COMPILE_LANGUAGE:CXX,C>:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") + # Disable libstdc++/libc++ assertions, even in an LLVM_ENABLE_ASSERTIONS + # build, to avoid an unwanted dependency on libstdc++/libc++.so. + if (FLANG_RT_SUPPORTS_UNDEFINE_FLAG) + target_compile_options(${tgtname} PUBLIC -U_GLIBCXX_ASSERTIONS) + target_compile_options(${tgtname} PUBLIC -U_LIBCPP_ENABLE_ASSERTIONS) endif () - endif () - if (MSVC AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang") - if (FLANG_RT_BUILTINS_LIBRARY) - target_compile_options(${name} PRIVATE "$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "$<$<COMPILE_LANGUAGE:Fortran>:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") - else () - message(WARNING "Did not find libclang_rt.builtins.lib. - LLVM may emit builtins that are not implemented in msvcrt/ucrt and - instead falls back to builtins from Compiler-RT. Linking with ${name} - may result in a linker error.") + + # Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI + # should only depend on msvcrt/ucrt. LLVM still emits libgcc/compiler-rt + # functions in some cases like 128-bit integer math (__udivti3, __modti3, + # __fixsfti, __floattidf, ...) that msvc does not support. We are injecting a + # dependency to Compiler-RT's builtin library where these are implemented. + if (MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if (FLANG_RT_BUILTINS_LIBRARY) + target_compile_options(${tgtname} PRIVATE "$<$<COMPILE_LANGUAGE:CXX,C>:-Xclang>" "$<$<COMPILE_LANGUAGE:CXX,C>:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") + endif () + endif () + if (MSVC AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang") + if (FLANG_RT_BUILTINS_LIBRARY) + target_compile_options(${tgtname} PRIVATE "$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "$<$<COMPILE_LANGUAGE:Fortran>:--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}>") + else () + message(WARNING "Did not find libclang_rt.builtins.lib. + LLVM may emit builtins that are not implemented in msvcrt/ucrt and + instead falls back to builtins from Compiler-RT. Linking with ${tgtname} + may result in a linker error.") + endif () endif () - endif () - # Non-GTest unittests depend on LLVMSupport - if (ARG_LINK_TO_LLVM) - if (LLVM_LINK_LLVM_DYLIB) - set(llvm_libs LLVM) - else() - llvm_map_components_to_libnames(llvm_libs Support) - endif() - target_link_libraries(${name} PUBLIC ${llvm_libs}) - target_include_directories(${name} PUBLIC ${LLVM_INCLUDE_DIRS}) - endif () + # Non-GTest unittests depend on LLVMSupport + if (ARG_LINK_TO_LLVM) + if (LLVM_LINK_LLVM_DYLIB) + set(llvm_libs LLVM) + else() + llvm_map_components_to_libnames(llvm_libs Support) + endif() + target_link_libraries(${tgtname} PUBLIC ${llvm_libs}) + target_include_directories(${tgtname} PUBLIC ${LLVM_INCLUDE_DIRS}) + endif () + endforeach () - # If this is part of the toolchain, put it into the compiler's resource - # directory. Otherwise it is part of testing and is not installed at all. - # TODO: Consider multi-configuration builds (MSVC_IDE, "Ninja Multi-Config") - if (ARG_INSTALL_WITH_TOOLCHAIN) - set_target_properties(${name} - PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}" - ) + foreach (tgtname IN LISTS libtargets) + # If this is part of the toolchain, put it into the compiler's resource + # directory. Otherwise it is part of testing and is not installed at all. + # TODO: Consider multi-configuration builds (MSVC_IDE, "Ninja Multi-Config") + if (ARG_INSTALL_WITH_TOOLCHAIN) + set_target_properties(${tgtname} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}" + LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}" + ) - install(TARGETS ${name} - ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}" - ) - endif () + install(TARGETS ${tgtname} + ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}" + LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}" + ) + endif () - # flang-rt should build all the Flang-RT targets that are built in an - # 'all' build. - if (NOT ARG_EXCLUDE_FROM_ALL) - add_dependencies(flang-rt ${name}) - endif () + # flang-rt should build all the Flang-RT targets that are built in an + # 'all' build. + if (NOT ARG_EXCLUDE_FROM_ALL) + add_dependencies(flang-rt ${tgtname}) + endif () + endforeach () endfunction (add_flangrt_library) diff --git a/flang-rt/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake index 84eabba05b49b9..94b7309a955f32 100644 --- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake +++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake @@ -8,9 +8,9 @@ macro(enable_cuda_compilation name files) if (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA") - if (BUILD_SHARED_LIBS) + if (FLANG_RT_ENABLE_SHARED) message(FATAL_ERROR - "BUILD_SHARED_LIBS is not supported for CUDA build of Fortran runtime" + "FLANG_RT_ENABLE_SHARED is not supported for CUDA build of Flang-RT" ) endif() @@ -70,9 +70,9 @@ macro(enable_omp_offload_compilation name files) if (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP") # OpenMP offload build only works with Clang compiler currently. - if (BUILD_SHARED_LIBS) + if (FLANG_RT_ENABLE_SHARED) message(FATAL_ERROR - "BUILD_SHARED_LIBS is not supported for OpenMP offload build of Fortran runtime" + "FLANG_RT_ENABLE_SHARED is not supported for OpenMP offload build of Flang-RT" ) endif() diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/flang-rt/cmake/modules/GetToolchainDirs.cmake index fc1a406f99ab29..1f251790f22a01 100644 --- a/flang-rt/cmake/modules/GetToolchainDirs.cmake +++ b/flang-rt/cmake/modules/GetToolchainDirs.cmake @@ -1,127 +1,127 @@ -#===-- cmake/modules/GetToolchainDirs.cmake --------------------------------===# -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -# -#===------------------------------------------------------------------------===# - -include(GNUInstallDirs) - - -# Determine the subdirectory relative to Clang's resource dir/sysroot where to -# install target-specific libraries, to be found by Clang/Flang driver. This was -# adapted from Compiler-RT's mechanism to find the path for -# libclang_rt.builtins.a. -# -# Compiler-RT has two mechanisms for the path (simplified): -# -# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=1: lib/${oslibname}/libclang_rt.builtins-${arch}.a -# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0: lib/${triple}/libclang_rt.builtins.a -# -# LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON is the newer scheme, but the old one is -# currently still used for some platforms such as Windows. Clang looks for which -# of the files exist before passing the path to the linker. Hence, the -# directories have to match what Clang is looking for, which is done in -# ToolChain::getArchSpecificLibPaths(..), ToolChain::getRuntimePath(), -# ToolChain::getCompilerRTPath(), and ToolChain::getCompilerRT(..), not entirely -# consistent between these functions, Compiler-RT's CMake code, and overrides -# in different toolchains. -# -# For Fortran, Flang always assumes the library name libflang_rt.a without -# architecture suffix. Hence, we always use the second scheme even as if -# LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON, even if it actually set to OFF. It as -# added unconditionally to the library search path by -# ToolChain::getArchSpecificLibPaths(...). -function (get_toolchain_library_subdir outvar) - if (NOT APPLE) - set(outval "${CMAKE_INSTALL_LIBDIR}") - else () - # Required to be "darwin" for MachO toolchain. - get_toolchain_os_dirname(os_dirname) - set(outval "${CMAKE_INSTALL_LIBDIR}/${os_dirname}") - endif () - - get_toolchain_arch_dirname(arch_dirname) - set(outval "${CMAKE_INSTALL_LIBDIR}/${arch_dirname}") - - set(${outvar} "${outval}" PARENT_SCOPE) -endfunction () - - -# Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT. -function (get_toolchain_os_dirname outvar) - if (ANDROID) - # The CMAKE_SYSTEM_NAME for Android is "Android", but the OS is Linux and the - # driver will search for libraries in the "linux" directory. - set(outval "linux") - else () - string(TOLOWER "${CMAKE_SYSTEM_NAME}" outval) - endif () - set(${outvar} "${outval}" PARENT_SCOPE) -endfunction () - - -# Corresponds to Clang's ToolChain::getRuntimePath(). Adapted from Compiler-RT. -function (get_toolchain_arch_dirname outvar) - string(REPLACE "-" ";" triple_list ${LLVM_TARGET_TRIPLE}) - list(GET triple_list 0 arch) - - if("${arch}" MATCHES "^i.86$") - # Android uses i686, but that's remapped at a later stage. - set(arch "i386") - endif() - - string(FIND ${LLVM_TARGET_TRIPLE} "-" dash_index) - string(SUBSTRING ${LLVM_TARGET_TRIPLE} ${dash_index} -1 triple_suffix) - string(SUBSTRING ${LLVM_TARGET_TRIPLE} 0 ${dash_index} triple_cpu) - set(arch "${triple_cpu}") - if("${arch}" MATCHES "^i.86$") - # Android uses i686, but that's remapped at a later stage. - set(arch "i386") - endif() - - if(ANDROID AND ${arch} STREQUAL "i386") - set(target "i686${triple_suffix}") - elseif(${arch} STREQUAL "amd64") - set(target "x86_64${triple_suffix}") - elseif(${arch} STREQUAL "sparc64") - set(target "sparcv9${triple_suffix}") - elseif("${arch}" MATCHES "mips64|mips64el") - string(REGEX REPLACE "-gnu.*" "-gnuabi64" triple_suffix_gnu "${triple_suffix}") - string(REGEX REPLACE "mipsisa32" "mipsisa64" triple_cpu_mips "${triple_cpu}") - string(REGEX REPLACE "^mips$" "mips64" triple_cpu_mips "${triple_cpu_mips}") - string(REGEX REPLACE "^mipsel$" "mips64el" triple_cpu_mips "${triple_cpu_mips}") - set(target "${triple_cpu_mips}${triple_suffix_gnu}") - elseif("${arch}" MATCHES "mips|mipsel") - string(REGEX REPLACE "-gnuabi.*" "-gnu" triple_suffix_gnu "${triple_suffix}") - string(REGEX REPLACE "mipsisa64" "mipsisa32" triple_cpu_mips "${triple_cpu}") - string(REGEX REPLACE "mips64" "mips" triple_cpu_mips "${triple_cpu_mips}") - set(target "${triple_cpu_mips}${triple_suffix_gnu}") - elseif("${arch}" MATCHES "^arm") - # FIXME: Handle arch other than arm, armhf, armv6m - if (${arch} STREQUAL "armhf") - # If we are building for hard float but our ABI is soft float. - if ("${triple_suffix}" MATCHES ".*eabi$") - # Change "eabi" -> "eabihf" - set(triple_suffix "${triple_suffix}hf") - endif() - # ABI is already set in the triple, don't repeat it in the architecture. - set(arch "arm") - else () - # If we are building for soft float, but the triple's ABI is hard float. - if ("${triple_suffix}" MATCHES ".*eabihf$") - # Change "eabihf" -> "eabi" - string(REGEX REPLACE "hf$" "" triple_suffix "${triple_suffix}") - endif() - endif() - set(target "${arch}${triple_suffix}") - elseif("${arch}" MATCHES "^amdgcn") - set(target "amdgcn-amd-amdhsa") - elseif("${arch}" MATCHES "^nvptx") - set(target "nvptx64-nvidia-cuda") - else() - set(target "${arch}${triple_suffix}") - endif() - set(${outvar} "${target}" PARENT_SCOPE) -endfunction() +#===-- cmake/modules/GetToolchainDirs.cmake --------------------------------===# +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===------------------------------------------------------------------------===# + +include(GNUInstallDirs) + + +# Determine the subdirectory relative to Clang's resource dir/sysroot where to +# install target-specific libraries, to be found by Clang/Flang driver. This was +# adapted from Compiler-RT's mechanism to find the path for +# libclang_rt.builtins.a. +# +# Compiler-RT has two mechanisms for the path (simplified): +# +# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=1: lib/${oslibname}/libclang_rt.builtins-${arch}.a +# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=0: lib/${triple}/libclang_rt.builtins.a +# +# LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON is the newer scheme, but the old one is +# currently still used for some platforms such as Windows. Clang looks for which +# of the files exist before passing the path to the linker. Hence, the +# directories have to match what Clang is looking for, which is done in +# ToolChain::getArchSpecificLibPaths(..), ToolChain::getRuntimePath(), +# ToolChain::getCompilerRTPath(), and ToolChain::getCompilerRT(..), not entirely +# consistent between these functions, Compiler-RT's CMake code, and overrides +# in different toolchains. +# +# For Fortran, Flang always assumes the library name libflang_rt.a without +# architecture suffix. Hence, we always use the second scheme even as if +# LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON, even if it actually set to OFF. It as +# added unconditionally to the library search path by +# ToolChain::getArchSpecificLibPaths(...). +function (get_toolchain_library_subdir outvar) + if (NOT APPLE) + set(outval "${CMAKE_INSTALL_LIBDIR}") + else () + # Required to be "darwin" for MachO toolchain. + get_toolchain_os_dirname(os_dirname) + set(outval "${CMAKE_INSTALL_LIBDIR}/${os_dirname}") + endif () + + get_toolchain_arch_dirname(arch_dirname) + set(outval "${CMAKE_INSTALL_LIBDIR}/${arch_dirname}") + + set(${outvar} "${outval}" PARENT_SCOPE) +endfunction () + + +# Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT. +function (get_toolchain_os_dirname outvar) + if (ANDROID) + # The CMAKE_SYSTEM_NAME for Android is "Android", but the OS is Linux and the + # driver will search for libraries in the "linux" directory. + set(outval "linux") + else () + string(TOLOWER "${CMAKE_SYSTEM_NAME}" outval) + endif () + set(${outvar} "${outval}" PARENT_SCOPE) +endfunction () + + +# Corresponds to Clang's ToolChain::getRuntimePath(). Adapted from Compiler-RT. +function (get_toolchain_arch_dirname outvar) + string(REPLACE "-" ";" triple_list ${LLVM_TARGET_TRIPLE}) + list(GET triple_list 0 arch) + + if("${arch}" MATCHES "^i.86$") + # Android uses i686, but that's remapped at a later stage. + set(arch "i386") + endif() + + string(FIND ${LLVM_TARGET_TRIPLE} "-" dash_index) + string(SUBSTRING ${LLVM_TARGET_TRIPLE} ${dash_index} -1 triple_suffix) + string(SUBSTRING ${LLVM_TARGET_TRIPLE} 0 ${dash_index} triple_cpu) + set(arch "${triple_cpu}") + if("${arch}" MATCHES "^i.86$") + # Android uses i686, but that's remapped at a later stage. + set(arch "i386") + endif() + + if(ANDROID AND ${arch} STREQUAL "i386") + set(target "i686${triple_suffix}") + elseif(${arch} STREQUAL "amd64") + set(target "x86_64${triple_suffix}") + elseif(${arch} STREQUAL "sparc64") + set(target "sparcv9${triple_suffix}") + elseif("${arch}" MATCHES "mips64|mips64el") + string(REGEX REPLACE "-gnu.*" "-gnuabi64" triple_suffix_gnu "${triple_suffix}") + string(REGEX REPLACE "mipsisa32" "mipsisa64" triple_cpu_mips "${triple_cpu}") + string(REGEX REPLACE "^mips$" "mips64" triple_cpu_mips "${triple_cpu_mips}") + string(REGEX REPLACE "^mipsel$" "mips64el" triple_cpu_mips "${triple_cpu_mips}") + set(target "${triple_cpu_mips}${triple_suffix_gnu}") + elseif("${arch}" MATCHES "mips|mipsel") + string(REGEX REPLACE "-gnuabi.*" "-gnu" triple_suffix_gnu "${triple_suffix}") + string(REGEX REPLACE "mipsisa64" "mipsisa32" triple_cpu_mips "${triple_cpu}") + string(REGEX REPLACE "mips64" "mips" triple_cpu_mips "${triple_cpu_mips}") + set(target "${triple_cpu_mips}${triple_suffix_gnu}") + elseif("${arch}" MATCHES "^arm") + # FIXME: Handle arch other than arm, armhf, armv6m + if (${arch} STREQUAL "armhf") + # If we are building for hard float but our ABI is soft float. + if ("${triple_suffix}" MATCHES ".*eabi$") + # Change "eabi" -> "eabihf" + set(triple_suffix "${triple_suffix}hf") + endif() + # ABI is already set in the triple, don't repeat it in the architecture. + set(arch "arm") + else () + # If we are building for soft float, but the triple's ABI is hard float. + if ("${triple_suffix}" MATCHES ".*eabihf$") + # Change "eabihf" -> "eabi" + string(REGEX REPLACE "hf$" "" triple_suffix "${triple_suffix}") + endif() + endif() + set(target "${arch}${triple_suffix}") + elseif("${arch}" MATCHES "^amdgcn") + set(target "amdgcn-amd-amdhsa") + elseif("${arch}" MATCHES "^nvptx") + set(target "nvptx64-nvidia-cuda") + else() + set(target "${arch}${triple_suffix}") + endif() + set(${outvar} "${target}" PARENT_SCOPE) +endfunction() diff --git a/flang-rt/lib/flang_rt/CMakeLists.txt b/flang-rt/lib/flang_rt/CMakeLists.txt index ff45e26961a42c..c0dfc7e976f28b 100644 --- a/flang-rt/lib/flang_rt/CMakeLists.txt +++ b/flang-rt/lib/flang_rt/CMakeLists.txt @@ -128,19 +128,25 @@ endif () set(sources ${supported_sources} ${host_sources} ${f128_sources}) if (NOT WIN32) - add_flangrt_library(flang_rt STATIC + add_flangrt_library(flang_rt STATIC SHARED ${sources} INSTALL_WITH_TOOLCHAIN ADDITIONAL_HEADERS ${public_headers} ${private_headers} ) - enable_cuda_compilation(flang_rt "${supported_sources}") - enable_omp_offload_compilation(flang_rt "${supported_sources}") + enable_cuda_compilation(flang_rt.static "${supported_sources}") + enable_omp_offload_compilation(flang_rt.static "${supported_sources}") - # For unittests that depend on flang_rt. Should link to the static version - # of the library. - add_library(flang_rt.static ALIAS flang_rt) - add_library(flang_rt.unittest ALIAS flang_rt) + # Select a default runtime, which is used for unittests. + if (TARGET flang_rt.shared AND BUILD_SHARED_LIBS) + set(default_flang_rt "flang_rt.shared") + elseif (TARGET flang_rt.static) + set(default_flang_rt "flang_rt.static") + else () + set(default_flang_rt "flang_rt.shared") + endif () + add_library(flang_rt ALIAS "${default_flang_rt}") + add_library(flang_rt.unittest ALIAS "${default_flang_rt}") else() # Target for building all versions of the runtime add_custom_target(flang_rt) diff --git a/flang-rt/test/CMakeLists.txt b/flang-rt/test/CMakeLists.txt index 5ca07b66e4f9b5..74f506d6f98f00 100644 --- a/flang-rt/test/CMakeLists.txt +++ b/flang-rt/test/CMakeLists.txt @@ -45,7 +45,7 @@ set_target_properties(flang-rt-test-depends PROPERTIES FOLDER "Flang-RT/Meta") add_dependencies(flang-rt-test-depends FlangRTUnitTests flang_rt.unittest - flang_rt.static + flang_rt ) add_lit_testsuite(check-flang-rt "Running the Flang-RT regression tests" diff --git a/flang-rt/test/lit.cfg.py b/flang-rt/test/lit.cfg.py index 8a810f40558664..46274c5c8b1b1e 100644 --- a/flang-rt/test/lit.cfg.py +++ b/flang-rt/test/lit.cfg.py @@ -94,7 +94,7 @@ def shjoin(args, sep=" "): # Include path for C headers that define Flang's Fortran ABI. config.substitutions.append(("%include", os.path.join(config.flang_source_dir, "include"))) -# Library path of libflang_rt.a (for lib search path when using non-Flang driver for linking) +# Library path of libflang_rt.a/.so (for lib search path when using non-Flang driver for linking and LD_LIBRARY_PATH) config.substitutions.append(("%libdir", config.flang_rt_output_resource_lib_dir)) # Additional library depedendencies the that Flang driver does not add itself. >From 323504f8160921684e0c26543df6c8b1203bdc13 Mon Sep 17 00:00:00 2001 From: Michael Kruse <llvm-proj...@meinersbur.de> Date: Wed, 8 Jan 2025 17:14:43 +0100 Subject: [PATCH 2/2] CufRuntime only supports static library --- flang-rt/cmake/modules/AddFlangRT.cmake | 15 +++++++++ .../cmake/modules/AddFlangRTOffload.cmake | 4 +-- flang-rt/lib/flang_rt/CUDA/CMakeLists.txt | 32 ++++++++----------- .../unittests/Runtime/CUDA/CMakeLists.txt | 12 +------ 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake index 5f493a80c35f20..5c8d1c15f8b02d 100644 --- a/flang-rt/cmake/modules/AddFlangRT.cmake +++ b/flang-rt/cmake/modules/AddFlangRT.cmake @@ -138,6 +138,21 @@ function (add_flangrt_library name) add_library("${name_shared}" SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS}) endif () + # Provide a default target if building both and which exists in either setting. + if (BUILD_SHARED_LIBS) + if (build_shared) + add_library(${name}.default ALIAS ${name_shared}) + else () + add_library(${name}.default ALIAS ${name}) + endif () + else () + if (build_static) + add_library(${name}.default ALIAS ${name_static}) + else () + add_library(${name}.default ALIAS ${name}) + endif () + endif () + foreach (tgtname IN LISTS libtargets) if (NOT WIN32) # Use same stem name for .a and .so. Common in UNIX environments. diff --git a/flang-rt/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake index 94b7309a955f32..bde98eb2747b96 100644 --- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake +++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake @@ -8,9 +8,9 @@ macro(enable_cuda_compilation name files) if (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA") - if (FLANG_RT_ENABLE_SHARED) + if (NOT FLANG_RT_ENABLE_STATIC) message(FATAL_ERROR - "FLANG_RT_ENABLE_SHARED is not supported for CUDA build of Flang-RT" + "FLANG_RT_ENABLE_STATIC is required for CUDA build of Flang-RT" ) endif() diff --git a/flang-rt/lib/flang_rt/CUDA/CMakeLists.txt b/flang-rt/lib/flang_rt/CUDA/CMakeLists.txt index 8a6b8d30e721ef..c92f6afe034e77 100644 --- a/flang-rt/lib/flang_rt/CUDA/CMakeLists.txt +++ b/flang-rt/lib/flang_rt/CUDA/CMakeLists.txt @@ -6,12 +6,8 @@ # #===------------------------------------------------------------------------===# -# libCufRuntime depends on a certain version of CUDA. To be able to have -# multiple build of this library with different CUDA version, the version is -# added to the library name. -set(CUFRT_LIBNAME CufRuntime_cuda_${CUDAToolkit_VERSION_MAJOR}) -add_flangrt_library(${CUFRT_LIBNAME} +add_flangrt_library(CufRuntime STATIC allocatable.cpp allocator.cpp descriptor.cpp @@ -20,21 +16,19 @@ add_flangrt_library(${CUFRT_LIBNAME} memory.cpp registration.cpp ) -target_include_directories(${CUFRT_LIBNAME} PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) -if (BUILD_SHARED_LIBS) - set(CUDA_RT_TARGET CUDA::cudart) -else() - set(CUDA_RT_TARGET CUDA::cudart_static) -endif() - -target_link_libraries(${CUFRT_LIBNAME} - PRIVATE - flang_rt - ${CUDA_RT_TARGET} +# libCufRuntime depends on a certain version of CUDA. To be able to have +# multiple build of this library with different CUDA version, the version is +# added to the library name. +set_target_properties(CufRuntime + PROPERTIES + OUTPUT_NAME "CufRuntime_cuda_${CUDAToolkit_VERSION_MAJOR}" ) -# Phony build target that does not include the CUDA version. -add_custom_target(CufRuntime) -add_dependencies(CufRuntime ${CUFRT_LIBNAME}) +target_include_directories(CufRuntime PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) +target_link_libraries(CufRuntime + PUBLIC + flang_rt + CUDA::cudart_static +) diff --git a/flang-rt/unittests/Runtime/CUDA/CMakeLists.txt b/flang-rt/unittests/Runtime/CUDA/CMakeLists.txt index 4e5b8a9848dd0c..37b117234208c4 100644 --- a/flang-rt/unittests/Runtime/CUDA/CMakeLists.txt +++ b/flang-rt/unittests/Runtime/CUDA/CMakeLists.txt @@ -12,17 +12,7 @@ add_flangrt_unittest(FlangCufRuntimeTests Memory.cpp ) -if (BUILD_SHARED_LIBS) - set(CUDA_RT_TARGET CUDA::cudart) -else() - set(CUDA_RT_TARGET CUDA::cudart_static) -endif() - target_link_libraries(FlangCufRuntimeTests PRIVATE - ${CUDA_RT_TARGET} - CufRuntime_cuda_${CUDAToolkit_VERSION_MAJOR} - flang_rt.unittest + CufRuntime ) - -target_include_directories(FlangCufRuntimeTests PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits