Esempio n. 1
0
        /// <summary>
        /// Execute the mode
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns></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);

            // Ensure the path to the output file is valid
            if (OutputFile == null)
            {
                OutputFile = GetDefaultOutputFile(ProjectFile);
            }

            // Create the rules assembly
            RulesAssembly Assembly;

            if (ProjectFile == null)
            {
                Assembly = RulesCompiler.CreateEnterpriseRulesAssembly(BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile);
            }
            else
            {
                Assembly = RulesCompiler.CreateProjectRulesAssembly(ProjectFile, BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile);
            }

            // Write information about these targets
            WriteTargetInfo(ProjectFile, Assembly, OutputFile, Arguments);
            Log.TraceInformation("Written {0}", OutputFile);
            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);

            // Read the XML configuration files
            XmlConfig.ApplyTo(this);

            // Create the build configuration object, and read the settings
            BuildConfiguration BuildConfiguration = new BuildConfiguration();

            XmlConfig.ApplyTo(BuildConfiguration);
            Arguments.ApplyTo(BuildConfiguration);

            // Read the actions file
            List <Action> Actions;

            using (Timeline.ScopeEvent("ActionGraph.ReadActions()"))
            {
                Actions = ActionGraph.ImportJson(ActionsFile);
            }

            // Link the action graph
            using (Timeline.ScopeEvent("ActionGraph.Link()"))
            {
                ActionGraph.Link(Actions);
            }

            // Execute the actions
            using (Timeline.ScopeEvent("ActionGraph.ExecuteActions()"))
            {
                ActionGraph.ExecuteActions(BuildConfiguration, Actions);
            }

            return(0);
        }
        /// <summary>
        /// Execute this command
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code (always zero)</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, false, false);

            foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
            {
                // Create the target
                UEBuildTarget Target = UEBuildTarget.Create(TargetDescriptor, false, false);

                // Get the output file
                FileReference OutputFile = TargetDescriptor.AdditionalArguments.GetFileReferenceOrDefault("-OutputFile=", null);
                if (OutputFile == null)
                {
                    OutputFile = Target.ReceiptFileName.ChangeExtension(".json");
                }

                // Execute code generation actions
                if (bExecCodeGenActions)
                {
                    using (ISourceFileWorkingSet WorkingSet = new EmptySourceFileWorkingSet())
                    {
                        // Create the build configuration object, and read the settings
                        BuildConfiguration BuildConfiguration = new BuildConfiguration();
                        XmlConfig.ApplyTo(BuildConfiguration);
                        Arguments.ApplyTo(BuildConfiguration);

                        // Create the makefile
                        const bool     bIsAssemblingBuild = true;
                        TargetMakefile Makefile           = Target.Build(BuildConfiguration, WorkingSet, bIsAssemblingBuild, TargetDescriptor.SingleFileToCompile);
                        ActionGraph.Link(Makefile.Actions);

                        // Filter all the actions to execute
                        HashSet <FileItem> PrerequisiteItems   = new HashSet <FileItem>(Makefile.Actions.SelectMany(x => x.ProducedItems).Where(x => x.HasExtension(".h") || x.HasExtension(".cpp")));
                        List <Action>      PrerequisiteActions = ActionGraph.GatherPrerequisiteActions(Makefile.Actions, PrerequisiteItems);

                        // Execute these actions
                        if (PrerequisiteActions.Count > 0)
                        {
                            Log.TraceInformation("Exeucting actions that produce source files...");
                            ActionGraph.ExecuteActions(BuildConfiguration, PrerequisiteActions);
                        }
                    }
                }

                // Write the output file
                Log.TraceInformation("Writing {0}...", OutputFile);
                Target.ExportJson(OutputFile);
            }
            return(0);
        }
Esempio n. 4
0
 public RiderProjectFileGenerator(FileReference InOnlyGameProject,
                                  CommandLineArguments InArguments)
     : base(InOnlyGameProject)
 {
     Arguments = InArguments;
     Arguments.ApplyTo(this);
 }
