示例#1
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);
        }
示例#2
0
        /// <summary>
        /// Creates the makefile for a target. If an existing, valid makefile already exists on disk, loads that instead.
        /// </summary>
        /// <param name="BuildConfiguration">The build configuration</param>
        /// <param name="TargetDescriptor">Target being built</param>
        /// <param name="WorkingSet">Set of source files which are part of the working set</param>
        /// <returns>Makefile for the given target</returns>
        static TargetMakefile CreateMakefile(BuildConfiguration BuildConfiguration, TargetDescriptor TargetDescriptor, ISourceFileWorkingSet WorkingSet)
        {
            // Get the path to the makefile for this target
            FileReference MakefileLocation = null;

            if (BuildConfiguration.bUseUBTMakefiles && TargetDescriptor.SpecificFilesToCompile.Count == 0)
            {
                MakefileLocation = TargetMakefile.GetLocation(TargetDescriptor.ProjectFile, TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration);
            }

            // Try to load an existing makefile
            TargetMakefile Makefile = null;

            if (MakefileLocation != null)
            {
                using (Timeline.ScopeEvent("TargetMakefile.Load()"))
                {
                    string ReasonNotLoaded;
                    Makefile = TargetMakefile.Load(MakefileLocation, TargetDescriptor.ProjectFile, TargetDescriptor.Platform, TargetDescriptor.AdditionalArguments.GetRawArray(), out ReasonNotLoaded);
                    if (Makefile == null)
                    {
                        Log.TraceInformation("Creating makefile for {0} ({1})", TargetDescriptor.Name, ReasonNotLoaded);
                    }
                }
            }

            // If we have a makefile, execute the pre-build steps and check it's still valid
            bool bHasRunPreBuildScripts = false;

            if (Makefile != null)
            {
                // Execute the scripts. We have to invalidate all cached file info after doing so, because we don't know what may have changed.
                if (Makefile.PreBuildScripts.Length > 0)
                {
                    Utils.ExecuteCustomBuildSteps(Makefile.PreBuildScripts);
                    DirectoryItem.ResetAllCachedInfo_SLOW();
                }

                // Don't run the pre-build steps again, even if we invalidate the makefile.
                bHasRunPreBuildScripts = true;

                // Check that the makefile is still valid
                string Reason;
                if (!TargetMakefile.IsValidForSourceFiles(Makefile, TargetDescriptor.ProjectFile, TargetDescriptor.Platform, WorkingSet, out Reason))
                {
                    Log.TraceInformation("Invalidating makefile for {0} ({1})", TargetDescriptor.Name, Reason);
                    Makefile = null;
                }
            }

            // If we couldn't load a makefile, create a new one
            if (Makefile == null)
            {
                // Create the target
                UEBuildTarget Target;
                using (Timeline.ScopeEvent("UEBuildTarget.Create()"))
                {
                    Target = UEBuildTarget.Create(TargetDescriptor, BuildConfiguration.bSkipRulesCompile, BuildConfiguration.bUsePrecompiled);
                }

                // Create the pre-build scripts
                FileReference[] PreBuildScripts = Target.CreatePreBuildScripts();

                // Execute the pre-build scripts
                if (!bHasRunPreBuildScripts)
                {
                    Utils.ExecuteCustomBuildSteps(PreBuildScripts);
                    bHasRunPreBuildScripts = true;
                }

                // Build the target
                using (Timeline.ScopeEvent("UEBuildTarget.Build()"))
                {
                    const bool bIsAssemblingBuild = true;
                    Makefile = Target.Build(BuildConfiguration, WorkingSet, bIsAssemblingBuild, TargetDescriptor.SpecificFilesToCompile);
                }

                // Save the pre-build scripts onto the makefile
                Makefile.PreBuildScripts = PreBuildScripts;

                // Save the additional command line arguments
                Makefile.AdditionalArguments = TargetDescriptor.AdditionalArguments.GetRawArray();

                // Save the environment variables
                foreach (System.Collections.DictionaryEntry EnvironmentVariable in Environment.GetEnvironmentVariables())
                {
                    Makefile.EnvironmentVariables.Add(Tuple.Create((string)EnvironmentVariable.Key, (string)EnvironmentVariable.Value));
                }

                // Save the makefile for next time
                if (MakefileLocation != null)
                {
                    using (Timeline.ScopeEvent("TargetMakefile.Save()"))
                    {
                        Makefile.Save(MakefileLocation);
                    }
                }
            }
            else
            {
                // Restore the environment variables
                foreach (Tuple <string, string> EnvironmentVariable in Makefile.EnvironmentVariables)
                {
                    Environment.SetEnvironmentVariable(EnvironmentVariable.Item1, EnvironmentVariable.Item2);
                }

                // If the target needs UHT to be run, we'll go ahead and do that now
                if (Makefile.UObjectModules.Count > 0)
                {
                    const bool bIsGatheringBuild  = false;
                    const bool bIsAssemblingBuild = true;

                    FileReference ModuleInfoFileName = FileReference.Combine(Makefile.ProjectIntermediateDirectory, TargetDescriptor.Name + ".uhtmanifest");
                    ExternalExecution.ExecuteHeaderToolIfNecessary(BuildConfiguration, TargetDescriptor.ProjectFile, TargetDescriptor.Name, Makefile.TargetType, Makefile.bHasProjectScriptPlugin, UObjectModules: Makefile.UObjectModules, ModuleInfoFileName: ModuleInfoFileName, bIsGatheringBuild: bIsGatheringBuild, bIsAssemblingBuild: bIsAssemblingBuild, WorkingSet: WorkingSet);
                }
            }
            return(Makefile);
        }
