https://github.com/wenju-he created 
https://github.com/llvm/llvm-project/pull/198480

Fix runtimes not rebuilt when clang is updated. Rebuild is critical for 
runtimes like libclc that produces bitcode-based builtin library, where 
compiler change should immediately trigger a re-compilation.

By default, CMake add_library does not add compiler executable as dependency 
for objects of source file.

Add a helper LLVMRuntimeCompilerDependency.cmake which exposes 
llvm_defer_compiler_dependency_tracking function. Each runtime can explicitly 
opt-in by calling the function at the beginning of its root CMakeLists to add 
dependency on compilers it uses.

Assisted-by: Claude Sonnet 4.6

>From c10840f2caea25759d9377edfe99ae9246b46b2d Mon Sep 17 00:00:00 2001
From: Wenju He <[email protected]>
Date: Mon, 18 May 2026 11:22:53 +0200
Subject: [PATCH] [Runtimes][CMake] Add dependency on compiler to source files

Fix runtimes not rebuilt when clang is updated. Rebuild is critical for
runtimes like libclc that produces bitcode-based builtin library, where
compiler change should immediately trigger a re-compilation.

By default, CMake add_library does not add compiler executable as
dependency for objects of source file.

Add a helper LLVMRuntimeCompilerDependency.cmake which exposes
llvm_defer_compiler_dependency_tracking function. Each runtime can
explicitly opt-in by calling the function at the beginning of its root
CMakeLists to add dependency on compilers it uses.

Assisted-by: Claude Sonnet 4.6
---
 .../LLVMRuntimeCompilerDependency.cmake       | 14 ++++
 compiler-rt/CMakeLists.txt                    |  4 ++
 flang-rt/CMakeLists.txt                       |  4 ++
 libc/CMakeLists.txt                           |  4 ++
 libclc/CMakeLists.txt                         |  3 +
 libcxx/CMakeLists.txt                         |  3 +
 libcxxabi/CMakeLists.txt                      |  3 +
 libsycl/CMakeLists.txt                        |  3 +
 libunwind/CMakeLists.txt                      |  4 ++
 llvm-libgcc/CMakeLists.txt                    |  4 ++
 .../LLVMRuntimeCompilerDependency.cmake       | 69 +++++++++++++++++++
 offload/CMakeLists.txt                        |  3 +
 openmp/CMakeLists.txt                         |  4 ++
 orc-rt/CMakeLists.txt                         |  4 ++
 14 files changed, 126 insertions(+)
 create mode 100644 cmake/Modules/LLVMRuntimeCompilerDependency.cmake
 create mode 100644 llvm/cmake/modules/LLVMRuntimeCompilerDependency.cmake

diff --git a/cmake/Modules/LLVMRuntimeCompilerDependency.cmake 
b/cmake/Modules/LLVMRuntimeCompilerDependency.cmake
new file mode 100644
index 0000000000000..057eabd5f5404
--- /dev/null
+++ b/cmake/Modules/LLVMRuntimeCompilerDependency.cmake
@@ -0,0 +1,14 @@
+set(_llvm_runtime_compiler_dependency
+  
"${CMAKE_CURRENT_LIST_DIR}/../../llvm/cmake/modules/LLVMRuntimeCompilerDependency.cmake")
+
+if(EXISTS "${_llvm_runtime_compiler_dependency}")
+  include("${_llvm_runtime_compiler_dependency}")
+elseif(LLVM_CMAKE_DIR AND EXISTS 
"${LLVM_CMAKE_DIR}/LLVMRuntimeCompilerDependency.cmake")
+  include("${LLVM_CMAKE_DIR}/LLVMRuntimeCompilerDependency.cmake")
+elseif(LLVM_DIR AND EXISTS "${LLVM_DIR}/LLVMRuntimeCompilerDependency.cmake")
+  include("${LLVM_DIR}/LLVMRuntimeCompilerDependency.cmake")
+else()
+  message(FATAL_ERROR "Could not find LLVMRuntimeCompilerDependency.cmake")
+endif()
+
+unset(_llvm_runtime_compiler_dependency)
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index e88321d822f84..35737cb60de9d 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -51,9 +51,13 @@ include(base-config-ix)
 include(CompilerRTUtils)
 include(CMakeDependentOption)
 include(GetDarwinLinkerVersion)
+include(LLVMRuntimeCompilerDependency)
 
 include(CheckCXXCompilerFlag)
 
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_ASM_COMPILER}")
+
 # Check if we can compile with --no-default-config, or if that omits a config
 # file that is essential for the toolchain to work properly.
 #
diff --git a/flang-rt/CMakeLists.txt b/flang-rt/CMakeLists.txt
index cd1fc8cfbcff9..b51d5d4c0e2cc 100644
--- a/flang-rt/CMakeLists.txt
+++ b/flang-rt/CMakeLists.txt
@@ -57,6 +57,10 @@ if (CMAKE_VERSION VERSION_LESS "3.24")
 endif ()
 enable_language(Fortran)
 
