3f8ebd8631
The unique-temp-name fix was treating symptoms. The actual defect is structural: run_parallel_cook documents the invariant 'each recipe builds in its own target/stage/sysroot' and that invariant is false. dep_levels() keys on the package NAME, so a recipe's optional-package variants -- llvm-native, llvm-native.dev, llvm-native.runtime -- are distinct units with no dependency between them. They therefore land in the same level and cook concurrently while sharing one target/<triple>/ directory, because build/, sysroot/ and the stage* dirs are all derived from the recipe directory, not the package name. create_dir_clean() on the shared build/ then wipes a sibling's tree mid-compile: ninja: error: failed recompaction: No such file or directory which is the error the earlier parallel builds kept producing and which unique temp names could never have fixed -- build/ is a real, shared, destructively re-created directory, not a staging path. It is also why llvm-native cooks clean in isolation but failed in every parallel build, and why that failure was misread as a porting gap serious enough to exclude the package from the config. Make the recipe DIRECTORY the unit of mutual exclusion. Distinct recipes still cook fully in parallel; only siblings serialise, and that costs almost nothing because one cook already populates every stage dir for the recipe -- the siblings that follow find their work done and return cached. It also stops LLVM being built three times over. Residual, not addressed here: recipes joined by [source] same_as (e.g. llvm-native -> llvm21) share a source tree. That is read-only during cook, but a concurrent fetch/patch of the shared source would be a separate race.