public static bool LoadBundleConfig(string BundleIniFile, ref Dictionary <string, BundleSettings> Bundles) { if (System.IO.File.Exists(BundleIniFile) == false) { CommandUtils.LogWarning("Unable to find bundle config ini file {0}", BundleIniFile); return(false); } FileReference BundleFileReference = new FileReference(BundleIniFile); ConfigHierarchy BundleConfig = new ConfigHierarchy(new ConfigFile[] { new ConfigFile(BundleFileReference) }); int PriorityCounter = 0; foreach (string SectionName in BundleConfig.SectionNames) { BundleSettings Bundle = new BundleSettings(); Bundle.Name = SectionName; Bundle.Priority = PriorityCounter; ++PriorityCounter; { string ExecFileName; BundleConfig.GetString(SectionName, "ExecFileName", out ExecFileName); Bundle.ExecFileName = ExecFileName; } { List <string> Tags; BundleConfig.GetArray(SectionName, "Tags", out Tags); Bundle.Tags = Tags; } { List <string> FileRegex; BundleConfig.GetArray(SectionName, "FileRegex", out FileRegex); Bundle.FileRegex = FileRegex; } { bool bContainsShaderLibrary; BundleConfig.GetBool(SectionName, "ContainsShaderLibrary", out bContainsShaderLibrary); Bundle.bContainsShaderLibrary = bContainsShaderLibrary; } if (Bundle.Tags == null) { Bundle.Tags = new List <string>(); } Bundles.Add(SectionName, Bundle); } return(true); }
// Load SkookumScript.ini and return any ScriptSupportedModules specified public static List <string> GetSkookumScriptModuleNames(string PluginOrProjectRootDirectory, bool AddSkookumScriptRuntime = true) { List <string> moduleList = null; // Load SkookumScript.ini and get ScriptSupportedModules string iniFilePath = Path.Combine(PluginOrProjectRootDirectory, "Config/SkookumScript.ini"); if (File.Exists(iniFilePath)) { ConfigFile iniFile = new ConfigFile(new FileReference(iniFilePath), ConfigLineAction.Add); var skookumConfig = new ConfigHierarchy(new ConfigFile[] { iniFile }); skookumConfig.GetArray("CommonSettings", "ScriptSupportedModules", out moduleList); } if (moduleList == null) { moduleList = new List <string>(); } // Add additional modules needed for SkookumScript to function moduleList.Add("AgogCore"); moduleList.Add("SkookumScript"); if (AddSkookumScriptRuntime) { moduleList.Add("SkookumScriptRuntime"); } return(moduleList); }
private ProjectImportExportInfo GenerateProjectImportExportInfo(string RootWorkingDirectory, string LocalizationConfigFile) { ConfigFile File = new ConfigFile(new FileReference(LocalizationConfigFile), ConfigLineAction.Add); var LocalizationConfig = new ConfigHierarchy(new ConfigFile[] { File }); string DestinationPath; if (!LocalizationConfig.GetString("CommonSettings", "DestinationPath", out DestinationPath)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'DestinationPath', File: '{0}'", LocalizationConfigFile); } string ManifestName; if (!LocalizationConfig.GetString("CommonSettings", "ManifestName", out ManifestName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ManifestName', File: '{0}'", LocalizationConfigFile); } string ArchiveName; if (!LocalizationConfig.GetString("CommonSettings", "ArchiveName", out ArchiveName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ArchiveName', File: '{0}'", LocalizationConfigFile); } string PortableObjectName; if (!LocalizationConfig.GetString("CommonSettings", "PortableObjectName", out PortableObjectName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'PortableObjectName', File: '{0}'", LocalizationConfigFile); } string NativeCulture; if (!LocalizationConfig.GetString("CommonSettings", "NativeCulture", out NativeCulture)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'NativeCulture', File: '{0}'", LocalizationConfigFile); } List <string> CulturesToGenerate; if (!LocalizationConfig.GetArray("CommonSettings", "CulturesToGenerate", out CulturesToGenerate)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'CulturesToGenerate', File: '{0}'", LocalizationConfigFile); } bool bUseCultureDirectory; if (!LocalizationConfig.GetBool("CommonSettings", "bUseCultureDirectory", out bUseCultureDirectory)) { // bUseCultureDirectory is optional, default is true bUseCultureDirectory = true; } var ProjectImportExportInfo = new ProjectImportExportInfo(DestinationPath, ManifestName, ArchiveName, PortableObjectName, NativeCulture, CulturesToGenerate, bUseCultureDirectory); ProjectImportExportInfo.CalculateSplitPlatformNames(RootWorkingDirectory); return(ProjectImportExportInfo); }
public static bool HasPlatformBundleSource(DirectoryReference ProjectDir, UnrealTargetPlatform Platform) { ConfigHierarchy BundleConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.InstallBundle, ProjectDir, Platform); return (BundleConfig.GetArray("InstallBundleManager.BundleSources", "DefaultBundleSources", out List <string> InstallBundleSources) && InstallBundleSources.Contains("Platform")); }
protected void DoBuildCookRun(ProjectParams Params) { const ProjectBuildTargets ClientTargets = ProjectBuildTargets.ClientCooked | ProjectBuildTargets.ServerCooked; bool bGenerateNativeScripts = Params.RunAssetNativization; int WorkingCL = -1; if (P4Enabled && GlobalCommandLine.Submit && AllowSubmit) { WorkingCL = P4.CreateChange(P4Env.Client, String.Format("{0} build from changelist {1}", Params.ShortProjectName, P4Env.Changelist)); } Project.Build(this, Params, WorkingCL, bGenerateNativeScripts ? (ProjectBuildTargets.All & ~ClientTargets) : ProjectBuildTargets.All); Project.Cook(Params); if (bGenerateNativeScripts) { // crash reporter is built along with client targets, so we need to // include that target flag here as well - note: that its not folded // into ClientTargets because the editor needs its own CrashReporter // as well (which would be built above) Project.Build(this, Params, WorkingCL, ClientTargets | ProjectBuildTargets.CrashReporter); } else { ConfigHierarchy GameIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, Params.RawProjectPath.Directory, HostPlatform.Current.HostEditorPlatform); if (GameIni != null) { List <string> NativizeBlueprintAssets = null; string BlueprintNativizationMethod = "Disabled"; bool bWarnIfPackagedWithoutNativizationFlag = true; GameIni.GetString("/Script/UnrealEd.ProjectPackagingSettings", "BlueprintNativizationMethod", out BlueprintNativizationMethod); GameIni.GetBool("/Script/UnrealEd.ProjectPackagingSettings", "bWarnIfPackagedWithoutNativizationFlag", out bWarnIfPackagedWithoutNativizationFlag); GameIni.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "NativizeBlueprintAssets", out NativizeBlueprintAssets); if (bWarnIfPackagedWithoutNativizationFlag && BlueprintNativizationMethod != "Disabled") { // Warn if we're cooking without the -nativizeAssets flag, when the project settings specify a nativization method. // If the "exclusive" (whitelist) method is set, we only warn if at least one asset has been selected for conversion. if (BlueprintNativizationMethod != "Exclusive" || (NativizeBlueprintAssets != null && NativizeBlueprintAssets.Count > 0)) { LogWarning("Project is configured for Blueprint nativization, but the conversion flag (-nativizeAssets) was omitted from the command line. No nativized assets have been built as a result."); } } } } Project.CopyBuildToStagingDirectory(Params); Project.Package(Params, WorkingCL); Project.Archive(Params); Project.Deploy(Params); PrintRunTime(); Project.Run(Params); // Check everything in! if (WorkingCL != -1) { int SubmittedCL; P4.Submit(WorkingCL, out SubmittedCL, true, true); } }
/// <summary> /// Read a list of whitelisted or blacklisted config files names from a config file /// </summary> /// <param name="Config">The config hierarchy to read from</param> /// <param name="SectionName">The section name</param> /// <param name="KeyName">The key name to read from</param> /// <param name="ConfigFiles">Receives a list of config file paths</param> private static void ReadConfigFileList(ConfigHierarchy Config, string SectionName, string KeyName, HashSet <StagedFileReference> ConfigFiles) { List <string> ConfigFileNames; if (Config.GetArray(SectionName, KeyName, out ConfigFileNames)) { foreach (string ConfigFileName in ConfigFileNames) { ConfigFiles.Add(new StagedFileReference(ConfigFileName)); } } }
/** * Notify stakeholders of the commandlet results */ void SendCompletionMessage(bool bWasSuccessful, String MessageBody) { MailMessage Message = new System.Net.Mail.MailMessage(); Message.Priority = MailPriority.High; Message.From = new MailAddress("*****@*****.**"); string Branch = "Unknown"; if (P4Enabled) { Branch = P4Env.Branch; } foreach (String NextStakeHolder in StakeholdersEmailAddresses) { Message.To.Add(new MailAddress(NextStakeHolder)); } ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(ProjectFullPath), UnrealTargetPlatform.Win64); List <string> Emails; Ini.GetArray("RebuildlightingSettings", "EmailNotification", out Emails); foreach (var Email in Emails) { Message.CC.Add(new MailAddress(Email)); } Message.Subject = String.Format("Nightly lightmap rebuild {0} for {1}", bWasSuccessful ? "[SUCCESS]" : "[FAILED]", Branch); Message.Body = MessageBody; /*Attachment Attach = new Attachment(); * Message.Attachments.Add()*/ try { #pragma warning disable CS0618 // Mono 4.6.x obsoletes this class SmtpClient MailClient = new SmtpClient("smtp.epicgames.net"); MailClient.Send(Message); #pragma warning restore CS0618 } catch (Exception Ex) { LogError("Failed to send notify email to {0} ({1})", String.Join(", ", StakeholdersEmailAddresses.ToArray()), Ex.Message); } }
private ProjectImportExportInfo GenerateProjectImportExportInfo(string LocalizationConfigFile) { var ProjectImportExportInfo = new ProjectImportExportInfo(); ConfigFile File = new ConfigFile(new FileReference(LocalizationConfigFile), ConfigLineAction.Add); var LocalizationConfig = new ConfigHierarchy(new ConfigFile[] { File }); if (!LocalizationConfig.GetString("CommonSettings", "DestinationPath", out ProjectImportExportInfo.DestinationPath)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'DestinationPath', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "ManifestName", out ProjectImportExportInfo.ManifestName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ManifestName', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "ArchiveName", out ProjectImportExportInfo.ArchiveName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'ArchiveName', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "PortableObjectName", out ProjectImportExportInfo.PortableObjectName)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'PortableObjectName', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetString("CommonSettings", "NativeCulture", out ProjectImportExportInfo.NativeCulture)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'NativeCulture', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetArray("CommonSettings", "CulturesToGenerate", out ProjectImportExportInfo.CulturesToGenerate)) { throw new AutomationException("Failed to find a required config key! Section: 'CommonSettings', Key: 'CulturesToGenerate', File: '{0}'", LocalizationConfigFile); } if (!LocalizationConfig.GetBool("CommonSettings", "bUseCultureDirectory", out ProjectImportExportInfo.bUseCultureDirectory)) { // bUseCultureDirectory is optional, default is true ProjectImportExportInfo.bUseCultureDirectory = true; } return(ProjectImportExportInfo); }
public static void CopySharedCookedBuildForTarget(string ProjectFullPath, UnrealTargetPlatform TargetPlatform, string CookPlatform, bool bOnlyCopyAssetRegistry = false) { var LocalPath = CommandUtils.CombinePaths(Path.GetDirectoryName(ProjectFullPath), "Saved", "SharedIterativeBuild", CookPlatform); FileReference ProjectFileRef = new FileReference(ProjectFullPath); // get network location ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFileRef), TargetPlatform); List <string> CookedBuildPaths; if (Hierarchy.GetArray("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPaths) == false) { CommandUtils.Log("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings"); return; } foreach (var CookedBuildPath in CookedBuildPaths) { if (CopySharedCookedBuildForTargetInternal(CookedBuildPath, CookPlatform, LocalPath, bOnlyCopyAssetRegistry) == true) { return; } } return; }
public DeploymentContext( FileReference RawProjectPathOrName, DirectoryReference InLocalRoot, DirectoryReference BaseStageDirectory, DirectoryReference BaseArchiveDirectory, Platform InSourcePlatform, Platform InTargetPlatform, List <UnrealTargetConfiguration> InTargetConfigurations, IEnumerable <StageTarget> InStageTargets, List <String> InStageExecutables, bool InServer, bool InCooked, bool InStageCrashReporter, bool InStage, bool InCookOnTheFly, bool InArchive, bool InProgram, bool IsClientInsteadOfNoEditor, bool InForceChunkManifests, bool InSeparateDebugStageDirectory ) { bStageCrashReporter = InStageCrashReporter; RawProjectPath = RawProjectPathOrName; DedicatedServer = InServer; LocalRoot = InLocalRoot; CookSourcePlatform = InSourcePlatform; StageTargetPlatform = InTargetPlatform; StageTargetConfigurations = new List <UnrealTargetConfiguration>(InTargetConfigurations); StageTargets = new List <StageTarget>(InStageTargets); StageExecutables = InStageExecutables; IsCodeBasedProject = ProjectUtils.IsCodeBasedUProjectFile(RawProjectPath, StageTargetConfigurations); ShortProjectName = ProjectUtils.GetShortProjectName(RawProjectPath); Stage = InStage; Archive = InArchive; if (CookSourcePlatform != null && InCooked) { CookPlatform = CookSourcePlatform.GetCookPlatform(DedicatedServer, IsClientInsteadOfNoEditor); } else if (CookSourcePlatform != null && InProgram) { CookPlatform = CookSourcePlatform.GetCookPlatform(false, false); } else { CookPlatform = ""; } if (StageTargetPlatform != null && InCooked) { FinalCookPlatform = StageTargetPlatform.GetCookPlatform(DedicatedServer, IsClientInsteadOfNoEditor); } else if (StageTargetPlatform != null && InProgram) { FinalCookPlatform = StageTargetPlatform.GetCookPlatform(false, false); } else { FinalCookPlatform = ""; } PlatformDir = StageTargetPlatform.PlatformType.ToString(); if (BaseStageDirectory != null) { StageDirectory = DirectoryReference.Combine(BaseStageDirectory, FinalCookPlatform); DebugStageDirectory = InSeparateDebugStageDirectory? DirectoryReference.Combine(BaseStageDirectory, FinalCookPlatform + "Debug") : StageDirectory; } if (BaseArchiveDirectory != null) { ArchiveDirectory = DirectoryReference.Combine(BaseArchiveDirectory, FinalCookPlatform); } if (!FileReference.Exists(RawProjectPath)) { throw new AutomationException("Can't find uproject file {0}.", RawProjectPathOrName); } EngineRoot = DirectoryReference.Combine(LocalRoot, "Engine"); ProjectRoot = RawProjectPath.Directory; RelativeProjectRootForStage = new StagedDirectoryReference(ShortProjectName); ProjectArgForCommandLines = CommandUtils.MakePathSafeToUseWithCommandLine(RawProjectPath.FullName); CookSourceRuntimeRootDir = RuntimeRootDir = LocalRoot; RuntimeProjectRootDir = ProjectRoot; if (Stage) { CommandUtils.CreateDirectory(StageDirectory.FullName); RuntimeRootDir = StageDirectory; CookSourceRuntimeRootDir = DirectoryReference.Combine(BaseStageDirectory, CookPlatform); RuntimeProjectRootDir = DirectoryReference.Combine(StageDirectory, RelativeProjectRootForStage.Name); ProjectArgForCommandLines = CommandUtils.MakePathSafeToUseWithCommandLine(UProjectCommandLineArgInternalRoot + RelativeProjectRootForStage.Name + "/" + ShortProjectName + ".uproject"); } if (Archive) { CommandUtils.CreateDirectory(ArchiveDirectory.FullName); } ProjectArgForCommandLines = ProjectArgForCommandLines.Replace("\\", "/"); ProjectBinariesFolder = DirectoryReference.Combine(ProjectUtils.GetClientProjectBinariesRootPath(RawProjectPath, TargetType.Game, IsCodeBasedProject), PlatformDir); // Build a list of restricted folder names. This will comprise all other restricted platforms, plus standard restricted folder names such as NoRedist, NotForLicensees, etc... RestrictedFolderNames.UnionWith(PlatformExports.GetPlatformFolderNames()); foreach (UnrealTargetPlatform StagePlatform in StageTargetPlatform.GetStagePlatforms()) { RestrictedFolderNames.ExceptWith(PlatformExports.GetIncludedFolderNames(StagePlatform)); } RestrictedFolderNames.UnionWith(FileFilter.RestrictedFolderNames); RestrictedFolderNames.Remove(new FileSystemName(StageTargetPlatform.IniPlatformType.ToString())); // Read the game config files ConfigHierarchy GameConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, ProjectRoot, InTargetPlatform.PlatformType); // Read the list of directories to remap when staging List <string> RemapDirectoriesList; if (GameConfig.GetArray("Staging", "RemapDirectories", out RemapDirectoriesList)) { foreach (string RemapDirectory in RemapDirectoriesList) { Dictionary <string, string> Properties; if (!ConfigHierarchy.TryParse(RemapDirectory, out Properties)) { throw new AutomationException("Unable to parse '{0}'", RemapDirectory); } string FromDir; if (!Properties.TryGetValue("From", out FromDir)) { throw new AutomationException("Missing 'From' property in '{0}'", RemapDirectory); } string ToDir; if (!Properties.TryGetValue("To", out ToDir)) { throw new AutomationException("Missing 'To' property in '{0}'", RemapDirectory); } RemapDirectories.Add(Tuple.Create(new StagedDirectoryReference(FromDir), new StagedDirectoryReference(ToDir))); } } // Read the list of directories to whitelist from restricted folder warnings List <string> WhitelistDirectoriesList; if (GameConfig.GetArray("Staging", "WhitelistDirectories", out WhitelistDirectoriesList)) { foreach (string WhitelistDirectory in WhitelistDirectoriesList) { WhitelistDirectories.Add(new StagedDirectoryReference(WhitelistDirectory)); } } // Read the list of files which are whitelisted to be staged ReadConfigFileList(GameConfig, "Staging", "WhitelistConfigFiles", WhitelistConfigFiles); ReadConfigFileList(GameConfig, "Staging", "BlacklistConfigFiles", BlacklistConfigFiles); // If we were configured to use manifests across the whole project, then this platform should use manifests. // Otherwise, read whether we are generating chunks from the ProjectPackagingSettings ini. if (InForceChunkManifests) { PlatformUsesChunkManifests = true; } else { ConfigHierarchy GameIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, ProjectRoot, InTargetPlatform.PlatformType); String IniPath = "/Script/UnrealEd.ProjectPackagingSettings"; bool bSetting = false; if (GameIni.GetBool(IniPath, "bGenerateChunks", out bSetting)) { PlatformUsesChunkManifests = bSetting; } } }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { LogInformation("Package {0}", Params.RawProjectPath); LogInformation("Setting Emscripten SDK for packaging.."); HTML5SDKInfo.SetupEmscriptenTemp(); HTML5SDKInfo.SetUpEmscriptenConfigFile(); // ---------------------------------------- // ini configurations ConfigHierarchy ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5); // Debug and Development builds are not compressed to: // - speed up iteration times // - ensure (IndexedDB) data are not cached/used // Shipping builds "can be": // - compressed // - (IndexedDB) cached string ProjectConfiguration = Params.ClientConfigsToBuild[0].ToString(); if (ProjectConfiguration == "Shipping") { ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed); ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB); } LogInformation("HTML5Platform.Automation: Compressed = " + Compressed); LogInformation("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB); // ---------------------------------------- // package directory string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5"); if (!Directory.Exists(PackagePath)) { Directory.CreateDirectory(PackagePath); } string _ProjectNameExtra = ProjectConfiguration != "Development" ? "-HTML5-" + ProjectConfiguration : ""; string _ProjectFullpath = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString(); string _ProjectFilename = Path.GetFileNameWithoutExtension(_ProjectFullpath) + _ProjectNameExtra; string SrcUE4GameBasename = Path.Combine(Path.GetDirectoryName(_ProjectFullpath), _ProjectFilename); string UE4GameBasename = Path.Combine(PackagePath, _ProjectFilename); string ProjectBasename = Path.Combine(PackagePath, Params.ShortProjectName + _ProjectNameExtra); // ---------------------------------------- // packaging if (HTMLPakAutomation.CanCreateMapPaks(Params)) { HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC); // Create Necessary Paks. PakAutomation.CreateEnginePak(); PakAutomation.CreateGamePak(); PakAutomation.CreateContentDirectoryPak(); // Create Emscripten Package from Necessary Paks. - This will be the VFS. PakAutomation.CreateEmscriptenDataPackage(PackagePath, ProjectBasename + ".data"); // Create All Map Paks which will be downloaded on the fly. PakAutomation.CreateMapPak(); // Create Delta Paks if setup. List <string> Paks = new List <string>(); ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks); if (Paks != null) { foreach (var Pak in Paks) { var Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase); string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", "")); string MapTo = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", "")); PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo); } } } else { // we need to operate in the root string PythonPath = HTML5SDKInfo.Python(); string EmPackagerPath = HTML5SDKInfo.EmscriptenPackager(); using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN)) { using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5"))) { string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", EmPackagerPath, ProjectBasename + ".data"); RunAndLog(CmdEnv, PythonPath, CmdLine); } } } // ---------------------------------------- // copy to package directory // ensure the ue4game binary exists, if applicable if (!FileExists_NoExceptions(SrcUE4GameBasename + ".js")) { LogInformation("Failed to find game application " + SrcUE4GameBasename + ".js"); throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", SrcUE4GameBasename + ".js"); } if (!Params.IsCodeBasedProject) { // template project - need to copy over UE4Game.* File.Copy(SrcUE4GameBasename + ".wasm", UE4GameBasename + ".wasm", true); File.Copy(SrcUE4GameBasename + ".js", UE4GameBasename + ".js", true); File.Copy(SrcUE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbols", true); File.SetAttributes(UE4GameBasename + ".wasm", FileAttributes.Normal); File.SetAttributes(UE4GameBasename + ".js", FileAttributes.Normal); File.SetAttributes(UE4GameBasename + ".js.symbols", FileAttributes.Normal); } // else, c++ projects will compile "to" PackagePath // note: ( ProjectBasename + ".data" ) already created above (!HTMLPakAutomation.CanCreateMapPaks()) // ---------------------------------------- // generate HTML files to the package directory // custom HTML, JS (if any), and CSS (if any) template files string LocalBuildPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5"); string BuildPath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Build", "HTML5"); string TemplateFile = CombinePaths(BuildPath, "project_template.html"); if (!File.Exists(TemplateFile)) { // fall back to default UE4 template files BuildPath = LocalBuildPath; TemplateFile = CombinePaths(BuildPath, "project_template.html"); } GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".html", Params, ConfigCache); TemplateFile = CombinePaths(BuildPath, "project_template.js"); if (File.Exists(TemplateFile)) { GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".UE4.js", Params, ConfigCache); } TemplateFile = CombinePaths(BuildPath, "project_template.css"); if (File.Exists(TemplateFile)) { GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".css", Params, ConfigCache); } // ---------------------------------------- // (development) support files string MacBashTemplateFile = CombinePaths(LocalBuildPath, "RunMacHTML5LaunchHelper_template.command"); string MacBashOutputFile = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command"); string MonoPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh"); GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath); // ........................................ string htaccesspath = Path.Combine(PackagePath, ".htaccess"); if (File.Exists(htaccesspath)) { FileAttributes attributes = File.GetAttributes(htaccesspath); if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) { attributes &= ~FileAttributes.ReadOnly; File.SetAttributes(htaccesspath, attributes); } } File.Copy(CombinePaths(LocalBuildPath, "htaccess_template.txt"), htaccesspath, true); // ---------------------------------------- // final copies // Gather utlity .js files and combine into one file string DestinationFile = PackagePath + "/Utility.js"; File.Delete(DestinationFile); // spelling this out - one file at a time (i.e. don't slurp in project_template.js) File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "json2.js"))); File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "jstorage.js"))); File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "moz_binarystring.js"))); if (Compressed) { LogInformation("Build configuration is " + ProjectConfiguration + ", so (gzip) compressing files for web servers."); // Compress all files. These are independent tasks which can be threaded. List <Task> CompressionTasks = new List <Task>(); CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".wasm", UE4GameBasename + ".wasmgz"))); // main game code CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js", UE4GameBasename + ".jsgz"))); // main js (emscripten) CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbolsgz"))); // symbols fil. CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(PackagePath + "/Utility.js", PackagePath + "/Utility.jsgz"))); // Utility CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data", ProjectBasename + ".datagz"))); // DATA file CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data.js", ProjectBasename + ".data.jsgz"))); // DATA file .js driver (emscripten) if (File.Exists(ProjectBasename + ".UE4.js")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".UE4.js", ProjectBasename + ".UE4.jsgz"))); // UE4 js } if (File.Exists(ProjectBasename + ".css")) { CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".css", ProjectBasename + ".cssgz"))); // UE4 css } Task.WaitAll(CompressionTasks.ToArray()); } else { LogInformation("Build configuration is " + ProjectConfiguration + ", so not compressing. Build Shipping configuration to compress files to save space."); // nuke old compressed files to prevent using stale files File.Delete(UE4GameBasename + ".wasmgz"); File.Delete(UE4GameBasename + ".jsgz"); File.Delete(UE4GameBasename + ".js.symbolsgz"); File.Delete(PackagePath + "/Utility.jsgz"); File.Delete(ProjectBasename + ".datagz"); File.Delete(ProjectBasename + ".data.jsgz"); File.Delete(ProjectBasename + ".UE4.jsgz"); File.Delete(ProjectBasename + ".cssgz"); } File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(PackagePath, "HTML5LaunchHelper.exe"), true); // Task.WaitAll(CompressionTasks); PrintRunTime(); }
public static bool LoadBundleConfig(string BundleIniFile, ref Dictionary <string, BundleSettings> Bundles) { if (System.IO.File.Exists(BundleIniFile) == false) { CommandUtils.LogWarning("Unable to find bundle config ini file {0}", BundleIniFile); return(false); } FileReference BundleFileReference = new FileReference(BundleIniFile); ConfigHierarchy BundleConfig = new ConfigHierarchy(new ConfigFile[] { new ConfigFile(BundleFileReference) }); int PriorityCounter = 0; foreach (string SectionName in BundleConfig.SectionNames) { BundleSettings Bundle = new BundleSettings(); Bundle.Name = SectionName; Bundle.Priority = PriorityCounter; ++PriorityCounter; { string OverrideName; if (BundleConfig.GetString(SectionName, "OverrideName", out OverrideName)) { Bundle.OverrideName = OverrideName; } else { Bundle.OverrideName = Bundle.Name; } } { string ParentName; BundleConfig.GetString(SectionName, "Parent", out ParentName); Bundle.ParentName = ParentName; } { List <string> Tags; BundleConfig.GetArray(SectionName, "Tags", out Tags); Bundle.Tags = Tags; } { List <string> FileRegex; BundleConfig.GetArray(SectionName, "FileRegex", out FileRegex); Bundle.FileRegex = FileRegex; } { bool bContainsShaderLibrary; BundleConfig.GetBool(SectionName, "ContainsShaderLibrary", out bContainsShaderLibrary); Bundle.bContainsShaderLibrary = bContainsShaderLibrary; } if (Bundle.Tags == null) { Bundle.Tags = new List <string>(); } Bundles.Add(SectionName, Bundle); //BundleConfig.GetArray(SectionName, "OptionalTags", out Bundle.OptionalTags); } foreach (var BundleIt in Bundles) { BundleSettings Bundle = BundleIt.Value; if (Bundles.ContainsKey(Bundle.ParentName)) { BundleSettings ParentBundle = Bundles[Bundle.ParentName]; ParentBundle.Children.Add(Bundle); Bundle.bFoundParent = true; } } return(true); }
private static bool FindBestSharedCookedBuild(ref string FinalCookedBuildPath, string ProjectFullPath, UnrealTargetPlatform TargetPlatform, string CookPlatform, string SharedCookedBuildCL) { string BuildRoot = CommandUtils.P4Enabled ? CommandUtils.P4Env.Branch.Replace("/", "+") : ""; int CurrentCLInt = CommandUtils.P4Enabled ? CommandUtils.P4Env.Changelist : 0; BuildVersion Version; if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version)) { CurrentCLInt = Version.Changelist; BuildRoot = Version.BranchName; } System.GC.Collect(); string CurrentCL = CurrentCLInt.ToString(); FileReference ProjectFileRef = new FileReference(ProjectFullPath); // get network location ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFileRef), TargetPlatform); List <string> CookedBuildPaths; if (Hierarchy.GetArray("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPaths) == false) { CommandUtils.LogInformation("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings"); return(false); } const string MetaDataFilename = "\\Metadata\\DevelopmentAssetRegistry.bin"; if (SharedCookedBuildCL == "usesyncedbuild") { foreach (string CookedBuildPath in CookedBuildPaths) { if (CurrentCL == "" && FinalCookedBuildPath.Contains("[CL]")) { CommandUtils.LogInformation("Unable to copy shared cooked build: Unable to determine CL number from P4 or UGS, and is required by SharedCookedBuildPath"); return(false); } if (CurrentCL == "" && FinalCookedBuildPath.Contains("[BRANCHNAME]")) { CommandUtils.LogInformation("Unable to copy shared cooked build: Unable to determine BRANCHNAME number from P4 or UGS, and is required by SharedCookedBuildPath"); return(false); } FinalCookedBuildPath = FinalCookedBuildPath.Replace("[CL]", CurrentCL.ToString()); FinalCookedBuildPath = FinalCookedBuildPath.Replace("[BRANCHNAME]", BuildRoot); FinalCookedBuildPath = FinalCookedBuildPath.Replace("[PLATFORM]", CookPlatform); // make sure that the directory and metadata file exist. otherwise this build might not be finished yet and we should skip it if (Directory.Exists(FinalCookedBuildPath)) { if (File.Exists(FinalCookedBuildPath + MetaDataFilename)) { return(true); } } } } else if (SharedCookedBuildCL == "userecentbuild") { // build our CookedBUildPath into a regex which we can execute on the directories and extract info from string BestBuild = null; int BestCLNumber = 0; // find all the recent builds which are valid foreach (string CookedBuildPath in CookedBuildPaths) { int IndexOfFirstParam = CookedBuildPath.IndexOf("["); int CustomFolderStart = CookedBuildPath.LastIndexOf("\\", IndexOfFirstParam); string CookedBuildDirectory = CookedBuildPath.Substring(0, CustomFolderStart); string BuildNameWildcard = CookedBuildPath.Substring(CustomFolderStart); BuildNameWildcard += MetaDataFilename; FileFilter BuildSearch = new FileFilter(); // we know the platform and the branch name; string BuildRule = BuildNameWildcard; BuildRule = BuildRule.Replace("[BRANCHNAME]", BuildRoot); BuildRule = BuildRule.Replace("[PLATFORM]", CookPlatform); string IncludeRule = BuildRule.Replace("[CL]", "*"); string ForgetRule = BuildRule.Replace("[CL]", "*-PF-*"); // get rid of any preflights from the list... they don't count because who knows what they did... BuildSearch.AddRule(IncludeRule); BuildSearch.AddRule(ForgetRule, FileFilterType.Exclude); List <FileReference> ValidBuilds = BuildSearch.ApplyToDirectory(new DirectoryReference(CookedBuildDirectory), false); // figure out what the CL is string BuildNameRegex = String.Format(".*{0}", CookedBuildPath.Substring(CustomFolderStart)); BuildNameRegex = BuildNameRegex.Replace("\\", "\\\\"); BuildNameRegex = BuildNameRegex.Replace("[BRANCHNAME]", BuildRoot); BuildNameRegex = BuildNameRegex.Replace("+", "\\+"); BuildNameRegex = BuildNameRegex.Replace("[PLATFORM]", CookPlatform); BuildNameRegex = BuildNameRegex.Replace("[CL]", "(?<CL>.*)"); Regex ExtractCL = new Regex(BuildNameRegex); foreach (FileReference ValidBuild in ValidBuilds) { string BuildPath = ValidBuild.FullName.Replace(MetaDataFilename, ""); Match CLMatch = ExtractCL.Match(BuildPath); if (CLMatch != null) { string CLNumber = CLMatch.Result("${CL}"); int CLNumberInt = int.Parse(CLNumber); if (CLNumberInt <= CurrentCLInt) { if (CLNumberInt > BestCLNumber) { BestCLNumber = CLNumberInt; BestBuild = BuildPath; } } } } } if (string.IsNullOrEmpty(BestBuild)) { return(false); } FinalCookedBuildPath = BestBuild; return(true); } return(false); }
public static void LoadBundleConfig <TPlatformBundleSettings>(DirectoryReference ProjectDir, UnrealTargetPlatform Platform, out IReadOnlyDictionary <string, TPlatformBundleSettings> Bundles, Action <TPlatformBundleSettings, ConfigHierarchy, string> GetPlatformSettings) where TPlatformBundleSettings : BundleSettings, new() { var Results = new List <TPlatformBundleSettings>(); ConfigHierarchy BundleConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.InstallBundle, ProjectDir, Platform); const string BundleDefinitionPrefix = "InstallBundleDefinition "; foreach (string SectionName in BundleConfig.SectionNames) { if (!SectionName.StartsWith(BundleDefinitionPrefix)) { continue; } TPlatformBundleSettings Bundle = new TPlatformBundleSettings(); Bundle.Name = SectionName.Substring(BundleDefinitionPrefix.Length); { int Order; if (BundleConfig.GetInt32(SectionName, "Order", out Order)) { Bundle.Order = Order; } else { Bundle.Order = int.MaxValue; } } { List <string> Tags; if (BundleConfig.GetArray(SectionName, "Tags", out Tags)) { Bundle.Tags = Tags; } else { Bundle.Tags = new List <string>(); } } { List <string> Dependencies; if (BundleConfig.GetArray(SectionName, "Dependencies", out Dependencies)) { Bundle.Dependencies = Dependencies; } else { Bundle.Dependencies = new List <string>(); } } { List <string> FileRegex; if (BundleConfig.GetArray(SectionName, "FileRegex", out FileRegex)) { Bundle.FileRegex = FileRegex; } else { Bundle.FileRegex = new List <string>(); } } { bool bContainsShaderLibrary; if (BundleConfig.GetBool(SectionName, "ContainsShaderLibrary", out bContainsShaderLibrary)) { Bundle.bContainsShaderLibrary = bContainsShaderLibrary; } else { Bundle.bContainsShaderLibrary = false; } } GetPlatformSettings(Bundle, BundleConfig, BundleDefinitionPrefix + Bundle.Name); Results.Add(Bundle); } // Use OrderBy and not Sort because OrderBy is stable Bundles = Results.OrderBy(b => b.Order).ToDictionary(b => b.Name, b => b); }
public static void LoadBundleConfig <TPlatformBundleSettings>(DirectoryReference ProjectDir, UnrealTargetPlatform Platform, out List <TPlatformBundleSettings> Bundles, Action <TPlatformBundleSettings, ConfigHierarchy, string> GetPlatformSettings) where TPlatformBundleSettings : BundleSettings, new() { Bundles = new List <TPlatformBundleSettings>(); ConfigHierarchy BundleConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.InstallBundle, ProjectDir, Platform); const string BundleDefinitionPrefix = "InstallBundleDefinition "; foreach (string SectionName in BundleConfig.SectionNames) { if (!SectionName.StartsWith(BundleDefinitionPrefix)) { continue; } TPlatformBundleSettings Bundle = new TPlatformBundleSettings(); Bundle.Name = SectionName.Substring(BundleDefinitionPrefix.Length); { int Order; if (BundleConfig.GetInt32(SectionName, "Order", out Order)) { Bundle.Order = Order; } else { Bundle.Order = int.MaxValue; } } { string ExecFileName; BundleConfig.GetString(SectionName, "ExecFileName", out ExecFileName); Bundle.ExecFileName = ExecFileName; } { List <string> Tags; BundleConfig.GetArray(SectionName, "Tags", out Tags); Bundle.Tags = Tags; } { List <string> FileRegex; BundleConfig.GetArray(SectionName, "FileRegex", out FileRegex); Bundle.FileRegex = FileRegex; } { bool bContainsShaderLibrary; BundleConfig.GetBool(SectionName, "ContainsShaderLibrary", out bContainsShaderLibrary); Bundle.bContainsShaderLibrary = bContainsShaderLibrary; } if (Bundle.Tags == null) { Bundle.Tags = new List <string>(); } GetPlatformSettings(Bundle, BundleConfig, BundleDefinitionPrefix + Bundle.Name); Bundles.Add(Bundle); } // Use OrderBy and not Sort because OrderBy is stable Bundles = Bundles.OrderBy(Bundle => Bundle.Order).ToList(); }