( new string[] { "Unset", "Reviewed", "New", "Coder", "EngineQA", "GameQA" } ); } }
@@ -101,6 +107,7 @@ namespace Tools.CrashReporter.CrashReportWebSite.Models
DateTime ToDate = DateTime.Today.ToUniversalTime();
BranchNames = CrashRepository.GetBranchesAsListItems();
VersionNames = CrashRepository.GetVersionsAsListItems();
+ PlatformNames = CrashRepository.GetPlatformsAsListItems();
DateFrom = (long)( FromDate - Epoch ).TotalMilliseconds;
DateTo = (long)( ToDate - Epoch ).TotalMilliseconds;
CrashType = "CrashesAsserts";
diff --git a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Models/FormHelper.cs b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Models/FormHelper.cs
index ca343a144a07..ad5e43e212bf 100644
--- a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Models/FormHelper.cs
+++ b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Models/FormHelper.cs
@@ -68,6 +68,9 @@ namespace Tools.CrashReporter.CrashReportWebSite.Models
/// The version name to filter by.
public string VersionName = "";
+ /// The platform name to filter by.
+ public string PlatformName = "";
+
/// The game to filter by.
public string GameName = "";
@@ -184,6 +187,7 @@ namespace Tools.CrashReporter.CrashReportWebSite.Models
GetFormParameter( Request, Form, "UserGroup", UserGroup, out UserGroup );
GetFormParameter( Request, Form, "BranchName", BranchName, out BranchName );
GetFormParameter( Request, Form, "VersionName", VersionName, out VersionName );
+ GetFormParameter( Request, Form, "PlatformName", PlatformName, out PlatformName );
GetFormParameter( Request, Form, "GameName", GameName, out GameName );
diff --git a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Crashes/Index.aspx b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Crashes/Index.aspx
index 3c8c4fad0b67..59cc450a6669 100644
--- a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Crashes/Index.aspx
+++ b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Crashes/Index.aspx
@@ -217,6 +217,13 @@
|
|
+
+
+ Filter by Platform
+ |
+
+ <%=Html.DropDownListFor( m=>m.PlatformName, Model.PlatformNames )%>
+ |
@@ -272,6 +279,7 @@
DateTo = Model.DateTo,
BranchName = Model.BranchName,
VersionName = Model.VersionName,
+ PlatformName = Model.PlatformName,
GameName = Model.GameName,
RealUserName = Model.RealUserName
}
@@ -297,6 +305,7 @@
DateTo = Model.DateTo,
BranchName = Model.BranchName,
VersionName = Model.VersionName,
+ PlatformName = Model.PlatformName,
GameName = Model.GameName,
RealUserName = Model.RealUserName
}
@@ -328,6 +337,7 @@
DateTo = Model.DateTo,
BranchName = Model.BranchName,
VersionName = Model.VersionName,
+ PlatformName = Model.PlatformName,
GameName = Model.GameName,
RealUserName = Model.RealUserName
}
diff --git a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Helpers/UrlHelperExtension.cs b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Helpers/UrlHelperExtension.cs
index 2f6588a47d80..e36bfbd38acc 100644
--- a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Helpers/UrlHelperExtension.cs
+++ b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Helpers/UrlHelperExtension.cs
@@ -44,6 +44,7 @@ namespace Tools.CrashReporter.CrashReportWebSite.Views.Helpers
DateTo = Model.DateTo,
BranchName = Model.BranchName,
VersionName = Model.VersionName,
+ PlatformName = Model.PlatformName,
GameName = Model.GameName
} );
@@ -100,6 +101,7 @@ namespace Tools.CrashReporter.CrashReportWebSite.Views.Helpers
DateTo = Model.DateTo,
BranchName = Model.BranchName,
VersionName = Model.VersionName,
+ PlatformName = Model.PlatformName,
GameName = Model.GameName
} );
@@ -139,6 +141,7 @@ namespace Tools.CrashReporter.CrashReportWebSite.Views.Helpers
DateTo = Model.DateTo,
BranchName = Model.BranchName,
VersionName = Model.VersionName,
+ PlatformName = Model.PlatformName,
GameName = Model.GameName
} );
diff --git a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Home/Index.aspx b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Home/Index.aspx
index 825c3db2294b..ad8af2347058 100644
--- a/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Home/Index.aspx
+++ b/Engine/Source/Programs/CrashReporter/CrashReportWebSite/Views/Home/Index.aspx
@@ -209,6 +209,13 @@
|
|
+
+
+ Filter by Platform
+ |
+
+ <%=Html.DropDownListFor( m=>m.PlatformName, Model.PlatformNames )%>
+ |
diff --git a/Engine/Source/Programs/UnrealBuildTool/Configuration/BuildConfiguration.cs b/Engine/Source/Programs/UnrealBuildTool/Configuration/BuildConfiguration.cs
index a794e904b477..63911c73de63 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Configuration/BuildConfiguration.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Configuration/BuildConfiguration.cs
@@ -448,6 +448,13 @@ namespace UnrealBuildTool
[XmlConfig]
public static bool bUseUBTMakefiles;
+ ///
+ /// Enables support for fast UHT parsing by caching results of previous UHT runs. If a module or UnrealHeaderTool.manifest
+ /// gets changed, all modules up to first changed one get loaded from makefile and the rest is parsed regularly.
+ ///
+ [XmlConfig]
+ public static bool bUseUHTMakefiles;
+
///
/// Whether DMUCS/Distcc may be used.
///
@@ -647,6 +654,10 @@ namespace UnrealBuildTool
// NOTE: This feature is new and has a number of known issues (search the code for '@todo ubtmake')
bUseUBTMakefiles = true;
+ // Enables support for caching results of previous UHT runs to speed up iterative development.
+ // This feature is new and can have issues that weren't discovered in isolated testing so disabling by default.
+ bUseUHTMakefiles = false;
+
// Distcc requires some setup - so by default disable it so we don't break local or remote building
bAllowDistcc = false;
bAllowDistccLocalFallback = true;
diff --git a/Engine/Source/Programs/UnrealBuildTool/System/ExternalExecution.cs b/Engine/Source/Programs/UnrealBuildTool/System/ExternalExecution.cs
index 0750e46b061b..25f25fd3ff2d 100644
--- a/Engine/Source/Programs/UnrealBuildTool/System/ExternalExecution.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/System/ExternalExecution.cs
@@ -648,7 +648,8 @@ namespace UnrealBuildTool
}
}
-
+ // Set to true if makefiles need invalidating
+ static public bool bInvalidateUHTMakefile = false;
///
/// Builds and runs the header tool and touches the header directories.
@@ -774,6 +775,11 @@ namespace UnrealBuildTool
CmdLine += " -FailIfGeneratedCodeChanges";
}
+ if (!bInvalidateUHTMakefile && BuildConfiguration.bUseUHTMakefiles)
+ {
+ CmdLine += " -UseMakefiles";
+ }
+
Log.TraceInformation(" Running UnrealHeaderTool {0}", CmdLine);
Stopwatch s = new Stopwatch();
diff --git a/Engine/Source/Programs/UnrealBuildTool/System/ProjectFileGenerator.cs b/Engine/Source/Programs/UnrealBuildTool/System/ProjectFileGenerator.cs
index 19e6b44d24fe..24042697cc10 100644
--- a/Engine/Source/Programs/UnrealBuildTool/System/ProjectFileGenerator.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/System/ProjectFileGenerator.cs
@@ -1788,7 +1788,12 @@ namespace UnrealBuildTool
TargetRules = TargetRulesObject,
TargetFilePath = TargetFilePath,
ProjectFilePath = ProjectFilePath
- };
+ };
+
+ if (TargetName == "UnrealCodeAnalyzer")
+ {
+ ProjectFile.ShouldBuildByDefaultForSolutionTargets = false;
+ }
if (TargetName == "ShaderCompileWorker") // @todo projectfiles: Ideally, the target rules file should set this
{
diff --git a/Engine/Source/Programs/UnrealBuildTool/System/UnrealBuildTool.cs b/Engine/Source/Programs/UnrealBuildTool/System/UnrealBuildTool.cs
index 4ff09d75b66a..d60275669511 100644
--- a/Engine/Source/Programs/UnrealBuildTool/System/UnrealBuildTool.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/System/UnrealBuildTool.cs
@@ -766,6 +766,10 @@ namespace UnrealBuildTool
{
BuildConfiguration.bUseUBTMakefiles = false;
}
+ else if (LowercaseArg == "-uhtmakefiles")
+ {
+ BuildConfiguration.bUseUHTMakefiles = true;
+ }
else if (LowercaseArg == "-nosimplygon")
{
UEBuildConfiguration.bCompileSimplygon = false;
@@ -1725,6 +1729,9 @@ namespace UnrealBuildTool
TargetDescs[0].TargetName,
TargetDescs.Count > 1 ? (" (and " + (TargetDescs.Count - 1).ToString() + " more)") : "",
ReasonNotLoaded);
+
+ // Invalidate UHT makefiles too
+ ExternalExecution.bInvalidateUHTMakefile = true;
}
}
@@ -2132,17 +2139,14 @@ namespace UnrealBuildTool
}
var Processes = BuildHostPlatform.Current.GetProcesses();
- var RootDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Modules.First().FullyQualifiedName), "..", "..", "..");
- var EditorRunsDir = Path.Combine(RootDir, "Engine", "Intermediate", "EditorRuns");
+ var EditorRunsDir = Path.Combine(UnrealBuildTool.EngineDirectory.FullName, "Intermediate", "EditorRuns");
- if (!Directory.Exists(EditorRunsDir))
- {
- return false;
- }
+ if (!Directory.Exists(EditorRunsDir))
+ {
+ return false;
+ }
- var EditorRunsFiles = new DirectoryInfo(EditorRunsDir).GetFiles();
-
- var NormalizedProcFileName = Path.GetFullPath(EditorProcessFilenames[0].ToString()).TrimEnd(Path.DirectorySeparatorChar).TrimEnd(Path.AltDirectorySeparatorChar).ToLowerInvariant();
+ var EditorRunsFiles = new DirectoryInfo(EditorRunsDir).GetFiles();
foreach(var File in EditorRunsFiles)
{
@@ -2155,13 +2159,12 @@ namespace UnrealBuildTool
continue;
}
- // Don't break here to allow clean-up of other stale files.
- if (!bIsRunning)
- {
- // Otherwise check if the path matches.
- var FileProcName = Path.GetFullPath(Proc.Filename).TrimEnd(Path.DirectorySeparatorChar).TrimEnd(Path.AltDirectorySeparatorChar).ToLowerInvariant();
- bIsRunning = NormalizedProcFileName == FileProcName;
- }
+ // Don't break here to allow clean-up of other stale files.
+ if (!bIsRunning)
+ {
+ // Otherwise check if the path matches.
+ bIsRunning = new FileReference(Proc.Filename).CanonicalName == EditorProcessFilenames[0].CanonicalName;
+ }
}
}
return bIsRunning;
@@ -2440,6 +2443,14 @@ namespace UnrealBuildTool
return null;
}
+ // Check to see if any BuildConfiguration files have changed since the last build
+ if (XmlConfigLoader.NewestXmlTimestamp > UBTMakefileInfo.LastWriteTime)
+ {
+ Log.TraceVerbose("Makefile is older than BuildConfiguration.xml, ignoring it" );
+ ReasonNotLoaded = "BuildConfiguration.xml is newer";
+ return null;
+ }
+
UBTMakefile LoadedUBTMakefile = null;
try
diff --git a/Engine/Source/Programs/UnrealBuildTool/Utilities/XmlConfigLoader.cs b/Engine/Source/Programs/UnrealBuildTool/Utilities/XmlConfigLoader.cs
index 7b33b9d28df9..7648aeb353ee 100644
--- a/Engine/Source/Programs/UnrealBuildTool/Utilities/XmlConfigLoader.cs
+++ b/Engine/Source/Programs/UnrealBuildTool/Utilities/XmlConfigLoader.cs
@@ -392,6 +392,9 @@ namespace UnrealBuildTool
// Tells if config file exists in this location.
public bool bExists { get; protected set; }
+ // Timestamp of file.
+ public DateTime Timestamp { get; protected set; }
+
public XmlConfigLocation(string[] FSLocations, string IDEFolderName, bool bCreateIfDoesNotExist = false)
{
bool bExists;
@@ -400,6 +403,17 @@ namespace UnrealBuildTool
this.IDEFolderName = IDEFolderName;
this.bCreateIfDoesNotExist = bCreateIfDoesNotExist;
this.bExists = bExists;
+ if (bExists)
+ {
+ try
+ {
+ Timestamp = new FileInfo(FSLocation).LastWriteTime;
+ }
+ catch (Exception)
+ {
+ Timestamp = DateTime.MaxValue;
+ }
+ }
}
public XmlConfigLocation(string FSLocation, string IDEFolderName, bool bCreateIfDoesNotExist = false)
@@ -494,7 +508,7 @@ namespace UnrealBuildTool
* a. UE4/Engine/Programs/UnrealBuildTool
* b. UE4/Engine/Programs/NotForLicensees/UnrealBuildTool
* c. UE4/Engine/Saved/UnrealBuildTool
- * d. /Unreal Engine/UnrealBuildTool -- the location is
+ * d. /Unreal Engine/UnrealBuildTool -- the location is
* chosen by existence and if both exist most recently used.
*
* The UBT is looking for it in all four places in the given order and
@@ -516,6 +530,14 @@ namespace UnrealBuildTool
};
}
+ public static DateTime NewestXmlTimestamp
+ {
+ get
+ {
+ return ConfigLocationHierarchy.Max(x => x.Timestamp);
+ }
+ }
+
///
/// Loads BuildConfiguration from XML into memory.
///
diff --git a/Engine/Source/Programs/UnrealFrontend/Private/Commands/StatsConvertCommand.cpp b/Engine/Source/Programs/UnrealFrontend/Private/Commands/StatsConvertCommand.cpp
index 26f0d1cd3a0a..9e4867cd124a 100644
--- a/Engine/Source/Programs/UnrealFrontend/Private/Commands/StatsConvertCommand.cpp
+++ b/Engine/Source/Programs/UnrealFrontend/Private/Commands/StatsConvertCommand.cpp
@@ -117,57 +117,25 @@ void FStatsConvertCommand::ReadAndConvertStatMessages( FArchive& Reader, FArchiv
const bool bIsFinalized = Stream.Header.IsFinalized();
float DataLoadingProgress = 0.0f;
- if( bHasCompressedData )
+ // Sanity checks.
+ check( bHasCompressedData );
+
+ while( Reader.Tell() < Reader.TotalSize() )
{
- while( Reader.Tell() < Reader.TotalSize() )
+ // Read the compressed data.
+ FCompressedStatsData UncompressedData( SrcData, DestData );
+ Reader << UncompressedData;
+ if( UncompressedData.HasReachedEndOfCompressedData() )
{
- // Read the compressed data.
- FCompressedStatsData UncompressedData( SrcData, DestData );
- Reader << UncompressedData;
- if( UncompressedData.HasReachedEndOfCompressedData() )
- {
- return;
- }
-
- FMemoryReader MemoryReader( DestData, true );
-
- while( MemoryReader.Tell() < MemoryReader.TotalSize() )
- {
- // read the message
- FStatMessage Message( Stream.ReadMessage( MemoryReader, bIsFinalized ) );
- ReadMessages++;
- if( ReadMessages % 32768 == 0 )
- {
- UE_LOG( LogStats, Log, TEXT( "StatsConvertCommand progress: %.1f%%" ), DataLoadingProgress );
- }
-
- if( Message.NameAndInfo.GetShortName() != TEXT( "Unknown FName" ) )
- {
- if( Message.NameAndInfo.GetField() == EStatOperation::AdvanceFrameEventGameThread && ReadMessages > 2 )
- {
- new (Messages) FStatMessage( Message );
- ThreadState.AddMessages( Messages );
- Messages.Reset();
-
- CollectAndWriteStatsValues( Writer );
- DataLoadingProgress = (double)Reader.Tell() / (double)Reader.TotalSize() * 100.0f;
- }
-
- new (Messages) FStatMessage( Message );
- }
- else
- {
- break;
- }
- }
+ return;
}
- }
- else
- {
- while( Reader.Tell() < Reader.TotalSize() )
+
+ FMemoryReader MemoryReader( DestData, true );
+
+ while( MemoryReader.Tell() < MemoryReader.TotalSize() )
{
// read the message
- FStatMessage Message( Stream.ReadMessage( Reader, bIsFinalized ) );
+ FStatMessage Message( Stream.ReadMessage( MemoryReader, bIsFinalized ) );
ReadMessages++;
if( ReadMessages % 32768 == 0 )
{
@@ -176,13 +144,7 @@ void FStatsConvertCommand::ReadAndConvertStatMessages( FArchive& Reader, FArchiv
if( Message.NameAndInfo.GetShortName() != TEXT( "Unknown FName" ) )
{
- if( Message.NameAndInfo.GetField() == EStatOperation::SpecialMessageMarker )
- {
- // Simply break the loop.
- // The profiler supports more advanced handling of this message.
- return;
- }
- else if( Message.NameAndInfo.GetField() == EStatOperation::AdvanceFrameEventGameThread && ReadMessages > 2 )
+ if( Message.NameAndInfo.GetField() == EStatOperation::AdvanceFrameEventGameThread && ReadMessages > 2 )
{
new (Messages) FStatMessage( Message );
ThreadState.AddMessages( Messages );
@@ -218,7 +180,7 @@ void FStatsConvertCommand::CollectAndWriteStatsValues( FArchive& Writer )
FStatMessage const& Meta = Stats[Index];
//UE_LOG(LogTemp, Display, TEXT("Stat: %s"), *Meta.NameAndInfo.GetShortName().ToString());
- if (Meta.NameAndInfo.GetShortName() == TEXT("STAT_SecondsPerCycle"))
+ if (Meta.NameAndInfo.GetShortName() == FStatConstants::NAME_SecondsPerCycle)
{
// SecondsPerCycle may vary over time, so we update it here
MillisecondsPerCycle = Meta.GetValue_double() * 1000.0f;
diff --git a/Engine/Source/Programs/UnrealFrontend/Private/UnrealFrontendMain.cpp b/Engine/Source/Programs/UnrealFrontend/Private/UnrealFrontendMain.cpp
index 6ba00a64fffb..32ee58e1e893 100644
--- a/Engine/Source/Programs/UnrealFrontend/Private/UnrealFrontendMain.cpp
+++ b/Engine/Source/Programs/UnrealFrontend/Private/UnrealFrontendMain.cpp
@@ -21,6 +21,9 @@ IMPLEMENT_APPLICATION(UnrealFrontend, "UnrealFrontend");
*/
int32 UnrealFrontendMain( const TCHAR* CommandLine )
{
+ // Override the stack size for the thread pool.
+ FQueuedThreadPool::OverrideStackSize = 256 * 1024;
+
FCommandLine::Set(CommandLine);
FString Command;
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ClassDeclarationMetaData.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/ClassDeclarationMetaData.cpp
index 486571fb7b60..cc42cb1be196 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ClassDeclarationMetaData.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ClassDeclarationMetaData.cpp
@@ -406,7 +406,7 @@ void FClassDeclarationMetaData::MergeAndValidateClassFlags(const FString& Declar
FError::Throwf(TEXT("'abstract': NoExport class missing abstract keyword from class declaration (must change C++ version first)"));
Class->ClassFlags |= CLASS_Abstract;
}
- else if (Class->HasAnyFlags(RF_Native))
+ else if (Class->IsNative())
{
FError::Throwf(TEXT("'abstract': missing abstract keyword from class declaration - class will no longer be exported as abstract"));
}
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.cpp
index 642ec28cef1b..6368a5053599 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.cpp
@@ -5,6 +5,7 @@
#include "ClassMaps.h"
#include "UnrealSourceFile.h"
#include "UnrealTypeDefinitionInfo.h"
+#include "UHTMakefile/UHTMakefile.h"
TMap > GUnrealSourceFilesMap;
TMap > GTypeDefinitionInfoMap;
@@ -19,10 +20,13 @@ TMap GGeneratedCodeCRCs;
TMap GEnumUnderlyingTypes;
TMap > GClassDeclarations;
-TSharedRef AddTypeDefinition(FUnrealSourceFile& SourceFile, UField* Field, int32 Line)
+TSharedRef AddTypeDefinition(FUHTMakefile& UHTMakefile, FUnrealSourceFile* SourceFile, UField* Field, int32 Line)
{
- TSharedRef DefinitionInfo = MakeShareable(new FUnrealTypeDefinitionInfo(SourceFile, Line));
+ FUnrealTypeDefinitionInfo* UnrealTypeDefinitionInfo = new FUnrealTypeDefinitionInfo(*SourceFile, Line);
+ UHTMakefile.AddUnrealTypeDefinitionInfo(SourceFile, UnrealTypeDefinitionInfo);
+ TSharedRef DefinitionInfo = MakeShareable(UnrealTypeDefinitionInfo);
+ UHTMakefile.AddTypeDefinitionInfoMapEntry(SourceFile, Field, UnrealTypeDefinitionInfo);
GTypeDefinitionInfoMap.Add(Field, DefinitionInfo);
return DefinitionInfo;
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.h b/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.h
index 84b9c951602e..024269337006 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ClassMaps.h
@@ -39,13 +39,31 @@ enum EAccessSpecifier
ACCESS_Num,
};
+inline FArchive& operator<<(FArchive& Ar, EAccessSpecifier& ObjectType)
+{
+ if (Ar.IsLoading())
+ {
+ int32 Value;
+ Ar << Value;
+ ObjectType = EAccessSpecifier(Value);
+ }
+ else if (Ar.IsSaving())
+ {
+ int32 Value = (int32)ObjectType;
+ Ar << Value;
+ }
+
+ return Ar;
+}
+
/**
* Add type definition info to global map.
*
+ * @param UHTMakefile Makefile to which data is saved.
* @param SourceFile SourceFile in which type was defined.
* @param Field Defined type.
* @param Line Line on which the type was defined.
*
* @returns Type definition info.
*/
-TSharedRef AddTypeDefinition(FUnrealSourceFile& SourceFile, UField* Field, int32 Line);
\ No newline at end of file
+TSharedRef AddTypeDefinition(FUHTMakefile& UHTMakefile, FUnrealSourceFile* SourceFile, UField* Field, int32 Line);
\ No newline at end of file
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.cpp
index 0d2353720a30..63a577b700b7 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.cpp
@@ -180,7 +180,7 @@ FClass* FClasses::FindScriptClass(const FString& InClassName, FString& OutErrorM
return NULL;
}
-TArray FClasses::GetClassesInPackage(UPackage* InPackage) const
+TArray FClasses::GetClassesInPackage(const UPackage* InPackage) const
{
TArray Result;
Result.Add(UObjectClass);
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.h b/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.h
index 3606ad579dd9..c242edf59de1 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/Classes.h
@@ -71,7 +71,7 @@ public:
* @param InPackage The package to return the classes from.
* @return The classes in the specified package.
*/
- TArray GetClassesInPackage(UPackage* InPackage = ANY_PACKAGE) const;
+ TArray GetClassesInPackage(const UPackage* InPackage = ANY_PACKAGE) const;
// Anything in here should eventually be removed when this class encapsulates its own data structure, rather than being 'poked' by the outside
#if WIP_UHT_REFACTOR
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/CodeGenerator.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/CodeGenerator.cpp
index 36974c108570..16e1e6b84adc 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/CodeGenerator.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/CodeGenerator.cpp
@@ -12,6 +12,8 @@
#include "StringUtils.h"
#include "IPluginManager.h"
#include "Runtime/Core/Public/Features/IModularFeatures.h"
+#include "UHTMakefile/UHTMakefile.h"
+#include "ScopeExit.h"
/////////////////////////////////////////////////////
// Globals
@@ -27,7 +29,7 @@ static bool bVerifyContents = false;
static const bool bMultiLineUFUNCTION = true;
static const bool bMultiLineUPROPERTY = true;
-static TSharedRef PerformInitialParseOnHeader(UPackage* InParent, const FString& FileName, EObjectFlags Flags, const TCHAR* Buffer);
+static TSharedRef PerformInitialParseOnHeader(UPackage* InParent, const FString& FileName, EObjectFlags Flags, const TCHAR* Buffer, FUHTMakefile& UHTMakefile);
FCompilerMetadataManager GScriptHelper;
@@ -52,38 +54,37 @@ const TCHAR* FindIdentifierExactMatch(const TCHAR* StringBegin, const TCHAR* Str
return StringBegin;
}
- auto FindLen = Identifier.Len();
- auto StringToSearch = StringBegin;
+ int32 FindLen = Identifier.Len();
+ const TCHAR* StringToSearch = StringBegin;
for (;;)
{
- auto IdentifierStart = FCString::Strstr(StringToSearch, *Identifier);
+ const TCHAR* IdentifierStart = FCString::Strstr(StringToSearch, *Identifier);
if (IdentifierStart == nullptr)
{
// Not found.
return nullptr;
}
- if ((IdentifierStart > StringEnd) || (IdentifierStart + FindLen + 1 > StringEnd))
+ if (IdentifierStart > StringEnd || IdentifierStart + FindLen + 1 > StringEnd)
{
// Found match is out of string range.
return nullptr;
}
- if ((IdentifierStart == StringBegin) && (!FChar::IsIdentifier(*(IdentifierStart + FindLen + 1))))
+ if (IdentifierStart == StringBegin && !FChar::IsIdentifier(*(IdentifierStart + FindLen + 1)))
{
// Found match is at the beginning of string.
return IdentifierStart;
}
- if ((IdentifierStart + FindLen == StringEnd) && (!FChar::IsIdentifier(*(IdentifierStart - 1))))
+ if (IdentifierStart + FindLen == StringEnd && !FChar::IsIdentifier(*(IdentifierStart - 1)))
{
// Found match ends with end of string.
return IdentifierStart;
}
- if ((!FChar::IsIdentifier(*(IdentifierStart + FindLen)))
- && (!FChar::IsIdentifier(*(IdentifierStart - 1))))
+ if (!FChar::IsIdentifier(*(IdentifierStart + FindLen)) && !FChar::IsIdentifier(*(IdentifierStart - 1)))
{
// Found match is in the middle of string
return IdentifierStart;
@@ -107,7 +108,7 @@ const TCHAR* FindIdentifierExactMatch(const TCHAR* StringBegin, const TCHAR* Str
*/
int32 FindIdentifierExactMatch(const FString& String, const FString& Identifier)
{
- auto IdentifierPtr = FindIdentifierExactMatch(*String, *String + String.Len(), Identifier);
+ const TCHAR* IdentifierPtr = FindIdentifierExactMatch(*String, *String + String.Len(), Identifier);
if (IdentifierPtr == nullptr)
{
return INDEX_NONE;
@@ -152,7 +153,7 @@ static struct FFlagAudit
{
FString Name;
uint64 Flags;
- Pair(UObject* Source, const TCHAR* FlagType, uint64 InFlags)
+ Pair(const UObject* Source, const TCHAR* FlagType, uint64 InFlags)
{
Name = Source->GetFullName() + TEXT("[") + FlagType + TEXT("]");
Flags = InFlags;
@@ -161,7 +162,7 @@ static struct FFlagAudit
TArray Items;
- void Add(UObject* Source, const TCHAR* FlagType, uint64 Flags)
+ void Add(const UObject* Source, const TCHAR* FlagType, uint64 Flags)
{
new (Items) Pair(Source, FlagType, Flags);
}
@@ -230,7 +231,7 @@ static struct FFlagAudit
}
} TheFlagAudit;
-void ConvertToBuildIncludePath(UPackage* Package, FString& LocalPath)
+void ConvertToBuildIncludePath(const UPackage* Package, FString& LocalPath)
{
FPaths::MakePathRelativeTo(LocalPath, *GPackageToManifestModuleMap.FindChecked(Package)->IncludeBase);
}
@@ -253,11 +254,11 @@ bool FindPackageLocation(const TCHAR* InPackage, FString& OutLocation, FString&
FString CheckPackage(InPackage);
- auto* ModuleInfoPtr = CheckedPackageList.FindRef(CheckPackage);
+ FManifestModule* ModuleInfoPtr = CheckedPackageList.FindRef(CheckPackage);
if (!ModuleInfoPtr)
{
- auto* ModuleInfoPtr2 = GManifest.Modules.FindByPredicate([&](FManifestModule& Module) { return Module.Name == CheckPackage; });
+ FManifestModule* ModuleInfoPtr2 = GManifest.Modules.FindByPredicate([&](FManifestModule& Module) { return Module.Name == CheckPackage; });
if (ModuleInfoPtr2 && IFileManager::Get().DirectoryExists(*ModuleInfoPtr2->BaseDirectory))
{
ModuleInfoPtr = ModuleInfoPtr2;
@@ -266,7 +267,9 @@ bool FindPackageLocation(const TCHAR* InPackage, FString& OutLocation, FString&
}
if (!ModuleInfoPtr)
+ {
return false;
+ }
OutLocation = ModuleInfoPtr->BaseDirectory;
OutHeaderLocation = ModuleInfoPtr->GeneratedIncludeDirectory;
@@ -305,7 +308,7 @@ FString Macroize(const TCHAR* MacroName, const TCHAR* StringToMacroize)
static FString GetGeneratedCodeCRCTag(UField* Field)
{
FString Tag;
- auto FieldCrc = GGeneratedCodeCRCs.Find(Field);
+ const uint32* FieldCrc = GGeneratedCodeCRCs.Find(Field);
if (FieldCrc)
{
Tag = FString::Printf(TEXT(" // %u"), *FieldCrc);
@@ -441,7 +444,7 @@ FString CreateLiteralString(const FString& Str)
return Result;
}
-static FString GetMetaDataCodeForObject(UObject* Object, const TCHAR* SymbolName, const TCHAR* Spaces)
+static FString GetMetaDataCodeForObject(const UObject* Object, const TCHAR* SymbolName, const TCHAR* Spaces)
{
TMap* MetaData = UMetaData::GetMapForObject(Object);
@@ -450,7 +453,7 @@ static FString GetMetaDataCodeForObject(UObject* Object, const TCHAR* SymbolName
{
typedef TKeyValuePair KVPType;
TArray KVPs;
- for (auto& KVP : *MetaData)
+ for (TPair& KVP : *MetaData)
{
KVPs.Add(KVPType(KVP.Key, KVP.Value));
}
@@ -459,7 +462,7 @@ static FString GetMetaDataCodeForObject(UObject* Object, const TCHAR* SymbolName
// even when metadata is added in a different order
KVPs.Sort([](const KVPType& Lhs, const KVPType& Rhs) { return Lhs.Key < Rhs.Key; });
- for (const auto& KVP : KVPs)
+ for (const KVPType& KVP : KVPs)
{
Result += FString::Printf(TEXT("%sMetaData->SetValue(%s, TEXT(\"%s\"), %s);\r\n"), Spaces, SymbolName, *KVP.Key.ToString(), *CreateLiteralString(KVP.Value));
}
@@ -964,7 +967,7 @@ FString FNativeClassHeaderGenerator::PropertyNew(FString& Meta, UProperty* Prop,
ExtraArgs = FString::Printf(TEXT(", %s"), *GetSingletonName(TargetFunction));
}
- FString Constructor = FString::Printf(TEXT("new(EC_InternalUseOnlyConstructor, %s, TEXT(\"%s\"), RF_Public|RF_Transient|RF_Native) U%s(%s, 0x%016llx%s);"),
+ FString Constructor = FString::Printf(TEXT("new(EC_InternalUseOnlyConstructor, %s, TEXT(\"%s\"), RF_Public|RF_Transient|RF_MarkAsNative) U%s(%s, 0x%016llx%s);"),
*OuterString,
*FNativeClassHeaderGenerator::GetOverriddenName(Prop),
*Prop->GetClass()->GetName(),
@@ -1177,13 +1180,13 @@ static void FindNoExportStructs(TArray& Structs, UStruct* Start)
}
}
-FString GetPackageSingletonName(UPackage* Package)
+FString GetPackageSingletonName(const UPackage* Package)
{
static FString ClassString = NameLookupCPP.GetNameCPP(UPackage::StaticClass());
- return FString(TEXT("Z_Construct_")) + ClassString + TEXT("_") + FPackageName::GetShortName(Package) + TEXT("()");
+ return FString(TEXT("Z_Construct_")) + ClassString + TEXT("_") + Package->GetName().Replace(TEXT("/"), TEXT("_")) + TEXT("()");
}
-void FNativeClassHeaderGenerator::ExportGeneratedPackageInitCode(UPackage* InPackage)
+void FNativeClassHeaderGenerator::ExportGeneratedPackageInitCode(const UPackage* InPackage)
{
FString ApiString = GetAPIString();
FString SingletonName(GetPackageSingletonName(InPackage));
@@ -1214,7 +1217,7 @@ void FNativeClassHeaderGenerator::ExportGeneratedPackageInitCode(UPackage* InPac
FGuid Guid;
uint32 CombinedCRC = 0;
- for (auto& Split : GeneratedFunctionBodyTextSplit)
+ for (TUniqueObj& Split : GeneratedFunctionBodyTextSplit)
{
uint32 SplitCRC = GenerateTextCRC(*Split->ToUpper());
if (CombinedCRC == 0)
@@ -1328,8 +1331,9 @@ void FNativeClassHeaderGenerator::ExportNativeGeneratedInitCode(FClass* Class, F
}
else
{
- GeneratedClassRegisterFunctionText.Logf(TEXT("\t\tUClass* OuterClass = Cast(StaticFindObjectFast(UClass::StaticClass(), %s, TEXT(\"%s\")));\r\n"),
- *GetPackageSingletonName(CastChecked(Class->GetOutermost())), *Class->GetName());
+ const FString DynamicClassPackageName = FClass::GetTypePackageName(Class);
+ GeneratedClassRegisterFunctionText.Logf(TEXT("\t\tUPackage* OuterPackage = FindOrConstructDynamicTypePackage(TEXT(\"%s\"));\r\n"), *DynamicClassPackageName);
+ GeneratedClassRegisterFunctionText.Logf(TEXT("\t\tUClass* OuterClass = Cast(StaticFindObjectFast(UClass::StaticClass(), OuterPackage, TEXT(\"%s\")));\r\n"), *Class->GetName());
GeneratedClassRegisterFunctionText.Logf(TEXT("\t\tif (!OuterClass || !(OuterClass->ClassFlags & CLASS_Constructed))\r\n"));
}
@@ -1461,6 +1465,7 @@ void FNativeClassHeaderGenerator::ExportNativeGeneratedInitCode(FClass* Class, F
// Calculate generated class initialization code CRC so that we know when it changes after hot-reload
uint32 ClassCrc = GenerateTextCRC(*GeneratedClassRegisterFunctionText);
GGeneratedCodeCRCs.Add(Class, ClassCrc);
+ UHTMakefile.AddGeneratedCodeCRC(CurrentSourceFile.Top(), Class, ClassCrc);
// Emit the IMPLEMENT_CLASS macro to go in the generated cpp file.
if (!bIsDynamic)
{
@@ -1546,7 +1551,7 @@ void FNativeClassHeaderGenerator::ExportFunction(UFunction* Function, FScope* Sc
FString UFunctionType = bIsDelegate ? TEXT("UDelegateFunction") : TEXT("UFunction");
- CurrentFunctionText.Logf(TEXT("\t\t\tReturnFunction = new(EC_InternalUseOnlyConstructor, Outer, TEXT(\"%s\"), RF_Public|RF_Transient|RF_Native) %s(FObjectInitializer(), %s, 0x%08X, %d%s);\r\n"),
+ CurrentFunctionText.Logf(TEXT("\t\t\tReturnFunction = new(EC_InternalUseOnlyConstructor, Outer, TEXT(\"%s\"), RF_Public|RF_Transient|RF_MarkAsNative) %s(FObjectInitializer(), %s, 0x%08X, %d%s);\r\n"),
*FNativeClassHeaderGenerator::GetOverriddenName(Function),
*UFunctionType,
*SuperFunctionString,
@@ -1588,7 +1593,7 @@ void FNativeClassHeaderGenerator::ExportFunction(UFunction* Function, FScope* Sc
uint32 FunctionCrc = GenerateTextCRC(*CurrentFunctionText);
GGeneratedCodeCRCs.Add(Function, FunctionCrc);
-
+ UHTMakefile.AddGeneratedCodeCRC(CurrentSourceFile.Top(), Function, FunctionCrc);
GetGeneratedFunctionTextDevice() += CurrentFunctionText;
}
@@ -1637,7 +1642,7 @@ void FNativeClassHeaderGenerator::ExportNatives(FClass* Class)
GeneratedPackageCPP.Logf(TEXT("\t}\r\n"));
}
-void FNativeClassHeaderGenerator::ExportInterfaceCallFunctions(const TArray& InCallbackFunctions, UClass* Class, FClassMetaData* ClassData, FUHTStringBuilder& HeaderOutput)
+void FNativeClassHeaderGenerator::ExportInterfaceCallFunctions(const TArray& InCallbackFunctions, UClass* Class, FUHTStringBuilder& HeaderOutput)
{
TArray CallbackFunctions = InCallbackFunctions;
CallbackFunctions.Sort();
@@ -1863,6 +1868,14 @@ void ExportAutoIncludes(FStringOutputDevice& Out, const FUnrealSourceFile& Sourc
void FNativeClassHeaderGenerator::ExportClassesFromSourceFileInner(FUnrealSourceFile& SourceFile)
{
+ CurrentSourceFile.Push(&SourceFile);
+ ON_SCOPE_EXIT
+ {
+ CurrentSourceFile.Pop();
+ };
+
+ NameLookupCPP.SetCurrentSourceFile(&SourceFile);
+ UHTMakefile.AddToHeaderOrder(&SourceFile);
TArray Enums;
TArray Structs;
TArray DelegateFunctions;
@@ -1890,7 +1903,7 @@ void FNativeClassHeaderGenerator::ExportClassesFromSourceFileInner(FUnrealSource
ExportGeneratedEnumsInitCode(Enums);
// export boilerplate macros for structs
- ExportGeneratedStructBodyMacros(SourceFile, Structs);
+ ExportGeneratedStructBodyMacros(Structs);
// export delegate wrapper function implementations
ExportDelegateDefinitions(SourceFile, DelegateFunctions, true);
@@ -1950,12 +1963,12 @@ void FNativeClassHeaderGenerator::ExportClassesFromSourceFileInner(FUnrealSource
}
const bool bCastedClass = Class->HasAnyCastFlag(CASTCLASS_AllFlags) && SuperClass && Class->ClassCastFlags != SuperClass->ClassCastFlags;
- UInterfaceBoilerplate.Logf(TEXT("\tDECLARE_CLASS(%s, %s, COMPILED_IN_FLAGS(CLASS_Abstract%s), %s, %s, %s_API)\r\n"),
+ UInterfaceBoilerplate.Logf(TEXT("\tDECLARE_CLASS(%s, %s, COMPILED_IN_FLAGS(CLASS_Abstract%s), %s, TEXT(\"%s\"), %s_API)\r\n"),
ClassCPPName,
SuperClassCPPName,
*GetClassFlagExportText(Class),
bCastedClass ? *FString::Printf(TEXT("CASTCLASS_%s"), ClassCPPName) : TEXT("0"),
- *FPackageName::GetShortName(Class->GetOuter()->GetName()),
+ *FClass::GetTypePackageName(Class),
*APIArg);
UInterfaceBoilerplate.Logf(TEXT("\tDECLARE_SERIALIZER(%s)\r\n"), ClassCPPName);
@@ -1988,7 +2001,7 @@ void FNativeClassHeaderGenerator::ExportClassesFromSourceFileInner(FUnrealSource
InterfaceBoilerplate.Logf(TEXT("protected:\r\n\tvirtual ~%s() {}\r\npublic:\r\n"), *InterfaceCPPName);
InterfaceBoilerplate.Logf(TEXT("\ttypedef %s UClassType;\r\n"), ClassCPPName);
- ExportInterfaceCallFunctions(CallbackFunctions, Class, ClassData, InterfaceBoilerplate);
+ ExportInterfaceCallFunctions(CallbackFunctions, Class, InterfaceBoilerplate);
// we'll need a way to get to the UObject portion of a native interface, so that we can safely pass native interfaces
// to script VM functions
@@ -2059,13 +2072,13 @@ void FNativeClassHeaderGenerator::ExportClassesFromSourceFileInner(FUnrealSource
APIArg = TEXT("NO");
}
const bool bCastedClass = Class->HasAnyCastFlag(CASTCLASS_AllFlags) && SuperClass && Class->ClassCastFlags != SuperClass->ClassCastFlags;
- ClassBoilerplate.Logf(TEXT("\tDECLARE_CLASS(%s, %s, COMPILED_IN_FLAGS(%s%s), %s, %s, %s_API)\r\n"),
+ ClassBoilerplate.Logf(TEXT("\tDECLARE_CLASS(%s, %s, COMPILED_IN_FLAGS(%s%s), %s, TEXT(\"%s\"), %s_API)\r\n"),
ClassCPPName,
SuperClassCPPName ? SuperClassCPPName : TEXT("None"),
Class->HasAnyClassFlags(CLASS_Abstract) ? TEXT("CLASS_Abstract") : TEXT("0"),
*GetClassFlagExportText(Class),
bCastedClass ? *FString::Printf(TEXT("CASTCLASS_%s"), ClassCPPName) : TEXT("0"),
- *FPackageName::GetShortName(*Class->GetOuter()->GetName()),
+ *FClass::GetTypePackageName(Class),
*APIArg);
ClassBoilerplate.Logf(TEXT("\tDECLARE_SERIALIZER(%s)\r\n"), ClassCPPName);
@@ -2408,7 +2421,7 @@ FString GetBuildPath(FUnrealSourceFile& SourceFile)
return Out;
}
-FString FNativeClassHeaderGenerator::GetListOfPublicHeaderGroupIncludesString(UPackage* InPackage)
+FString FNativeClassHeaderGenerator::GetListOfPublicHeaderGroupIncludesString(const UPackage* InPackage)
{
FUHTStringBuilder Out;
@@ -2466,6 +2479,11 @@ void FNativeClassHeaderGenerator::ExportConstructorsMacros(const FString& Constr
void FNativeClassHeaderGenerator::ExportClassesFromSourceFileWrapper(FUnrealSourceFile& SourceFile)
{
+ CurrentSourceFile.Push(&SourceFile);
+ ON_SCOPE_EXIT
+ {
+ CurrentSourceFile.Pop();
+ };
check(!GeneratedHeaderText.Len());
ExportClassesFromSourceFileInner(SourceFile);
@@ -2557,6 +2575,12 @@ void FNativeClassHeaderGenerator::ExportClassesFromSourceFileWrapper(FUnrealSour
void FNativeClassHeaderGenerator::ExportSourceFileHeaderRecursive(FClasses& AllClasses, FUnrealSourceFile* SourceFile, TSet& VisitedSet, bool bCheckDependenciesOnly)
{
+ CurrentSourceFile.Push(SourceFile);
+ ON_SCOPE_EXIT
+ {
+ CurrentSourceFile.Pop();
+ };
+
bool bIsCorrectHeader = SourceFile->GetPackage() == Package;
// Check for circular header dependencies between export classes.
@@ -2677,7 +2701,7 @@ void FNativeClassHeaderGenerator::ExportEnums( const TArray& Enums )
}
// Exports the header text for the list of structs specified (GENERATED_BODY impls)
-void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceFile& SourceFile, const TArray& NativeStructs)
+void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(const TArray& NativeStructs)
{
// reverse the order.
for (int32 i = NativeStructs.Num() - 1; i >= 0; --i)
@@ -2703,7 +2727,7 @@ void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceF
const FString StaticClassLine = FString::Printf(TEXT("\t%sstatic class UScriptStruct* StaticStruct();\r\n"), *RequiredAPI);
const FString CombinedLine = FriendLine + StaticClassLine;
- const FString MacroName = SourceFile.GetGeneratedBodyMacroName(Struct->StructMacroDeclaredLineNumber);
+ const FString MacroName = CurrentSourceFile.Top()->GetGeneratedBodyMacroName(Struct->StructMacroDeclaredLineNumber);
const FString Macroized = Macroize(*MacroName, *CombinedLine);
GeneratedHeaderText.Log(*Macroized);
@@ -2722,11 +2746,16 @@ void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceF
OuterName = NameLookupCPP.GetNameCPP(CastChecked(Struct->GetOuter()));
OuterName += TEXT("::StaticClass()");
}
- else
+ else if (!bIsDynamic)
{
OuterName = GetPackageSingletonName(CastChecked(Struct->GetOuter()));
GeneratedPackageCPP.Logf(TEXT("\textern %sclass UPackage* %s;\r\n"), *FriendApiString, *OuterName);
}
+ else
+ {
+ OuterName = TEXT("StructPackage");
+ GeneratedPackageCPP.Logf(TEXT("\tclass UPackage* %s = FindOrConstructDynamicTypePackage(TEXT(\"%s\"));\r\n"), *OuterName, *FClass::GetTypePackageName(Struct));
+ }
if (!bIsDynamic)
{
@@ -2734,7 +2763,6 @@ void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceF
}
else
{
- FString PackageSingletonName = GetPackageSingletonName(CastChecked(Struct->GetOuter()));
GeneratedPackageCPP.Logf(TEXT("\tclass UScriptStruct* Singleton = Cast(StaticFindObjectFast(UScriptStruct::StaticClass(), %s, TEXT(\"%s\")));\r\n"),
*OuterName, *Struct->GetName());
}
@@ -2796,12 +2824,17 @@ void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceF
// Structs can either have a UClass or UPackage as outer (if delcared in non-UClass header).
if (ScriptStruct->GetOuter()->IsA(UStruct::StaticClass()))
{
- GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tUStruct* Outer=%s;\r\n"), *GetSingletonName(CastChecked(ScriptStruct->GetOuter())));
+ GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tUStruct* Outer = %s;\r\n"), *GetSingletonName(CastChecked(ScriptStruct->GetOuter())));
+ }
+ else if (!bIsDynamic)
+ {
+ GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tUPackage* Outer = %s;\r\n"), *GetPackageSingletonName(CastChecked(ScriptStruct->GetOuter())));
}
else
{
- GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tUPackage* Outer=%s;\r\n"), *GetPackageSingletonName(CastChecked(ScriptStruct->GetOuter())));
+ GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tUPackage* Outer = FindOrConstructDynamicTypePackage(TEXT(\"%s\"));\r\n"), *FClass::GetTypePackageName(ScriptStruct));
}
+
GeneratedStructRegisterFunctionText.Logf(TEXT("\t\textern uint32 %s();\r\n"), *CRCFuncName);
GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tstatic UScriptStruct* ReturnStruct = FindExistingStructIfHotReloadOrDynamic(Outer, TEXT(\"%s\"), sizeof(%s), %s(), %s);\r\n"), *ScriptStruct->GetName(), NameLookupCPP.GetNameCPP(Struct), *CRCFuncName, bIsDynamic ? TEXT("true") : TEXT("false"));
GeneratedStructRegisterFunctionText.Logf(TEXT("\t\tif (!ReturnStruct)\r\n"));
@@ -2825,7 +2858,7 @@ void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceF
ExplicitSizeString = FString::Printf(TEXT(", sizeof(%s), ALIGNOF(%s)"), NameLookupCPP.GetNameCPP(ScriptStruct), NameLookupCPP.GetNameCPP(ScriptStruct));
}
- GeneratedStructRegisterFunctionText.Logf(TEXT("\t\t\tReturnStruct = new(EC_InternalUseOnlyConstructor, Outer, TEXT(\"%s\"), RF_Public|RF_Transient|RF_Native) UScriptStruct(FObjectInitializer(), %s, %s, EStructFlags(0x%08X)%s);\r\n"),
+ GeneratedStructRegisterFunctionText.Logf(TEXT("\t\t\tReturnStruct = new(EC_InternalUseOnlyConstructor, Outer, TEXT(\"%s\"), RF_Public|RF_Transient|RF_MarkAsNative) UScriptStruct(FObjectInitializer(), %s, %s, EStructFlags(0x%08X)%s);\r\n"),
*ScriptStruct->GetName(),
*BaseStructString,
*CppStructOpsString,
@@ -2858,6 +2891,7 @@ void FNativeClassHeaderGenerator::ExportGeneratedStructBodyMacros(FUnrealSourceF
uint32 StructCrc = GenerateTextCRC(*GeneratedStructRegisterFunctionText);
GGeneratedCodeCRCs.Add(ScriptStruct, StructCrc);
+ UHTMakefile.AddGeneratedCodeCRC(CurrentSourceFile.Top(), ScriptStruct, StructCrc);
auto& GeneratedFunctionText = GetGeneratedFunctionTextDevice();
GeneratedFunctionText += GeneratedStructRegisterFunctionText;
@@ -2887,24 +2921,39 @@ void FNativeClassHeaderGenerator::ExportGeneratedEnumsInitCode(const TArray(Enum->GetOuter()));
+ if (!bIsDynamic)
+ {
+ PackageSingletonName = GetPackageSingletonName(CastChecked(Enum->GetOuter()));
+ }
+ else
+ {
+ PackageSingletonName = FClass::GetTypePackageName(Enum);
+ }
GeneratedPackageCPP.Logf(TEXT("static class UEnum* %s_StaticEnum()\r\n"), *Enum->GetName());
GeneratedPackageCPP.Logf(TEXT("{\r\n"));
- GeneratedPackageCPP.Logf(TEXT("\textern %sclass UPackage* %s;\r\n"), *FriendApiString, *PackageSingletonName);
-
+
if (!bIsDynamic)
{
+ GeneratedPackageCPP.Logf(TEXT("\textern %sclass UPackage* %s;\r\n"), *FriendApiString, *PackageSingletonName);
GeneratedPackageCPP.Logf(TEXT("\tstatic class UEnum* Singleton = NULL;\r\n"));
}
else
{
- GeneratedPackageCPP.Logf(TEXT("\tclass UEnum* Singleton = Cast(StaticFindObjectFast(UEnum::StaticClass(), %s, TEXT(\"%s\")));\r\n"),
- *PackageSingletonName, *Enum->GetName());
+ GeneratedPackageCPP.Logf(TEXT("\tclass UPackage* EnumPackage = FindOrConstructDynamicTypePackage(TEXT(\"%s\"));\r\n"), *PackageSingletonName);
+ GeneratedPackageCPP.Logf(TEXT("\tclass UEnum* Singleton = Cast(StaticFindObjectFast(UEnum::StaticClass(), EnumPackage, TEXT(\"%s\")));\r\n"), *Enum->GetName());
}
GeneratedPackageCPP.Logf(TEXT("\tif (!Singleton)\r\n"));
GeneratedPackageCPP.Logf(TEXT("\t{\r\n"));
- GeneratedPackageCPP.Logf(TEXT("\t\textern %sclass UEnum* %s;\r\n"), *FriendApiString, *StaticConstructionString);
- GeneratedPackageCPP.Logf(TEXT("\t\tSingleton = GetStaticEnum(%s, %s, TEXT(\"%s\"));\r\n"), *SingletonName, *PackageSingletonName, *Enum->GetName());
+ GeneratedPackageCPP.Logf(TEXT("\t\textern %sclass UEnum* %s;\r\n"), *FriendApiString, *StaticConstructionString);
+ if (!bIsDynamic)
+ {
+ GeneratedPackageCPP.Logf(TEXT("\t\tSingleton = GetStaticEnum(%s, %s, TEXT(\"%s\"));\r\n"), *SingletonName, *PackageSingletonName, *Enum->GetName());
+ }
+ else
+ {
+ GeneratedPackageCPP.Logf(TEXT("\t\tSingleton = GetStaticEnum(%s, EnumPackage, TEXT(\"%s\"));\r\n"), *SingletonName, *Enum->GetName());
+ }
GeneratedPackageCPP.Logf(TEXT("\t}\r\n"));
GeneratedPackageCPP.Logf(TEXT("\treturn Singleton;\r\n"));
@@ -2929,16 +2978,20 @@ void FNativeClassHeaderGenerator::ExportGeneratedEnumsInitCode(const TArray(Enum->GetOuter())));
}
- else
+ else if (!bIsDynamic)
{
GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\tUPackage* Outer=%s;\r\n"), *GetPackageSingletonName(CastChecked(Enum->GetOuter())));
}
+ else
+ {
+ GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\tUPackage* Outer = FindOrConstructDynamicTypePackage(TEXT(\"%s\"));\r\n"), *PackageSingletonName);
+ }
GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\textern uint32 %s();\r\n"), *CRCFuncName);
GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\tstatic UEnum* ReturnEnum = FindExistingEnumIfHotReload(Outer, TEXT(\"%s\"), 0, %s());\r\n"), *Enum->GetName(), *CRCFuncName);
GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\tif (!ReturnEnum)\r\n"));
GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\t{\r\n"));
- GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\t\tReturnEnum = new(EC_InternalUseOnlyConstructor, Outer, TEXT(\"%s\"), RF_Public|RF_Transient|RF_Native) UEnum(FObjectInitializer());\r\n"), *Enum->GetName());
+ GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\t\tReturnEnum = new(EC_InternalUseOnlyConstructor, Outer, TEXT(\"%s\"), RF_Public|RF_Transient|RF_MarkAsNative) UEnum(FObjectInitializer());\r\n"), *Enum->GetName());
GeneratedEnumRegisterFunctionText.Logf(TEXT("\t\t\tTArray> EnumNames;\r\n"));
for (int32 Index = 0; Index < Enum->NumEnums(); Index++)
{
@@ -2973,6 +3026,7 @@ void FNativeClassHeaderGenerator::ExportGeneratedEnumsInitCode(const TArrayLinkChild(%s); // %u\r\n"), *EnumSingletonName, EnumCrc);
}
@@ -3126,7 +3180,7 @@ void FNativeClassHeaderGenerator::ExportDelegateDefinitions(FUnrealSourceFile& S
// Only exporting function prototype
DelegateOutput.Logf(TEXT(";\r\n"));
- ExportFunction(Function, &SourceFile.GetScope().Get(), false);
+ ExportFunction(Function, &CurrentSourceFile.Top()->GetScope().Get(), false);
}
else
{
@@ -3273,7 +3327,7 @@ void ExportProtoDeclaration(FOutputDevice& Out, const FString& MessageName, TFie
* @param Indent starting indentation level
* @param Output optional output redirect
*/
-void FNativeClassHeaderGenerator::ExportProtoMessage(const TArray& InCallbackFunctions, FClassMetaData* ClassData, int32 Indent, FUHTStringBuilder* Output)
+void FNativeClassHeaderGenerator::ExportProtoMessage(const TArray& InCallbackFunctions, int32 Indent, FUHTStringBuilder* Output)
{
// Parms struct definitions.
FUHTStringBuilder HeaderOutput;
@@ -4443,7 +4497,7 @@ TArray FNativeClassHeaderGenerator::ExportCallbackFunctions(FUnrealS
PrologMacroCalls.Logf(TEXT("\t%s\r\n"), *MacroName);
// export .proto files for any net service functions
- ExportProtoMessage(CallbackFunctions, ClassData);
+ ExportProtoMessage(CallbackFunctions);
// export .java files for any net service functions
ExportMCPMessage(CallbackFunctions, ClassData);
@@ -4692,13 +4746,14 @@ FUHTStringBuilder& FNativeClassHeaderGenerator::GetGeneratedFunctionTextDevice()
// Constructor.
FNativeClassHeaderGenerator::FNativeClassHeaderGenerator(
- UPackage* InPackage,
+ const UPackage* InPackage,
const TArray& SourceFiles,
FClasses& AllClasses,
bool InAllowSaveExportedHeaders
#if WITH_HOT_RELOAD_CTORS
, bool bInExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
+ , FUHTMakefile& InUHTMakefile
)
: API (FPackageName::GetShortName(InPackage).ToUpper())
, Package (InPackage)
@@ -4708,6 +4763,7 @@ FNativeClassHeaderGenerator::FNativeClassHeaderGenerator(
#if WITH_HOT_RELOAD_CTORS
, bExportVTableConstructors (bInExportVTableConstructors)
#endif // WITH_HOT_RELOAD_CTORS
+ , UHTMakefile(InUHTMakefile)
{
const FString PackageName = FPackageName::GetShortName(Package);
@@ -5265,12 +5321,12 @@ void GetScriptPlugins(TArray& ScriptPlugins)
bool bSupportedPlugin = ScriptGenerator->SupportsTarget(GManifest.TargetName);
if (bSupportedPlugin)
{
- // Find the right output direcotry for this plugin base on its target (Engine-side) plugin name.
+ // Find the right output directory for this plugin base on its target (Engine-side) plugin name.
FString GeneratedCodeModuleName = ScriptGenerator->GetGeneratedCodeModuleName();
const FManifestModule* GeneratedCodeModule = NULL;
FString OutputDirectory;
FString IncludeBase;
- for (const auto& Module : GManifest.Modules)
+ for (const FManifestModule& Module : GManifest.Modules)
{
if (Module.Name == GeneratedCodeModuleName)
{
@@ -5349,36 +5405,8 @@ void ResolveSuperClasses(UPackage* Package)
}
}
-ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename)
-{
- check(GIsUCCMakeStandaloneHeaderGenerator);
- ECompilationResult::Type Result = ECompilationResult::Succeeded;
-
- if ( !FParse::Param( FCommandLine::Get(), TEXT("IgnoreWarnings")) )
+ECompilationResult::Type PreparseModules(FUHTMakefile& UHTMakefile, const FString& ModuleInfoPath, int32& NumFailures)
{
- GWarn->TreatWarningsAsErrors = true;
- }
-
- FString ModuleInfoPath = FPaths::GetPath(ModuleInfoFilename);
-
- // Load the manifest file, giving a list of all modules to be processed, pre-sorted by dependency ordering
-#if !PLATFORM_EXCEPTIONS_DISABLED
- try
-#endif
- {
- GManifest = FManifest::LoadFromFile(ModuleInfoFilename);
- }
-#if !PLATFORM_EXCEPTIONS_DISABLED
- catch (const TCHAR* Ex)
- {
- UE_LOG(LogCompile, Error, TEXT("Failed to load manifest file '%s': %s"), *ModuleInfoFilename, Ex);
- return GCompilationResult;
- }
-#endif
-
- // Load classes for editing.
- int32 NumFailures = 0;
-
// Three passes. 1) Public 'Classes' headers (legacy) 2) Public headers 3) Private headers
enum EHeaderFolderTypes
{
@@ -5389,20 +5417,30 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
FolderType_Count
};
- double TotalModulePreparseTime = 0.0;
- double TotalParseAndCodegenTime = 0.0;
-
- for (const auto& Module : GManifest.Modules)
+ ECompilationResult::Type Result = ECompilationResult::Succeeded;
+ for (FManifestModule& Module : GManifest.Modules)
{
if (Result != ECompilationResult::Succeeded)
{
break;
}
- double ThisModulePreparseTime = 0.0;
- int32 NumHeadersPreparsed = 0;
- FDurationTimer ThisModuleTimer(ThisModulePreparseTime);
- ThisModuleTimer.Start();
+ FName ModuleName = FName(*Module.Name);
+ UHTMakefile.SetCurrentModuleName(ModuleName);
+ bool bLoadFromMakefile = UHTMakefile.CanLoadModule(Module);
+ if (bLoadFromMakefile)
+ {
+ // Load module data from makefile.
+ UHTMakefile.LoadModuleData(ModuleName, Module);
+ continue;
+ }
+ UHTMakefile.AddModule(ModuleName);
+
+ // Mark that we'll need to append newly constructed objects to ones loaded from makefile.
+ UHTMakefile.SetShouldMoveNewObjects();
+
+ // Force regeneration of all subsequent modules, otherwise data will get corrupted.
+ Module.ForceRegeneration();
UPackage* Package = Cast(StaticFindObjectFast(UPackage::StaticClass(), NULL, FName(*Module.LongPackageName), false, false));
if (Package == NULL)
@@ -5419,8 +5457,15 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
Package->SetPackageFlags(PKG_EditorOnly);
}
+ // Add new module or overwrite whatever we had loaded, that data is obsolete.
+ UHTMakefile.AddPackage(Package);
GPackageToManifestModuleMap.Add(Package, &Module);
+ double ThisModulePreparseTime = 0.0;
+ int32 NumHeadersPreparsed = 0;
+ FDurationTimer ThisModuleTimer(ThisModulePreparseTime);
+ ThisModuleTimer.Start();
+
// Pre-parse the headers
for (int32 PassIndex = 0; PassIndex < FolderType_Count && Result == ECompilationResult::Succeeded; ++PassIndex)
{
@@ -5454,18 +5499,25 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
FError::Throwf(TEXT("UnrealHeaderTool was unable to load source file '%s'"), *FullFilename);
}
- TSharedRef UnrealSourceFile = PerformInitialParseOnHeader(Package, RawFilename, RF_Public | RF_Standalone, *HeaderFile);
-
+ TSharedRef UnrealSourceFile = PerformInitialParseOnHeader(Package, RawFilename, RF_Public | RF_Standalone, *HeaderFile, UHTMakefile);
+ FUnrealSourceFile* UnrealSourceFilePtr = &UnrealSourceFile.Get();
+ TArray DefinedClasses = UnrealSourceFile->GetDefinedClasses();
+ for (UClass* DefinedClass : DefinedClasses)
+ {
+ UHTMakefile.AddClass(UnrealSourceFilePtr, DefinedClass);
+ }
GUnrealSourceFilesMap.Add(RawFilename, UnrealSourceFile);
+ UHTMakefile.AddUnrealSourceFilesMapEntry(UnrealSourceFilePtr, RawFilename);
if (CurrentlyProcessing == PublicClassesHeaders)
{
for (auto* Class : UnrealSourceFile->GetDefinedClasses())
{
GPublicClassSet.Add(Class);
+ UHTMakefile.AddPublicClassSetEntry(UnrealSourceFilePtr, Class);
}
- GPublicSourceFileSet.Add(&UnrealSourceFile.Get());
+ GPublicSourceFileSet.Add(UnrealSourceFilePtr);
}
// Save metadata for the class path, both for it's include path and relative to the module base directory
@@ -5532,6 +5584,10 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
}
}
+ // Don't resolve superclasses for module when loading from makefile.
+ // Data is only partially loaded at this point.
+ if (!bLoadFromMakefile)
+ {
#if !PLATFORM_EXCEPTIONS_DISABLED
try
#endif
@@ -5555,10 +5611,69 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
#endif
ThisModuleTimer.Stop();
- TotalModulePreparseTime += ThisModulePreparseTime;
UE_LOG(LogCompile, Log, TEXT("Preparsed module %s containing %i files(s) in %.2f secs."), *Module.LongPackageName, NumHeadersPreparsed, ThisModulePreparseTime);
}
+ }
+ return Result;
+}
+
+ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename)
+{
+ check(GIsUCCMakeStandaloneHeaderGenerator);
+ ECompilationResult::Type Result = ECompilationResult::Succeeded;
+
+ if ( !FParse::Param( FCommandLine::Get(), TEXT("IgnoreWarnings")) )
+ {
+ GWarn->TreatWarningsAsErrors = true;
+ }
+
+ FString ModuleInfoPath = FPaths::GetPath(ModuleInfoFilename);
+
+ // Load the manifest file, giving a list of all modules to be processed, pre-sorted by dependency ordering
+#if !PLATFORM_EXCEPTIONS_DISABLED
+ try
+#endif
+ {
+ GManifest = FManifest::LoadFromFile(ModuleInfoFilename);
+ }
+#if !PLATFORM_EXCEPTIONS_DISABLED
+ catch (const TCHAR* Ex)
+ {
+ UE_LOG(LogCompile, Error, TEXT("Failed to load manifest file '%s': %s"), *ModuleInfoFilename, Ex);
+ return GCompilationResult;
+ }
+#endif
+
+ // Counters.
+ int32 NumFailures = 0;
+ double TotalModulePreparseTime = 0.0;
+ double TotalParseAndCodegenTime = 0.0;
+
+ // Check if makefiles should be used. If not, only makefile serialization is skipped.
+ // as the rest of code doesn't impact performance and we don't want to add ifs around
+ // every makefile related piece of code.
+ bool bUseMakefile = FParse::Param(FCommandLine::Get(), TEXT("UseMakefiles"));
+
+ FUHTMakefile UHTMakefile;
+ UHTMakefile.SetNameLookupCPP(&NameLookupCPP);
+ UHTMakefile.SetManifest(&GManifest);
+
+ // Declaring outside of bUseMakefile scope as the same value is used when saving makefile.
+ FString MakefilePath;
+ if (bUseMakefile)
+ {
+ MakefilePath = FPaths::Combine(*ModuleInfoPath, TEXT("UHT.makefile"));
+ UHTMakefile.LoadFromFile(*MakefilePath, &GManifest);
+ }
+ UHTMakefile.StartPreloading();
+ {
+ FDurationTimer TotalModulePreparseTimer(TotalModulePreparseTime);
+ TotalModulePreparseTimer.Start();
+ PreparseModules(UHTMakefile, ModuleInfoPath, NumFailures);
+ TotalModulePreparseTimer.Stop();
+ }
+ UHTMakefile.StopPreloading();
// Do the actual parse of the headers and generate for them
if (Result == ECompilationResult::Succeeded)
{
@@ -5610,7 +5725,12 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
GetScriptPlugins(ScriptPlugins);
}
- for (const auto& Module : GManifest.Modules)
+ if (UHTMakefile.ShouldMoveNewObjects())
+ {
+ UHTMakefile.MoveNewObjects();
+ }
+
+ for (const FManifestModule& Module : GManifest.Modules)
{
if (UPackage* Package = Cast(StaticFindObjectFast(UPackage::StaticClass(), NULL, FName(*Module.LongPackageName), false, false)))
{
@@ -5631,9 +5751,9 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
} UseVTableConstructorsCache;
Result = FHeaderParser::ParseAllHeadersInside(AllClasses, GWarn, Package, Module, ScriptPlugins,
- Module.ModuleType != EBuildModuleType::Game || UseVTableConstructorsCache.bUseVTableConstructors);
+ Module.ModuleType != EBuildModuleType::Game || UseVTableConstructorsCache.bUseVTableConstructors, UHTMakefile);
#else // WITH_HOT_RELOAD_CTORS
- Result = FHeaderParser::ParseAllHeadersInside(AllClasses, GWarn, Package, Module, ScriptPlugins);
+ Result = FHeaderParser::ParseAllHeadersInside(AllClasses, GWarn, Package, Module, ScriptPlugins, UHTMakefile);
#endif // WITH_HOT_RELOAD_CTORS
if (Result != ECompilationResult::Succeeded)
{
@@ -5645,7 +5765,7 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
{
FScopedDurationTimer PluginTimeTracker(GPluginOverheadTime);
- for (auto ScriptGenerator : ScriptPlugins)
+ for (IScriptGeneratorPluginInterface* ScriptGenerator : ScriptPlugins)
{
ScriptGenerator->FinishExport();
}
@@ -5682,15 +5802,23 @@ ECompilationResult::Type UnrealHeaderTool_Main(const FString& ModuleInfoFilename
UE_LOG(LogCompile, Error, TEXT("Number of generated files mismatch ref=%d, ver=%d"), RefFileNames.Num(), VerFileNames.Num());
}
}
+
TheFlagAudit.WriteResults();
GIsRequestingExit = true;
- if ((Result == ECompilationResult::Succeeded) && (NumFailures > 0))
+ if ((Result != ECompilationResult::Succeeded) || (NumFailures > 0))
{
+ // Makefile might be corrupted, it's safer to delete it now.
+ IFileManager::Get().Delete(*MakefilePath);
return ECompilationResult::OtherCompilationError;
}
+ if (bUseMakefile)
+ {
+ UHTMakefile.SaveToFile(*MakefilePath);
+ }
+
return Result;
}
@@ -5743,7 +5871,7 @@ UClass* ProcessParsedClass(bool bClassIsAnInterface, TArray &De
const static bool bVerboseOutput = FParse::Param(FCommandLine::Get(), TEXT("VERBOSE"));
- if (ResultClass == nullptr || !ResultClass->HasAnyFlags(RF_Native))
+ if (ResultClass == nullptr || !ResultClass->IsNative())
{
// detect if the same class name is used in multiple packages
if (ResultClass == nullptr)
@@ -5785,7 +5913,7 @@ UClass* ProcessParsedClass(bool bClassIsAnInterface, TArray &De
}
-TSharedRef PerformInitialParseOnHeader(UPackage* InParent, const FString& FileName, EObjectFlags Flags, const TCHAR* Buffer)
+TSharedRef PerformInitialParseOnHeader(UPackage* InParent, const FString& FileName, EObjectFlags Flags, const TCHAR* Buffer, FUHTMakefile& UHTMakefile)
{
const TCHAR* InBuffer = Buffer;
@@ -5799,19 +5927,21 @@ TSharedRef PerformInitialParseOnHeader(UPackage* InParent, co
TArray ParsedClassArray;
FHeaderParser::SimplifiedClassParse(Buffer, /*out*/ ParsedClassArray, /*out*/ DependsOn, ClassHeaderTextStrippedOfCppText);
- TSharedRef UnrealSourceFile = MakeShareable(new FUnrealSourceFile(InParent, FileName, ClassHeaderTextStrippedOfCppText));
-
+ FUnrealSourceFile* UnrealSourceFilePtr = new FUnrealSourceFile(InParent, FileName, ClassHeaderTextStrippedOfCppText);
+ TSharedRef UnrealSourceFile = MakeShareable(UnrealSourceFilePtr);
+ UHTMakefile.AddUnrealSourceFile(UnrealSourceFilePtr);
+ UHTMakefile.AddToHeaderOrder(UnrealSourceFilePtr);
for (auto& ParsedClassInfo : ParsedClassArray)
{
UClass* ResultClass = ProcessParsedClass(ParsedClassInfo.IsInterface(), DependsOn, ParsedClassInfo.GetClassName(), ParsedClassInfo.GetBaseClassName(), InParent, Flags);
- FScope::AddTypeScope(ResultClass, &UnrealSourceFile->GetScope().Get());
+ FScope::AddTypeScope(ResultClass, &UnrealSourceFile->GetScope().Get(), UnrealSourceFilePtr, UHTMakefile);
- AddTypeDefinition(*UnrealSourceFile, ResultClass, ParsedClassInfo.GetClassDefLine());
+ AddTypeDefinition(UHTMakefile, UnrealSourceFilePtr, ResultClass, ParsedClassInfo.GetClassDefLine());
UnrealSourceFile->AddDefinedClass(ResultClass, MoveTemp(ParsedClassInfo));
}
- for (const auto& DependsOnElement : DependsOn)
+ for (auto& DependsOnElement : DependsOn)
{
UnrealSourceFile->GetIncludes().Add(DependsOnElement);
}
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/GeneratedCodeVersion.h b/Engine/Source/Programs/UnrealHeaderTool/Private/GeneratedCodeVersion.h
index 9689dcb48c82..41dbbb1cf666 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/GeneratedCodeVersion.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/GeneratedCodeVersion.h
@@ -5,7 +5,7 @@
// This MUST be kept in sync with EGeneratedBodyVersion in UBT defined in ExternalExecution.cs
// and with ToGeneratedBodyVersion function below
//
-enum class EGeneratedCodeVersion : int32
+enum class EGeneratedCodeVersion : uint8
{
None,
V1,
@@ -13,6 +13,22 @@ enum class EGeneratedCodeVersion : int32
VLatest = V2
};
+inline FArchive& operator<<(FArchive& Ar, EGeneratedCodeVersion& Type)
+{
+ if (Ar.IsLoading())
+ {
+ uint8 Value;
+ Ar << Value;
+ Type = (EGeneratedCodeVersion)Value;
+ }
+ else if (Ar.IsSaving())
+ {
+ uint8 Value = (uint8)Type;
+ Ar << Value;
+ }
+ return Ar;
+}
+
inline EGeneratedCodeVersion ToGeneratedCodeVersion(const FString& InString)
{
if (InString.Compare(TEXT("V1")) == 0)
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.cpp
index ca31c577cf94..89bf9dd593f2 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.cpp
@@ -21,6 +21,7 @@
#include "Specifiers/InterfaceSpecifiers.h"
#include "Specifiers/StructSpecifiers.h"
#include "Specifiers/VariableSpecifiers.h"
+#include "UHTMakefile/UHTMakefile.h"
double GPluginOverheadTime = 0.0;
double GHeaderCodeGenTime = 0.0;
@@ -184,7 +185,7 @@ namespace
for (const auto& Specifier : Specifiers)
{
- switch ((EFunctionSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GFunctionSpecifierStrings, ARRAY_COUNT(GFunctionSpecifierStrings)))
+ switch ((EFunctionSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GFunctionSpecifierStrings))
{
default:
{
@@ -486,87 +487,130 @@ namespace
return bDefaultToInstanced;
}
- UProperty* CreateVariableProperty(FPropertyBase& VarProperty, UObject* Scope, FName Name, EObjectFlags ObjectFlags, EVariableCategory::Type VariableCategory)
+ UProperty* CreateVariableProperty(FPropertyBase& VarProperty, UObject* Scope, FName Name, EObjectFlags ObjectFlags, EVariableCategory::Type VariableCategory, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
{
switch (VarProperty.Type)
{
case CPT_Byte:
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UByteProperty(FObjectInitializer());
+ UByteProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UByteProperty(FObjectInitializer());
Result->Enum = VarProperty.Enum;
+ UHTMakefile.AddByteProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Int8:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInt8Property(FObjectInitializer());
+ {
+ UInt8Property* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInt8Property(FObjectInitializer());
+ UHTMakefile.AddInt8Property(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Int16:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInt16Property(FObjectInitializer());
+ {
+ UInt16Property* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInt16Property(FObjectInitializer());
+ UHTMakefile.AddInt16Property(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Int:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UIntProperty(FObjectInitializer());
+ {
+ UIntProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UIntProperty(FObjectInitializer());
+ UHTMakefile.AddIntProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Int64:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInt64Property(FObjectInitializer());
+ {
+ UInt64Property* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInt64Property(FObjectInitializer());
+ UHTMakefile.AddInt64Property(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_UInt16:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UUInt16Property(FObjectInitializer());
+ {
+ UUInt16Property* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UUInt16Property(FObjectInitializer());
+ UHTMakefile.AddUInt16Property(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_UInt32:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UUInt32Property(FObjectInitializer());
+ {
+ UUInt32Property* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UUInt32Property(FObjectInitializer());
+ UHTMakefile.AddUInt32Property(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_UInt64:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UUInt64Property(FObjectInitializer());
+ {
+ UUInt64Property* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UUInt64Property(FObjectInitializer());
+ UHTMakefile.AddUInt64Property(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Bool:
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
+ UBoolProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
Result->SetBoolSize(sizeof(bool), true);
+ UHTMakefile.AddBoolProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Bool8:
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
+ UBoolProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
Result->SetBoolSize((VariableCategory == EVariableCategory::Return) ? sizeof(bool) : sizeof(uint8), VariableCategory == EVariableCategory::Return);
+ UHTMakefile.AddBoolProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Bool16:
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
+ UBoolProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
Result->SetBoolSize((VariableCategory == EVariableCategory::Return) ? sizeof(bool) : sizeof(uint16), VariableCategory == EVariableCategory::Return);
+ UHTMakefile.AddBoolProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Bool32:
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
+ UBoolProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
Result->SetBoolSize((VariableCategory == EVariableCategory::Return) ? sizeof(bool) : sizeof(uint32), VariableCategory == EVariableCategory::Return);
+ UHTMakefile.AddBoolProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Bool64:
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
+ UBoolProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UBoolProperty(FObjectInitializer());
Result->SetBoolSize((VariableCategory == EVariableCategory::Return) ? sizeof(bool) : sizeof(uint64), VariableCategory == EVariableCategory::Return);
+ UHTMakefile.AddBoolProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Float:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UFloatProperty(FObjectInitializer());
+ {
+ UFloatProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UFloatProperty(FObjectInitializer());
+ UHTMakefile.AddFloatProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Double:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UDoubleProperty(FObjectInitializer());
+ {
+ UDoubleProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UDoubleProperty(FObjectInitializer());
+ UHTMakefile.AddDoubleProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_ObjectReference:
check(VarProperty.PropertyClass);
if (VarProperty.PropertyClass->IsChildOf(UClass::StaticClass()))
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UClassProperty(FObjectInitializer());
+ UClassProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UClassProperty(FObjectInitializer());
Result->MetaClass = VarProperty.MetaClass;
Result->PropertyClass = VarProperty.PropertyClass;
+ UHTMakefile.AddClassProperty(UnrealSourceFile, Result);
return Result;
}
else
@@ -577,8 +621,9 @@ namespace
AddEditInlineMetaData(VarProperty.MetaData);
}
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UObjectProperty(FObjectInitializer());
+ UObjectProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UObjectProperty(FObjectInitializer());
Result->PropertyClass = VarProperty.PropertyClass;
+ UHTMakefile.AddObjectProperty(UnrealSourceFile, Result);
return Result;
}
@@ -586,8 +631,9 @@ namespace
{
check(VarProperty.PropertyClass);
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UWeakObjectProperty(FObjectInitializer());
+ UWeakObjectProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UWeakObjectProperty(FObjectInitializer());
Result->PropertyClass = VarProperty.PropertyClass;
+ UHTMakefile.AddWeakObjectProperty(UnrealSourceFile, Result);
return Result;
}
@@ -595,8 +641,9 @@ namespace
{
check(VarProperty.PropertyClass);
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) ULazyObjectProperty(FObjectInitializer());
+ ULazyObjectProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) ULazyObjectProperty(FObjectInitializer());
Result->PropertyClass = VarProperty.PropertyClass;
+ UHTMakefile.AddLazyObjectProperty(UnrealSourceFile, Result);
return Result;
}
@@ -605,15 +652,17 @@ namespace
if (VarProperty.PropertyClass->IsChildOf(UClass::StaticClass()))
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UAssetClassProperty(FObjectInitializer());
+ UAssetClassProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UAssetClassProperty(FObjectInitializer());
Result->MetaClass = VarProperty.MetaClass;
Result->PropertyClass = VarProperty.PropertyClass;
+ UHTMakefile.AddAssetClassProperty(UnrealSourceFile, Result);
return Result;
}
else
{
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UAssetObjectProperty(FObjectInitializer());
+ UAssetObjectProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UAssetObjectProperty(FObjectInitializer());
Result->PropertyClass = VarProperty.PropertyClass;
+ UHTMakefile.AddAssetObjectProperty(UnrealSourceFile, Result);
return Result;
}
@@ -622,19 +671,32 @@ namespace
check(VarProperty.PropertyClass);
check(VarProperty.PropertyClass->HasAnyClassFlags(CLASS_Interface));
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInterfaceProperty(FObjectInitializer());
+ UInterfaceProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UInterfaceProperty(FObjectInitializer());
Result->InterfaceClass = VarProperty.PropertyClass;
+ UHTMakefile.AddInterfaceProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Name:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UNameProperty(FObjectInitializer());
+ {
+ UNameProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UNameProperty(FObjectInitializer());
+ UHTMakefile.AddNameProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_String:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UStrProperty(FObjectInitializer());
+ {
+ UStrProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UStrProperty(FObjectInitializer());
+ UHTMakefile.AddStrProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Text:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UTextProperty(FObjectInitializer());
+ {
+ UTextProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UTextProperty(FObjectInitializer());
+ UHTMakefile.AddTextProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_Struct:
{
@@ -643,16 +705,25 @@ namespace
VarProperty.PropertyFlags |= CPF_ContainsInstancedReference;
}
- auto* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UStructProperty(FObjectInitializer());
+ UStructProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UStructProperty(FObjectInitializer());
Result->Struct = VarProperty.Struct;
+ UHTMakefile.AddStructProperty(UnrealSourceFile, Result);
return Result;
}
case CPT_Delegate:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UDelegateProperty(FObjectInitializer());
+ {
+ UDelegateProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UDelegateProperty(FObjectInitializer());
+ UHTMakefile.AddDelegateProperty(UnrealSourceFile, Result);
+ return Result;
+ }
case CPT_MulticastDelegate:
- return new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UMulticastDelegateProperty(FObjectInitializer());
+ {
+ UMulticastDelegateProperty* Result = new (EC_InternalUseOnlyConstructor, Scope, Name, ObjectFlags) UMulticastDelegateProperty(FObjectInitializer());
+ UHTMakefile.AddMulticastDelegateProperty(UnrealSourceFile, Result);
+ return Result;
+ }
default:
FError::Throwf(TEXT("Unknown property type %i"), (uint8)VarProperty.Type);
@@ -670,7 +741,7 @@ namespace
*/
void ValidateMetaDataFormat(UField* Field, const FString& InKey, const FString& InValue)
{
- switch ((ECheckedMetadataSpecifier)Algo::FindSortedStringCaseInsensitive(*InKey, GCheckedMetadataSpecifierStrings, ARRAY_COUNT(GCheckedMetadataSpecifierStrings)))
+ switch ((ECheckedMetadataSpecifier)Algo::FindSortedStringCaseInsensitive(*InKey, GCheckedMetadataSpecifierStrings))
{
default:
{
@@ -1038,9 +1109,10 @@ void AddModuleRelativePathToMetadata(UField* Type, TMap &MetaDat
//
// Compile an enumeration definition.
//
-UEnum* FHeaderParser::CompileEnum(FUnrealSourceFile& SourceFile)
+UEnum* FHeaderParser::CompileEnum()
{
- auto Scope = SourceFile.GetScope();
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
+ auto Scope = CurrentSourceFile->GetScope();
CheckAllow( TEXT("'Enum'"), ALLOW_TypeDecl );
@@ -1107,13 +1179,12 @@ UEnum* FHeaderParser::CompileEnum(FUnrealSourceFile& SourceFile)
}
ParseFieldMetaData(EnumToken.MetaData, EnumToken.Identifier);
-
// Create enum definition.
- UEnum* Enum = new(EC_InternalUseOnlyConstructor, SourceFile.GetPackage(), EnumToken.Identifier, RF_Public) UEnum(FObjectInitializer());
+ UEnum* Enum = new(EC_InternalUseOnlyConstructor, CurrentSourceFile->GetPackage(), EnumToken.Identifier, RF_Public) UEnum(FObjectInitializer());
Scope->AddType(Enum);
- AddTypeDefinition(SourceFile, Enum, InputLine);
-
+ AddTypeDefinition(UHTMakefile, CurrentSourceFile, Enum, InputLine);
+ UHTMakefile.AddEnum(CurrentSourceFile, Enum);
// Validate the metadata for the enum
ValidateMetaDataFormat(Enum, EnumToken.MetaData);
@@ -1133,6 +1204,7 @@ UEnum* FHeaderParser::CompileEnum(FUnrealSourceFile& SourceFile)
}
GEnumUnderlyingTypes.Add(Enum, CPT_Byte);
+ UHTMakefile.AddGEnumUnderlyingType(CurrentSourceFile, Enum, CPT_Byte);
}
// Get opening brace.
@@ -1618,9 +1690,10 @@ EAccessSpecifier FHeaderParser::ParseAccessProtectionSpecifier(FToken& Token)
/**
* Compile a struct definition.
*/
-UScriptStruct* FHeaderParser::CompileStructDeclaration(FClasses& AllClasses, FUnrealSourceFile& SourceFile)
+UScriptStruct* FHeaderParser::CompileStructDeclaration(FClasses& AllClasses)
{
- auto Scope = SourceFile.GetScope();
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
+ auto Scope = CurrentSourceFile->GetScope();
// Make sure structs can be declared here.
CheckAllow( TEXT("'struct'"), ALLOW_TypeDecl );//@TODO: UCREMOVAL: After the switch: Make this require global scope
@@ -1668,7 +1741,7 @@ UScriptStruct* FHeaderParser::CompileStructDeclaration(FClasses& AllClasses, FUn
// Process the list of specifiers
for (const FPropertySpecifier& Specifier : SpecifiersFound)
{
- switch ((EStructSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GStructSpecifierStrings, ARRAY_COUNT(GStructSpecifierStrings)))
+ switch ((EStructSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GStructSpecifierStrings))
{
default:
{
@@ -1834,14 +1907,14 @@ UScriptStruct* FHeaderParser::CompileStructDeclaration(FClasses& AllClasses, FUn
{
StructFlags |= (BaseStruct->StructFlags&STRUCT_Inherit);
}
-
// Create.
- UScriptStruct* Struct = new(EC_InternalUseOnlyConstructor, SourceFile.GetPackage(), *EffectiveStructName, RF_Public) UScriptStruct(FObjectInitializer(), BaseStruct);
+ UScriptStruct* Struct = new(EC_InternalUseOnlyConstructor, CurrentSourceFile->GetPackage(), *EffectiveStructName, RF_Public) UScriptStruct(FObjectInitializer(), BaseStruct);
+ UHTMakefile.AddScriptStruct(CurrentSourceFile, Struct);
Scope->AddType(Struct);
- FScope::AddTypeScope(Struct, &SourceFile.GetScope().Get());
+ FScope::AddTypeScope(Struct, &CurrentSourceFile->GetScope().Get(), CurrentSourceFile, UHTMakefile);
- AddTypeDefinition(SourceFile, Struct, InputLine);
+ AddTypeDefinition(UHTMakefile, CurrentSourceFile, Struct, InputLine);
AddModuleRelativePathToMetadata(Struct, MetaData);
@@ -1884,7 +1957,8 @@ UScriptStruct* FHeaderParser::CompileStructDeclaration(FClasses& AllClasses, FUn
StructToken.Struct = Struct;
// add this struct to the compiler's persistent tracking system
- GScriptHelper.AddClassData(StructToken.Struct);
+ FClassMetaData* ClassMetaData = GScriptHelper.AddClassData(StructToken.Struct, UHTMakefile, CurrentSourceFile);
+ UHTMakefile.AddGScriptHelperEntry(CurrentSourceFile, Struct, ClassMetaData);
}
int32 SavedLineNumber = InputLine;
@@ -1927,7 +2001,7 @@ UScriptStruct* FHeaderParser::CompileStructDeclaration(FClasses& AllClasses, FUn
Struct->StructMacroDeclaredLineNumber = InputLine;
RequireSymbol(TEXT("("), TEXT("'struct'"));
- CompileVersionDeclaration(SourceFile, Struct);
+ CompileVersionDeclaration(Struct);
RequireSymbol(TEXT(")"), TEXT("'struct'"));
@@ -2480,8 +2554,10 @@ void FHeaderParser::VerifyRepNotifyCallbacks( UClass* TargetClass )
//
// Process a compiler directive.
//
-void FHeaderParser::CompileDirective(FClasses& AllClasses, FUnrealSourceFile& SourceFile)
+void FHeaderParser::CompileDirective(FClasses& AllClasses)
{
+ FUnrealSourceFile* CurrentSourceFilePtr = GetCurrentSourceFile();
+ TSharedRef CurrentSourceFile = CurrentSourceFilePtr->AsShared();
FToken Directive;
int32 LineAtStartOfDirective = InputLine;
@@ -2516,7 +2592,7 @@ void FHeaderParser::CompileDirective(FClasses& AllClasses, FUnrealSourceFile& So
}
else if (Directive.Matches(TEXT("include")))
{
- FString ExpectedHeaderName = SourceFile.GetGeneratedHeaderFilename();
+ FString ExpectedHeaderName = CurrentSourceFile->GetGeneratedHeaderFilename();
FToken IncludeName;
if (GetToken(IncludeName) && (IncludeName.TokenType == TOKEN_Const) && (IncludeName.Type == CPT_String))
{
@@ -2680,7 +2756,7 @@ FIndexRange* ParsedVarIndexRange
bool bSeenBlueprintEditSpecifier = false;
for (const FPropertySpecifier& Specifier : SpecifiersFound)
{
- EVariableSpecifier SpecID = (EVariableSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GVariableSpecifierStrings, ARRAY_COUNT(GVariableSpecifierStrings));
+ EVariableSpecifier SpecID = (EVariableSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GVariableSpecifierStrings);
if (VariableCategory == EVariableCategory::Member)
{
switch (SpecID)
@@ -3279,7 +3355,9 @@ FIndexRange* ParsedVarIndexRange
OriginalVarTypeFlags |= VarProperty.PropertyFlags & (CPF_ContainsInstancedReference | CPF_InstancedReference); // propagate these to the array, we will fix them later
OriginalVarTypeFlags |= MapKeyType .PropertyFlags & (CPF_ContainsInstancedReference | CPF_InstancedReference); // propagate these to the array, we will fix them later
VarType.PropertyFlags = OriginalVarTypeFlags;
- VarProperty.MapKeyProp = MakeShareable(new FToken(MapKeyType));
+ FToken* MapKeyProp = new FToken(MapKeyType);
+ VarProperty.MapKeyProp = MakeShareable(MapKeyProp);
+ UHTMakefile.AddToken(GetCurrentSourceFile(), MapKeyProp);
VarProperty.MapKeyProp->PropertyFlags = OriginalVarTypeFlags;
FToken CloseTemplateToken;
@@ -3877,6 +3955,7 @@ UProperty* FHeaderParser::GetVarNameAndDim
{
check(Scope);
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
EObjectFlags ObjectFlags = RF_Public;
if (VariableCategory == EVariableCategory::Member && CurrentAccessSpecifier == ACCESS_Private)
{
@@ -4107,6 +4186,7 @@ UProperty* FHeaderParser::GetVarNameAndDim
if (VarProperty.ArrayType == EArrayType::Dynamic)
{
Array = new (EC_InternalUseOnlyConstructor, Scope, PropertyName, ObjectFlags) UArrayProperty(FObjectInitializer());
+ UHTMakefile.AddArrayProperty(CurrentSourceFile, Array);
NewScope = Array;
ObjectFlags = RF_Public;
}
@@ -4117,12 +4197,13 @@ UProperty* FHeaderParser::GetVarNameAndDim
else if (VarProperty.MapKeyProp.IsValid())
{
Map = new (EC_InternalUseOnlyConstructor, Scope, PropertyName, ObjectFlags) UMapProperty(FObjectInitializer());
+ UHTMakefile.AddMapProperty(CurrentSourceFile, Map);
NewScope = Map;
ObjectFlags = RF_Public;
- NewMapKeyProperty = CreateVariableProperty(*VarProperty.MapKeyProp, NewScope, *(PropertyName.ToString() + TEXT("_Key")), ObjectFlags, VariableCategory);
+ NewMapKeyProperty = CreateVariableProperty(*VarProperty.MapKeyProp, NewScope, *(PropertyName.ToString() + TEXT("_Key")), ObjectFlags, VariableCategory, UHTMakefile, CurrentSourceFile);
}
- NewProperty = CreateVariableProperty(VarProperty, NewScope, PropertyName, ObjectFlags, VariableCategory);
+ NewProperty = CreateVariableProperty(VarProperty, NewScope, PropertyName, ObjectFlags, VariableCategory, UHTMakefile, CurrentSourceFile);
auto PropagateFlags = [](uint64 FlagsToPropagate, FPropertyBase& From, UProperty* To) {
// Copy some of the property flags to the inner property.
@@ -4184,11 +4265,10 @@ UProperty* FHeaderParser::GetVarNameAndDim
VarProperty.TokenProperty = NewProperty;
FClassMetaData* ScopeData = GScriptHelper.FindClassData(Scope);
check(ScopeData);
- ScopeData->AddProperty(VarProperty);
+ ScopeData->AddProperty(VarProperty, UHTMakefile, CurrentSourceFile);
// if we had any metadata, add it to the class
AddMetaDataToClassData(VarProperty.TokenProperty, VarProperty.MetaData);
-
return NewProperty;
}
@@ -4199,7 +4279,7 @@ UProperty* FHeaderParser::GetVarNameAndDim
//
// Compile a declaration in Token. Returns 1 if compiled, 0 if not.
//
-bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile& SourceFile, FToken& Token)
+bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FToken& Token)
{
EAccessSpecifier AccessSpecifier = ParseAccessProtectionSpecifier(Token);
if (AccessSpecifier)
@@ -4241,7 +4321,7 @@ bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile&
FError::Throwf(TEXT("%s must occur inside the native interface definition"), Token.Identifier);
}
RequireSymbol(TEXT("("), Token.Identifier);
- CompileVersionDeclaration(SourceFile, GetCurrentClass());
+ CompileVersionDeclaration(GetCurrentClass());
RequireSymbol(TEXT(")"), Token.Identifier);
auto* ClassData = GetCurrentClassData();
@@ -4270,7 +4350,7 @@ bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile&
FError::Throwf(TEXT("%s must occur inside the interface definition"), Token.Identifier);
}
RequireSymbol(TEXT("("), Token.Identifier);
- CompileVersionDeclaration(SourceFile, GetCurrentClass());
+ CompileVersionDeclaration(GetCurrentClass());
RequireSymbol(TEXT(")"), Token.Identifier);
auto* ClassData = GetCurrentClassData();
@@ -4313,7 +4393,7 @@ bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile&
}
RequireSymbol(TEXT("("), Token.Identifier);
- CompileVersionDeclaration(SourceFile, GetCurrentClass());
+ CompileVersionDeclaration(GetCurrentClass());
RequireSymbol(TEXT(")"), Token.Identifier);
ClassData->SetGeneratedBodyLine(InputLine);
@@ -4340,19 +4420,19 @@ bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile&
if (Token.Matches(TEXT("UFUNCTION"), ESearchCase::CaseSensitive))
{
- CompileFunctionDeclaration(SourceFile, AllClasses);
+ CompileFunctionDeclaration(AllClasses);
return true;
}
if (Token.Matches(TEXT("UDELEGATE")))
{
- CompileDelegateDeclaration(SourceFile, AllClasses, Token.Identifier, EDelegateSpecifierAction::Parse);
+ CompileDelegateDeclaration(AllClasses, Token.Identifier, EDelegateSpecifierAction::Parse);
return true;
}
if (IsValidDelegateDeclaration(Token)) // Legacy delegate parsing - it didn't need a UDELEGATE
{
- CompileDelegateDeclaration(SourceFile, AllClasses, Token.Identifier);
+ CompileDelegateDeclaration(AllClasses, Token.Identifier);
return true;
}
@@ -4368,21 +4448,21 @@ bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile&
if (Token.Matches(TEXT("UENUM")))
{
// Enumeration definition.
- CompileEnum(SourceFile);
+ CompileEnum();
return true;
}
if (Token.Matches(TEXT("USTRUCT")))
{
// Struct definition.
- CompileStructDeclaration(AllClasses, SourceFile);
+ CompileStructDeclaration(AllClasses);
return true;
}
if (Token.Matches(TEXT("#")))
{
// Compiler directive.
- CompileDirective(AllClasses, SourceFile);
+ CompileDirective(AllClasses);
return true;
}
@@ -4614,12 +4694,14 @@ bool FHeaderParser::SafeMatchSymbol( const TCHAR* Match )
FClass* FHeaderParser::ParseClassNameDeclaration(FClasses& AllClasses, FString& DeclaredClassName, FString& RequiredAPIMacroIfPresent)
{
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
ParseNameWithPotentialAPIMacroPrefix(/*out*/ DeclaredClassName, /*out*/ RequiredAPIMacroIfPresent, TEXT("class"));
FClass* FoundClass = AllClasses.FindClass(*GetClassNameWithPrefixRemoved(*DeclaredClassName));
check(FoundClass);
- GScriptHelper.AddClassData(FoundClass);
+ FClassMetaData* ClassMetaData = GScriptHelper.AddClassData(FoundClass, UHTMakefile, CurrentSourceFile);
+ UHTMakefile.AddGScriptHelperEntry(CurrentSourceFile, FoundClass, ClassMetaData);
// Get parent class.
bool bSpecifiesParentClass = false;
@@ -4706,6 +4788,7 @@ FClass* FHeaderParser::ParseClassNameDeclaration(FClasses& AllClasses, FString&
void FHeaderParser::HandleOneInheritedClass(FClasses& AllClasses, UClass* Class, FString InterfaceName)
{
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
// Check for UInterface derived interface inheritance
if (UClass* Interface = AllClasses.FindScriptClass(InterfaceName))
{
@@ -4723,7 +4806,7 @@ void FHeaderParser::HandleOneInheritedClass(FClasses& AllClasses, UClass* Class,
{
FClassMetaData* ClassData = GScriptHelper.FindClassData(Class);
check(ClassData);
- ClassData->AddInheritanceParent(Interface);
+ ClassData->AddInheritanceParent(Interface, UHTMakefile, CurrentSourceFile);
}
}
else
@@ -4731,7 +4814,7 @@ void FHeaderParser::HandleOneInheritedClass(FClasses& AllClasses, UClass* Class,
// Non-UObject inheritance
FClassMetaData* ClassData = GScriptHelper.FindClassData(Class);
check(ClassData);
- ClassData->AddInheritanceParent(InterfaceName);
+ ClassData->AddInheritanceParent(InterfaceName, UHTMakefile, CurrentSourceFile);
}
}
@@ -4819,7 +4902,9 @@ void FHeaderParser::CompileClassDeclaration(FClasses& AllClasses)
// Make sure our parent classes is parsed.
for (UClass* Temp = Class->GetSuperClass(); Temp; Temp = Temp->GetSuperClass())
{
- if (!(Temp->ClassFlags & (CLASS_Parsed | CLASS_Intrinsic)))
+ bool bIsParsed = !!(Temp->ClassFlags & CLASS_Parsed);
+ bool bIsIntrinsic = !!(Temp->ClassFlags & CLASS_Intrinsic);
+ if (!(bIsParsed || bIsIntrinsic))
{
FError::Throwf(TEXT("'%s' can't be compiled: Parent class '%s' has errors"), *Class->GetName(), *Temp->GetName());
}
@@ -4834,7 +4919,7 @@ void FHeaderParser::CompileClassDeclaration(FClasses& AllClasses)
ClassData->SetPrologLine(PrologFinishLine);
ClassDeclarationData->MergeAndValidateClassFlags(DeclaredClassName, PrevClassFlags, Class, AllClasses);
- Class->SetFlags(RF_Native);
+ Class->SetInternalFlags(EInternalObjectFlags::Native);
// Class metadata
MetaData.Append(ClassDeclarationData->MetaData);
@@ -4873,7 +4958,7 @@ void FHeaderParser::CompileClassDeclaration(FClasses& AllClasses)
for (int32 ParentIndex = InheritanceParents.Num() - 1; ParentIndex >= 0; ParentIndex--)
{
// if this base class corresponds to an interface class, assign the vtable UProperty in the class's Interfaces map now...
- if (UClass* InheritedInterface = InheritanceParents[ParentIndex].InterfaceClass)
+ if (UClass* InheritedInterface = InheritanceParents[ParentIndex]->InterfaceClass)
{
if (FImplementedInterface* Found = Class->Interfaces.FindByPredicate([=](const FImplementedInterface& Impl) { return Impl.Class == InheritedInterface; }))
{
@@ -4974,6 +5059,7 @@ bool FHeaderParser::TryParseIInterfaceClass(FClasses& AllClasses)
*/
void FHeaderParser::CompileInterfaceDeclaration(FClasses& AllClasses)
{
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
// Start of an interface block. Since Interfaces and Classes are always at the same nesting level,
// whereever a class declaration is allowed, an interface declaration is also allowed.
CheckAllow( TEXT("'interface'"), ALLOW_Class );
@@ -5014,13 +5100,13 @@ void FHeaderParser::CompileInterfaceDeclaration(FClasses& AllClasses)
FError::Throwf(TEXT("Native classes cannot extend non-native classes") );
}
- InterfaceClass->SetFlags(RF_Native);
+ InterfaceClass->SetInternalFlags(EInternalObjectFlags::Native);
InterfaceClass->ClassFlags |= CLASS_Native;
// Process all of the interface specifiers
for (const FPropertySpecifier& Specifier : SpecifiersFound)
{
- switch ((EInterfaceSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GInterfaceSpecifierStrings, ARRAY_COUNT(GInterfaceSpecifierStrings)))
+ switch ((EInterfaceSpecifier)Algo::FindSortedStringCaseInsensitive(*Specifier.Key, GInterfaceSpecifierStrings))
{
default:
{
@@ -5056,7 +5142,8 @@ void FHeaderParser::CompileInterfaceDeclaration(FClasses& AllClasses)
}
// Try parsing metadata for the interface
- FClassMetaData* ClassData = GScriptHelper.AddClassData(InterfaceClass);
+ FClassMetaData* ClassData = GScriptHelper.AddClassData(InterfaceClass, UHTMakefile, CurrentSourceFile);
+ UHTMakefile.AddGScriptHelperEntry(CurrentSourceFile, InterfaceClass, ClassData);
check(ClassData);
ClassData->SetPrologLine(PrologFinishLine);
@@ -5210,12 +5297,11 @@ void FHeaderParser::ParseParameterList(FClasses& AllClasses, UFunction* Function
} while( MatchSymbol(TEXT(",")) );
RequireSymbol( TEXT(")"), TEXT("parameter list") );
}
-
-void FHeaderParser::CompileDelegateDeclaration(FUnrealSourceFile& SourceFile, FClasses& AllClasses, const TCHAR* DelegateIdentifier, EDelegateSpecifierAction::Type SpecifierAction)
+void FHeaderParser::CompileDelegateDeclaration(FClasses& AllClasses, const TCHAR* DelegateIdentifier, EDelegateSpecifierAction::Type SpecifierAction)
{
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
TMap MetaData;
-
- AddModuleRelativePathToMetadata(SourceFile, MetaData);
+ AddModuleRelativePathToMetadata(*CurrentSourceFile, MetaData);
FFuncInfo FuncInfo;
@@ -5326,8 +5412,10 @@ void FHeaderParser::CompileDelegateDeclaration(FUnrealSourceFile& SourceFile, FC
FuncInfo.MacroLine = InputLine;
auto* DelegateSignatureFunction = CreateDelegateFunction(FuncInfo);
+ UHTMakefile.AddDelegateFunction(CurrentSourceFile, DelegateSignatureFunction);
- GScriptHelper.AddClassData(DelegateSignatureFunction);
+ FClassMetaData* ClassMetaData = GScriptHelper.AddClassData(DelegateSignatureFunction, UHTMakefile, CurrentSourceFile);
+ UHTMakefile.AddGScriptHelperEntry(CurrentSourceFile, DelegateSignatureFunction, ClassMetaData);
DelegateSignatureFunction->FunctionFlags |= FuncInfo.FunctionFlags;
@@ -5407,13 +5495,13 @@ void FHeaderParser::CompileDelegateDeclaration(FUnrealSourceFile& SourceFile, FC
/**
* Parses and compiles a function declaration
*/
-void FHeaderParser::CompileFunctionDeclaration(FUnrealSourceFile& SourceFile, FClasses& AllClasses)
+void FHeaderParser::CompileFunctionDeclaration(FClasses& AllClasses)
{
CheckAllow(TEXT("'Function'"), ALLOW_Function);
+ FUnrealSourceFile* CurrentSourceFile = GetCurrentSourceFile();
TMap MetaData;
-
- AddModuleRelativePathToMetadata(SourceFile, MetaData);
+ AddModuleRelativePathToMetadata(*CurrentSourceFile, MetaData);
// New-style UFUNCTION() syntax
TArray SpecifiersFound;
@@ -5691,8 +5779,10 @@ void FHeaderParser::CompileFunctionDeclaration(FUnrealSourceFile& SourceFile, FC
}
auto* TopFunction = CreateFunction(FuncInfo);
+ UHTMakefile.AddFunction(CurrentSourceFile, TopFunction);
- GScriptHelper.AddClassData(TopFunction);
+ FClassMetaData* ClassMetaData = GScriptHelper.AddClassData(TopFunction, UHTMakefile, CurrentSourceFile);
+ UHTMakefile.AddGScriptHelperEntry(CurrentSourceFile, TopFunction, ClassMetaData);
TopFunction->FunctionFlags |= FuncInfo.FunctionFlags;
@@ -6139,7 +6229,6 @@ void FHeaderParser::CompileVariableDeclaration(FClasses& AllClasses, UStruct* St
// Get variable type.
FPropertyBase OriginalProperty(CPT_None);
-
FIndexRange TypeRange;
GetVarType( AllClasses, &FScope::GetTypeScope(Struct).Get(), OriginalProperty, DisallowFlags, /*OuterPropertyType=*/ NULL, EPropertyDeclarationStyle::UPROPERTY, EVariableCategory::Member, &TypeRange );
OriginalProperty.PropertyFlags |= EdFlags;
@@ -6286,7 +6375,7 @@ void FHeaderParser::CompileVariableDeclaration(FClasses& AllClasses, UStruct* St
// Compile a statement: Either a declaration or a command.
// Returns 1 if success, 0 if end of file.
//
-bool FHeaderParser::CompileStatement(FClasses& AllClasses, FUnrealSourceFile& SourceFile)
+bool FHeaderParser::CompileStatement(FClasses& AllClasses)
{
// Get a token and compile it.
FToken Token;
@@ -6295,7 +6384,7 @@ bool FHeaderParser::CompileStatement(FClasses& AllClasses, FUnrealSourceFile& So
// End of file.
return false;
}
- else if (!CompileDeclaration(AllClasses, SourceFile, Token))
+ else if (!CompileDeclaration(AllClasses, Token))
{
FError::Throwf(TEXT("'%s': Bad command or expression"), Token.Identifier );
}
@@ -6433,17 +6522,21 @@ void FHeaderParser::FinalizeScriptExposedFunctions(UClass* Class)
// Parses the header associated with the specified class.
// Returns result enumeration.
//
-ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrealSourceFile& SourceFile)
+ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrealSourceFile* SourceFile)
{
- if (SourceFile.IsParsed())
+ SetCurrentSourceFile(SourceFile);
+ UHTMakefile.AddToHeaderOrder(SourceFile);
+ NameLookupCPP.SetCurrentSourceFile(SourceFile);
+ FUnrealSourceFile* CurrentSourceFile = SourceFile;
+ if (CurrentSourceFile->IsParsed())
{
return ECompilationResult::Succeeded;
}
- SourceFile.MarkAsParsed();
+ CurrentSourceFile->MarkAsParsed();
// Early-out if this class has previously failed some aspect of parsing
- if (FailedFilesAnnotation.Get(&SourceFile))
+ if (FailedFilesAnnotation.Get(CurrentSourceFile))
{
return ECompilationResult::OtherCompilationError;
}
@@ -6462,16 +6555,16 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
if (FParse::Param(FCommandLine::Get(), TEXT("VERBOSE")))
{
// Message.
- Warn->Logf(TEXT("Parsing %s"), *SourceFile.GetFilename());
+ Warn->Logf(TEXT("Parsing %s"), *CurrentSourceFile->GetFilename());
}
// Init compiler variables.
- ResetParser(*SourceFile.GetContent());
+ ResetParser(*CurrentSourceFile->GetContent());
// Init nesting.
NestLevel = 0;
TopNest = NULL;
- PushNest(NEST_GlobalScope, nullptr, &SourceFile);
+ PushNest(NEST_GlobalScope, nullptr, CurrentSourceFile);
// C++ classes default to private access level
CurrentAccessSpecifier = ACCESS_Private;
@@ -6487,7 +6580,7 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
#endif
{
// Parse entire program.
- while (CompileStatement(AllClasses, SourceFile))
+ while (CompileStatement(AllClasses))
{
bEmptyFile = false;
@@ -6498,7 +6591,7 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
PopNest(NEST_GlobalScope, TEXT("Global scope"));
- auto ScopeTypeIterator = SourceFile.GetScope()->GetTypeIterator();
+ auto ScopeTypeIterator = CurrentSourceFile->GetScope()->GetTypeIterator();
while (ScopeTypeIterator.MoveNext())
{
auto* Type = *ScopeTypeIterator;
@@ -6548,7 +6641,7 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
// First-pass success.
Result = ECompilationResult::Succeeded;
- for (auto* Class : SourceFile.GetDefinedClasses())
+ for (auto* Class : CurrentSourceFile->GetDefinedClasses())
{
PostParsingClassSetup(Class);
@@ -6564,11 +6657,11 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
bNoExportClassesOnly = bNoExportClassesOnly && Class->HasAnyClassFlags(CLASS_NoExport);
}
- check(SourceFile.IsParsed());
+ check(CurrentSourceFile->IsParsed());
if (!bSpottedAutogeneratedHeaderInclude && !bEmptyFile && !bNoExportClassesOnly)
{
- const FString ExpectedHeaderName = SourceFile.GetGeneratedHeaderFilename();
+ const FString ExpectedHeaderName = CurrentSourceFile->GetGeneratedHeaderFilename();
FError::Throwf(TEXT("Expected an include at the top of the header: '#include \"%s\"'"), *ExpectedHeaderName);
}
}
@@ -6578,7 +6671,7 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
if (NestLevel == 0)
{
// Pushing nest so there is a file context for this error.
- PushNest(NEST_GlobalScope, nullptr, &SourceFile);
+ PushNest(NEST_GlobalScope, nullptr, CurrentSourceFile);
}
// Handle compiler error.
@@ -6590,7 +6683,7 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
Warn->Log(ELogVerbosity::Error, ErrorMsg);
}
- FailedFilesAnnotation.Set(&SourceFile);
+ FailedFilesAnnotation.Set(CurrentSourceFile);
Result = GCompilationResult;
}
#endif
@@ -6602,16 +6695,16 @@ ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrea
Global functions.
-----------------------------------------------------------------------------*/
-ECompilationResult::Type FHeaderParser::ParseRestOfModulesSourceFiles(FClasses& AllClasses, UPackage* ModulePackage, FHeaderParser& HeaderParser)
+ECompilationResult::Type FHeaderParser::ParseRestOfModulesSourceFiles(FClasses& AllClasses, UPackage* ModulePackage, FHeaderParser& HeaderParser, FUHTMakefile& UHTMakefile)
{
for (auto& Pair : GUnrealSourceFilesMap)
{
- FUnrealSourceFile& SourceFile = Pair.Value.Get();
+ FUnrealSourceFile* SourceFile = &Pair.Value.Get();
- if (SourceFile.GetPackage() == ModulePackage && (!SourceFile.IsParsed() || SourceFile.GetDefinedClassesCount() == 0))
+ if (SourceFile->GetPackage() == ModulePackage && (!SourceFile->IsParsed() || SourceFile->GetDefinedClassesCount() == 0))
{
ECompilationResult::Type Result;
- if ((Result = ParseHeaders(AllClasses, HeaderParser, SourceFile, true)) != ECompilationResult::Succeeded)
+ if ((Result = ParseHeaders(AllClasses, HeaderParser, SourceFile, true, UHTMakefile)) != ECompilationResult::Succeeded)
{
return Result;
}
@@ -6622,22 +6715,23 @@ ECompilationResult::Type FHeaderParser::ParseRestOfModulesSourceFiles(FClasses&
}
// Parse Class's annotated headers and optionally its child classes.
-ECompilationResult::Type FHeaderParser::ParseHeaders(FClasses& AllClasses, FHeaderParser& HeaderParser, FUnrealSourceFile& SourceFile, bool bParseSubclasses)
+ECompilationResult::Type FHeaderParser::ParseHeaders(FClasses& AllClasses, FHeaderParser& HeaderParser, FUnrealSourceFile* SourceFile, bool bParseSubclasses, FUHTMakefile& UHTMakefile)
{
ECompilationResult::Type Result = ECompilationResult::Succeeded;
- if (SourceFile.AreDependenciesResolved())
+ if (SourceFile->AreDependenciesResolved())
{
return Result;
}
- SourceFile.MarkDependenciesResolved();
+ SourceFile->MarkDependenciesResolved();
TArray SourceFilesRequired;
- for (auto& Include : SourceFile.GetIncludes())
+ static const FString ObjectHeader = FString(TEXT("Object.h"));
+ for (auto& Include : SourceFile->GetIncludes())
{
- if (Include.GetId() == "Object.h")
+ if (Include.GetId() == ObjectHeader)
{
continue;
}
@@ -6650,7 +6744,7 @@ ECompilationResult::Type FHeaderParser::ParseHeaders(FClasses& AllClasses, FHead
}
}
- auto Classes = SourceFile.GetDefinedClasses();
+ auto Classes = SourceFile->GetDefinedClasses();
for (auto* Class : Classes)
{
@@ -6659,19 +6753,20 @@ ECompilationResult::Type FHeaderParser::ParseHeaders(FClasses& AllClasses, FHead
SourceFilesRequired.Add(>ypeDefinitionInfoMap[ParentClass]->GetUnrealSourceFile());
}
}
+ UHTMakefile.GetHeaderDescriptor(SourceFile).AddPrerequesites(SourceFilesRequired);
for (auto* RequiredFile : SourceFilesRequired)
{
- SourceFile.GetScope()->IncludeScope(&RequiredFile->GetScope().Get());
+ SourceFile->GetScope()->IncludeScope(&RequiredFile->GetScope().Get());
- ECompilationResult::Type SuperClassParseResult = ParseHeaders(AllClasses, HeaderParser, *RequiredFile, true);
+ ECompilationResult::Type SuperClassParseResult = ParseHeaders(AllClasses, HeaderParser, RequiredFile, true, UHTMakefile);
if (SuperClassParseResult == ECompilationResult::Succeeded)
{
continue;
}
- SuperClassParseResult = ParseHeaders(AllClasses, HeaderParser, *RequiredFile, false);
+ SuperClassParseResult = ParseHeaders(AllClasses, HeaderParser, RequiredFile, false, UHTMakefile);
if (SuperClassParseResult != ECompilationResult::Succeeded)
{
@@ -6769,6 +6864,8 @@ void FHeaderParser::ExportNativeHeaders(
#if WITH_HOT_RELOAD_CTORS
, bool bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
+ , FUHTMakefile& UHTMakefile
+ , const FManifestModule& Module
)
{
// Build a list of header filenames
@@ -6776,7 +6873,6 @@ void FHeaderParser::ExportNativeHeaders(
new (ClassHeaderFilenames) FString();
auto SourceFiles = GetSourceFilesWithInheritanceOrdering(CurrentPackage, AllClasses);
-
if (SourceFiles.Num() > 0)
{
const static bool bQuiet = !FParse::Param(FCommandLine::Get(),TEXT("VERBOSE"));
@@ -6802,7 +6898,19 @@ void FHeaderParser::ExportNativeHeaders(
UE_LOG(LogCompile, Warning, TEXT("Exporting native class declarations"));
}
}
+ UHTMakefile.StartExporting();
+
+ FName ModuleName = FName(*Module.Name);
+ bool bNeedsRegeneration = Module.NeedsRegeneration();
+ bool bUHTMakefileContainsModuleData = UHTMakefile.HasModule(ModuleName);
+ bool bLoadFromMakefile = !bNeedsRegeneration && bUHTMakefileContainsModuleData;
+ if (bLoadFromMakefile)
+ {
+ UHTMakefile.LoadModuleData(ModuleName, Module);
+ }
+ else
+ {
// Export native class definitions to package header files.
FNativeClassHeaderGenerator(
CurrentPackage,
@@ -6812,15 +6920,19 @@ void FHeaderParser::ExportNativeHeaders(
#if WITH_HOT_RELOAD_CTORS
, bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
+ , UHTMakefile
);
}
+ UHTMakefile.StopExporting();
+}
}
-FHeaderParser::FHeaderParser(FFeedbackContext* InWarn)
+FHeaderParser::FHeaderParser(FFeedbackContext* InWarn, FUHTMakefile& InUHTMakefile)
: FBaseParser ()
, Warn (InWarn)
, bSpottedAutogeneratedHeaderInclude(false)
, TopNest (NULL)
+, UHTMakefile(InUHTMakefile)
{
FScriptLocation::Compiler = this;
@@ -6916,19 +7028,18 @@ ECompilationResult::Type FHeaderParser::ParseAllHeadersInside(
#if WITH_HOT_RELOAD_CTORS
, bool bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
-)
+ , FUHTMakefile& UHTMakefile
+ )
{
// Disable loading of objects outside of this package (or more exactly, objects which aren't UFields, CDO, or templates)
TGuardValue AutoRestoreVerifyObjectRefsFlag(GVerifyObjectReferencesOnly, true);
-
+ UHTMakefile.SetCurrentModuleName(FName(*Module.Name));
// Create the header parser and register it as the warning context.
// Note: This must be declared outside the try block, since the catch block will log into it.
- FHeaderParser HeaderParser(Warn);
+ FHeaderParser HeaderParser(Warn, UHTMakefile);
HeaderParser.CurrentlyParsedModule = &Module;
Warn->SetContext(&HeaderParser);
- // Set up a filename for the error context if we don't even get as far parsing a class
- HeaderParser.Filename = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*GTypeDefinitionInfoMap[ModuleClasses.GetRootClass()]->GetUnrealSourceFile().GetFilename());
// Hierarchically parse all classes.
ECompilationResult::Type Result = ECompilationResult::Succeeded;
@@ -6936,24 +7047,43 @@ ECompilationResult::Type FHeaderParser::ParseAllHeadersInside(
try
#endif
{
- for (auto* SourceFilePtr : GPublicSourceFileSet)
+ UHTMakefile.StartLoading();
+ FName ModuleName = FName(*Module.Name);
+ UHTMakefile.SetCurrentModuleName(ModuleName);
+ bool bNeedsRegeneration = Module.NeedsRegeneration();
+ bool bUHTMakefileContainsModuleData = UHTMakefile.HasModule(ModuleName);
+ bool bLoadFromMakefile = !bNeedsRegeneration && bUHTMakefileContainsModuleData;
+ if (bLoadFromMakefile)
{
- FUnrealSourceFile& SourceFile = *SourceFilePtr;
+ UHTMakefile.LoadModuleData(ModuleName, Module);
+ }
+ else
+ {
+ // Set up a filename for the error context if we don't even get as far parsing a class
+ FClass* RootClass = ModuleClasses.GetRootClass();
+ const TSharedRef& TypeDefinitionInfo = GTypeDefinitionInfoMap[RootClass];
+ const FUnrealSourceFile& RootSourceFile = TypeDefinitionInfo->GetUnrealSourceFile();
+ const FString& RootFilename = RootSourceFile.GetFilename();
- if (SourceFile.GetPackage() == CurrentPackage && (!SourceFile.IsParsed() || SourceFile.GetDefinedClassesCount() == 0))
+ HeaderParser.Filename = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*RootFilename);
+
+ for (FUnrealSourceFile* SourceFile : GPublicSourceFileSet)
{
- Result = ParseHeaders(ModuleClasses, HeaderParser, SourceFile, true);
- if (Result != ECompilationResult::Succeeded)
+ if (SourceFile->GetPackage() == CurrentPackage && (!SourceFile->IsParsed() || SourceFile->GetDefinedClassesCount() == 0))
{
- return Result;
+ Result = ParseHeaders(ModuleClasses, HeaderParser, SourceFile, true, UHTMakefile);
+ if (Result != ECompilationResult::Succeeded)
+ {
+ return Result;
+ }
}
}
+ if (Result == ECompilationResult::Succeeded)
+ {
+ Result = FHeaderParser::ParseRestOfModulesSourceFiles(ModuleClasses, CurrentPackage, HeaderParser, UHTMakefile);
+ }
}
-
- if (Result == ECompilationResult::Succeeded)
- {
- Result = FHeaderParser::ParseRestOfModulesSourceFiles(ModuleClasses, CurrentPackage, HeaderParser);
- }
+ UHTMakefile.StopLoading();
// Export the autogenerated code wrappers
if (Result == ECompilationResult::Succeeded)
@@ -6973,7 +7103,9 @@ ECompilationResult::Type FHeaderParser::ParseAllHeadersInside(
#if WITH_HOT_RELOAD_CTORS
, bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
- );
+ , UHTMakefile
+ , Module
+ );
}
GHeaderCodeGenTime += ExportTime;
@@ -6989,7 +7121,7 @@ ECompilationResult::Type FHeaderParser::ParseAllHeadersInside(
}
}
#if !PLATFORM_EXCEPTIONS_DISABLED
- catch( TCHAR* ErrorMsg )
+ catch (TCHAR* ErrorMsg)
{
Warn->Log(ELogVerbosity::Error, ErrorMsg);
Result = GCompilationResult;
@@ -7896,8 +8028,10 @@ void FHeaderParser::SkipDeprecatedMacroIfNecessary()
RequireSymbol(TEXT(")"), TEXT("DEPRECATED macro"));
}
-void FHeaderParser::CompileVersionDeclaration(FUnrealSourceFile& SourceFile, UStruct* Struct)
+void FHeaderParser::CompileVersionDeclaration(UStruct* Struct)
{
+ FUnrealSourceFile* CurrentSourceFilePtr = GetCurrentSourceFile();
+ TSharedRef CurrentSourceFile = CurrentSourceFilePtr->AsShared();
// Do nothing if we're at the end of file.
FToken Token;
if (!GetToken(Token, true, ESymbolParseOption::Normal))
@@ -7917,7 +8051,7 @@ void FHeaderParser::CompileVersionDeclaration(FUnrealSourceFile& SourceFile, USt
if (Token.TokenType == ETokenType::TOKEN_Symbol
&& !FCString::Stricmp(Token.Identifier, TEXT(")")))
{
- SourceFile.GetGeneratedCodeVersions().FindOrAdd(Struct) = Version;
+ CurrentSourceFile->GetGeneratedCodeVersions().FindOrAdd(Struct) = Version;
UngetToken(Token);
return;
}
@@ -7925,7 +8059,7 @@ void FHeaderParser::CompileVersionDeclaration(FUnrealSourceFile& SourceFile, USt
// Overwrite with version specified by macro.
Version = ToGeneratedCodeVersion(Token.Identifier);
- SourceFile.GetGeneratedCodeVersions().FindOrAdd(Struct) = Version;
+ CurrentSourceFile->GetGeneratedCodeVersions().FindOrAdd(Struct) = Version;
}
void FHeaderParser::ResetClassData()
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.h b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.h
index 1c635eacb677..9ef93a277900 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderParser.h
@@ -13,6 +13,7 @@ class FClass;
class FClasses;
class FScope;
class FHeaderProvider;
+class FUHTMakefile;
extern double GPluginOverheadTime;
extern double GHeaderCodeGenTime;
@@ -156,6 +157,7 @@ public:
#if WITH_HOT_RELOAD_CTORS
, bool bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
+ , FUHTMakefile& UHTMakefile
);
// Performs a preliminary parse of the text in the specified buffer, pulling out:
@@ -205,7 +207,7 @@ public:
*
* @return Result enumeration.
*/
- static ECompilationResult::Type ParseHeaders(FClasses& AllClasses, FHeaderParser& HeaderParser, FUnrealSourceFile& SourceFile, bool bParseSubclasses);
+ static ECompilationResult::Type ParseHeaders(FClasses& AllClasses, FHeaderParser& HeaderParser, FUnrealSourceFile* SourceFile, bool bParseSubclasses, FUHTMakefile& UHTMakefile);
protected:
friend struct FScriptLocation;
@@ -216,6 +218,9 @@ protected:
// Filename currently being parsed
FString Filename;
+ // Makefile to which parsing intermediate data will be saved.
+ FUHTMakefile& UHTMakefile;
+
// Was the first include in the file a validly formed auto-generated header include?
bool bSpottedAutogeneratedHeaderInclude;
@@ -252,7 +257,12 @@ protected:
*/
FUnrealSourceFile* GetCurrentSourceFile() const
{
- return GetCurrentFileScope()->GetSourceFile();
+ return CurrentSourceFile;
+ }
+
+ void SetCurrentSourceFile(FUnrealSourceFile* UnrealSourceFile)
+ {
+ CurrentSourceFile = UnrealSourceFile;
}
/**
@@ -382,7 +392,7 @@ protected:
protected:
// Constructor.
- FHeaderParser(FFeedbackContext* InWarn);
+ FHeaderParser(FFeedbackContext* InWarn, FUHTMakefile& InUHTMakefile);
~FHeaderParser()
{
@@ -411,13 +421,14 @@ protected:
/**
* Parse rest of the module's source files.
*
- * @param AllClasses the class tree containing all classes in the current package
- * @param ModulePackage current package
- * @param HeaderParser the header parser
+ * @param AllClasses The class tree containing all classes in the current package.
+ * @param ModulePackage Current package.
+ * @param HeaderParser The header parser.
+ * @param UHTMakefile Makefile to which parsing data is saved.
*
* @return Result enumeration.
*/
- static ECompilationResult::Type ParseRestOfModulesSourceFiles(FClasses& AllClasses, UPackage* ModulePackage, FHeaderParser& HeaderParser);
+ static ECompilationResult::Type ParseRestOfModulesSourceFiles(FClasses& AllClasses, UPackage* ModulePackage, FHeaderParser& HeaderParser, FUHTMakefile& UHTMakefile);
//@TODO: Remove this method
static void ParseClassName(const TCHAR* Temp, FString& ClassName);
@@ -431,8 +442,10 @@ protected:
/**
* Begins the process of exporting C++ class declarations for native classes in the specified package
*
- * @param CurrentPackage the package being compiled
- * @param AllClasses the class tree for CurrentPackage
+ * @param CurrentPackage The package being compiled.
+ * @param AllClasses The class tree for CurrentPackage.
+ * @param UHTMakefile Makefile to which parsing data is saved.
+ * @param Module Currently exported module.
*/
static void ExportNativeHeaders(
UPackage* CurrentPackage,
@@ -441,6 +454,8 @@ protected:
#if WITH_HOT_RELOAD_CTORS
, bool bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
+ , FUHTMakefile& UHTMakefile
+ , const FManifestModule& Module
);
// FContextSupplier interface.
@@ -456,12 +471,12 @@ protected:
*
* @returns Compilation result enum.
*/
- ECompilationResult::Type ParseHeader(FClasses& AllClasses, FUnrealSourceFile& SourceFile);
- void CompileDirective(FClasses& AllClasses, FUnrealSourceFile& SourceFile);
+ ECompilationResult::Type ParseHeader(FClasses& AllClasses, FUnrealSourceFile* SourceFile);
+ void CompileDirective(FClasses& AllClasses);
void FinalizeScriptExposedFunctions(UClass* Class);
- UEnum* CompileEnum(FUnrealSourceFile& SourceFile);
- UScriptStruct* CompileStructDeclaration(FClasses& AllClasses, FUnrealSourceFile& SourceFile);
- bool CompileDeclaration(FClasses& AllClasses, FUnrealSourceFile& SourceFile, FToken& Token);
+ UEnum* CompileEnum();
+ UScriptStruct* CompileStructDeclaration(FClasses& AllClasses);
+ bool CompileDeclaration(FClasses& AllClasses, FToken& Token);
/** Skip C++ (noexport) declaration. */
bool SkipDeclaration(FToken& Token);
@@ -496,15 +511,15 @@ protected:
UDelegateFunction* CreateDelegateFunction(const FFuncInfo &FuncInfo) const;
void CompileClassDeclaration(FClasses& AllClasses);
- void CompileDelegateDeclaration(FUnrealSourceFile& SourceFile, FClasses& AllClasses, const TCHAR* DelegateIdentifier, EDelegateSpecifierAction::Type SpecifierAction = EDelegateSpecifierAction::DontParse);
- void CompileFunctionDeclaration(FUnrealSourceFile& SourceFile, FClasses& AllClasses);
+ void CompileDelegateDeclaration(FClasses& AllClasses, const TCHAR* DelegateIdentifier, EDelegateSpecifierAction::Type SpecifierAction = EDelegateSpecifierAction::DontParse);
+ void CompileFunctionDeclaration(FClasses& AllClasses);
void CompileVariableDeclaration (FClasses& AllClasses, UStruct* Struct);
void CompileInterfaceDeclaration(FClasses& AllClasses);
FClass* ParseInterfaceNameDeclaration(FClasses& AllClasses, FString& DeclaredInterfaceName, FString& RequiredAPIMacroIfPresent);
bool TryParseIInterfaceClass(FClasses& AllClasses);
- bool CompileStatement(FClasses& AllClasses, FUnrealSourceFile& SourceFile);
+ bool CompileStatement(FClasses& AllClasses);
// Checks to see if a particular kind of command is allowed on this nesting level.
bool IsAllowedInThisNesting(uint32 AllowFlags);
@@ -684,6 +699,9 @@ protected:
static void ValidatePropertyIsDeprecatedIfNecessary(FPropertyBase& VarProperty, FToken* OuterPropertyType);
private:
+ // Source file currently parsed by UHT.
+ FUnrealSourceFile* CurrentSourceFile;
+
// Module currently parsed by UHT.
const FManifestModule* CurrentlyParsedModule;
@@ -701,7 +719,7 @@ private:
void SkipDeprecatedMacroIfNecessary();
// Parses possible version declaration in generated code, e.g. GENERATED_BODY().
- void CompileVersionDeclaration(FUnrealSourceFile& SourceFile, UStruct* Struct);
+ void CompileVersionDeclaration(UStruct* Struct);
};
/////////////////////////////////////////////////////
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.cpp
index f67c4e9c8863..98c8724e301d 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.cpp
@@ -26,6 +26,7 @@ bool TryFindSourceFileWithPredicate(FUnrealSourceFile*& Out, Predicate Pred)
return false;
}
+
FUnrealSourceFile* FHeaderProvider::Resolve()
{
if (Type != EHeaderProviderSourceType::Resolved)
@@ -55,15 +56,15 @@ FUnrealSourceFile* FHeaderProvider::Resolve()
{
FString SlashId = TEXT("/") + Id;
FString BackslashId = TEXT("\\") + Id;
- TryFindSourceFileWithPredicate(Cache,
+ TryFindSourceFileWithPredicate(Cache,
[&SlashId, &BackslashId](const FUnrealSourceFile& SourceFile)
- {
+ {
return SourceFile.GetFilename().EndsWith(SlashId) || SourceFile.GetFilename().EndsWith(BackslashId);
- }
- );
- }
+ }
+ );
}
}
+ }
Type = EHeaderProviderSourceType::Resolved;
}
@@ -92,6 +93,12 @@ const FUnrealSourceFile* FHeaderProvider::GetResolved() const
return Cache;
}
+FUnrealSourceFile* FHeaderProvider::GetResolved()
+{
+ check(Type == EHeaderProviderSourceType::Resolved);
+ return Cache;
+}
+
bool operator==(const FHeaderProvider& A, const FHeaderProvider& B)
{
if (A.Cache != B.Cache)
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.h b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.h
index 511bb06f5fd6..56c147584f72 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/HeaderProvider.h
@@ -5,12 +5,14 @@
#include "UnrealString.h"
class FUnrealSourceFile;
+class FUHTMakefile;
enum class EHeaderProviderSourceType
{
ClassName,
FileName,
- Resolved
+ Resolved,
+ Invalid,
};
class FHeaderProvider
@@ -18,9 +20,16 @@ class FHeaderProvider
friend bool operator==(const FHeaderProvider& A, const FHeaderProvider& B);
public:
FHeaderProvider(EHeaderProviderSourceType Type, const FString& Id, bool bAutoInclude = false);
+ FHeaderProvider()
+ : Type(EHeaderProviderSourceType::Invalid)
+ , Id(FString())
+ , Cache(nullptr)
+ , bAutoInclude(false)
+ { }
FUnrealSourceFile* Resolve();
const FUnrealSourceFile* GetResolved() const;
+ FUnrealSourceFile* GetResolved();
FString ToString() const;
@@ -29,7 +38,10 @@ public:
EHeaderProviderSourceType GetType() const;
bool IsAutoInclude() const { return bAutoInclude; }
-
+ void SetCache(FUnrealSourceFile* InCache)
+ {
+ Cache = InCache;
+ }
private:
EHeaderProviderSourceType Type;
FString Id;
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.cpp
index a315524e8e5c..6bce3171ea2a 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.cpp
@@ -176,3 +176,72 @@ FManifest FManifest::LoadFromFile(const FString& Filename)
return Result;
}
+
+bool FManifestModule::NeedsRegeneration() const
+{
+ if (ShouldForceRegeneration())
+ {
+ return true;
+ }
+ FString Timestamp;
+ TCHAR TimestampText[] = TEXT("Timestamp");
+ Timestamp.Empty(GeneratedIncludeDirectory.Len() + ARRAY_COUNT(TimestampText));
+ Timestamp += GeneratedIncludeDirectory;
+ Timestamp += TEXT("Timestamp");
+
+ if (!FPaths::FileExists(Timestamp))
+ {
+ // No timestamp, must regenerate.
+ return true;
+ }
+
+ FDateTime TimestampFileLastModify = IFileManager::Get().GetTimeStamp(*Timestamp);
+
+ for (const FString& Header : PublicUObjectClassesHeaders)
+ {
+ if (IFileManager::Get().GetTimeStamp(*Header) > TimestampFileLastModify)
+ {
+ UE_LOG(LogCompile, Log, TEXT("File %s is newer than last timestamp. Regenerating reflection data for module %s."), *Header, *Name);
+ return true;
+ }
+ }
+
+ for (const FString& Header : PublicUObjectHeaders)
+ {
+ if (IFileManager::Get().GetTimeStamp(*Header) > TimestampFileLastModify)
+ {
+ UE_LOG(LogCompile, Log, TEXT("File %s is newer than last timestamp. Regenerating reflection data for module %s."), *Header, *Name);
+ return true;
+ }
+ }
+
+ for (const FString& Header : PrivateUObjectHeaders)
+ {
+ if (IFileManager::Get().GetTimeStamp(*Header) > TimestampFileLastModify)
+ {
+ UE_LOG(LogCompile, Log, TEXT("File %s is newer than last timestamp. Regenerating reflection data for module %s."), *Header, *Name);
+ return true;
+ }
+ }
+
+ // No header is newer than timestamp, no need to regenerate.
+ return false;
+}
+
+bool FManifestModule::IsCompatibleWith(const FManifestModule& ManifestModule)
+{
+ return Name == ManifestModule.Name
+ && ModuleType == ManifestModule.ModuleType
+ && LongPackageName == ManifestModule.LongPackageName
+ && BaseDirectory == ManifestModule.BaseDirectory
+ && IncludeBase == ManifestModule.IncludeBase
+ && GeneratedIncludeDirectory == ManifestModule.GeneratedIncludeDirectory
+ && BaseDirectory == ManifestModule.BaseDirectory
+ && PublicUObjectClassesHeaders == ManifestModule.PublicUObjectClassesHeaders
+ && PublicUObjectHeaders == ManifestModule.PublicUObjectHeaders
+ && PrivateUObjectHeaders == ManifestModule.PrivateUObjectHeaders
+ && PCH == ManifestModule.PCH
+ && GeneratedCPPFilenameBase == ManifestModule.GeneratedCPPFilenameBase
+ && SaveExportedHeaders == SaveExportedHeaders
+ && GeneratedCodeVersion == GeneratedCodeVersion;
+}
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.h b/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.h
index a704fa7e6c62..fde24c0422b1 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/Manifest.h
@@ -2,7 +2,7 @@
#pragma once
#include "UnrealSourceFile.h"
-
+#include "IScriptGeneratorPluginInterface.h"
struct FManifestModule
{
@@ -44,6 +44,44 @@ struct FManifestModule
/** Version of generated code. */
EGeneratedCodeVersion GeneratedCodeVersion;
+
+ /** Returns true if module headers were modified since last code generation. */
+ bool NeedsRegeneration() const;
+
+ /** Returns true if modules are compatible. Used to determine if module data can be loaded from makefile. */
+ bool IsCompatibleWith(const FManifestModule& ManifestModule);
+
+ friend FArchive& operator<<(FArchive& Ar, FManifestModule& ManifestModule)
+ {
+ Ar << ManifestModule.Name;
+ Ar << ManifestModule.ModuleType;
+ Ar << ManifestModule.LongPackageName;
+ Ar << ManifestModule.BaseDirectory;
+ Ar << ManifestModule.IncludeBase;
+ Ar << ManifestModule.GeneratedIncludeDirectory;
+ Ar << ManifestModule.PublicUObjectClassesHeaders;
+ Ar << ManifestModule.PublicUObjectHeaders;
+ Ar << ManifestModule.PrivateUObjectHeaders;
+ Ar << ManifestModule.PCH;
+ Ar << ManifestModule.GeneratedCPPFilenameBase;
+ Ar << ManifestModule.SaveExportedHeaders;
+ Ar << ManifestModule.GeneratedCodeVersion;
+
+ return Ar;
+ }
+
+ bool ShouldForceRegeneration() const
+ {
+ return bForceRegeneration;
+ }
+
+ void ForceRegeneration()
+ {
+ bForceRegeneration = true;
+ }
+
+private:
+ bool bForceRegeneration;
};
@@ -65,4 +103,15 @@ struct FManifest
* @return The loaded module info.
*/
static FManifest LoadFromFile(const FString& Filename);
+
+ friend FArchive& operator<<(FArchive& Ar, FManifest& Manifest)
+ {
+ Ar << Manifest.IsGameTarget;
+ Ar << Manifest.RootLocalPath;
+ Ar << Manifest.RootBuildPath;
+ Ar << Manifest.TargetName;
+ Ar << Manifest.Modules;
+
+ return Ar;
+ }
};
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/NativeClassExporter.h b/Engine/Source/Programs/UnrealHeaderTool/Private/NativeClassExporter.h
index 6b9515726c83..2142c91963ed 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/NativeClassExporter.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/NativeClassExporter.h
@@ -40,6 +40,9 @@ typedef FStringOutputDeviceCountLines FUHTStringBuilderLineCounter;
struct FNativeClassHeaderGenerator
{
private:
+ /** Stack of currently parsed source files. */
+ TArray CurrentSourceFile;
+
FString API;
/**
@@ -57,7 +60,7 @@ private:
FString GeneratedProtoFilenameBase;
/** the name of the java file where mcp definitions are generated */
FString GeneratedMCPFilenameBase;
- UPackage* Package;
+ const UPackage* Package;
FUHTStringBuilder PreHeaderText;
FUHTStringBuilder EnumForeachText;
TArray ListOfPublicHeaderGroupIncludes; // This is built up each time from scratch each time for each header groups
@@ -120,6 +123,8 @@ private:
/** All properties that need to be forward declared. */
TArray ForwardDeclarations;
+ /** Makefile to save parsing data to. */
+ FUHTMakefile& UHTMakefile;
// This exists because it makes debugging much easier on VC2010, since the visualizers can't properly understand templates with templated args
struct HeaderDependents : TArray
{
@@ -201,7 +206,7 @@ private:
/**
* Export functions used to find and call C++ or script implementation of a script function in the interface
*/
- void ExportInterfaceCallFunctions(const TArray& CallbackFunctions, UClass* Class, FClassMetaData* ClassData, FUHTStringBuilder& HeaderOutput);
+ void ExportInterfaceCallFunctions(const TArray& CallbackFunctions, UClass* Class, FUHTStringBuilder& HeaderOutput);
/**
* Export UInterface boilerplate.
@@ -268,10 +273,9 @@ private:
/**
* Exports the macro declarations for GENERATED_BODY() for each Foo in the list of structs specified
*
- * @param SourceFile the source file
* @param Structs the structs to export
*/
- void ExportGeneratedStructBodyMacros(FUnrealSourceFile& SourceFile, const TArray& NativeStructs);
+ void ExportGeneratedStructBodyMacros(const TArray& NativeStructs);
/**
* Exports a local mirror of the specified struct; used to get offsets for noexport structs
@@ -324,11 +328,10 @@ private:
* Generate a .proto message declaration for any functions marked as requiring one
*
* @param InCallbackFunctions array of functions for consideration to generate .proto definitions
- * @param ClassData class data
* @param Indent starting indentation level
* @param Output optional output redirect
*/
- void ExportProtoMessage(const TArray& InCallbackFunctions, FClassMetaData* ClassData, int32 Indent = 0, FUHTStringBuilder* Output = NULL);
+ void ExportProtoMessage(const TArray& InCallbackFunctions, int32 Indent = 0, FUHTStringBuilder* Output = NULL);
/**
* Generate a .java message declaration for any functions marked as requiring one
@@ -443,7 +446,7 @@ private:
*
* @param Package Package to export code for.
**/
- void ExportGeneratedPackageInitCode(UPackage* Package);
+ void ExportGeneratedPackageInitCode(const UPackage* Package);
/**
* Function to output the C++ code necessary to set up the given array of properties
@@ -532,19 +535,20 @@ private:
/**
* Gets list of public headers for the given package in the form of string of includes.
*/
- FString GetListOfPublicHeaderGroupIncludesString(UPackage* Package);
+ FString GetListOfPublicHeaderGroupIncludesString(const UPackage* Package);
public:
// Constructor
FNativeClassHeaderGenerator(
- UPackage* InPackage,
+ const UPackage* InPackage,
const TArray& SourceFiles,
FClasses& AllClasses,
bool InAllowSaveExportedHeaders
#if WITH_HOT_RELOAD_CTORS
, bool bExportVTableConstructors
#endif // WITH_HOT_RELOAD_CTORS
+ , FUHTMakefile& UHTMakefile
);
/**
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.cpp
index 3f119710e42d..2cf5b0088cf4 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.cpp
@@ -91,4 +91,25 @@ bool FClass::IsDynamic(UField* Field)
{
static const FName NAME_ReplaceConverted(TEXT("ReplaceConverted"));
return Field->HasMetaData(NAME_ReplaceConverted);
-}
\ No newline at end of file
+}
+
+FString FClass::GetTypePackageName(UField* Field)
+{
+ static const FName NAME_ReplaceConverted(TEXT("ReplaceConverted"));
+ FString PackageName = Field->GetMetaData(NAME_ReplaceConverted);
+ if (PackageName.Len())
+ {
+ int32 ObjectDotIndex = INDEX_NONE;
+ // Strip the object name
+ if (PackageName.FindChar(TEXT('.'), ObjectDotIndex))
+ {
+ PackageName = PackageName.Mid(0, ObjectDotIndex);
+ }
+ }
+ else
+ {
+ PackageName = Field->GetOutermost()->GetName();
+ }
+ return PackageName;
+}
+
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.h b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.h
index 31c71fd592d2..ba3da195553f 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserClass.h
@@ -47,4 +47,7 @@ public:
/** Helper function that checks if the field is a dynamic type (can be constructed post-startup) */
static bool IsDynamic(UField* Field);
+
+ /** Helper function to get the source replaced package name */
+ static FString GetTypePackageName(UField* Field);
};
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.cpp b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.cpp
index a172167c06bb..51a9c8afbfb1 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.cpp
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.cpp
@@ -4,43 +4,11 @@
#include "UnrealHeaderTool.h"
#include "ParserHelper.h"
#include "DefaultValueHelper.h"
+#include "UHTMakefile/UHTMakefile.h"
/////////////////////////////////////////////////////
// FClassMetaData
-/**
- * Finds the metadata for the struct specified
- *
- * @param Struct the struct to search for
- *
- * @return pointer to the metadata for the struct specified, or NULL
- * if the struct doesn't exist in the list (for example, if it
- * is declared in a package that is already compiled and has had its
- * source stripped)
- */
-FStructData* FClassMetaData::FindStructData( UScriptStruct* Struct )
-{
- FStructData* Result = NULL;
-
- TScopedPointer* pStructData = StructData.Find(Struct);
- if ( pStructData != NULL )
- {
- Result = pStructData->GetOwnedPointer();
- }
-
- if ( Result == NULL )
- {
- UClass* OwnerClass = Struct->GetOwnerClass();
- FClassMetaData* OwnerClassData = GScriptHelper.FindClassData(OwnerClass);
- if ( OwnerClassData && OwnerClassData != this )
- {
- Result = OwnerClassData->FindStructData(Struct);
- }
- }
-
- return Result;
-}
-
/**
* Finds the metadata for the property specified
*
@@ -98,20 +66,7 @@ FTokenData* FClassMetaData::FindTokenData( UProperty* Prop )
// struct property
UScriptStruct* OuterStruct = Cast(Outer);
check(OuterStruct != NULL);
-
- TScopedPointer* pStructInfo = StructData.Find(OuterStruct);
- if ( pStructInfo != NULL )
- {
- FStructData* StructInfo = pStructInfo->GetOwnedPointer();
- check(StructInfo);
-
- FPropertyData& StructProperties = StructInfo->GetStructPropertyData();
- Result = StructProperties.Find(Prop);
- }
- else
- {
- OuterClass = OuterStruct->GetOwnerClass();
- }
+ OuterClass = OuterStruct->GetOwnerClass();
}
}
@@ -127,6 +82,18 @@ FTokenData* FClassMetaData::FindTokenData( UProperty* Prop )
return Result;
}
+void FClassMetaData::AddInheritanceParent(const FString& InParent, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
+{
+ MultipleInheritanceParents.Add(new FMultipleInheritanceBaseClass(InParent));
+ UHTMakefile.AddMultipleInheritanceBaseClass(UnrealSourceFile, MultipleInheritanceParents.Last());
+}
+
+void FClassMetaData::AddInheritanceParent(UClass* ImplementedInterfaceClass, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
+{
+ MultipleInheritanceParents.Add(new FMultipleInheritanceBaseClass(ImplementedInterfaceClass));
+ UHTMakefile.AddMultipleInheritanceBaseClass(UnrealSourceFile, MultipleInheritanceParents.Last());
+}
+
/////////////////////////////////////////////////////
// FPropertyBase
@@ -287,3 +254,68 @@ bool FFunctionData::TryFindForFunction(UFunction* Function, FFunctionData*& OutD
OutData = &(*Output).Get();
return true;
}
+
+FClassMetaData* FCompilerMetadataManager::AddClassData(UStruct* Struct, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
+{
+ TScopedPointer* pClassData = Find(Struct);
+ if (pClassData == NULL)
+ {
+ pClassData = &Emplace(Struct, new FClassMetaData());
+ if (UnrealSourceFile)
+ {
+ UHTMakefile.AddClassMetaData(UnrealSourceFile, *pClassData);
+ }
+ }
+
+ return *pClassData;
+}
+
+FTokenData* FPropertyData::Set(UProperty* InKey, const FTokenData& InValue, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
+{
+ FTokenData* Result = NULL;
+
+ TSharedPtr* pResult = Super::Find(InKey);
+ if (pResult != NULL)
+ {
+ Result = pResult->Get();
+ *Result = FTokenData(InValue);
+ }
+ else
+ {
+ pResult = &Super::Emplace(InKey, new FTokenData(InValue));
+ Result = pResult->Get();
+ UHTMakefile.AddPropertyDataEntry(UnrealSourceFile, *pResult, InKey);
+ }
+
+ return Result;
+}
+
+const TCHAR* FNameLookupCPP::GetNameCPP(UStruct* Struct, bool bForceInterface /*= false */)
+{
+ TCHAR* NameCPP = StructNameMap.FindRef(Struct);
+ if (NameCPP && !bForceInterface)
+ {
+ return NameCPP;
+ }
+
+ FString DesiredStructName = Struct->GetName();
+ FString TempName = FString(bForceInterface ? TEXT("I") : Struct->GetPrefixCPP()) + DesiredStructName;
+ int32 StringLength = TempName.Len();
+
+ NameCPP = new TCHAR[StringLength + 1];
+ FCString::Strcpy(NameCPP, StringLength + 1, *TempName);
+ NameCPP[StringLength] = 0;
+
+ if (bForceInterface)
+ {
+ InterfaceAllocations.Add(NameCPP);
+ UHTMakefile->AddInterfaceAllocation(UnrealSourceFile, NameCPP);
+ }
+ else
+ {
+ StructNameMap.Add(Struct, NameCPP);
+ UHTMakefile->AddStructNameMapEntry(UnrealSourceFile, Struct, NameCPP);
+ }
+
+ return NameCPP;
+}
diff --git a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.h b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.h
index 9a8b8c7d1ea2..259e4e3c5eb5 100644
--- a/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.h
+++ b/Engine/Source/Programs/UnrealHeaderTool/Private/ParserHelper.h
@@ -66,7 +66,7 @@ struct ERefQualifier
/**
* Basic information describing a type.
*/
-class FPropertyBase
+class FPropertyBase : public TSharedFromThis
{
public:
// Variables.
@@ -593,6 +593,8 @@ public:
//@}
static const TCHAR* GetPropertyTypeText( EPropertyType Type );
+
+ friend struct FPropertyBaseArchiveProxy;
};
//
@@ -848,6 +850,8 @@ public:
ImpliedPropertyFlags
);
}
+
+ friend struct FTokenArchiveProxy;
};
/**
@@ -1036,9 +1040,9 @@ struct FTokenData
* Class for storing data about a list of properties. Though FToken contains a reference to its
* associated UProperty, it's faster lookup to use the UProperty as the key in a TMap.
*/
-class FPropertyData : public TMap< UProperty*, TScopedPointer >
+class FPropertyData : public TMap< UProperty*, TSharedPtr >
{
- typedef TMap > Super;
+ typedef TMap > Super;
public:
/**
@@ -1051,10 +1055,10 @@ public:
{
FTokenData* Result = NULL;
- TScopedPointer* pResult = Super::Find(Key);
+ TSharedPtr* pResult = Super::Find(Key);
if ( pResult != NULL )
{
- Result = pResult->GetOwnedPointer();
+ Result = pResult->Get();
}
return Result;
}
@@ -1062,10 +1066,10 @@ public:
{
const FTokenData* Result = NULL;
- const TScopedPointer* pResult = Super::Find(Key);
+ const TSharedPtr* pResult = Super::Find(Key);
if ( pResult != NULL )
{
- Result = pResult->GetOwnedPointer();
+ Result = pResult->Get();
}
return Result;
}
@@ -1079,24 +1083,7 @@ public:
*
* @return a pointer to token data created associated with the property
*/
- FTokenData* Set(UProperty* InKey, const FTokenData& InValue)
- {
- FTokenData* Result = NULL;
-
- TScopedPointer* pResult = Super::Find(InKey);
- if ( pResult != NULL )
- {
- Result = pResult->GetOwnedPointer();
- *Result = FTokenData(InValue);
- }
- else
- {
- pResult = &Super::Emplace(InKey, new FTokenData(InValue));
- Result = *pResult;
- }
-
- return Result;
- }
+ FTokenData* Set(UProperty* InKey, const FTokenData& InValue, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile);
/**
* (debug) Dumps the values of this FPropertyData to the log file
@@ -1105,10 +1092,10 @@ public:
*/
void Dump( int32 Indent )
{
- for ( TMap >::TIterator It(*this); It; ++It )
+ for (auto& Kvp : *this)
{
- TScopedPointer& PointerVal = It.Value();
- FToken& Token = PointerVal.GetOwnedPointer()->Token;
+ TSharedPtr& PointerVal = Kvp.Value;
+ FToken& Token = PointerVal->Token;
if ( Token.Type != CPT_None )
{
UE_LOG(LogCompile, Log, TEXT("%s%s"), FCString::Spc(Indent), *Token.Describe());
@@ -1136,10 +1123,10 @@ public:
*
* @param PropertyToken token that should be added to the list
*/
- void AddStructProperty( const FToken& PropertyToken )
+ void AddStructProperty(const FTokenData& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
{
- check(PropertyToken.TokenProperty);
- StructPropertyData.Set(PropertyToken.TokenProperty, PropertyToken);
+ check(PropertyToken.Token.TokenProperty);
+ StructPropertyData.Set(PropertyToken.Token.TokenProperty, PropertyToken, UHTMakefile, UnrealSourceFile);
}
FPropertyData& GetStructPropertyData()
@@ -1166,6 +1153,8 @@ public:
/** Constructor */
FStructData( const FToken& StructToken ) : StructData(StructToken) {}
+
+ friend struct FStructDataArchiveProxy;
};
/**
@@ -1187,10 +1176,10 @@ class FFunctionData
*
* @param PropertyToken token that should be added to the list
*/
- void AddParameter( const FToken& PropertyToken )
+ void AddParameter(const FToken& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
{
check(PropertyToken.TokenProperty);
- ParameterData.Set(PropertyToken.TokenProperty, PropertyToken);
+ ParameterData.Set(PropertyToken.TokenProperty, PropertyToken, UHTMakefile, UnrealSourceFile);
}
/**
@@ -1247,7 +1236,7 @@ public:
*
* @param PropertyToken the property to add
*/
- void AddProperty( const FToken& PropertyToken )
+ void AddProperty(const FToken& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
{
const UProperty* Prop = PropertyToken.TokenProperty;
check(Prop);
@@ -1259,7 +1248,7 @@ public:
}
else
{
- AddParameter(PropertyToken);
+ AddParameter(PropertyToken, UHTMakefile, UnrealSourceFile);
}
}
@@ -1358,11 +1347,8 @@ class FClassMetaData
/** member properties for this class */
FPropertyData GlobalPropertyData;
- /** structs declared in this class */
- TMap< UScriptStruct*, TScopedPointer