From bae6a2a76b632fa5fa4f103bb7aaff067c19c949 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Sat, 21 Mar 2026 07:33:21 +0800 Subject: [PATCH] [Runtimes] Fix Unix Makefiles race between runtimes-build and EXTRA_TARGETS (#187634) In our downstream we have a non-runtime target depending on libclc EXTRA_TARGET and then observe a race condition in parallel build: both runtimes-build (full build, no lock) and libclc EXTRA_TARGET (triggered by non-runtime target, FileLock) build concurrently, leading to corrupt libclc library. This exposes an limitation in ExternalProject EXTRA_TARGET design: EXTRA_TARGETS in llvm_ExternalProject_Add only depend on ${name}-configure, not ${name}-build. This makes EXTRA_TARGETS unsafe as dependencies of a non-runtime target.. Fix: Add a locked BUILD_COMMAND to ExternalProject_Add for Unix Makefiles generator, using the same cmake.lock as EXTRA_TARGETS. This serializes runtimes-build with all EXTRA_TARGETS under one lock. With this PR, a non-runtime target can depend on a specific EXTRA_TARGET, rather than needing to depend on the umbrella runtimes target. This is an improvement. A non-runtime target can start as soon as its dependent specific EXTRA_TARGET build finishes, without waiting for other runtimes. In addition, the non-runtime target may only need a specific EXTRA_TARGET and minimal dependency on it is accurate. Assisted-by: Claude Sonnet 4.6 --------- Co-authored-by: Petr Hosek --- .../cmake/modules/LLVMExternalProjectUtils.cmake | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake index 975798a8c263..61f3bc83a83a 100644 --- a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake +++ b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake @@ -9,7 +9,12 @@ function(llvm_ExternalProject_BuildCmd out_var target bin_dir stamp_dir) endif() if (CMAKE_GENERATOR MATCHES "Make") # Use special command for Makefiles to support parallelism. - string(JOIN "@" make_cmd "$(MAKE)" "-C" "${bin_dir}" "${target}") + # Handle empty target (full build, no target argument). + if(target) + string(JOIN "@" make_cmd "$(MAKE)" "-C" "${bin_dir}" "${target}") + else() + string(JOIN "@" make_cmd "$(MAKE)" "-C" "${bin_dir}") + endif() set(file_lock_script "${LLVM_CMAKE_DIR}/FileLock.cmake") set(${out_var} ${CMAKE_COMMAND} "-DLOCK_FILE_PATH=${stamp_dir}/cmake.lock" "-DCOMMAND=${make_cmd}" @@ -378,6 +383,14 @@ function(llvm_ExternalProject_Add name source_dir) set(verbose -DCMAKE_VERBOSE_MAKEFILE=ON) endif() + if(CMAKE_GENERATOR MATCHES "Make") + # Use the same FileLock for Unix Makefiles to serialize the main build with + # EXTRA_TARGETS. This prevents concurrent make invocations from corrupting + # shared artifacts in BINARY_DIR. + llvm_ExternalProject_BuildCmd(build_cmd "" ${BINARY_DIR} ${STAMP_DIR}) + set(build_command_arg BUILD_COMMAND ${build_cmd}) + endif() + ExternalProject_Add(${name} DEPENDS ${ARG_DEPENDS} llvm-config ${name}-clobber @@ -408,6 +421,7 @@ function(llvm_ExternalProject_Add name source_dir) ${cmake_args} ${PASSTHROUGH_VARIABLES} CMAKE_CACHE_DEFAULT_ARGS ${CMAKE_CACHE_DEFAULT_ARGS} + ${build_command_arg} INSTALL_COMMAND "" STEP_TARGETS configure build BUILD_ALWAYS 1