示例#3
0
        /// <summary>
        /// Build a list of targets with a given set of makefiles.
        /// </summary>
        /// <param name="Makefiles">Makefiles created with CreateMakefiles</param>
        /// <param name="TargetDescriptors">Target descriptors</param>
        /// <param name="BuildConfiguration">Current build configuration</param>
        /// <param name="WorkingSet">The source file working set</param>
        /// <param name="Options">Additional options for the build</param>
        /// <param name="WriteOutdatedActionsFile">Files to write the list of outdated actions to (rather than building them)</param>
        /// <returns>Result from the compilation</returns>
        static void Build(TargetMakefile[] Makefiles, List <TargetDescriptor> TargetDescriptors, BuildConfiguration BuildConfiguration, ISourceFileWorkingSet WorkingSet, BuildOptions Options, FileReference WriteOutdatedActionsFile)
        {
            // Export the actions for each target
            for (int TargetIdx = 0; TargetIdx < TargetDescriptors.Count; TargetIdx++)
            {
                TargetDescriptor TargetDescriptor = TargetDescriptors[TargetIdx];
                foreach (FileReference WriteActionFile in TargetDescriptor.WriteActionFiles)
                {
                    Log.TraceInformation("Writing actions to {0}", WriteActionFile);
                    ActionGraph.ExportJson(Makefiles[TargetIdx].Actions, WriteActionFile);
                }
            }

            // Execute the build
            if ((Options & BuildOptions.SkipBuild) == 0)
            {
                // Make sure that none of the actions conflict with any other (producing output files differently, etc...)
                ActionGraph.CheckForConflicts(Makefiles.SelectMany(x => x.Actions));

                // Check we don't exceed the nominal max path length
                using (Timeline.ScopeEvent("ActionGraph.CheckPathLengths"))
                {
                    ActionGraph.CheckPathLengths(BuildConfiguration, Makefiles.SelectMany(x => x.Actions));
                }

                // Clean up any previous hot reload runs, and reapply the current state if it's already active
                for (int TargetIdx = 0; TargetIdx < TargetDescriptors.Count; TargetIdx++)
                {
                    HotReload.Setup(TargetDescriptors[TargetIdx], Makefiles[TargetIdx], BuildConfiguration);
                }

                // Merge the action graphs together
                List <Action> MergedActions;
                if (TargetDescriptors.Count == 1)
                {
                    MergedActions = new List <Action>(Makefiles[0].Actions);
                }
                else
                {
                    MergedActions = MergeActionGraphs(TargetDescriptors, Makefiles);
                }

                // Gather all the prerequisite actions that are part of the targets
                HashSet <FileItem> MergedOutputItems = new HashSet <FileItem>();
                for (int TargetIdx = 0; TargetIdx < TargetDescriptors.Count; TargetIdx++)
                {
                    GatherOutputItems(TargetDescriptors[TargetIdx], Makefiles[TargetIdx], MergedOutputItems);
                }

                // Link all the actions together
                ActionGraph.Link(MergedActions);

                // Get all the actions that are prerequisites for these targets. This forms the list of actions that we want executed.
                List <Action> PrerequisiteActions = ActionGraph.GatherPrerequisiteActions(MergedActions, MergedOutputItems);

                // Create the action history
                ActionHistory History = new ActionHistory();
                for (int TargetIdx = 0; TargetIdx < TargetDescriptors.Count; TargetIdx++)
                {
                    using (Timeline.ScopeEvent("Reading action history"))
                    {
                        TargetDescriptor TargetDescriptor = TargetDescriptors[TargetIdx];
                        if (TargetDescriptor.ProjectFile != null)
                        {
                            History.Mount(TargetDescriptor.ProjectFile.Directory);
                        }
                    }
                }

                // Figure out which actions need to be built
                Dictionary <Action, bool> ActionToOutdatedFlag = new Dictionary <Action, bool>();
                for (int TargetIdx = 0; TargetIdx < TargetDescriptors.Count; TargetIdx++)
                {
                    TargetDescriptor TargetDescriptor = TargetDescriptors[TargetIdx];

                    // Create the dependencies cache
                    CppDependencyCache CppDependencies;
                    using (Timeline.ScopeEvent("Reading dependency cache"))
                    {
                        CppDependencies = CppDependencyCache.CreateHierarchy(TargetDescriptor.ProjectFile, TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration, Makefiles[TargetIdx].TargetType, TargetDescriptor.Architecture);
                    }

                    // Plan the actions to execute for the build. For single file compiles, always rebuild the source file regardless of whether it's out of date.
                    if (TargetDescriptor.SpecificFilesToCompile.Count == 0)
                    {
                        ActionGraph.GatherAllOutdatedActions(PrerequisiteActions, History, ActionToOutdatedFlag, CppDependencies, BuildConfiguration.bIgnoreOutdatedImportLibraries);
                    }
                    else
                    {
                        foreach (FileReference SpecificFile in TargetDescriptor.SpecificFilesToCompile)
                        {
                            foreach (Action PrerequisiteAction in PrerequisiteActions.Where(x => x.PrerequisiteItems.Any(y => y.Location == SpecificFile)))
                            {
                                ActionToOutdatedFlag[PrerequisiteAction] = true;
                            }
                        }
                    }
                }

                // Link the action graph again to sort it
                List <Action> MergedActionsToExecute = ActionToOutdatedFlag.Where(x => x.Value).Select(x => x.Key).ToList();
                ActionGraph.Link(MergedActionsToExecute);

                // Allow hot reload to override the actions
                int HotReloadTargetIdx = -1;
                for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++)
                {
                    if (TargetDescriptors[Idx].HotReloadMode != HotReloadMode.Disabled)
                    {
                        if (HotReloadTargetIdx != -1)
                        {
                            throw new BuildException("Unable to perform hot reload with multiple targets.");
                        }
                        else
                        {
                            MergedActionsToExecute = HotReload.PatchActionsForTarget(BuildConfiguration, TargetDescriptors[Idx], Makefiles[Idx], PrerequisiteActions, MergedActionsToExecute);
                        }
                        HotReloadTargetIdx = Idx;
                    }
                }

                // Make sure we're not modifying any engine files
                if ((Options & BuildOptions.NoEngineChanges) != 0)
                {
                    List <FileItem> EngineChanges = MergedActionsToExecute.SelectMany(x => x.ProducedItems).Where(x => x.Location.IsUnderDirectory(UnrealBuildTool.EngineDirectory)).Distinct().OrderBy(x => x.FullName).ToList();
                    if (EngineChanges.Count > 0)
                    {
                        StringBuilder Result = new StringBuilder("Building would modify the following engine files:\n");
                        foreach (FileItem EngineChange in EngineChanges)
                        {
                            Result.AppendFormat("\n{0}", EngineChange.FullName);
                        }
                        Result.Append("\n\nPlease rebuild from an IDE instead.");
                        Log.TraceError("{0}", Result.ToString());
                        throw new CompilationResultException(CompilationResult.FailedDueToEngineChange);
                    }
                }

                // Make sure the appropriate executor is selected
                foreach (TargetDescriptor TargetDescriptor in TargetDescriptors)
                {
                    UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(TargetDescriptor.Platform);
                    BuildConfiguration.bAllowXGE    &= BuildPlatform.CanUseXGE();
                    BuildConfiguration.bAllowDistcc &= BuildPlatform.CanUseDistcc();
                    BuildConfiguration.bAllowSNDBS  &= BuildPlatform.CanUseSNDBS();
                }

                // Delete produced items that are outdated.
                ActionGraph.DeleteOutdatedProducedItems(MergedActionsToExecute);

                // Save all the action histories now that files have been removed. We have to do this after deleting produced items to ensure that any
                // items created during the build don't have the wrong command line.
                History.Save();

                // Create directories for the outdated produced items.
                ActionGraph.CreateDirectoriesForProducedItems(MergedActionsToExecute);

                // Execute the actions
                if ((Options & BuildOptions.XGEExport) != 0)
                {
                    OutputToolchainInfo(TargetDescriptors, Makefiles);

                    // Just export to an XML file
                    using (Timeline.ScopeEvent("XGE.ExportActions()"))
                    {
                        XGE.ExportActions(MergedActionsToExecute);
                    }
                }
                else if (WriteOutdatedActionsFile != null)
                {
                    OutputToolchainInfo(TargetDescriptors, Makefiles);

                    // Write actions to an output file
                    using (Timeline.ScopeEvent("ActionGraph.WriteActions"))
                    {
                        ActionGraph.ExportJson(MergedActionsToExecute, WriteOutdatedActionsFile);
                    }
                }
                else
                {
                    // Execute the actions
                    if (MergedActionsToExecute.Count == 0)
                    {
                        if (TargetDescriptors.Any(x => !x.bQuiet))
                        {
                            Log.TraceInformation((TargetDescriptors.Count == 1)? "Target is up to date" : "Targets are up to date");
                        }
                    }
                    else
                    {
                        if (TargetDescriptors.Any(x => !x.bQuiet))
                        {
                            Log.TraceInformation("Building {0}...", StringUtils.FormatList(TargetDescriptors.Select(x => x.Name).Distinct()));
                        }

                        OutputToolchainInfo(TargetDescriptors, Makefiles);

                        using (Timeline.ScopeEvent("ActionGraph.ExecuteActions()"))
                        {
                            ActionGraph.ExecuteActions(BuildConfiguration, MergedActionsToExecute);
                        }
                    }

                    // Run the deployment steps
                    foreach (TargetMakefile Makefile in Makefiles)
                    {
                        if (Makefile.bDeployAfterCompile)
                        {
                            TargetReceipt Receipt = TargetReceipt.Read(Makefile.ReceiptFile);
                            Log.TraceInformation("Deploying {0} {1} {2}...", Receipt.TargetName, Receipt.Platform, Receipt.Configuration);

                            UEBuildPlatform.GetBuildPlatform(Receipt.Platform).Deploy(Receipt);
                        }
                    }
                }
            }
        }
