Summary
On Mac, every UnrealBuildTool build of a GAME target re-runs ALL its compile actions (shared PCHs, every unity file, then the link), even with no source change and right after a successful build. For our project that is 26 actions and about 25 s every time. Editor targets are unaffected: a no-change editor build reports “Target is up to date”.
Cause: two writers in the same build disagree about the contents of the target’s shared-PCH response files, Intermediate/Build/Mac/arm64/TARGET/Development/MODULE/SharedPCH.*.gch.rsp (Core, CoreUObject, Slate, Engine):
- The main build’s makefile generation writes them WITHOUT include paths like -I"../Intermediate/Build/Mac/UnrealGame/Inc/Core/UHT" (in the installed engine those directories do not exist, apart from CoreUObject’s).
- The [ApplePostBuildSync] action runs a child UBT that regenerates the run-only Xcode project (AppleToolChain.GenerateRunOnlyXcodeProject → GenerateProjectFiles -DeployOnly …). That pass rewrites the SAME .rsp files WITH those UHT include paths, after the makefile was written.
- On the next build those files are internal dependencies newer than the makefile, so it is invalidated (“Invalidating makefile for TARGET (SharedPCH.CoreUObject.Cpp20.h.gch.rsp modified)”). Regeneration writes the version from step 1 back, saving .rsp.old because “contents have changed”. Each shared-PCH action then sees a prerequisite .rsp newer than its last execution, and everything downstream rebuilds. Step 2 flips the files back again at the end, so the cycle never settles.
Observed by polling SharedPCH.CoreUObject.Cpp20.h.gch.rsp during a build: 3245 → 2958 bytes at makefile time, 2958 → 3245 bytes while the -Mode=ApplePostBuildSync child was running.
Suggested fix: the project-generation pass run by PostBuildSync should not write build response files, or should compute the same include set as the build.
What Type of Bug are you experiencing?
Foundation (C++ Tools, Profiling, & Pipeline)
Steps to Reproduce
- Installed UE 5.8.3 on a Mac. Any C++ project with a Game target.
- Build the Game target twice with no changes: Engine/Build/BatchFiles/Mac/Build.sh PROJECT Mac Development PATH_TO/PROJECT.uproject
- The second build runs every compile action again (“Using Unreal Build Accelerator local executor to run N action(s)”, same N as a full build).
- With -VeryVerbose, UBT’s Log.txt shows the makefile invalidated for “SharedPCH.CoreUObject.Cpp20.h.gch.rsp modified”, “Updating …SharedPCH.*.gch.rsp: contents have changed”, and “Prerequisite …SharedPCH.Engine…gch.rsp is newer than the last execution of the action”.
- diff the SharedPCH.CoreUObject.Cpp20.h.gch.rsp against its .rsp.old: the only difference is the -I"../Intermediate/Build/Mac/UnrealGame/Inc/MODULE/UHT" lines.
Expected Result
The second, no-change build reports “Target is up to date” (or runs only the PostBuildSync/metadata steps), as the Editor target does.
Observed Result
Every Game-target build recompiles everything. On Mac that also means every Game-target build re-links and re-finalizes the .app. Tested on UE 5.8.3 (launcher build), macOS 27.0.1, Xcode 27.0, Apple Silicon. The same build was observed to recompile fully before a local workaround we carry for an unrelated finalize failure, so that workaround is not the cause: [UE 5.8.3][Build] macOS 27: every Mac game-target build fails at "Failed to finalize the .app with Xcode" because UBA starts xcodebuild with stdin closed
Affects Versions
5.8
Platform(s)
Mac
Additional Notes
Separate minor issue found alongside (reported separately): every build also logs “Invalidating makefile (ispc deleted)” because ISPCToolChain.GetExternalDependencies adds Engine/Source/ThirdParty/Intel/ISPC/bin/Mac/ispc unconditionally and the installed engine does not ship it. That one only costs makefile regeneration and is not what forces these recompiles.