public static void FindProjects(DirectoryReference BaseDir, List <FileReference> ProjectFiles) { if (BaseDir != CommandUtils.EngineDirectory) { int InitialProjectFileCount = ProjectFiles.Count; ProjectFiles.AddRange(DirectoryReference.EnumerateFiles(BaseDir, "*.uproject")); if (InitialProjectFileCount == ProjectFiles.Count) { foreach (DirectoryReference SubDir in DirectoryReference.EnumerateDirectories(BaseDir)) { FindProjects(SubDir, ProjectFiles); } } } }
/// <summary> /// Finds files to stage under a given base directory. /// </summary> /// <param name="BaseDir">The directory to search under</param> /// <param name="Pattern">Pattern for files to match</param> /// <param name="ExcludePatterns">Patterns to exclude from staging</param> /// <param name="Option">Options for the search</param> /// <param name="Files">List to receive the enumerated files</param> private void FindFilesToStageInternal(DirectoryReference BaseDir, string Pattern, StageFilesSearch Option, List <FileReference> Files) { // Enumerate all the files in this directory Files.AddRange(DirectoryReference.EnumerateFiles(BaseDir, Pattern)); // Recurse through subdirectories if necessary if (Option == StageFilesSearch.AllDirectories) { foreach (DirectoryReference SubDir in DirectoryReference.EnumerateDirectories(BaseDir)) { FileSystemName Name = new FileSystemName(SubDir); if (!RestrictedFolderNames.Contains(Name)) { FindFilesToStageInternal(SubDir, Pattern, Option, Files); } } } }
public override void ExecuteBuild() { // Parse the arguments DirectoryReference FromDir = ParseRequiredDirectoryReferenceParam("From"); if (!DirectoryReference.Exists(FromDir)) { throw new AutomationException("Source directory '{0}' does not exist", FromDir); } // Just copy all the files into place foreach (FileReference SourceFile in DirectoryReference.EnumerateFiles(FromDir, "*", SearchOption.AllDirectories)) { FileReference TargetFile = FileReference.Combine(RootDirectory, SourceFile.MakeRelativeTo(FromDir)); LogInformation("Copying {0} to {1}", SourceFile, TargetFile); CopyFile(SourceFile.FullName, TargetFile.FullName); } }
private static void CleanupScriptsAssemblies() { if (!CommandUtils.IsEngineInstalled()) { CommandUtils.LogVerbose("Cleaning up script DLL folder"); CommandUtils.DeleteDirectory(GetScriptAssemblyFolder()); // Bug in PortalPublishingTool caused these DLLs to be copied into Engine/Binaries/DotNET. Delete any files left over. DirectoryReference BinariesDir = DirectoryReference.Combine(CommandUtils.RootDirectory, "Engine", "Binaries", "DotNET"); foreach (FileReference FileToDelete in DirectoryReference.EnumerateFiles(BinariesDir, "*.automation.dll")) { CommandUtils.DeleteFile(FileToDelete.FullName); } foreach (FileReference FileToDelete in DirectoryReference.EnumerateFiles(BinariesDir, "*.automation.pdb")) { CommandUtils.DeleteFile(FileToDelete.FullName); } } }
/// <summary> /// Returns true/false based on whether the project supports a client configuration /// </summary> /// <param name="ProjectName"></param> /// <returns></returns> FileReference FindProjectSourceFile(FileReference InProjectFile) { FileReference SourceFile = null; if (InProjectFile != null) { DirectoryReference SourceDir = DirectoryReference.Combine(InProjectFile.Directory, "Source", InProjectFile.GetFileNameWithoutAnyExtensions()); var Files = DirectoryReference.EnumerateFiles(SourceDir, "*.cpp", System.IO.SearchOption.AllDirectories); SourceFile = Files.FirstOrDefault(); } if (SourceFile == null) { // touch the write time on a file, first making it writable since it may be under P4 SourceFile = FileReference.Combine(CommandUtils.EngineDirectory, "Source/Runtime/Engine/Private/UnrealEngine.cpp"); } Log.TraceVerbose("Will compile {0} for single-file compilation test for {1}", SourceFile, InProjectFile.GetFileNameWithoutAnyExtensions()); return(SourceFile); }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // Stage all the build products foreach (StageTarget Target in SC.StageTargets) { SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles); } if (SC.bStageCrashReporter) { StagedDirectoryReference CrashReportClientPath = StagedDirectoryReference.Combine("Engine/Binaries", SC.PlatformDir, "CrashReportClient.app"); StageAppBundle(SC, DirectoryReference.Combine(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "CrashReportClient.app"), CrashReportClientPath); } // Find the app bundle path List <FileReference> Exes = GetExecutableNames(SC); foreach (var Exe in Exes) { StagedDirectoryReference AppBundlePath = null; if (Exe.IsUnderDirectory(DirectoryReference.Combine(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir))) { AppBundlePath = StagedDirectoryReference.Combine(SC.ShortProjectName, "Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe.FullName) + ".app"); } else if (Exe.IsUnderDirectory(DirectoryReference.Combine(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir))) { AppBundlePath = StagedDirectoryReference.Combine("Engine/Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe.FullName) + ".app"); } // Copy the custom icon and Steam dylib, if needed if (AppBundlePath != null) { FileReference AppIconsFile = FileReference.Combine(SC.ProjectRoot, "Build", "Mac", "Application.icns"); if (FileReference.Exists(AppIconsFile)) { SC.StageFile(StagedFileType.NonUFS, AppIconsFile, StagedFileReference.Combine(AppBundlePath, "Contents", "Resources", "Application.icns")); } } } // Copy the splash screen, Mac specific FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp"); if (FileReference.Exists(SplashImage)) { SC.StageFile(StagedFileType.NonUFS, SplashImage); } // Stage the bootstrap executable if (!Params.NoBootstrapExe) { foreach (StageTarget Target in SC.StageTargets) { BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if (Executable != null) { // only create bootstraps for executables List <StagedFileReference> StagedFiles = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList(); if (StagedFiles.Count > 0 && Executable.Path.FullName.Replace("\\", "/").Contains("/" + TargetPlatformType.ToString() + "/")) { string BootstrapArguments = ""; if (!ShouldStageCommandLine(Params, SC)) { if (!SC.IsCodeBasedProject) { BootstrapArguments = String.Format("../../../{0}/{0}.uproject", SC.ShortProjectName); } else { BootstrapArguments = SC.ShortProjectName; } } string BootstrapExeName; if (SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Path.GetFileName(Executable.Path.FullName) + ".app"; } else if (Params.IsCodeBasedProject) { BootstrapExeName = Target.Receipt.TargetName + ".app"; } else { BootstrapExeName = SC.ShortProjectName + ".app"; } string AppSuffix = ".app" + Path.DirectorySeparatorChar; string AppPath = Executable.Path.FullName.Substring(0, Executable.Path.FullName.LastIndexOf(AppSuffix) + AppSuffix.Length); foreach (var DestPath in StagedFiles) { string AppRelativePath = DestPath.Name.Substring(0, DestPath.Name.LastIndexOf(AppSuffix) + AppSuffix.Length); StageBootstrapExecutable(SC, BootstrapExeName, AppPath, AppRelativePath, BootstrapArguments); } } } } } // Copy the ShaderCache files, if they exist FileReference DrawCacheFile = FileReference.Combine(SC.ProjectRoot, "Content", "DrawCache.ushadercache"); if (FileReference.Exists(DrawCacheFile)) { SC.StageFile(StagedFileType.UFS, DrawCacheFile); } FileReference ByteCodeCacheFile = FileReference.Combine(SC.ProjectRoot, "Content", "ByteCodeCache.ushadercode"); if (FileReference.Exists(ByteCodeCacheFile)) { SC.StageFile(StagedFileType.UFS, ByteCodeCacheFile); } { // Stage any *.metallib files as NonUFS. // Get the final output directory for cooked data DirectoryReference CookOutputDir; if (!String.IsNullOrEmpty(Params.CookOutputDir)) { CookOutputDir = DirectoryReference.Combine(new DirectoryReference(Params.CookOutputDir), SC.CookPlatform); } else if (Params.CookInEditor) { CookOutputDir = DirectoryReference.Combine(SC.ProjectRoot, "Saved", "EditorCooked", SC.CookPlatform); } else { CookOutputDir = DirectoryReference.Combine(SC.ProjectRoot, "Saved", "Cooked", SC.CookPlatform); } if (DirectoryReference.Exists(CookOutputDir)) { List <FileReference> CookedFiles = DirectoryReference.EnumerateFiles(CookOutputDir, "*.metallib", SearchOption.AllDirectories).ToList(); foreach (FileReference CookedFile in CookedFiles) { SC.StageFile(StagedFileType.NonUFS, CookedFile, new StagedFileReference(CookedFile.MakeRelativeTo(CookOutputDir))); } } } }
public override void ExecuteBuild() { // just calling this DesiredTargetVersion because TargetVersion and TargetedVersion get super confusing. string DesiredTargetVersion = this.ParseParamValue("TargetVersion", null); if (string.IsNullOrEmpty(DesiredTargetVersion)) { throw new AutomationException("-TargetVersion was not specified."); } CommandUtils.Log("Scanning for all csproj's..."); // Check for all csproj's in the engine dir DirectoryReference EngineDir = CommandUtils.EngineDirectory; // grab the targeted version., Regex FrameworkRegex = new Regex("<TargetFrameworkVersion>v(\\d\\.\\d\\.?\\d?)<\\/TargetFrameworkVersion>"); Regex PossibleAppConfigRegex = new Regex("<TargetFrameworkProfile>(.+)<\\/TargetFrameworkProfile>"); Regex AppConfigRegex = new Regex("<supportedRuntime version=\"v(\\d\\.\\d\\.?\\d?)\" sku=\"\\.NETFramework,Version=v(\\d\\.\\d\\.?\\d?),Profile=(.+)\"\\/>"); foreach (FileReference CsProj in DirectoryReference.EnumerateFiles(EngineDir, "*.csproj", SearchOption.AllDirectories)) { if (CsProj.ContainsName(new FileSystemName("ThirdParty"), EngineDir) || (CsProj.ContainsName(new FileSystemName("UE4TemplateProject"), EngineDir) && CsProj.GetFileName().Equals("ProjectTemplate.csproj"))) { continue; } // read in the file string Contents = File.ReadAllText(CsProj.FullName); Match m = FrameworkRegex.Match(Contents); if (m.Success) { string TargetedVersion = m.Groups[1].Value; // make sure we match, throw warning otherwise if (!DesiredTargetVersion.Equals(TargetedVersion, StringComparison.InvariantCultureIgnoreCase)) { CommandUtils.LogWarning("Targeted Framework version for project: {0} was not {1}! Targeted Version: {2}", CsProj, DesiredTargetVersion, TargetedVersion); } } // if we don't have a TargetFrameworkVersion, check for the existence of TargetFrameworkProfile. else { m = PossibleAppConfigRegex.Match(Contents); if (!m.Success) { CommandUtils.Log("No TargetFrameworkVersion or TargetFrameworkProfile found for project {0}, is it a mono project? If not, does it compile properly?", CsProj); continue; } // look for the app config FileReference AppConfigFile = FileReference.Combine(CsProj.Directory, "app.config"); string Profile = m.Groups[1].Value; if (!FileReference.Exists(AppConfigFile)) { CommandUtils.Log("Found TargetFrameworkProfile but no associated app.config containing the version for project {0}.", CsProj); continue; } // read in the app config Contents = File.ReadAllText(AppConfigFile.FullName); m = AppConfigRegex.Match(Contents); if (!m.Success) { CommandUtils.Log("Couldn't find a supportedRuntime match for the version in the app.config for project {0}.", CsProj); continue; } // Version1 is the one that appears right after supportedRuntime // Version2 is the one in the sku // ProfileString should match the TargetFrameworkProfile from the csproj string Version1String = m.Groups[1].Value; string Version2String = m.Groups[2].Value; string ProfileString = m.Groups[3].Value; // not sure how this is possible, but check for it anyway if (!ProfileString.Equals(Profile, StringComparison.InvariantCultureIgnoreCase)) { CommandUtils.LogWarning("The TargetFrameworkProfile in csproj {0} ({1}) doesn't match the sku in it's app.config ({2}).", CsProj, Profile, ProfileString); continue; } // if the version numbers don't match the app.config is probably corrupt. if (!Version1String.Equals(Version2String, StringComparison.InvariantCultureIgnoreCase)) { CommandUtils.LogWarning("The supportedRunTimeVersion ({0}) and the sku version ({1}) in the app.config for project {2} don't match.", Version1String, Version2String, CsProj); continue; } // make sure the versions match if (!(DesiredTargetVersion.Equals(Version1String, StringComparison.InvariantCultureIgnoreCase))) { CommandUtils.LogWarning("Targeted Framework version for project: {0} was not {1}! Targeted Version: {2}", CsProj, DesiredTargetVersion, Version1String); } } } }
public override void ExecuteBuild() { CommandUtils.Log("************************* List Third Party Software"); string ProjectPath = ParseParamValue("Project", String.Empty); //Add quotes to avoid issues with spaces in project path if (ProjectPath != String.Empty) { ProjectPath = "\"" + ProjectPath + "\""; } // Parse the list of targets to list TPS for. Each target is specified by -Target="Name|Configuration|Platform" on the command line. HashSet <FileReference> TpsFiles = new HashSet <FileReference>(); foreach (string Target in ParseParamValues(Params, "Target")) { // Get the path to store the exported JSON target data FileReference OutputFile = FileReference.Combine(CommandUtils.EngineDirectory, "Intermediate", "Build", "ThirdParty.json"); IProcessResult Result; Result = Run(UE4Build.GetUBTExecutable(), String.Format("{0} {1} -jsonexport=\"{2}\" -skipbuild", Target.Replace('|', ' '), ProjectPath, OutputFile.FullName), Options: ERunOptions.Default); if (Result.ExitCode != 0) { throw new AutomationException("Failed to run UBT"); } // Read the exported target info back in JsonObject Object = JsonObject.Read(OutputFile); // Get the project file if there is one FileReference ProjectFile = null; string ProjectFileName; if (Object.TryGetStringField("ProjectFile", out ProjectFileName)) { ProjectFile = new FileReference(ProjectFileName); } // Get the default paths to search HashSet <DirectoryReference> DirectoriesToScan = new HashSet <DirectoryReference>(); DirectoriesToScan.Add(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Shaders")); DirectoriesToScan.Add(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Content")); if (ProjectFile != null) { DirectoriesToScan.Add(DirectoryReference.Combine(ProjectFile.Directory, "Content")); } // Get the variables to be expanded in any runtime dependencies variables Dictionary <string, string> Variables = new Dictionary <string, string>(); Variables.Add("EngineDir", CommandUtils.EngineDirectory.FullName); if (ProjectFile != null) { Variables.Add("ProjectDir", ProjectFile.Directory.FullName); } // Add all the paths for each module, and its runtime dependencies JsonObject Modules = Object.GetObjectField("Modules"); foreach (string ModuleName in Modules.KeyNames) { JsonObject Module = Modules.GetObjectField(ModuleName); DirectoriesToScan.Add(new DirectoryReference(Module.GetStringField("Directory"))); foreach (JsonObject RuntimeDependency in Module.GetObjectArrayField("RuntimeDependencies")) { string RuntimeDependencyPath = RuntimeDependency.GetStringField("Path"); RuntimeDependencyPath = Utils.ExpandVariables(RuntimeDependencyPath, Variables); DirectoriesToScan.Add(new FileReference(RuntimeDependencyPath).Directory); } } // Remove any directories that are under other directories, and sort the output list List <DirectoryReference> SortedDirectoriesToScan = new List <DirectoryReference>(); foreach (DirectoryReference DirectoryToScan in DirectoriesToScan.OrderBy(x => x.FullName)) { if (SortedDirectoriesToScan.Count == 0 || !DirectoryToScan.IsUnderDirectory(SortedDirectoriesToScan[SortedDirectoriesToScan.Count - 1])) { SortedDirectoriesToScan.Add(DirectoryToScan); } } // Get the platforms to exclude List <UnrealTargetPlatform> SupportedPlatforms = new List <UnrealTargetPlatform> { (UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), Object.GetStringField("Platform")) }; FileSystemName[] ExcludePlatformNames = Utils.MakeListOfUnsupportedPlatforms(SupportedPlatforms).Select(x => new FileSystemName(x)).ToArray(); // Find all the TPS files under the engine directory which match foreach (DirectoryReference DirectoryToScan in SortedDirectoriesToScan) { foreach (FileReference TpsFile in DirectoryReference.EnumerateFiles(DirectoryToScan, "*.tps", SearchOption.AllDirectories)) { if (!TpsFile.ContainsAnyNames(ExcludePlatformNames, DirectoryToScan)) { TpsFiles.Add(TpsFile); } } } } // Also add any redirects List <string> OutputMessages = new List <string>(); foreach (FileReference TpsFile in TpsFiles) { string Message = TpsFile.FullName; string[] Lines = FileReference.ReadAllLines(TpsFile); foreach (string Line in Lines) { const string RedirectPrefix = "Redirect:"; int Idx = Line.IndexOf(RedirectPrefix, StringComparison.InvariantCultureIgnoreCase); if (Idx >= 0) { FileReference RedirectTpsFile = FileReference.Combine(TpsFile.Directory, Line.Substring(Idx + RedirectPrefix.Length).Trim()); Message = String.Format("{0} (redirect from {1})", RedirectTpsFile.FullName, TpsFile.FullName); break; } } OutputMessages.Add(Message); } OutputMessages.Sort(); // Print them all out foreach (string OutputMessage in OutputMessages) { CommandUtils.Log(OutputMessage); } }
public override void ExecuteBuild() { string[] ProjectParams = ParseParamValues("Project"); string UpdateDirParam = ParseParamValue("UpdateDir", null); if (UpdateDirParam == null) { throw new AutomationException("Missing -UpdateDir=... parameter"); } DirectoryReference UpdateDir = new DirectoryReference(UpdateDirParam); bool bWrite = ParseParam("Write"); // Get all the root dirs HashSet <DirectoryReference> RootDirs = new HashSet <DirectoryReference>(); RootDirs.Add(EngineDirectory); // Add the enterprise edirectory DirectoryReference EnterpriseDirectory = DirectoryReference.Combine(RootDirectory, "Enterprise"); if (DirectoryReference.Exists(EnterpriseDirectory)) { RootDirs.Add(EnterpriseDirectory); } // Add the project directories foreach (string ProjectParam in ProjectParams) { FileReference ProjectLocation = new FileReference(ProjectParam); if (!FileReference.Exists(ProjectLocation)) { throw new AutomationException("Unable to find project '{0}'", ProjectLocation); } RootDirs.Add(ProjectLocation.Directory); } // Find all the modules HashSet <DirectoryReference> ModuleDirs = new HashSet <DirectoryReference>(); foreach (DirectoryReference RootDir in RootDirs) { // Find all the modules from the source folder DirectoryReference SourceDir = DirectoryReference.Combine(RootDir, "Source"); if (DirectoryReference.Exists(SourceDir)) { foreach (FileReference ModuleFile in DirectoryReference.EnumerateFiles(SourceDir, "*.Build.cs", SearchOption.AllDirectories)) { ModuleDirs.Add(ModuleFile.Directory); } } // Find all the modules under the plugins folder DirectoryReference PluginsDir = DirectoryReference.Combine(RootDir, "Plugins"); foreach (FileReference PluginFile in DirectoryReference.EnumerateFiles(PluginsDir, "*.uplugin", SearchOption.AllDirectories)) { DirectoryReference PluginSourceDir = DirectoryReference.Combine(PluginFile.Directory, "Source"); if (DirectoryReference.Exists(PluginSourceDir)) { foreach (FileReference PluginModuleFile in DirectoryReference.EnumerateFiles(PluginSourceDir, "*.Build.cs", SearchOption.AllDirectories)) { ModuleDirs.Add(PluginModuleFile.Directory); } } } } // Find a mapping from old to new include paths Dictionary <string, Tuple <string, FileReference> > RemapIncludePaths = new Dictionary <string, Tuple <string, FileReference> >(StringComparer.InvariantCultureIgnoreCase); foreach (DirectoryReference ModuleDir in ModuleDirs) { DirectoryReference ModulePublicDir = DirectoryReference.Combine(ModuleDir, "Public"); if (DirectoryReference.Exists(ModulePublicDir)) { foreach (FileReference HeaderFile in DirectoryReference.EnumerateFiles(ModulePublicDir, "*.h", SearchOption.AllDirectories)) { string BaseIncludeFile = HeaderFile.GetFileName(); Tuple <string, FileReference> ExistingIncludeName; if (RemapIncludePaths.TryGetValue(BaseIncludeFile, out ExistingIncludeName)) { LogWarning("Multiple include paths for {0}: {1}, {2}", BaseIncludeFile, ExistingIncludeName.Item2, HeaderFile); } else { RemapIncludePaths.Add(BaseIncludeFile, Tuple.Create(HeaderFile.MakeRelativeTo(ModulePublicDir).Replace('\\', '/'), HeaderFile)); } } } } // List of folders to exclude from updates string[] ExcludeFoldersFromUpdate = { "Intermediate", "ThirdParty" }; // Enumerate all the files to update HashSet <FileReference> UpdateFiles = new HashSet <FileReference>(); foreach (FileReference UpdateFile in DirectoryReference.EnumerateFiles(UpdateDir, "*", SearchOption.AllDirectories)) { if (!UpdateFile.ContainsAnyNames(ExcludeFoldersFromUpdate, UpdateDir)) { if (UpdateFile.HasExtension(".cpp") | UpdateFile.HasExtension(".h") || UpdateFile.HasExtension(".inl")) { UpdateFiles.Add(UpdateFile); } } } // Process all the source files Dictionary <FileReference, string[]> ModifiedFiles = new Dictionary <FileReference, string[]>(); foreach (FileReference UpdateFile in UpdateFiles) { bool bModifiedFile = false; string[] Lines = FileReference.ReadAllLines(UpdateFile); for (int Idx = 0; Idx < Lines.Length; Idx++) { Match Match = Regex.Match(Lines[Idx], "^(\\s*#\\s*include\\s+\\\")([^\"]+)(\\\".*)$"); if (Match.Success) { string IncludePath = Match.Groups[2].Value; Tuple <string, FileReference> NewIncludePath; if (RemapIncludePaths.TryGetValue(IncludePath, out NewIncludePath)) { if (IncludePath != NewIncludePath.Item1) { // Log("{0}: Changing {1} -> {2}", UpdateFile, IncludePath, NewIncludePath.Item1); Lines[Idx] = String.Format("{0}{1}{2}", Match.Groups[1].Value, NewIncludePath.Item1, Match.Groups[3].Value); bModifiedFile = true; } } } } if (bModifiedFile) { ModifiedFiles.Add(UpdateFile, Lines); } } // Output them all to disk if (bWrite && ModifiedFiles.Count > 0) { LogInformation("Updating {0} files...", ModifiedFiles.Count); List <FileReference> FilesToCheckOut = new List <FileReference>(); foreach (FileReference ModifiedFile in ModifiedFiles.Keys) { if ((FileReference.GetAttributes(ModifiedFile) & FileAttributes.ReadOnly) != 0) { FilesToCheckOut.Add(ModifiedFile); } } if (FilesToCheckOut.Count > 0) { if (!P4Enabled) { throw new AutomationException("{0} files have been modified, but are read only. Run with -P4 to enable Perforce checkout.\n{1}", FilesToCheckOut.Count, String.Join("\n", FilesToCheckOut.Select(x => " " + x))); } LogInformation("Checking out files from Perforce"); int ChangeNumber = P4.CreateChange(Description: "Updating source files"); P4.Edit(ChangeNumber, FilesToCheckOut.Select(x => x.FullName).ToList(), false); } foreach (KeyValuePair <FileReference, string[]> FileToWrite in ModifiedFiles) { LogInformation("Writing {0}", FileToWrite.Key); FileReference.WriteAllLines(FileToWrite.Key, FileToWrite.Value); } } }
public override void ExecuteBuild() { string RootDirParam = ParseParamValue("RootDir", null); if (RootDirParam == null) { throw new AutomationException("Missing -BaseDir=... parameter"); } string CreatedBy = ParseParamValue("CreatedBy", null); string CreatedByUrl = ParseParamValue("CreatedByUrl", null); bool bForce = ParseParam("Force"); foreach (FileReference PluginFile in DirectoryReference.EnumerateFiles(new DirectoryReference(RootDirParam), "*.uplugin", System.IO.SearchOption.AllDirectories)) { Log("Reading {0}", PluginFile); string InputText = File.ReadAllText(PluginFile.FullName); // Parse the descriptor PluginDescriptor Descriptor; try { Descriptor = new PluginDescriptor(JsonObject.Parse(InputText)); } catch (JsonParseException Ex) { LogError("Unable to parse {0}: {1}", PluginFile, Ex.ToString()); continue; } // Update the fields if (CreatedBy != null && Descriptor.CreatedBy != CreatedBy) { Log(" Updating 'CreatedBy' field from '{0}' to '{1}'", Descriptor.CreatedBy ?? "<empty>", CreatedBy); Descriptor.CreatedBy = CreatedBy; } if (CreatedByUrl != null) { Log(" Updating 'CreatedByURL' field from '{0}' to '{1}'", Descriptor.CreatedByURL ?? "<empty>", CreatedByUrl); Descriptor.CreatedByURL = CreatedByUrl; } // Format the output text StringBuilder Output = new StringBuilder(); using (JsonWriter Writer = new JsonWriter(new StringWriter(Output))) { Writer.WriteObjectStart(); Descriptor.Write(Writer); Writer.WriteObjectEnd(); } // Compare the output and input; write it if it differs string OutputText = Output.ToString(); if (InputText != OutputText) { if (CommandUtils.IsReadOnly(PluginFile.FullName)) { if (!bForce) { LogWarning("File is read only; skipping write."); continue; } CommandUtils.SetFileAttributes(PluginFile.FullName, ReadOnly: false); } Log(" Writing updated file.", PluginFile); FileReference.WriteAllText(PluginFile, OutputText); } } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // if (UnrealBuildTool.BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { // copy the icons/launch screens from the engine { FileReference SourcePath = FileReference.Combine(SC.LocalRoot, "Engine", "Binaries", "TVOS", "AssetCatalog", "Assets.car"); if (FileReference.Exists(SourcePath)) { SC.StageFile(StagedFileType.SystemNonUFS, SourcePath, new StagedFileReference("Assets.car")); } } // copy any additional framework assets that will be needed at runtime { DirectoryReference SourcePath = DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Intermediate", "TVOS", "FrameworkAssets"); if (DirectoryReference.Exists(SourcePath)) { SC.StageFiles(StagedFileType.SystemNonUFS, SourcePath, StageFilesSearch.AllDirectories, StagedDirectoryReference.Root); } } // copy the icons/launch screens from the game (may stomp the engine copies) { FileReference SourcePath = FileReference.Combine(SC.ProjectRoot, "Binaries", "TVOS", "AssetCatalog", "Assets.car"); if (FileReference.Exists(SourcePath)) { SC.StageFile(StagedFileType.SystemNonUFS, SourcePath, new StagedFileReference("Assets.car")); } } // copy the plist (only if code signing, as it's protected by the code sign blob in the executable and can't be modified independently) if (GetCodeSignDesirability(Params)) { DirectoryReference SourcePath = DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Intermediate", "TVOS"); FileReference TargetPListFile = FileReference.Combine(SourcePath, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + "-Info.plist"); // if (!File.Exists(TargetPListFile)) { // ensure the plist, entitlements, and provision files are properly copied Console.WriteLine("CookPlat {0}, this {1}", GetCookPlatform(false, false), ToString()); if (!SC.IsCodeBasedProject) { UnrealBuildTool.PlatformExports.SetRemoteIniPath(SC.ProjectRoot.FullName); } if (SC.StageTargetConfigurations.Count != 1) { throw new AutomationException("iOS is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations", SC.StageTargetConfigurations.Count); } var TargetConfiguration = SC.StageTargetConfigurations[0]; bool bSupportsPortrait = false; bool bSupportsLandscape = false; bool bSkipIcons = false; DeployGeneratePList(SC.RawProjectPath, TargetConfiguration, (SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), !SC.IsCodeBasedProject, (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game"), Params.Client, SC.ShortProjectName, SC.EngineRoot, DirectoryReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Binaries", "TVOS", "Payload", (SC.IsCodeBasedProject ? SC.ShortProjectName : "UE4Game") + ".app"), SC.StageExecutables[0], out bSupportsPortrait, out bSupportsLandscape, out bSkipIcons); } // copy the udebugsymbols if they exist { ConfigHierarchy PlatformGameConfig; bool bIncludeSymbols = false; if (Params.EngineConfigs.TryGetValue(SC.StageTargetPlatform.PlatformType, out PlatformGameConfig)) { PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGenerateCrashReportSymbols", out bIncludeSymbols); } if (bIncludeSymbols) { FileReference SymbolFileName = FileReference.Combine((SC.IsCodeBasedProject ? SC.ProjectRoot : SC.EngineRoot), "Binaries", "TVOS", SC.StageExecutables[0] + ".udebugsymbols"); if (FileReference.Exists(SymbolFileName)) { SC.StageFile(StagedFileType.NonUFS, SymbolFileName, new StagedFileReference((Params.ShortProjectName + ".udebugsymbols").ToLowerInvariant())); } } } SC.StageFile(StagedFileType.SystemNonUFS, TargetPListFile, new StagedFileReference("Info.plist")); } } // copy the movies from the project { StageMovieFiles(DirectoryReference.Combine(SC.EngineRoot, "Content", "Movies"), SC); StageMovieFiles(DirectoryReference.Combine(SC.ProjectRoot, "Content", "Movies"), SC); } { // Stage any *.metallib files as NonUFS. // Get the final output directory for cooked data DirectoryReference CookOutputDir; if (!String.IsNullOrEmpty(Params.CookOutputDir)) { CookOutputDir = DirectoryReference.Combine(new DirectoryReference(Params.CookOutputDir), SC.CookPlatform); } else if (Params.CookInEditor) { CookOutputDir = DirectoryReference.Combine(SC.ProjectRoot, "Saved", "EditorCooked", SC.CookPlatform); } else { CookOutputDir = DirectoryReference.Combine(SC.ProjectRoot, "Saved", "Cooked", SC.CookPlatform); } if (DirectoryReference.Exists(CookOutputDir)) { List <FileReference> CookedFiles = DirectoryReference.EnumerateFiles(CookOutputDir, "*.metallib", SearchOption.AllDirectories).ToList(); foreach (FileReference CookedFile in CookedFiles) { SC.StageFile(StagedFileType.NonUFS, CookedFile, new StagedFileReference(CookedFile.MakeRelativeTo(CookOutputDir))); } } } }
public override bool PublishSymbols(DirectoryReference SymbolStoreDirectory, List <FileReference> Files, string Product, string BuildVersion = null) { // Get the SYMSTORE.EXE path, using the latest SDK version we can find. FileReference SymStoreExe = GetSymStoreExe(); List <FileReference> FilesToAdd = Files.Where(x => x.HasExtension(".pdb") || x.HasExtension(".exe") || x.HasExtension(".dll")).ToList(); if (FilesToAdd.Count > 0) { DateTime Start = DateTime.Now; DirectoryReference TempSymStoreDir = DirectoryReference.Combine(RootDirectory, "Saved", "SymStore"); DirectoryReference.CreateDirectory(TempSymStoreDir); DeleteDirectoryContents(TempSymStoreDir); string TempFileName = Path.GetTempFileName(); try { File.WriteAllLines(TempFileName, FilesToAdd.Select(x => x.FullName), Encoding.ASCII); // Copy everything to the temp symstore ProcessStartInfo StartInfo = new ProcessStartInfo(); StartInfo.FileName = SymStoreExe.FullName; StartInfo.Arguments = string.Format("add /f \"@{0}\" /s \"{1}\" /t \"{2}\" /compress", TempFileName, TempSymStoreDir, Product); StartInfo.UseShellExecute = false; StartInfo.CreateNoWindow = true; if (Utils.RunLocalProcessAndLogOutput(StartInfo) != 0) { return(false); } } finally { File.Delete(TempFileName); } DateTime CompressDone = DateTime.Now; LogInformation("Took {0}s to compress the symbol files", (CompressDone - Start).TotalSeconds); // Take each new compressed file made and try and copy it to the real symstore. Exclude any symstore admin files foreach (FileReference File in DirectoryReference.EnumerateFiles(TempSymStoreDir, "*.*", SearchOption.AllDirectories).Where(File => File.HasExtension(".dl_") || File.HasExtension(".ex_") || File.HasExtension(".pd_"))) { string RelativePath = File.MakeRelativeTo(DirectoryReference.Combine(TempSymStoreDir)); FileReference ActualDestinationFile = FileReference.Combine(SymbolStoreDirectory, RelativePath); // Try and add a version file. Do this before checking to see if the symbol is there already in the case of exact matches (multiple builds could use the same pdb, for example) if (!string.IsNullOrWhiteSpace(BuildVersion)) { FileReference BuildVersionFile = FileReference.Combine(ActualDestinationFile.Directory, string.Format("{0}.version", BuildVersion)); // Attempt to create the file. Just continue if it fails. try { DirectoryReference.CreateDirectory(BuildVersionFile.Directory); FileReference.WriteAllText(BuildVersionFile, string.Empty); } catch (Exception Ex) { LogWarning("Failed to write the version file, reason {0}", Ex.ToString()); } } // Don't bother copying the temp file if the destination file is there already. if (FileReference.Exists(ActualDestinationFile)) { LogInformation("Destination file {0} already exists, skipping", ActualDestinationFile.FullName); continue; } FileReference TempDestinationFile = new FileReference(ActualDestinationFile.FullName + Guid.NewGuid().ToString()); try { CommandUtils.CopyFile(File.FullName, TempDestinationFile.FullName); } catch (Exception Ex) { throw new AutomationException("Couldn't copy the symbol file to the temp store! Reason: {0}", Ex.ToString()); } // Move the file in the temp store over. try { FileReference.Move(TempDestinationFile, ActualDestinationFile); } catch (Exception Ex) { // If the file is there already, it was likely either copied elsewhere (and this is an ioexception) or it had a file handle open already. // Either way, it's fine to just continue on. if (FileReference.Exists(ActualDestinationFile)) { LogInformation("Destination file {0} already exists or was in use, skipping.", ActualDestinationFile.FullName); continue; } // If it doesn't exist, we actually failed to copy it entirely. else { LogWarning("Couldn't move temp file {0} to the symbol store at location {1}! Reason: {2}", TempDestinationFile.FullName, ActualDestinationFile.FullName, Ex.ToString()); } } // Delete the temp one no matter what, don't want them hanging around in the symstore finally { FileReference.Delete(TempDestinationFile); } } LogInformation("Took {0}s to copy the symbol files to the store", (DateTime.Now - CompressDone).TotalSeconds); } return(true); }
/// <summary> /// Finds and/or compiles all script files and assemblies. /// </summary> /// <param name="ScriptsForProjectFileName">Path to the current project. May be null, in which case we compile scripts for all projects.</param> /// <param name="AdditionalScriptsFolders">Additional script fodlers to look for source files in.</param> public static void FindAndCompileAllScripts(string ScriptsForProjectFileName, List <string> AdditionalScriptsFolders) { // Find all the project files Stopwatch SearchTimer = Stopwatch.StartNew(); List <FileReference> ProjectFiles = FindAutomationProjects(ScriptsForProjectFileName, AdditionalScriptsFolders); Log.TraceLog("Found {0} project files in {1:0.000}s", ProjectFiles.Count, SearchTimer.Elapsed.TotalSeconds); // Get the default properties for compiling the projects Dictionary <string, string> MsBuildProperties = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); MsBuildProperties.Add("Platform", "AnyCPU"); MsBuildProperties.Add("Configuration", BuildConfig); MsBuildProperties.Add("EngineDir", CommandUtils.EngineDirectory.FullName); // Read all the projects Stopwatch ParsingTimer = Stopwatch.StartNew(); CsProjectInfo[] Projects = new CsProjectInfo[ProjectFiles.Count]; Parallel.For(0, ProjectFiles.Count, Idx => Projects[Idx] = CsProjectInfo.Read(ProjectFiles[Idx], MsBuildProperties)); Log.TraceLog("Parsed project files in {0:0.000}s", ParsingTimer.Elapsed.TotalSeconds); // Compile only if not disallowed. if (GlobalCommandLine.Compile && !String.IsNullOrEmpty(CommandUtils.CmdEnv.MsBuildExe)) { List <CsProjectInfo> CompileProjects = new List <CsProjectInfo>(Projects); if (CommandUtils.IsEngineInstalled()) { CompileProjects.RemoveAll(x => x.ProjectPath.IsUnderDirectory(CommandUtils.EngineDirectory)); } CompileAutomationProjects(CompileProjects, MsBuildProperties); } // Get all the build artifacts BuildProducts = new HashSet <FileReference>(); HashSet <DirectoryReference> OutputDirs = new HashSet <DirectoryReference>(); OutputDirs.Add(DirectoryReference.Combine(CommandUtils.EngineDirectory, "Binaries", "DotNET")); // Don't want any artifacts from this directory (just AutomationTool.exe and AutomationScripts.dll) foreach (CsProjectInfo Project in Projects) { DirectoryReference OutputDir; if (!Project.TryGetOutputDir(out OutputDir)) { throw new AutomationException("Unable to get output directory for {0}", Project.ProjectPath); } if (OutputDirs.Add(OutputDir)) { BuildProducts.UnionWith(DirectoryReference.EnumerateFiles(OutputDir)); } } // Load everything Stopwatch LoadTimer = Stopwatch.StartNew(); List <Assembly> Assemblies = LoadAutomationAssemblies(Projects); Log.TraceLog("Loaded assemblies in {0:0.000}s", LoadTimer.Elapsed.TotalSeconds); // Setup platforms Platform.InitializePlatforms(Assemblies.ToArray()); // Instantiate all the automation classes for interrogation Log.TraceVerbose("Creating commands."); ScriptCommands = new Dictionary <string, Type>(StringComparer.InvariantCultureIgnoreCase); foreach (Assembly CompiledScripts in Assemblies) { try { foreach (Type ClassType in CompiledScripts.GetTypes()) { if (ClassType.IsSubclassOf(typeof(BuildCommand)) && ClassType.IsAbstract == false) { if (ScriptCommands.ContainsKey(ClassType.Name) == false) { ScriptCommands.Add(ClassType.Name, ClassType); } else { bool IsSame = string.Equals(ClassType.AssemblyQualifiedName, ScriptCommands[ClassType.Name].AssemblyQualifiedName); if (IsSame == false) { Log.TraceWarning("Unable to add command {0} twice. Previous: {1}, Current: {2}", ClassType.Name, ClassType.AssemblyQualifiedName, ScriptCommands[ClassType.Name].AssemblyQualifiedName); } } } } } catch (ReflectionTypeLoadException LoadEx) { foreach (Exception SubEx in LoadEx.LoaderExceptions) { Log.TraceWarning("Got type loader exception: {0}", SubEx.ToString()); } throw new AutomationException("Failed to add commands from {0}. {1}", CompiledScripts, LoadEx); } catch (Exception Ex) { throw new AutomationException("Failed to add commands from {0}. {1}", CompiledScripts, Ex); } } }