In 5.5, RunUAT.sh always triggers a full rebuild on macOS, even for brand new default C++ projects

Hello there, I’m encountering a new issue with RunUAT.sh on macOS 15 in UE 5.5 building with Xcode 16. It always triggers a full rebuild, even when I run it twice in a row without changing any source files or project files, and even for a brand new default C++ project. The issue does not happen with UE 5.4. There are a ton of great new features in 5.5 that we’re excited to explore, but needing to do full rebuilds every time we run RunUAT.sh is a deal-breaker for us.

To reproduce the issue, here is what I do:

  1. Create a new default C++ project. In my experiments, I have been creating a default third-person C++ project, but any of the starter project templates will trigger the same behavior.
  2. Build the project on the command-line as follows:

path/to/UE_5.5/Engine/Build/BatchFiles/RunUAT.sh BuildCookRun -project=path/to/MyProject/MyProject.uproject -target=MyProject -targetPlatform=Mac -clientConfig=Development -build

  1. Notice that it triggers 31 build actions.
  2. Re-run the exact same command. Notice that it triggers 11 build actions (corresponding to compiling all the cpp files, linking the executable, etc). On larger projects, it will always trigger K build actions where K is roughly equal to the number of source files in the project and plugins.

To verify that this isn’t an issue in UE 5.4, I repeat the experiment, but with a new default project created for UE 5.4, and using the UE 5.4 RunUAT.sh script. The first run triggers 21 build actions, but the second run triggers 0 build actions, which is what I expect since I haven’t changed any source or project files between runs. I expect UE 5.5 to do the same thing, but it doesn’t.

Is anyone else encountering this issue? Does anyone have a workaround? Is there a new command-line argument that I need to use to get the incremental build functionality back from UE 5.4?

I’m attaching my complete build logs to this post in case it’s helpful to anyone.

Cheers,
Mike

ue_55.txt (45.1 KB)
ue_54.txt (22.5 KB)

1 Like

Update: Good news. I figured out a workaround. I was combing through build logs for the working UE 5.4 case and the non-working UE 5.5 case. Specifically, I was looking at these logs:

/Users/miroberts/Library/Logs/Unreal Engine/LocalBuildLogs/UBA-MyProject1Editor-Mac-Development.txt
/Users/miroberts/Library/Logs/Unreal Engine/LocalBuildLogs/UBA-MyProject3Editor-Mac-Development.txt

Here is an excerpt from the working UE 5.4 log:

...
Compile module: WorldMetricsTest
Compile module: CsvMetrics
Compile module: RHICore
Compile module: MetalCPP
Compile module: MetalShaderConverter
Compile module: MetalRHI
Writing manifest to /Users/miroberts/Downloads/MyProject1/Intermediate/Build/Manifest-2-MyProject1-Mac-Development.xml
Targets are up to date
Deploying MyProject1Editor Mac Development...
Deploying now!
Deploying MyProject1 Mac Development...
Deploying now!
Total execution time: 4.32 seconds
WriteFileIfChanged() wrote 0 changed files of 65 requested writes.
...

Here is the corresponding excerpt from the non-working UE 5.5 log. Notice all of the SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action messages:

...
Compile module: WorldMetricsTest
Compile module: CsvMetrics
Compile module: NVAftermath
Compile module: RHICore
Compile module: MetalCPP
Compile module: MetalShaderConverter
Compile module: MetalRHI
Writing manifest to /Users/miroberts/Downloads/MyProject3/Intermediate/Build/Manifest-2-MyProject3-Mac-Development.xml
SharedPCH.Engine.Project.ValApi.Cpp20.h: Prerequisite /Users/miroberts/Downloads/MyProject3/Intermediate/Build/Mac/arm64/MyProject3/Development/Engine/SharedPCH.Engine.Project.ValApi.Cpp20.h.gch.rsp is newer than the last execution of the action: 11/16/2024 10:51:35 vs 11/14/2024 00:44:28
Executing PostBuildSync [/Users/miroberts/Downloads/MyProject3/Binaries/Mac/MyProject3]: Produced item "/Users/miroberts/Downloads/MyProject3/Binaries/Mac/MyProject3.app/Contents/PkgInfo" was produced by outdated attributes.
  New attributes: /Users/Shared/Epic_Games/UE_5.5/Engine/Binaries/ThirdParty/DotNet/8.0.300/mac-arm64/dotnet "/Users/Shared/Epic_Games/UE_5.5/Engine/Binaries/DotNET/UnrealBuildTool/UnrealBuildTool.dll" -Session="{78cbdb8b-3513-440e-a5c4-d94ab2b03178}" -Mode=ApplePostBuildSync -modernxcode -Input="/Users/miroberts/Downloads/MyProject3/Intermediate/Build/Mac/arm64/MyProject3/Development/PostBuildSync.dat" -XmlConfigCache="/Users/miroberts/Documents/Library/Application Support/Epic/UnrealEngine/XmlConfigCache-+Users+Shared+Epic_Games+UE_5.5.bin" -remoteini="" (ver 0)