+include(LLVMRuntimeCompilerDependency)
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_Fortran_COMPILER}")
+
 # Try to include the RPC utilities from the `libc` project for GPU I/O support.
 include(FindLibcCommonUtils)
 
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 3b5f3949b286d..2e0a75dc0c7ef 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -38,6 +38,10 @@ endif()
 set(CMAKE_CXX_STANDARD 17)
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
+include(LLVMRuntimeCompilerDependency)
+
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_ASM_COMPILER}")
 
 # The top-level source directory.
 set(LIBC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 44d9f7a281b5d..05f45e6700e75 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -88,6 +88,9 @@ else()
   cmake_path( APPEND LIBCLC_OUTPUT_LIBRARY_DIR ${LIBCLC_INSTALL_DIR} )
 endif()
 
+include(LLVMRuntimeCompilerDependency)
+llvm_defer_compiler_dependency_tracking("${CMAKE_CLC_COMPILER}")
+
 if( NOT LIBCLC_USE_SPIRV_BACKEND )
   # llvm-spirv is an optional dependency, used to build spirv-* targets when
   # the SPIR-V backend hasn't been requested. It may be provided in-tree or
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 845240d1b894c..2c0280e485f3a 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -27,8 +27,11 @@ set(LIBCXX_SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
 set(LIBCXX_BINARY_DIR  ${CMAKE_CURRENT_BINARY_DIR})
 
 include(GNUInstallDirs)
+include(LLVMRuntimeCompilerDependency)
 include(WarningFlags)
 
+llvm_defer_compiler_dependency_tracking("${CMAKE_CXX_COMPILER}")
+
 # Require out of source build.
 include(MacroEnsureOutOfSourceBuild)
 MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
index e1a1587fb6283..7e1fe55646166 100644
--- a/libcxxabi/CMakeLists.txt
+++ b/libcxxabi/CMakeLists.txt
@@ -26,6 +26,9 @@ set(LIBCXXABI_LIBCXX_PATH 
"${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
         "Specify path to libc++ source.")
 
 include(GNUInstallDirs)
+include(LLVMRuntimeCompilerDependency)
+
+llvm_defer_compiler_dependency_tracking("${CMAKE_CXX_COMPILER}")
 
 # Require out of source build.
 include(MacroEnsureOutOfSourceBuild)
diff --git a/libsycl/CMakeLists.txt b/libsycl/CMakeLists.txt
index ae3fd4359c3f2..7a1b34a126b60 100644
--- a/libsycl/CMakeLists.txt
+++ b/libsycl/CMakeLists.txt
@@ -12,6 +12,9 @@ set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED YES)
 set(CMAKE_CXX_EXTENSIONS OFF)
 
+include(LLVMRuntimeCompilerDependency)
+llvm_defer_compiler_dependency_tracking("${CMAKE_CXX_COMPILER}")
+
 
#===============================================================================
 # Limitations
 
#===============================================================================
diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt
index 02132f6c07fcd..30ceeb564bd73 100644
--- a/libunwind/CMakeLists.txt
+++ b/libunwind/CMakeLists.txt
@@ -23,6 +23,10 @@ set(LIBUNWIND_LIBCXX_PATH 
"${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
 
 include(GNUInstallDirs)
 include(CheckSymbolExists)
+include(LLVMRuntimeCompilerDependency)
+
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_ASM_COMPILER}")
 
 if (MSVC)
   message(FATAL_ERROR "Libunwind doesn't build for MSVC targets, and that is 
almost certainly not what you want to do "
diff --git a/llvm-libgcc/CMakeLists.txt b/llvm-libgcc/CMakeLists.txt
index 55c052165dbd1..5c736862ddb24 100644
--- a/llvm-libgcc/CMakeLists.txt
+++ b/llvm-libgcc/CMakeLists.txt
@@ -34,6 +34,10 @@ set(LLVM_LIBGCC_COMPILER_RT_PATH 
"${CMAKE_CURRENT_LIST_DIR}/../compiler-rt"
   CACHE PATH "Specify path to compiler-rt source.")
 
 include(GNUInstallDirs)
+include(LLVMRuntimeCompilerDependency)
+
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_ASM_COMPILER}")
 
 if(NOT LLVM_LIBGCC_EXPLICIT_OPT_IN)
   message(FATAL_ERROR
diff --git a/llvm/cmake/modules/LLVMRuntimeCompilerDependency.cmake 
b/llvm/cmake/modules/LLVMRuntimeCompilerDependency.cmake
new file mode 100644
index 0000000000000..f78192e8cf680
--- /dev/null
+++ b/llvm/cmake/modules/LLVMRuntimeCompilerDependency.cmake
@@ -0,0 +1,69 @@
+include_guard(GLOBAL)
+
+function(_llvm_track_compiler_dependency_dir dir)
+  set(_compilers ${ARGN})
+  if(NOT _compilers)
+    return()
+  endif()
+
+  get_property(_targets DIRECTORY "${dir}" PROPERTY BUILDSYSTEM_TARGETS)
+  foreach(_target IN LISTS _targets)
+    get_target_property(_type ${_target} TYPE)
+    if(NOT _type MATCHES 
"^(OBJECT_LIBRARY|STATIC_LIBRARY|SHARED_LIBRARY|MODULE_LIBRARY|EXECUTABLE)$")
+      continue()
+    endif()
+
+    get_target_property(_sources ${_target} SOURCES)
+
+    # Filter out generator expressions (e.g., $<TARGET_OBJECTS:...>).
+    list(FILTER _sources EXCLUDE REGEX "^\\$<")
+    if(NOT _sources)
+      continue()
+    endif()
+
+    foreach(_compiler IN LISTS _compilers)
+      set_property(SOURCE ${_sources}
+        TARGET_DIRECTORY ${_target}
+        APPEND PROPERTY OBJECT_DEPENDS "${_compiler}")
+    endforeach()
+  endforeach()
+
+  # BUILDSYSTEM_TARGETS is flat, so recurse into subdirectories.
+  get_property(_subdirs DIRECTORY "${dir}" PROPERTY SUBDIRECTORIES)
+  foreach(_subdir IN LISTS _subdirs)
+    _llvm_track_compiler_dependency_dir("${_subdir}" ${_compilers})
+  endforeach()
+endfunction()
+
+# cmake_language(DEFER CALL) re-evaluates arguments at call time in the
+# directory scope.
+function(_llvm_track_compiler_dependency_dir_deferred)
+  get_property(_compilers DIRECTORY PROPERTY _LLVM_TRACK_COMPILERS)
+  if(NOT _compilers)
+    return()
+  endif()
+  _llvm_track_compiler_dependency_dir("${CMAKE_CURRENT_SOURCE_DIR}" 
${_compilers})
+endfunction()
+
+# Add compiler binaries as target dependencies for code recompilation tracking.
+#
+# This function registers compiler binaries as build dependencies for all 
target
+# objects compiled within the specified directory hierarchy. This guarantees
+# that if a compiler binary is rebuilt, all runtime library objects are
+# invalidated and rebuilt.
+#
+# This function must be called at the beginning of a runtime root CMakeLists.
+#
+# Argument COMPILERS is a ist of compiler binary file paths to track.
+#
+function(llvm_defer_compiler_dependency_tracking)
+  set(COMPILERS ${ARGN})
+  if(NOT COMPILERS)
+    message(FATAL_ERROR "COMPILERS is required for 
llvm_defer_compiler_dependency_tracking")
+  endif()
+
+  # Store compilers as a directory property so the deferred call can read them.
+  set_property(DIRECTORY APPEND PROPERTY _LLVM_TRACK_COMPILERS "${COMPILERS}")
+  # Defer to triggers at the end of the current source dir.
+  cmake_language(DEFER CALL _llvm_track_compiler_dependency_dir_deferred)
+endfunction()
diff --git a/offload/CMakeLists.txt b/offload/CMakeLists.txt
index 472fee8e64156..4a9445823c210 100644
--- a/offload/CMakeLists.txt
+++ b/offload/CMakeLists.txt
@@ -54,6 +54,9 @@ list(INSERT CMAKE_MODULE_PATH 0
   "${LLVM_COMMON_CMAKE_UTILS}/Modules"
   )
 
+include(LLVMRuntimeCompilerDependency)
+llvm_defer_compiler_dependency_tracking("${CMAKE_C_COMPILER}" 
"${CMAKE_CXX_COMPILER}")
+
 set(OPENMP_TEST_C_COMPILER_default 
"${LLVM_TOOLS_BINARY_DIR}/clang${CMAKE_EXECUTABLE_SUFFIX}")
 set(OPENMP_TEST_CXX_COMPILER_default 
"${LLVM_TOOLS_BINARY_DIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}")
 set(OPENMP_TEST_Fortran_COMPILER_default 
"${LLVM_TOOLS_BINARY_DIR}/flang${CMAKE_EXECUTABLE_SUFFIX}")
diff --git a/openmp/CMakeLists.txt b/openmp/CMakeLists.txt
index 08e6c97d43c43..b5776ddcc6613 100644
--- a/openmp/CMakeLists.txt
+++ b/openmp/CMakeLists.txt
@@ -22,6 +22,10 @@ endif()
 
 # Must go below project(..)
 include(GNUInstallDirs)
+include(LLVMRuntimeCompilerDependency)
+
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_ASM_COMPILER}")
 
 # Usually <llvm-project>/runtimes/CMakeLists.txt sets LLVM_TREE_AVAILABLE and
 # we assume it is not available otherwise. The exception is that we are in an
diff --git a/orc-rt/CMakeLists.txt b/orc-rt/CMakeLists.txt
index 95b7b852138e7..e4ea79a84d33f 100644
--- a/orc-rt/CMakeLists.txt
+++ b/orc-rt/CMakeLists.txt
@@ -21,6 +21,10 @@ list(INSERT CMAKE_MODULE_PATH 0
   )
 
 include(GNUInstallDirs)
+include(LLVMRuntimeCompilerDependency)
+
+llvm_defer_compiler_dependency_tracking(
+  "${CMAKE_C_COMPILER}" "${CMAKE_CXX_COMPILER}" "${CMAKE_ASM_COMPILER}")
 
 
#===============================================================================
 # Setup CMake Options

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to