/// <summary> /// /// </summary> /// <param name="ProjectFile"></param> /// <param name="Executable"></param> /// <param name="StageDirectory"></param> /// <param name="PlatformType"></param> public static void GenerateAssetCatalog(FileReference ProjectFile, FileReference Executable, DirectoryReference StageDirectory, UnrealTargetPlatform PlatformType) { CppPlatform Platform = PlatformType == UnrealTargetPlatform.IOS ? CppPlatform.IOS : CppPlatform.TVOS; // Determine whether the user has modified icons that require a remote Mac to build. bool bUserImagesExist = false; DirectoryReference ResourcesDir = IOSToolChain.GenerateAssetCatalog(ProjectFile, Platform, ref bUserImagesExist); // Don't attempt to do anything remotely if the user is using the default UE4 images. if (!bUserImagesExist) { return; } // Also don't attempt to use a remote Mac if packaging for TVOS on PC. if (Platform == CppPlatform.TVOS && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { return; } // Compile the asset catalog immediately if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { FileReference OutputFile = FileReference.Combine(StageDirectory, "Assets.car"); RemoteMac Remote = new RemoteMac(ProjectFile); Remote.RunAssetCatalogTool(Platform, ResourcesDir, OutputFile); } else { // Get the output file FileReference OutputFile = IOSToolChain.GetAssetCatalogFile(Platform, Executable); // Delete the Assets.car file to force the asset catalog to build every time, because // removals of files or copies of icons (for instance) with a timestamp earlier than // the last generated Assets.car will result in nothing built. if (FileReference.Exists(OutputFile)) { FileReference.Delete(OutputFile); } // Run the process locally using (Process Process = new Process()) { Process.StartInfo.FileName = "/usr/bin/xcrun"; Process.StartInfo.Arguments = IOSToolChain.GetAssetCatalogArgs(Platform, ResourcesDir.FullName, OutputFile.Directory.FullName);; Process.StartInfo.UseShellExecute = false; Utils.RunLocalProcess(Process); } } }
/// <summary> /// Main entry point /// </summary> /// <param name="Arguments">Command-line arguments</param> /// <returns>One of the values of ECompilationResult</returns> public override int Execute(CommandLineArguments Arguments) { Arguments.ApplyTo(this); // Create the build configuration object, and read the settings BuildConfiguration BuildConfiguration = new BuildConfiguration(); XmlConfig.ApplyTo(BuildConfiguration); Arguments.ApplyTo(BuildConfiguration); // Parse all the targets being built List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, bSkipRulesCompile); if (TargetDescriptors.Count == 0) { throw new BuildException("No targets specified to clean"); } // Also add implicit descriptors for cleaning UnrealBuildTool if (!BuildConfiguration.bDoNotBuildUHT) { const string UnrealHeaderToolTarget = "UnrealHeaderTool"; // Get a list of project files to clean UHT for List <FileReference> ProjectFiles = new List <FileReference>(); foreach (TargetDescriptor TargetDesc in TargetDescriptors) { if (TargetDesc.Name != UnrealHeaderToolTarget && !RemoteMac.HandlesTargetPlatform(TargetDesc.Platform)) { if (ProjectFiles.Count == 0) { ProjectFiles.Add(null); } if (TargetDesc.ProjectFile != null && !ProjectFiles.Contains(TargetDesc.ProjectFile)) { ProjectFiles.Add(TargetDesc.ProjectFile); } } } // Add descriptors for cleaning UHT with all these projects if (ProjectFiles.Count > 0) { UnrealTargetConfiguration Configuration = BuildConfiguration.bForceDebugUnrealHeaderTool ? UnrealTargetConfiguration.Debug : UnrealTargetConfiguration.Development; string Architecture = UEBuildPlatform.GetBuildPlatform(BuildHostPlatform.Current.Platform).GetDefaultArchitecture(null); foreach (FileReference ProjectFile in ProjectFiles) { TargetDescriptors.Add(new TargetDescriptor(ProjectFile, UnrealHeaderToolTarget, BuildHostPlatform.Current.Platform, Configuration, Architecture, null)); } } } // Output the list of targets that we're cleaning Log.TraceInformation("Cleaning {0} binaries...", StringUtils.FormatList(TargetDescriptors.Select(x => x.Name).Distinct())); // Loop through all the targets, and clean them all HashSet <FileReference> FilesToDelete = new HashSet <FileReference>(); HashSet <DirectoryReference> DirectoriesToDelete = new HashSet <DirectoryReference>(); foreach (TargetDescriptor TargetDescriptor in TargetDescriptors) { // Create the rules assembly RulesAssembly RulesAssembly = RulesCompiler.CreateTargetRulesAssembly(TargetDescriptor.ProjectFile, TargetDescriptor.Name, bSkipRulesCompile, BuildConfiguration.bUsePrecompiled, TargetDescriptor.ForeignPlugin); // Create the rules object ReadOnlyTargetRules Target = new ReadOnlyTargetRules(RulesAssembly.CreateTargetRules(TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration, TargetDescriptor.Architecture, TargetDescriptor.ProjectFile, TargetDescriptor.AdditionalArguments)); // Find the base folders that can contain binaries List <DirectoryReference> BaseDirs = new List <DirectoryReference>(); BaseDirs.Add(UnrealBuildTool.EngineDirectory); BaseDirs.Add(UnrealBuildTool.EnterpriseDirectory); foreach (FileReference Plugin in Plugins.EnumeratePlugins(Target.ProjectFile)) { BaseDirs.Add(Plugin.Directory); } if (Target.ProjectFile != null) { BaseDirs.Add(Target.ProjectFile.Directory); } // If we're running a precompiled build, remove anything under the engine folder BaseDirs.RemoveAll(x => RulesAssembly.IsReadOnly(x)); // Get all the names which can prefix build products List <string> NamePrefixes = new List <string>(); if (Target.Type != TargetType.Program) { NamePrefixes.Add(UEBuildTarget.GetAppNameForTargetType(Target.Type)); } NamePrefixes.Add(Target.Name); // Get the suffixes for this configuration List <string> NameSuffixes = new List <string>(); if (Target.Configuration == Target.UndecoratedConfiguration) { NameSuffixes.Add(""); } NameSuffixes.Add(String.Format("-{0}-{1}", Target.Platform.ToString(), Target.Configuration.ToString())); if (!String.IsNullOrEmpty(Target.Architecture)) { NameSuffixes.AddRange(NameSuffixes.ToArray().Select(x => x + Target.Architecture)); } // Add all the makefiles and caches to be deleted FilesToDelete.Add(TargetMakefile.GetLocation(Target.ProjectFile, Target.Name, Target.Platform, Target.Configuration)); FilesToDelete.UnionWith(SourceFileMetadataCache.GetFilesToClean(Target.ProjectFile)); FilesToDelete.UnionWith(ActionHistory.GetFilesToClean(Target.ProjectFile, Target.Name, Target.Platform, Target.Type)); // Add all the intermediate folders to be deleted foreach (DirectoryReference BaseDir in BaseDirs) { foreach (string NamePrefix in NamePrefixes) { DirectoryReference GeneratedCodeDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, "Inc"); if (DirectoryReference.Exists(GeneratedCodeDir)) { DirectoriesToDelete.Add(GeneratedCodeDir); } DirectoryReference IntermediateDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, Target.Configuration.ToString()); if (DirectoryReference.Exists(IntermediateDir)) { DirectoriesToDelete.Add(IntermediateDir); } } } // List of additional files and directories to clean, specified by the target platform List <FileReference> AdditionalFilesToDelete = new List <FileReference>(); List <DirectoryReference> AdditionalDirectoriesToDelete = new List <DirectoryReference>(); // Add all the build products from this target string[] NamePrefixesArray = NamePrefixes.Distinct().ToArray(); string[] NameSuffixesArray = NameSuffixes.Distinct().ToArray(); foreach (DirectoryReference BaseDir in BaseDirs) { DirectoryReference BinariesDir = DirectoryReference.Combine(BaseDir, "Binaries", Target.Platform.ToString()); if (DirectoryReference.Exists(BinariesDir)) { UEBuildPlatform.GetBuildPlatform(Target.Platform).FindBuildProductsToClean(BinariesDir, NamePrefixesArray, NameSuffixesArray, AdditionalFilesToDelete, AdditionalDirectoriesToDelete); } } // Get all the additional intermediate folders created by this platform UEBuildPlatform.GetBuildPlatform(Target.Platform).FindAdditionalBuildProductsToClean(Target, AdditionalFilesToDelete, AdditionalDirectoriesToDelete); // Add the platform's files and directories to the main list FilesToDelete.UnionWith(AdditionalFilesToDelete); DirectoriesToDelete.UnionWith(AdditionalDirectoriesToDelete); } // Delete all the directories, then all the files. By sorting the list of directories before we delete them, we avoid spamming the log if a parent directory is deleted first. foreach (DirectoryReference DirectoryToDelete in DirectoriesToDelete.OrderBy(x => x.FullName)) { if (DirectoryReference.Exists(DirectoryToDelete)) { Log.TraceVerbose(" Deleting {0}{1}...", DirectoryToDelete, Path.DirectorySeparatorChar); try { DirectoryReference.Delete(DirectoryToDelete, true); } catch (Exception Ex) { throw new BuildException(Ex, "Unable to delete {0} ({1})", DirectoryToDelete, Ex.Message.TrimEnd()); } } } foreach (FileReference FileToDelete in FilesToDelete.OrderBy(x => x.FullName)) { if (FileReference.Exists(FileToDelete)) { Log.TraceVerbose(" Deleting " + FileToDelete); try { FileReference.Delete(FileToDelete); } catch (Exception Ex) { throw new BuildException(Ex, "Unable to delete {0} ({1})", FileToDelete, Ex.Message.TrimEnd()); } } } // Also clean all the remote targets for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++) { TargetDescriptor TargetDescriptor = TargetDescriptors[Idx]; if (RemoteMac.HandlesTargetPlatform(TargetDescriptor.Platform)) { RemoteMac RemoteMac = new RemoteMac(TargetDescriptor.ProjectFile); RemoteMac.Clean(TargetDescriptor); } } return(0); }
/// <summary> /// Main entry point /// </summary> /// <param name="Arguments">Command-line arguments</param> /// <returns>One of the values of ECompilationResult</returns> public override int Execute(CommandLineArguments Arguments) { Arguments.ApplyTo(this); // Initialize the log system, buffering the output until we can create the log file StartupTraceListener StartupListener = new StartupTraceListener(); Trace.Listeners.Add(StartupListener); // Write the command line Log.TraceLog("Command line: {0}", Environment.CommandLine); // Grab the environment. UnrealBuildTool.InitialEnvironment = Environment.GetEnvironmentVariables(); if (UnrealBuildTool.InitialEnvironment.Count < 1) { throw new BuildException("Environment could not be read"); } // Read the XML configuration files XmlConfig.ApplyTo(this); // Fixup the log path if it wasn't overridden by a config file if (BaseLogFileName == null) { BaseLogFileName = FileReference.Combine(UnrealBuildTool.EngineProgramSavedDirectory, "UnrealBuildTool", "Log.txt").FullName; } // Create the log file, and flush the startup listener to it if (!Arguments.HasOption("-NoLog") && !Log.HasFileWriter()) { FileReference LogFile = new FileReference(BaseLogFileName); foreach (string LogSuffix in Arguments.GetValues("-LogSuffix=")) { LogFile = LogFile.ChangeExtension(null) + "_" + LogSuffix + LogFile.GetExtension(); } TextWriterTraceListener LogTraceListener = Log.AddFileWriter("DefaultLogTraceListener", LogFile); StartupListener.CopyTo(LogTraceListener); } Trace.Listeners.Remove(StartupListener); // Create the build configuration object, and read the settings BuildConfiguration BuildConfiguration = new BuildConfiguration(); XmlConfig.ApplyTo(BuildConfiguration); Arguments.ApplyTo(BuildConfiguration); // Check the root path length isn't too long if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64 && UnrealBuildTool.RootDirectory.FullName.Length > BuildConfiguration.MaxRootPathLength) { Log.TraceWarning("Running from a path with a long directory name (\"{0}\" = {1} characters). Root paths shorter than {2} characters are recommended to avoid exceeding maximum path lengths on Windows.", UnrealBuildTool.RootDirectory, UnrealBuildTool.RootDirectory.FullName.Length, BuildConfiguration.MaxRootPathLength); } // now that we know the available platforms, we can delete other platforms' junk. if we're only building specific modules from the editor, don't touch anything else (it may be in use). if (!bIgnoreJunk && !UnrealBuildTool.IsEngineInstalled()) { using (Timeline.ScopeEvent("DeleteJunk()")) { JunkDeleter.DeleteJunk(); } } // Parse and build the targets try { List <TargetDescriptor> TargetDescriptors; // Parse all the target descriptors using (Timeline.ScopeEvent("TargetDescriptor.ParseCommandLine()")) { TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile); } // Hack for specific files compile; don't build the ShaderCompileWorker target that's added to the command line for generated project files if (TargetDescriptors.Count >= 2) { TargetDescriptors.RemoveAll(x => (x.Name == "ShaderCompileWorker" || x.Name == "LiveCodingConsole") && x.SpecificFilesToCompile.Count > 0); } // Handle remote builds for (int Idx = 0; Idx < TargetDescriptors.Count; ++Idx) { TargetDescriptor TargetDesc = TargetDescriptors[Idx]; if (RemoteMac.HandlesTargetPlatform(TargetDesc.Platform)) { FileReference BaseLogFile = Log.OutputFile ?? new FileReference(BaseLogFileName); FileReference RemoteLogFile = FileReference.Combine(BaseLogFile.Directory, BaseLogFile.GetFileNameWithoutExtension() + "_Remote.txt"); RemoteMac RemoteMac = new RemoteMac(TargetDesc.ProjectFile); if (!RemoteMac.Build(TargetDesc, RemoteLogFile, bSkipPreBuildTargets)) { return((int)CompilationResult.Unknown); } TargetDescriptors.RemoveAt(Idx--); } } // Handle local builds if (TargetDescriptors.Count > 0) { // Get a set of all the project directories HashSet <DirectoryReference> ProjectDirs = new HashSet <DirectoryReference>(); foreach (TargetDescriptor TargetDesc in TargetDescriptors) { if (TargetDesc.ProjectFile != null) { DirectoryReference ProjectDirectory = TargetDesc.ProjectFile.Directory; FileMetadataPrefetch.QueueProjectDirectory(ProjectDirectory); ProjectDirs.Add(ProjectDirectory); } } // Get all the build options BuildOptions Options = BuildOptions.None; if (bSkipBuild) { Options |= BuildOptions.SkipBuild; } if (bXGEExport) { Options |= BuildOptions.XGEExport; } if (bNoEngineChanges) { Options |= BuildOptions.NoEngineChanges; } // Create the working set provider per group. using (ISourceFileWorkingSet WorkingSet = SourceFileWorkingSet.Create(UnrealBuildTool.RootDirectory, ProjectDirs)) { Build(TargetDescriptors, BuildConfiguration, WorkingSet, Options, WriteOutdatedActionsFile, bSkipPreBuildTargets); } } } finally { // Save all the caches SourceFileMetadataCache.SaveAll(); CppDependencyCache.SaveAll(); } return(0); }
/// <summary> /// Main entry point /// </summary> /// <param name="Arguments">Command-line arguments</param> /// <returns>One of the values of ECompilationResult</returns> public override int Execute(CommandLineArguments Arguments) { Arguments.ApplyTo(this); // Initialize the log system, buffering the output until we can create the log file StartupTraceListener StartupListener = new StartupTraceListener(); Trace.Listeners.Add(StartupListener); // Write the command line Log.TraceLog("Command line: {0}", Environment.CommandLine); // Grab the environment. UnrealBuildTool.InitialEnvironment = Environment.GetEnvironmentVariables(); if (UnrealBuildTool.InitialEnvironment.Count < 1) { throw new BuildException("Environment could not be read"); } // Read the XML configuration files XmlConfig.ApplyTo(this); // Create the log file, and flush the startup listener to it if (!Arguments.HasOption("-NoLog") && !Log.HasFileWriter()) { FileReference LogFile = new FileReference(BaseLogFileName); foreach (string LogSuffix in Arguments.GetValues("-LogSuffix=")) { LogFile = LogFile.ChangeExtension(null) + "_" + LogSuffix + LogFile.GetExtension(); } TextWriterTraceListener LogTraceListener = Log.AddFileWriter("DefaultLogTraceListener", LogFile); StartupListener.CopyTo(LogTraceListener); } Trace.Listeners.Remove(StartupListener); // Create the build configuration object, and read the settings BuildConfiguration BuildConfiguration = new BuildConfiguration(); XmlConfig.ApplyTo(BuildConfiguration); Arguments.ApplyTo(BuildConfiguration); // now that we know the available platforms, we can delete other platforms' junk. if we're only building specific modules from the editor, don't touch anything else (it may be in use). if (!bIgnoreJunk && !UnrealBuildTool.IsEngineInstalled()) { using (Timeline.ScopeEvent("DeleteJunk()")) { JunkDeleter.DeleteJunk(); } } // Parse and build the targets try { // Parse all the target descriptors List <TargetDescriptor> TargetDescriptors; using (Timeline.ScopeEvent("TargetDescriptor.ParseCommandLine()")) { TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile); } // Hack for single file compile; don't build the ShaderCompileWorker target that's added to the command line for generated project files if (TargetDescriptors.Count >= 2) { TargetDescriptors.RemoveAll(x => x.Name == "ShaderCompileWorker" && x.SingleFileToCompile != null); } // Handle remote builds for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++) { TargetDescriptor TargetDesc = TargetDescriptors[Idx]; if (RemoteMac.HandlesTargetPlatform(TargetDesc.Platform)) { FileReference BaseLogFile = Log.OutputFile ?? new FileReference(BaseLogFileName); FileReference RemoteLogFile = FileReference.Combine(BaseLogFile.Directory, BaseLogFile.GetFileNameWithoutExtension() + "_Remote.txt"); RemoteMac RemoteMac = new RemoteMac(TargetDesc.ProjectFile); if (!RemoteMac.Build(TargetDesc, RemoteLogFile)) { return((int)CompilationResult.Unknown); } TargetDescriptors.RemoveAt(Idx--); } } // Handle local builds if (TargetDescriptors.Count > 0) { // Get a set of all the project directories HashSet <DirectoryReference> ProjectDirs = new HashSet <DirectoryReference>(); foreach (TargetDescriptor TargetDesc in TargetDescriptors) { if (TargetDesc.ProjectFile != null) { DirectoryReference ProjectDirectory = TargetDesc.ProjectFile.Directory; FileMetadataPrefetch.QueueProjectDirectory(ProjectDirectory); ProjectDirs.Add(ProjectDirectory); } } // Get all the build options BuildOptions Options = BuildOptions.None; if (bSkipBuild) { Options |= BuildOptions.SkipBuild; } if (bXGEExport) { Options |= BuildOptions.XGEExport; } // Create the working set provider using (ISourceFileWorkingSet WorkingSet = SourceFileWorkingSet.Create(UnrealBuildTool.RootDirectory, ProjectDirs)) { Build(TargetDescriptors, BuildConfiguration, WorkingSet, Options); } } } finally { // Save all the caches SourceFileMetadataCache.SaveAll(); CppDependencyCache.SaveAll(); } return(0); }