2021-02-08 10:48:17 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "PackageStoreOptimizer.h"
# include "ProfilingDebugging/CountersTrace.h"
# include "Serialization/BufferWriter.h"
# include "Serialization/LargeMemoryWriter.h"
2021-06-15 16:38:03 -04:00
# include "Serialization/MemoryReader.h"
2021-02-08 10:48:17 -04:00
# include "UObject/NameBatchSerialization.h"
# include "Containers/Map.h"
# include "UObject/UObjectHash.h"
# include "Interfaces/ITargetPlatform.h"
# include "UObject/Object.h"
# include "Serialization/MemoryReader.h"
# include "UObject/Package.h"
2024-06-19 12:16:51 -04:00
# include "Misc/PackageName.h"
2021-06-10 09:36:47 -04:00
# include "Misc/SecureHash.h"
2023-09-13 18:11:20 -04:00
# include "Misc/StringBuilder.h"
2021-09-15 10:39:23 -04:00
# include "Serialization/LargeMemoryReader.h"
2021-02-08 10:48:17 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogPackageStoreOptimizer , Log , All ) ;
// modified copy from SavePackage
EObjectMark GetExcludedObjectMarksForTargetPlatform ( const ITargetPlatform * TargetPlatform )
{
2021-06-22 00:27:54 -04:00
EObjectMark Marks = OBJECTMARK_NotForTargetPlatform ;
if ( ! TargetPlatform - > AllowsEditorObjects ( ) )
2021-02-08 10:48:17 -04:00
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_EditorOnly ) ;
}
if ( TargetPlatform - > IsServerOnly ( ) )
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_NotForServer ) ;
}
if ( TargetPlatform - > IsClientOnly ( ) )
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_NotForClient ) ;
}
return Marks ;
}
// modified copy from SavePackage
EObjectMark GetExcludedObjectMarksForObject ( const UObject * Object , const ITargetPlatform * TargetPlatform )
{
EObjectMark Marks = OBJECTMARK_NOMARKS ;
if ( ! Object - > NeedsLoadForClient ( ) )
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_NotForClient ) ;
}
if ( ! Object - > NeedsLoadForServer ( ) )
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_NotForServer ) ;
}
2021-06-22 00:27:54 -04:00
# if WITH_ENGINE
// NotForServer && NotForClient implies EditorOnly
const bool bIsEditorOnlyObject = ( Marks & OBJECTMARK_NotForServer ) & & ( Marks & OBJECTMARK_NotForClient ) ;
const bool bTargetAllowsEditorObjects = TargetPlatform - > AllowsEditorObjects ( ) ;
// no need to query the target platform if the object is editoronly and the targetplatform doesn't allow editor objects
const bool bCheckTargetPlatform = ! bIsEditorOnlyObject | | bTargetAllowsEditorObjects ;
if ( bCheckTargetPlatform & & ( ! Object - > NeedsLoadForTargetPlatform ( TargetPlatform ) | | ! TargetPlatform - > AllowObject ( Object ) ) )
2021-02-08 10:48:17 -04:00
{
2021-06-22 00:27:54 -04:00
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_NotForTargetPlatform ) ;
2021-02-08 10:48:17 -04:00
}
2021-06-22 00:27:54 -04:00
# endif
2021-02-08 10:48:17 -04:00
if ( Object - > IsEditorOnly ( ) )
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_EditorOnly ) ;
}
if ( ( Marks & OBJECTMARK_NotForClient ) & & ( Marks & OBJECTMARK_NotForServer ) )
{
Marks = ( EObjectMark ) ( Marks | OBJECTMARK_EditorOnly ) ;
}
return Marks ;
}
2021-10-12 21:21:22 -04:00
void FPackageStoreOptimizer : : Initialize ( )
2021-02-08 10:48:17 -04:00
{
2021-10-12 21:21:22 -04:00
FindScriptObjects ( ) ;
2021-02-08 10:48:17 -04:00
}
2021-09-15 10:39:23 -04:00
void FPackageStoreOptimizer : : Initialize ( const FIoBuffer & ScriptObjectsBuffer )
{
LoadScriptObjectsBuffer ( ScriptObjectsBuffer ) ;
}
2021-05-06 08:02:55 -04:00
FPackageStorePackage * FPackageStoreOptimizer : : CreateMissingPackage ( const FName & Name ) const
{
FPackageStorePackage * Package = new FPackageStorePackage ( ) ;
Package - > Name = Name ;
Package - > Id = FPackageId : : FromName ( Name ) ;
return Package ;
}
2021-02-08 10:48:17 -04:00
FPackageStorePackage * FPackageStoreOptimizer : : CreatePackageFromCookedHeader ( const FName & Name , const FIoBuffer & CookedHeaderBuffer ) const
{
FPackageStorePackage * Package = new FPackageStorePackage ( ) ;
Package - > Id = FPackageId : : FromName ( Name ) ;
2022-04-25 07:37:07 -04:00
Package - > Name = Name ;
2023-03-24 10:06:23 -04:00
2021-06-15 16:38:03 -04:00
FCookedHeaderData CookedHeaderData = LoadCookedHeader ( CookedHeaderBuffer ) ;
2021-10-12 21:21:22 -04:00
if ( ! CookedHeaderData . Summary . bUnversioned )
{
FZenPackageVersioningInfo & VersioningInfo = Package - > VersioningInfo . Emplace ( ) ;
VersioningInfo . ZenVersion = EZenPackageVersion : : Latest ;
VersioningInfo . PackageVersion = CookedHeaderData . Summary . GetFileVersionUE ( ) ;
VersioningInfo . LicenseeVersion = CookedHeaderData . Summary . GetFileVersionLicenseeUE ( ) ;
VersioningInfo . CustomVersions = CookedHeaderData . Summary . GetCustomVersionContainer ( ) ;
}
2021-06-15 16:38:03 -04:00
Package - > PackageFlags = CookedHeaderData . Summary . GetPackageFlags ( ) ;
Package - > CookedHeaderSize = CookedHeaderData . Summary . TotalHeaderSize ;
2021-09-30 02:05:41 -04:00
for ( int32 I = 0 ; I < CookedHeaderData . Summary . NamesReferencedFromExportDataCount ; + + I )
2021-06-15 16:38:03 -04:00
{
2021-09-30 02:05:41 -04:00
Package - > NameMapBuilder . AddName ( CookedHeaderData . SummaryNames [ I ] ) ;
2021-06-15 16:38:03 -04:00
}
2022-01-18 13:01:31 -05:00
2024-06-19 12:16:51 -04:00
Package - > SoftPackageReferences = MoveTemp ( CookedHeaderData . SoftPackageReferences ) ;
2022-01-18 13:01:31 -05:00
TArray < FPackageStorePackage : : FUnresolvedImport > Imports ;
ProcessImports ( CookedHeaderData , Package , Imports ) ;
ProcessExports ( CookedHeaderData , Package , Imports . GetData ( ) ) ;
2021-06-15 16:38:03 -04:00
ProcessPreloadDependencies ( CookedHeaderData , Package ) ;
2022-12-13 03:51:37 -05:00
ProcessDataResources ( CookedHeaderData , Package ) ;
2023-04-06 10:50:30 -04:00
CreateExportBundle ( Package ) ;
2021-02-08 10:48:17 -04:00
2023-04-06 10:50:30 -04:00
FinalizePackageHeader ( Package ) ;
2021-06-15 16:38:03 -04:00
return Package ;
}
PRAGMA_DISABLE_DEPRECATION_WARNINGS
FPackageStoreOptimizer : : FCookedHeaderData FPackageStoreOptimizer : : LoadCookedHeader ( const FIoBuffer & CookedHeaderBuffer ) const
{
FCookedHeaderData CookedHeaderData ;
2021-02-08 10:48:17 -04:00
TArrayView < const uint8 > MemView ( CookedHeaderBuffer . Data ( ) , CookedHeaderBuffer . DataSize ( ) ) ;
FMemoryReaderView Ar ( MemView ) ;
2021-06-15 16:38:03 -04:00
FPackageFileSummary & Summary = CookedHeaderData . Summary ;
2021-02-08 10:48:17 -04:00
{
TGuardValue < int32 > GuardAllowUnversionedContentInEditor ( GAllowUnversionedContentInEditor , 1 ) ;
2021-06-15 16:38:03 -04:00
Ar < < Summary ;
2021-02-08 10:48:17 -04:00
}
2023-09-14 18:18:29 -04:00
Ar . SetUseUnversionedPropertySerialization ( ( CookedHeaderData . Summary . GetPackageFlags ( ) & EPackageFlags : : PKG_UnversionedProperties ) ! = 0 ) ;
2021-06-15 16:38:03 -04:00
Ar . SetFilterEditorOnly ( ( CookedHeaderData . Summary . GetPackageFlags ( ) & EPackageFlags : : PKG_FilterEditorOnly ) ! = 0 ) ;
2021-02-08 10:48:17 -04:00
2021-06-15 16:38:03 -04:00
if ( Summary . NameCount > 0 )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
Ar . Seek ( Summary . NameOffset ) ;
2021-02-08 10:48:17 -04:00
FNameEntrySerialized NameEntry ( ENAME_LinkerConstructor ) ;
2021-12-16 18:22:15 -05:00
CookedHeaderData . SummaryNames . Reserve ( Summary . NameCount ) ;
2021-06-15 16:38:03 -04:00
for ( int32 I = 0 ; I < Summary . NameCount ; + + I )
2021-02-08 10:48:17 -04:00
{
Ar < < NameEntry ;
2021-06-15 16:38:03 -04:00
CookedHeaderData . SummaryNames . Add ( NameEntry ) ;
2021-02-08 10:48:17 -04:00
}
}
class FNameReaderProxyArchive
: public FArchiveProxy
{
public :
using FArchiveProxy : : FArchiveProxy ;
2021-06-15 16:38:03 -04:00
FNameReaderProxyArchive ( FArchive & InAr , const TArray < FName > & InNameMap )
2021-02-08 10:48:17 -04:00
: FArchiveProxy ( InAr )
, NameMap ( InNameMap )
{
// Replicate the filter editor only state of the InnerArchive as FArchiveProxy will
// not intercept it.
FArchive : : SetFilterEditorOnly ( InAr . IsFilterEditorOnly ( ) ) ;
}
FArchive & operator < < ( FName & Name )
{
2021-02-09 15:11:26 -04:00
int32 NameIndex = 0 ;
int32 Number = 0 ;
2021-02-08 10:48:17 -04:00
InnerArchive < < NameIndex < < Number ;
if ( ! NameMap . IsValidIndex ( NameIndex ) )
{
UE_LOG ( LogPackageStoreOptimizer , Fatal , TEXT ( " Bad name index %i/%i " ) , NameIndex , NameMap . Num ( ) ) ;
}
2021-06-15 16:38:03 -04:00
const FName & MappedName = NameMap [ NameIndex ] ;
Name = FName : : CreateFromDisplayId ( MappedName . GetDisplayIndex ( ) , Number ) ;
2021-02-08 10:48:17 -04:00
return * this ;
}
private :
2021-06-15 16:38:03 -04:00
const TArray < FName > & NameMap ;
2021-02-08 10:48:17 -04:00
} ;
2021-06-15 16:38:03 -04:00
FNameReaderProxyArchive ProxyAr ( Ar , CookedHeaderData . SummaryNames ) ;
2021-02-08 10:48:17 -04:00
2021-06-15 16:38:03 -04:00
if ( Summary . ImportCount > 0 )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
CookedHeaderData . ObjectImports . Reserve ( Summary . ImportCount ) ;
ProxyAr . Seek ( Summary . ImportOffset ) ;
for ( int32 I = 0 ; I < Summary . ImportCount ; + + I )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
ProxyAr < < CookedHeaderData . ObjectImports . AddDefaulted_GetRef ( ) ;
2021-02-08 10:48:17 -04:00
}
}
2021-06-15 16:38:03 -04:00
if ( Summary . PreloadDependencyCount > 0 )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
CookedHeaderData . PreloadDependencies . Reserve ( Summary . PreloadDependencyCount ) ;
ProxyAr . Seek ( Summary . PreloadDependencyOffset ) ;
for ( int32 I = 0 ; I < Summary . PreloadDependencyCount ; + + I )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
ProxyAr < < CookedHeaderData . PreloadDependencies . AddDefaulted_GetRef ( ) ;
2021-02-08 10:48:17 -04:00
}
}
2021-06-15 16:38:03 -04:00
if ( Summary . ExportCount > 0 )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
CookedHeaderData . ObjectExports . Reserve ( Summary . ExportCount ) ;
ProxyAr . Seek ( Summary . ExportOffset ) ;
for ( int32 I = 0 ; I < Summary . ExportCount ; + + I )
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
FObjectExport & ObjectExport = CookedHeaderData . ObjectExports . AddDefaulted_GetRef ( ) ;
2021-02-08 10:48:17 -04:00
ProxyAr < < ObjectExport ;
}
}
2024-06-19 12:16:51 -04:00
if ( Summary . SoftPackageReferencesCount > 0 )
{
ProxyAr . Seek ( Summary . SoftPackageReferencesOffset ) ;
CookedHeaderData . SoftPackageReferences . Reserve ( Summary . SoftPackageReferencesCount ) ;
for ( int32 I = 0 ; I < Summary . SoftPackageReferencesCount ; + + I )
{
FName & SoftReference = CookedHeaderData . SoftPackageReferences . Emplace_GetRef ( ) ;
ProxyAr < < SoftReference ;
}
}
2022-12-13 03:51:37 -05:00
if ( Summary . DataResourceOffset > 0 )
{
ProxyAr . Seek ( Summary . DataResourceOffset ) ;
FObjectDataResource : : Serialize ( ProxyAr , CookedHeaderData . DataResources ) ;
}
2021-06-15 16:38:03 -04:00
return CookedHeaderData ;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2021-08-02 07:21:44 -04:00
void FPackageStoreOptimizer : : ResolveImport ( FPackageStorePackage : : FUnresolvedImport * Imports , const FObjectImport * ObjectImports , int32 LocalImportIndex ) const
2021-02-08 10:48:17 -04:00
{
2021-08-02 07:21:44 -04:00
FPackageStorePackage : : FUnresolvedImport * Import = Imports + LocalImportIndex ;
2021-02-08 10:48:17 -04:00
if ( Import - > FullName . Len ( ) = = 0 )
{
Import - > FullName . Reserve ( 256 ) ;
const FObjectImport * ObjectImport = ObjectImports + LocalImportIndex ;
if ( ObjectImport - > OuterIndex . IsNull ( ) )
{
FName PackageName = ObjectImport - > ObjectName ;
PackageName . AppendString ( Import - > FullName ) ;
Import - > FullName . ToLowerInline ( ) ;
2021-08-02 07:21:44 -04:00
Import - > FromPackageName = PackageName ;
Import - > FromPackageNameLen = Import - > FullName . Len ( ) ;
2021-02-08 10:48:17 -04:00
Import - > bIsScriptImport = Import - > FullName . StartsWith ( TEXT ( " /Script/ " ) ) ;
2021-08-02 07:21:44 -04:00
Import - > bIsImportOfPackage = true ;
2021-02-08 10:48:17 -04:00
}
else
{
const int32 OuterIndex = ObjectImport - > OuterIndex . ToImport ( ) ;
ResolveImport ( Imports , ObjectImports , OuterIndex ) ;
2021-08-02 07:21:44 -04:00
FPackageStorePackage : : FUnresolvedImport * OuterImport = Imports + OuterIndex ;
2021-02-08 10:48:17 -04:00
check ( OuterImport - > FullName . Len ( ) > 0 ) ;
Import - > bIsScriptImport = OuterImport - > bIsScriptImport ;
Import - > FullName . Append ( OuterImport - > FullName ) ;
Import - > FullName . AppendChar ( TEXT ( ' / ' ) ) ;
ObjectImport - > ObjectName . AppendString ( Import - > FullName ) ;
Import - > FullName . ToLowerInline ( ) ;
2022-01-18 13:01:31 -05:00
Import - > bIsImportOptional = ObjectImport - > bImportOptional ;
2021-08-02 07:21:44 -04:00
Import - > FromPackageName = OuterImport - > FromPackageName ;
Import - > FromPackageNameLen = OuterImport - > FromPackageNameLen ;
2021-02-08 10:48:17 -04:00
}
}
}
2023-09-13 18:11:20 -04:00
void FPackageStoreOptimizer : : AppendPathForPublicExportHash ( UObject * Object , FStringBuilderBase & OutPath )
{
if ( ! Object )
{
return ;
}
if ( ! Object - > GetOuter ( ) )
{
// Outermost package objects do not have a PublicExportHash Name; they use 0 for PublicExportHash
// Write nothing for them.
return ;
}
constexpr int32 DirectorySeparatorLen = 1 ;
const TCHAR DirectorySeparatorChar = ' / ' ;
TArray < FName , TInlineAllocator < 10 > > PathNames ;
int32 PathNameLen = 0 ;
2023-09-20 08:41:40 -04:00
for ( UObject * Iter = Object ; Iter - > GetOuter ( ) ; Iter = Iter - > GetOuter ( ) )
2023-09-13 18:11:20 -04:00
{
FName PathName = Iter - > GetFName ( ) ;
PathNames . Add ( PathName ) ;
PathNameLen + = PathName . GetStringLength ( ) + DirectorySeparatorLen ;
}
if ( PathNameLen < = 1 )
{
// We should be writing at least 2 characters: /<LeafName>. Write nothing if we find an empty LeafName.
return ;
}
int32 InitialLength = OutPath . Len ( ) ;
for ( FName PathName : ReverseIterate ( PathNames ) )
{
OutPath < < DirectorySeparatorChar < < PathName ;
}
// Down-case the characters we wrote; public export hash is based on lower-case
TCHAR * OutPathData = OutPath . GetData ( ) ;
int32 NewLength = OutPath . Len ( ) ;
for ( int32 N = InitialLength ; N < NewLength ; + + N )
{
OutPathData [ N ] = FChar : : ToLower ( OutPathData [ N ] ) ;
}
}
bool FPackageStoreOptimizer : : TryGetPublicExportHash ( FStringView PackageRelativeExportPath , uint64 & OutPublicExportHash )
{
OutPublicExportHash = 0 ;
// PackageRelativeExportHash should have been generated by GetNameForPublicExportHash or an equivalent function
if ( PackageRelativeExportPath . Len ( ) = = 0 | | // PublicExportHash is not defined for the UPackage object
PackageRelativeExportPath . Len ( ) = = 1 | | // An object with an empty leaf name is an error, but we ignore it and treat it the same as a package
PackageRelativeExportPath [ 0 ] ! = ' / ' ) // Invalid string; GetNameForPublicExportHash starts every relative path with /
{
return false ;
}
OutPublicExportHash = GetPublicExportHash ( PackageRelativeExportPath ) ;
return true ;
}
2021-11-18 14:37:34 -05:00
uint64 FPackageStoreOptimizer : : GetPublicExportHash ( FStringView PackageRelativeExportPath )
{
check ( PackageRelativeExportPath . Len ( ) > 1 ) ;
check ( PackageRelativeExportPath [ 0 ] = = ' / ' ) ;
return CityHash64 ( reinterpret_cast < const char * > ( PackageRelativeExportPath . GetData ( ) + 1 ) , ( PackageRelativeExportPath . Len ( ) - 1 ) * sizeof ( TCHAR ) ) ;
}
2022-01-18 13:01:31 -05:00
void FPackageStoreOptimizer : : ProcessImports ( const FCookedHeaderData & CookedHeaderData , FPackageStorePackage * Package , TArray < FPackageStorePackage : : FUnresolvedImport > & UnresolvedImports ) const
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
int32 ImportCount = CookedHeaderData . ObjectImports . Num ( ) ;
2021-08-02 07:21:44 -04:00
UnresolvedImports . SetNum ( ImportCount ) ;
2021-02-08 10:48:17 -04:00
Package - > Imports . SetNum ( ImportCount ) ;
2023-03-29 04:40:20 -04:00
TSet < FName > ImportedPackageNames ;
2021-02-08 10:48:17 -04:00
for ( int32 ImportIndex = 0 ; ImportIndex < ImportCount ; + + ImportIndex )
{
2021-08-02 07:21:44 -04:00
ResolveImport ( UnresolvedImports . GetData ( ) , CookedHeaderData . ObjectImports . GetData ( ) , ImportIndex ) ;
FPackageStorePackage : : FUnresolvedImport & UnresolvedImport = UnresolvedImports [ ImportIndex ] ;
2022-01-18 13:01:31 -05:00
if ( ! UnresolvedImport . bIsScriptImport )
2021-02-08 10:48:17 -04:00
{
2022-01-18 13:01:31 -05:00
if ( UnresolvedImport . bIsImportOfPackage )
{
2023-03-29 04:40:20 -04:00
ImportedPackageNames . Add ( UnresolvedImport . FromPackageName ) ;
2022-01-18 13:01:31 -05:00
}
2021-02-08 10:48:17 -04:00
}
}
2023-03-29 04:40:20 -04:00
Package - > ImportedPackages . Reserve ( ImportedPackageNames . Num ( ) ) ;
for ( FName ImportedPackageName : ImportedPackageNames )
{
Package - > ImportedPackages . Emplace ( ImportedPackageName ) ;
}
Algo : : Sort ( Package - > ImportedPackages ) ;
2021-08-02 07:21:44 -04:00
for ( int32 ImportIndex = 0 ; ImportIndex < ImportCount ; + + ImportIndex )
{
FPackageStorePackage : : FUnresolvedImport & UnresolvedImport = UnresolvedImports [ ImportIndex ] ;
if ( UnresolvedImport . bIsScriptImport )
{
2021-09-15 10:39:23 -04:00
FPackageObjectIndex ScriptObjectIndex = FPackageObjectIndex : : FromScriptPath ( UnresolvedImport . FullName ) ;
if ( ! ScriptObjectsMap . Contains ( ScriptObjectIndex ) )
{
UE_LOG ( LogPackageStoreOptimizer , Warning , TEXT ( " Package '%s' is referencing missing script import '%s' " ) , * Package - > Name . ToString ( ) , * UnresolvedImport . FullName ) ;
}
2021-12-16 18:22:15 -05:00
Package - > Imports [ ImportIndex ] = ScriptObjectIndex ;
2021-08-02 07:21:44 -04:00
}
else if ( ! UnresolvedImport . bIsImportOfPackage )
{
bool bFoundPackageIndex = false ;
2023-03-29 04:40:20 -04:00
for ( uint32 PackageIndex = 0 , PackageCount = static_cast < uint32 > ( Package - > ImportedPackages . Num ( ) ) ; PackageIndex < PackageCount ; + + PackageIndex )
2021-08-02 07:21:44 -04:00
{
2023-03-29 04:40:20 -04:00
if ( UnresolvedImport . FromPackageName = = Package - > ImportedPackages [ PackageIndex ] . Name )
2021-08-02 07:21:44 -04:00
{
FStringView PackageRelativeName = FStringView ( UnresolvedImport . FullName ) . RightChop ( UnresolvedImport . FromPackageNameLen ) ;
check ( PackageRelativeName . Len ( ) ) ;
2021-11-18 14:37:34 -05:00
FPackageImportReference PackageImportRef ( PackageIndex , Package - > ImportedPublicExportHashes . Num ( ) ) ;
2021-08-02 07:21:44 -04:00
Package - > Imports [ ImportIndex ] = FPackageObjectIndex : : FromPackageImportRef ( PackageImportRef ) ;
2021-11-18 14:37:34 -05:00
uint64 ExportHash = GetPublicExportHash ( PackageRelativeName ) ;
Package - > ImportedPublicExportHashes . Add ( ExportHash ) ;
2021-08-02 07:21:44 -04:00
bFoundPackageIndex = true ;
break ;
}
}
check ( bFoundPackageIndex ) ;
}
}
2021-06-15 16:38:03 -04:00
}
2021-02-08 10:48:17 -04:00
void FPackageStoreOptimizer : : ResolveExport (
2023-01-31 10:47:12 -05:00
FPackageStorePackage : : FUnresolvedExport * Exports ,
2021-02-08 10:48:17 -04:00
const FObjectExport * ObjectExports ,
const int32 LocalExportIndex ,
2022-01-18 13:01:31 -05:00
const FName & PackageName ,
FPackageStorePackage : : FUnresolvedImport * Imports ,
const FObjectImport * ObjectImports ) const
2021-02-08 10:48:17 -04:00
{
2023-01-31 10:47:12 -05:00
FPackageStorePackage : : FUnresolvedExport * Export = Exports + LocalExportIndex ;
2021-02-08 10:48:17 -04:00
if ( Export - > FullName . Len ( ) = = 0 )
{
Export - > FullName . Reserve ( 256 ) ;
const FObjectExport * ObjectExport = ObjectExports + LocalExportIndex ;
if ( ObjectExport - > OuterIndex . IsNull ( ) )
{
PackageName . AppendString ( Export - > FullName ) ;
Export - > FullName . AppendChar ( TEXT ( ' / ' ) ) ;
ObjectExport - > ObjectName . AppendString ( Export - > FullName ) ;
Export - > FullName . ToLowerInline ( ) ;
check ( Export - > FullName . Len ( ) > 0 ) ;
}
else
{
2022-01-18 13:01:31 -05:00
FString * OuterName = nullptr ;
if ( ObjectExport - > OuterIndex . IsExport ( ) )
{
int32 OuterExportIndex = ObjectExport - > OuterIndex . ToExport ( ) ;
2022-05-18 12:56:12 -04:00
ResolveExport ( Exports , ObjectExports , OuterExportIndex , PackageName , Imports , ObjectImports ) ;
2022-01-18 13:01:31 -05:00
OuterName = & Exports [ OuterExportIndex ] . FullName ;
}
else
{
check ( Imports & & ObjectImports ) ;
int32 OuterImportIndex = ObjectExport - > OuterIndex . ToImport ( ) ;
ResolveImport ( Imports , ObjectImports , OuterImportIndex ) ;
OuterName = & Imports [ OuterImportIndex ] . FullName ;
2021-02-08 10:48:17 -04:00
2022-01-18 13:01:31 -05:00
}
check ( OuterName & & OuterName - > Len ( ) > 0 ) ;
Export - > FullName . Append ( * OuterName ) ;
2021-02-08 10:48:17 -04:00
Export - > FullName . AppendChar ( TEXT ( ' / ' ) ) ;
ObjectExport - > ObjectName . AppendString ( Export - > FullName ) ;
Export - > FullName . ToLowerInline ( ) ;
}
}
}
2022-01-18 13:01:31 -05:00
void FPackageStoreOptimizer : : ProcessExports ( const FCookedHeaderData & CookedHeaderData , FPackageStorePackage * Package , FPackageStorePackage : : FUnresolvedImport * Imports ) const
2021-06-15 16:38:03 -04:00
{
int32 ExportCount = CookedHeaderData . ObjectExports . Num ( ) ;
2023-01-31 10:47:12 -05:00
TArray < FPackageStorePackage : : FUnresolvedExport > UnresolvedExports ;
UnresolvedExports . SetNum ( ExportCount ) ;
2021-02-08 10:48:17 -04:00
Package - > Exports . SetNum ( ExportCount ) ;
Package - > ExportGraphNodes . Reserve ( ExportCount * 2 ) ;
auto PackageObjectIdFromPackageIndex =
2021-08-02 07:21:44 -04:00
[ ] ( const TArray < FPackageObjectIndex > & Imports , const FPackageIndex & PackageIndex ) - > FPackageObjectIndex
2021-02-08 10:48:17 -04:00
{
if ( PackageIndex . IsImport ( ) )
{
2021-08-02 07:21:44 -04:00
return Imports [ PackageIndex . ToImport ( ) ] ;
2021-02-08 10:48:17 -04:00
}
if ( PackageIndex . IsExport ( ) )
{
return FPackageObjectIndex : : FromExportIndex ( PackageIndex . ToExport ( ) ) ;
}
return FPackageObjectIndex ( ) ;
} ;
2021-08-02 07:21:44 -04:00
FString PackageNameStr = Package - > Name . ToString ( ) ;
2023-01-31 10:47:12 -05:00
TMap < uint64 , const FPackageStorePackage : : FUnresolvedExport * > SeenPublicExportHashes ;
2021-02-08 10:48:17 -04:00
for ( int32 ExportIndex = 0 ; ExportIndex < ExportCount ; + + ExportIndex )
{
2021-06-15 16:38:03 -04:00
const FObjectExport & ObjectExport = CookedHeaderData . ObjectExports [ ExportIndex ] ;
2021-02-08 10:48:17 -04:00
FPackageStorePackage : : FExport & Export = Package - > Exports [ ExportIndex ] ;
2023-01-31 10:47:12 -05:00
FPackageStorePackage : : FUnresolvedExport & UnresolvedExport = UnresolvedExports [ ExportIndex ] ;
2021-02-08 10:48:17 -04:00
Export . ObjectName = ObjectExport . ObjectName ;
Export . ObjectFlags = ObjectExport . ObjectFlags ;
2023-04-06 10:50:30 -04:00
check ( ObjectExport . SerialOffset > = Package - > CookedHeaderSize ) ;
Export . SerialOffset = ObjectExport . SerialOffset - Package - > CookedHeaderSize ;
2021-06-15 16:38:03 -04:00
Export . SerialSize = ObjectExport . SerialSize ;
2021-02-08 10:48:17 -04:00
Export . bNotForClient = ObjectExport . bNotForClient ;
Export . bNotForServer = ObjectExport . bNotForServer ;
2022-01-18 13:01:31 -05:00
Export . bIsPublic = ( Export . ObjectFlags & RF_Public ) > 0 | | ObjectExport . bGeneratePublicHash ;
2023-01-31 10:47:12 -05:00
ResolveExport ( UnresolvedExports . GetData ( ) , CookedHeaderData . ObjectExports . GetData ( ) , ExportIndex , Package - > Name , Imports , CookedHeaderData . ObjectImports . GetData ( ) ) ;
2021-02-08 10:48:17 -04:00
if ( Export . bIsPublic )
{
2023-01-31 10:47:12 -05:00
check ( UnresolvedExport . FullName . Len ( ) > 0 ) ;
FStringView PackageRelativeName = FStringView ( UnresolvedExport . FullName ) . RightChop ( PackageNameStr . Len ( ) ) ;
2021-08-02 07:21:44 -04:00
check ( PackageRelativeName . Len ( ) ) ;
2021-11-18 14:37:34 -05:00
Export . PublicExportHash = GetPublicExportHash ( PackageRelativeName ) ;
2023-01-31 10:47:12 -05:00
const FPackageStorePackage : : FUnresolvedExport * FindCollidingExport = SeenPublicExportHashes . FindRef ( Export . PublicExportHash ) ;
2021-11-18 14:37:34 -05:00
if ( FindCollidingExport )
{
UE_LOG ( LogPackageStoreOptimizer , Fatal , TEXT ( " Export hash collision in package \" %s \" : \" %s \" and \" %s " ) , * PackageNameStr , PackageRelativeName . GetData ( ) , * FindCollidingExport - > FullName . RightChop ( PackageNameStr . Len ( ) ) ) ;
}
2023-01-31 10:47:12 -05:00
SeenPublicExportHashes . Add ( Export . PublicExportHash , & UnresolvedExport ) ;
2021-02-08 10:48:17 -04:00
}
Export . OuterIndex = PackageObjectIdFromPackageIndex ( Package - > Imports , ObjectExport . OuterIndex ) ;
Export . ClassIndex = PackageObjectIdFromPackageIndex ( Package - > Imports , ObjectExport . ClassIndex ) ;
Export . SuperIndex = PackageObjectIdFromPackageIndex ( Package - > Imports , ObjectExport . SuperIndex ) ;
Export . TemplateIndex = PackageObjectIdFromPackageIndex ( Package - > Imports , ObjectExport . TemplateIndex ) ;
2021-06-15 16:38:03 -04:00
for ( uint8 CommandType = 0 ; CommandType < FExportBundleEntry : : ExportCommandType_Count ; + + CommandType )
{
FPackageStorePackage : : FExportGraphNode & Node = Package - > ExportGraphNodes . AddDefaulted_GetRef ( ) ;
Node . BundleEntry . CommandType = FExportBundleEntry : : EExportCommandType ( CommandType ) ;
Node . BundleEntry . LocalExportIndex = ExportIndex ;
Node . bIsPublic = Export . bIsPublic ;
Export . Nodes [ CommandType ] = & Node ;
}
2021-02-08 10:48:17 -04:00
}
}
2021-06-15 16:38:03 -04:00
void FPackageStoreOptimizer : : ProcessPreloadDependencies ( const FCookedHeaderData & CookedHeaderData , FPackageStorePackage * Package ) const
{
TRACE_CPUPROFILER_EVENT_SCOPE ( ProcessPreloadDependencies ) ;
2023-04-06 10:50:30 -04:00
auto AddNodeDependency = [ ] ( FPackageStorePackage * Package , int32 FromExportIndex , FExportBundleEntry : : EExportCommandType FromExportBundleCommandType , FPackageStorePackage : : FExportGraphNode * ToNode )
2021-06-15 16:38:03 -04:00
{
FPackageStorePackage : : FExport & FromExport = Package - > Exports [ FromExportIndex ] ;
FPackageStorePackage : : FExportGraphNode * FromNode = FromExport . Nodes [ FromExportBundleCommandType ] ;
ToNode - > InternalDependencies . Add ( FromNode ) ;
} ;
2023-04-06 10:50:30 -04:00
TArray < FDependencyBundleHeader > & DependencyBundleHeaders = Package - > GraphData . DependencyBundleHeaders ;
TArray < FDependencyBundleEntry > & DependencyBundleEntries = Package - > GraphData . DependencyBundleEntries ;
2021-06-15 16:38:03 -04:00
for ( int32 ExportIndex = 0 ; ExportIndex < Package - > Exports . Num ( ) ; + + ExportIndex )
{
FPackageStorePackage : : FExport & Export = Package - > Exports [ ExportIndex ] ;
const FObjectExport & ObjectExport = CookedHeaderData . ObjectExports [ ExportIndex ] ;
2023-04-06 10:50:30 -04:00
AddNodeDependency ( Package , ExportIndex , FExportBundleEntry : : ExportCommandType_Create , Export . Nodes [ FExportBundleEntry : : ExportCommandType_Serialize ] ) ;
2021-06-15 16:38:03 -04:00
2023-04-06 10:50:30 -04:00
FDependencyBundleHeader & DependencyBundleHeader = DependencyBundleHeaders . AddDefaulted_GetRef ( ) ;
FMemory : : Memzero ( & DependencyBundleHeader , sizeof ( FDependencyBundleHeader ) ) ;
2021-06-15 16:38:03 -04:00
if ( ObjectExport . FirstExportDependency > = 0 )
{
2023-04-06 10:50:30 -04:00
DependencyBundleHeader . FirstEntryIndex = DependencyBundleEntries . Num ( ) ;
int32 StartIndex = ObjectExport . FirstExportDependency +
ObjectExport . SerializationBeforeSerializationDependencies +
ObjectExport . CreateBeforeSerializationDependencies +
ObjectExport . SerializationBeforeCreateDependencies ;
for ( int32 Index = StartIndex ; Index < StartIndex + ObjectExport . CreateBeforeCreateDependencies ; + + Index )
2021-06-15 16:38:03 -04:00
{
2023-04-06 10:50:30 -04:00
FPackageIndex Dep = CookedHeaderData . PreloadDependencies [ Index ] ;
2021-06-15 16:38:03 -04:00
if ( Dep . IsExport ( ) )
{
2023-04-06 10:50:30 -04:00
AddNodeDependency ( Package , Dep . ToExport ( ) , FExportBundleEntry : : ExportCommandType_Create , Export . Nodes [ FExportBundleEntry : : ExportCommandType_Create ] ) ;
2021-06-15 16:38:03 -04:00
}
2023-04-06 10:50:30 -04:00
if ( Dep . IsExport ( ) | | ! Package - > Imports [ Dep . ToImport ( ) ] . IsScriptImport ( ) )
2021-06-15 16:38:03 -04:00
{
2023-04-06 10:50:30 -04:00
DependencyBundleEntries . AddDefaulted_GetRef ( ) . LocalImportOrExportIndex = Dep ;
+ + DependencyBundleHeader . EntryCount [ FExportBundleEntry : : ExportCommandType_Create ] [ FExportBundleEntry : : ExportCommandType_Create ] ;
2021-06-15 16:38:03 -04:00
}
}
2023-04-06 10:50:30 -04:00
StartIndex = ObjectExport . FirstExportDependency +
ObjectExport . SerializationBeforeSerializationDependencies +
ObjectExport . CreateBeforeSerializationDependencies ;
for ( int32 Index = StartIndex ; Index < StartIndex + ObjectExport . SerializationBeforeCreateDependencies ; + + Index )
2021-06-15 16:38:03 -04:00
{
2023-04-06 10:50:30 -04:00
FPackageIndex Dep = CookedHeaderData . PreloadDependencies [ Index ] ;
2021-06-15 16:38:03 -04:00
if ( Dep . IsExport ( ) )
{
2023-04-06 10:50:30 -04:00
AddNodeDependency ( Package , Dep . ToExport ( ) , FExportBundleEntry : : ExportCommandType_Serialize , Export . Nodes [ FExportBundleEntry : : ExportCommandType_Create ] ) ;
2021-06-15 16:38:03 -04:00
}
2023-04-06 10:50:30 -04:00
if ( Dep . IsExport ( ) | | ! Package - > Imports [ Dep . ToImport ( ) ] . IsScriptImport ( ) )
2021-06-15 16:38:03 -04:00
{
2023-04-06 10:50:30 -04:00
DependencyBundleEntries . AddDefaulted_GetRef ( ) . LocalImportOrExportIndex = Dep ;
+ + DependencyBundleHeader . EntryCount [ FExportBundleEntry : : ExportCommandType_Create ] [ FExportBundleEntry : : ExportCommandType_Serialize ] ;
}
}
StartIndex = ObjectExport . FirstExportDependency +
ObjectExport . SerializationBeforeSerializationDependencies ;
for ( int32 Index = StartIndex ; Index < StartIndex + ObjectExport . CreateBeforeSerializationDependencies ; + + Index )
{
FPackageIndex Dep = CookedHeaderData . PreloadDependencies [ Index ] ;
if ( Dep . IsExport ( ) )
{
AddNodeDependency ( Package , Dep . ToExport ( ) , FExportBundleEntry : : ExportCommandType_Create , Export . Nodes [ FExportBundleEntry : : ExportCommandType_Serialize ] ) ;
}
if ( Dep . IsExport ( ) | | ! Package - > Imports [ Dep . ToImport ( ) ] . IsScriptImport ( ) )
{
DependencyBundleEntries . AddDefaulted_GetRef ( ) . LocalImportOrExportIndex = Dep ;
+ + DependencyBundleHeader . EntryCount [ FExportBundleEntry : : ExportCommandType_Serialize ] [ FExportBundleEntry : : ExportCommandType_Create ] ;
2021-06-15 16:38:03 -04:00
}
}
2023-04-06 10:50:30 -04:00
StartIndex = ObjectExport . FirstExportDependency ;
for ( int32 Index = StartIndex ; Index < StartIndex + ObjectExport . SerializationBeforeSerializationDependencies ; + + Index )
2021-06-15 16:38:03 -04:00
{
2023-04-06 10:50:30 -04:00
FPackageIndex Dep = CookedHeaderData . PreloadDependencies [ Index ] ;
2021-06-15 16:38:03 -04:00
if ( Dep . IsExport ( ) )
{
2023-04-06 10:50:30 -04:00
AddNodeDependency ( Package , Dep . ToExport ( ) , FExportBundleEntry : : ExportCommandType_Serialize , Export . Nodes [ FExportBundleEntry : : ExportCommandType_Serialize ] ) ;
2021-06-15 16:38:03 -04:00
}
2023-04-06 10:50:30 -04:00
if ( Dep . IsExport ( ) | | ! Package - > Imports [ Dep . ToImport ( ) ] . IsScriptImport ( ) )
2021-06-15 16:38:03 -04:00
{
2023-04-06 10:50:30 -04:00
DependencyBundleEntries . AddDefaulted_GetRef ( ) . LocalImportOrExportIndex = Dep ;
+ + DependencyBundleHeader . EntryCount [ FExportBundleEntry : : ExportCommandType_Serialize ] [ FExportBundleEntry : : ExportCommandType_Serialize ] ;
2021-06-15 16:38:03 -04:00
}
}
}
2023-04-06 10:50:30 -04:00
else
{
DependencyBundleHeader . FirstEntryIndex = - 1 ;
}
2021-06-15 16:38:03 -04:00
}
}
2022-12-13 03:51:37 -05:00
void FPackageStoreOptimizer : : ProcessDataResources ( const FCookedHeaderData & CookedHeaderData , FPackageStorePackage * Package ) const
{
for ( const FObjectDataResource & DataResource : CookedHeaderData . DataResources )
{
FBulkDataMapEntry & Entry = Package - > BulkDataEntries . AddDefaulted_GetRef ( ) ;
checkf ( DataResource . SerialSize = = DataResource . RawSize , TEXT ( " Compressed bulk data is not supported in cooked builds " ) ) ;
Entry . SerialOffset = DataResource . SerialOffset ;
Entry . DuplicateSerialOffset = DataResource . DuplicateSerialOffset ;
Entry . SerialSize = DataResource . SerialSize ;
Entry . Flags = DataResource . LegacyBulkDataFlags ;
2024-10-01 18:59:56 -04:00
Entry . CookedIndex = DataResource . CookedIndex ;
2022-12-13 03:51:37 -05:00
}
}
2021-06-15 16:38:03 -04:00
TArray < FPackageStorePackage : : FExportGraphNode * > FPackageStoreOptimizer : : SortExportGraphNodesInLoadOrder ( FPackageStorePackage * Package , FExportGraphEdges & Edges ) const
{
TRACE_CPUPROFILER_EVENT_SCOPE ( SortExportGraphNodesInLoadOrder ) ;
int32 NodeCount = Package - > ExportGraphNodes . Num ( ) ;
for ( auto & KV : Edges )
{
FPackageStorePackage : : FExportGraphNode * ToNode = KV . Value ;
+ + ToNode - > IncomingEdgeCount ;
}
auto NodeSorter = [ ] ( const FPackageStorePackage : : FExportGraphNode & A , const FPackageStorePackage : : FExportGraphNode & B )
{
if ( A . bIsPublic ! = B . bIsPublic )
{
return A . bIsPublic ;
}
if ( A . BundleEntry . CommandType ! = B . BundleEntry . CommandType )
{
return A . BundleEntry . CommandType < B . BundleEntry . CommandType ;
}
return A . BundleEntry . LocalExportIndex < B . BundleEntry . LocalExportIndex ;
} ;
TArray < FPackageStorePackage : : FExportGraphNode * > NodesWithNoIncomingEdges ;
NodesWithNoIncomingEdges . Reserve ( NodeCount ) ;
for ( FPackageStorePackage : : FExportGraphNode & Node : Package - > ExportGraphNodes )
{
if ( Node . IncomingEdgeCount = = 0 )
{
NodesWithNoIncomingEdges . HeapPush ( & Node , NodeSorter ) ;
}
}
TArray < FPackageStorePackage : : FExportGraphNode * > LoadOrder ;
LoadOrder . Reserve ( NodeCount ) ;
while ( NodesWithNoIncomingEdges . Num ( ) )
{
FPackageStorePackage : : FExportGraphNode * RemovedNode ;
2024-01-19 19:41:56 -05:00
NodesWithNoIncomingEdges . HeapPop ( RemovedNode , NodeSorter , EAllowShrinking : : No ) ;
2021-06-15 16:38:03 -04:00
LoadOrder . Add ( RemovedNode ) ;
for ( auto EdgeIt = Edges . CreateKeyIterator ( RemovedNode ) ; EdgeIt ; + + EdgeIt )
{
FPackageStorePackage : : FExportGraphNode * ToNode = EdgeIt . Value ( ) ;
check ( ToNode - > IncomingEdgeCount > 0 ) ;
if ( - - ToNode - > IncomingEdgeCount = = 0 )
{
NodesWithNoIncomingEdges . HeapPush ( ToNode , NodeSorter ) ;
}
EdgeIt . RemoveCurrent ( ) ;
}
}
check ( LoadOrder . Num ( ) = = NodeCount ) ;
return LoadOrder ;
}
2023-04-06 10:50:30 -04:00
void FPackageStoreOptimizer : : CreateExportBundle ( FPackageStorePackage * Package ) const
2021-02-08 10:48:17 -04:00
{
TRACE_CPUPROFILER_EVENT_SCOPE ( CreateExportBundles ) ;
2021-06-15 16:38:03 -04:00
FExportGraphEdges Edges ;
for ( FPackageStorePackage : : FExportGraphNode & ExportGraphNode : Package - > ExportGraphNodes )
{
for ( FPackageStorePackage : : FExportGraphNode * InternalDependency : ExportGraphNode . InternalDependencies )
{
Edges . Add ( InternalDependency , & ExportGraphNode ) ;
}
}
TArray < FPackageStorePackage : : FExportGraphNode * > LoadOrder = SortExportGraphNodesInLoadOrder ( Package , Edges ) ;
2021-02-08 10:48:17 -04:00
for ( FPackageStorePackage : : FExportGraphNode * Node : LoadOrder )
{
2023-04-06 10:50:30 -04:00
Package - > GraphData . ExportBundleEntries . Add ( Node - > BundleEntry ) ;
2021-02-08 10:48:17 -04:00
}
}
void FPackageStoreOptimizer : : FinalizePackageHeader ( FPackageStorePackage * Package ) const
{
2021-11-18 14:37:34 -05:00
FBufferWriter ImportedPublicExportHashesArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
for ( uint64 ImportedPublicExportHash : Package - > ImportedPublicExportHashes )
{
ImportedPublicExportHashesArchive < < ImportedPublicExportHash ;
}
2023-03-24 10:06:23 -04:00
uint64 ImportedPublicExportHashesSize = ImportedPublicExportHashesArchive . Tell ( ) ;
2021-11-18 14:37:34 -05:00
2021-02-08 10:48:17 -04:00
FBufferWriter ImportMapArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
2021-08-02 07:21:44 -04:00
for ( FPackageObjectIndex Import : Package - > Imports )
2021-02-08 10:48:17 -04:00
{
2021-08-02 07:21:44 -04:00
ImportMapArchive < < Import ;
2021-02-08 10:48:17 -04:00
}
2023-03-24 10:06:23 -04:00
uint64 ImportMapSize = ImportMapArchive . Tell ( ) ;
2021-02-08 10:48:17 -04:00
FBufferWriter ExportMapArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
for ( const FPackageStorePackage : : FExport & Export : Package - > Exports )
{
FExportMapEntry ExportMapEntry ;
2023-04-06 10:50:30 -04:00
ExportMapEntry . CookedSerialOffset = Export . SerialOffset ;
2021-06-15 16:38:03 -04:00
ExportMapEntry . CookedSerialSize = Export . SerialSize ;
2021-09-30 02:05:41 -04:00
Package - > NameMapBuilder . MarkNameAsReferenced ( Export . ObjectName ) ;
2021-02-08 10:48:17 -04:00
ExportMapEntry . ObjectName = Package - > NameMapBuilder . MapName ( Export . ObjectName ) ;
2021-11-18 14:37:34 -05:00
ExportMapEntry . PublicExportHash = Export . PublicExportHash ;
2021-02-08 10:48:17 -04:00
ExportMapEntry . OuterIndex = Export . OuterIndex ;
ExportMapEntry . ClassIndex = Export . ClassIndex ;
ExportMapEntry . SuperIndex = Export . SuperIndex ;
ExportMapEntry . TemplateIndex = Export . TemplateIndex ;
ExportMapEntry . ObjectFlags = Export . ObjectFlags ;
ExportMapEntry . FilterFlags = EExportFilterFlags : : None ;
if ( Export . bNotForClient )
{
ExportMapEntry . FilterFlags = EExportFilterFlags : : NotForClient ;
}
else if ( Export . bNotForServer )
{
ExportMapEntry . FilterFlags = EExportFilterFlags : : NotForServer ;
}
ExportMapArchive < < ExportMapEntry ;
}
2023-03-24 10:06:23 -04:00
uint64 ExportMapSize = ExportMapArchive . Tell ( ) ;
2021-02-08 10:48:17 -04:00
2021-06-15 16:38:03 -04:00
FBufferWriter ExportBundleEntriesArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
2023-04-06 10:50:30 -04:00
for ( FExportBundleEntry BundleEntry : Package - > GraphData . ExportBundleEntries )
2021-02-08 10:48:17 -04:00
{
2023-04-06 10:50:30 -04:00
ExportBundleEntriesArchive < < BundleEntry ;
2021-02-08 10:48:17 -04:00
}
2023-03-24 10:06:23 -04:00
uint64 ExportBundleEntriesSize = ExportBundleEntriesArchive . Tell ( ) ;
2021-06-15 16:38:03 -04:00
2023-04-06 10:50:30 -04:00
FBufferWriter DependencyBundleHeadersArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
for ( FDependencyBundleHeader DependencyBundleHeader : Package - > GraphData . DependencyBundleHeaders )
{
DependencyBundleHeadersArchive < < DependencyBundleHeader ;
}
FBufferWriter DependencyBundleEntriesArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
for ( FDependencyBundleEntry DependencyBundleEntry : Package - > GraphData . DependencyBundleEntries )
{
DependencyBundleEntriesArchive < < DependencyBundleEntry ;
}
uint64 GraphDataSize = DependencyBundleHeadersArchive . Tell ( ) + DependencyBundleEntriesArchive . Tell ( ) ;
2021-02-08 10:48:17 -04:00
Package - > NameMapBuilder . MarkNameAsReferenced ( Package - > Name ) ;
FMappedName MappedPackageName = Package - > NameMapBuilder . MapName ( Package - > Name ) ;
2023-03-31 07:20:51 -04:00
FZenPackageImportedPackageNamesContainer ImportedPackageNamesContainer ;
ImportedPackageNamesContainer . Names . Reserve ( Package - > ImportedPackages . Num ( ) ) ;
for ( const FPackageStorePackage : : FImportedPackageRef & ImportedPackage : Package - > ImportedPackages )
{
ImportedPackageNamesContainer . Names . Add ( ImportedPackage . Name ) ;
}
FBufferWriter ImportedPackagesArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
ImportedPackagesArchive < < ImportedPackageNamesContainer ;
uint64 ImportedPackagesSize = ImportedPackagesArchive . Tell ( ) ;
2021-06-15 16:38:03 -04:00
FBufferWriter NameMapArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
SaveNameBatch ( Package - > NameMapBuilder . GetNameMap ( ) , NameMapArchive ) ;
2023-03-24 10:06:23 -04:00
uint64 NameMapSize = NameMapArchive . Tell ( ) ;
2021-02-08 10:48:17 -04:00
2021-10-12 21:21:22 -04:00
FBufferWriter VersioningInfoArchive ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
if ( Package - > VersioningInfo . IsSet ( ) )
{
VersioningInfoArchive < < Package - > VersioningInfo . GetValue ( ) ;
}
2023-03-24 10:06:23 -04:00
uint64 VersioningInfoSize = VersioningInfoArchive . Tell ( ) ;
2022-12-13 03:51:37 -05:00
FBufferWriter BulkDataMapAr ( nullptr , 0 , EBufferWriterFlags : : AllowResize | EBufferWriterFlags : : TakeOwnership ) ;
for ( FBulkDataMapEntry & Entry : Package - > BulkDataEntries )
{
BulkDataMapAr < < Entry ;
}
2023-03-24 10:06:23 -04:00
uint64 BulkDataMapSize = BulkDataMapAr . Tell ( ) ;
2021-10-12 21:21:22 -04:00
2023-08-29 07:38:16 -04:00
uint64 BulkDataPad = 0 ;
uint64 OffsetBeforeBulkDataMap =
2021-10-12 21:21:22 -04:00
sizeof ( FZenPackageSummary )
2023-03-24 10:06:23 -04:00
+ VersioningInfoSize
+ NameMapSize
2023-08-29 07:38:16 -04:00
+ sizeof ( BulkDataPad ) ;
2023-08-16 06:18:19 -04:00
2023-08-29 07:38:16 -04:00
uint64 AlignedOffsetBeforeBulkDataMap = Align ( OffsetBeforeBulkDataMap , sizeof ( uint64 ) ) ;
BulkDataPad = AlignedOffsetBeforeBulkDataMap - OffsetBeforeBulkDataMap ;
uint64 OffsetBeforePublicExportHashes =
AlignedOffsetBeforeBulkDataMap
+ BulkDataMapSize + sizeof ( BulkDataMapSize ) ;
uint64 AlignedOffsetBeforePublicExportHashes = Align ( OffsetBeforePublicExportHashes , sizeof ( uint64 ) ) ;
2023-08-16 06:18:19 -04:00
uint64 HeaderSize =
2023-08-29 07:38:16 -04:00
AlignedOffsetBeforePublicExportHashes
2023-03-24 10:06:23 -04:00
+ ImportedPublicExportHashesSize
+ ImportMapSize
+ ExportMapSize
+ ExportBundleEntriesSize
+ GraphDataSize
2023-08-16 06:18:19 -04:00
+ ImportedPackagesSize ;
2021-02-08 10:48:17 -04:00
2023-04-06 10:50:30 -04:00
Package - > HeaderBuffer = FIoBuffer ( HeaderSize ) ;
2021-06-15 16:38:03 -04:00
uint8 * HeaderData = Package - > HeaderBuffer . Data ( ) ;
2023-04-06 10:50:30 -04:00
FMemory : : Memzero ( HeaderData , HeaderSize ) ;
2021-10-12 21:21:22 -04:00
FZenPackageSummary * PackageSummary = reinterpret_cast < FZenPackageSummary * > ( HeaderData ) ;
2023-04-06 10:50:30 -04:00
PackageSummary - > HeaderSize = HeaderSize ;
2021-02-08 10:48:17 -04:00
PackageSummary - > Name = MappedPackageName ;
PackageSummary - > PackageFlags = Package - > PackageFlags ;
PackageSummary - > CookedHeaderSize = Package - > CookedHeaderSize ;
2023-04-06 10:50:30 -04:00
FBufferWriter HeaderArchive ( HeaderData , HeaderSize ) ;
2021-10-12 21:21:22 -04:00
HeaderArchive . Seek ( sizeof ( FZenPackageSummary ) ) ;
2021-02-08 10:48:17 -04:00
2021-10-12 21:21:22 -04:00
if ( Package - > VersioningInfo . IsSet ( ) )
2021-02-08 10:48:17 -04:00
{
2021-10-12 21:21:22 -04:00
PackageSummary - > bHasVersioningInfo = 1 ;
HeaderArchive . Serialize ( VersioningInfoArchive . GetWriterData ( ) , VersioningInfoArchive . Tell ( ) ) ;
}
else
{
PackageSummary - > bHasVersioningInfo = 0 ;
2021-02-08 10:48:17 -04:00
}
2021-06-15 16:38:03 -04:00
HeaderArchive . Serialize ( NameMapArchive . GetWriterData ( ) , NameMapArchive . Tell ( ) ) ;
2022-12-13 03:51:37 -05:00
2023-08-29 07:38:16 -04:00
HeaderArchive < < BulkDataPad ;
if ( BulkDataPad > 0 )
{
uint8 PadBytes [ sizeof ( uint64 ) ] = { } ;
HeaderArchive . Serialize ( PadBytes , BulkDataPad ) ;
}
check ( HeaderArchive . Tell ( ) = = AlignedOffsetBeforeBulkDataMap ) ;
2023-03-24 10:06:23 -04:00
HeaderArchive < < BulkDataMapSize ;
HeaderArchive . Serialize ( BulkDataMapAr . GetWriterData ( ) , BulkDataMapSize ) ;
2022-12-13 03:51:37 -05:00
2023-08-29 07:38:16 -04:00
if ( uint64 Pad = AlignedOffsetBeforePublicExportHashes - OffsetBeforePublicExportHashes ; Pad > 0 )
2023-08-16 06:18:19 -04:00
{
uint8 PadBytes [ sizeof ( uint64 ) ] = { } ;
2023-08-29 07:38:16 -04:00
HeaderArchive . Serialize ( PadBytes , Pad ) ;
2023-08-16 06:18:19 -04:00
}
2023-08-29 07:38:16 -04:00
check ( HeaderArchive . Tell ( ) = = AlignedOffsetBeforePublicExportHashes ) ;
2023-08-16 06:18:19 -04:00
// raw arrays of 8-byte aligned items
2021-11-18 14:37:34 -05:00
PackageSummary - > ImportedPublicExportHashesOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( ImportedPublicExportHashesArchive . GetWriterData ( ) , ImportedPublicExportHashesArchive . Tell ( ) ) ;
2021-06-15 16:38:03 -04:00
PackageSummary - > ImportMapOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( ImportMapArchive . GetWriterData ( ) , ImportMapArchive . Tell ( ) ) ;
PackageSummary - > ExportMapOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( ExportMapArchive . GetWriterData ( ) , ExportMapArchive . Tell ( ) ) ;
2023-08-16 06:18:19 -04:00
// raw arrays of 4-byte aligned items
2021-06-15 16:38:03 -04:00
PackageSummary - > ExportBundleEntriesOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( ExportBundleEntriesArchive . GetWriterData ( ) , ExportBundleEntriesArchive . Tell ( ) ) ;
2023-04-06 10:50:30 -04:00
PackageSummary - > DependencyBundleHeadersOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( DependencyBundleHeadersArchive . GetWriterData ( ) , DependencyBundleHeadersArchive . Tell ( ) ) ;
PackageSummary - > DependencyBundleEntriesOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( DependencyBundleEntriesArchive . GetWriterData ( ) , DependencyBundleEntriesArchive . Tell ( ) ) ;
2023-03-31 07:20:51 -04:00
PackageSummary - > ImportedPackageNamesOffset = HeaderArchive . Tell ( ) ;
HeaderArchive . Serialize ( ImportedPackagesArchive . GetWriterData ( ) , ImportedPackagesArchive . Tell ( ) ) ;
2021-06-15 16:38:03 -04:00
check ( HeaderArchive . Tell ( ) = = PackageSummary - > HeaderSize )
2021-02-08 10:48:17 -04:00
}
2023-04-06 10:50:30 -04:00
FIoBuffer FPackageStoreOptimizer : : CreatePackageBuffer ( const FPackageStorePackage * Package , const FIoBuffer & CookedExportsDataBuffer ) const
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
check ( Package - > HeaderBuffer . DataSize ( ) > 0 ) ;
2023-04-06 10:50:30 -04:00
const uint64 BundleBufferSize = Package - > HeaderBuffer . DataSize ( ) + CookedExportsDataBuffer . DataSize ( ) ;
2021-02-08 10:48:17 -04:00
FIoBuffer BundleBuffer ( BundleBufferSize ) ;
2023-04-06 10:50:30 -04:00
FMemory : : Memcpy ( BundleBuffer . Data ( ) , Package - > HeaderBuffer . Data ( ) , Package - > HeaderBuffer . DataSize ( ) ) ;
FMemory : : Memcpy ( BundleBuffer . Data ( ) + Package - > HeaderBuffer . DataSize ( ) , CookedExportsDataBuffer . Data ( ) , CookedExportsDataBuffer . DataSize ( ) ) ;
2021-02-08 10:48:17 -04:00
return BundleBuffer ;
}
2023-09-13 18:11:20 -04:00
void FPackageStoreOptimizer : : FindScriptObjectsRecursive (
TMap < FPackageObjectIndex , FScriptObjectData > & OutScriptObjectsMap , FPackageObjectIndex OuterIndex , UObject * Object )
2021-02-08 10:48:17 -04:00
{
if ( ! Object - > HasAllFlags ( RF_Public ) )
{
UE_LOG ( LogPackageStoreOptimizer , Verbose , TEXT ( " Skipping script object: %s (!RF_Public) " ) , * Object - > GetFullName ( ) ) ;
return ;
}
2021-03-18 15:20:03 -04:00
FString OuterFullName ;
FPackageObjectIndex OuterCDOClassIndex ;
{
2023-09-13 18:11:20 -04:00
const FScriptObjectData * Outer = OutScriptObjectsMap . Find ( OuterIndex ) ;
2021-03-18 15:20:03 -04:00
check ( Outer ) ;
OuterFullName = Outer - > FullName ;
OuterCDOClassIndex = Outer - > CDOClassIndex ;
}
2021-02-08 10:48:17 -04:00
FName ObjectName = Object - > GetFName ( ) ;
2021-03-18 15:20:03 -04:00
FString TempFullName = OuterFullName ;
2021-02-08 10:48:17 -04:00
TempFullName . AppendChar ( TEXT ( ' / ' ) ) ;
ObjectName . AppendString ( TempFullName ) ;
TempFullName . ToLowerInline ( ) ;
FPackageObjectIndex GlobalImportIndex = FPackageObjectIndex : : FromScriptPath ( TempFullName ) ;
2023-09-13 18:11:20 -04:00
FScriptObjectData * ScriptImport = OutScriptObjectsMap . Find ( GlobalImportIndex ) ;
2021-02-08 10:48:17 -04:00
if ( ScriptImport )
{
UE_LOG ( LogPackageStoreOptimizer , Fatal , TEXT ( " Import name hash collision \" %s \" and \" %s " ) , * TempFullName , * ScriptImport - > FullName ) ;
}
2021-03-18 15:20:03 -04:00
FPackageObjectIndex CDOClassIndex = OuterCDOClassIndex ;
2021-02-08 10:48:17 -04:00
if ( CDOClassIndex . IsNull ( ) )
{
TCHAR NameBuffer [ FName : : StringBufferSize ] ;
uint32 Len = ObjectName . ToString ( NameBuffer ) ;
if ( FCString : : Strncmp ( NameBuffer , TEXT ( " Default__ " ) , 9 ) = = 0 )
{
2021-03-18 15:20:03 -04:00
FString CDOClassFullName = OuterFullName ;
2021-02-08 10:48:17 -04:00
CDOClassFullName . AppendChar ( TEXT ( ' / ' ) ) ;
CDOClassFullName . AppendChars ( NameBuffer + 9 , Len - 9 ) ;
CDOClassFullName . ToLowerInline ( ) ;
CDOClassIndex = FPackageObjectIndex : : FromScriptPath ( CDOClassFullName ) ;
}
}
2023-09-13 18:11:20 -04:00
ScriptImport = & OutScriptObjectsMap . Add ( GlobalImportIndex ) ;
2021-02-08 10:48:17 -04:00
ScriptImport - > GlobalIndex = GlobalImportIndex ;
ScriptImport - > FullName = MoveTemp ( TempFullName ) ;
2021-03-18 15:20:03 -04:00
ScriptImport - > OuterIndex = OuterIndex ;
2021-02-08 10:48:17 -04:00
ScriptImport - > ObjectName = ObjectName ;
ScriptImport - > CDOClassIndex = CDOClassIndex ;
TArray < UObject * > InnerObjects ;
GetObjectsWithOuter ( Object , InnerObjects , /*bIncludeNestedObjects*/ false ) ;
for ( UObject * InnerObject : InnerObjects )
{
2023-09-13 18:11:20 -04:00
FindScriptObjectsRecursive ( OutScriptObjectsMap , GlobalImportIndex , InnerObject ) ;
2021-02-08 10:48:17 -04:00
}
} ;
2021-10-12 21:21:22 -04:00
void FPackageStoreOptimizer : : FindScriptObjects ( )
2023-09-13 18:11:20 -04:00
{
FindScriptObjects ( ScriptObjectsMap ) ;
TotalScriptObjectCount = ScriptObjectsMap . Num ( ) ;
}
void FPackageStoreOptimizer : : FindScriptObjects ( TMap < FPackageObjectIndex , FScriptObjectData > & OutScriptObjectsMap )
2021-02-08 10:48:17 -04:00
{
2023-02-06 11:39:10 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FindScriptObjects ) ;
2021-02-08 10:48:17 -04:00
TArray < UPackage * > ScriptPackages ;
FindAllRuntimeScriptPackages ( ScriptPackages ) ;
TArray < UObject * > InnerObjects ;
for ( UPackage * Package : ScriptPackages )
{
FName ObjectName = Package - > GetFName ( ) ;
FString FullName = Package - > GetName ( ) ;
FullName . ToLowerInline ( ) ;
FPackageObjectIndex GlobalImportIndex = FPackageObjectIndex : : FromScriptPath ( FullName ) ;
2023-09-13 18:11:20 -04:00
FScriptObjectData * ScriptImport = OutScriptObjectsMap . Find ( GlobalImportIndex ) ;
2021-02-08 10:48:17 -04:00
checkf ( ! ScriptImport , TEXT ( " Import name hash collision \" %s \" and \" %s " ) , * FullName , * ScriptImport - > FullName ) ;
2023-09-13 18:11:20 -04:00
ScriptImport = & OutScriptObjectsMap . Add ( GlobalImportIndex ) ;
2021-02-08 10:48:17 -04:00
ScriptImport - > GlobalIndex = GlobalImportIndex ;
ScriptImport - > FullName = FullName ;
ScriptImport - > OuterIndex = FPackageObjectIndex ( ) ;
ScriptImport - > ObjectName = ObjectName ;
InnerObjects . Reset ( ) ;
GetObjectsWithOuter ( Package , InnerObjects , /*bIncludeNestedObjects*/ false ) ;
for ( UObject * InnerObject : InnerObjects )
{
2023-09-13 18:11:20 -04:00
FindScriptObjectsRecursive ( OutScriptObjectsMap , GlobalImportIndex , InnerObject ) ;
2021-02-08 10:48:17 -04:00
}
}
}
2021-06-15 16:38:03 -04:00
FIoBuffer FPackageStoreOptimizer : : CreateScriptObjectsBuffer ( ) const
2021-02-08 10:48:17 -04:00
{
TArray < FScriptObjectData > ScriptObjectsAsArray ;
ScriptObjectsMap . GenerateValueArray ( ScriptObjectsAsArray ) ;
Algo : : Sort ( ScriptObjectsAsArray , [ ] ( const FScriptObjectData & A , const FScriptObjectData & B )
{
return A . FullName < B . FullName ;
} ) ;
2021-06-15 16:38:03 -04:00
TArray < FScriptObjectEntry > ScriptObjectEntries ;
ScriptObjectEntries . Reserve ( ScriptObjectsAsArray . Num ( ) ) ;
2021-02-08 10:48:17 -04:00
FPackageStoreNameMapBuilder NameMapBuilder ;
NameMapBuilder . SetNameMapType ( FMappedName : : EType : : Global ) ;
for ( const FScriptObjectData & ImportData : ScriptObjectsAsArray )
{
NameMapBuilder . MarkNameAsReferenced ( ImportData . ObjectName ) ;
2021-06-15 16:38:03 -04:00
FScriptObjectEntry & Entry = ScriptObjectEntries . AddDefaulted_GetRef ( ) ;
2022-02-21 02:35:48 -05:00
Entry . Mapped = NameMapBuilder . MapName ( ImportData . ObjectName ) ;
2021-02-08 10:48:17 -04:00
Entry . GlobalIndex = ImportData . GlobalIndex ;
Entry . OuterIndex = ImportData . OuterIndex ;
Entry . CDOClassIndex = ImportData . CDOClassIndex ;
2021-06-15 16:38:03 -04:00
}
2021-02-08 10:48:17 -04:00
2021-06-15 16:38:03 -04:00
FLargeMemoryWriter ScriptObjectsArchive ( 0 , true ) ;
SaveNameBatch ( NameMapBuilder . GetNameMap ( ) , ScriptObjectsArchive ) ;
int32 NumScriptObjects = ScriptObjectEntries . Num ( ) ;
ScriptObjectsArchive < < NumScriptObjects ;
for ( FScriptObjectEntry & Entry : ScriptObjectEntries )
{
2021-02-08 10:48:17 -04:00
ScriptObjectsArchive < < Entry ;
}
2021-06-15 16:38:03 -04:00
int64 DataSize = ScriptObjectsArchive . TotalSize ( ) ;
return FIoBuffer ( FIoBuffer : : AssumeOwnership , ScriptObjectsArchive . ReleaseOwnership ( ) , DataSize ) ;
2021-02-08 10:48:17 -04:00
}
2021-09-15 10:39:23 -04:00
void FPackageStoreOptimizer : : LoadScriptObjectsBuffer ( const FIoBuffer & ScriptObjectsBuffer )
{
2023-02-06 11:39:10 -05:00
TRACE_CPUPROFILER_EVENT_SCOPE ( LoadScriptObjectsBuffer ) ;
2021-09-15 10:39:23 -04:00
FLargeMemoryReader ScriptObjectsArchive ( ScriptObjectsBuffer . Data ( ) , ScriptObjectsBuffer . DataSize ( ) ) ;
2022-04-25 03:48:33 -04:00
TArray < FDisplayNameEntryId > NameMap = LoadNameBatch ( ScriptObjectsArchive ) ;
2021-09-15 10:39:23 -04:00
int32 NumScriptObjects ;
ScriptObjectsArchive < < NumScriptObjects ;
for ( int32 Index = 0 ; Index < NumScriptObjects ; + + Index )
{
2022-02-21 02:35:48 -05:00
FScriptObjectEntry Entry { } ;
2021-09-15 10:39:23 -04:00
ScriptObjectsArchive < < Entry ;
FScriptObjectData & ImportData = ScriptObjectsMap . Add ( Entry . GlobalIndex ) ;
2022-02-21 02:35:48 -05:00
FMappedName MappedName = Entry . Mapped ;
2022-04-25 03:48:33 -04:00
ImportData . ObjectName = NameMap [ MappedName . GetIndex ( ) ] . ToName ( MappedName . GetNumber ( ) ) ;
2021-09-15 10:39:23 -04:00
ImportData . GlobalIndex = Entry . GlobalIndex ;
ImportData . OuterIndex = Entry . OuterIndex ;
ImportData . CDOClassIndex = Entry . CDOClassIndex ;
}
}
2022-04-25 07:37:07 -04:00
FPackageStoreEntryResource FPackageStoreOptimizer : : CreatePackageStoreEntry ( const FPackageStorePackage * Package , const FPackageStorePackage * OptionalSegmentPackage ) const
2021-02-08 10:48:17 -04:00
{
2021-06-15 16:38:03 -04:00
FPackageStoreEntryResource Result ;
2023-03-24 10:06:23 -04:00
Result . Flags = EPackageStoreEntryFlags : : None ;
2022-06-17 04:25:23 -04:00
2023-03-29 04:40:20 -04:00
if ( OptionalSegmentPackage )
2022-06-17 04:25:23 -04:00
{
2023-03-29 04:40:20 -04:00
Result . Flags | = EPackageStoreEntryFlags : : OptionalSegment ;
if ( OptionalSegmentPackage - > HasEditorData ( ) )
{
// AutoOptional packages are saved with editor data included
Result . Flags | = EPackageStoreEntryFlags : : AutoOptional ;
}
2022-06-17 04:25:23 -04:00
}
2021-06-15 16:38:03 -04:00
Result . PackageName = Package - > Name ;
2023-02-08 00:25:34 -05:00
Result . PackageId = FPackageId : : FromName ( Package - > Name ) ;
2023-03-29 04:40:20 -04:00
Result . ImportedPackageIds . Reserve ( Package - > ImportedPackages . Num ( ) ) ;
for ( const FPackageStorePackage : : FImportedPackageRef & ImportedPackage : Package - > ImportedPackages )
{
Result . ImportedPackageIds . Add ( ImportedPackage . Id ) ;
}
2023-03-24 10:06:23 -04:00
2022-04-25 07:37:07 -04:00
if ( OptionalSegmentPackage )
{
2023-03-29 04:40:20 -04:00
Result . OptionalSegmentImportedPackageIds . Reserve ( OptionalSegmentPackage - > ImportedPackages . Num ( ) ) ;
for ( const FPackageStorePackage : : FImportedPackageRef & ImportedPackage : OptionalSegmentPackage - > ImportedPackages )
{
Result . OptionalSegmentImportedPackageIds . Add ( ImportedPackage . Id ) ;
}
2022-04-25 07:37:07 -04:00
}
2024-06-19 12:16:51 -04:00
Result . SoftPackageReferences . Reserve ( Package - > SoftPackageReferences . Num ( ) ) ;
for ( const FName & SoftRefName : Package - > SoftPackageReferences )
{
TCHAR NameStr [ FName : : StringBufferSize ] ;
const uint32 NameLen = SoftRefName . ToString ( NameStr ) ;
const FStringView SoftRef ( NameStr , NameLen ) ;
if ( ! FPackageName : : IsScriptPackage ( SoftRef ) )
{
if ( ! FPackageName : : IsValidLongPackageName ( SoftRef ) )
{
UE_LOG ( LogPackageStoreOptimizer , Warning , TEXT ( " Invalid soft package reference name '%s' " ) , * SoftRefName . ToString ( ) ) ;
continue ;
}
Result . SoftPackageReferences . Add ( FPackageId : : FromName ( SoftRefName ) ) ;
}
}
Result . SoftPackageReferences . Sort ( ) ;
2021-02-08 10:48:17 -04:00
return Result ;
}