Esempio n. 5
0
        /// <summary>
        /// Executes the tool with the given arguments
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            // Output a message if there are any arguments that are still unused
            Arguments.ApplyTo(this);
            Arguments.CheckAllArgumentsUsed();

            // If the -AllPlatforms argument is specified, add all the known platforms into the list
            if (bAllPlatforms)
            {
                Platforms.UnionWith(UnrealTargetPlatform.GetValidPlatforms());
            }

            // Output a line for each registered platform
            foreach (UnrealTargetPlatform Platform in Platforms)
            {
                UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(Platform, true);
                if (BuildPlatform != null && BuildPlatform.HasRequiredSDKsInstalled() == SDKStatus.Valid)
                {
                    Log.TraceInformation("##PlatformValidate: {0} VALID", Platform.ToString());
                }
                else
                {
                    Log.TraceInformation("##PlatformValidate: {0} INVALID", Platform.ToString());
                }
            }
            return(0);
        }
Esempio n. 6
0
 /// <summary>
 /// Initialize the options with the given commnad line arguments
 /// </summary>
 /// <param name="Arguments"></param>
 public GlobalOptions(CommandLineArguments Arguments)
 {
     Arguments.ApplyTo(this);
     if (!string.IsNullOrEmpty(RemoteIni))
     {
         UnrealBuildTool.SetRemoteIniPath(RemoteIni);
     }
 }
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);
            Arguments.CheckAllArgumentsUsed();

            // Run the PostBuildSync command
            IOSPostBuildSyncTarget Target = BinaryFormatterUtils.Load <IOSPostBuildSyncTarget>(InputFile);

            IOSToolChain.PostBuildSync(Target);

            return(0);
        }
Esempio n. 8
0
        /// <summary>
        /// Execute the tool mode
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            // Apply the arguments
            Arguments.ApplyTo(this);
            Arguments.CheckAllArgumentsUsed();

            // Execute the deploy
            TargetReceipt Receipt = TargetReceipt.Read(ReceiptFile);

            Log.WriteLine(LogEventType.Console, "Deploying {0} {1} {2}...", Receipt.TargetName, Receipt.Platform, Receipt.Configuration);
            UEBuildPlatform.GetBuildPlatform(Receipt.Platform).Deploy(Receipt);

            return((int)CompilationResult.Succeeded);
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="ProjectFile">Path to the project file</param>
        /// <param name="TargetName">Name of the target to build</param>
        /// <param name="Platform">Platform to build for</param>
        /// <param name="Configuration">Configuration to build</param>
        /// <param name="Architecture">Architecture to build for</param>
        /// <param name="Arguments">Other command-line arguments for the target</param>
        public TargetDescriptor(FileReference ProjectFile, string TargetName, UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, string Architecture, CommandLineArguments Arguments)
        {
            this.ProjectFile   = ProjectFile;
            this.Name          = TargetName;
            this.Platform      = Platform;
            this.Configuration = Configuration;
            this.Architecture  = Architecture;

            // If there are any additional command line arguments
            List <string> AdditionalArguments = new List <string>();

            if (Arguments != null)
            {
                // Apply the arguments to this object
                Arguments.ApplyTo(this);

                // Parse all the hot-reload module names
                foreach (string ModuleWithSuffix in Arguments.GetValues("-ModuleWithSuffix="))
                {
                    int SuffixIdx = ModuleWithSuffix.LastIndexOf(',');
                    if (SuffixIdx == -1)
                    {
                        throw new BuildException("Missing suffix argument from -ModuleWithSuffix=Name,Suffix");
                    }

                    string ModuleName = ModuleWithSuffix.Substring(0, SuffixIdx);

                    int Suffix;
                    if (!Int32.TryParse(ModuleWithSuffix.Substring(SuffixIdx + 1), out Suffix))
                    {
                        throw new BuildException("Suffix for modules must be an integer");
                    }

                    HotReloadModuleNameToSuffix[ModuleName] = Suffix;
                }

                // Pull out all the arguments that haven't been used so far
                for (int Idx = 0; Idx < Arguments.Count; Idx++)
                {
                    if (!Arguments.HasBeenUsed(Idx))
                    {
                        AdditionalArguments.Add(Arguments[Idx]);
                    }
                }
            }
            this.AdditionalArguments = new CommandLineArguments(AdditionalArguments.ToArray());
        }
