[llvm-branch-commits] [compiler-rt] [libc] [libcxx] [libcxxabi] [libunwind] [llvm] [openmp] [runtimes][CMake] Move Fortran support code from flang-rt (PR #171610)

Michael Kruse via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Mar 26 05:41:12 PDT 2026


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

>From cc7a3242e91940b0bb304917fb03655599e55974 Mon Sep 17 00:00:00 2001
From: Michael Kruse <michael.kruse at amd.com>
Date: Wed, 10 Dec 2025 06:10:43 -0600
Subject: [PATCH 01/13] Move GetToolchainDirs.cmake

---
 {flang-rt/cmake/modules => cmake/Modules}/GetToolchainDirs.cmake | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename {flang-rt/cmake/modules => cmake/Modules}/GetToolchainDirs.cmake (100%)

diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
similarity index 100%
rename from flang-rt/cmake/modules/GetToolchainDirs.cmake
rename to cmake/Modules/GetToolchainDirs.cmake

>From 4ff6d124565cac0975951e5b310266543de66fa3 Mon Sep 17 00:00:00 2001
From: Michael Kruse <michael.kruse at amd.com>
Date: Wed, 10 Dec 2025 06:27:32 -0600
Subject: [PATCH 02/13] Backport runtimes files

---
 cmake/Modules/GetToolchainDirs.cmake |  11 +
 runtimes/CMakeLists.txt              | 303 ++++++++++++++++++++++++++-
 2 files changed, 303 insertions(+), 11 deletions(-)

diff --git a/cmake/Modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
index fba12502b5946..ce2f8c294b2bc 100644
--- a/cmake/Modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -47,6 +47,17 @@ function (get_toolchain_library_subdir outvar)
 endfunction ()
 
 
+# Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
+function (get_toolchain_module_subdir outvar)
+  set(outval "finclude/flang")
+
+  get_toolchain_arch_dirname(arch_dirname)
+  set(outval "${outval}/${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)
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 5220b9353fed7..a5bb2d975272e 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -85,6 +85,195 @@ include(CheckLibraryExists)
 include(LLVMCheckCompilerLinkerFlag)
 include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
+include(GetToolchainDirs)
+include(ExtendPath)
+
+# Check whether the Fortran compiler already access to builtin modules. Sets
+# HAVE_FORTRAN_INTRINSIC_MODS when returning.
+#
+# This must be wrapped in a function because
+# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
+# a compiler introspection environment, see
+# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
+function (check_fortran_builtins_available)
+  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    # CMake's try_compile does not take a user-defined
+    # CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of test-compiling,
+    # ask Flang directly for the builtin module files.
+    if (NOT DEFINED HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD)
+      message(STATUS "Performing Test ISO_C_BINDING_PATH")
+      execute_process(
+        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
+        OUTPUT_VARIABLE ISO_C_BINDING_PATH
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        ERROR_QUIET
+      )
+      set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD "" )
+      if (EXISTS "${ISO_C_BINDING_PATH}")
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
+        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      else ()
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
+        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      endif ()
+    endif ()
+  else ()
+    cmake_push_check_state(RESET)
+    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+    check_fortran_source_compiles("
+      subroutine testroutine
+        use iso_c_binding
+      end subroutine
+      " HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
+    cmake_pop_check_state()
+  endif ()
+  set(HAVE_FORTRAN_INTRINSIC_MODS "${HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
+endfunction ()
+
+
+# Set options to compile Fortran module files.
+#
+# Usage:
+#
+# flang_module_target(name
+#   PUBLIC
+#     Modules files are to be used by other Fortran sources. If a library is
+#     compiled multiple times (e.g. static/shared, or msvcrt variants), only
+#     one of those can be public module files; non-public modules are still
+#     generated but to be forgotten deep inside the build directory to not
+#     conflict with each other.
+#     Also, installs the module with the toolchain.
+# )
+function (flang_module_target tgtname)
+  set(options PUBLIC)
+  cmake_parse_arguments(ARG
+    "${options}"
+    ""
+    ""
+    ${ARGN})
+
+  if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
+    message(WARNING "Cannot build module files for ${tgtname} when RUNTIMES_FLANG_MODULES_ENABLED is ${RUNTIMES_FLANG_MODULES_ENABLED}")
+    return ()
+  endif ()
+
+  target_compile_options(${tgtname} PRIVATE
+      # Let non-public modules find the public module files
+      "$<$<COMPILE_LANGUAGE:Fortran>:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
+
+      # Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
+    )
+
+  if (LLVM_RUNTIMES_TARGET MATCHES "^nvptx")
+    foreach (_arch IN LISTS RUNTIMES_DEVICE_ARCHITECTURES)
+      target_compile_options(${tgtname} PRIVATE
+       "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
+      )
+    endforeach()
+  endif ()
+
+  if (ARG_PUBLIC)
+    set_target_properties(${tgtname}
+      PROPERTIES
+        Fortran_MODULE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+      )
+  else ()
+    set_target_properties(${tgtname}
+      PROPERTIES
+        Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${tgtname}.mod"
+      )
+  endif ()
+endfunction ()
+
+# Check whether the build environment supports building Fortran modules
+# flang-rt and openmp are the only runtimes that contain Fortran modules.
+set(FORTRAN_MODULE_DEPS "")
+if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
+  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
+
+  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
+    # CMake 3.24 is the first version of CMake that directly recognizes Flang.
+    # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
+    if (CMAKE_VERSION VERSION_LESS "3.24")
+      include(CMakeForceCompiler)
+      CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
+
+      set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
+      set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
+
+      set(CMAKE_Fortran_SUBMODULE_SEP "-")
+      set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
+
+      set(CMAKE_Fortran_PREPROCESS_SOURCE
+        "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+
+      set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
+      set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
+
+      set(CMAKE_Fortran_MODDIR_FLAG "-J")
+
+      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
+      set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
+
+      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
+      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+
+      set(CMAKE_Fortran_VERBOSE_FLAG "-v")
+
+      set(CMAKE_Fortran_LINK_MODE DRIVER)
+    endif ()
+
+    # Optimization flags are only passed after CMake 3.27.4
+    # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
+    if (CMAKE_VERSION VERSION_LESS "3.27.4")
+      string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
+      string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
+      string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
+    endif ()
+
+    # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
+    # to nvptx amd amdgpu targets, passing the target triple is essential.
+    # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
+    if (CMAKE_VERSION VERSION_LESS "3.28")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
+    endif ()
+  endif ()
+
+  include(CheckFortranSourceCompiles)
+  include(CheckLanguage)
+
+  set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
+  check_language(Fortran)
+  if (CMAKE_Fortran_COMPILER)
+    enable_language(Fortran)
+
+    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+      # In a bootstrapping build (or any runtimes-build that includes flang-rt),
+      # the intrinsic modules are not built yet. Targets can depend on
+      # flang-rt-mod to ensure that flang-rt's modules are built first.
+      set(FORTRAN_MODULE_DEPS flang-rt-mod)
+      set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+    else ()
+      # Check whether building modules works, avoid causing the entire build to
+      # fail because of Fortran. The primary situation we want to support here
+      # is Flang, or its intrinsic modules were built separately in a
+      # non-bootstrapping build.
+      check_fortran_builtins_available()
+      if (HAVE_FORTRAN_INTRINSIC_MODS)
+        set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+        message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
+      else ()
+        message(STATUS "Not compiling Flang modules: Not passing smoke check")
+      endif ()
+    endif ()
+  endif ()
+
+  option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
+else ()
+  set(RUNTIMES_FLANG_MODULES_ENABLED NO)
+endif ()
 
 
 # Determine whether we are in the runtimes/runtimes-bins directory of a
@@ -94,17 +283,6 @@ if (LLVM_LIBRARY_DIR AND LLVM_TOOLS_BINARY_DIR AND PACKAGE_VERSION)
   set(LLVM_TREE_AVAILABLE ON)
 endif()
 
-if(LLVM_TREE_AVAILABLE)
-  # Setting these variables will allow the sub-build to put their outputs into
-  # the library and bin directories of the top-level build.
-  set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_LIBRARY_DIR})
-  set(LLVM_RUNTIME_OUTPUT_INTDIR ${LLVM_TOOLS_BINARY_DIR})
-else()
-  # Use own build directory for artifact output.
-  set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
-  set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
-endif()
-
 # CMake omits default compiler include paths, but in runtimes build, we use
 # -nostdinc and -nostdinc++ and control include paths manually so this behavior
 # is undesirable. Filtering CMAKE_{LANG}_IMPLICIT_INCLUDE_DIRECTORIES to remove
@@ -236,6 +414,109 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
   endif()
 endif()
 
+# Determine output and install paths based on LLVM_TARGET_TRIPLE
+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
+  # just-built compiler without specifying paths to runtime libraries.
+  # LLVM_LIBRARY_OUTPUT_INTDIR/LLVM_RUNTIME_OUTPUT_INTDIR is used by
+  # AddLLVM.cmake as artifact output locations.
+  set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_LIBRARY_DIR})
+  set(LLVM_RUNTIME_OUTPUT_INTDIR ${LLVM_TOOLS_BINARY_DIR})
+
+  # 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(RUNTIMES_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
+  get_clang_resource_dir(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT)
+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
+  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
+  # non-toolchain library. Use own build directory for artifact output.
+  set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
+  set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
+
+  # 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(RUNTIMES_OUTPUT_RESOURCE_DIR "${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
+  set(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
+endif()
+
+# 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.
+# FIXME: For shared libraries, 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>/lib<name>.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(RUNTIMES_OUTPUT_RESOURCE_LIB_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
+
+set(RUNTIMES_INSTALL_RESOURCE_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT}" CACHE PATH "Path to install headers, runtime libraries, and Fortran modules to (default: Clang resource dir)")
+extend_path(RUNTIMES_INSTALL_RESOURCE_LIB_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
+
+cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_DIR)
+cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_PATH)
+cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_LIB_DIR)
+cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_LIB_PATH)
+
+
+if (RUNTIMES_FLANG_MODULES_ENABLED)
+  if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    # Flang expects its builtin modules in Clang's resource directory
+    get_toolchain_module_subdir(toolchain_mod_subdir)
+    extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
+    extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
+  else ()
+    # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
+    extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+    extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+  endif ()
+  cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
+  cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
+
+  # No way to find out which mod files are built by a target, so install the
+  # entire output directory
+  # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
+  set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
+  cmake_path(NORMAL_PATH destination)
+    install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+      DESTINATION "${destination}"
+    )
+endif ()
+
+
+if (RUNTIMES_FLANG_MODULES_ENABLED)
+  set(RUNTIMES_DEVICE_ARCHITECTURES "all" CACHE STRING
+      "List of offload device architectures to be used to compile the Fortran offload code (e.g. 'gfx1103;sm_90')"
+    )
+
+  if (RUNTIMES_DEVICE_ARCHITECTURES STREQUAL "all")
+    # TODO: support auto detection on the build system.
+    set(all_amdgpu_architectures
+      "gfx700;gfx701;gfx801;gfx803;gfx900;gfx902;gfx906"
+      "gfx908;gfx90a;gfx90c;gfx940;gfx1010;gfx1030"
+      "gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036"
+      "gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151"
+      "gfx1152;gfx1153")
+    set(all_nvptx_architectures
+      "sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62"
+      "sm_70;sm_72;sm_75;sm_80;sm_86;sm_89;sm_90")
+    set(all_gpu_architectures
+      "${all_amdgpu_architectures};${all_nvptx_architectures}")
+      set(RUNTIMES_DEVICE_ARCHITECTURES ${all_gpu_architectures})
+  endif()
+  list(REMOVE_DUPLICATES RUNTIMES_DEVICE_ARCHITECTURES)
+endif ()
+
+
 option(LLVM_INCLUDE_TESTS "Generate build targets for the runtimes unit tests." ON)
 option(LLVM_INCLUDE_DOCS "Generate build targets for the runtimes documentation." ON)
 option(LLVM_ENABLE_SPHINX "Use Sphinx to generate the runtimes documentation." OFF)

