Common CMake code to be used by flang-rt and openmp to emit Flang module files. Most of the code is not yet used within this PR. Extracted out of #171515 for review by @petrhosek.
385 lines
15 KiB
CMake
385 lines
15 KiB
CMake
#===-- cmake/modules/AddFlangRT.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
|
|
#
|
|
#===------------------------------------------------------------------------===#
|
|
|
|
# Builds a library with common options for Flang-RT.
|
|
#
|
|
# Usage:
|
|
#
|
|
# add_flangrt_library(name sources ...
|
|
# SHARED
|
|
# Build a dynamic (.so/.dll) library
|
|
# STATIC
|
|
# Build a static (.a/.lib) library
|
|
# OBJECT
|
|
# 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
|
|
# EXCLUDE_FROM_ALL
|
|
# Do not build library by default; typically used for libraries needed for
|
|
# testing only, no install
|
|
# LINK_TO_LLVM
|
|
# Library requires include path and linking to LLVM's Support component
|
|
# ADDITIONAL_HEADERS
|
|
# May specify header files for IDE generators.
|
|
# INCLUDE_DIRECTORIES
|
|
# Additional target_include_directories for all added targets
|
|
# LINK_LIBRARIES
|
|
# Additional target_link_libraries for all added targets
|
|
# TARGET_PROPERTIES
|
|
# Set target properties of all added targets
|
|
# )
|
|
function (add_flangrt_library name)
|
|
set(options STATIC SHARED OBJECT INSTALL_WITH_TOOLCHAIN EXCLUDE_FROM_ALL LINK_TO_LLVM)
|
|
set(multiValueArgs ADDITIONAL_HEADERS INCLUDE_DIRECTORIES LINK_LIBRARIES TARGET_PROPERTIES)
|
|
cmake_parse_arguments(ARG
|
|
"${options}"
|
|
""
|
|
"${multiValueArgs}"
|
|
${ARGN})
|
|
|
|
if (ARG_INSTALL_WITH_TOOLCHAIN AND ARG_EXCLUDE_FROM_ALL)
|
|
message(SEND_ERROR "add_flangrt_library(${name} ...):
|
|
INSTALL_WITH_TOOLCHAIN and EXCLUDE_FROM_ALL are in conflict. When
|
|
installing an artifact it must have been built first in the 'all' target.
|
|
")
|
|
endif ()
|
|
|
|
# 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 (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)
|
|
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 ()
|
|
|
|
# Include the RPC utilities from the `libc` project.
|
|
if (TARGET llvm-libc-common-utilities)
|
|
set(extra_deps llvm-libc-common-utilities)
|
|
endif()
|
|
|
|
# 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)
|
|
|
|
# Create selected library types.
|
|
if (build_object)
|
|
add_library("${name_object}" OBJECT ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
|
|
target_link_libraries(${name_object} PRIVATE ${extra_deps})
|
|
set_target_properties(${name_object} PROPERTIES
|
|
POSITION_INDEPENDENT_CODE ON
|
|
FOLDER "Flang-RT/Object 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})
|
|
target_link_libraries("${name_static}" PRIVATE flang-rt-libcxx-headers flang-rt-libc-headers flang-rt-libc-static ${extra_deps})
|
|
endif ()
|
|
if (build_shared)
|
|
add_library("${name_shared}" SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
|
|
target_link_libraries("${name_shared}" PRIVATE flang-rt-libcxx-headers flang-rt-libc-headers flang-rt-libc-shared ${extra_deps})
|
|
if (Threads_FOUND)
|
|
target_link_libraries(${name_shared} PUBLIC Threads::Threads)
|
|
endif ()
|
|
|
|
# Special dependencies handling for shared libraries only:
|
|
#
|
|
# flang-rt libraries must not depend on libc++/libstdc++,
|
|
# so set the linker language to C to avoid the unnecessary
|
|
# library dependence. Note that libc++/libstdc++ may still
|
|
# come through CMAKE_CXX_IMPLICIT_LINK_LIBRARIES.
|
|
set_target_properties(${name_shared} PROPERTIES LINKER_LANGUAGE C)
|
|
# Use --as-needed to avoid unnecessary dependencies.
|
|
if (LINKER_AS_NEEDED_OPT)
|
|
target_link_options(${name_shared} BEFORE PRIVATE
|
|
"${LINKER_AS_NEEDED_OPT}"
|
|
)
|
|
endif()
|
|
endif ()
|
|
|
|
if (libtargets)
|
|
# Provide a default alias which exists in either setting.
|
|
if (BUILD_SHARED_LIBS)
|
|
if (build_shared)
|
|
set(default_target "${name_shared}")
|
|
else ()
|
|
set(default_target "${name_static}")
|
|
endif ()
|
|
else ()
|
|
if (build_static)
|
|
set(default_target "${name_static}")
|
|
else ()
|
|
set(default_target "${name_shared}")
|
|
endif ()
|
|
endif ()
|
|
add_library(${name}.default ALIAS "${default_target}")
|
|
|
|
# Provide a build target that builds any enabled library.
|
|
# Not intended for target_link_libraries. Either use the ${name}.static,
|
|
# ${name}.shared variants, or ${name}.default to let BUILD_SHARED_LIBS
|
|
# decide.
|
|
if (NOT TARGET ${name})
|
|
add_custom_target(${name})
|
|
add_dependencies(${name} ${libtargets})
|
|
endif ()
|
|
endif ()
|
|
|
|
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 ()
|
|
|
|
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 ()
|
|
|
|
set(TARGET_FLAGS)
|
|
if(APPLE)
|
|
set(DARWIN_EMBEDDED_PLATFORMS)
|
|
set(DARWIN_osx_BUILTIN_MIN_VER 10.7)
|
|
set(DARWIN_osx_BUILTIN_MIN_VER_FLAG
|
|
-mmacosx-version-min=${DARWIN_osx_BUILTIN_MIN_VER})
|
|
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)
|
|
|
|
# When building the flang runtime if LTO is enabled the archive file
|
|
# contains LLVM IR rather than object code. Currently flang is not
|
|
# LTO aware so cannot link this file to compiled Fortran code.
|
|
if (FLANG_RT_HAS_FNO_LTO_FLAG)
|
|
target_compile_options(${tgtname} PRIVATE -fno-lto)
|
|
endif ()
|
|
|
|
# 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 -funwind-tables -fno-asynchronous-unwind-tables>
|
|
)
|
|
|
|
# Include header at the top of all compilation units to avoid dependency
|
|
# on the C++ STL (libstdc++ or libc++).
|
|
target_compile_options(${tgtname} PRIVATE
|
|
"$<$<COMPILE_LANGUAGE:CXX>:-include${FLANG_RT_SOURCE_DIR}/lib/runtime/stl-overrides.h>"
|
|
)
|
|
elseif (MSVC)
|
|
target_compile_options(${tgtname} PRIVATE
|
|
$<$<COMPILE_LANGUAGE:CXX>:/EHs-c- /GR->
|
|
)
|
|
|
|
# Include header at the top of all compilation units to avoid dependency
|
|
# on the C++ STL (libstdc++ or libc++).
|
|
target_compile_options(${tgtname} PRIVATE
|
|
"$<$<COMPILE_LANGUAGE:CXX>:/FI${FLANG_RT_SOURCE_DIR}/lib/runtime/stl-overrides.h>"
|
|
)
|
|
elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL")
|
|
target_compile_options(${tgtname} PRIVATE
|
|
$<$<COMPILE_LANGUAGE:CXX>:-qnoeh -qnortti>
|
|
)
|
|
|
|
# Include header at the top of all compilation units to avoid dependency
|
|
# on the C++ STL (libstdc++ or libc++).
|
|
target_compile_options(${tgtname} PRIVATE
|
|
"$<$<COMPILE_LANGUAGE:CXX>:-qinclude=${FLANG_RT_SOURCE_DIR}/lib/runtime/stl-overrides.h>"
|
|
)
|
|
endif ()
|
|
|
|
# Add target specific options if necessary.
|
|
if ("${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^amdgcn")
|
|
target_compile_options(${tgtname} PRIVATE
|
|
$<$<COMPILE_LANGUAGE:CXX>:-nogpulib -flto -fvisibility=hidden>
|
|
)
|
|
elseif ("${LLVM_DEFAULT_TARGET_TRIPLE}" MATCHES "^nvptx")
|
|
target_compile_options(${tgtname} PRIVATE
|
|
$<$<COMPILE_LANGUAGE:CXX>:-nogpulib -flto -fvisibility=hidden -Wno-unknown-cuda-version --cuda-feature=+ptx63>
|
|
)
|
|
elseif (APPLE)
|
|
# Clang on Darwin enables non-POSIX extensions by default.
|
|
# This causes some macros to leak, such as HUGE from <math.h>, which
|
|
# causes some conflicts with Flang symbols (but not with Flang-RT, for
|
|
# now).
|
|
# It also causes some Flang-RT extensions to be disabled, such as fdate,
|
|
# that checks for _POSIX_C_SOURCE.
|
|
# Setting _POSIX_C_SOURCE avoids these issues.
|
|
target_compile_options(${tgtname} PRIVATE
|
|
$<$<COMPILE_LANGUAGE:CXX>:${DARWIN_osx_BUILTIN_MIN_VER_FLAG} -D_POSIX_C_SOURCE=200809>
|
|
)
|
|
endif ()
|
|
|
|
# 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 ()
|
|
|
|
# Flang-RT's public headers
|
|
target_include_directories(${tgtname} PUBLIC "${FLANG_RT_SOURCE_DIR}/include")
|
|
|
|
# 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} PUBLIC "${FLANG_SOURCE_DIR}/include")
|
|
|
|
# For Flang-RT's configured config.h to be found
|
|
target_include_directories(${tgtname} PRIVATE "${FLANG_RT_BINARY_DIR}")
|
|
|
|
# Disable libstdc++/libc++ assertions, even in an LLVM_ENABLE_ASSERTIONS
|
|
# build, to avoid an unwanted dependency on libstdc++/libc++.so.
|
|
target_compile_definitions(${tgtname} PUBLIC _GLIBCXX_NO_ASSERTIONS)
|
|
if (FLANG_RT_SUPPORTS_UNDEFINE_FLAG)
|
|
target_compile_options(${tgtname} PUBLIC
|
|
"$<$<COMPILE_LANGUAGE:CXX>:-Wp,-U_GLIBCXX_ASSERTIONS>")
|
|
target_compile_options(${tgtname} PUBLIC
|
|
"$<$<COMPILE_LANGUAGE:CXX>:-Wp,-U_LIBCPP_ENABLE_ASSERTIONS>")
|
|
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 ()
|
|
|
|
if (ARG_INCLUDE_DIRECTORIES)
|
|
target_include_directories(${tgtname} ${ARG_INCLUDE_DIRECTORIES})
|
|
endif ()
|
|
|
|
if (ARG_LINK_LIBRARIES)
|
|
target_link_libraries(${tgtname} PUBLIC ${ARG_LINK_LIBRARIES})
|
|
endif ()
|
|
endforeach ()
|
|
|
|
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)
|
|
# FIXME: RUNTIMES_OUTPUT_RESOURCE_LIB_DIR is not a good location for
|
|
# shared libraries because it is not a ld.so default search path.
|
|
# Also, the machine where the executable is eventually executed may
|
|
# not be one where the compiler is installed, so even RPATH/RUNPATH
|
|
# will not help. The most appropriate location for shared libraries
|
|
# is /usr/lib/<triple>/lib<name>.so, like e.g. libgcc_s.so.
|
|
# Flang-RT also would require a library versioning scheme so
|
|
# executables compiled with different versions of Flang either use
|
|
# matching versions of Flang-RT, or use a newer backward-compatible
|
|
# version. Currently, Flang-RT has no ABI backwards-compatibility
|
|
# policy.
|
|
# Currently, we just emit it into RUNTIMES_OUTPUT_RESOURCE_LIB_DIR
|
|
# like the static library, which is already in the driver's and
|
|
# linker's search path.
|
|
set_target_properties(${tgtname}
|
|
PROPERTIES
|
|
ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
|
|
LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
|
|
)
|
|
|
|
install(TARGETS ${tgtname}
|
|
ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
|
|
LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
|
|
)
|
|
endif ()
|
|
|
|
if (ARG_TARGET_PROPERTIES)
|
|
set_target_properties(${tgtname} PROPERTIES ${ARG_TARGET_PROPERTIES})
|
|
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)
|