https://github.com/ceph/ceph/pull/73585

From 2e5697967906f0d931b5a0bb97bfa25b10e561fa Mon Sep 17 00:00:00 2001
From: "Z. Liu" <zhixu.liu@gmail.com>
Date: Fri, 6 Nov 2026 21:59:10 +0800
Subject: [PATCH] cmake: order src targets after legacy option header
 generation

The headers generated by src/common/options/y2c.py are included
indirectly through common/config.h and are required by many targets
throughout src.

Without an explicit build-order dependency, parallel builds may
compile sources before these headers have been generated. This can
result in incomplete ConfigValues definitions, as seen with
src/perfglue/heap_profiler.cc.

Instead of adding add_dependencies() to individual targets, create
an interface library and add it to the directory-level LINK_LIBRARIES
property in src/. This propagates its build dependency to targets
created in this directory and its subdirectories.

The interface library depends on a custom target in
src/common/options that represents the generated headers.
Using BUILD_INTERFACE keeps this helper out of installed target
interfaces without changing the actual linker command lines.

Verified by adding time.sleep(600) to y2c.py and building the full
tree from an empty build directory. No header-generation ordering
failures occurred.

However, with the Unix Makefiles generator, custom commands may be
duplicated across multiple targets' build.make files when their
outputs are consumed by independent targets. Under parallel builds,
separate make processes can execute the same command concurrently,
causing them to overwrite the generated files and potentially leave
them truncated or incomplete.

This is particularly problematic for the legacy option headers,
which are generated by y2c.py and consumed by multiple targets.
Ninja handles this differently by maintaining a single global
build graph, so the same generation rule is executed only once.

Signed-off-by: Z. Liu <zhixu.liu@gmail.com>

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 46226c6bbe8..c23cb48f05c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -590,6 +590,29 @@ if(WITH_JAEGER)
 endif()
 
 CHECK_C_COMPILER_FLAG("-fvar-tracking-assignments" HAS_VTA)
+
+# The *_legacy_options.h headers generated by src/common/options/y2c.py
+# are included indirectly by a large part of the source tree:
+# common/config.h includes common/options/legacy_config_opts.h, which
+# in turn includes these generated headers.
+#
+# Without an explicit build-order dependency, parallel builds may start
+# compiling sources before the headers have been generated. One example
+# is src/perfglue/heap_profiler.cc, which may then see an incomplete
+# ConfigValues definition.
+#
+# Propagate the dependency to all targets in this directory tree through
+# the directory-level LINK_LIBRARIES property, rather than adding
+# add_dependencies() to individual targets.
+#
+# The interface library provides a build-order dependency without adding
+# anything to the actual link command. BUILD_INTERFACE also keeps this
+# helper out of the exported link interfaces of installed targets.
+add_library(ceph-legacy-option-headers INTERFACE)
+add_dependencies(ceph-legacy-option-headers ceph-legacy-option-header-files)
+set_property(DIRECTORY APPEND PROPERTY LINK_LIBRARIES
+  "$<BUILD_INTERFACE:ceph-legacy-option-headers>")
+
 add_subdirectory(auth)
 add_subdirectory(common)
 add_subdirectory(crush)
diff --git a/src/common/options/CMakeLists.txt b/src/common/options/CMakeLists.txt
index 916f55dcfbd..8225dc0d900 100644
--- a/src/common/options/CMakeLists.txt
+++ b/src/common/options/CMakeLists.txt
@@ -111,6 +111,11 @@ target_sources(legacy-option-headers
   PRIVATE
     ${legacy_options_headers})
 
+# Expose the generated headers through a custom target so that targets
+# in parent directories can depend on their generation.
+add_custom_target(ceph-legacy-option-header-files
+  DEPENDS ${legacy_options_headers})
+
 include(AddCephTest)
 add_ceph_test(validate-options
   ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/validate-options.py ${options_yamls})
-- 
2.49.1

