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