示例#4
0
        /// <summary>
        /// Checks if the editor is currently running and this is a hot-reload
        /// </summary>
        public static bool ShouldDoHotReloadFromIDE(BuildConfiguration BuildConfiguration, TargetDescriptor TargetDesc)
        {
            // Check if Hot-reload is disabled globally for this project
            ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(TargetDesc.ProjectFile), TargetDesc.Platform);
            bool            bAllowHotReloadFromIDE;

            if (Hierarchy.TryGetValue("BuildConfiguration", "bAllowHotReloadFromIDE", out bAllowHotReloadFromIDE) && !bAllowHotReloadFromIDE)
            {
                return(false);
            }

            if (!BuildConfiguration.bAllowHotReloadFromIDE)
            {
                return(false);
            }

            // Check if we're using LiveCode instead
            ConfigHierarchy EditorPerProjectHierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(TargetDesc.ProjectFile), TargetDesc.Platform);
            bool            bEnableLiveCode;

            if (EditorPerProjectHierarchy.GetBool("/Script/LiveCoding.LiveCodingSettings", "bEnabled", out bEnableLiveCode) && bEnableLiveCode)
            {
                return(false);
            }

            bool bIsRunning = false;

            // @todo ubtmake: Kind of cheating here to figure out if an editor target.  At this point we don't have access to the actual target description, and
            // this code must be able to execute before we create or load module rules DLLs so that hot reload can work with bUseUBTMakefiles
            if (TargetDesc.Name.EndsWith("Editor", StringComparison.OrdinalIgnoreCase))
            {
                string EditorBaseFileName = "UE4Editor";
                if (TargetDesc.Configuration != UnrealTargetConfiguration.Development)
                {
                    EditorBaseFileName = String.Format("{0}-{1}-{2}", EditorBaseFileName, TargetDesc.Platform, TargetDesc.Configuration);
                }

                FileReference EditorLocation;
                if (TargetDesc.Platform == UnrealTargetPlatform.Win64)
                {
                    EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Win64", String.Format("{0}.exe", EditorBaseFileName));
                }
                else if (TargetDesc.Platform == UnrealTargetPlatform.Mac)
                {
                    EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Mac", String.Format("{0}.app/Contents/MacOS/{0}", EditorBaseFileName));
                }
                else if (TargetDesc.Platform == UnrealTargetPlatform.Linux)
                {
                    EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Linux", EditorBaseFileName);
                }
                else
                {
                    throw new BuildException("Unknown editor filename for this platform");
                }

                using (Timeline.ScopeEvent("Finding editor processes for hot-reload"))
                {
                    DirectoryReference EditorRunsDir = DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "EditorRuns");
                    if (!DirectoryReference.Exists(EditorRunsDir))
                    {
                        return(false);
                    }

                    if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64)
                    {
                        foreach (FileReference EditorInstanceFile in DirectoryReference.EnumerateFiles(EditorRunsDir))
                        {
                            int ProcessId;
                            if (!Int32.TryParse(EditorInstanceFile.GetFileName(), out ProcessId))
                            {
                                FileReference.Delete(EditorInstanceFile);
                                continue;
                            }

                            Process RunningProcess;
                            try
                            {
                                RunningProcess = Process.GetProcessById(ProcessId);
                            }
                            catch
                            {
                                RunningProcess = null;
                            }

                            if (RunningProcess == null)
                            {
                                FileReference.Delete(EditorInstanceFile);
                                continue;
                            }

                            FileReference MainModuleFile;
                            try
                            {
                                MainModuleFile = new FileReference(RunningProcess.MainModule.FileName);
                            }
                            catch
                            {
                                MainModuleFile = null;
                            }

                            if (!bIsRunning && EditorLocation == MainModuleFile)
                            {
                                bIsRunning = true;
                            }
                        }
                    }
                    else
                    {
                        FileInfo[] EditorRunsFiles = new DirectoryInfo(EditorRunsDir.FullName).GetFiles();
                        BuildHostPlatform.ProcessInfo[] Processes = BuildHostPlatform.Current.GetProcesses();

                        foreach (FileInfo File in EditorRunsFiles)
                        {
                            int PID;
                            BuildHostPlatform.ProcessInfo Proc = null;
                            if (!Int32.TryParse(File.Name, out PID) || (Proc = Processes.FirstOrDefault(P => P.PID == PID)) == default(BuildHostPlatform.ProcessInfo))
                            {
                                // Delete stale files (it may happen if editor crashes).
                                File.Delete();
                                continue;
                            }

                            // Don't break here to allow clean-up of other stale files.
                            if (!bIsRunning)
                            {
                                // Otherwise check if the path matches.
                                bIsRunning = new FileReference(Proc.Filename) == EditorLocation;
                            }
                        }
                    }
                }
            }
            return(bIsRunning);
        }
示例#5
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);
                    FileReference ClangPath   = FileReference.Combine(Environment.CompilerDir, "bin", "clang++.exe");

                    // 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);
        }
示例#6
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, Target.Architecture));

                // 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);
        }