Esempio n. 10
0
        /// <summary>
        /// Entry point for this command
        /// </summary>
        /// <returns></returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);
            Arguments.CheckAllArgumentsUsed();

            switch (Type)
            {
            case DocumentationType.BuildConfiguration:
                XmlConfig.WriteDocumentation(OutputFile);
                break;

            case DocumentationType.ModuleRules:
                RulesDocumentation.WriteDocumentation(typeof(ModuleRules), OutputFile);
                break;

            case DocumentationType.TargetRules:
                RulesDocumentation.WriteDocumentation(typeof(TargetRules), OutputFile);
                break;

            default:
                throw new BuildException("Invalid documentation type: {0}", Type);
            }
            return(0);
        }
Esempio n. 11
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);

            // 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);
        }
Esempio n. 12
0
        /// <summary>
        /// Execute the command
        /// </summary>
        /// <param name="Arguments">List of command line arguments</param>
        /// <returns>Always zero, or throws an exception</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);
            Arguments.CheckAllArgumentsUsed();

            Log.TraceInformation("{0}", OutputFile.GetFileName());

            // Read the input files
            string[]        InputFileLines = FileReference.ReadAllLines(InputFileList);
            FileReference[] InputFiles     = InputFileLines.Select(x => x.Trim()).Where(x => x.Length > 0).Select(x => new FileReference(x)).ToArray();

            // Create the combined output file, and print the diagnostics to the log
            HashSet <string> UniqueItems = new HashSet <string>();

            using (StreamWriter RawWriter = new StreamWriter(OutputFile.FullName))
            {
                foreach (FileReference InputFile in InputFiles)
                {
                    string[] Lines = File.ReadAllLines(InputFile.FullName);
                    for (int LineIdx = 0; LineIdx < Lines.Length; LineIdx++)
                    {
                        string Line = Lines[LineIdx];
                        if (!String.IsNullOrWhiteSpace(Line) && UniqueItems.Add(Line))
                        {
                            bool bCanParse = false;

                            string[] Tokens = Line.Split(new string[] { "<#~>" }, StringSplitOptions.None);
                            if (Tokens.Length >= 9)
                            {
                                //string Trial = Tokens[1];
                                string LineNumberStr  = Tokens[2];
                                string FileName       = Tokens[3];
                                string WarningCode    = Tokens[5];
                                string WarningMessage = Tokens[6];
                                string FalseAlarmStr  = Tokens[7];
                                string LevelStr       = Tokens[8];

                                int  LineNumber;
                                bool bFalseAlarm;
                                int  Level;
                                if (int.TryParse(LineNumberStr, out LineNumber) && bool.TryParse(FalseAlarmStr, out bFalseAlarm) && int.TryParse(LevelStr, out Level))
                                {
                                    bCanParse = true;

                                    // Ignore anything in ThirdParty folders
                                    if (FileName.Replace('/', '\\').IndexOf("\\ThirdParty\\", StringComparison.InvariantCultureIgnoreCase) == -1)
                                    {
                                        // Output the line to the raw output file
                                        RawWriter.WriteLine(Line);

                                        // Output the line to the log
                                        if (!bFalseAlarm && Level == 1)
                                        {
                                            Log.WriteLine(LogEventType.Warning, LogFormatOptions.NoSeverityPrefix, "{0}({1}): warning {2}: {3}", FileName, LineNumber, WarningCode, WarningMessage);
                                        }
                                    }
                                }
                            }

                            if (!bCanParse)
                            {
                                Log.WriteLine(LogEventType.Warning, LogFormatOptions.NoSeverityPrefix, "{0}({1}): warning: Unable to parse PVS output line '{2}' (tokens=|{3}|)", InputFile, LineIdx + 1, Line, String.Join("|", Tokens));
                            }
                        }
                    }
                }
            }
            Log.TraceInformation("Written {0} {1} to {2}.", UniqueItems.Count, (UniqueItems.Count == 1)? "diagnostic" : "diagnostics", OutputFile.FullName);
            return(0);
        }
