/** * Return the path name of the UObject represented by the specified export. * (can be used with StaticFindObject) * * @param ExportIndex index into the ExportMap for the resource to get the name for * @param FakeRoot Optional name to replace use as the root package of this object instead of the linker * @param bResolveForcedExports if true, the package name part of the return value will be the export's original package, * not the name of the package it's currently contained within. * * @return the path name of the UObject represented by the resource at ExportIndex */ FString ULinker::GetExportPathName(int32 ExportIndex, const TCHAR* FakeRoot,bool bResolveForcedExports/*=false*/) { FString Result; ULinkerLoad* Loader = dynamic_cast<ULinkerLoad*>(this); bool bForcedExport = false; for ( FPackageIndex LinkerIndex = FPackageIndex::FromExport(ExportIndex); !LinkerIndex.IsNull(); LinkerIndex = Exp(LinkerIndex).OuterIndex ) { const FObjectExport Export = Exp(LinkerIndex); // don't append a dot in the first iteration if ( Result.Len() > 0 ) { // if this export is not a UPackage but this export's Outer is a UPackage, we need to use subobject notation if (Loader != NULL && ( Export.OuterIndex.IsNull() || Loader->GetExportClassName(Export.OuterIndex) == NAME_Package) && Loader->GetExportClassName(LinkerIndex) != NAME_Package) { Result = FString(SUBOBJECT_DELIMITER) + Result; } else { Result = FString(TEXT(".")) + Result; } } Result = Export.ObjectName.ToString() + Result; bForcedExport = bForcedExport || Export.bForcedExport; } if ( bForcedExport && FakeRoot == NULL && bResolveForcedExports ) { // Result already contains the correct path name for this export return Result; } return (FakeRoot ? FakeRoot : LinkerRoot->GetPathName()) + TEXT(".") + Result; }
void FPackageDependencyInfo::RecursiveDeterminePackageDependentTimeStamp(const TCHAR* InPackageName, FDateTime& OutNewestTime, bool& bOutHadCircularReferences) { // Find the package info... FPackageDependencyTrackingInfo** pPkgInfo = PackageInformation.Find(InPackageName); if ((pPkgInfo != NULL) && (*pPkgInfo != NULL)) { FPackageDependencyTrackingInfo* PkgInfo = *pPkgInfo; if (PkgInfo->bBeingProcessed == true) { // Circular reference?? bOutHadCircularReferences = true; return; } checkf((PkgInfo->DependentTimeStamp == FDateTime::MinValue()), TEXT("RecursiveDeterminePackageDependentTimeStamp: Package already processed: %s"), InPackageName); // We have the package info, so process the actual package. BeginLoad(); ULinkerLoad* Linker = GetPackageLinker(NULL, InPackageName, LOAD_NoVerify, NULL, NULL); EndLoad(); if (Linker != NULL) { PkgInfo->bBeingProcessed = true; // Start off with setting the dependent time to the package itself PkgInfo->DependentTimeStamp = PkgInfo->TimeStamp; // Map? Code (ie blueprint)? PkgInfo->bContainsMap = Linker->ContainsMap(); PkgInfo->bContainsBlueprints = Linker->ContainsCode(); FName CheckMaterial = FName(TEXT("Material")); FName CheckMIC = FName(TEXT("MaterialInstanceConstant")); FName CheckMID = FName(TEXT("MaterialInstanceDynamic")); FName CheckLMIC = FName(TEXT("LandscapeMaterialInstanceConstant")); FName CheckWorld = FName(TEXT("World")); FName CheckBlueprint = FName(TEXT("Blueprint")); FName CheckAnimBlueprint = FName(TEXT("AnimBlueprint")); // Check the export map for material interfaces for (int32 ExpIdx = 0; ExpIdx < Linker->ExportMap.Num(); ExpIdx++) { FObjectExport& ObjExp = Linker->ExportMap[ExpIdx]; FName ExpClassName = Linker->GetExportClassName(ExpIdx); if ((ExpClassName == CheckMaterial) || (ExpClassName == CheckMIC) || (ExpClassName == CheckMID) || (ExpClassName == CheckLMIC)) { PkgInfo->bContainsShaders = true; if (PkgInfo->DependentTimeStamp < ShaderSourceTimeStamp) { PkgInfo->DependentTimeStamp = ShaderSourceTimeStamp; } PkgInfo->DependentPackages.Add(ShaderSourcePkgName, ShaderSourcePkgInfo); AllPackages.Add(ShaderSourcePkgInfo); } else if (ExpClassName == CheckWorld) { PkgInfo->bContainsMap = true; } else if ((ExpClassName == CheckBlueprint) || (ExpClassName == CheckAnimBlueprint)) { PkgInfo->bContainsBlueprints = true; if (PkgInfo->DependentTimeStamp < ScriptSourceTimeStamp) { PkgInfo->DependentTimeStamp = ScriptSourceTimeStamp; } PkgInfo->DependentPackages.Add(ScriptSourcePkgName, ScriptSourcePkgInfo); AllPackages.Add(ScriptSourcePkgInfo); } } // Check the dependencies //@todo. Make this a function of the linker? Almost the exact same code is used in PkgInfo commandlet... FName LinkerName = Linker->LinkerRoot->GetFName(); TArray<FName> DependentPackages; for (int32 ImpIdx = 0; ImpIdx < Linker->ImportMap.Num(); ImpIdx++) { FObjectImport& ObjImp = Linker->ImportMap[ImpIdx]; FName PackageName = NAME_None; FName OuterName = NAME_None; if (!ObjImp.OuterIndex.IsNull()) { // Find the package which contains this import. import.SourceLinker is cleared in EndLoad, so we'll need to do this manually now. FPackageIndex OutermostLinkerIndex = ObjImp.OuterIndex; for (FPackageIndex LinkerIndex = ObjImp.OuterIndex; !LinkerIndex.IsNull();) { OutermostLinkerIndex = LinkerIndex; LinkerIndex = Linker->ImpExp(LinkerIndex).OuterIndex; } PackageName = Linker->ImpExp(OutermostLinkerIndex).ObjectName; } if (PackageName == NAME_None && ObjImp.ClassName == NAME_Package) { PackageName = ObjImp.ObjectName; } if ((PackageName != NAME_None) && (PackageName != LinkerName)) { DependentPackages.AddUnique(PackageName); } if ((ObjImp.ClassPackage != NAME_None) && (ObjImp.ClassPackage != LinkerName)) { DependentPackages.AddUnique(ObjImp.ClassPackage); } } for (int32 DependentIdx = 0; DependentIdx < DependentPackages.Num(); DependentIdx++) { FString PkgName = DependentPackages[DependentIdx].ToString(); FText Reason; if (!FPackageName::IsValidLongPackageName(PkgName, true, &Reason)) { //UE_LOG(LogPackageDependencyInfo, Display, TEXT("%s --> %s"), *PkgName, *Reason.ToString()); continue; } FString LongName = FPackageName::LongPackageNameToFilename(PkgName); //UE_LOG(LogPackageDependencyInfo, Display, TEXT("%s --> %s"), *PkgName, *LongName); // Is it already in the list FPackageDependencyTrackingInfo** pDepPkgInfo = PackageInformation.Find(LongName); if ((pDepPkgInfo == NULL) || (*pDepPkgInfo == NULL)) { continue; } FPackageDependencyTrackingInfo* DepPkgInfo = *pDepPkgInfo; if (DepPkgInfo->bBeingProcessed == true) { bOutHadCircularReferences = true; // Circular reference // For now, store it off and we will resolve when completed PkgInfo->DependentPackages.Add(LongName, DepPkgInfo); PkgInfo->bHasCircularReferences = true; AllPackages.Add(PkgInfo); continue; } if (DepPkgInfo->DependentTimeStamp == FDateTime::MinValue()) { FDateTime TempTime; RecursiveDeterminePackageDependentTimeStamp(*LongName, TempTime, bOutHadCircularReferences); } PkgInfo->DependentPackages.Add(LongName, DepPkgInfo); AllPackages.Add(DepPkgInfo); if (DepPkgInfo->DependentTimeStamp != FDateTime::MinValue()) { if (PkgInfo->DependentTimeStamp < DepPkgInfo->DependentTimeStamp) { PkgInfo->DependentTimeStamp = DepPkgInfo->DependentTimeStamp; } } } PkgInfo->bBeingProcessed = false; OutNewestTime = PkgInfo->DependentTimeStamp; } else { UE_LOG(LogPackageDependencyInfo, Display, TEXT("RecursiveDeterminePackageDependentTimeStamp: Failed to find linker for %s"), InPackageName); } } else { UE_LOG(LogPackageDependencyInfo, Display, TEXT("RecursiveDeterminePackageDependentTimeStamp: Failed to find package info for %s"), InPackageName); } }