Skip to content

[Flang-RT] Build libflang_rt.so #120213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions flang-rt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand All @@ -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
""
Expand Down
291 changes: 190 additions & 101 deletions flang-rt/cmake/modules/AddFlangRT.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -44,131 +45,219 @@ 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 ()

# 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)
8 changes: 4 additions & 4 deletions flang-rt/cmake/modules/AddFlangRTOffload.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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()

Expand Down
Loading
Loading