Esempio n. 13
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>
        /// Execute the tool mode
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            // Apply any command line arguments to this class
            Arguments.ApplyTo(this);

            // Apply the XML config to this class
            XmlConfig.ApplyTo(this);

            // Parse rocket-specific arguments.
            FileReference ProjectFile;

            TryParseProjectFileArgument(Arguments, out ProjectFile);

            // If there aren't any formats set, read the default project file format from the config file
            if (ProjectFileFormats.Count == 0)
            {
                // Read from the XML config
                if (!String.IsNullOrEmpty(ProjectFileGeneratorSettings.Format))
                {
                    ProjectFileFormats.UnionWith(ProjectFileGeneratorSettings.ParseFormatList(ProjectFileGeneratorSettings.Format));
                }

                // Read from the editor config
                ProjectFileFormat PreferredSourceCodeAccessor;
                if (ProjectFileGenerator.GetPreferredSourceCodeAccessor(ProjectFile, out PreferredSourceCodeAccessor))
                {
                    ProjectFileFormats.Add(PreferredSourceCodeAccessor);
                }

                // If there's still nothing set, get the default project file format for this platform
                if (ProjectFileFormats.Count == 0)
                {
                    ProjectFileFormats.UnionWith(BuildHostPlatform.Current.GetDefaultProjectFileFormats());
                }
            }

            // Register all the platform project generators
            PlatformProjectGeneratorCollection PlatformProjectGenerators = new PlatformProjectGeneratorCollection();

            foreach (Type CheckType in Assembly.GetExecutingAssembly().GetTypes())
            {
                if (CheckType.IsClass && !CheckType.IsAbstract && CheckType.IsSubclassOf(typeof(PlatformProjectGenerator)))
                {
                    PlatformProjectGenerator Generator = (PlatformProjectGenerator)Activator.CreateInstance(CheckType, Arguments);
                    foreach (UnrealTargetPlatform Platform in Generator.GetPlatforms())
                    {
                        if (DisablePlatformProjectGenerators == null || !DisablePlatformProjectGenerators.Any(x => x.Equals(Platform.ToString(), StringComparison.OrdinalIgnoreCase)))
                        {
                            Log.TraceVerbose("Registering project generator {0} for {1}", CheckType, Platform);
                            PlatformProjectGenerators.RegisterPlatformProjectGenerator(Platform, Generator);
                        }
                    }
                }
            }

            // Create each project generator and run it
            List <ProjectFileGenerator> Generators = new List <ProjectFileGenerator>();

            foreach (ProjectFileFormat ProjectFileFormat in ProjectFileFormats.Distinct())
            {
                ProjectFileGenerator Generator;
                switch (ProjectFileFormat)
                {
                case ProjectFileFormat.Make:
                    Generator = new MakefileGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.CMake:
                    Generator = new CMakefileGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.QMake:
                    Generator = new QMakefileGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.KDevelop:
                    Generator = new KDevelopGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.CodeLite:
                    Generator = new CodeLiteGenerator(ProjectFile, Arguments);
                    break;

                case ProjectFileFormat.VisualStudio:
                    Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.Default, Arguments);
                    break;

                case ProjectFileFormat.VisualStudio2012:
                    Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.VisualStudio2012, Arguments);
                    break;

                case ProjectFileFormat.VisualStudio2013:
                    Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.VisualStudio2013, Arguments);
                    break;

                case ProjectFileFormat.VisualStudio2015:
                    Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.VisualStudio2015, Arguments);
                    break;

                case ProjectFileFormat.VisualStudio2017:
                    Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.VisualStudio2017, Arguments);
                    break;

                case ProjectFileFormat.VisualStudio2019:
                    Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.VisualStudio2019, Arguments);
                    break;

                case ProjectFileFormat.XCode:
                    Generator = new XcodeProjectFileGenerator(ProjectFile, Arguments);
                    break;

                case ProjectFileFormat.Eddie:
                    Generator = new EddieProjectFileGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.VisualStudioCode:
                    Generator = new VSCodeProjectFileGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.CLion:
                    Generator = new CLionGenerator(ProjectFile);
                    break;

                case ProjectFileFormat.VisualStudioMac:
                    Generator = new VCMacProjectFileGenerator(ProjectFile, Arguments);
                    break;

                default:
                    throw new BuildException("Unhandled project file type '{0}", ProjectFileFormat);
                }
                Generators.Add(Generator);
            }

            // Check there are no superfluous command line arguments
            // TODO (still pass raw arguments below)
            // Arguments.CheckAllArgumentsUsed();

            // Now generate project files
            ProjectFileGenerator.bGenerateProjectFiles = true;
            foreach (ProjectFileGenerator Generator in Generators)
            {
                if (!Generator.GenerateProjectFiles(PlatformProjectGenerators, Arguments.GetRawArray()))
                {
                    return((int)CompilationResult.OtherCompilationError);
                }
            }
            return((int)CompilationResult.Succeeded);
        }
