[flang-commits] [clang] [flang] [llvm] [openmp] [Flang][OpenMP] Move builtin .mod generation into runtimes (PR #137828)

Michael Kruse via flang-commits flang-commits at lists.llvm.org
Thu Jul 17 10:39:28 PDT 2025


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

>From 839198d61f9937b5504d5e036c67266b4b84da8e Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 17 Jul 2025 14:09:57 +0200
Subject: [PATCH 1/5] [Flang][Flang-RT][OpenMP] Move builtin .mod generation
 into runtimes

---
 clang/include/clang/Driver/Driver.h           |   3 +-
 clang/include/clang/Driver/Options.td         |   2 +-
 clang/include/clang/Driver/ToolChain.h        |   4 +
 clang/lib/Driver/Driver.cpp                   |  10 +
 clang/lib/Driver/ToolChain.cpp                |   6 +
 clang/lib/Driver/ToolChains/Flang.cpp         |   7 +
 .../Modules}/GetToolchainDirs.cmake           |  11 ++
 flang-rt/CMakeLists.txt                       |  73 ++------
 flang-rt/cmake/modules/AddFlangRT.cmake       |  14 +-
 .../cmake/modules/AddFlangRTOffload.cmake     |  14 +-
 flang-rt/lib/runtime/CMakeLists.txt           | 109 ++++++++++-
 .../lib/runtime}/__cuda_builtins.f90          |   0
 .../lib/runtime}/__cuda_device.f90            |   0
 .../lib/runtime}/__fortran_builtins.f90       |   4 +-
 .../runtime}/__fortran_ieee_exceptions.f90    |   0
 .../lib/runtime}/__fortran_type_info.f90      |   7 +-
 .../lib/runtime}/__ppc_intrinsics.f90         |   0
 .../lib/runtime}/__ppc_types.f90              |   0
 .../lib/runtime}/cooperative_groups.f90       |   1 +
 .../lib/runtime}/cudadevice.f90               |   0
 .../lib/runtime}/ieee_arithmetic.f90          |  29 ++-
 .../lib/runtime}/ieee_exceptions.f90          |   0
 .../lib/runtime}/ieee_features.f90            |   0
 .../lib/runtime}/iso_c_binding.f90            |   0
 .../lib/runtime}/iso_fortran_env.f90          |   0
 .../lib/runtime}/iso_fortran_env_impl.f90     |   0
 .../module => flang-rt/lib/runtime}/mma.f90   |   0
 flang-rt/test/lit.site.cfg.py.in              |   2 +-
 flang-rt/unittests/CMakeLists.txt             |   5 +-
 flang/CMakeLists.txt                          |   2 +-
 .../flang/Frontend/CompilerInvocation.h       |   7 +
 flang/lib/Frontend/CompilerInvocation.cpp     |  26 +--
 flang/lib/Optimizer/CodeGen/CodeGen.cpp       |   8 +-
 flang/module/.clang-format                    |   1 -
 flang/test/CMakeLists.txt                     |   7 +-
 flang/test/Driver/intrinsic-module-path.f90   |   4 +-
 .../Lower/HLFIR/type-bound-call-mismatch.f90  |   2 +-
 flang/test/Lower/OpenMP/simd_aarch64.f90      |   7 +-
 .../target-enter-data-default-openmp52.f90    |   4 +-
 flang/test/lit.cfg.py                         |  57 +++++-
 flang/test/lit.site.cfg.py.in                 |   1 +
 flang/tools/CMakeLists.txt                    |   1 -
 flang/tools/bbc/bbc.cpp                       |  16 +-
 flang/tools/f18/CMakeLists.txt                | 176 ------------------
 flang/tools/f18/dump.cpp                      |  42 -----
 llvm/runtimes/CMakeLists.txt                  |  21 +--
 openmp/CMakeLists.txt                         |   4 +
 openmp/runtime/src/CMakeLists.txt             |  62 ++----
 runtimes/CMakeLists.txt                       | 163 +++++++++++++++-
 49 files changed, 512 insertions(+), 400 deletions(-)
 rename {flang-rt/cmake/modules => cmake/Modules}/GetToolchainDirs.cmake (94%)
 rename {flang/module => flang-rt/lib/runtime}/__cuda_builtins.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/__cuda_device.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/__fortran_builtins.f90 (98%)
 rename {flang/module => flang-rt/lib/runtime}/__fortran_ieee_exceptions.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/__fortran_type_info.f90 (98%)
 rename {flang/module => flang-rt/lib/runtime}/__ppc_intrinsics.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/__ppc_types.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/cooperative_groups.f90 (95%)
 rename {flang/module => flang-rt/lib/runtime}/cudadevice.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/ieee_arithmetic.f90 (95%)
 rename {flang/module => flang-rt/lib/runtime}/ieee_exceptions.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/ieee_features.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/iso_c_binding.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/iso_fortran_env.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/iso_fortran_env_impl.f90 (100%)
 rename {flang/module => flang-rt/lib/runtime}/mma.f90 (100%)
 delete mode 100644 flang/module/.clang-format
 delete mode 100644 flang/tools/f18/CMakeLists.txt
 delete mode 100644 flang/tools/f18/dump.cpp

diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index d9e328fe918bc..9343fed36b6ac 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -403,9 +403,10 @@ class Driver {
                               SmallString<128> &CrashDiagDir);
 
 public:
-
   /// Takes the path to a binary that's either in bin/ or lib/ and returns
   /// the path to clang's resource directory.