MyProject3.cpp: Prerequisite SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action.
MyProject3: Prerequisite MyProject3.cpp is produced by outdated action.
MyProject3.init.gen.cpp: Prerequisite SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action.
MyProject3Character.cpp: Prerequisite SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action.
MyProject3Character.gen.cpp: Prerequisite SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action.
MyProject3GameMode.cpp: Prerequisite SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action.
MyProject3GameMode.gen.cpp: Prerequisite SharedPCH.Engine.Project.ValApi.Cpp20.h is produced by outdated action.
Updating version file: /Users/miroberts/Downloads/MyProject3/Intermediate/Build/Versions.xcconfig: Prerequisite MyProject3 is produced by outdated action.
MyProject3.target: Prerequisite MyProject3 is produced by outdated action.
Checking for live coding mutex: Global\LiveCoding_+Users+Shared+Epic_Games+UE_5.5+Engine+Binaries+Mac+UnrealEditor
Checking for live coding mutex: Global\LiveCoding_+Users+miroberts+Downloads+MyProject3+Binaries+Mac+MyProject3
Deleting outdated item: /Users/miroberts/Downloads/MyProject3/Binaries/Mac/MyProject3
Building MyProject3Editor and MyProject3...
Determining max actions to execute in parallel (16 physical cores, 16 logical cores)
  Executing up to 16 processes, one per physical core
Using Unreal Build Accelerator local executor to run 11 action(s)
  Storage capacity 40Gb
---- Starting trace ----
UbaSessionServer - Disable remote execution (remote sessions will finish current processes)
------ Building 11 action(s) started ------
** For MyProject3-Mac-Development **
[1/11] Compile [Apple] SharedPCH.Engine.Project.ValApi.Cpp20.h (UBA disabled)
[2/11] Compile [Apple] MyProject3GameMode.gen.cpp
[3/11] Compile [Apple] MyProject3Character.gen.cpp
[4/11] Compile [Apple] MyProject3GameMode.cpp
[5/11] Compile [Apple] MyProject3.cpp
[6/11] Compile [Apple] MyProject3Character.cpp
[7/11] Compile [Apple] MyProject3.init.gen.cpp
[8/11] Link [Apple] MyProject3 (UBA disabled)
[9/11] Updating version file: /Users/miroberts/Downloads/MyProject3/Intermediate/Build/Versions.xcconfig (UBA disabled)
[10/11] ApplePostBuildSync Executing PostBuildSync [/Users/miroberts/Downloads/MyProject3/Binaries/Mac/MyProject3] (UBA disabled)
...

All these SharedPCH.Engine.Project.ValApi.Cpp20.h messages made me suspect that the issue was being caused by a bug in Unreal’s precompiled header logic. So, as a sanity check, I set PCHUsage = PCHUsageMode.NoPCHs in my Build.cs file. This change restored the desired incremental build behavior in UE 5.5.

As you might expect, this change makes RunUAT.sh more strict about including what you use. It took me a while to add all of the missing includes that had crept into my project over time. In particular, for the plugins in my codebase, I needed to explicitly include <HAL/Platform.h> so Unreal would recognize the MYPLUGIN_API macros used throughout my plugins.

For me, the increased strictness imposed by RunUAT.sh after making this change is a feature, not a bug. I want Unreal to be strict about including what you use, and I don’t like how Unreal’s precompiled headers can obfuscate missing include directives throughout my code. As far as I’m concerned, if a source file is using the FHitResult type, it should always explicitly include <Engine/HitResult.h>, if for no other reason than to improve readability. So, even if Epic Games fixes the incremental build bug from my original post, I think I’m going to keep precompiled headers turned off.

1 Like