Esempio n. 15
0
        /// <summary>
        /// Construct an instance of the given target rules
        /// </summary>
        /// <param name="TypeName">Type name of the target rules</param>
        /// <param name="TargetInfo">Target configuration information to pass to the constructor</param>
        /// <param name="Arguments">Command line arguments for this target</param>
        /// <returns>Instance of the corresponding TargetRules</returns>
        protected TargetRules CreateTargetRulesInstance(string TypeName, TargetInfo TargetInfo, CommandLineArguments Arguments)
        {
            // The build module must define a type named '<TargetName>Target' that derives from our 'TargetRules' type.
            Type RulesType = CompiledAssembly.GetType(TypeName);

            if (RulesType == null)
            {
                throw new BuildException("Expecting to find a type to be declared in a target rules named '{0}'.  This type must derive from the 'TargetRules' type defined by Unreal Build Tool.", TypeName);
            }

            // Create an instance of the module's rules object, and set some defaults before calling the constructor.
            TargetRules Rules = (TargetRules)FormatterServices.GetUninitializedObject(RulesType);

            Rules.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults;

            // Find the constructor
            ConstructorInfo Constructor = RulesType.GetConstructor(new Type[] { typeof(TargetInfo) });

            if (Constructor == null)
            {
                throw new BuildException("No constructor found on {0} which takes an argument of type TargetInfo.", RulesType.Name);
            }

            // Invoke the regular constructor
            try
            {
                Constructor.Invoke(Rules, new object[] { TargetInfo });
            }
            catch (Exception Ex)
            {
                throw new BuildException(Ex, "Unable to instantiate instance of '{0}' object type from compiled assembly '{1}'.  Unreal Build Tool creates an instance of your module's 'Rules' object in order to find out about your module's requirements.  The CLR exception details may provide more information:  {2}", TypeName, Path.GetFileNameWithoutExtension(CompiledAssembly.Location), Ex.ToString());
            }

            // Return the target file name to the caller
            Rules.File = TargetNameToTargetFile[TargetInfo.Name];

            // Set the default overriddes for the configured target type
            Rules.SetOverridesForTargetType();

            // Parse any additional command-line arguments. These override default settings specified in config files or the .target.cs files.
            if (Arguments != null)
            {
                foreach (object ConfigurableObject in Rules.GetConfigurableObjects())
                {
                    Arguments.ApplyTo(ConfigurableObject);
                }
            }

            // Set the final value for the link type in the target rules
            if (Rules.LinkType == TargetLinkType.Default)
            {
                throw new BuildException("TargetRules.LinkType should be inferred from TargetType");
            }

            // Set the default value for whether to use the shared build environment
            if (Rules.BuildEnvironment == TargetBuildEnvironment.Default)
            {
                if (Rules.Type == TargetType.Program && TargetInfo.ProjectFile != null && TargetNameToTargetFile[Rules.Name].IsUnderDirectory(TargetInfo.ProjectFile.Directory))
                {
                    Rules.BuildEnvironment = TargetBuildEnvironment.Unique;
                }
                else if (UnrealBuildTool.IsEngineInstalled() || Rules.LinkType != TargetLinkType.Monolithic)
                {
                    Rules.BuildEnvironment = TargetBuildEnvironment.Shared;
                }
                else
                {
                    Rules.BuildEnvironment = TargetBuildEnvironment.Unique;
                }
            }

            // Automatically include CoreUObject
            if (Rules.bCompileAgainstEngine)
            {
                Rules.bCompileAgainstCoreUObject = true;
            }

            // Must have editor only data if building the editor.
            if (Rules.bBuildEditor)
            {
                Rules.bBuildWithEditorOnlyData = true;
            }

            // Apply the override to force debug info to be enabled
            if (Rules.bForceDebugInfo)
            {
                Rules.bDisableDebugInfo             = false;
                Rules.bOmitPCDebugInfoInDevelopment = false;
            }

            // Setup the malloc profiler
            if (Rules.bUseMallocProfiler)
            {
                Rules.bOmitFramePointers = false;
                Rules.GlobalDefinitions.Add("USE_MALLOC_PROFILER=1");
            }

            // Set a macro if we allow using generated inis
            if (!Rules.bAllowGeneratedIniWhenCooked)
            {
                Rules.GlobalDefinitions.Add("DISABLE_GENERATED_INI_WHEN_COOKED=1");
            }

            if (!Rules.bAllowNonUFSIniWhenCooked)
            {
                Rules.GlobalDefinitions.Add("DISABLE_NONUFS_INI_WHEN_COOKED=1");
            }

            if (Rules.bDisableUnverifiedCertificates)
            {
                Rules.GlobalDefinitions.Add("DISABLE_UNVERIFIED_CERTIFICATE_LOADING=1");
            }

            // Allow the platform to finalize the settings
            UEBuildPlatform Platform = UEBuildPlatform.GetBuildPlatform(Rules.Platform);

            Platform.ValidateTarget(Rules);

            // Some platforms may *require* monolithic compilation...
            if (Rules.LinkType != TargetLinkType.Monolithic && UEBuildPlatform.PlatformRequiresMonolithicBuilds(Rules.Platform, Rules.Configuration))
            {
                throw new BuildException(String.Format("{0}: {1} does not support modular builds", Rules.Name, Rules.Platform));
            }

            return(Rules);
        }