+  /// Do not pass argv[0] as argument, llvm-lit does not adjust argv[0] to the
+  /// changing cwd. Use llvm::sys::fs::getMainExecutable instead.
   static std::string GetResourcesPath(StringRef BinaryPath);
 
   Driver(StringRef ClangExecutable, StringRef TargetTriple,
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index a8c1b5dd8ab3b..ed0d0cda49ad7 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5921,7 +5921,7 @@ def prebind : Flag<["-"], "prebind">;
 def preload : Flag<["-"], "preload">;
 def print_file_name_EQ : Joined<["-", "--"], "print-file-name=">,
   HelpText<"Print the full library path of <file>">, MetaVarName<"<file>">,
-  Visibility<[ClangOption, CLOption]>;
+  Visibility<[ClangOption, FlangOption, CLOption]>;
 def print_ivar_layout : Flag<["-"], "print-ivar-layout">,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable Objective-C Ivar layout bitmap print trace">,
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index b8899e78176b4..5cac39a8ed4e9 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -542,6 +542,10 @@ class ToolChain {
   // Returns Triple without the OSs version.
   llvm::Triple getTripleWithoutOSVersion() const;
 
+  /// Returns the target-specific path for Flang's intrinsic modules in the
+  /// resource directory if it exists.
+  std::optional<std::string> getDefaultIntrinsicModuleDir() const;
+
   // Returns the target specific runtime path if it exists.
   std::optional<std::string> getRuntimePath() const;
 
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ec1135eecd401..28ae55b024c33 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -6536,6 +6536,16 @@ std::string Driver::GetFilePath(StringRef Name, const ToolChain &TC) const {
   if (llvm::sys::fs::exists(Twine(P)))
     return std::string(P);
 
+  if (IsFlangMode()) {
+    if (std::optional<std::string> IntrPath =
+            TC.getDefaultIntrinsicModuleDir()) {
+      SmallString<128> P(*IntrPath);
+      llvm::sys::path::append(P, Name);
+      if (llvm::sys::fs::exists(Twine(P)))
+        return std::string(P);
+    }
+  }
+
   SmallString<128> D(Dir);
   llvm::sys::path::append(D, "..", Name);
   if (llvm::sys::fs::exists(Twine(D)))
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 3f9b808b2722e..ba20cda5e339b 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -983,6 +983,12 @@ ToolChain::getTargetSubDirPath(StringRef BaseDir) const {
   return {};
 }
 
+std::optional<std::string> ToolChain::getDefaultIntrinsicModuleDir() const {
+  SmallString<128> P(D.ResourceDir);
+  llvm::sys::path::append(P, "finclude");
+  return getTargetSubDirPath(P);
+}
+
 std::optional<std::string> ToolChain::getRuntimePath() const {
   SmallString<128> P(D.ResourceDir);
   llvm::sys::path::append(P, "lib");
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 1edb83f7255eb..dba2f6fae493b 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -957,6 +957,13 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
   CmdArgs.push_back("-resource-dir");
   CmdArgs.push_back(D.ResourceDir.c_str());
 
+  // Default intrinsic module dirs must be added after any user-provided
+  // -fintrinsic-modules-path to have lower precedence
+  if (auto IntrModPath = TC.getDefaultIntrinsicModuleDir()) {
+    CmdArgs.push_back("-fintrinsic-modules-path");
+    CmdArgs.push_back(Args.MakeArgString(*IntrModPath));
+  }
+
   // Offloading related options
   addOffloadOptions(C, Inputs, JA, Args, CmdArgs);
 
diff --git a/flang-rt/cmake/modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
similarity index 94%
rename from flang-rt/cmake/modules/GetToolchainDirs.cmake
rename to cmake/Modules/GetToolchainDirs.cmake
index fba12502b5946..f32e1264cc373 100644
--- a/flang-rt/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")
+
+  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/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index d048ac4b3e5a4..09f4f9e7213f1 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -67,68 +67,17 @@ include(GetToolchainDirs)
 include(FlangCommon)
 include(HandleCompilerRT)
 include(ExtendPath)
+include(CheckFortranSourceCompiles)
+include(CMakePushCheckState)
 
 
 ############################
 # 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 #
@@ -243,6 +192,22 @@ check_cxx_source_compiles(
   "
   HAVE_DECL_STRERROR_S)
 
+include(CheckFortranSourceCompiles)
+include(CMakePushCheckState)
+cmake_push_check_state(RESET)
+set(CMAKE_REQUIRED_FLAGS "-ffree-form")
+set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
+check_fortran_source_compiles([[
+    subroutine test_quadmath
+      real(16) :: var1
+    end
+  ]]
+  FORTRAN_SUPPORTS_REAL16
+)
+cmake_pop_check_state()
+
+flang_module_fortran_enable()
+
 # Search for clang_rt.builtins library. Need in addition to msvcrt.
 if (WIN32)
   find_compiler_rt_library(builtins FLANG_RT_BUILTINS_LIBRARY)
@@ -338,4 +303,4 @@ if (FLANG_RT_INCLUDE_TESTS)
   add_subdirectory(unittests)
 else ()
   add_custom_target(check-flang-rt)
-endif()
+endif()
\ No newline at end of file
diff --git a/flang-rt/cmake/modules/AddFlangRT.cmake b/flang-rt/cmake/modules/AddFlangRT.cmake
index e51590fdae3d3..febaac3058b3f 100644
--- a/flang-rt/cmake/modules/AddFlangRT.cmake
+++ b/flang-rt/cmake/modules/AddFlangRT.cmake
@@ -190,6 +190,12 @@ function (add_flangrt_library name)
     endif ()
   endif ()
 
+  if (build_object)
+    add_library(${name}.compile ALIAS "${name_object}")
+  else ()
+    add_library(${name}.compile ALIAS "${default_target}")
+  endif ()
+
   foreach (tgtname IN LISTS libtargets)
     if (NOT WIN32)
       # Use same stem name for .a and .so. Common in UNIX environments.
@@ -334,13 +340,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/cmake/modules/AddFlangRTOffload.cmake b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
index cbc69f3a9656a..4a6f047a86af2 100644
--- a/flang-rt/cmake/modules/AddFlangRTOffload.cmake
+++ b/flang-rt/cmake/modules/AddFlangRTOffload.cmake
@@ -88,16 +88,16 @@ macro(enable_omp_offload_compilation name files)
         "${FLANG_RT_DEVICE_ARCHITECTURES}"
         )
 
-      set(OMP_COMPILE_OPTIONS
+      set(OMP_COMPILE_OPTIONS $<$<COMPILE_LANGUAGE:C,CXX>:
         -fopenmp
         -fvisibility=hidden
         -fopenmp-cuda-mode
         --offload-arch=${compile_for_architectures}
         # Force LTO for the device part.
         -foffload-lto
-        )
-      set_source_files_properties(${files} PROPERTIES COMPILE_OPTIONS
-        "${OMP_COMPILE_OPTIONS}"
+        >)
+      set_property(SOURCE ${files} APPEND
+        PROPERTY COMPILE_DEFINITIONS ${OMP_COMPILE_OPTIONS}
         )
       target_link_options(${name}.static PUBLIC ${OMP_COMPILE_OPTIONS})
 
@@ -105,6 +105,12 @@ macro(enable_omp_offload_compilation name files)
       set_source_files_properties(${files}
         PROPERTIES COMPILE_DEFINITIONS OMP_OFFLOAD_BUILD
         )
+
+     # If building flang-rt together with libomp, ensure that libomp is built first and found because -fopenmp will try to link it.
+     if (TARGET omp)
+       add_dependencies(${name} omp)
+       target_link_options(${name}.static PUBLIC "-L$<TARGET_FILE_DIR:omp>")
+     endif ()
     else()
       message(FATAL_ERROR
         "Flang-rt build with OpenMP offload is not supported for these compilers:\n"
diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt
index 332c0872e065f..1b8114c102205 100644
--- a/flang-rt/lib/runtime/CMakeLists.txt
+++ b/flang-rt/lib/runtime/CMakeLists.txt
@@ -73,7 +73,16 @@ set(supported_sources
 
 # List of source not used for GPU offloading.
 set(host_sources
-  ${FLANG_SOURCE_DIR}/module/iso_fortran_env_impl.f90
+  __fortran_ieee_exceptions.f90
+  __fortran_type_info.f90
+  iso_fortran_env.f90
+  ieee_arithmetic.f90
+  ieee_exceptions.f90
+  ieee_features.f90
+  iso_c_binding.f90
+  iso_fortran_env_impl.f90
+  iso_fortran_env.f90
+
   command.cpp
   complex-powi.cpp
   complex-reduction.c
@@ -90,6 +99,35 @@ set(host_sources
   unit-map.cpp
 )
 
+# Module sources that are required by other modules
+set(intrinsics_sources
+  __fortran_builtins.f90
+  __cuda_builtins.f90
+)
+
+if (CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc")
+  list(APPEND host_source
+    __ppc_types.f90
+    __ppc_intrinsics.f90
+    mma.f90
+  )
+endif ()
+
+list(APPEND supported_sources
+  __cuda_device.f90
+  cooperative_groups.f90
+  cudadevice.f90
+)
+
+# Compile as CUDA-Fortran, not directly supported by CMake
+set_property(SOURCE
+    __cuda_device.f90
+    cooperative_groups.f90
+    cudadevice.f90
+  APPEND PROPERTY
+    COMPILE_OPTIONS --offload-host-only -xcuda
+)
+
 # Sources that can be compiled directly for the GPU.
 set(gpu_sources
   ${FLANG_SOURCE_DIR}/lib/Decimal/binary-to-decimal.cpp
@@ -182,10 +220,42 @@ else ()
 endif ()
 
 
+if (FORTRAN_SUPPORTS_REAL16)
+  add_compile_definitions(FLANG_SUPPORT_R16=1)
+  add_compile_options("$<$<COMPILE_LANGUAGE:Fortran>:-cpp>")
+endif ()
+
+add_compile_options(
+  "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-mmlir;SHELL:-ignore-missing-type-desc>"
+
+  # Flang bug workaround: Reformating of cooked token buffer causes identifier to be split between lines
+  "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-Xflang;SHELL:-fno-reformat>"
+)
+
+
+# check-flang depends on this to build intrinsic modules
+if (NOT TARGET flang-rt-mod)
+  add_custom_target(flang-rt-mod)
+endif ()
+
 if (NOT WIN32)
+  # CMake ignores intrinsic USE dependencies
+  # CMake has an option Fortran_BUILDING_INSTRINSIC_MODULES/Fortran_BUILDING_INTRINSIC_MODULES to disable this behavior, unfortunately it does not work with Ninja (https://gitlab.kitware.com/cmake/cmake/-/issues/26803) 
+  # As a workaround, we build those intrinsic modules first such that the main runtime can depend on it.
+  add_flangrt_library(flang_rt.intrinsics.obj OBJECT
+    ${intrinsics_sources}
+  )
+
+  # This barrier exists to force all of the intrinsic modules of flang_rt.intrinsics.obj to be built before anything that depends on it.
+  # Without it, CMake/Ninja seem to think that the modules of flang_rt.intrinsics.obj can be built concurrently to those in flang_rt.runtime.
+  add_custom_target(flang_rt.intrinsics
+    COMMENT "Intrinsic module dependency barrier"
+  )
+  add_dependencies(flang_rt.intrinsics flang_rt.intrinsics.obj)
+
   add_flangrt_library(flang_rt.runtime STATIC SHARED
-    ${sources}
-    LINK_LIBRARIES ${Backtrace_LIBRARY}
+    ${sources} $<TARGET_OBJECTS:flang_rt.intrinsics.obj>
+    LINK_LIBRARIES flang_rt.intrinsics.obj ${Backtrace_LIBRARY}
     INSTALL_WITH_TOOLCHAIN
     ADDITIONAL_HEADERS ${public_headers} ${private_headers}
   )
@@ -196,6 +266,13 @@ if (NOT WIN32)
   # Select a default runtime, which is used for unit and regression tests.
   get_target_property(default_target flang_rt.runtime.default ALIASED_TARGET)
   add_library(flang_rt.runtime.unittest ALIAS "${default_target}")
+
+  # Select a target that compiles the sources to build the public module files.
+  get_target_property(compile_target flang_rt.runtime.compile ALIASED_TARGET)
+  flang_module_target(flang_rt.intrinsics.obj PUBLIC)
+  flang_module_target(${compile_target} PUBLIC)
+  add_dependencies(${compile_target} flang_rt.intrinsics)
+  add_dependencies(flang-rt-mod flang_rt.intrinsics ${compile_target})
 else()
   # Target for building all versions of the runtime
   add_custom_target(flang_rt.runtime)
@@ -203,10 +280,15 @@ else()
 
   function (add_win_flangrt_runtime libtype suffix msvc_lib)
     set(name "flang_rt.runtime.${suffix}")
+
+    add_flangrt_library(${name}.intrinsics OBJECT
+      ${intrinsics_sources}
+    )
+
     add_flangrt_library(${name} ${libtype}
-        ${sources}
+        ${sources} $<TARGET_OBJECTS:${name}.intrinsics>
         ${ARGN}
-        LINK_LIBRARIES ${Backtrace_LIBRARY}
+        LINK_LIBRARIES ${name}.intrinsics ${Backtrace_LIBRARY}
         ADDITIONAL_HEADERS ${public_headers} ${private_headers}
       )
 
@@ -219,10 +301,19 @@ else()
 
     # Setting an unique Fortran_MODULE_DIRECTORY is required for each variant to
     # write a different .mod file.
-    set_target_properties(${name}
-        PROPERTIES
-          Fortran_MODULE_DIRECTORY "module.${suffix}"
-      )
+    # One has to be selected to be the public module that is to be installed.
+    # We select the first.
+    if (_has_public_intrinsics)
+      set(is_public "")
+    else ()
+      set(is_public PUBLIC)
+      set(_has_public_intrinsics "YES" PARENT_SCOPE)
+    endif ()
+
+    get_target_property(compile_target ${name}.compile ALIASED_TARGET)
+    flang_module_target(${name}.intrinsics ${is_public})
+    flang_module_target(${compile_target} ${is_public})
+    add_dependencies(flang-rt-mod ${name}.intrinsics ${compile_target})
 
     enable_cuda_compilation(${name} "${supported_sources}")
     enable_omp_offload_compilation(${name} "${supported_sources}")
diff --git a/flang/module/__cuda_builtins.f90 b/flang-rt/lib/runtime/__cuda_builtins.f90
similarity index 100%
rename from flang/module/__cuda_builtins.f90
rename to flang-rt/lib/runtime/__cuda_builtins.f90
diff --git a/flang/module/__cuda_device.f90 b/flang-rt/lib/runtime/__cuda_device.f90
similarity index 100%
rename from flang/module/__cuda_device.f90
rename to flang-rt/lib/runtime/__cuda_device.f90
diff --git a/flang/module/__fortran_builtins.f90 b/flang-rt/lib/runtime/__fortran_builtins.f90
similarity index 98%
rename from flang/module/__fortran_builtins.f90
rename to flang-rt/lib/runtime/__fortran_builtins.f90
index 4d134fa4b62b1..d5e55b5d95020 100644
--- a/flang/module/__fortran_builtins.f90
+++ b/flang-rt/lib/runtime/__fortran_builtins.f90
@@ -6,13 +6,13 @@
 !
 !===------------------------------------------------------------------------===!
 
-#include '../include/flang/Runtime/magic-numbers.h'
+#include '../../../flang/include/flang/Runtime/magic-numbers.h'
 
 ! These naming shenanigans prevent names from Fortran intrinsic modules
 ! from being usable on INTRINSIC statements, and force the program
 ! to USE the standard intrinsic modules in order to access the
 ! standard names of the procedures.
-module __fortran_builtins
+module    __fortran_builtins
   implicit none
 
   ! Set PRIVATE by default to explicitly only export what is meant
diff --git a/flang/module/__fortran_ieee_exceptions.f90 b/flang-rt/lib/runtime/__fortran_ieee_exceptions.f90
similarity index 100%
rename from flang/module/__fortran_ieee_exceptions.f90
rename to flang-rt/lib/runtime/__fortran_ieee_exceptions.f90
diff --git a/flang/module/__fortran_type_info.f90 b/flang-rt/lib/runtime/__fortran_type_info.f90
similarity index 98%
rename from flang/module/__fortran_type_info.f90
rename to flang-rt/lib/runtime/__fortran_type_info.f90
index 6af2a5a5e30ff..2f936c3787a61 100644
--- a/flang/module/__fortran_type_info.f90
+++ b/flang-rt/lib/runtime/__fortran_type_info.f90
@@ -12,8 +12,11 @@
 ! in order to generate description tables for all other derived types.
 
 module __fortran_type_info
-
-  use, intrinsic :: __fortran_builtins, &
+#if 0
+  use       __fortran_builtins, &
+#else
+  use, intrinsic ::    __fortran_builtins, &
+#endif
     only: __builtin_c_ptr, __builtin_c_devptr, __builtin_c_funptr
   implicit none
 
diff --git a/flang/module/__ppc_intrinsics.f90 b/flang-rt/lib/runtime/__ppc_intrinsics.f90
similarity index 100%
rename from flang/module/__ppc_intrinsics.f90
rename to flang-rt/lib/runtime/__ppc_intrinsics.f90
diff --git a/flang/module/__ppc_types.f90 b/flang-rt/lib/runtime/__ppc_types.f90
similarity index 100%
rename from flang/module/__ppc_types.f90
rename to flang-rt/lib/runtime/__ppc_types.f90
diff --git a/flang/module/cooperative_groups.f90 b/flang-rt/lib/runtime/cooperative_groups.f90
similarity index 95%
rename from flang/module/cooperative_groups.f90
rename to flang-rt/lib/runtime/cooperative_groups.f90
index b8875f72f8079..82d1e0fe84042 100644
--- a/flang/module/cooperative_groups.f90
+++ b/flang-rt/lib/runtime/cooperative_groups.f90
@@ -11,6 +11,7 @@
 module cooperative_groups
 
 use, intrinsic :: __fortran_builtins, only: c_devptr => __builtin_c_devptr
+use :: cudadevice ! implicit dependency, make explicit for CMake
 
 implicit none
 
diff --git a/flang/module/cudadevice.f90 b/flang-rt/lib/runtime/cudadevice.f90
similarity index 100%
rename from flang/module/cudadevice.f90
rename to flang-rt/lib/runtime/cudadevice.f90
diff --git a/flang/module/ieee_arithmetic.f90 b/flang-rt/lib/runtime/ieee_arithmetic.f90
similarity index 95%
rename from flang/module/ieee_arithmetic.f90
rename to flang-rt/lib/runtime/ieee_arithmetic.f90
index 4e938a2daaa91..b3288a5cdd69f 100644
--- a/flang/module/ieee_arithmetic.f90
+++ b/flang-rt/lib/runtime/ieee_arithmetic.f90
@@ -8,7 +8,7 @@
 
 ! Fortran 2018 Clause 17
 
-#include '../include/flang/Runtime/magic-numbers.h'
+#include   '../include/flang/Runtime/magic-numbers.h'
 
 module ieee_arithmetic
   ! F18 Clause 17.1p1:
@@ -336,13 +336,28 @@ end subroutine ieee_get_underflow_mode_l##GKIND;
   public ::  ieee_get_underflow_mode
 #undef IEEE_GET_UNDERFLOW_MODE_L
 
-#define IEEE_IS_FINITE_R(XKIND) \
-  elemental logical function ieee_is_finite_a##XKIND(x); \
-    real(XKIND), intent(in) :: x; \
-    !dir$ ignore_tkr(d) x; \
-  end function ieee_is_finite_a##XKIND;
+! #define IEEE_IS_FINITE_R(XKIND) elemental logical function ieee_is_finite_a##XKIND(x);  real(XKIND), intent(in) :: x;  !dir$ ignore_tkr(d) x;   end function ieee_is_finite_a##XKIND;
   interface ieee_is_finite
-    SPECIFICS_R(IEEE_IS_FINITE_R)
+elemental logical function ieee_is_finite_a2(x); real(2), intent(in) :: x;
+!dir$ ignore_tkr(d) x;
+end function ieee_is_finite_a2;
+elemental logical function ieee_is_finite_a3(x); real(3), intent(in) :: x;
+!dir$ ignore_tkr(d) x;
+end function ieee_is_finite_a3;
+ elemental logical function ieee_is_finite_a4(x); real(4), intent(in) :: x;
+!dir$ ignore_tkr(d) x;
+end function ieee_is_finite_a4;
+elemental logical function ieee_is_finite_a8(x); real(8), intent(in) :: x;
+!dir$ ignore_tkr(d) x;
+end function ieee_is_finite_a8;
+elemental logical function ieee_is_finite_a10(x); real(10), intent(in) :: x;
+!dir$ ignore_tkr(d) x;
+end function ieee_is_finite_a10;
+#if FLANG_SUPPORT_R16
+elemental logical function ieee_is_finite_a16(x); real(16), intent(in) :: x;
+!dir$ ignore_tkr(d) x;
+end function ieee_is_finite_a16;
+#endif
   end interface ieee_is_finite
   public :: ieee_is_finite
 #undef IEEE_IS_FINITE_R
diff --git a/flang/module/ieee_exceptions.f90 b/flang-rt/lib/runtime/ieee_exceptions.f90
similarity index 100%
rename from flang/module/ieee_exceptions.f90
rename to flang-rt/lib/runtime/ieee_exceptions.f90
diff --git a/flang/module/ieee_features.f90 b/flang-rt/lib/runtime/ieee_features.f90
similarity index 100%
rename from flang/module/ieee_features.f90
rename to flang-rt/lib/runtime/ieee_features.f90
diff --git a/flang/module/iso_c_binding.f90 b/flang-rt/lib/runtime/iso_c_binding.f90
similarity index 100%
rename from flang/module/iso_c_binding.f90
rename to flang-rt/lib/runtime/iso_c_binding.f90
diff --git a/flang/module/iso_fortran_env.f90 b/flang-rt/lib/runtime/iso_fortran_env.f90
similarity index 100%
rename from flang/module/iso_fortran_env.f90
rename to flang-rt/lib/runtime/iso_fortran_env.f90
diff --git a/flang/module/iso_fortran_env_impl.f90 b/flang-rt/lib/runtime/iso_fortran_env_impl.f90
similarity index 100%
rename from flang/module/iso_fortran_env_impl.f90
rename to flang-rt/lib/runtime/iso_fortran_env_impl.f90
diff --git a/flang/module/mma.f90 b/flang-rt/lib/runtime/mma.f90
similarity index 100%
rename from flang/module/mma.f90
rename to flang-rt/lib/runtime/mma.f90
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@"
diff --git a/flang-rt/unittests/CMakeLists.txt b/flang-rt/unittests/CMakeLists.txt
index 5282196174134..82f32d027944e 100644
--- a/flang-rt/unittests/CMakeLists.txt
+++ b/flang-rt/unittests/CMakeLists.txt
@@ -53,9 +53,8 @@ function(add_flangrt_unittest_offload_properties target)
   # FIXME: replace 'native' in --offload-arch option with the list
   #        of targets that Fortran Runtime was built for.
   if (FLANG_RT_EXPERIMENTAL_OFFLOAD_SUPPORT STREQUAL "OpenMP")
-    set_target_properties(${target}
-      PROPERTIES LINK_OPTIONS
-      "-fopenmp;--offload-arch=native"
+    set_property(TARGET ${target} APPEND
+      PROPERTY LINK_OPTIONS -fopenmp --offload-arch=native
       )
   endif()
 endfunction()
diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt
index 0bfada476348a..5bdb43e5ab5e6 100644
--- a/flang/CMakeLists.txt
+++ b/flang/CMakeLists.txt
@@ -273,7 +273,7 @@ set(FLANG_TOOLS_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
     "Path for binary subdirectory (defaults to '${CMAKE_INSTALL_BINDIR}')")
 mark_as_advanced(FLANG_TOOLS_INSTALL_DIR)
 
-set(FLANG_INTRINSIC_MODULES_DIR ${CMAKE_BINARY_DIR}/include/flang)
+set(FLANG_INTRINSIC_MODULES_DIR "" CACHE PATH "Additional search path for modules; needed for running all tests if not building flang-rt in a bootstrapping build")
 set(FLANG_INCLUDE_DIR ${FLANG_BINARY_DIR}/include)
 
 # TODO: Remove when libclangDriver is lifted out of Clang
diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index d294955af780e..feaee28a53349 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -92,6 +92,10 @@ class CompilerInvocation : public CompilerInvocationBase {
   // intrinsic of iso_fortran_env.
   std::string allCompilerInvocOpts;
 
+  /// Location of the resource directory containing files specific to this
+  /// instance/version of Flang.
+  std::string resourceDir;
+
   /// Semantic options
   // TODO: Merge with or translate to frontendOpts. We shouldn't need two sets
   // of options.
@@ -177,6 +181,9 @@ class CompilerInvocation : public CompilerInvocationBase {
   getSemanticsCtx(Fortran::parser::AllCookedSources &allCookedSources,
                   const llvm::TargetMachine &);
 
+  std::string &getResourceDir() { return resourceDir; }
+  const std::string &getResourceDir() const { return resourceDir; }
+
   std::string &getModuleDir() { return moduleDir; }
   const std::string &getModuleDir() const { return moduleDir; }
 
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f55d866435997..bd0f0a381bbd3 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -884,16 +884,6 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args,
   return diags.getNumErrors() == numErrorsBefore;
 }
 
-// Generate the path to look for intrinsic modules
-static std::string getIntrinsicDir(const char *argv) {
-  // TODO: Find a system independent API
-  llvm::SmallString<128> driverPath;
-  driverPath.assign(llvm::sys::fs::getMainExecutable(argv, nullptr));
-  llvm::sys::path::remove_filename(driverPath);
-  driverPath.append("/../include/flang/");
-  return std::string(driverPath);
-}
-
 // Generate the path to look for OpenMP headers
 static std::string getOpenMPHeadersDir(const char *argv) {
   llvm::SmallString<128> includePath;
@@ -1509,6 +1499,14 @@ bool CompilerInvocation::createFromArgs(
     success = false;
   }
 
+  // User-specified or default resource dir
+  if (const llvm::opt::Arg *a =
+          args.getLastArg(clang::driver::options::OPT_resource_dir))
+    invoc.resourceDir = a->getValue();
+  else
+    invoc.resourceDir = clang::driver::Driver::GetResourcesPath(
+        llvm::sys::fs::getMainExecutable(argv0, nullptr));
+
   // -flang-experimental-hlfir
   if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir) ||
       args.hasArg(clang::driver::options::OPT_emit_hlfir)) {
@@ -1759,9 +1757,11 @@ void CompilerInvocation::setFortranOpts() {
       preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
       preprocessorOptions.searchDirectoriesFromIntrModPath.end());
 
-  //  Add the default intrinsic module directory
-  fortranOptions.intrinsicModuleDirectories.emplace_back(
-      getIntrinsicDir(getArgv0()));
+  // Add the ordered list of -fintrinsic-modules-path
+  fortranOptions.intrinsicModuleDirectories.insert(
+      fortranOptions.intrinsicModuleDirectories.end(),
+      preprocessorOptions.searchDirectoriesFromIntrModPath.begin(),
+      preprocessorOptions.searchDirectoriesFromIntrModPath.end());
 
   // Add the directory supplied through -J/-module-dir to the list of search
   // directories
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 5ca53ee48955e..14f422a6098b2 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -1365,10 +1365,10 @@ getTypeDescriptor(ModOpTy mod, mlir::ConversionPatternRewriter &rewriter,
     return rewriter.create<mlir::LLVM::ZeroOp>(loc, llvmPtrTy);
 
   if (!options.skipExternalRttiDefinition)
-    fir::emitFatalError(loc,
-                        "runtime derived type info descriptor was not "
-                        "generated and skipExternalRttiDefinition and "
-                        "ignoreMissingTypeDescriptors options are not set");
+    fir::emitFatalError(
+        loc, llvm::Twine("runtime derived type info descriptor of '") + name +
+                 "' was not generated and skipExternalRttiDefinition and "
+                 "ignoreMissingTypeDescriptors options are not set");
 
   // Rtti for a derived type defined in another compilation unit and for which
   // rtti was not defined in lowering because of the skipExternalRttiDefinition
diff --git a/flang/module/.clang-format b/flang/module/.clang-format
deleted file mode 100644
index e3845288a2aec..0000000000000
--- a/flang/module/.clang-format
+++ /dev/null
@@ -1 +0,0 @@
-DisableFormat: true
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index 8520bec646971..6cc7abd5fe7dc 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -59,7 +59,6 @@ set(FLANG_TEST_PARAMS
 
 set(FLANG_TEST_DEPENDS
   flang
-  module_files
   fir-opt
   tco
   bbc
@@ -97,8 +96,12 @@ if (LLVM_BUILD_EXAMPLES)
     )
 endif ()
 
+if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES AND NOT FLANG_STANDALONE_BUILD)
+  list(APPEND FLANG_TEST_DEPENDS "flang-rt-mod") # For intrinsic module files (in flang-rt/)
+endif ()
+
 if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES AND NOT FLANG_STANDALONE_BUILD)
-  list(APPEND FLANG_TEST_DEPENDS "libomp-mod")
+  list(APPEND FLANG_TEST_DEPENDS "libomp-mod") # For omplib.mod and omplib_kinds.mod (in openmp/)
 endif ()
 
 add_custom_target(flang-test-depends DEPENDS ${FLANG_TEST_DEPENDS})
diff --git a/flang/test/Driver/intrinsic-module-path.f90 b/flang/test/Driver/intrinsic-module-path.f90
index 8fe486cf61c83..a6f0cb04453f4 100644
--- a/flang/test/Driver/intrinsic-module-path.f90
+++ b/flang/test/Driver/intrinsic-module-path.f90
@@ -6,8 +6,8 @@
 !-----------------------------------------
 ! FRONTEND FLANG DRIVER (flang -fc1)
 !-----------------------------------------
-! RUN: %flang_fc1 -fsyntax-only %s  2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT
-! RUN: not %flang_fc1 -fsyntax-only -fintrinsic-modules-path %S/Inputs/ %s  2>&1 | FileCheck %s --check-prefix=GIVEN
+! RUN:     %flang_bare -fsyntax-only                                     %s %intrinsic_module_flags 2>&1 | FileCheck %s --check-prefix=WITHOUT --allow-empty
+! RUN: not %flang_bare -fsyntax-only -fintrinsic-modules-path %S/Inputs/ %s %intrinsic_module_flags 2>&1 | FileCheck %s --check-prefix=GIVEN
 
 ! WITHOUT-NOT: 'ieee_arithmetic.mod' was not found
 ! WITHOUT-NOT: 'iso_fortran_env.mod' was not found
diff --git a/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90 b/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90
index 2e0c72ccfe048..29a9784b984b6 100644
--- a/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90
+++ b/flang/test/Lower/HLFIR/type-bound-call-mismatch.f90
@@ -1,6 +1,6 @@
 ! Test interface that lowering handles small interface mismatch with
 ! type bound procedures.
-! RUN: bbc -emit-hlfir %s -o - -I nw | FileCheck %s
+! RUN: %bbc_bare -emit-hlfir %s -o - -I nw | FileCheck %s
 
 module dispatch_mismatch
 type t
diff --git a/flang/test/Lower/OpenMP/simd_aarch64.f90 b/flang/test/Lower/OpenMP/simd_aarch64.f90
index 735237223bcb5..2e4136273c75b 100644
--- a/flang/test/Lower/OpenMP/simd_aarch64.f90
+++ b/flang/test/Lower/OpenMP/simd_aarch64.f90
@@ -1,6 +1,11 @@
-! Tests for 2.9.3.1 Simd and target dependent defult alignment for AArch64
+! Tests for 2.9.3.1 Simd and target dependent default alignment for AArch64
 ! The default alignment for AARCH64 is 0 so we do not emit aligned clause
 ! REQUIRES: aarch64-registered-target
+
+! Requires aarch64 iso_c_binding.mod which currently is only available if your host is also aarch64
+! FIXME: Make flang a cross-compiler
+! UNSUPPORTED: true
+
 ! RUN: %flang_fc1 -triple aarch64-unknown-linux-gnu -emit-hlfir -fopenmp %s -o - | FileCheck  %s
 subroutine simdloop_aligned_cptr(A)
     use iso_c_binding
diff --git a/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90 b/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90
index 0d4fd964b71ec..72b5fea2c171e 100644
--- a/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90
+++ b/flang/test/Lower/OpenMP/target-enter-data-default-openmp52.f90
@@ -1,7 +1,7 @@
 ! This test checks the lowering and application of default map types for the target enter/exit data constructs and map clauses
 
-!RUN: %flang -fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s | FileCheck %s --check-prefix=CHECK-52
-!RUN: not %flang -fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-51
+!RUN: %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s | FileCheck %s --check-prefix=CHECK-52
+!RUN: not %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-51
 
 module test
   real, allocatable :: A
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 7eb57670ac767..8a375fdf49b8b 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -127,19 +127,64 @@
 if config.default_sysroot:
     config.available_features.add("default_sysroot")
 
+
+flang_exe =  lit.util.which("flang", config.flang_llvm_tools_dir)
+if not flang_exe:
+    lit_config.fatal(f"Could not identify flang executable")
+
+def get_resource_module_intrinsic_dir():
+    # Determine the intrinsic module search path that is added by the driver. If
+    # skipping the driver using -fc1, we need to append the path manually.
+    flang_intrinsics_dir = subprocess.check_output([flang_exe, "-print-file-name=__fortran_builtins.mod"], text=True).strip()
+    if not flang_intrinsics_dir:
+        return None
+    flang_intrinsics_dir = os.path.dirname(flang_intrinsics_dir)
+    return flang_intrinsics_dir
+
+intrinsics_search_args = []
+if flang_intrinsics_dir := get_resource_module_intrinsic_dir():
+    intrinsics_search_args += ["-fintrinsic-modules-path",flang_intrinsics_dir]
+    lit_config.note(f"using default module intrinsics: {flang_intrinsics_dir}")
+
+extra_intrinsics_search_args = []
+if config.flang_intrinsic_modules_dir:
+    extra_intrinsics_search_args += ["-fintrinsic-modules-path", config.flang_intrinsic_modules_dir]
+    lit_config.note(f"using extra module intrinsics: {config.flang_intrinsic_modules_dir}")
+
+config.substitutions.append(("%intrinsic_module_flags", ' '.join(intrinsics_search_args + extra_intrinsics_search_args)))
+
 # For each occurrence of a flang tool name, replace it with the full path to
 # the build directory holding that tool.
 tools = [
+    ToolSubst(
+        "bbc",
+         command=FindTool("bbc"),
+         extra_args=intrinsics_search_args + extra_intrinsics_search_args,
+         unresolved="fatal",
+    ),
     ToolSubst(
         "%flang",
         command=FindTool("flang"),
-        extra_args=isysroot_flag,
+        extra_args=isysroot_flag + extra_intrinsics_search_args,
         unresolved="fatal",
     ),
     ToolSubst(
         "%flang_fc1",
         command=FindTool("flang"),
-        extra_args=["-fc1"],
+        extra_args=["-fc1"] + intrinsics_search_args + extra_intrinsics_search_args,
+        unresolved="fatal",
+    ),
+
+    # For not having intrinsic search paths to be added implicitly
+    ToolSubst(
+         "%bbc_bare",
+         command=FindTool("bbc"),
+         unresolved="fatal",
+    ),
+    ToolSubst(
+        "%flang_bare",
+        command=FindTool("flang"),
+        extra_args=isysroot_flag,
         unresolved="fatal",
     ),
 ]
@@ -177,6 +222,14 @@
 if result:
     config.environment["LIBPGMATH"] = True
 
+# If intrinsic modules are not available, disable tests unless they are marked as 'module-independent'.
+config.available_features.add("module-independent")
+if config.have_flangrt_mod or config.flang_intrinsic_modules_dir:
+   config.available_features.add("flangrt-modules")
+else:
+   lit_config.warning(f"Intrinsic modules not available: disabling most tests")
+   config.limit_to_features.add("module-independent")
+
 # Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file)
 openmp_flags_substitution = "-fopenmp"
 if config.have_openmp_rtl:
diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index ae5144010bc8b..5d07af42c6487 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -23,6 +23,7 @@ config.linked_bye_extension = @LLVM_BYE_LINK_INTO_TOOLS@
 config.osx_sysroot = path(r"@CMAKE_OSX_SYSROOT@")
 config.targets_to_build = "@TARGETS_TO_BUILD@"
 config.default_sysroot = "@DEFAULT_SYSROOT@"
+config.have_flangrt_mod = ("flang-rt" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"))
 config.have_openmp_rtl = ("@LLVM_TOOL_OPENMP_BUILD@" == "TRUE") or ("openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"))
 if "openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"):
     config.openmp_module_dir = "@CMAKE_BINARY_DIR@/runtimes/runtimes-bins/openmp/runtime/src"
diff --git a/flang/tools/CMakeLists.txt b/flang/tools/CMakeLists.txt
index 1d2d2c608faf9..1b297af74cae7 100644
--- a/flang/tools/CMakeLists.txt
+++ b/flang/tools/CMakeLists.txt
@@ -7,7 +7,6 @@
 #===------------------------------------------------------------------------===#
 
 add_subdirectory(bbc)
-add_subdirectory(f18)
 add_subdirectory(flang-driver)
 add_subdirectory(tco)
 add_subdirectory(f18-parse-demo)
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index edfc878d17524..a98a94e32bee4 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -98,6 +98,11 @@ static llvm::cl::alias
                           llvm::cl::desc("intrinsic module directory"),
                           llvm::cl::aliasopt(intrinsicIncludeDirs));
 
+static llvm::cl::alias
+    intrinsicModulePath("fintrinsic-modules-path",
+                        llvm::cl::desc("intrinsic module search paths"),
+                        llvm::cl::aliasopt(intrinsicIncludeDirs));
+
 static llvm::cl::opt<std::string>
     moduleDir("module", llvm::cl::desc("module output directory (default .)"),
               llvm::cl::init("."));
@@ -568,17 +573,8 @@ int main(int argc, char **argv) {
   ProgramName programPrefix;
   programPrefix = argv[0] + ": "s;
 
-  if (includeDirs.size() == 0) {
+  if (includeDirs.size() == 0)
     includeDirs.push_back(".");
-    // Default Fortran modules should be installed in include/flang (a sibling
-    // to the bin) directory.
-    intrinsicIncludeDirs.push_back(
-        llvm::sys::path::parent_path(
-            llvm::sys::path::parent_path(
-                llvm::sys::fs::getMainExecutable(argv[0], nullptr)))
-            .str() +
-        "/include/flang");
-  }
 
   Fortran::parser::Options options;
   options.predefinitions.emplace_back("__flang__"s, "1"s);
diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
deleted file mode 100644
index 546b6acaaf91d..0000000000000
--- a/flang/tools/f18/CMakeLists.txt
+++ /dev/null
@@ -1,176 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  FrontendOpenACC
-  FrontendOpenMP
-  Support
-  )
-
-# Define the list of Fortran module files for which it is
-# sufficient to generate the module file via -fsyntax-only.
-set(MODULES
-  "__fortran_builtins"
-  "__fortran_ieee_exceptions"
-  "__fortran_type_info"
-  "__ppc_types"
-  "__ppc_intrinsics"
-  "mma"
-  "__cuda_builtins"
-  "__cuda_device"
-  "cooperative_groups"
-  "cudadevice"
-  "ieee_arithmetic"
-  "ieee_exceptions"
-  "ieee_features"
-  "iso_c_binding"
-  "iso_fortran_env"
-  "iso_fortran_env_impl"
-)
-
-# Check if 128-bit float computations can be done via long double.
-check_cxx_source_compiles(
-  "#include <cfloat>
-   #if LDBL_MANT_DIG != 113
-   #error LDBL_MANT_DIG != 113
-   #endif
-   int main() { return 0; }
-  "
-  HAVE_LDBL_MANT_DIG_113)
-
-# Figure out whether we can support REAL(KIND=16)
-if (FLANG_RUNTIME_F128_MATH_LIB)
-  set(FLANG_SUPPORT_R16 "1")
-elseif (HAVE_LDBL_MANT_DIG_113)
-  set(FLANG_SUPPORT_R16 "1")
-else()
-  set(FLANG_SUPPORT_R16 "0")
-endif()
-
-# Init variable to hold extra object files coming from the Fortran modules;
-# these module files will be contributed from the CMakeLists in flang/tools/f18.
-set(module_objects "")
-
-# Create module files directly from the top-level module source directory.
-# If CMAKE_CROSSCOMPILING, then the newly built flang executable was
-# cross compiled, and thus can't be executed on the build system and thus
-# can't be used for generating module files.
-if (NOT CMAKE_CROSSCOMPILING)
-  foreach(filename ${MODULES})
-    set(depends "")
-    set(opts "")
-    if(${filename} STREQUAL "__fortran_builtins" OR
-       ${filename} STREQUAL "__ppc_types")
-    elseif(${filename} STREQUAL "__ppc_intrinsics" OR
-           ${filename} STREQUAL "mma")
-      set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__ppc_types.mod)
-    elseif(${filename} STREQUAL "__cuda_device" OR
-           ${filename} STREQUAL "cudadevice" OR
-           ${filename} STREQUAL "cooperative_groups")
-      set(opts -fc1 -xcuda)
-      if(${filename} STREQUAL "__cuda_device")
-        set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__cuda_builtins.mod)
-      elseif(${filename} STREQUAL "cudadevice")
-        set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__cuda_device.mod)
-      elseif(${filename} STREQUAL "cooperative_groups")
-        set(depends ${FLANG_INTRINSIC_MODULES_DIR}/cudadevice.mod)
-      endif()
-    else()
-      set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_builtins.mod)
-      if(${filename} STREQUAL "iso_fortran_env")
-        set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/iso_fortran_env_impl.mod)
-      endif()
-      if(${filename} STREQUAL "ieee_arithmetic" OR
-         ${filename} STREQUAL "ieee_exceptions")
-        set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod)
-      endif()
-    endif()
-    if(NOT ${filename} STREQUAL "__fortran_type_info" AND NOT ${filename} STREQUAL "__fortran_builtins")
-      set(depends ${depends} ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_type_info.mod)
-    endif()
-
-    # The module contains PPC vector types that needs the PPC target.
-    if(${filename} STREQUAL "__ppc_intrinsics" OR
-       ${filename} STREQUAL "mma")
-      if (PowerPC IN_LIST LLVM_TARGETS_TO_BUILD)
-        set(opts "--target=ppc64le")
-      else()
-        # Do not compile PPC module if the target is not available.
-        continue()
-      endif()
-    endif()
-
-    set(decls "")
-    if (FLANG_SUPPORT_R16)
-      set(decls "-DFLANG_SUPPORT_R16")
-    endif()
-
-    # Some modules have an implementation part that needs to be added to the
-    # flang_rt.runtime library.
-    set(compile_with "-fsyntax-only")
-    set(object_output "")
-    set(include_in_link FALSE)
-
-    set(base ${FLANG_INTRINSIC_MODULES_DIR}/${filename})
-    # TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support
-    add_custom_command(OUTPUT ${base}.mod ${object_output}
-      COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
-      COMMAND flang ${opts} ${decls} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
-        ${FLANG_SOURCE_DIR}/module/${filename}.f90
-      DEPENDS flang ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${FLANG_SOURCE_DIR}/module/__fortran_builtins.f90 ${depends}
-    )
-    list(APPEND MODULE_FILES ${base}.mod)
-    install(FILES ${base}.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang" COMPONENT flang-module-interfaces)
-
-    # If a module has been compiled into an object file, add the file to
-    # the link line for the flang_rt.runtime library.
-    if(include_in_link)
-      list(APPEND module_objects ${object_output})
-    endif()
-  endforeach()
-
-  # Set a CACHE variable that is visible to the CMakeLists.txt in runtime/, so that
-  # the compiled Fortran modules can be added to the link line of the flang_rt.runtime
-  # library.
-  set(FORTRAN_MODULE_OBJECTS ${module_objects} CACHE INTERNAL "" FORCE)
-
-  # Special case for omp_lib.mod, because its source comes from openmp/runtime/src/include.
-  # It also produces two module files: omp_lib.mod and omp_lib_kinds.mod.  Compile these
-  # files only if OpenMP support has been configured.
-  if (LLVM_TOOL_OPENMP_BUILD)
-    message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_PROJECTS, building omp_lib.mod")
-    set(base ${FLANG_INTRINSIC_MODULES_DIR}/omp_lib)
-    add_custom_command(OUTPUT ${base}.mod ${base}_kinds.mod
-      COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
-      COMMAND flang -cpp -fsyntax-only ${opts} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
-        ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.F90
-      DEPENDS flang ${FLANG_INTRINSIC_MODULES_DIR}/iso_c_binding.mod ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.F90 ${depends}
-    )
-    add_custom_command(OUTPUT ${base}.f18.mod
-      DEPENDS ${base}.mod
-      COMMAND ${CMAKE_COMMAND} -E copy ${base}.mod ${base}.f18.mod)
-      add_custom_command(OUTPUT ${base}_kinds.f18.mod
-        DEPENDS ${base}.mod
-        COMMAND ${CMAKE_COMMAND} -E copy ${base}_kinds.mod ${base}_kinds.f18.mod)
-    list(APPEND MODULE_FILES ${base}.mod ${base}.f18.mod ${base}_kinds.mod ${base}_kinds.f18.mod)
-    install(FILES ${base}.mod ${base}.f18.mod ${base}_kinds.mod ${base}_kinds.f18.mod DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang" COMPONENT flang-module-interfaces)
-  elseif ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
-    message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_RUNTIMES, assuming omp_lib.mod is built there")
-  else()
-    message(WARNING "Not building omp_lib.mod, no OpenMP runtime in either LLVM_ENABLE_PROJECTS or LLVM_ENABLE_RUNTIMES")
-  endif()
-  add_llvm_install_targets(install-flang-module-interfaces
-    COMPONENT flang-module-interfaces)
-endif()
-
-add_custom_target(module_files ALL DEPENDS ${MODULE_FILES})
-set_target_properties(module_files PROPERTIES FOLDER "Flang/Resources")
-
-# TODO Move this to a more suitable location
-# Copy the generated omp_lib.h header file, if OpenMP support has been configured.
-if (LLVM_TOOL_OPENMP_BUILD)
-  message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_PROJECTS, building omp_lib.h")
-  file(COPY ${CMAKE_BINARY_DIR}/projects/openmp/runtime/src/omp_lib.h DESTINATION "${CMAKE_BINARY_DIR}/include/flang/OpenMP/" FILE_PERMISSIONS OWNER_READ OWNER_WRITE)
-  install(FILES ${CMAKE_BINARY_DIR}/include/flang/OpenMP/omp_lib.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/flang/OpenMP")
-elseif ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES)
-  message(STATUS "OpenMP runtime support enabled via LLVM_ENABLE_RUNTIMES, assuming omp_lib.h is built there")
-else()
-  message(STATUS "Not copying omp_lib.h, no OpenMP runtime in either LLVM_ENABLE_PROJECTS or LLVM_ENABLE_RUNTIMES")
-endif()
diff --git a/flang/tools/f18/dump.cpp b/flang/tools/f18/dump.cpp
deleted file mode 100644
index f11b5aedf4c6a..0000000000000
--- a/flang/tools/f18/dump.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===-- tools/f18/dump.cpp ------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// This file defines Dump routines available for calling from the debugger.
-// Each is based on operator<< for that type. There are overloadings for
-// reference and pointer, and for dumping to a provided raw_ostream or errs().
-
-#ifdef DEBUGF18
-
-#include "llvm/Support/raw_ostream.h"
-
-#define DEFINE_DUMP(ns, name) \
-  namespace ns { \
-  class name; \
-  llvm::raw_ostream &operator<<(llvm::raw_ostream &, const name &); \
-  } \
-  void Dump(llvm::raw_ostream &os, const ns::name &x) { os << x << '\n'; } \
-  void Dump(llvm::raw_ostream &os, const ns::name *x) { \
-    if (x == nullptr) \
-      os << "null\n"; \
-    else \
-      Dump(os, *x); \
-  } \
-  void Dump(const ns::name &x) { Dump(llvm::errs(), x); } \
-  void Dump(const ns::name *x) { Dump(llvm::errs(), *x); }
-
-namespace Fortran {
-DEFINE_DUMP(parser, Name)
-DEFINE_DUMP(parser, CharBlock)
-DEFINE_DUMP(semantics, Symbol)
-DEFINE_DUMP(semantics, Scope)
-DEFINE_DUMP(semantics, IntrinsicTypeSpec)
-DEFINE_DUMP(semantics, DerivedTypeSpec)
-DEFINE_DUMP(semantics, DeclTypeSpec)
-} // namespace Fortran
-
-#endif
diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt
index 94a43b96d2188..96391ed70133e 100644
--- a/llvm/runtimes/CMakeLists.txt
+++ b/llvm/runtimes/CMakeLists.txt
@@ -252,6 +252,11 @@ function(runtime_default_target)
     # OpenMP tests
     list(APPEND extra_targets "libomp-mod")
   endif ()
+  if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+    # The target flang-rt-mod is a dependee of check-flang needed to run its
+    # tests.
+    list(APPEND extra_targets "flang-rt-mod")
+  endif ()
 
   if(LLVM_INCLUDE_TESTS)
     set_property(GLOBAL APPEND PROPERTY LLVM_ALL_LIT_TESTSUITES "@${LLVM_BINARY_DIR}/runtimes/runtimes-bins/lit.tests")
@@ -519,18 +524,12 @@ if(build_runtimes)
       endif()
     endforeach()
   endif()
+
+  # TODO: Also enable Fortran for per-target runtimes needed for cross-compilation.
+  if ("openmp" IN_LIST LLVM_ENABLE_RUNTIMES AND "flang" IN_LIST LLVM_ENABLE_PROJECTS)
+    list(APPEND extra_args ENABLE_FORTRAN)
+  endif()
   if("openmp" IN_LIST LLVM_ENABLE_RUNTIMES OR "offload" IN_LIST LLVM_ENABLE_RUNTIMES)
-    if (${LLVM_TOOL_FLANG_BUILD})
-      message(STATUS "Configuring build of omp_lib.mod and omp_lib_kinds.mod via flang")
-      set(LIBOMP_FORTRAN_MODULES_COMPILER "${CMAKE_BINARY_DIR}/bin/flang")
-      set(LIBOMP_MODULES_INSTALL_PATH "${CMAKE_INSTALL_INCLUDEDIR}/flang")
-      # TODO: This is a workaround until flang becomes a first-class project
-      # in llvm/CMakeList.txt.  Until then, this line ensures that flang is
-      # built before "openmp" is built as a runtime project.  Besides "flang"
-      # to build the compiler, we also need to add "module_files" to make sure
-      # that all .mod files are also properly build.
-      list(APPEND extra_deps "flang" "module_files")
-    endif()
     foreach(dep opt llvm-link llvm-extract clang clang-offload-packager clang-nvlink-wrapper)
       if(TARGET ${dep})
         list(APPEND extra_deps ${dep})
diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt
index c206386fa6b61..3b64db92dcdea 100644
--- a/openmp/CMakeLists.txt
+++ b/openmp/CMakeLists.txt
@@ -100,6 +100,10 @@ set(OPENMP_TEST_FLAGS "" CACHE STRING
 set(OPENMP_TEST_OPENMP_FLAGS ${OPENMP_TEST_COMPILER_OPENMP_FLAGS} CACHE STRING
   "OpenMP compiler flag to use for testing OpenMP runtime libraries.")
 
+if (LLVM_RUNTIMES_BUILD)
+  flang_module_fortran_enable()
+endif ()
+
 set(ENABLE_LIBOMPTARGET ON)
 # Currently libomptarget cannot be compiled on Windows or MacOS X.
 # Since the device plugins are only supported on Linux anyway,
diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 698e185d9c4dd..66acb3fd04136 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -368,45 +368,6 @@ endif()
 configure_file(${LIBOMP_INC_DIR}/omp_lib.h.var omp_lib.h @ONLY)
 configure_file(${LIBOMP_INC_DIR}/omp_lib.F90.var omp_lib.F90 @ONLY)
 
-set(BUILD_FORTRAN_MODULES False)
-if (NOT ${LIBOMP_FORTRAN_MODULES_COMPILER} STREQUAL "")
-  # If libomp is built as an LLVM runtime and the flang compiler is available,
-  # compile the Fortran module files.
-  message(STATUS "configuring openmp to build Fortran module files using ${LIBOMP_FORTRAN_MODULES_COMPILER}")
-  set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.F90)
-  add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod)
-  add_custom_command(
-    OUTPUT omp_lib.mod omp_lib_kinds.mod
-    COMMAND ${LIBOMP_FORTRAN_MODULES_COMPILER} -cpp -fsyntax-only ${LIBOMP_FORTRAN_SOURCE_FILE}
-    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_FORTRAN_SOURCE_FILE}
-      ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
-  )
-  set(BUILD_FORTRAN_MODULES True)
-elseif(${LIBOMP_FORTRAN_MODULES})
-  # The following requests explicit building of the Fortran module files
-  # Workaround for gfortran to build modules with the
-  # omp_sched_monotonic integer parameter
-  if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
-    set(ADDITIONAL_Fortran_FLAGS "-fno-range-check")
-  endif()
-  add_custom_target(libomp-mod ALL DEPENDS omp_lib.mod omp_lib_kinds.mod)
-  set_target_properties(libomp-mod PROPERTIES FOLDER "OpenMP/Misc")
-  libomp_get_fflags(LIBOMP_CONFIGURED_FFLAGS)
-  if(CMAKE_Fortran_COMPILER_SUPPORTS_F90)
-    set(LIBOMP_FORTRAN_SOURCE_FILE omp_lib.F90)
-  else()
-    message(FATAL_ERROR "Fortran module build requires Fortran 90 compiler")
-  endif()
-  add_custom_command(
-    OUTPUT omp_lib.mod omp_lib_kinds.mod
-    COMMAND ${CMAKE_Fortran_COMPILER} -c ${ADDITIONAL_Fortran_FLAGS}
-            ${LIBOMP_CONFIGURED_FFLAGS} ${LIBOMP_FORTRAN_SOURCE_FILE}
-    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${LIBOMP_FORTRAN_SOURCE_FILE}
-      ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
-  )
-  set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES omp_lib${CMAKE_C_OUTPUT_EXTENSION})
-  set(BUILD_FORTRAN_MODULES True)
-endif()
 
 # Move files to exports/ directory if requested
 if(${LIBOMP_COPY_EXPORTS})
@@ -482,15 +443,32 @@ if(${LIBOMP_OMPT_SUPPORT})
   install(FILES ${LIBOMP_HEADERS_INTDIR}/omp-tools.h DESTINATION ${LIBOMP_HEADERS_INSTALL_PATH} RENAME ompt.h)
   set(LIBOMP_OMP_TOOLS_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
 endif()
-if(${BUILD_FORTRAN_MODULES})
+
+
+# Build the modules files if a Fortran compiler is available
+# only LLVM_ENABLE_RUNTIMES=openmp is supported, LLVM_ENABLE_PROJECTS=openmp has been deprecated.
+if(LLVM_RUNTIMES_BUILD AND RUNTIMES_FLANG_MODULES_ENABLED)
+  # TODO: Consider including in LIBOMP_SOURCE_FILES instead
+  add_library(libomp-mod OBJECT
+    omp_lib.F90
+  )
+  set_target_properties(libomp-mod PROPERTIES FOLDER "OpenMP/Fortran Modules")
+
+  libomp_get_fflags(LIBOMP_CONFIGURED_FFLAGS)
+  target_compile_options(libomp-mod PRIVATE ${LIBOMP_CONFIGURED_FFLAGS})
+  if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
+   target_compile_options(libomp-mod PRIVATE -fno-range-check)
+  endif()
+
+  flang_module_target(libomp-mod PUBLIC)
+  add_dependencies(libomp-mod flang-rt-mod)
+
   set (destination ${LIBOMP_HEADERS_INSTALL_PATH})
   if (NOT ${LIBOMP_MODULES_INSTALL_PATH} STREQUAL "")
     set (destination ${LIBOMP_MODULES_INSTALL_PATH})
   endif()
   install(FILES
     ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.h
-    ${CMAKE_CURRENT_BINARY_DIR}/omp_lib.mod
-    ${CMAKE_CURRENT_BINARY_DIR}/omp_lib_kinds.mod
     DESTINATION ${destination}
   )
 endif()
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index e4dd4ebfc678d..2dcc68b80b07c 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -91,6 +91,16 @@ include(CheckLibraryExists)
 include(LLVMCheckCompilerLinkerFlag)
 include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
+include(ExtendPath)
+
+
+# Determine whether we are in the runtimes/runtimes-bins directory of a
+# bootstrapping 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()
+
 
 # CMake omits default compiler include paths, but in runtimes build, we use
 # -nostdinc and -nostdinc++ and control include paths manually so this behavior
@@ -98,6 +108,7 @@ include(CheckCXXCompilerFlag)
 # paths that are inside the build directory disables this behavior.
 #
 # See https://gitlab.kitware.com/cmake/cmake/-/issues/19227 for further details.
+# FIXME: This assumes compiling libc++, but creates problems for every library that uses the C++ standard library
 
 function(filter_prefixed list prefix outvar)
   foreach(str ${list})
@@ -276,6 +287,156 @@ if(LLVM_INCLUDE_TESTS)
   umbrella_lit_testsuite_begin(check-runtimes)
 endif()
 
+# Determine paths for files that belong into the Clang/Flang resource dir.
+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(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.
+  # 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.
+include(GetToolchainDirs)
+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)
+
+
+# Enable building Fortran modules
+# * Set up the Fortran compiler
+# * Determine files location in the Clang/Flang resource dir
+# * Install module files
+macro (flang_module_fortran_enable)
+  include(CheckLanguage)
+  check_language(Fortran)
+  if(NOT CMAKE_Fortran_COMPILER)
+    message(STATUS "Not compiling Flang modules: Fortran not enabled")
+    return ()
+  endif ()
+  enable_language(Fortran)
+
+  if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    if ("flang-rt" IN_LIST LLVM_ENABLE_RUNTIMES)
+      message(STATUS "Compiling Flang modules")
+      set(RUNTIMES_FLANG_MODULES_ENABLED ON)
+    else ()
+      # TODO: Introspection of whether intrinsic modules are already available, so the openmp modules can be built without flang-rt in LLVM_ENABLE_RUNTIMES
+      message(STATUS "Not compiling Flang modules: flang-rt not available")
+    endif ()
+  else ()
+    message(STATUS "Compiling modules for non-Flang compiler (${CMAKE_Fortran_COMPILER_ID})")
+    set(RUNTIMES_FLANG_MODULES_ENABLED ON)
+  endif ()
+
+  if (NOT RUNTIMES_FLANG_MODULES_ENABLED)
+    return ()
+  endif ()
+
+
+  if (CMAKE_Fortran_COMPILER_ID STREQUAL "LLVMFlang")
+    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)
+
+  # Avoid module files to be installed multiple times if this macro is called multiple times
+  get_property(is_installed GLOBAL PROPERTY RUNTIMES_MODS_INSTALLED)
+  if (NOT is_installed)
+    # No way to find out which mod files built by target individually, 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}"
+    )
+    set_property(GLOBAL PROPERTY RUNTIMES_MODS_INSTALLED TRUE)
+  endif ()
+endmacro ()
+
+
+# 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)
+    return ()
+  endif ()
+
+  # Let it find the other public module files
+  target_compile_options(${tgtname} PRIVATE
+      "$<$<COMPILE_LANGUAGE:Fortran>:SHELL:-fintrinsic-modules-path;SHELL:${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>"
+    )
+
+  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 ()
+
+
 # We do this in two loops so that HAVE_* is set for each runtime before the
 # other runtimes are added.
 foreach(entry ${runtimes})
@@ -363,4 +524,4 @@ if(CMAKE_EXPORT_COMPILE_COMMANDS AND NOT ("${LLVM_BINARY_DIR}" STREQUAL "${CMAKE
                              -o ${LLVM_BINARY_DIR}/compile_commands.json
                      DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json)
   add_custom_target(merge_runtime_commands ALL DEPENDS ${LLVM_BINARY_DIR}/compile_commands.json)
-endif()
+endif()
\ No newline at end of file

>From a1533ccdd1e0ac3c153a3b8a6007004a0a6cac75 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 17 Jul 2025 15:13:47 +0200
Subject: [PATCH 2/5] python format

---
 flang/test/lit.cfg.py | 45 ++++++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 16 deletions(-)

diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 8a375fdf49b8b..b05eba8da0b0c 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -128,39 +128,53 @@
     config.available_features.add("default_sysroot")
 
 
-flang_exe =  lit.util.which("flang", config.flang_llvm_tools_dir)
+flang_exe = lit.util.which("flang", config.flang_llvm_tools_dir)
 if not flang_exe:
     lit_config.fatal(f"Could not identify flang executable")
 
+
 def get_resource_module_intrinsic_dir():
     # Determine the intrinsic module search path that is added by the driver. If
     # skipping the driver using -fc1, we need to append the path manually.
-    flang_intrinsics_dir = subprocess.check_output([flang_exe, "-print-file-name=__fortran_builtins.mod"], text=True).strip()
+    flang_intrinsics_dir = subprocess.check_output(
+        [flang_exe, "-print-file-name=__fortran_builtins.mod"], text=True
+    ).strip()
     if not flang_intrinsics_dir:
         return None
     flang_intrinsics_dir = os.path.dirname(flang_intrinsics_dir)
     return flang_intrinsics_dir
 
+
 intrinsics_search_args = []
 if flang_intrinsics_dir := get_resource_module_intrinsic_dir():
-    intrinsics_search_args += ["-fintrinsic-modules-path",flang_intrinsics_dir]
+    intrinsics_search_args += ["-fintrinsic-modules-path", flang_intrinsics_dir]
     lit_config.note(f"using default module intrinsics: {flang_intrinsics_dir}")
 
 extra_intrinsics_search_args = []
 if config.flang_intrinsic_modules_dir:
-    extra_intrinsics_search_args += ["-fintrinsic-modules-path", config.flang_intrinsic_modules_dir]
-    lit_config.note(f"using extra module intrinsics: {config.flang_intrinsic_modules_dir}")
+    extra_intrinsics_search_args += [
+        "-fintrinsic-modules-path",
+        config.flang_intrinsic_modules_dir,
+    ]
+    lit_config.note(
+        f"using extra module intrinsics: {config.flang_intrinsic_modules_dir}"
+    )
 
-config.substitutions.append(("%intrinsic_module_flags", ' '.join(intrinsics_search_args + extra_intrinsics_search_args)))
+config.substitutions.append(
+    (
+        "%intrinsic_module_flags",
+        " ".join(intrinsics_search_args + extra_intrinsics_search_args),
+    )
+)
 
 # For each occurrence of a flang tool name, replace it with the full path to
 # the build directory holding that tool.
 tools = [
     ToolSubst(
         "bbc",
-         command=FindTool("bbc"),
-         extra_args=intrinsics_search_args + extra_intrinsics_search_args,
-         unresolved="fatal",
+        command=FindTool("bbc"),
+        extra_args=intrinsics_search_args + extra_intrinsics_search_args,
+        unresolved="fatal",
     ),
     ToolSubst(
         "%flang",
@@ -174,12 +188,11 @@ def get_resource_module_intrinsic_dir():
         extra_args=["-fc1"] + intrinsics_search_args + extra_intrinsics_search_args,
         unresolved="fatal",
     ),
-
     # For not having intrinsic search paths to be added implicitly
     ToolSubst(
-         "%bbc_bare",
-         command=FindTool("bbc"),
-         unresolved="fatal",
+        "%bbc_bare",
+        command=FindTool("bbc"),
+        unresolved="fatal",
     ),
     ToolSubst(
         "%flang_bare",
@@ -225,10 +238,10 @@ def get_resource_module_intrinsic_dir():
 # If intrinsic modules are not available, disable tests unless they are marked as 'module-independent'.
 config.available_features.add("module-independent")
 if config.have_flangrt_mod or config.flang_intrinsic_modules_dir:
-   config.available_features.add("flangrt-modules")
+    config.available_features.add("flangrt-modules")
 else:
-   lit_config.warning(f"Intrinsic modules not available: disabling most tests")
-   config.limit_to_features.add("module-independent")
+    lit_config.warning(f"Intrinsic modules not available: disabling most tests")
+    config.limit_to_features.add("module-independent")
 
 # Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file)
 openmp_flags_substitution = "-fopenmp"

>From 60ad12fb5bf75fbb33348846bbbd1929eb15ea6d Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 17 Jul 2025 16:58:49 +0200
Subject: [PATCH 3/5] Minimize changes in .f90 files

---
 flang-rt/lib/runtime/__fortran_builtins.f90  | 2 +-
 flang-rt/lib/runtime/__fortran_type_info.f90 | 7 ++-----
 flang-rt/lib/runtime/cooperative_groups.f90  | 2 +-
 flang-rt/lib/runtime/ieee_arithmetic.f90     | 3 ++-
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/flang-rt/lib/runtime/__fortran_builtins.f90 b/flang-rt/lib/runtime/__fortran_builtins.f90
index d5e55b5d95020..7bb078c0b428e 100644
--- a/flang-rt/lib/runtime/__fortran_builtins.f90
+++ b/flang-rt/lib/runtime/__fortran_builtins.f90
@@ -12,7 +12,7 @@
 ! from being usable on INTRINSIC statements, and force the program
 ! to USE the standard intrinsic modules in order to access the
 ! standard names of the procedures.
-module    __fortran_builtins
+module __fortran_builtins
   implicit none
 
   ! Set PRIVATE by default to explicitly only export what is meant
diff --git a/flang-rt/lib/runtime/__fortran_type_info.f90 b/flang-rt/lib/runtime/__fortran_type_info.f90
index 2f936c3787a61..6af2a5a5e30ff 100644
--- a/flang-rt/lib/runtime/__fortran_type_info.f90
+++ b/flang-rt/lib/runtime/__fortran_type_info.f90
@@ -12,11 +12,8 @@
 ! in order to generate description tables for all other derived types.
 
 module __fortran_type_info
-#if 0
-  use       __fortran_builtins, &
-#else
-  use, intrinsic ::    __fortran_builtins, &
-#endif
+
+  use, intrinsic :: __fortran_builtins, &
     only: __builtin_c_ptr, __builtin_c_devptr, __builtin_c_funptr
   implicit none
 
diff --git a/flang-rt/lib/runtime/cooperative_groups.f90 b/flang-rt/lib/runtime/cooperative_groups.f90
index 82d1e0fe84042..fb6d24c8f7bc3 100644
--- a/flang-rt/lib/runtime/cooperative_groups.f90
+++ b/flang-rt/lib/runtime/cooperative_groups.f90
@@ -11,7 +11,7 @@
 module cooperative_groups
 
 use, intrinsic :: __fortran_builtins, only: c_devptr => __builtin_c_devptr
-use :: cudadevice ! implicit dependency, make explicit for CMake
+use :: cudadevice ! implicit dependency, made explicit for CMake
 
 implicit none
 
diff --git a/flang-rt/lib/runtime/ieee_arithmetic.f90 b/flang-rt/lib/runtime/ieee_arithmetic.f90
index b3288a5cdd69f..bad290ab30097 100644
--- a/flang-rt/lib/runtime/ieee_arithmetic.f90
+++ b/flang-rt/lib/runtime/ieee_arithmetic.f90
@@ -8,7 +8,7 @@
 
 ! Fortran 2018 Clause 17
 
-#include   '../include/flang/Runtime/magic-numbers.h'
+#include '../../../flang/include/flang/Runtime/magic-numbers.h'
 
 module ieee_arithmetic
   ! F18 Clause 17.1p1:
@@ -336,6 +336,7 @@ end subroutine ieee_get_underflow_mode_l##GKIND;
   public ::  ieee_get_underflow_mode
 #undef IEEE_GET_UNDERFLOW_MODE_L
 
+! Workaround for https://github.com/llvm/llvm-project/issues/139297
 ! #define IEEE_IS_FINITE_R(XKIND) elemental logical function ieee_is_finite_a##XKIND(x);  real(XKIND), intent(in) :: x;  !dir$ ignore_tkr(d) x;   end function ieee_is_finite_a##XKIND;
   interface ieee_is_finite
 elemental logical function ieee_is_finite_a2(x); real(2), intent(in) :: x;

>From e58c524bd588484e99163899241d55be316b719a Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 17 Jul 2025 17:05:16 +0200
Subject: [PATCH 4/5] Move CMake 3.20 workaround to where it is needed

---
 flang-rt/CMakeLists.txt | 34 ----------------------------------
 runtimes/CMakeLists.txt | 34 +++++++++++++++++++++++++++++++++-
 2 files changed, 33 insertions(+), 35 deletions(-)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 09f4f9e7213f1..61fb9e744bce9 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -23,40 +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"
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 2dcc68b80b07c..a49453a5fcf67 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -108,7 +108,6 @@ endif()
 # paths that are inside the build directory disables this behavior.
 #
 # See https://gitlab.kitware.com/cmake/cmake/-/issues/19227 for further details.
-# FIXME: This assumes compiling libc++, but creates problems for every library that uses the C++ standard library
 
 function(filter_prefixed list prefix outvar)
   foreach(str ${list})
@@ -335,6 +334,39 @@ cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_LIB_DIR)
 cmake_path(NORMAL_PATH RUNTIMES_INSTALL_RESOURCE_LIB_PATH)
 
 
+# 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 building Fortran modules
 # * Set up the Fortran compiler
 # * Determine files location in the Clang/Flang resource dir

>From 7d1a8bee595443112031604bf9e7bf43f3a2635a Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Thu, 17 Jul 2025 19:39:06 +0200
Subject: [PATCH 5/5] Don't forget to enable Fortran

---
 flang-rt/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index 61fb9e744bce9..fd6ad5a170934 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -23,6 +23,7 @@ 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")
 
+enable_language(Fortran)
 
 list(APPEND CMAKE_MODULE_PATH
     "${FLANG_RT_SOURCE_DIR}/cmake/modules"



More information about the flang-commits mailing list