CMake Unix Makefiles generator has a parallel build race for conflict-set.o #47

Closed
opened 2026-06-21 11:19:24 +00:00 by weaselbot · 0 comments
Member

CMakeLists.txt uses an object library plus a custom command to pre-link ConflictSet.cpp into a single conflict-set.o with ld -r. The custom command depends on $<TARGET_OBJECTS:conflict-set-object>, but this does not establish a target-level dependency for the Unix Makefiles generator. Parallel builds with Make therefore fail to find the rule for the object file before the custom command runs.

File: CMakeLists.txt
Lines: 126–157 (conflict-set-object definition, add_custom_command for conflict-set.o, conflict-set and conflict-set-static libraries)

Expected behavior: cmake --build build -j4 --target conflict-set should work with the Unix Makefiles generator.

Actual behavior: A parallel Make build from a clean tree fails with:

gmake[3]: *** No rule to make target 'CMakeFiles/conflict-set-object.dir/ConflictSet.cpp.o', needed by 'conflict-set.o'.  Stop.

Reproduced with:

rm -rf build
cmake -B build -S .
cmake --build build -j4 --target conflict-set

The same build succeeds with -j1 and also succeeds with the Ninja generator (cmake -G Ninja ... && ninja -j4 conflict-set), because both serialize the object library before the consuming target through different dependency tracking.

Impact: Build scripts or users that default to the Make generator and enable parallelism will hit intermittent or deterministic failures. CI currently uses Ninja, so this is latent.

Suggested fix: Add explicit target dependencies so that conflict-set and conflict-set-static cannot build until conflict-set-object has produced its object files:

add_library(${PROJECT_NAME} SHARED ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-object)
...
add_library(${PROJECT_NAME}-static STATIC ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o)
add_dependencies(${PROJECT_NAME}-static ${PROJECT_NAME}-object)

I verified locally that adding these two add_dependencies lines allows cmake --build build -j4 --target conflict-set and cmake --build build -j4 --target driver to succeed from a clean tree.

`CMakeLists.txt` uses an object library plus a custom command to pre-link `ConflictSet.cpp` into a single `conflict-set.o` with `ld -r`. The custom command depends on `$<TARGET_OBJECTS:conflict-set-object>`, but this does not establish a target-level dependency for the Unix Makefiles generator. Parallel builds with Make therefore fail to find the rule for the object file before the custom command runs. File: `CMakeLists.txt` Lines: 126–157 (`conflict-set-object` definition, `add_custom_command` for `conflict-set.o`, `conflict-set` and `conflict-set-static` libraries) Expected behavior: `cmake --build build -j4 --target conflict-set` should work with the Unix Makefiles generator. Actual behavior: A parallel Make build from a clean tree fails with: ``` gmake[3]: *** No rule to make target 'CMakeFiles/conflict-set-object.dir/ConflictSet.cpp.o', needed by 'conflict-set.o'. Stop. ``` Reproduced with: ```sh rm -rf build cmake -B build -S . cmake --build build -j4 --target conflict-set ``` The same build succeeds with `-j1` and also succeeds with the Ninja generator (`cmake -G Ninja ... && ninja -j4 conflict-set`), because both serialize the object library before the consuming target through different dependency tracking. Impact: Build scripts or users that default to the Make generator and enable parallelism will hit intermittent or deterministic failures. CI currently uses Ninja, so this is latent. Suggested fix: Add explicit target dependencies so that `conflict-set` and `conflict-set-static` cannot build until `conflict-set-object` has produced its object files: ```cmake add_library(${PROJECT_NAME} SHARED ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o) add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-object) ... add_library(${PROJECT_NAME}-static STATIC ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.o) add_dependencies(${PROJECT_NAME}-static ${PROJECT_NAME}-object) ``` I verified locally that adding these two `add_dependencies` lines allows `cmake --build build -j4 --target conflict-set` and `cmake --build build -j4 --target driver` to succeed from a clean tree.
weaselbot was assigned by andrew 2026-06-21 15:02:19 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weaselab/conflict-set#47