Esempio n. 16
0
 public virtual void Configure(CommandLineArguments Arguments)
 {
     Arguments.ApplyTo(this);
 }
Esempio n. 17
0
        /// <summary>
        /// Execute the command
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</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 the filter argument
            FileFilter FileFilter = null;

            if (FilterRules.Count > 0)
            {
                FileFilter = new FileFilter(FileFilterType.Exclude);
                foreach (string FilterRule in FilterRules)
                {
                    FileFilter.AddRules(FilterRule.Split(';'));
                }
            }

            // Parse all the target descriptors
            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, BuildConfiguration.bSkipRulesCompile);

            // Generate the compile DB for each target
            using (ISourceFileWorkingSet WorkingSet = new EmptySourceFileWorkingSet())
            {
                // Find the compile commands for each file in the target
                Dictionary <FileReference, string> FileToCommand = new Dictionary <FileReference, string>();
                foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
                {
                    // Disable PCHs and unity builds for the target
                    TargetDescriptor.AdditionalArguments = TargetDescriptor.AdditionalArguments.Append(new string[] { "-NoPCH", "-DisableUnity" });

                    // Create a makefile for the target
                    UEBuildTarget Target = UEBuildTarget.Create(TargetDescriptor, BuildConfiguration.bSkipRulesCompile, BuildConfiguration.bUsePrecompiled);

                    // Find the location of the compiler
                    VCEnvironment Environment = VCEnvironment.Create(WindowsCompiler.Clang, Target.Platform, Target.Rules.WindowsPlatform.Architecture, null, Target.Rules.WindowsPlatform.WindowsSdkVersion, null);
                    FileReference ClangPath   = FileReference.Combine(Environment.CompilerDir, "bin", "clang++.exe");

                    // Convince each module to output its generated code include path
                    foreach (UEBuildBinary Binary in Target.Binaries)
                    {
                        foreach (UEBuildModuleCPP Module in Binary.Modules.OfType <UEBuildModuleCPP>())
                        {
                            Module.bAddGeneratedCodeIncludePath = true;
                        }
                    }

                    // Create all the binaries and modules
                    CppCompileEnvironment GlobalCompileEnvironment = Target.CreateCompileEnvironmentForProjectFiles();
                    foreach (UEBuildBinary Binary in Target.Binaries)
                    {
                        CppCompileEnvironment BinaryCompileEnvironment = Binary.CreateBinaryCompileEnvironment(GlobalCompileEnvironment);
                        foreach (UEBuildModuleCPP Module in Binary.Modules.OfType <UEBuildModuleCPP>())
                        {
                            if (!Module.Rules.bUsePrecompiled)
                            {
                                UEBuildModuleCPP.InputFileCollection InputFileCollection = Module.FindInputFiles(Target.Platform, new Dictionary <DirectoryItem, FileItem[]>());

                                List <FileItem> InputFiles = new List <FileItem>();
                                InputFiles.AddRange(InputFileCollection.CPPFiles);
                                InputFiles.AddRange(InputFileCollection.CCFiles);

                                CppCompileEnvironment ModuleCompileEnvironment = Module.CreateModuleCompileEnvironment(Target.Rules, BinaryCompileEnvironment);

                                StringBuilder CommandBuilder = new StringBuilder();
                                CommandBuilder.AppendFormat("\"{0}\"", ClangPath.FullName);
                                foreach (FileItem ForceIncludeFile in ModuleCompileEnvironment.ForceIncludeFiles)
                                {
                                    CommandBuilder.AppendFormat(" -include \"{0}\"", ForceIncludeFile.FullName);
                                }
                                foreach (string Definition in ModuleCompileEnvironment.Definitions)
                                {
                                    CommandBuilder.AppendFormat(" -D\"{0}\"", Definition);
                                }
                                foreach (DirectoryReference IncludePath in ModuleCompileEnvironment.UserIncludePaths)
                                {
                                    CommandBuilder.AppendFormat(" -I\"{0}\"", IncludePath);
                                }
                                foreach (DirectoryReference IncludePath in ModuleCompileEnvironment.SystemIncludePaths)
                                {
                                    CommandBuilder.AppendFormat(" -I\"{0}\"", IncludePath);
                                }

                                foreach (FileItem InputFile in InputFiles)
                                {
                                    if (FileFilter == null || FileFilter.Matches(InputFile.Location.MakeRelativeTo(UnrealBuildTool.RootDirectory)))
                                    {
                                        FileToCommand[InputFile.Location] = String.Format("{0} \"{1}\"", CommandBuilder, InputFile.FullName);
                                    }
                                }
                            }
                        }
                    }
                }

                // Write the compile database
                FileReference DatabaseFile = FileReference.Combine(UnrealBuildTool.RootDirectory, "compile_commands.json");
                using (JsonWriter Writer = new JsonWriter(DatabaseFile))
                {
                    Writer.WriteArrayStart();
                    foreach (KeyValuePair <FileReference, string> FileCommandPair in FileToCommand.OrderBy(x => x.Key.FullName))
                    {
                        Writer.WriteObjectStart();
                        Writer.WriteValue("file", FileCommandPair.Key.FullName);
                        Writer.WriteValue("command", FileCommandPair.Value);
                        Writer.WriteValue("directory", UnrealBuildTool.EngineSourceDirectory.ToString());
                        Writer.WriteObjectEnd();
                    }
                    Writer.WriteArrayEnd();
                }
            }

            return(0);
        }
Esempio n. 18
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);
        }