[llvm-branch-commits] [llvm] [Flang-RT] Build libflang_rt.so (PR #120213)

Michael Kruse via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jan 6 07:31:30 PST 2025


https://github.com/Meinersbur updated https://github.com/llvm/llvm-project/pull/120213

>From 7e252f1a64e12ac04706175cabc303076d9e973f Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Tue, 17 Dec 2024 12:00:38 +0100
Subject: [PATCH 1/5] Add FLANG_RT_ENABLE_STATIC and _SHARED

---
 flang-rt/CMakeLists.txt                 |  14 +++
 flang-rt/cmake/modules/AddFlangRT.cmake | 123 ++++++++++++++++++++----
 2 files changed, 117 insertions(+), 20 deletions(-)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 1d7b241adea89c..48169673ad772f 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -115,6 +115,20 @@ endif ()
 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 ()
+  option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." ON)
+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 6e55a0d115713d..e20622b7039785 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -38,42 +38,124 @@ function (add_flangrt_library name)
     ${ARGN})
 
   if (ARG_INSTALL_WITH_TOOLCHAIN AND ARG_EXCLUDE_FROM_ALL)
-     message(SEND_ERROR "add_flangrt_library(${name} ...):
+    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.
-     ")
+      ")
+    return ()
   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)
+  #if (ARG_CMAKE_CONFIGURABLE AND (ARG_STATIC OR ARG_SHARED))
+  #  message(SEND_ERROR "add_flangrt_library(${name} ...):
+  #     CMAKE_CONFIGURABLE cannot be used together with STATIC or SHARED.
+  #    ")
+  #  return ()
+  #endif ()
+
+  #if (NOT ARG_STATIC AND NOT ARG_SHARED AND NOT ARG_CMAKE_CONFIGURABLE AND NOT ARG_OBJECT)
+  #  message(SEND_ERROR "add_flangrt_library(${name} ...):
+  #     Must specifiy library type.
+  #    ")
+  #  return ()
+  #endif () 
+
+  set(build_static OFF)
+  set(build_shared OFF)
+  if (ARG_STATIC AND FLANG_RT_ENABLE_STATIC)
+    set(build_static ON)
+  endif ()
+  if (ARG_SHARED AND FLANG_RT_ENABLE_SHARED)
+    set(build_shared ON)
+  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 ()
 
-  # Forward libtype to add_library
-  set(extra_args "")
-  if (ARG_SHARED)
-    list(APPEND extra_args SHARED)
+  # Name of targets must only depend on function arguments to be predictable for callers.
+  if (ARG_STATIC AND ARG_SHARED)
+    set(name_static "${name}.static")
+    set(name_shared "${name}.shared")
+  else ()
+    set(name_static "${name}")
+    set(name_shared "${name}")
   endif ()
-  if (ARG_STATIC)
-    list(APPEND extra_args STATIC)
+  if (ARG_OBJECT AND NOT ARG_STATIC AND NOT ARG_SHARED)
+    set(name_object "${name}")
+  else ()
+    set(name_object "obj.${name}")
   endif ()
-  if (ARG_OBJECT)
-    list(APPEND extra_args OBJECT)
+
+
+  if (ARG_OBJECT AND NOT build_static AND NOT build_shared)
+    set(build_only_objectlib ON)
+  else ()
+    set(build_only_objectlib OFF)
   endif ()
+  if (build_only_objectlib OR (build_static AND build_shared))
+    set(need_objectlib ON)
+  else ()
+    set(need_objectlib OFF)
+  endif ()
+
+  if (NOT build_static AND NOT build_shared AND NOT need_objectlib)
+    # Nothing to build
+    return ()
+  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)
+
+  set(extra_args "")
   if (ARG_EXCLUDE_FROM_ALL)
     list(APPEND extra_args EXCLUDE_FROM_ALL)
   endif ()
 
