void FBlueprintNativeCodeGenModule::GenerateSingleAsset(UField* ForConversion, const TCHAR* PlatformName, TSharedPtr<FNativizationSummary> NativizationSummary) { IBlueprintCompilerCppBackendModule& BackEndModule = (IBlueprintCompilerCppBackendModule&)IBlueprintCompilerCppBackendModule::Get(); auto& BackendPCHQuery = BackEndModule.OnPCHFilenameQuery(); const IAssetRegistry& Registry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get(); FAssetData AssetInfo = Registry.GetAssetByObjectPath(*ForConversion->GetPathName()); FBlueprintNativeCodeGenPaths TargetPaths = GetManifest(PlatformName).GetTargetPaths(); BackendPCHQuery.BindLambda([TargetPaths]()->FString { return TargetPaths.RuntimePCHFilename(); }); FConvertedAssetRecord& ConversionRecord = GetManifest(PlatformName).CreateConversionRecord(*ForConversion->GetPathName(), AssetInfo); TSharedPtr<FString> HeaderSource(new FString()); TSharedPtr<FString> CppSource(new FString()); FBlueprintNativeCodeGenUtils::GenerateCppCode(ForConversion, HeaderSource, CppSource, NativizationSummary); bool bSuccess = !HeaderSource->IsEmpty() || !CppSource->IsEmpty(); // Run the cpp first, because we cue off of the presence of a header for a valid conversion record (see // FConvertedAssetRecord::IsValid) if (!CppSource->IsEmpty()) { if (!FFileHelper::SaveStringToFile(*CppSource, *ConversionRecord.GeneratedCppPath, ForcedEncoding())) { bSuccess &= false; ConversionRecord.GeneratedCppPath.Empty(); } CppSource->Empty(CppSource->Len()); } else { ConversionRecord.GeneratedCppPath.Empty(); } if (bSuccess && !HeaderSource->IsEmpty()) { if (!FFileHelper::SaveStringToFile(*HeaderSource, *ConversionRecord.GeneratedHeaderPath, ForcedEncoding())) { bSuccess &= false; ConversionRecord.GeneratedHeaderPath.Empty(); } HeaderSource->Empty(HeaderSource->Len()); } else { ConversionRecord.GeneratedHeaderPath.Empty(); } if (bSuccess) { GetManifest(PlatformName).GatherModuleDependencies(ForConversion->GetOutermost()); } else { UE_LOG(LogBlueprintCodeGen, Error, TEXT("FBlueprintNativeCodeGenModule::GenerateSingleAsset error: %s"), *GetPathNameSafe(ForConversion)); } BackendPCHQuery.Unbind(); }
void FBlueprintNativeCodeGenModule::GenerateSingleStub(UBlueprint* BP, const TCHAR* PlatformName) { if (!ensure(BP)) { return; } UClass* Class = BP->GeneratedClass; if (!ensure(Class)) { return; } // no PCHFilename should be necessary const IAssetRegistry& Registry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get(); FAssetData AssetInfo = Registry.GetAssetByObjectPath(*Class->GetPathName()); FString FileContents; TUniquePtr<IBlueprintCompilerCppBackend> Backend_CPP(IBlueprintCompilerCppBackendModuleInterface::Get().Create()); // Apparently we can only generate wrappers for classes, so any logic that results in non classes requesting // wrappers will fail here: FileContents = Backend_CPP->GenerateWrapperForClass(Class); if (!FileContents.IsEmpty()) { FFileHelper::SaveStringToFile(FileContents , *(GetManifest(PlatformName).CreateUnconvertedDependencyRecord(AssetInfo.PackageName, AssetInfo).GeneratedWrapperPath) , ForcedEncoding()); } // The stub we generate still may have dependencies on other modules, so make sure the module dependencies are // still recorded so that the .build.cs is generated correctly. Without this you'll get include related errors // (or possibly linker errors) in stub headers: GetManifest(PlatformName).GatherModuleDependencies(BP->GetOutermost()); }
void FBlueprintNativeCodeGenModule::FinalizeManifest() { for(auto& PlatformName : TargetPlatformNames) { GetManifest(*PlatformName).Save(-1); check(FBlueprintNativeCodeGenUtils::FinalizePlugin(GetManifest(*PlatformName))); } }
void FBlueprintNativeCodeGenModule::InitializeForRerunDebugOnly(const TArray< TPair< FString, FString > >& CodegenTargets) { ReadConfig(); IBlueprintNativeCodeGenCore::Register(this); FillTargetedForReplacementQuery(); FillIsFunctionUsedInADelegate(); for (const auto& Platform : CodegenTargets) { // load the old manifest: const TCHAR* TargetDirectory = *Platform.Value; FString OutputPath = FPaths::Combine(TargetDirectory, NativizationCookControllerImpl::DefaultPluginName, *FBlueprintNativeCodeGenPaths::GetDefaultManifestPath()); Manifests.Add(FString(*Platform.Key), TUniquePtr<FBlueprintNativeCodeGenManifest>(new FBlueprintNativeCodeGenManifest(FPaths::ConvertRelativePathToFull(OutputPath)))); //FBlueprintNativeCodeGenManifest OldManifest(FPaths::ConvertRelativePathToFull(OutputPath)); // reconvert every assets listed in the manifest: for (const auto& ConversionTarget : GetManifest(*Platform.Key).GetConversionRecord()) { // load the package: UPackage* Package = LoadPackage(nullptr, *ConversionTarget.Value.TargetObjPath, LOAD_None); if (!Package) { UE_LOG(LogBlueprintCodeGen, Error, TEXT("Unable to load the package: %s"), *ConversionTarget.Value.TargetObjPath); continue; } // reconvert it Convert(Package, ESavePackageResult::ReplaceCompletely, *Platform.Key); } // reconvert every unconverted dependency listed in the manifest: for (const auto& ConversionTarget : GetManifest(*Platform.Key).GetUnconvertedDependencies()) { // load the package: UPackage* Package = LoadPackage(nullptr, *ConversionTarget.Key.GetPlainNameString(), LOAD_None); UStruct* Struct = nullptr; UEnum* Enum = nullptr; GetFieldFormPackage(Package, Struct, Enum); UBlueprint* BP = Cast<UBlueprint>(CastChecked<UClass>(Struct)->ClassGeneratedBy); if (ensure(BP)) { CollectBoundFunctions(BP); GenerateSingleStub(BP, *Platform.Key); } } for (TAssetPtr<UBlueprint>& BPPtr : ToGenerate) { UBlueprint* BP = BPPtr.LoadSynchronous(); if (ensure(BP)) { GenerateSingleAsset(BP->GeneratedClass, *Platform.Key); } } } }
void FBlueprintNativeCodeGenModule::SaveManifest(int32 Id ) { for (auto& PlatformName : TargetPlatformNames) { GetManifest(*PlatformName).Save(Id); } }
void FBlueprintNativeCodeGenModule::Initialize(const FNativeCodeGenInitData& InitData) { ReadConfig(); IBlueprintNativeCodeGenCore::Register(this); // Each platform will need a manifest, because each platform could cook different assets: for (auto& Platform : InitData.CodegenTargets) { const TCHAR* TargetDirectory = *Platform.Value; FString OutputPath = FPaths::Combine(TargetDirectory, NativizationCookControllerImpl::DefaultPluginName); Manifests.Add(FString(*Platform.Key), TUniquePtr<FBlueprintNativeCodeGenManifest>(new FBlueprintNativeCodeGenManifest(NativizationCookControllerImpl::DefaultPluginName, OutputPath))); TargetPlatformNames.Add(Platform.Key); // Clear source code folder const FString SourceCodeDir = GetManifest(*Platform.Key).GetTargetPaths().PluginSourceDir(); UE_LOG(LogBlueprintCodeGen, Log, TEXT("Clear nativized source code directory: %s"), *SourceCodeDir); IFileManager::Get().DeleteDirectory(*SourceCodeDir, false, true); } FillTargetedForReplacementQuery(); FillIsFunctionUsedInADelegate(); }
void FBlueprintNativeCodeGenModule::MergeManifest(int32 ManifestIdentifier) { for (auto& PlatformName : TargetPlatformNames) { FBlueprintNativeCodeGenManifest& CurrentManifest = GetManifest(*PlatformName); FBlueprintNativeCodeGenManifest OtherManifest = FBlueprintNativeCodeGenManifest(CurrentManifest.GetTargetPaths().ManifestFilePath() + FString::FromInt(ManifestIdentifier)); CurrentManifest.Merge(OtherManifest); } }
void ViewManager::RemoveQuark (const QUrl& url) { for (int i = 0; i < ViewItemsModel_->rowCount (); ++i) { auto item = ViewItemsModel_->item (i); if (item->data (ViewItemsModel::Role::SourceURL) != url) continue; ViewItemsModel_->removeRow (i); } auto mgr = Quark2Manager_.take (url); AddToRemoved (mgr->GetManifest ().GetID ()); SaveQuarkOrder (); }
void ViewManager::RemoveQuark (const QString& id) { QUrl url; for (int i = 0; i < ViewItemsModel_->rowCount (); ++i) { auto item = ViewItemsModel_->item (i); if (item->data (ViewItemsModel::Role::QuarkClass) != id) continue; url = item->data (ViewItemsModel::Role::SourceURL).toUrl (); ViewItemsModel_->removeRow (i); } if (!url.isValid ()) return; auto mgr = Quark2Manager_.take (url); AddToRemoved (mgr->GetManifest ().GetID ()); }