>From d4b194d6ce7e11fb565a41a78bbe0d459bea09fd Mon Sep 17 00:00:00 2001
From: Michael Kruse <michael.kruse at amd.com>
Date: Wed, 10 Dec 2025 06:45:31 -0600
Subject: [PATCH 03/13] Avoid redundancies in flang-rt CMakeLists.txt

---
 flang-rt/CMakeLists.txt                 | 90 +------------------------
 flang-rt/cmake/modules/AddFlangRT.cmake |  8 +--
 flang-rt/test/lit.site.cfg.py.in        |  2 +-
 3 files changed, 6 insertions(+), 94 deletions(-)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 50b8e834776fb..1e492d9c4feb8 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -23,41 +23,6 @@ set(FLANG_RT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
 set(FLANG_RT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
 set(FLANG_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../flang")
 
-# CMake 3.24 is the first version of CMake that directly recognizes Flang.
-# LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang.
-if (CMAKE_VERSION VERSION_LESS "3.24")
-  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
-  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
-    include(CMakeForceCompiler)
-    CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
-
-    set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
-    set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
-
-    set(CMAKE_Fortran_SUBMODULE_SEP "-")
-    set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
-
-    set(CMAKE_Fortran_PREPROCESS_SOURCE
-      "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
-
-    set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
-    set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
-
-    set(CMAKE_Fortran_MODDIR_FLAG "-module-dir")
-
-    set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
-    set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
-    set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
-
-    set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
-
-    set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
-    set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
-  endif ()
-endif ()
-enable_language(Fortran)
-
-
 list(APPEND CMAKE_MODULE_PATH
     "${FLANG_RT_SOURCE_DIR}/cmake/modules"
     "${FLANG_SOURCE_DIR}/cmake/modules"
@@ -73,62 +38,9 @@ include(ExtendPath)
 # Build Mode Introspection #
 ############################
 
-# Determine whether we are in the runtimes/runtimes-bins directory of a
-# bootstrap build.
-set(LLVM_TREE_AVAILABLE OFF)
-if (LLVM_LIBRARY_OUTPUT_INTDIR AND LLVM_RUNTIME_OUTPUT_INTDIR AND PACKAGE_VERSION)
-  set(LLVM_TREE_AVAILABLE ON)
-endif()
-
 # Path to LLVM development tools (FileCheck, llvm-lit, not, ...)
 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
-  # just-built compiler without specifying paths to runtime libraries.
-  #
-  # 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_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
-  get_clang_resource_dir(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT)
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_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
-  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
-  # 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.
-  set(FLANG_RT_OUTPUT_RESOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-  set(FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
-
-  extend_path(FLANG_RT_OUTPUT_RESOURCE_LIB_DIR "${FLANG_RT_OUTPUT_RESOURCE_DIR}" "lib${LLVM_LIBDIR_SUFFIX}")
-endif ()
-set(FLANG_RT_INSTALL_RESOURCE_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH_DEFAULT}"
-    CACHE PATH "Path to install runtime libraries to (default: clang resource dir)")
-extend_path(FLANG_RT_INSTALL_RESOURCE_LIB_PATH "${FLANG_RT_INSTALL_RESOURCE_PATH}" "${toolchain_lib_subdir}")
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_PATH)
-# 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.
-cmake_path(NORMAL_PATH FLANG_RT_OUTPUT_RESOURCE_LIB_DIR)
-cmake_path(NORMAL_PATH FLANG_RT_INSTALL_RESOURCE_LIB_PATH)
-
 
 #################
 # Build Options #
@@ -186,7 +98,7 @@ elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "CUDA")
   option(FLANG_RT_CUDA_RUNTIME_PTX_WITHOUT_GLOBAL_VARS "Do not compile global variables' definitions when producing PTX library" OFF)
 elseif (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
   # Support for OpenMP offloading
-  set(FLANG_RT_DEVICE_ARCHITECTURES "all" CACHE STRING
+  set(FLANG_RT_DEVICE_ARCHITECTURES "${RUNTIMES_DEVICE_ARCHITECTURES}" CACHE STRING
       "List of OpenMP device architectures to be used to compile the Fortran runtime (e.g. 'gfx1103;sm_90')"
     )
 
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index 923507764d691..e960e79473cbb 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -344,13 +344,13 @@ function (add_flangrt_library name)
     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}"
+          ARCHIVE_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
+          LIBRARY_OUTPUT_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_LIB_DIR}"
         )
 
       install(TARGETS ${tgtname}
-          ARCHIVE DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
-          LIBRARY DESTINATION "${FLANG_RT_INSTALL_RESOURCE_LIB_PATH}"
+          ARCHIVE DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
+          LIBRARY DESTINATION "${RUNTIMES_INSTALL_RESOURCE_LIB_PATH}"
         )
     endif ()
 
diff --git a/flang-rt/test/lit.site.cfg.py.in b/flang-rt/test/lit.site.cfg.py.in
index 662d076b1fe24..0e9dc08b59925 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_output_resource_lib_dir = "@FLANG_RT_OUTPUT_RESOURCE_LIB_DIR@"
+config.flang_rt_output_resource_lib_dir = "@RUNTIMES_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@"

>From 99b86b92e0f7066ccf56d5fc91d5620e09a2e99a Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Wed, 17 Dec 2025 17:10:15 +0100
Subject: [PATCH 04/13] Avoid general references to Flang

---
 runtimes/CMakeLists.txt | 25 ++++++++-----------------
 1 file changed, 8 insertions(+), 17 deletions(-)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index a5bb2d975272e..368a048a4a691 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -430,32 +430,23 @@ if(LLVM_TREE_AVAILABLE)
   get_clang_resource_dir(RUNTIMES_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
   get_clang_resource_dir(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT)
 else()
-  # In a standalone runtimes build, do not write into LLVM_BINARY_DIR. It may be
+  # In a default runtimes build, do not write into LLVM_BINARY_DIR. It may be
   # read-only and/or shared by multiple runtimes with different build
   # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
   # non-toolchain library. Use own build directory for artifact output.
   set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
   set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
 
-  # 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.
+  # For the install prefix, still use the resource dir assuming the compilers
+  # looking for it (Clang, Flang) will be installed there using the same prefix.
+  # This is to not have a difference between bootstrapping and default runtimes
+  # builds.
   set(RUNTIMES_OUTPUT_RESOURCE_DIR "${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
   set(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
 endif()
 
-# 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.
-# FIXME: For shared libraries, 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>/lib<name>.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.
+# Determine build and install paths. The ouptut paths are absolute, but the
+# install dirs are relative to CMAKE_INSTALL_PREFIX to be resolved by CMake.
 get_toolchain_library_subdir(toolchain_lib_subdir)
 extend_path(RUNTIMES_OUTPUT_RESOURCE_LIB_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
 
@@ -483,7 +474,7 @@ if (RUNTIMES_FLANG_MODULES_ENABLED)
   cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
 
   # No way to find out which mod files are built by a target, so install the
-  # entire output directory
+  # entire output directory.
   # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
   set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
   cmake_path(NORMAL_PATH destination)

>From ac11614f458506faaec1e35f340b80f135ba26db Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Wed, 14 Jan 2026 14:17:42 +0100
Subject: [PATCH 05/13] Address Petr Hosek's review

---
 cmake/Modules/GetToolchainDirs.cmake       |   9 -
 runtimes/CMakeLists.txt                    | 289 +++------------------
 runtimes/cmake/Modules/HandleFortran.cmake | 226 ++++++++++++++++
 3 files changed, 265 insertions(+), 259 deletions(-)
 create mode 100644 runtimes/cmake/Modules/HandleFortran.cmake

diff --git a/cmake/Modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
index ce2f8c294b2bc..ccc815c91d05f 100644
--- a/cmake/Modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -1,12 +1,3 @@
-#===-- 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
-#
-#===------------------------------------------------------------------------===#
-
-
 # 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
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 368a048a4a691..768fddb8b4dd7 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -87,194 +87,10 @@ include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
 include(GetToolchainDirs)
 include(ExtendPath)
+include(HandleFortran)
 
-# Check whether the Fortran compiler already access to builtin modules. Sets
-# HAVE_FORTRAN_INTRINSIC_MODS when returning.
-#
-# This must be wrapped in a function because
-# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
-# a compiler introspection environment, see
-# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
-function (check_fortran_builtins_available)
-  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
-    # CMake's try_compile does not take a user-defined
-    # CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of test-compiling,
-    # ask Flang directly for the builtin module files.
-    if (NOT DEFINED HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD)
-      message(STATUS "Performing Test ISO_C_BINDING_PATH")
-      execute_process(
-        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
-        OUTPUT_VARIABLE ISO_C_BINDING_PATH
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-        ERROR_QUIET
-      )
-      set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD "" )
-      if (EXISTS "${ISO_C_BINDING_PATH}")
-        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
-        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
-      else ()
-        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
-        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
-      endif ()
-    endif ()
-  else ()
-    cmake_push_check_state(RESET)
-    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
-    check_fortran_source_compiles("
-      subroutine testroutine
-        use iso_c_binding
-      end subroutine
-      " HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
-    cmake_pop_check_state()
-  endif ()
-  set(HAVE_FORTRAN_INTRINSIC_MODS "${HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
-endfunction ()
-
-
-# Set options to compile Fortran module files.
-#
-# Usage:
-#
-# flang_module_target(name
-#   PUBLIC
-#     Modules files are to be used by other Fortran sources. If a library is
-#     compiled multiple times (e.g. static/shared, or msvcrt variants), only
-#     one of those can be public module files; non-public modules are still
-#     generated but to be forgotten deep inside the build directory to not
-#     conflict with each other.
-#     Also, installs the module with the toolchain.
-# )
-function (flang_module_target tgtname)
-  set(options PUBLIC)
-  cmake_parse_arguments(ARG
-    "${options}"
-    ""
-    ""
-    ${ARGN})
-
-  if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
-    message(WARNING "Cannot build module files for ${tgtname} when RUNTIMES_FLANG_MODULES_ENABLED is ${RUNTIMES_FLANG_MODULES_ENABLED}")
-    return ()
-  endif ()
-
-  target_compile_options(${tgtname} PRIVATE
-      # Let non-public modules find the public module files
-      "$<$<COMPILE_LANGUAGE:Fortran>:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
-
-      # Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
-      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
-    )
-
-  if (LLVM_RUNTIMES_TARGET MATCHES "^nvptx")
-    foreach (_arch IN LISTS RUNTIMES_DEVICE_ARCHITECTURES)
-      target_compile_options(${tgtname} PRIVATE
-       "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
-      )
-    endforeach()
-  endif ()
-
-  if (ARG_PUBLIC)
-    set_target_properties(${tgtname}
-      PROPERTIES
-        Fortran_MODULE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
-      )
-  else ()
-    set_target_properties(${tgtname}
-      PROPERTIES
-        Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${tgtname}.mod"
-      )
-  endif ()
-endfunction ()
-
-# Check whether the build environment supports building Fortran modules
-# flang-rt and openmp are the only runtimes that contain Fortran modules.
-set(FORTRAN_MODULE_DEPS "")
-if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
-  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
-
-  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
-    # CMake 3.24 is the first version of CMake that directly recognizes Flang.
-    # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
-    if (CMAKE_VERSION VERSION_LESS "3.24")
-      include(CMakeForceCompiler)
-      CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
-
-      set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
-      set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
-
-      set(CMAKE_Fortran_SUBMODULE_SEP "-")
-      set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
-
-      set(CMAKE_Fortran_PREPROCESS_SOURCE
-        "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
-
-      set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
-      set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
-
-      set(CMAKE_Fortran_MODDIR_FLAG "-J")
-
-      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
-      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
-      set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
-
-      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
-      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
-
-      set(CMAKE_Fortran_VERBOSE_FLAG "-v")
-
-      set(CMAKE_Fortran_LINK_MODE DRIVER)
-    endif ()
-
-    # Optimization flags are only passed after CMake 3.27.4
-    # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
-    if (CMAKE_VERSION VERSION_LESS "3.27.4")
-      string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
-      string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
-      string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
-    endif ()
-
-    # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
-    # to nvptx amd amdgpu targets, passing the target triple is essential.
-    # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
-    if (CMAKE_VERSION VERSION_LESS "3.28")
-      set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
-    endif ()
-  endif ()
-
-  include(CheckFortranSourceCompiles)
-  include(CheckLanguage)
-
-  set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
-  check_language(Fortran)
-  if (CMAKE_Fortran_COMPILER)
-    enable_language(Fortran)
-
-    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
-      # In a bootstrapping build (or any runtimes-build that includes flang-rt),
-      # the intrinsic modules are not built yet. Targets can depend on
-      # flang-rt-mod to ensure that flang-rt's modules are built first.
-      set(FORTRAN_MODULE_DEPS flang-rt-mod)
-      set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
-    else ()
-      # Check whether building modules works, avoid causing the entire build to
-      # fail because of Fortran. The primary situation we want to support here
-      # is Flang, or its intrinsic modules were built separately in a
-      # non-bootstrapping build.
-      check_fortran_builtins_available()
-      if (HAVE_FORTRAN_INTRINSIC_MODS)
-        set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
-        message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
-      else ()
-        message(STATUS "Not compiling Flang modules: Not passing smoke check")
-      endif ()
-    endif ()
-  endif ()
-
-  option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
-else ()
-  set(RUNTIMES_FLANG_MODULES_ENABLED NO)
-endif ()
-
+# Determine wither we can compile Fortran code.
+init_fortran_support()
 
 # Determine whether we are in the runtimes/runtimes-bins directory of a
 # bootstrap build.
@@ -283,6 +99,17 @@ if (LLVM_LIBRARY_DIR AND LLVM_TOOLS_BINARY_DIR AND PACKAGE_VERSION)
   set(LLVM_TREE_AVAILABLE ON)
 endif()
 
+if(LLVM_TREE_AVAILABLE)
+  # Setting these variables will allow the sub-build to put their outputs into
+  # the library and bin directories of the top-level build.
+  set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_LIBRARY_DIR})
+  set(LLVM_RUNTIME_OUTPUT_INTDIR ${LLVM_TOOLS_BINARY_DIR})
+else()
+  # Use own build directory for artifact output.
+  set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
+  set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
+endif()
+
 # CMake omits default compiler include paths, but in runtimes build, we use
 # -nostdinc and -nostdinc++ and control include paths manually so this behavior
 # is undesirable. Filtering CMAKE_{LANG}_IMPLICIT_INCLUDE_DIRECTORIES to remove
@@ -416,30 +243,15 @@ endif()
 
 # Determine output and install paths based on LLVM_TARGET_TRIPLE
 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
-  # just-built compiler without specifying paths to runtime libraries.
-  # LLVM_LIBRARY_OUTPUT_INTDIR/LLVM_RUNTIME_OUTPUT_INTDIR is used by
-  # AddLLVM.cmake as artifact output locations.
-  set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_LIBRARY_DIR})
-  set(LLVM_RUNTIME_OUTPUT_INTDIR ${LLVM_TOOLS_BINARY_DIR})
-
   # 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(RUNTIMES_OUTPUT_RESOURCE_DIR PREFIX "${LLVM_LIBRARY_OUTPUT_INTDIR}/..")
   get_clang_resource_dir(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT)
 else()
-  # In a default runtimes build, do not write into LLVM_BINARY_DIR. It may be
-  # read-only and/or shared by multiple runtimes with different build
-  # configurations (e.g. Debug/Release). Use the runtime's own lib dir like any
-  # non-toolchain library. Use own build directory for artifact output.
-  set(LLVM_LIBRARY_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}")
-  set(LLVM_RUNTIME_OUTPUT_INTDIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin")
-
   # For the install prefix, still use the resource dir assuming the compilers
   # looking for it (Clang, Flang) will be installed there using the same prefix.
-  # This is to not have a difference between bootstrapping and default runtimes
+  # This is to not have a difference between bootstrapping and default/standalone runtimes
   # builds.
   set(RUNTIMES_OUTPUT_RESOURCE_DIR "${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
   set(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
@@ -459,53 +271,30 @@ cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_LIB_DIR)
 cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_LIB_PATH)
 
 
-if (RUNTIMES_FLANG_MODULES_ENABLED)
-  if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
-    # Flang expects its builtin modules in Clang's resource directory
-    get_toolchain_module_subdir(toolchain_mod_subdir)
-    extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
-    extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
-  else ()
-    # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
-    extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
-    extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
-  endif ()
-  cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
-  cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
-
-  # No way to find out which mod files are built by a target, so install the
-  # entire output directory.
-  # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
-  set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
-  cmake_path(NORMAL_PATH destination)
-    install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
-      DESTINATION "${destination}"
-    )
-endif ()
-
-
-if (RUNTIMES_FLANG_MODULES_ENABLED)
-  set(RUNTIMES_DEVICE_ARCHITECTURES "all" CACHE STRING
-      "List of offload device architectures to be used to compile the Fortran offload code (e.g. 'gfx1103;sm_90')"
-    )
-
-  if (RUNTIMES_DEVICE_ARCHITECTURES STREQUAL "all")
-    # TODO: support auto detection on the build system.
-    set(all_amdgpu_architectures
-      "gfx700;gfx701;gfx801;gfx803;gfx900;gfx902;gfx906"
-      "gfx908;gfx90a;gfx90c;gfx940;gfx1010;gfx1030"
-      "gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036"
-      "gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151"
-      "gfx1152;gfx1153")
-    set(all_nvptx_architectures
-      "sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62"
-      "sm_70;sm_72;sm_75;sm_80;sm_86;sm_89;sm_90")
-    set(all_gpu_architectures
-      "${all_amdgpu_architectures};${all_nvptx_architectures}")
-      set(RUNTIMES_DEVICE_ARCHITECTURES ${all_gpu_architectures})
-  endif()
-  list(REMOVE_DUPLICATES RUNTIMES_DEVICE_ARCHITECTURES)
-endif ()
+fortran_output_and_install_paths()
+
+
+# For subprojects supporting offloading targets (offload, flang-rt, ..) specify
+# which architectures should be included in the fat binaries.
+set(RUNTIMES_DEVICE_ARCHITECTURES "all" CACHE STRING
+    "List of offload device architectures to be used to compile the offload code (e.g. 'gfx1103;sm_90')"
+  )
+if (RUNTIMES_DEVICE_ARCHITECTURES STREQUAL "all")
+  # TODO: support auto detection on the build system.
+  set(all_amdgpu_architectures
+    "gfx700;gfx701;gfx801;gfx803;gfx900;gfx902;gfx906"
+    "gfx908;gfx90a;gfx90c;gfx940;gfx1010;gfx1030"
+    "gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036"
+    "gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151"
+    "gfx1152;gfx1153")
+  set(all_nvptx_architectures
+    "sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62"
+    "sm_70;sm_72;sm_75;sm_80;sm_86;sm_89;sm_90")
+  set(all_gpu_architectures
+    "${all_amdgpu_architectures};${all_nvptx_architectures}")
+  set(RUNTIMES_DEVICE_ARCHITECTURES ${all_gpu_architectures})
+endif()
+list(REMOVE_DUPLICATES RUNTIMES_DEVICE_ARCHITECTURES)
 
 
 option(LLVM_INCLUDE_TESTS "Generate build targets for the runtimes unit tests." ON)
diff --git a/runtimes/cmake/Modules/HandleFortran.cmake b/runtimes/cmake/Modules/HandleFortran.cmake
new file mode 100644
index 0000000000000..9ebf69c88a333
--- /dev/null
+++ b/runtimes/cmake/Modules/HandleFortran.cmake
@@ -0,0 +1,226 @@
+
+# Check whether the build environment supports building Fortran modules
+# flang-rt and openmp are the only runtimes that contain Fortran modules.
+#
+# Sets:
+#  * RUNTIMES_FLANG_MODULES_ENABLED Whether .mod files can be created
+#  * CMAKE_Fortran_*                CMake Fortran toolchain info for older versions of CMake
+macro (init_fortran_support)
+  set(FORTRAN_MODULE_DEPS "")
+  if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
+    cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
+
+    if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
+      # CMake 3.24 is the first version of CMake that directly recognizes Flang.
+      # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
+      if (CMAKE_VERSION VERSION_LESS "3.24")
+        include(CMakeForceCompiler)
+        CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
+
+        set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
+        set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
+
+        set(CMAKE_Fortran_SUBMODULE_SEP "-")
+        set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
+
+        set(CMAKE_Fortran_PREPROCESS_SOURCE
+            "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+
+        set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
+        set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
+
+        set(CMAKE_Fortran_MODDIR_FLAG "-J")
+
+        set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+        set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
+        set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
+
+        set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
+        set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+
+        set(CMAKE_Fortran_VERBOSE_FLAG "-v")
+
+        set(CMAKE_Fortran_LINK_MODE DRIVER)
+      endif ()
+
+      # Optimization flags are only passed after CMake 3.27.4
+      # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
+      if (CMAKE_VERSION VERSION_LESS "3.27.4")
+        string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
+        string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
+        string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
+      endif ()
+
+      # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
+      # to nvptx amd amdgpu targets, passing the target triple is essential.
+      # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
+      if (CMAKE_VERSION VERSION_LESS "3.28")
+        set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
+      endif ()
+    endif ()
+
+    include(CheckFortranSourceCompiles)
+    include(CheckLanguage)
+
+    set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
+    check_language(Fortran)
+    if (CMAKE_Fortran_COMPILER)
+        enable_language(Fortran)
+
+        if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+          # In a bootstrapping build (or any runtimes-build that includes flang-rt),
+          # the intrinsic modules are not built yet. Targets can depend on
+          # flang-rt-mod to ensure that flang-rt's modules are built first.
+          set(FORTRAN_MODULE_DEPS flang-rt-mod)
+          set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+        else ()
+          # Check whether building modules works, avoid causing the entire build to
+          # fail because of Fortran. The primary situation we want to support here
+          # is Flang, or its intrinsic modules were built separately in a
+          # non-bootstrapping build.
+          check_fortran_builtins_available()
+          if (HAVE_FORTRAN_INTRINSIC_MODS)
+            set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+            message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
+          else ()
+            message(STATUS "Not compiling Flang modules: Not passing smoke check")
+          endif ()
+        endif ()
+    endif ()
+
+    option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
+  else ()
+    set(RUNTIMES_FLANG_MODULES_ENABLED NO)
+  endif ()
+endmacro ()
+
+
+# Determine the paths for Fortran .mod files.
+#
+# Sets:
+#  * RUNTIMES_OUTPUT_RESOURCE_MOD_DIR   Path for .mod files in build dir
+#  * RUNTIMES_INSTALL_RESOURCE_MOD_PATH Path for .mod files in install dir, relative to CMAKE_INSTALL_PREFIX
+macro (fortran_output_and_install_paths)
+  if (RUNTIMES_FLANG_MODULES_ENABLED)
+    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+      # Flang expects its builtin modules in Clang's resource directory.
+      get_toolchain_module_subdir(toolchain_mod_subdir)
+      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
+      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
+    else ()
+      # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
+      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+    endif ()
+    cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
+    cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
+
+    # No way to find out which mod files are built by a target, so install the
+    # entire output directory.
+    # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
+    set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
+    cmake_path(NORMAL_PATH destination)
+      install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+        DESTINATION "${destination}"
+      )
+  endif ()
+endmacro ()
+
+
+# Check whether the Fortran compiler already access to builtin modules. Sets
+# HAVE_FORTRAN_INTRINSIC_MODS when returning.
+#
+# This must be wrapped in a function because
+# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
+# a compiler introspection environment, see
+# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
+function (check_fortran_builtins_available)
+  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    # CMake's check_fortran_source_compiles/try_compile does not take a
+    # user-defined CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of
+    # test-compiling, ask Flang directly for the builtin module files.
+    if (NOT DEFINED HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD)
+      message(STATUS "Performing Test ISO_C_BINDING_PATH")
+      execute_process(
+        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
+        OUTPUT_VARIABLE ISO_C_BINDING_PATH
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        ERROR_QUIET
+      )
+      set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD "")
+      if (EXISTS "${ISO_C_BINDING_PATH}")
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
+        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      else ()
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
+        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      endif ()
+    endif ()
+  else ()
+    cmake_push_check_state(RESET)
+    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+    check_fortran_source_compiles("
+      subroutine testroutine
+        use iso_c_binding
+      end subroutine
+      " HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
+    cmake_pop_check_state()
+  endif ()
+  set(HAVE_FORTRAN_INTRINSIC_MODS "${HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
+endfunction ()
+
+
+# Set options to compile Fortran module files.
+#
+# Usage:
+#
+# flang_module_target(name
+#   PUBLIC
+#     Modules files are to be used by other Fortran sources. If a library is
+#     compiled multiple times (e.g. static/shared, or msvcrt variants), only
+#     one of those can be public module files; non-public modules are still
+#     generated but to be forgotten deep inside the build directory to not
+#     conflict with each other.
+#     Also, installs the module with the toolchain.
+# )
+function (flang_module_target tgtname)
+  set(options PUBLIC)
+  cmake_parse_arguments(ARG
+    "${options}"
+    ""
+    ""
+    ${ARGN})
+
+  if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
+    message(WARNING "Cannot build module files for ${tgtname} when RUNTIMES_FLANG_MODULES_ENABLED is ${RUNTIMES_FLANG_MODULES_ENABLED}")
+    return ()
+  endif ()
+
+  target_compile_options(${tgtname} PRIVATE
+      # Let non-public modules find the public module files
+      "$<$<COMPILE_LANGUAGE:Fortran>:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
+
+      # Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
+    )
+
+  if (LLVM_RUNTIMES_TARGET MATCHES "^nvptx")
+    foreach (_arch IN LISTS RUNTIMES_DEVICE_ARCHITECTURES)
+      target_compile_options(${tgtname} PRIVATE
+       "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
+      )
+    endforeach()
+  endif ()
+
+  if (ARG_PUBLIC)
+    set_target_properties(${tgtname}
+      PROPERTIES
+        Fortran_MODULE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+      )
+  else ()
+    set_target_properties(${tgtname}
+      PROPERTIES
+        Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${tgtname}.mod"
+      )
+  endif ()
+endfunction ()

>From a6e27b28cf1d408db543cf53bf9cf445ae9454ef Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 19 Jan 2026 12:44:40 +0100
Subject: [PATCH 06/13] Fix dir name case

---
 runtimes/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 768fddb8b4dd7..4254e33ad7655 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -26,7 +26,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
 list(INSERT CMAKE_MODULE_PATH 0
   "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
-  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
+  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
   "${LLVM_COMMON_CMAKE_UTILS}"
   "${LLVM_COMMON_CMAKE_UTILS}/Modules"
   "${CMAKE_CURRENT_SOURCE_DIR}/../llvm/cmake"

>From 419570d06d2b42ef831cbcc8b62c324c5433c1b5 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 19 Jan 2026 12:57:15 +0100
Subject: [PATCH 07/13] Try fixing libcxx-ci build issue

---
 runtimes/CMakeLists.txt                       |   5 +-
 ...an.cmake => config-runtimes-Fortran.cmake} | 230 +++++++++---------
 2 files changed, 118 insertions(+), 117 deletions(-)
 rename runtimes/cmake/{Modules/HandleFortran.cmake => config-runtimes-Fortran.cmake} (57%)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 4254e33ad7655..04899ca4583f7 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -89,8 +89,9 @@ include(GetToolchainDirs)
 include(ExtendPath)
 include(HandleFortran)
 
-# Determine wither we can compile Fortran code.
-init_fortran_support()
+# Handle Fortran code. Sets RUNTIMES_FLANG_MODULES_ENABLED when a Fortran
+# toolchain is available and required by one or more of the LLVM_ENABLED_RUNTIMES.
+include(config-runtimes-Fortran)
 
 # Determine whether we are in the runtimes/runtimes-bins directory of a
 # bootstrap build.
diff --git a/runtimes/cmake/Modules/HandleFortran.cmake b/runtimes/cmake/config-runtimes-Fortran.cmake
similarity index 57%
rename from runtimes/cmake/Modules/HandleFortran.cmake
rename to runtimes/cmake/config-runtimes-Fortran.cmake
index 9ebf69c88a333..5a8b03602acd2 100644
--- a/runtimes/cmake/Modules/HandleFortran.cmake
+++ b/runtimes/cmake/config-runtimes-Fortran.cmake
@@ -1,98 +1,140 @@
-
 # Check whether the build environment supports building Fortran modules
 # flang-rt and openmp are the only runtimes that contain Fortran modules.
 #
 # Sets:
 #  * RUNTIMES_FLANG_MODULES_ENABLED Whether .mod files can be created
 #  * CMAKE_Fortran_*                CMake Fortran toolchain info for older versions of CMake
-macro (init_fortran_support)
-  set(FORTRAN_MODULE_DEPS "")
-  if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
-    cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
 
-    if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
-      # CMake 3.24 is the first version of CMake that directly recognizes Flang.
-      # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
-      if (CMAKE_VERSION VERSION_LESS "3.24")
-        include(CMakeForceCompiler)
-        CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
 
-        set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
-        set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
+# Check whether the Fortran compiler already has access to builtin modules. Sets
+# HAVE_FORTRAN_INTRINSIC_MODS when returning.
+#
+# This must be wrapped in a function because
+# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
+# a compiler introspection environment, see
+# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
+function (check_fortran_builtins_available)
+  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    # CMake's check_fortran_source_compiles/try_compile does not take a
+    # user-defined CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of
+    # test-compiling, ask Flang directly for the builtin module files.
+    if (NOT DEFINED HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD)
+      message(STATUS "Performing Test ISO_C_BINDING_PATH")
+      execute_process(
+        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
+        OUTPUT_VARIABLE ISO_C_BINDING_PATH
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        ERROR_QUIET
+      )
+      set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD "")
+      if (EXISTS "${ISO_C_BINDING_PATH}")
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
+        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      else ()
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
+        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      endif ()
+    endif ()
+  else ()
+    cmake_push_check_state(RESET)
+    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+    check_fortran_source_compiles("
+      subroutine testroutine
+        use iso_c_binding
+      end subroutine
+      " HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
+    cmake_pop_check_state()
+  endif ()
+  set(HAVE_FORTRAN_INTRINSIC_MODS "${HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
+endfunction ()
+
+
+set(FORTRAN_MODULE_DEPS "")
+if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
+  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
 
-        set(CMAKE_Fortran_SUBMODULE_SEP "-")
-        set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
+  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
+    # CMake 3.24 is the first version of CMake that directly recognizes Flang.
+    # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
+    if (CMAKE_VERSION VERSION_LESS "3.24")
+      include(CMakeForceCompiler)
+      CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
 
-        set(CMAKE_Fortran_PREPROCESS_SOURCE
-            "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+      set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
+      set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
 
-        set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
-        set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
+      set(CMAKE_Fortran_SUBMODULE_SEP "-")
+      set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
 
-        set(CMAKE_Fortran_MODDIR_FLAG "-J")
+      set(CMAKE_Fortran_PREPROCESS_SOURCE
+          "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
 
-        set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
-        set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
-        set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
+      set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
+      set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
 
-        set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
-        set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+      set(CMAKE_Fortran_MODDIR_FLAG "-J")
 
-        set(CMAKE_Fortran_VERBOSE_FLAG "-v")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
+      set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
 
-        set(CMAKE_Fortran_LINK_MODE DRIVER)
-      endif ()
+      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
+      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
 
-      # Optimization flags are only passed after CMake 3.27.4
-      # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
-      if (CMAKE_VERSION VERSION_LESS "3.27.4")
-        string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
-        string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
-        string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
-      endif ()
+      set(CMAKE_Fortran_VERBOSE_FLAG "-v")
 
-      # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
-      # to nvptx amd amdgpu targets, passing the target triple is essential.
-      # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
-      if (CMAKE_VERSION VERSION_LESS "3.28")
-        set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
-      endif ()
+      set(CMAKE_Fortran_LINK_MODE DRIVER)
+    endif ()
+
+    # Optimization flags are only passed after CMake 3.27.4
+    # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
+    if (CMAKE_VERSION VERSION_LESS "3.27.4")
+      string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
+      string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
+      string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
+    endif ()
+
+    # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
+    # to nvptx amd amdgpu targets, passing the target triple is essential.
+    # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
+    if (CMAKE_VERSION VERSION_LESS "3.28")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
     endif ()
+  endif ()
 
-    include(CheckFortranSourceCompiles)
-    include(CheckLanguage)
+  include(CheckFortranSourceCompiles)
+  include(CheckLanguage)
 
-    set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
-    check_language(Fortran)
-    if (CMAKE_Fortran_COMPILER)
-        enable_language(Fortran)
+  set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
+  check_language(Fortran)
+  if (CMAKE_Fortran_COMPILER)
+      enable_language(Fortran)
 
-        if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
-          # In a bootstrapping build (or any runtimes-build that includes flang-rt),
-          # the intrinsic modules are not built yet. Targets can depend on
-          # flang-rt-mod to ensure that flang-rt's modules are built first.
-          set(FORTRAN_MODULE_DEPS flang-rt-mod)
+      if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+        # In a bootstrapping build (or any runtimes-build that includes flang-rt),
+        # the intrinsic modules are not built yet. Targets can depend on
+        # flang-rt-mod to ensure that flang-rt's modules are built first.
+        set(FORTRAN_MODULE_DEPS flang-rt-mod)
+        set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+      else ()
+        # Check whether building modules works, avoid causing the entire build to
+        # fail because of Fortran. The primary situation we want to support here
+        # is Flang, or its intrinsic modules were built separately in a
+        # non-bootstrapping build.
+        check_fortran_builtins_available()
+        if (HAVE_FORTRAN_INTRINSIC_MODS)
           set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+          message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
         else ()
-          # Check whether building modules works, avoid causing the entire build to
-          # fail because of Fortran. The primary situation we want to support here
-          # is Flang, or its intrinsic modules were built separately in a
-          # non-bootstrapping build.
-          check_fortran_builtins_available()
-          if (HAVE_FORTRAN_INTRINSIC_MODS)
-            set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
-            message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
-          else ()
-            message(STATUS "Not compiling Flang modules: Not passing smoke check")
-          endif ()
+          message(STATUS "Not compiling Flang modules: Not passing smoke check")
         endif ()
-    endif ()
-
-    option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
-  else ()
-    set(RUNTIMES_FLANG_MODULES_ENABLED NO)
+      endif ()
   endif ()
-endmacro ()
+
+  option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
+else ()
+  set(RUNTIMES_FLANG_MODULES_ENABLED NO)
+endif ()
 
 
 # Determine the paths for Fortran .mod files.
@@ -116,7 +158,8 @@ macro (fortran_output_and_install_paths)
     cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
 
     # No way to find out which mod files are built by a target, so install the
-    # entire output directory.
+    # entire output directory. flang_module_target() will copy (only) the PUBLIC
+    # .mod file into the output directory.
     # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
     set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
     cmake_path(NORMAL_PATH destination)
@@ -127,50 +170,7 @@ macro (fortran_output_and_install_paths)
 endmacro ()
 
 
-# Check whether the Fortran compiler already access to builtin modules. Sets
-# HAVE_FORTRAN_INTRINSIC_MODS when returning.
-#
-# This must be wrapped in a function because
-# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
-# a compiler introspection environment, see
-# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
-function (check_fortran_builtins_available)
-  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
-    # CMake's check_fortran_source_compiles/try_compile does not take a
-    # user-defined CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of
-    # test-compiling, ask Flang directly for the builtin module files.
-    if (NOT DEFINED HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD)
-      message(STATUS "Performing Test ISO_C_BINDING_PATH")
-      execute_process(
-        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
-        OUTPUT_VARIABLE ISO_C_BINDING_PATH
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-        ERROR_QUIET
-      )
-      set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD "")
-      if (EXISTS "${ISO_C_BINDING_PATH}")
-        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
-        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
-      else ()
-        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
-        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
-      endif ()
-    endif ()
-  else ()
-    cmake_push_check_state(RESET)
-    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
-    check_fortran_source_compiles("
-      subroutine testroutine
-        use iso_c_binding
-      end subroutine
-      " HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
-    cmake_pop_check_state()
-  endif ()
-  set(HAVE_FORTRAN_INTRINSIC_MODS "${HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
-endfunction ()
-
-
-# Set options to compile Fortran module files.
+# Set options to compile Fortran module files. Assumes the code above has run.
 #
 # Usage:
 #
@@ -207,7 +207,7 @@ function (flang_module_target tgtname)
   if (LLVM_RUNTIMES_TARGET MATCHES "^nvptx")
     foreach (_arch IN LISTS RUNTIMES_DEVICE_ARCHITECTURES)
       target_compile_options(${tgtname} PRIVATE
-       "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
+        "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
       )
     endforeach()
   endif ()

>From 774bd7e582ca2115165865c367f505986bee0f4d Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 19 Jan 2026 13:33:44 +0100
Subject: [PATCH 08/13] Build fix

---
 runtimes/CMakeLists.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 04899ca4583f7..8aae896536af0 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -87,10 +87,10 @@ include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
 include(GetToolchainDirs)
 include(ExtendPath)
-include(HandleFortran)
 
 # Handle Fortran code. Sets RUNTIMES_FLANG_MODULES_ENABLED when a Fortran
-# toolchain is available and required by one or more of the LLVM_ENABLED_RUNTIMES.
+# toolchain is available and required by one or more of the
+# runtimes.
 include(config-runtimes-Fortran)
 
 # Determine whether we are in the runtimes/runtimes-bins directory of a

>From f828f3c2d856a7e6f670c972a5169db85c5b770e Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 19 Jan 2026 17:59:53 +0100
Subject: [PATCH 09/13] Address review comments

---
 runtimes/cmake/config-runtimes-Fortran.cmake | 459 ++++++++++---------
 1 file changed, 233 insertions(+), 226 deletions(-)

diff --git a/runtimes/cmake/config-runtimes-Fortran.cmake b/runtimes/cmake/config-runtimes-Fortran.cmake
index 5a8b03602acd2..0db329ed09e4c 100644
--- a/runtimes/cmake/config-runtimes-Fortran.cmake
+++ b/runtimes/cmake/config-runtimes-Fortran.cmake
@@ -1,226 +1,233 @@
-# Check whether the build environment supports building Fortran modules
-# flang-rt and openmp are the only runtimes that contain Fortran modules.
-#
-# Sets:
-#  * RUNTIMES_FLANG_MODULES_ENABLED Whether .mod files can be created
-#  * CMAKE_Fortran_*                CMake Fortran toolchain info for older versions of CMake
-
-
-# Check whether the Fortran compiler already has access to builtin modules. Sets
-# HAVE_FORTRAN_INTRINSIC_MODS when returning.
-#
-# This must be wrapped in a function because
-# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
-# a compiler introspection environment, see
-# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
-function (check_fortran_builtins_available)
-  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
-    # CMake's check_fortran_source_compiles/try_compile does not take a
-    # user-defined CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of
-    # test-compiling, ask Flang directly for the builtin module files.
-    if (NOT DEFINED HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD)
-      message(STATUS "Performing Test ISO_C_BINDING_PATH")
-      execute_process(
-        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
-        OUTPUT_VARIABLE ISO_C_BINDING_PATH
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-        ERROR_QUIET
-      )
-      set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD "")
-      if (EXISTS "${ISO_C_BINDING_PATH}")
-        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
-        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
-      else ()
-        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
-        set(HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
-      endif ()
-    endif ()
-  else ()
-    cmake_push_check_state(RESET)
-    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
-    check_fortran_source_compiles("
-      subroutine testroutine
-        use iso_c_binding
-      end subroutine
-      " HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
-    cmake_pop_check_state()
-  endif ()
-  set(HAVE_FORTRAN_INTRINSIC_MODS "${HAVE_FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
-endfunction ()
-
-
-set(FORTRAN_MODULE_DEPS "")
-if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
-  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
-
-  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
-    # CMake 3.24 is the first version of CMake that directly recognizes Flang.
-    # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
-    if (CMAKE_VERSION VERSION_LESS "3.24")
-      include(CMakeForceCompiler)
-      CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
-
-      set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
-      set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
-
-      set(CMAKE_Fortran_SUBMODULE_SEP "-")
-      set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
-
-      set(CMAKE_Fortran_PREPROCESS_SOURCE
-          "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
-
-      set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
-      set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
-
-      set(CMAKE_Fortran_MODDIR_FLAG "-J")
-
-      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
-      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
-      set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
-
-      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
-      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
-
-      set(CMAKE_Fortran_VERBOSE_FLAG "-v")
-
-      set(CMAKE_Fortran_LINK_MODE DRIVER)
-    endif ()
-
-    # Optimization flags are only passed after CMake 3.27.4
-    # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
-    if (CMAKE_VERSION VERSION_LESS "3.27.4")
-      string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
-      string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
-      string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
-    endif ()
-
-    # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
-    # to nvptx amd amdgpu targets, passing the target triple is essential.
-    # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
-    if (CMAKE_VERSION VERSION_LESS "3.28")
-      set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
-    endif ()
-  endif ()
-
-  include(CheckFortranSourceCompiles)
-  include(CheckLanguage)
-
-  set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
-  check_language(Fortran)
-  if (CMAKE_Fortran_COMPILER)
-      enable_language(Fortran)
-
-      if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
-        # In a bootstrapping build (or any runtimes-build that includes flang-rt),
-        # the intrinsic modules are not built yet. Targets can depend on
-        # flang-rt-mod to ensure that flang-rt's modules are built first.
-        set(FORTRAN_MODULE_DEPS flang-rt-mod)
-        set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
-      else ()
-        # Check whether building modules works, avoid causing the entire build to
-        # fail because of Fortran. The primary situation we want to support here
-        # is Flang, or its intrinsic modules were built separately in a
-        # non-bootstrapping build.
-        check_fortran_builtins_available()
-        if (HAVE_FORTRAN_INTRINSIC_MODS)
-          set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
-          message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
-        else ()
-          message(STATUS "Not compiling Flang modules: Not passing smoke check")
-        endif ()
-      endif ()
-  endif ()
-
-  option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
-else ()
-  set(RUNTIMES_FLANG_MODULES_ENABLED NO)
-endif ()
-
-
-# Determine the paths for Fortran .mod files.
-#
-# Sets:
-#  * RUNTIMES_OUTPUT_RESOURCE_MOD_DIR   Path for .mod files in build dir
-#  * RUNTIMES_INSTALL_RESOURCE_MOD_PATH Path for .mod files in install dir, relative to CMAKE_INSTALL_PREFIX
-macro (fortran_output_and_install_paths)
-  if (RUNTIMES_FLANG_MODULES_ENABLED)
-    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
-      # Flang expects its builtin modules in Clang's resource directory.
-      get_toolchain_module_subdir(toolchain_mod_subdir)
-      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
-      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
-    else ()
-      # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
-      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
-      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
-    endif ()
-    cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
-    cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
-
-    # No way to find out which mod files are built by a target, so install the
-    # entire output directory. flang_module_target() will copy (only) the PUBLIC
-    # .mod file into the output directory.
-    # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
-    set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
-    cmake_path(NORMAL_PATH destination)
-      install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
-        DESTINATION "${destination}"
-      )
-  endif ()
-endmacro ()
-
-
-# Set options to compile Fortran module files. Assumes the code above has run.
-#
-# Usage:
-#
-# flang_module_target(name
-#   PUBLIC
-#     Modules files are to be used by other Fortran sources. If a library is
-#     compiled multiple times (e.g. static/shared, or msvcrt variants), only
-#     one of those can be public module files; non-public modules are still
-#     generated but to be forgotten deep inside the build directory to not
-#     conflict with each other.
-#     Also, installs the module with the toolchain.
-# )
-function (flang_module_target tgtname)
-  set(options PUBLIC)
-  cmake_parse_arguments(ARG
-    "${options}"
-    ""
-    ""
-    ${ARGN})
-
-  if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
-    message(WARNING "Cannot build module files for ${tgtname} when RUNTIMES_FLANG_MODULES_ENABLED is ${RUNTIMES_FLANG_MODULES_ENABLED}")
-    return ()
-  endif ()
-
-  target_compile_options(${tgtname} PRIVATE
-      # Let non-public modules find the public module files
-      "$<$<COMPILE_LANGUAGE:Fortran>:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
-
-      # Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
-      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
-    )
-
-  if (LLVM_RUNTIMES_TARGET MATCHES "^nvptx")
-    foreach (_arch IN LISTS RUNTIMES_DEVICE_ARCHITECTURES)
-      target_compile_options(${tgtname} PRIVATE
-        "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
-      )
-    endforeach()
-  endif ()
-
-  if (ARG_PUBLIC)
-    set_target_properties(${tgtname}
-      PROPERTIES
-        Fortran_MODULE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
-      )
-  else ()
-    set_target_properties(${tgtname}
-      PROPERTIES
-        Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${tgtname}.mod"
-      )
-  endif ()
-endfunction ()
+# Check whether the build environment supports building Fortran modules
+# flang-rt and openmp are the only runtimes that contain Fortran modules.
+#
+# Sets:
+#  * RUNTIMES_FLANG_MODULES_ENABLED Whether .mod files can be created
+#  * CMAKE_Fortran_*                CMake Fortran toolchain info for older versions of CMake
+
+
+# Check whether the Fortran compiler already has access to builtin modules. Sets
+# HAVE_FORTRAN_INTRINSIC_MODS when returning.
+#
+# This must be wrapped in a function because
+# cmake_push_check_state/cmake_pop_check_state is insufficient to isolate
+# a compiler introspection environment, see
+# https://gitlab.kitware.com/cmake/cmake/-/issues/27419
+function (check_fortran_builtins_available)
+  if (CMAKE_Fortran_COMPILER_FORCED AND CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    # CMake's check_fortran_source_compiles/try_compile does not take a
+    # user-defined CMAKE_Fortran_PREPROCESS_SOURCE into account. Instead of
+    # test-compiling, ask Flang directly for the builtin module files.
+    # CMAKE_Fortran_PREPROCESS_SOURCE is defined for CMake < 3.24 because it
+    # does not natively recognize Flang (see below). Once we bump the required
+    # CMake version, and because setting CMAKE_Fortran_PREPROCESS_SOURCE has
+    # been deprecated by CMake, this workaround can be removed.
+    if (NOT DEFINED FORTRAN_HAS_ISO_C_BINDING_MOD)
+      message(STATUS "Performing Test ISO_C_BINDING_PATH")
+      execute_process(
+        COMMAND ${CMAKE_Fortran_COMPILER} ${CMAKE_Fortran_FLAGS} "-print-file-name=iso_c_binding.mod"
+        OUTPUT_VARIABLE ISO_C_BINDING_PATH
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+        ERROR_QUIET
+      )
+      set(FORTRAN_HAS_ISO_C_BINDING_MOD "")
+      if (EXISTS "${ISO_C_BINDING_PATH}")
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Success")
+        set(FORTRAN_HAS_ISO_C_BINDING_MOD TRUE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      else ()
+        message(STATUS "Performing Test ISO_C_BINDING_PATH -- Failed")
+        set(FORTRAN_HAS_ISO_C_BINDING_MOD FALSE CACHE INTERNAL "Existence result of ${CMAKE_Fortran_COMPILER} -print-file-name=iso_c_binding.mod")
+      endif ()
+    endif ()
+  else ()
+    cmake_push_check_state(RESET)
+    set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
+    check_fortran_source_compiles("
+      subroutine testroutine
+        use iso_c_binding
+      end subroutine
+      " FORTRAN_HAS_ISO_C_BINDING_MOD SRC_EXT F90)
+    cmake_pop_check_state()
+  endif ()
+  set(HAVE_FORTRAN_INTRINSIC_MODS "${FORTRAN_HAS_ISO_C_BINDING_MOD}" PARENT_SCOPE)
+endfunction ()
+
+
+set(FORTRAN_MODULE_DEPS "")
+if (CMAKE_Fortran_COMPILER AND ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES OR "openmp" IN_LIST LLVM_ENABLE_RUNTIMES))
+  cmake_path(GET CMAKE_Fortran_COMPILER STEM _Fortran_COMPILER_STEM)
+
+  if (_Fortran_COMPILER_STEM STREQUAL "flang-new" OR _Fortran_COMPILER_STEM STREQUAL "flang")
+    # CMake 3.24 is the first version of CMake that directly recognizes Flang.
+    # LLVM's requirement is only CMake 3.20, teach CMake 3.20-3.23 how to use Flang, if used.
+    if (CMAKE_VERSION VERSION_LESS "3.24")
+      include(CMakeForceCompiler)
+      CMAKE_FORCE_Fortran_COMPILER("${CMAKE_Fortran_COMPILER}" "LLVMFlang")
+
+      set(CMAKE_Fortran_COMPILER_ID "LLVMFlang")
+      set(CMAKE_Fortran_COMPILER_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
+
+      set(CMAKE_Fortran_SUBMODULE_SEP "-")
+      set(CMAKE_Fortran_SUBMODULE_EXT ".mod")
+
+      set(CMAKE_Fortran_PREPROCESS_SOURCE
+          "<CMAKE_Fortran_COMPILER> -cpp <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
+
+      set(CMAKE_Fortran_FORMAT_FIXED_FLAG "-ffixed-form")
+      set(CMAKE_Fortran_FORMAT_FREE_FLAG "-ffree-form")
+
+      set(CMAKE_Fortran_MODDIR_FLAG "-J")
+
+      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON "-cpp")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF "-nocpp")
+      set(CMAKE_Fortran_POSTPROCESS_FLAG "-ffixed-line-length-72")
+
+      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG "-Wl,")
+      set(CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP ",")
+
+      set(CMAKE_Fortran_VERBOSE_FLAG "-v")
+
+      set(CMAKE_Fortran_LINK_MODE DRIVER)
+    endif ()
+
+    # Optimization flags are only passed after CMake 3.27.4
+    # https://gitlab.kitware.com/cmake/cmake/-/commit/1140087adea98bd8d8974e4c18979f4949b52c34
+    if (CMAKE_VERSION VERSION_LESS "3.27.4")
+      string(APPEND CMAKE_Fortran_FLAGS_DEBUG_INIT " -O0 -g")
+      string(APPEND CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT " -O2 -g")
+      string(APPEND CMAKE_Fortran_FLAGS_RELEASE_INIT " -O3")
+    endif ()
+
+    # Only CMake 3.28+ pass --target= to Flang. But for cross-compiling, including
+    # to nvptx amd amdgpu targets, passing the target triple is essential.
+    # https://gitlab.kitware.com/cmake/cmake/-/commit/e9af7b968756e72553296ecdcde6f36606a0babf
+    if (CMAKE_VERSION VERSION_LESS "3.28")
+      set(CMAKE_Fortran_COMPILE_OPTIONS_TARGET "--target=")
+    endif ()
+  endif ()
+
+  include(CheckFortranSourceCompiles)
+  include(CheckLanguage)
+
+  set(RUNTIMES_FLANG_MODULES_ENABLED_default OFF)
+  check_language(Fortran)
+  if (CMAKE_Fortran_COMPILER)
+    enable_language(Fortran)
+
+    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang" AND "flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+      # In a bootstrapping build (or any runtimes-build that includes flang-rt),
+      # the intrinsic modules are not built yet. Targets can depend on
+      # flang-rt-mod to ensure that flang-rt's modules are built first.
+      set(FORTRAN_MODULE_DEPS flang-rt-mod)
+      set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+    else ()
+      # Check whether building modules works, avoid causing the entire build to
+      # fail because of Fortran. The primary situation we want to support here
+      # is Flang, or its intrinsic modules were built separately in a
+      # non-bootstrapping build.
+      check_fortran_builtins_available()
+      if (HAVE_FORTRAN_INTRINSIC_MODS)
+        set(RUNTIMES_FLANG_MODULES_ENABLED_default ON)
+        message(STATUS "${LLVM_SUBPROJECT_TITLE}: Non-bootstrapping Fortran modules build (${CMAKE_Fortran_COMPILER_ID} located at ${CMAKE_Fortran_COMPILER})")
+      else ()
+        message(STATUS "Not compiling Flang modules: Not passing smoke check")
+      endif ()
+    endif ()
+  endif ()
+
+  option(RUNTIMES_FLANG_MODULES_ENABLED "Build Fortran modules" "${RUNTIMES_FLANG_MODULES_ENABLED_default}")
+else ()
+  set(RUNTIMES_FLANG_MODULES_ENABLED NO)
+endif ()
+
+
+# Determine the paths for Fortran .mod files.
+#
+# Sets:
+#  * RUNTIMES_OUTPUT_RESOURCE_MOD_DIR   Path for .mod files in build dir
+#  * RUNTIMES_INSTALL_RESOURCE_MOD_PATH Path for .mod files in install dir, relative to CMAKE_INSTALL_PREFIX
+macro (fortran_output_and_install_paths)
+  if (RUNTIMES_FLANG_MODULES_ENABLED)
+    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+      # Flang expects its builtin modules in Clang's resource directory.
+      get_toolchain_module_subdir(toolchain_mod_subdir)
+      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
+      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
+    else ()
+      # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
+      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+    endif ()
+    cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
+    cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
+
+    # No way to find out which mod files are built by a target, so install the
+    # entire output directory. flang_module_target() will copy (only) the PUBLIC
+    # .mod file into the output directory.
+    # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
+    set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
+    cmake_path(NORMAL_PATH destination)
+      install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+        DESTINATION "${destination}"
+      )
+  endif ()
+endmacro ()
+
+
+# Set options to compile Fortran module files. Assumes the code above has run.
+#
+# Usage:
+#
+# flang_module_target(name
+#   PUBLIC
+#     Modules files are to be used by other Fortran sources. If a library is
+#     compiled multiple times (e.g. static/shared, or msvcrt variants), only
+#     one of those can be public module files; non-public modules are still
+#     generated but to be forgotten deep inside the build directory to not
+#     conflict with each other.
+#     Also, installs the module with the toolchain.
+# )
+function (flang_module_target tgtname)
+  set(options PUBLIC)
+  cmake_parse_arguments(ARG
+    "${options}"
+    ""
+    ""
+    ${ARGN})
+
+  if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
+    message(WARNING "Cannot build module files for ${tgtname} when RUNTIMES_FLANG_MODULES_ENABLED is ${RUNTIMES_FLANG_MODULES_ENABLED}")
+    return ()
+  endif ()
+
+  target_compile_options(${tgtname} PRIVATE
+      # Let non-public modules find the public module files
+      "$<$<COMPILE_LANGUAGE:Fortran>:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
+
+      # Flang bug workaround: Reformating of cooked token buffer causes
+      # identifier to be split between lines
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
+    )
+
+  # `flang --target=nvptx64` fails when not specifying `-march`, even when only
+  # emitting .mod files. Ensure that we pass `-march`.
+  if (LLVM_RUNTIMES_TARGET MATCHES "^nvptx")
+    foreach (_arch IN LISTS RUNTIMES_DEVICE_ARCHITECTURES)
+      target_compile_options(${tgtname} PRIVATE
+        "$<$<COMPILE_LANGUAGE:Fortran>:-march=${_arch}>"
+      )
+    endforeach()
+  endif ()
+
+  if (ARG_PUBLIC)
+    set_target_properties(${tgtname}
+      PROPERTIES
+        Fortran_MODULE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+      )
+  else ()
+    set_target_properties(${tgtname}
+      PROPERTIES
+        Fortran_MODULE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${tgtname}.mod"
+      )
+  endif ()
+endfunction ()

>From e632eab10f75c5ea82b37dc076683776311e5dc1 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Fri, 23 Jan 2026 15:13:45 +0100
Subject: [PATCH 10/13] rename config-runtimes-Fortran.cmake ->
 config-Fortran.cmake

---
 runtimes/CMakeLists.txt                                         | 2 +-
 .../{config-runtimes-Fortran.cmake => config-Fortran.cmake}     | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename runtimes/cmake/{config-runtimes-Fortran.cmake => config-Fortran.cmake} (100%)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 8aae896536af0..86b7bccb14a35 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -91,7 +91,7 @@ include(ExtendPath)
 # Handle Fortran code. Sets RUNTIMES_FLANG_MODULES_ENABLED when a Fortran
 # toolchain is available and required by one or more of the
 # runtimes.
-include(config-runtimes-Fortran)
+include(config-Fortran)
 
 # Determine whether we are in the runtimes/runtimes-bins directory of a
 # bootstrap build.
diff --git a/runtimes/cmake/config-runtimes-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake
similarity index 100%
rename from runtimes/cmake/config-runtimes-Fortran.cmake
rename to runtimes/cmake/config-Fortran.cmake

>From 51c04af7d7465dc374eed3736c13e70cfbf5ee42 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Fri, 23 Jan 2026 16:22:49 +0100
Subject: [PATCH 11/13] Consecutive Fortran-handling cmake code

---
 runtimes/CMakeLists.txt             | 14 ++++-----
 runtimes/cmake/config-Fortran.cmake | 48 ++++++++++++++---------------
 2 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 86b7bccb14a35..78d194aea3cdb 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -88,11 +88,6 @@ include(CheckCXXCompilerFlag)
 include(GetToolchainDirs)
 include(ExtendPath)
 
-# Handle Fortran code. Sets RUNTIMES_FLANG_MODULES_ENABLED when a Fortran
-# toolchain is available and required by one or more of the
-# runtimes.
-include(config-Fortran)
-
 # Determine whether we are in the runtimes/runtimes-bins directory of a
 # bootstrap build.
 set(LLVM_TREE_AVAILABLE OFF)
@@ -258,7 +253,7 @@ else()
   set(RUNTIMES_INSTALL_RESOURCE_PATH_DEFAULT "lib${LLVM_LIBDIR_SUFFIX}/clang/${LLVM_VERSION_MAJOR}")
 endif()
 
-# Determine build and install paths. The ouptut paths are absolute, but the
+# Determine build and install paths. The output paths are absolute, but the
 # install dirs are relative to CMAKE_INSTALL_PREFIX to be resolved by CMake.
 get_toolchain_library_subdir(toolchain_lib_subdir)
 extend_path(RUNTIMES_OUTPUT_RESOURCE_LIB_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_lib_subdir}")
@@ -272,7 +267,12 @@ cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_LIB_DIR)
 cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_LIB_PATH)
 
 
-fortran_output_and_install_paths()
+# Handle Fortran code. When a Fortran  toolchain is available and required by
+# one or more of the runtimes, enables CMake's Fortran support and sets
+# RUNTIMES_FLANG_MODULES_ENABLED.
+# Makes use of RUNTIMES_OUTPUT_RESOURCE_DIR, RUNTIMES_INSTALL_RESOURCE_PATH,
+# hence must be included their those variables are defined.
+include(config-Fortran)
 
 
 # For subprojects supporting offloading targets (offload, flang-rt, ..) specify
diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake
index 0db329ed09e4c..a36003655d25a 100644
--- a/runtimes/cmake/config-Fortran.cmake
+++ b/runtimes/cmake/config-Fortran.cmake
@@ -146,32 +146,30 @@ endif ()
 # Sets:
 #  * RUNTIMES_OUTPUT_RESOURCE_MOD_DIR   Path for .mod files in build dir
 #  * RUNTIMES_INSTALL_RESOURCE_MOD_PATH Path for .mod files in install dir, relative to CMAKE_INSTALL_PREFIX
-macro (fortran_output_and_install_paths)
-  if (RUNTIMES_FLANG_MODULES_ENABLED)
-    if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
-      # Flang expects its builtin modules in Clang's resource directory.
-      get_toolchain_module_subdir(toolchain_mod_subdir)
-      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
-      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
-    else ()
-      # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
-      extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
-      extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
-    endif ()
-    cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
-    cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
-
-    # No way to find out which mod files are built by a target, so install the
-    # entire output directory. flang_module_target() will copy (only) the PUBLIC
-    # .mod file into the output directory.
-    # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
-    set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
-    cmake_path(NORMAL_PATH destination)
-      install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
-        DESTINATION "${destination}"
-      )
+if (RUNTIMES_FLANG_MODULES_ENABLED)
+  if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    # Flang expects its builtin modules in Clang's resource directory.
+    get_toolchain_module_subdir(toolchain_mod_subdir)
+    extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "${toolchain_mod_subdir}")
+    extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "${toolchain_mod_subdir}")
+  else ()
+    # For non-Flang compilers, avoid the risk of Flang accidentally picking them up.
+    extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${RUNTIMES_OUTPUT_RESOURCE_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
+    extend_path(RUNTIMES_INSTALL_RESOURCE_MOD_PATH "${RUNTIMES_INSTALL_RESOURCE_PATH}" "finclude-${CMAKE_Fortran_COMPILER_ID}")
   endif ()
-endmacro ()
+  cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR)
+  cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_MOD_PATH)
+
+  # No way to find out which mod files are built by a target, so install the
+  # entire output directory. flang_module_target() will copy (only) the PUBLIC
+  # .mod file into the output directory.
+  # https://stackoverflow.com/questions/52712416/cmake-fortran-module-directory-to-be-used-with-add-library
+  set(destination "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..")
+  cmake_path(NORMAL_PATH destination)
+    install(DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}"
+      DESTINATION "${destination}"
+    )
+endif ()
 
 
 # Set options to compile Fortran module files. Assumes the code above has run.

>From 161298fa144aecb27d960ce8d610f743ca84e6f2 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Mon, 26 Jan 2026 13:01:10 +0100
Subject: [PATCH 12/13] avoid unrelated change

---
 runtimes/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 78d194aea3cdb..027b90da9b17d 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -26,7 +26,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
 list(INSERT CMAKE_MODULE_PATH 0
   "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
-  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
+  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules"
   "${LLVM_COMMON_CMAKE_UTILS}"
   "${LLVM_COMMON_CMAKE_UTILS}/Modules"
   "${CMAKE_CURRENT_SOURCE_DIR}/../llvm/cmake"

>From c8280ddb02dab6df5897bc965a5fd95f382d31b2 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Sat, 21 Mar 2026 01:58:40 +0100
Subject: [PATCH 13/13] Apply changes from runtimes_resource-dir

---
 cmake/Modules/GetToolchainDirs.cmake          | 85 ++++++++++---------
 .../cmake/Modules/CompilerRTUtils.cmake       | 50 ++---------
 compiler-rt/cmake/base-config-ix.cmake        |  2 +
 libc/CMakeLists.txt                           |  2 +
 libcxx/CMakeLists.txt                         |  1 +
 libcxxabi/CMakeLists.txt                      |  1 +
 libsycl/CMakeLists.txt                        |  1 +
 libunwind/CMakeLists.txt                      |  1 +
 llvm-libgcc/CMakeLists.txt                    |  1 +
 openmp/CMakeLists.txt                         |  1 +
 orc-rt/lib/executor/CMakeLists.txt            |  1 +
 11 files changed, 63 insertions(+), 83 deletions(-)

diff --git a/cmake/Modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
index 21dffb40bf2ac..4cabf95311c5c 100644
--- a/cmake/Modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -1,27 +1,27 @@
-# 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.
+# Determine the subdirectory relative to Clang's resource dir/installation
+# prefix where to install target-specific libraries, to be found by the
+# 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=0: lib/${oslibname}/libclang_rt.builtins-${arch}.a
-# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=1: lib/${triple}/libclang_rt.builtins.a
+# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF: lib/${oslibname}/libclang_rt.builtins-${arch}.a
+# * LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON : 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(),
+# currently still used by default 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.
+# consistent between these functions, overrides in different toolchains, and
+# Compiler-RT's CMake code.
 #
-# 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(...).
+# For simplicity, we always use the second scheme even as if
+# LLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON, even if it actually set to OFF.
+# The driver's lookup does not take the build-time
+# LLVM_ENABLE_PER_TARGET_RUNTIME_DIR setting into account anyway
+# and will always find its files using either scheme.
 function (get_toolchain_library_subdir outvar)
   set(outval "lib")
 
@@ -30,8 +30,8 @@ function (get_toolchain_library_subdir outvar)
     get_toolchain_os_dirname(os_dirname)
     set(outval "${outval}/${os_dirname}")
   else ()
-    get_toolchain_arch_dirname(arch_dirname)
-    set(outval "${outval}/${arch_dirname}")
+    get_toolchain_target_dirname(target_dirname)
+    set(outval "${outval}/${target_dirname}")
   endif ()
 
   set(${outvar} "${outval}" PARENT_SCOPE)
@@ -39,11 +39,11 @@ endfunction ()
 
 
 # Corresponds to Flang's ToolChain::getDefaultIntrinsicModuleDir().
-function (get_toolchain_module_subdir outvar)
+function (get_toolchain_fortran_module_subdir outvar)
   set(outval "finclude/flang")
 
-  get_toolchain_arch_dirname(arch_dirname)
-  set(outval "${outval}/${arch_dirname}")
+  get_toolchain_target_dirname(target_dirname)
+  set(outval "${outval}/${target_dirname}")
 
   set(${outvar} "${outval}" PARENT_SCOPE)
 endfunction ()
@@ -62,22 +62,17 @@ function (get_toolchain_os_dirname outvar)
 endfunction ()
 
 
-# Corresponds to Clang's ToolChain::getRuntimePath(). Adapted from Compiler-RT.
-function (get_toolchain_arch_dirname outvar)
-  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")
+# Internal function extracted from compiler-rt. Use get_toolchain_target_dirname
+# instead for new code.
+function(get_runtimes_target_libdir_common default_target_triple arch variable)
+  string(FIND "${default_target_triple}" "-" dash_index)
+  string(SUBSTRING "${default_target_triple}" "${dash_index}" -1 triple_suffix)
+  string(SUBSTRING "${default_target_triple}" 0 "${dash_index}" triple_cpu)
+  if(ANDROID AND "${arch}" STREQUAL "i386")
     set(target "i686${triple_suffix}")
-  elseif(${arch} STREQUAL "amd64")
+  elseif("${arch}" STREQUAL "amd64")
     set(target "x86_64${triple_suffix}")
-  elseif(${arch} STREQUAL "sparc64")
+  elseif("${arch}" STREQUAL "sparc64")
     set(target "sparcv9${triple_suffix}")
   elseif("${arch}" MATCHES "mips64|mips64el")
     string(REGEX REPLACE "-gnu.*" "-gnuabi64" triple_suffix_gnu "${triple_suffix}")
@@ -91,7 +86,8 @@ function (get_toolchain_arch_dirname outvar)
     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
+    # Arch is arm, armhf, armv6m (anything else would come from using
+    # COMPILER_RT_DEFAULT_TARGET_ONLY, which is checked above).
     if (${arch} STREQUAL "armhf")
       # If we are building for hard float but our ABI is soft float.
       if ("${triple_suffix}" MATCHES ".*eabi$")
@@ -115,5 +111,18 @@ function (get_toolchain_arch_dirname outvar)
   else()
     set(target "${arch}${triple_suffix}")
   endif()
-  set(${outvar} "${target}" PARENT_SCOPE)
+  set("${variable}" "${target}" PARENT_SCOPE)
+endfunction()
+
+
+# Corresponds to Clang's ToolChain::getRuntimePath().
+function (get_toolchain_target_dirname outvar)
+  string(FIND "${LLVM_TARGET_TRIPLE}" "-" dash_index)
+  string(SUBSTRING "${LLVM_TARGET_TRIPLE}" 0 "${dash_index}" triple_cpu)
+  set(arch "${triple_cpu}")
+  if("${arch}" MATCHES "^i.86$")
+    set(arch "i386")
+  endif()
+  get_runtimes_target_libdir_common("${LLVM_TARGET_TRIPLE}" "${arch}" target)
+  set("${outvar}" "${target}" PARENT_SCOPE)
 endfunction()
diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
index cbd18d26c0b93..8c27c4585f73b 100644
--- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
@@ -1,5 +1,6 @@
 include(CMakePushCheckState)
 include(CheckSymbolExists)
+include(GetToolchainDirs)
 
 # Because compiler-rt spends a lot of time setting up custom compile flags,
 # define a handy helper function for it. The compile flags setting in CMake
@@ -460,59 +461,17 @@ function(filter_builtin_sources inout_var name)
 endfunction()
 
 function(get_compiler_rt_target arch variable)
-  string(FIND ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} "-" dash_index)
-  string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} ${dash_index} -1 triple_suffix)
-  string(SUBSTRING ${COMPILER_RT_DEFAULT_TARGET_TRIPLE} 0 ${dash_index} triple_cpu)
   if(COMPILER_RT_DEFAULT_TARGET_ONLY)
     # Use exact spelling when building only for the target specified to CMake.
     set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
-  elseif(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")
-    # Arch is arm, armhf, armv6m (anything else would come from using
-    # COMPILER_RT_DEFAULT_TARGET_ONLY, which is checked above).
-    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}")
+    get_runtimes_target_libdir_common("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" "${arch}" target)
   endif()
-  set(${variable} ${target} PARENT_SCOPE)
+  set(${variable} "${target}" PARENT_SCOPE)
 endfunction()
 
 function(get_compiler_rt_install_dir arch install_dir)
+  # TODO: Use RUNTIMES_INSTALL_RESOURCE_LIB_PATH instead
   if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
     get_compiler_rt_target(${arch} target)
     set(${install_dir} ${COMPILER_RT_INSTALL_LIBRARY_DIR}/${target} PARENT_SCOPE)
@@ -522,6 +481,7 @@ function(get_compiler_rt_install_dir arch install_dir)
 endfunction()
 
 function(get_compiler_rt_output_dir arch output_dir)
+  # TODO: Use RUNTIMES_OUTPUT_RESOURCE_LIB_DIR instead
   if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
     get_compiler_rt_target(${arch} target)
     set(${output_dir} ${COMPILER_RT_OUTPUT_LIBRARY_DIR}/${target} PARENT_SCOPE)
diff --git a/compiler-rt/cmake/base-config-ix.cmake b/compiler-rt/cmake/base-config-ix.cmake
index 6a6e2a88217fc..038cc191983f1 100644
--- a/compiler-rt/cmake/base-config-ix.cmake
+++ b/compiler-rt/cmake/base-config-ix.cmake
@@ -120,6 +120,8 @@ if(NOT DEFINED COMPILER_RT_OS_DIR)
     string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR)
   endif()
 endif()
+
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(COMPILER_RT_OUTPUT_LIBRARY_DIR
     ${COMPILER_RT_OUTPUT_DIR}/lib)
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 7a5ed88ef054c..6be26a1f6b174 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -234,6 +234,7 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
   cmake_path(NORMAL_PATH LIBC_TARGET_SUBDIR)
 endif()
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND (LIBC_ENABLE_USE_BY_CLANG OR LIBC_TARGET_OS_IS_GPU))
   set(LIBC_INCLUDE_DIR ${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE})
   set(LIBC_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
@@ -260,6 +261,7 @@ else()
   endif()
 endif()
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LIBC_TARGET_TRIPLE)
   set(LIBC_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LIBC_TARGET_TRIPLE})
 elseif(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index e1620f91a453c..4b39c2c78a365 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -425,6 +425,7 @@ set(LIBCXX_INSTALL_MODULES_DIR "share/libc++/v1" CACHE STRING
 set(LIBCXX_SHARED_OUTPUT_NAME "c++" CACHE STRING "Output name for the shared libc++ runtime library.")
 set(LIBCXX_STATIC_OUTPUT_NAME "c++" CACHE STRING "Output name for the static libc++ runtime library.")
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(LIBCXX_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
   if(LIBCXX_LIBDIR_SUBDIR)
diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
index 2b67c5972339e..e1a1587fb6283 100644
--- a/libcxxabi/CMakeLists.txt
+++ b/libcxxabi/CMakeLists.txt
@@ -185,6 +185,7 @@ set(CMAKE_MODULE_PATH
 set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING
     "Path where built libc++abi runtime libraries should be installed.")
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(LIBCXXABI_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
   if(LIBCXXABI_LIBDIR_SUBDIR)
diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index f75216978f69a..d2b0d79ea8e65 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -37,6 +37,7 @@ option(LIBSYCL_ENABLE_PEDANTIC "Compile with pedantic enabled." OFF)
 
 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(LIBSYCL_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
   if(LIBSYCL_LIBDIR_SUBDIR)
diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt
index fbef71f3f7446..1681b90b31cdb 100644
--- a/libunwind/CMakeLists.txt
+++ b/libunwind/CMakeLists.txt
@@ -140,6 +140,7 @@ set(LIBUNWIND_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING
 set(LIBUNWIND_SHARED_OUTPUT_NAME "unwind" CACHE STRING "Output name for the shared libunwind runtime library.")
 set(LIBUNWIND_STATIC_OUTPUT_NAME "unwind" CACHE STRING "Output name for the static libunwind runtime library.")
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(LIBUNWIND_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
   if(LIBUNWIND_LIBDIR_SUBDIR)
diff --git a/llvm-libgcc/CMakeLists.txt b/llvm-libgcc/CMakeLists.txt
index 47208fc198692..55c052165dbd1 100644
--- a/llvm-libgcc/CMakeLists.txt
+++ b/llvm-libgcc/CMakeLists.txt
@@ -61,6 +61,7 @@ endif()
 # Configure System
 #===============================================================================
 
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
   if(LLVM_LIBGCC_LIBDIR_SUBDIR)
diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt
index 7c0d3b222ddc0..ff5d475f7cf54 100644
--- a/openmp/CMakeLists.txt
+++ b/openmp/CMakeLists.txt
@@ -35,6 +35,7 @@ endif ()
 set(OPENMP_ENABLE_WERROR ${LLVM_ENABLE_WERROR})
 
 # When building in tree we install the runtime according to the LLVM settings.
+# TODO: Use common runtimes infrastructure for output and install paths
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
   set(OPENMP_INSTALL_LIBDIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING
       "Path where built openmp libraries should be installed.")
diff --git a/orc-rt/lib/executor/CMakeLists.txt b/orc-rt/lib/executor/CMakeLists.txt
index eebf142e5d868..cf0f2a1d39942 100644
--- a/orc-rt/lib/executor/CMakeLists.txt
+++ b/orc-rt/lib/executor/CMakeLists.txt
@@ -21,6 +21,7 @@ target_link_libraries(orc-rt-executor
   )
 
 # Apply RTTI and exceptions compile flags
+# TODO: Use common runtimes infrastructure for output and install paths
 target_compile_options(orc-rt-executor PRIVATE ${ORC_RT_COMPILE_FLAGS})
 install(TARGETS orc-rt-executor
   ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}



More information about the llvm-branch-commits mailing list