-  add_library(${name} ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
 
-  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")
+  if (need_objectlib)
+    add_library(${name_object} OBJECT ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
+    set_target_properties(${name_object} PROPERTIES 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:${objectlib_name}>)
+    set(srctargets ${name_object})
+    set(liblist nostargets)
+    set(alltargets ${name_object})
   else ()
-    set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Libraries")
+    set(liblist srctargets)
+    set(alltargets)
+  endif ()
+
+  set(libtargets "")
+  if (build_static)
+    add_library(${name_static} STATIC ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
+    list(APPEND alltargets ${name_static})
+    list(APPEND libtargets ${name_static})
+    list(APPEND ${liblist} ${name_static})
   endif ()
+  if (build_shared)
+    add_library(${name_shared} SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
+    list(APPEND alltargets ${name_shared})
+    list(APPEND libtargets ${name_shared})
+    list(APPEND ${liblist} ${name_shared})
+  endif ()
+
+  foreach (name IN LISTS libtargets)
+    if (ARG_INSTALL_WITH_TOOLCHAIN)
+      set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Toolchain Libraries")
+    else ()
+      set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Libraries")
+    endif ()
+  endforeach ()
+
+  foreach (name IN LISTS alltargets)
+    # 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)
 
-  # 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)
 
   # Use compiler-specific options to disable exceptions and RTTI.
   if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
@@ -163,4 +245,5 @@ function (add_flangrt_library name)
   if (NOT ARG_EXCLUDE_FROM_ALL)
     add_dependencies(flang-rt ${name})
   endif ()
+  endforeach ()
 endfunction (add_flangrt_library)

>From df2578a479d6370def88ec2caf7fe71ce272b17c Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 23 Dec 2024 15:24:46 +0100
Subject: [PATCH 2/5] Finalize FLANG_RT_ENABLE_SHARED

---
 flang-rt/CMakeLists.txt                       |   3 +-
 flang-rt/cmake/modules/AddFlangRT.cmake       | 304 +++++++++---------
 .../lib/FortranFloat128Math/CMakeLists.txt    |  10 +-
 flang-rt/lib/Testing/CMakeLists.txt           |  11 +-
 flang-rt/unittests/CMakeLists.txt             |   8 +-
 5 files changed, 175 insertions(+), 161 deletions(-)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index d75a5f2876f212..e8a4922f737b6a 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -142,7 +142,8 @@ else ()
   option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." ON)
 endif ()
 if (NOT FLANG_RT_ENABLE_STATIC AND NOT FLANG_RT_ENABLE_SHARED)
-  message(FATAL_ERROR "Must build at least one type of library
+  message(FATAL_ERROR "
+      Must build at least one type of library
       (FLANG_RT_ENABLE_STATIC=ON, FLANG_RT_ENABLE_SHARED=ON, or both)
     ")
 endif ()
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index c1e9aa938eb2c2..d8f56ccd1dae0f 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
@@ -42,30 +43,35 @@ function (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.
       ")
-    return ()
   endif ()
 
-  #if (ARG_CMAKE_CONFIGURABLE AND (ARG_STATIC OR ARG_SHARED))
-  #  message(SEND_ERROR "add_flangrt_library(${name} ...):
-  #     CMAKE_CONFIGURABLE cannot be used together with STATIC or SHARED.
-  #    ")
-  #  return ()
-  #endif ()
-
-  #if (NOT ARG_STATIC AND NOT ARG_SHARED AND NOT ARG_CMAKE_CONFIGURABLE AND NOT ARG_OBJECT)
-  #  message(SEND_ERROR "add_flangrt_library(${name} ...):
-  #     Must specifiy library type.
-  #    ")
-  #  return ()
-  #endif () 
-
-  set(build_static OFF)
-  set(build_shared OFF)
-  if (ARG_STATIC AND FLANG_RT_ENABLE_STATIC)
-    set(build_static ON)
+  # 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 ()
-  if (ARG_SHARED AND FLANG_RT_ENABLE_SHARED)
-    set(build_shared ON)
+
+  # 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)
@@ -75,73 +81,61 @@ function (add_flangrt_library name)
     endif ()
   endif ()
 
-  # Name of targets must only depend on function arguments to be predictable for callers.
-  if (ARG_STATIC AND ARG_SHARED)
-    set(name_static "${name}.static")
-    set(name_shared "${name}.shared")
-  else ()
-    set(name_static "${name}")
-    set(name_shared "${name}")
-  endif ()
-  if (ARG_OBJECT AND NOT ARG_STATIC AND NOT ARG_SHARED)
-    set(name_object "${name}")
-  else ()
-    set(name_object "obj.${name}")
+  # 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 ()
 
-
-  if (ARG_OBJECT AND NOT build_static AND NOT build_shared)
-    set(build_only_objectlib ON)
-  else ()
-    set(build_only_objectlib OFF)
+  # srctargets: targets that contain source files
+  # libtargets: static/shared if they are built
+  # alltargets: static/shared/object if they are built
+  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_only_objectlib OR (build_static AND build_shared))
-    set(need_objectlib ON)
-  else ()
-    set(need_objectlib OFF)
+  if (build_shared)
+    list(APPEND srctargets "${name_shared}")
+    list(APPEND libtargets "${name_shared}")
+    list(APPEND alltargets "${name_shared}")
   endif ()
-
-  if (NOT build_static AND NOT build_shared AND NOT need_objectlib)
-    # Nothing to build
-    return ()
+  if (build_object)
+    set(srctargets "${name_object}")
+    list(APPEND alltargets "${name_object}")
   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)
-
   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)
 
-  if (need_objectlib)
+  # 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 FOLDER "Flang-RT/Object Libraries")
+    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
+    # Replace arguments for the libraries we are going to create.
     set(ARG_ADDITIONAL_HEADERS "")
-    set(ARG_UNPARSED_ARGUMENTS $<TARGET_OBJECTS:${objectlib_name}>)
-    set(srctargets ${name_object})
-    set(liblist nostargets)
-    set(alltargets ${name_object})
-  else ()
-    set(liblist srctargets)
-    set(alltargets)
+    set(ARG_UNPARSED_ARGUMENTS "$<TARGET_OBJECTS:${objectlib_name}>")
   endif ()
-
-  set(libtargets "")
   if (build_static)
     add_library(${name_static} STATIC ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
-    list(APPEND alltargets ${name_static})
-    list(APPEND libtargets ${name_static})
-    list(APPEND ${liblist} ${name_static})
   endif ()
   if (build_shared)
     add_library(${name_shared} SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
-    list(APPEND alltargets ${name_shared})
-    list(APPEND libtargets ${name_shared})
-    list(APPEND ${liblist} ${name_shared})
   endif ()
 
   foreach (name IN LISTS libtargets)
@@ -152,98 +146,114 @@ function (add_flangrt_library name)
     endif ()
   endforeach ()
 
+  # 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 (name IN LISTS alltargets)
     # 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)
 
+    # 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 ()
 
-  # 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 ()
-
-  # 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 ()
+    # 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 ()
 
-  # Flang-rt's public headers
-  target_include_directories(${name} PRIVATE "${FLANG_RT_SOURCE_DIR}/include")
+    # Flang-RT's public headers
+    target_include_directories(${name} PRIVATE "${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(${name} PRIVATE "${FLANG_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(${name} PRIVATE "${FLANG_SOURCE_DIR}/include")
 
-  # For Flang-RT's configured config.h to be found
-  target_include_directories(${name} PRIVATE "${FLANG_RT_BINARY_DIR}")
+    # For Flang-RT's configured config.h to be found
+    target_include_directories(${name} 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.
-  if (FLANG_RT_SUPPORTS_UNDEFINE_FLAG)
-    target_compile_options(${name} PUBLIC -U_GLIBCXX_ASSERTIONS)
-    target_compile_options(${name} PUBLIC -U_LIBCPP_ENABLE_ASSERTIONS)
-  endif ()
+    # 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 ()
 
-  # Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI
-  # should only depend on msv(u)crt. 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") AND FLANG_RT_BUILTINS_LIBRARY)
-    target_compile_options(${name} PRIVATE "$<$<COMPILE_LANGUAGE:CXX,C>:-Xclang>$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}")
-  endif ()
+    # 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>" "--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(${name} PRIVATE "$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "--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.")
+      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(${name} PUBLIC ${llvm_libs})
+      target_include_directories(${name} 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
-        LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
-        ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
-        RUNTIME_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
-      )
+  foreach (name 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(${name}
+        PROPERTIES
+          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
+          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
+          RUNTIME_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
+        )
 
-    install(TARGETS ${name}
-        LIBRARY DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
-        ARCHIVE DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
-        RUNTIME DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
-      )
-  endif ()
+      install(TARGETS ${name}
+          LIBRARY DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
+          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
+          RUNTIME DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
+        )
+    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 ${name})
+    endif ()
   endforeach ()
 endfunction (add_flangrt_library)
diff --git a/flang-rt/lib/FortranFloat128Math/CMakeLists.txt b/flang-rt/lib/FortranFloat128Math/CMakeLists.txt
index 881f5f9d8212d4..c0b2ee32248f87 100644
--- a/flang-rt/lib/FortranFloat128Math/CMakeLists.txt
+++ b/flang-rt/lib/FortranFloat128Math/CMakeLists.txt
@@ -96,16 +96,16 @@ if (FLANG_RUNTIME_F128_MATH_LIB)
 
   if (WIN32)
     # Do not create a FortranFloat128Math library under Windows, the Flang
-    # driver never links it. Instead, add the sources to the flang_rt itself.
+    # driver never links it. Instead, add the sources to flang_rt itself.
     target_sources(FortranFloat128MathILib INTERFACE ${sources})
     target_compile_definitions(FortranFloat128MathILib INTERFACE HAS_QUADMATHLIB)
   else ()
     add_flangrt_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN
       ${sources})
-   endif ()
-   target_include_directories(FortranFloat128Math PRIVATE
-     "${FLANG_RT_SOURCE_DIR}/lib/flang_rt"
-     )
+    target_include_directories(FortranFloat128Math PRIVATE
+        "${FLANG_RT_SOURCE_DIR}/lib/flang_rt"
+      )
+  endif ()
 elseif (HAVE_LDBL_MANT_DIG_113)
   # We can use 'long double' versions from libc.
   check_library_exists(m sinl "" FOUND_LIBM)
diff --git a/flang-rt/lib/Testing/CMakeLists.txt b/flang-rt/lib/Testing/CMakeLists.txt
index bdfca0ee9d3f23..19c20ad44c0251 100644
--- a/flang-rt/lib/Testing/CMakeLists.txt
+++ b/flang-rt/lib/Testing/CMakeLists.txt
@@ -12,8 +12,9 @@ file(GLOB_RECURSE public_headers
 )
 
 add_flangrt_library(NonGTestTesting EXCLUDE_FROM_ALL LINK_TO_LLVM
-  ${FLANG_SOURCE_DIR}/lib/Testing/testing.cpp
-  ${FLANG_SOURCE_DIR}/lib/Testing/fp-testing.cpp
- ADDITIONAL_HEADERS
-   ${public_headers}
-)
+      ${FLANG_SOURCE_DIR}/lib/Testing/testing.cpp
+      ${FLANG_SOURCE_DIR}/lib/Testing/fp-testing.cpp
+
+    ADDITIONAL_HEADERS
+      ${public_headers}
+  )
diff --git a/flang-rt/unittests/CMakeLists.txt b/flang-rt/unittests/CMakeLists.txt
index 203ce42c33034b..4d852d3f19f9b5 100644
--- a/flang-rt/unittests/CMakeLists.txt
+++ b/flang-rt/unittests/CMakeLists.txt
@@ -10,7 +10,7 @@
 # output. Therefore it also needs to include files from LLVM. Unfortunately,
 # LLVM/GTest doesn't add the include search path itself. Limiting the scope
 # using target_include_directories does not work because with
-# LLVM_INSTALL_GTEST=ON, llvm_gtest is an IMPORT library.
+# LLVM_INSTALL_GTEST=ON, as llvm_gtest is an IMPORT library.
 include_directories("${LLVM_INCLUDE_DIR}" "${LLVM_MAIN_INCLUDE_DIR}")
 
 # Add GTest if not already present.
@@ -94,8 +94,10 @@ function(add_flangrt_nongtest_unittest test_name)
   add_executable(${test_name}${suffix} ${ARG_UNPARSED_ARGUMENTS})
   set_target_properties(${test_name}${suffix} PROPERTIES FOLDER "Flang-RT/Tests/Unit")
 
-  target_include_directories(${test_name}${suffix} PRIVATE "${FLANG_RT_SOURCE_DIR}/include")
-  target_include_directories(${test_name}${suffix} PRIVATE "${FLANG_SOURCE_DIR}/include")
+  target_include_directories(${test_name}${suffix} PRIVATE
+      "${FLANG_RT_SOURCE_DIR}/include"
+      "${FLANG_SOURCE_DIR}/include"
+    )
   target_link_libraries(${test_name}${suffix} PRIVATE NonGTestTesting ${ARG_LINK_LIBS})
 
   if(NOT ARG_SLOW_TEST)

>From ad1e6507b001e40a0912e24c53f25d6064c15fcb Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 23 Dec 2024 16:12:33 +0100
Subject: [PATCH 3/5] Backport from flang_runtime_shared

---
 flang-rt/cmake/modules/AddFlangRT.cmake       | 22 ++++++++++++++-----
 .../lib/FortranFloat128Math/CMakeLists.txt    | 10 ++++-----
 flang-rt/lib/Testing/CMakeLists.txt           | 11 +++++-----
 flang-rt/unittests/CMakeLists.txt             |  8 ++++---
 4 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 58870da9bb3688..2b1ee07c574bfd 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -103,7 +103,7 @@ function (add_flangrt_library name)
       )
   endif ()
 
-  # Flang-rt's public headers
+  # Flang-RT's public headers
   target_include_directories(${name} PRIVATE "${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")
@@ -121,12 +121,24 @@ function (add_flangrt_library name)
   endif ()
 
   # Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI
-  # should only depend on msv(u)crt. LLVM still emits libgcc/compiler-rt
+  # 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") AND FLANG_RT_BUILTINS_LIBRARY)
-    target_compile_options(${name} PRIVATE "$<$<COMPILE_LANGUAGE:CXX,C>:-Xclang>$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}")
+  if (MSVC AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    if (FLANG_RT_BUILTINS_LIBRARY)
+      target_compile_options(${name} PRIVATE "$<$<COMPILE_LANGUAGE:CXX,C>:-Xclang>" "--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(${name} PRIVATE "$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "--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.")
+    endif ()
   endif ()
 
   # Non-GTest unittests depend on LLVMSupport
@@ -158,7 +170,7 @@ function (add_flangrt_library name)
       )
   endif ()
 
-  # flang-rt should build all the flang-rt targets that are built in an
+  # 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})
diff --git a/flang-rt/lib/FortranFloat128Math/CMakeLists.txt b/flang-rt/lib/FortranFloat128Math/CMakeLists.txt
index 881f5f9d8212d4..c0b2ee32248f87 100644
--- a/flang-rt/lib/FortranFloat128Math/CMakeLists.txt
+++ b/flang-rt/lib/FortranFloat128Math/CMakeLists.txt
@@ -96,16 +96,16 @@ if (FLANG_RUNTIME_F128_MATH_LIB)
 
   if (WIN32)
     # Do not create a FortranFloat128Math library under Windows, the Flang
-    # driver never links it. Instead, add the sources to the flang_rt itself.
+    # driver never links it. Instead, add the sources to flang_rt itself.
     target_sources(FortranFloat128MathILib INTERFACE ${sources})
     target_compile_definitions(FortranFloat128MathILib INTERFACE HAS_QUADMATHLIB)
   else ()
     add_flangrt_library(FortranFloat128Math STATIC INSTALL_WITH_TOOLCHAIN
       ${sources})
-   endif ()
-   target_include_directories(FortranFloat128Math PRIVATE
-     "${FLANG_RT_SOURCE_DIR}/lib/flang_rt"
-     )
+    target_include_directories(FortranFloat128Math PRIVATE
+        "${FLANG_RT_SOURCE_DIR}/lib/flang_rt"
+      )
+  endif ()
 elseif (HAVE_LDBL_MANT_DIG_113)
   # We can use 'long double' versions from libc.
   check_library_exists(m sinl "" FOUND_LIBM)
diff --git a/flang-rt/lib/Testing/CMakeLists.txt b/flang-rt/lib/Testing/CMakeLists.txt
index bdfca0ee9d3f23..19c20ad44c0251 100644
--- a/flang-rt/lib/Testing/CMakeLists.txt
+++ b/flang-rt/lib/Testing/CMakeLists.txt
@@ -12,8 +12,9 @@ file(GLOB_RECURSE public_headers
 )
 
 add_flangrt_library(NonGTestTesting EXCLUDE_FROM_ALL LINK_TO_LLVM
-  ${FLANG_SOURCE_DIR}/lib/Testing/testing.cpp
-  ${FLANG_SOURCE_DIR}/lib/Testing/fp-testing.cpp
- ADDITIONAL_HEADERS
-   ${public_headers}
-)
+      ${FLANG_SOURCE_DIR}/lib/Testing/testing.cpp
+      ${FLANG_SOURCE_DIR}/lib/Testing/fp-testing.cpp
+
+    ADDITIONAL_HEADERS
+      ${public_headers}
+  )
diff --git a/flang-rt/unittests/CMakeLists.txt b/flang-rt/unittests/CMakeLists.txt
index 203ce42c33034b..4d852d3f19f9b5 100644
--- a/flang-rt/unittests/CMakeLists.txt
+++ b/flang-rt/unittests/CMakeLists.txt
@@ -10,7 +10,7 @@
 # output. Therefore it also needs to include files from LLVM. Unfortunately,
 # LLVM/GTest doesn't add the include search path itself. Limiting the scope
 # using target_include_directories does not work because with
-# LLVM_INSTALL_GTEST=ON, llvm_gtest is an IMPORT library.
+# LLVM_INSTALL_GTEST=ON, as llvm_gtest is an IMPORT library.
 include_directories("${LLVM_INCLUDE_DIR}" "${LLVM_MAIN_INCLUDE_DIR}")
 
 # Add GTest if not already present.
@@ -94,8 +94,10 @@ function(add_flangrt_nongtest_unittest test_name)
   add_executable(${test_name}${suffix} ${ARG_UNPARSED_ARGUMENTS})
   set_target_properties(${test_name}${suffix} PROPERTIES FOLDER "Flang-RT/Tests/Unit")
 
-  target_include_directories(${test_name}${suffix} PRIVATE "${FLANG_RT_SOURCE_DIR}/include")
-  target_include_directories(${test_name}${suffix} PRIVATE "${FLANG_SOURCE_DIR}/include")
+  target_include_directories(${test_name}${suffix} PRIVATE
+      "${FLANG_RT_SOURCE_DIR}/include"
+      "${FLANG_SOURCE_DIR}/include"
+    )
   target_link_libraries(${test_name}${suffix} PRIVATE NonGTestTesting ${ARG_LINK_LIBS})
 
   if(NOT ARG_SLOW_TEST)

>From 8e18401fd9ec2270be3044713d7a740116764410 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 2 Jan 2025 12:27:29 +0100
Subject: [PATCH 4/5] WIP

---
 flang-rt/CMakeLists.txt                       |  25 +-
 flang-rt/cmake/modules/AddFlangRT.cmake       |  70 ++---
 flang-rt/cmake/modules/GetToolchainDirs.cmake | 279 ++++++++++--------
 flang-rt/lib/flang_rt/CMakeLists.txt          |  16 +-
 flang-rt/test/CMakeLists.txt                  |   2 +-
 flang-rt/test/Runtime/no-cpp-dep.c            |   2 +-
 flang-rt/test/lit.cfg.py                      |   4 +-
 7 files changed, 219 insertions(+), 179 deletions(-)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index e8a4922f737b6a..1c20876dd07bfe 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -88,7 +88,6 @@ set(LLVM_TOOLS_DIR "${LLVM_BINARY_DIR}/bin")
 # Determine build and install paths.
 # The build path is absolute, but the install dir is relative, CMake's install
 # command has to apply CMAKE_INSTALL_PREFIX itself.
-get_toolchain_library_subdir(toolchain_lib_subdir)
 if (LLVM_TREE_AVAILABLE)
   # In a bootstrap build emit the libraries into a default search path in the
   # build directory of the just-built compiler. This allows using the
@@ -99,8 +98,6 @@ if (LLVM_TREE_AVAILABLE)
   include(GetClangResourceDir)
   get_clang_resource_dir(FLANG_RT_OUTPUT_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
   get_clang_resource_dir(FLANG_RT_INSTALL_PATH)
-
-  extend_path(FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${toolchain_lib_subdir}")
 else ()
   # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
   # read-only and/or shared by multiple runtimes with different build
@@ -108,20 +105,30 @@ else ()
   # non-toolchain library.
   # For the install prefix, still use the resource dir assuming that Flang will
   # be installed there using the same prefix. This is to not have a difference
- # between bootstrap and standalone runtimes builds.
+  # between bootstrap and standalone runtimes builds.
   set(FLANG_RT_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
   set(FLANG_RT_INSTALL_PATH "${CMAKE_INSTALL_LIBDIR}/clang/${LLVM_VERSION_MAJOR}")
-
-  extend_path(FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${CMAKE_INSTALL_LIBDIR}")
 endif ()
+cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_DIR)
+cmake_path(NORMAL_PATH FLANG_RT_INSTALL_PATH)
 
-# Apply the arch-specific library dir with the resource dir.
+# Determine subdirectories for build output and install destinations.
+get_toolchain_library_subdir(toolchain_lib_subdir)
+get_system_library_subdir(arch_lib_subdir)
+extend_path(FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${toolchain_lib_subdir}")
+if (LLVM_TREE_AVAILABLE)
+  extend_path(FLANG_RT_BUILD_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${arch_lib_subdir}")
+else ()
+  # Only building for a single target, so no need to write into a arch-specific subirectory.
+  extend_path(FLANG_RT_BUILD_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${CMAKE_INSTALL_LIBDIR}")
+endif ()
 extend_path(FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR "${FLANG_RT_INSTALL_PATH}" "${toolchain_lib_subdir}")
+extend_path(FLANG_RT_INSTALL_LIB_DIR "${FLANG_RT_INSTALL_PATH}" "${arch_lib_subdir}")
 
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_PATH)
 cmake_path(NORMAL_PATH FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR)
+cmake_path(NORMAL_PATH FLANG_RT_BUILD_LIB_DIR)
 cmake_path(NORMAL_PATH FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR)
+cmake_path(NORMAL_PATH FLANG_RT_INSTALL_LIB_DIR)
 
 
 #################
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index d8f56ccd1dae0f..63f694eb77bd6c 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -92,7 +92,7 @@ function (add_flangrt_library name)
 
   # srctargets: targets that contain source files
   # libtargets: static/shared if they are built
-  # alltargets: static/shared/object if they are built
+  # alltargets: any add_library target added by this function
   set(srctargets "")
   set(libtargets "")
   set(alltargets "")
@@ -121,7 +121,7 @@ function (add_flangrt_library name)
 
   # Create selected library types.
   if (build_object)
-    add_library(${name_object} OBJECT ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
+    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"
@@ -129,41 +129,47 @@ function (add_flangrt_library name)
 
     # Replace arguments for the libraries we are going to create.
     set(ARG_ADDITIONAL_HEADERS "")
-    set(ARG_UNPARSED_ARGUMENTS "$<TARGET_OBJECTS:${objectlib_name}>")
+    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})
+    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})
+    add_library("${name_shared}" SHARED ${extra_args} ${ARG_ADDITIONAL_HEADERS} ${ARG_UNPARSED_ARGUMENTS})
   endif ()
 
-  foreach (name IN LISTS libtargets)
+  foreach (tgtname IN LISTS libtargets)
+    if (NOT WIN32)
+      # Use same stem name for .a and .so. Common in UNIX environments. Not
+      # allowed with Windows.
+      set_target_properties(${tgtname} PROPERTIES OUTPUT_NAME "${name}")
+    endif ()
+
     if (ARG_INSTALL_WITH_TOOLCHAIN)
-      set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Toolchain Libraries")
+      set_target_properties(${tgtname} PROPERTIES FOLDER "Flang-RT/Toolchain Libraries")
     else ()
-      set_target_properties(${name} PROPERTIES FOLDER "Flang-RT/Libraries")
+      set_target_properties(${tgtname} PROPERTIES FOLDER "Flang-RT/Libraries")
     endif ()
   endforeach ()
 
   # 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 (name IN LISTS alltargets)
+  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(${name} PRIVATE cxx_std_17)
+    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(${name} PRIVATE
+      target_compile_options(${tgtname} PRIVATE
           $<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-unwind-tables -fno-asynchronous-unwind-tables>
         )
     elseif (MSVC)
-      target_compile_options(${name} PRIVATE
+      target_compile_options(${tgtname} PRIVATE
           $<$<COMPILE_LANGUAGE:CXX>:/EHs-c- /GR->
         )
     elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL")
-      target_compile_options(${name} PRIVATE
+      target_compile_options(${tgtname} PRIVATE
           $<$<COMPILE_LANGUAGE:CXX>:-qnoeh -qnortti>
         )
     endif ()
@@ -171,31 +177,31 @@ function (add_flangrt_library name)
     # 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
+      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(${name} PRIVATE
+      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(${name} PRIVATE "${FLANG_RT_SOURCE_DIR}/include")
+    target_include_directories(${tgtname} PRIVATE "${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(${name} PRIVATE "${FLANG_SOURCE_DIR}/include")
+    target_include_directories(${tgtname} PRIVATE "${FLANG_SOURCE_DIR}/include")
 
     # For Flang-RT's configured config.h to be found
-    target_include_directories(${name} PRIVATE "${FLANG_RT_BINARY_DIR}")
+    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.
     if (FLANG_RT_SUPPORTS_UNDEFINE_FLAG)
-      target_compile_options(${name} PUBLIC -U_GLIBCXX_ASSERTIONS)
-      target_compile_options(${name} PUBLIC -U_LIBCPP_ENABLE_ASSERTIONS)
+      target_compile_options(${tgtname} PUBLIC -U_GLIBCXX_ASSERTIONS)
+      target_compile_options(${tgtname} PUBLIC -U_LIBCPP_ENABLE_ASSERTIONS)
     endif ()
 
     # Flang/Clang (including clang-cl) -compiled programs targeting the MSVC ABI
@@ -205,16 +211,16 @@ function (add_flangrt_library name)
     # 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>" "--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}")
+        target_compile_options(${tgtname} PRIVATE "$<$<COMPILE_LANGUAGE:CXX,C>:-Xclang>" "--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(${name} PRIVATE "$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "--dependent-lib=${FLANG_RT_BUILTINS_LIBRARY}")
+        target_compile_options(${tgtname} PRIVATE "$<$<COMPILE_LANGUAGE:Fortran>:-Xflang>" "--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}
+          instead falls back to builtins from Compiler-RT. Linking with ${tgtname}
           may result in a linker error.")
       endif ()
     endif ()
@@ -226,34 +232,32 @@ function (add_flangrt_library name)
       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})
+      target_link_libraries(${tgtname} PUBLIC ${llvm_libs})
+      target_include_directories(${tgtname} PUBLIC ${LLVM_INCLUDE_DIRS})
     endif ()
   endforeach ()
 
-  foreach (name IN LISTS libtargets)
+  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(${name}
+      set_target_properties(${tgtname}
         PROPERTIES
-          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
           ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
-          RUNTIME_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_LIB_DIR}"
         )
 
-      install(TARGETS ${name}
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
+      install(TARGETS ${tgtname}
           ARCHIVE DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
-          RUNTIME DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
+          LIBRARY DESTINATION "${FLANG_RT_INSTALL_LIB_DIR}"
         )
     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})
+      add_dependencies(flang-rt ${tgtname})
     endif ()
   endforeach ()
 endfunction (add_flangrt_library)
diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/flang-rt/cmake/modules/GetToolchainDirs.cmake
index fc1a406f99ab29..fe44ee2a2a1ee1 100644
--- a/flang-rt/cmake/modules/GetToolchainDirs.cmake
+++ b/flang-rt/cmake/modules/GetToolchainDirs.cmake
@@ -1,127 +1,152 @@
-#===-- 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 ()
+
+
+# Return the subdir of PREFIX where the system holds target-system specific libraries.
+# E.g. lib/x86_64-linux-gnu in /usr
+function (get_system_library_subdir outvar)
+  get_lib_arch_dirname(archdirname)
+  set(${outvar} "${CMAKE_INSTALL_LIBDIR}/${archdirname}" 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()
+
+
+# Compute the arch-specific subdir of lib.
+function (get_lib_arch_dirname outvar)
+  get_toolchain_arch_dirname(normalize_triple)
+  string(REPLACE "-" ";" triple_list "${normalize_triple}")
+
+  # Vendor is optional. Remove if "unknown", as done by e.g. Debian.
+  #  x86_64-unkown-linux-gnu ->  x86_64-linux-gnu
+  list(GET triple_list 1 vendor)
+  if (vendor STREQUAL "unknown")
+     list(REMOVE_AT triple_list 1)
+  endif ()
+
+  list(JOIN triple_list "-" result)
+  set(${outvar} "${result}" PARENT_SCOPE)
+endfunction ()
diff --git a/flang-rt/lib/flang_rt/CMakeLists.txt b/flang-rt/lib/flang_rt/CMakeLists.txt
index ff45e26961a42c..4652e2b9f2cfcf 100644
--- a/flang-rt/lib/flang_rt/CMakeLists.txt
+++ b/flang-rt/lib/flang_rt/CMakeLists.txt
@@ -128,7 +128,7 @@ 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}
@@ -137,10 +137,16 @@ if (NOT WIN32)
   enable_cuda_compilation(flang_rt "${supported_sources}")
   enable_omp_offload_compilation(flang_rt "${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 also 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/Runtime/no-cpp-dep.c b/flang-rt/test/Runtime/no-cpp-dep.c
index 9880afc2749734..192395fa7769b9 100644
--- a/flang-rt/test/Runtime/no-cpp-dep.c
+++ b/flang-rt/test/Runtime/no-cpp-dep.c
@@ -6,7 +6,7 @@ a C compiler.
 UNSUPPORTED: system-windows
 
 RUN: %if system-aix %{ export OBJECT_MODE=64 %}
-RUN: %cc -std=c99 %s -I%include %libruntime -lm %deplibs \
+RUN: %cc -std=c99 %s -I%include -L%libdir -lflang_rt -lm %deplibs \
 RUN: %if system-aix %{-lpthread %}
 */
 
diff --git a/flang-rt/test/lit.cfg.py b/flang-rt/test/lit.cfg.py
index b32fa70f5ed35d..125e339f85bde0 100644
--- a/flang-rt/test/lit.cfg.py
+++ b/flang-rt/test/lit.cfg.py
@@ -87,14 +87,12 @@ def shjoin(args, sep=" "):
 # Let tests find LLVM's standard tools (FileCheck, split-file, not, ...)
 llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True)
 
-# Library path of libflang_rt.a
+# Library path of libflang_rt.a/so
 config.substitutions.append(("%libdir", config.flang_rt_build_lib_dir))
 
 # Define some variables to help us test that the flang runtime doesn't depend on
 # the C++ runtime libraries. For this we need a C compiler.
-libruntime = os.path.join(config.flang_rt_build_lib_dir, "libflang_rt.a")
 include = os.path.join(config.flang_source_dir, "include")
-config.substitutions.append(("%libruntime", libruntime))
 config.substitutions.append(("%include", include))
 
 # Additional library depedendencies the that flang driver does not add itself.

>From 4f6a242ac89326624255d8b1814f6ac178ffa374 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 2 Jan 2025 16:31:39 +0100
Subject: [PATCH 5/5] Fixed all check.sh

---
 flang-rt/CMakeLists.txt                       | 48 ++++++++++---------
 flang-rt/cmake/modules/AddFlangRT.cmake       | 12 ++---
 .../cmake/modules/AddFlangRTOffload.cmake     |  8 ++--
 flang-rt/cmake/modules/GetToolchainDirs.cmake | 25 ----------
 flang-rt/lib/flang_rt/CMakeLists.txt          |  6 +--
 flang-rt/test/Runtime/no-cpp-dep.c            |  2 +-
 flang-rt/test/lit.cfg.py                      | 18 +++----
 flang-rt/test/lit.site.cfg.py.in              |  2 +-
 flang-rt/unittests/CMakeLists.txt             |  2 +-
 9 files changed, 52 insertions(+), 71 deletions(-)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 1c20876dd07bfe..7effa6012a078f 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -96,8 +96,8 @@ if (LLVM_TREE_AVAILABLE)
   # Despite Clang in the name, get_clang_resource_dir does not depend on Clang
   # being added to the build. Flang uses the same resource dir as clang.
   include(GetClangResourceDir)
-  get_clang_resource_dir(FLANG_RT_OUTPUT_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
-  get_clang_resource_dir(FLANG_RT_INSTALL_PATH)
+  get_clang_resource_dir(FLANG_RT_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
+  get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH)
 else ()
   # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
   # read-only and/or shared by multiple runtimes with different build
@@ -106,29 +106,27 @@ else ()
   # For the install prefix, still use the resource dir assuming that Flang will
   # be installed there using the same prefix. This is to not have a difference
   # between bootstrap and standalone runtimes builds.
-  set(FLANG_RT_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-  set(FLANG_RT_INSTALL_PATH "${CMAKE_INSTALL_LIBDIR}/clang/${LLVM_VERSION_MAJOR}")
+  set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+  set(FLANG_RT_INSTALL_RESOURCE_PATH "${CMAKE_INSTALL_LIBDIR}/clang/${LLVM_VERSION_MAJOR}")
 endif ()
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_PATH)
+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)
-get_system_library_subdir(arch_lib_subdir)
-extend_path(FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${toolchain_lib_subdir}")
-if (LLVM_TREE_AVAILABLE)
-  extend_path(FLANG_RT_BUILD_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${arch_lib_subdir}")
-else ()
-  # Only building for a single target, so no need to write into a arch-specific subirectory.
-  extend_path(FLANG_RT_BUILD_LIB_DIR "${FLANG_RT_OUTPUT_DIR}" "${CMAKE_INSTALL_LIBDIR}")
-endif ()
-extend_path(FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR "${FLANG_RT_INSTALL_PATH}" "${toolchain_lib_subdir}")
-extend_path(FLANG_RT_INSTALL_LIB_DIR "${FLANG_RT_INSTALL_PATH}" "${arch_lib_subdir}")
-
-cmake_path(NORMAL_PATH FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_BUILD_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_LIB_DIR)
+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}")
+cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
+cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
 
 
 #################
@@ -146,7 +144,13 @@ if (WIN32)
   # Windows DLL currently not implemented.
   set(FLANG_RT_ENABLE_SHARED OFF)
 else ()
-  option(FLANG_RT_ENABLE_SHARED "Build Flang-RT as a shared library." ON)
+  # 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 "
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 63f694eb77bd6c..b7bc05b823071e 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -140,8 +140,8 @@ function (add_flangrt_library name)
 
   foreach (tgtname IN LISTS libtargets)
     if (NOT WIN32)
-      # Use same stem name for .a and .so. Common in UNIX environments. Not
-      # allowed with Windows.
+      # 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 ()
 
@@ -244,13 +244,13 @@ function (add_flangrt_library name)
     if (ARG_INSTALL_WITH_TOOLCHAIN)
       set_target_properties(${tgtname}
         PROPERTIES
-          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR}"
-          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_BUILD_LIB_DIR}"
+          ARCHIVE_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${FLANG_RT_OUTPUT_RESOURCE_LIB_DIR}"
         )
 
       install(TARGETS ${tgtname}
-          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_TOOLCHAIN_LIB_DIR}"
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_LIB_DIR}"
+          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
+          LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
         )
     endif ()
 
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 fe44ee2a2a1ee1..1f251790f22a01 100644
--- a/flang-rt/cmake/modules/GetToolchainDirs.cmake
+++ b/flang-rt/cmake/modules/GetToolchainDirs.cmake
@@ -49,14 +49,6 @@ function (get_toolchain_library_subdir outvar)
 endfunction ()
 
 
-# Return the subdir of PREFIX where the system holds target-system specific libraries.
-# E.g. lib/x86_64-linux-gnu in /usr
-function (get_system_library_subdir outvar)
-  get_lib_arch_dirname(archdirname)
-  set(${outvar} "${CMAKE_INSTALL_LIBDIR}/${archdirname}" PARENT_SCOPE)
-endfunction ()
-
-
 # Corresponds to Clang's ToolChain::getOSLibName(). Adapted from Compiler-RT.
 function (get_toolchain_os_dirname outvar)
   if (ANDROID)
@@ -133,20 +125,3 @@ function (get_toolchain_arch_dirname outvar)
   endif()
   set(${outvar} "${target}" PARENT_SCOPE)
 endfunction()
-
-
-# Compute the arch-specific subdir of lib.
-function (get_lib_arch_dirname outvar)
-  get_toolchain_arch_dirname(normalize_triple)
-  string(REPLACE "-" ";" triple_list "${normalize_triple}")
-
-  # Vendor is optional. Remove if "unknown", as done by e.g. Debian.
-  #  x86_64-unkown-linux-gnu ->  x86_64-linux-gnu
-  list(GET triple_list 1 vendor)
-  if (vendor STREQUAL "unknown")
-     list(REMOVE_AT triple_list 1)
-  endif ()
-
-  list(JOIN triple_list "-" result)
-  set(${outvar} "${result}" PARENT_SCOPE)
-endfunction ()
diff --git a/flang-rt/lib/flang_rt/CMakeLists.txt b/flang-rt/lib/flang_rt/CMakeLists.txt
index 4652e2b9f2cfcf..c0dfc7e976f28b 100644
--- a/flang-rt/lib/flang_rt/CMakeLists.txt
+++ b/flang-rt/lib/flang_rt/CMakeLists.txt
@@ -134,10 +134,10 @@ if (NOT WIN32)
     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}")
 
-  # Select a default runtime, which is also used for unittests.
+  # 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)
diff --git a/flang-rt/test/Runtime/no-cpp-dep.c b/flang-rt/test/Runtime/no-cpp-dep.c
index 192395fa7769b9..04283719461267 100644
--- a/flang-rt/test/Runtime/no-cpp-dep.c
+++ b/flang-rt/test/Runtime/no-cpp-dep.c
@@ -6,7 +6,7 @@ a C compiler.
 UNSUPPORTED: system-windows
 
 RUN: %if system-aix %{ export OBJECT_MODE=64 %}
-RUN: %cc -std=c99 %s -I%include -L%libdir -lflang_rt -lm %deplibs \
+RUN: %cc -std=c99 %s -I%include -L"%libdir" -lflang_rt -lm %deplibs \
 RUN: %if system-aix %{-lpthread %}
 */
 
diff --git a/flang-rt/test/lit.cfg.py b/flang-rt/test/lit.cfg.py
index 125e339f85bde0..46274c5c8b1b1e 100644
--- a/flang-rt/test/lit.cfg.py
+++ b/flang-rt/test/lit.cfg.py
@@ -80,22 +80,24 @@ def shjoin(args, sep=" "):
         extra_args=isysroot_flag,
         unresolved="fatal",
     ),
-    ToolSubst("%cc", command=config.cc, extra_args=isysroot_flag, unresolved="fatal"),
+    ToolSubst("%cc",
+        command=config.cc,
+        extra_args=isysroot_flag,
+        unresolved="fatal"
+    ),
 ]
 llvm_config.add_tool_substitutions(tools)
 
 # Let tests find LLVM's standard tools (FileCheck, split-file, not, ...)
 llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True)
 
-# Library path of libflang_rt.a/so
-config.substitutions.append(("%libdir", config.flang_rt_build_lib_dir))
+# Include path for C headers that define Flang's Fortran ABI.
+config.substitutions.append(("%include", os.path.join(config.flang_source_dir, "include")))
 
-# Define some variables to help us test that the flang runtime doesn't depend on
-# the C++ runtime libraries. For this we need a C compiler.
-include = os.path.join(config.flang_source_dir, "include")
-config.substitutions.append(("%include", include))
+# 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.
+# Additional library depedendencies the that Flang driver does not add itself.
 deplibs = []
 if config.flang_rt_experimental_offload_support == "CUDA":
     deplibs.append("-lcudart")
diff --git a/flang-rt/test/lit.site.cfg.py.in b/flang-rt/test/lit.site.cfg.py.in
index b6db393527ecb1..662d076b1fe24f 100644
--- a/flang-rt/test/lit.site.cfg.py.in
+++ b/flang-rt/test/lit.site.cfg.py.in
@@ -6,7 +6,7 @@ config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
 config.flang_source_dir = "@FLANG_SOURCE_DIR@"
 config.flang_rt_source_dir = "@FLANG_RT_SOURCE_DIR@"
 config.flang_rt_binary_test_dir = os.path.dirname(__file__)
-config.flang_rt_build_lib_dir = "@FLANG_RT_BUILD_TOOLCHAIN_LIB_DIR@"
+config.flang_rt_output_resource_lib_dir = "@FLANG_RT_OUTPUT_RESOURCE_LIB_DIR@"
 config.flang_rt_experimental_offload_support = "@FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT@"
 config.cc = "@CMAKE_C_COMPILER@"
 config.flang = "@CMAKE_Fortran_COMPILER@"
diff --git a/flang-rt/unittests/CMakeLists.txt b/flang-rt/unittests/CMakeLists.txt
index 4d852d3f19f9b5..ca94805f1403bc 100644
--- a/flang-rt/unittests/CMakeLists.txt
+++ b/flang-rt/unittests/CMakeLists.txt
@@ -91,7 +91,7 @@ function(add_flangrt_nongtest_unittest test_name)
       set(suffix .test)
   endif()
 
-  add_executable(${test_name}${suffix} ${ARG_UNPARSED_ARGUMENTS})
+  add_executable(${test_name}${suffix} EXCLUDE_FROM_ALL ${ARG_UNPARSED_ARGUMENTS})
   set_target_properties(${test_name}${suffix} PROPERTIES FOLDER "Flang-RT/Tests/Unit")
 
   target_include_directories(${test_name}${suffix} PRIVATE



More information about the llvm-branch-commits mailing list