From c829dbc2541f1d0bd2db6ee0128030262a757d34 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Wed, 22 Apr 2026 12:43:32 +0200 Subject: [PATCH 1/6] Use INTERFACE targets for dependencies --- runtimes/cmake/config-Fortran.cmake | 71 ++++++++++++++++++----------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake index f5cea1fc67e29..28899d07b87dc 100644 --- a/runtimes/cmake/config-Fortran.cmake +++ b/runtimes/cmake/config-Fortran.cmake @@ -6,11 +6,6 @@ # not needed or is insufficient, e.g. if intrinsic modules are missing and # cannot be compiled on-the-fly. # -# RUNTIMES_FORTRAN_BUILD_DEPS - If RUNTIMES_ENABLE_FORTRAN is true, this is a -# list of dependencies that must be built before any Fortran source can be -# compiled. Contains the build targets for intrinsic modules, if necessary. -# Otherweise, it is empty. -# # RUNTIMES_ENABLE_FLANG_MODULES - Whether to build Flang modules and emit them # into Flang's search path. This is a CMake CACHE option defined in # config-Fortran.cmake and default to ON iff the Fortran compiler is detected @@ -23,6 +18,18 @@ # RUNTIMES_INSTALL_RESOURCE_MOD_PATH - Where to install intrinsic module files # in the install prefix. Relative to CMAKE_INSTALL_PREFIX. Only used when # RUNTIMES_ENABLE_FLANG_MODULES is ON. +# +# +# The following targets are defined: +# +# fortran-compile-depends - link to this INTERFACE library to ensure Fortran +# sources can be compiled. Primarily ensures that the builtin modules from +# flang-rt are built before. +# +# fortran-link-depends - link to this INTERFACE library to ensure +# Fortran-compiled object files can be linked. Primarily ensures that libflang_rt.runtime(.a/.so) is build before. +# +# fortran-depends - combination of the two above # Check whether the Fortran compiler already has access to builtin modules. Sets @@ -74,14 +81,14 @@ endfunction () set(RUNTIMES_ENABLE_FORTRAN OFF) -# Insert at least one element for -# -# add_dependencies(target ${RUNTIMES_FORTRAN_BUILD_DEPS}) -# -# to not fail -add_custom_target(fortran-dummy-dep) -set(RUNTIMES_FORTRAN_BUILD_DEPS fortran-dummy-dep) - +# Targets compiling Fortran sources can depend on this target to ensure toolchain +# prerequisites are built before (runtime library and intrinsic modules). +add_library(fortran-compile-options INTERFACE) +add_library(fortran-compile-depends INTERFACE) +add_library(fortran-link-depends INTERFACE) +add_library(fortran-depends INTERFACE) +target_link_libraries(fortran-compile-depends INTERFACE fortran-compile-options) +target_link_libraries(fortran-depends INTERFACE fortran-compile-depends fortran-link-depends) if (CMAKE_Fortran_COMPILER) # Workarounds for older versions of CMake not recognizing FLang. Hence, we @@ -154,11 +161,20 @@ if (CMAKE_Fortran_COMPILER) enable_language(Fortran) include(CheckFortranSourceCompiles) + if (CMAKE_Fortran_COMPILER_ID MATCHES "LLVM") + target_compile_options(fortran-compile-options INTERFACE + # Flang bug workaround: Reformating of cooked token buffer causes + # identifier to be split between lines + "$<$:SHELL:-Xflang;SHELL:-fno-reformat>" + ) + endif () + 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. - list(APPEND RUNTIMES_FORTRAN_BUILD_DEPS flang-rt-mod) + target_link_libraries(fortran-compile-depends INTERFACE flang-rt-mod) + target_link_libraries(fortran-link-depends INTERFACE flang-rt.runtime.default) set(RUNTIMES_ENABLE_FORTRAN ON) message(STATUS "Fortran support enabled using just-built Flang-RT builtin modules") else () @@ -219,6 +235,13 @@ else () endif () cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR) +if (CMAKE_Fortran_COMPILER) + # Let all Fortran sources find the public module files + target_compile_options(fortran-compile-options INTERFACE + "$<$:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>" + ) +endif () + # Set options to compile Fortran module files. Assumes the code above has run. # @@ -232,9 +255,11 @@ cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR) # generated but to be forgotten inside the build directory to not # conflict with each other. # Also, installs the module with the toolchain. +# FLANG_RT +# Indicate this is compiling flang-rt to avoid a dependency cycle. # ) function (flang_module_target tgtname) - set(options PUBLIC) + set(options PUBLIC FLANG_RT) cmake_parse_arguments(ARG "${options}" "" @@ -242,17 +267,11 @@ function (flang_module_target tgtname) ${ARGN} ) - # Let all modules find the public module files - target_compile_options(${tgtname} PRIVATE - "$<$:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>" - ) - - if (CMAKE_Fortran_COMPILER_ID MATCHES "LLVM") - target_compile_options(${tgtname} PRIVATE - # Flang bug workaround: Reformating of cooked token buffer causes - # identifier to be split between lines - "$<$:SHELL:-Xflang;SHELL:-fno-reformat>" - ) + if (ARG_FLANG_RT) + # fortran-compile-options only applies compile options, not dependencies + target_link_libraries(${tgtname} INTERFACE fortran-compile-options) + else () + target_link_libraries(${tgtname} INTERFACE fortran-compile-depends) endif () if (ARG_PUBLIC) From 40ba29f30ccfa8ec812b797a14cdf02acf638b9b Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Wed, 22 Apr 2026 14:31:49 +0200 Subject: [PATCH 2/6] INTERFACE does not apply options to target itself --- runtimes/cmake/config-Fortran.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake index 28899d07b87dc..9914aa11af1aa 100644 --- a/runtimes/cmake/config-Fortran.cmake +++ b/runtimes/cmake/config-Fortran.cmake @@ -269,9 +269,9 @@ function (flang_module_target tgtname) if (ARG_FLANG_RT) # fortran-compile-options only applies compile options, not dependencies - target_link_libraries(${tgtname} INTERFACE fortran-compile-options) + target_link_libraries(${tgtname} PRIVATE fortran-compile-options) else () - target_link_libraries(${tgtname} INTERFACE fortran-compile-depends) + target_link_libraries(${tgtname} PRIVATE fortran-compile-depends) endif () if (ARG_PUBLIC) From 675ee70f6e926c0bb0035225a2c04cf094550cca Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Thu, 21 May 2026 23:55:41 +0200 Subject: [PATCH 3/6] Apply suggestions from @tarunprabhu Co-authored-by: Tarun Prabhu --- runtimes/cmake/config-Fortran.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake index 9914aa11af1aa..268c281dcdecd 100644 --- a/runtimes/cmake/config-Fortran.cmake +++ b/runtimes/cmake/config-Fortran.cmake @@ -82,7 +82,7 @@ endfunction () set(RUNTIMES_ENABLE_FORTRAN OFF) # Targets compiling Fortran sources can depend on this target to ensure toolchain -# prerequisites are built before (runtime library and intrinsic modules). +# prerequisites (runtime library and intrinsic modules) are built before. add_library(fortran-compile-options INTERFACE) add_library(fortran-compile-depends INTERFACE) add_library(fortran-link-depends INTERFACE) @@ -163,7 +163,7 @@ if (CMAKE_Fortran_COMPILER) if (CMAKE_Fortran_COMPILER_ID MATCHES "LLVM") target_compile_options(fortran-compile-options INTERFACE - # Flang bug workaround: Reformating of cooked token buffer causes + # Flang bug workaround: Reformatting of cooked token buffer causes # identifier to be split between lines "$<$:SHELL:-Xflang;SHELL:-fno-reformat>" ) From f559e0d9395a2fc9861ee34030412ffd9bdb7917 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Thu, 25 Jun 2026 15:30:00 +0200 Subject: [PATCH 4/6] Leftovers --- runtimes/cmake/config-Fortran.cmake | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake index bbb09d66aa2cf..97f0983c41ac8 100644 --- a/runtimes/cmake/config-Fortran.cmake +++ b/runtimes/cmake/config-Fortran.cmake @@ -253,11 +253,9 @@ endif () # generated but to be forgotten inside the build directory to not # conflict with each other. # Also, installs the module with the toolchain. -# FLANG_RT -# Indicate this is compiling flang-rt to avoid a dependency cycle. # ) function (flang_module_target tgtname) - set(options PUBLIC FLANG_RT) + set(options PUBLIC) cmake_parse_arguments(ARG "${options}" "" @@ -265,12 +263,7 @@ function (flang_module_target tgtname) ${ARGN} ) - if (ARG_FLANG_RT) - # fortran-compile-options only applies compile options, not dependencies - target_link_libraries(${tgtname} PRIVATE fortran-compile-options) - else () target_link_libraries(${tgtname} PRIVATE fortran-compile-depends) - endif () if (ARG_PUBLIC) set_target_properties(${tgtname} From ebac2c83231daefab6e7dbf6cb2a17e4cc76ff03 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 6 Jul 2026 12:52:59 +0200 Subject: [PATCH 5/6] Fix target-level dep --- flang-rt/lib/runtime/CMakeLists.txt | 20 ++++++++++++++++ runtimes/cmake/config-Fortran.cmake | 37 +++++++++++++---------------- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt index 13ce726c19002..ead12283afb02 100644 --- a/flang-rt/lib/runtime/CMakeLists.txt +++ b/flang-rt/lib/runtime/CMakeLists.txt @@ -258,6 +258,25 @@ if (TARGET FortranFloat128MathILib) endif () +# When a target depends on an object library, CMake seems to try to only build +# the object files that the target actual needs. Before having analyzed the module +# dependencies, CMake assumes there are no module-dependencies. +# To ensure that the module files are built, insert a custom target that is +# opaque to CMake so the library has to be built regardless. +# Dependees on module files must add a target-level dependency on the barrier, +# and file-level dependencies on source files via target_link_libraries +# on the OBJECT libray. The target-level dependency ensures that the module +# files are built when they do not exist yet, the file-level dependency ensures +# that dependees are rebuilt when the module file changes. +# An actual COMMAND (that does nothing) seems to be necessary +# on Windows for this to work. +function (add_module_barrier barriername objlib) + add_custom_target(${barriername} + COMMAND ${CMAKE_COMMAND} -E true + ) + add_dependencies(${barriername} ${objlib}) +endfunction () + # Build module files if requested. # The object files written by Flang for these are unused. In the future parts # of flang-rt may itself be implemented in Fortran in which case these Fortran @@ -269,6 +288,7 @@ if (FLANG_RT_FORTRAN_MODULES) ${module_sources} ) flang_module_target(flang-rt-mod PUBLIC) + add_module_barrier(flang-rt-mod.barrier flang-rt-mod) if (RUNTIMES_FORTRAN_MODULES) set(_mod_install_dest "${RUNTIMES_INSTALL_RESOURCE_MOD_PATH}/..") diff --git a/runtimes/cmake/config-Fortran.cmake b/runtimes/cmake/config-Fortran.cmake index 554d14e9c231b..1355796b76e8f 100644 --- a/runtimes/cmake/config-Fortran.cmake +++ b/runtimes/cmake/config-Fortran.cmake @@ -22,15 +22,13 @@ # # The following targets are defined: # +# fortran-compile-options - sets the compile options necessary to compile +# modules. Primarily sets up the intrinsic module search paths if necessary. +# Gets applied to flang-rt as well. +# # fortran-compile-depends - link to this INTERFACE library to ensure Fortran -# sources can be compiled. Primarily ensures that the builtin modules from +# sources can be compiled. Ensures that the builtin modules from # flang-rt are built before. -# -# fortran-link-depends - link to this INTERFACE library to ensure -# Fortran-compiled object files can be linked. Primarily ensures that -# libflang_rt.runtime(.a/.so) is build before. -# -# fortran-depends - combination of the two above # Check whether the Fortran compiler already has access to builtin modules. Sets @@ -86,10 +84,7 @@ set(RUNTIMES_ENABLE_FORTRAN OFF) # prerequisites are built before (runtime library and intrinsic modules). add_library(fortran-compile-options INTERFACE) add_library(fortran-compile-depends INTERFACE) -add_library(fortran-link-depends INTERFACE) -add_library(fortran-depends INTERFACE) target_link_libraries(fortran-compile-depends INTERFACE fortran-compile-options) -target_link_libraries(fortran-depends INTERFACE fortran-compile-depends fortran-link-depends) if (CMAKE_Fortran_COMPILER) # Workarounds for older versions of CMake not recognizing FLang. Hence, we @@ -174,8 +169,7 @@ if (CMAKE_Fortran_COMPILER) # 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. - target_link_libraries(fortran-compile-depends INTERFACE flang-rt-mod) - target_link_libraries(fortran-link-depends INTERFACE flang-rt.runtime.default) + target_link_libraries(fortran-compile-depends INTERFACE flang-rt-mod flang-rt-mod.barrier) set(RUNTIMES_ENABLE_FORTRAN ON) message(STATUS "Fortran support enabled using just-built Flang-RT builtin modules") else () @@ -224,6 +218,11 @@ if (RUNTIMES_FORTRAN_MODULES) # The INSTALL'ed directory must exist, even if empty, or `ninja install` will # fail with an error. file(MAKE_DIRECTORY "${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}") + + # Let all Fortran sources find the public module files + target_compile_options(fortran-compile-options INTERFACE + "$<$:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>" + ) else () # If Flang modules are disabled (e.g. because the compiler is not Flang), avoid the risk of Flang accidentally picking them up. extend_path(RUNTIMES_OUTPUT_RESOURCE_MOD_DIR "${CMAKE_CURRENT_BINARY_DIR}" "finclude-${CMAKE_Fortran_COMPILER_ID}") @@ -233,13 +232,6 @@ else () endif () cmake_path(NORMAL_PATH RUNTIMES_OUTPUT_RESOURCE_MOD_DIR) -if (CMAKE_Fortran_COMPILER) - # Let all Fortran sources find the public module files - target_compile_options(fortran-compile-options INTERFACE - "$<$:-fintrinsic-modules-path=${RUNTIMES_OUTPUT_RESOURCE_MOD_DIR}>" - ) -endif () - # Set options to compile Fortran module files. Assumes the code above has run. # @@ -263,7 +255,12 @@ function (flang_module_target tgtname) ${ARGN} ) - target_link_libraries(${tgtname} PRIVATE fortran-compile-depends) + if (tgtname STREQUAL "flang-rt-mod") + # Avoid circular dependency on flang-rt itself + target_link_libraries(${tgtname} PRIVATE fortran-compile-options) + else () + target_link_libraries(${tgtname} PRIVATE fortran-compile-depends) + endif () # Make CMake not ignore "use, intrinsic ::"-dependencies. Unfortunately, # it is not universally handled by CMake s.t. we currently must not use From 7fc10809cc7a9d16f00936c2b89395ef84316597 Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 6 Jul 2026 14:24:36 +0200 Subject: [PATCH 6/6] Actualy command seems unnecessary even under Windows --- flang-rt/lib/runtime/CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/flang-rt/lib/runtime/CMakeLists.txt b/flang-rt/lib/runtime/CMakeLists.txt index ead12283afb02..ae9a6e7fb7188 100644 --- a/flang-rt/lib/runtime/CMakeLists.txt +++ b/flang-rt/lib/runtime/CMakeLists.txt @@ -268,12 +268,8 @@ endif () # on the OBJECT libray. The target-level dependency ensures that the module # files are built when they do not exist yet, the file-level dependency ensures # that dependees are rebuilt when the module file changes. -# An actual COMMAND (that does nothing) seems to be necessary -# on Windows for this to work. function (add_module_barrier barriername objlib) - add_custom_target(${barriername} - COMMAND ${CMAKE_COMMAND} -E true - ) + add_custom_target(${barriername}) add_dependencies(${barriername} ${objlib}) endfunction ()