Esempio n. 1
0
        /// <summary>
        /// Adds a build product and its associated debug file to a receipt.
        /// </summary>
        /// <param name="OutputFile">Build product to add</param>
        /// <param name="DebugExtension">Extension for the matching debug file (may be null).</param>
        /// <param name="Receipt">Receipt to add to</param>
        static void AddBuildProductAndDebugFile(FileReference OutputFile, BuildProductType OutputType, string DebugExtension, Dictionary <FileReference, BuildProductType> BuildProducts, UEToolChain ToolChain)
        {
            BuildProducts.Add(OutputFile, OutputType);

            if (!String.IsNullOrEmpty(DebugExtension) && ToolChain.ShouldAddDebugFileToReceipt(OutputFile, OutputType))
            {
                BuildProducts.Add(OutputFile.ChangeExtension(DebugExtension), BuildProductType.SymbolFile);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Adds a build product and its associated debug file to a receipt.
        /// </summary>
        /// <param name="OutputFile">Build product to add</param>
        /// <param name="OutputType">The type of built product</param>
        /// <param name="DebugExtensions">Extensions for the matching debug file (may be null).</param>
        /// <param name="BuildProducts">Map of build products to their type</param>
        /// <param name="ToolChain">The toolchain used to build these binaries</param>
        /// <param name="bCreateDebugInfo">Whether creating debug info is enabled</param>
        static void AddBuildProductAndDebugFiles(FileReference OutputFile, BuildProductType OutputType, string[] DebugExtensions, Dictionary <FileReference, BuildProductType> BuildProducts, UEToolChain ToolChain, bool bCreateDebugInfo)
        {
            BuildProducts.Add(OutputFile, OutputType);

            foreach (string DebugExtension in DebugExtensions)
            {
                if (!String.IsNullOrEmpty(DebugExtension) && ToolChain.ShouldAddDebugFileToReceipt(OutputFile, OutputType) && bCreateDebugInfo)
                {
                    BuildProducts.Add(OutputFile.ChangeExtension(DebugExtension), BuildProductType.SymbolFile);
                }
            }
        }
        public PVSToolChain(ReadOnlyTargetRules Target)
        {
            this.Target    = Target;
            Platform       = Target.Platform;
            InnerToolChain = new VCToolChain(Target);

            AnalyzerFile = FileReference.Combine(new DirectoryReference(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)), "PVS-Studio", "x64", "PVS-Studio.exe");
            if (!FileReference.Exists(AnalyzerFile))
            {
                FileReference EngineAnalyzerFile = FileReference.Combine(UnrealBuildTool.RootDirectory, "Engine", "Extras", "ThirdPartyNotUE", "NoRedist", "PVS-Studio", "PVS-Studio.exe");
                if (FileReference.Exists(EngineAnalyzerFile))
                {
                    AnalyzerFile = EngineAnalyzerFile;
                }
                else
                {
                    throw new BuildException("Unable to find PVS-Studio at {0} or {1}", AnalyzerFile, EngineAnalyzerFile);
                }
            }

            FileReference SettingsPath = FileReference.Combine(new DirectoryReference(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)), "PVS-Studio", "Settings.xml");

            if (FileReference.Exists(SettingsPath))
            {
                try
                {
                    XmlSerializer Serializer = new XmlSerializer(typeof(PVSApplicationSettings));
                    using (FileStream Stream = new FileStream(SettingsPath.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        ApplicationSettings = (PVSApplicationSettings)Serializer.Deserialize(Stream);
                    }
                }
                catch (Exception Ex)
                {
                    throw new BuildException(Ex, "Unable to read PVS-Studio settings file from {0}", SettingsPath);
                }
            }

            if (ApplicationSettings != null && !String.IsNullOrEmpty(ApplicationSettings.UserName) && !String.IsNullOrEmpty(ApplicationSettings.SerialNumber))
            {
                LicenseFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "PVS", "PVS-Studio.lic");
                FileItem.CreateIntermediateTextFile(LicenseFile, new string[] { ApplicationSettings.UserName, ApplicationSettings.SerialNumber });
            }
            else
            {
                FileReference DefaultLicenseFile = AnalyzerFile.ChangeExtension(".lic");
                if (FileReference.Exists(DefaultLicenseFile))
                {
                    LicenseFile = DefaultLicenseFile;
                }
            }
        }
Esempio n. 4
0
 void ParseTimingDataToTracingFiles(FileReference InputFile)
 {
     string[] Lines = FileReference.ReadAllLines(InputFile);
     for (int LineIdx = 0; LineIdx < Lines.Length;)
     {
         string Line = Lines[LineIdx];
         if (Line.StartsWith("Include Headers:", StringComparison.Ordinal))
         {
             LineIdx = ParseIncludeHeadersToTraces(Lines, LineIdx + 1, InputFile.ChangeExtension(".json"));
         }
         else if (Line.StartsWith("Class Definitions:", StringComparison.Ordinal))
         {
             LineIdx = ParseDefinitions(Lines, LineIdx + 1, InputFile.ChangeExtension(".classes.txt"));
         }
         else if (Line.StartsWith("Function Definitions:", StringComparison.Ordinal))
         {
             LineIdx = ParseDefinitions(Lines, LineIdx + 1, InputFile.ChangeExtension(".functions.txt"));
         }
         else
         {
             LineIdx++;
         }
     }
 }
Esempio n. 5
0
        public PVSToolChain(ReadOnlyTargetRules Target)
        {
            this.Target    = Target;
            Platform       = Target.Platform;
            InnerToolChain = new VCToolChain(Target);

            AnalyzerFile = FileReference.Combine(new DirectoryReference(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)), "PVS-Studio", "x64", "PVS-Studio.exe");
            if (!FileReference.Exists(AnalyzerFile))
            {
                FileReference EngineAnalyzerFile = FileReference.Combine(UnrealBuildTool.RootDirectory, "Engine", "Extras", "ThirdPartyNotUE", "NoRedist", "PVS-Studio", "PVS-Studio.exe");
                if (FileReference.Exists(EngineAnalyzerFile))
                {
                    AnalyzerFile = EngineAnalyzerFile;
                }
                else
                {
                    throw new BuildException("Unable to find PVS-Studio at {0} or {1}", AnalyzerFile, EngineAnalyzerFile);
                }
            }

            Settings            = Target.WindowsPlatform.PVS;
            ApplicationSettings = Settings.ApplicationSettings;

            if (ApplicationSettings != null)
            {
                if (Settings.ModeFlags == 0)
                {
                    throw new BuildException("All PVS-Studio analysis modes are disabled.");
                }

                if (!String.IsNullOrEmpty(ApplicationSettings.UserName) && !String.IsNullOrEmpty(ApplicationSettings.SerialNumber))
                {
                    LicenseFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "PVS", "PVS-Studio.lic");
                    Utils.WriteFileIfChanged(LicenseFile, String.Format("{0}\n{1}\n", ApplicationSettings.UserName, ApplicationSettings.SerialNumber), StringComparison.Ordinal);
                }
            }
            else
            {
                FileReference DefaultLicenseFile = AnalyzerFile.ChangeExtension(".lic");
                if (FileReference.Exists(DefaultLicenseFile))
                {
                    LicenseFile = DefaultLicenseFile;
                }
            }
        }
Esempio n. 6
0
        public override FileItem LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly)
        {
            var EnvVars = VCEnvironment.SetEnvironment(LinkEnvironment.Config.Target.Platform, false);

            if (LinkEnvironment.Config.bIsBuildingDotNetAssembly)
            {
                return(FileItem.GetItemByFileReference(LinkEnvironment.Config.OutputFilePath));
            }

            bool bIsBuildingLibrary = LinkEnvironment.Config.bIsBuildingLibrary || bBuildImportLibraryOnly;
            bool bIncludeDependentLibrariesInLibrary = bIsBuildingLibrary && LinkEnvironment.Config.bIncludeDependentLibrariesInLibrary;

            // Get link arguments.
            StringBuilder Arguments = new StringBuilder();

            if (bIsBuildingLibrary)
            {
                AppendLibArguments(LinkEnvironment, Arguments);
            }
            else
            {
                AppendLinkArguments(LinkEnvironment, Arguments);
            }



            // If we're only building an import library, add the '/DEF' option that tells the LIB utility
            // to simply create a .LIB file and .EXP file, and don't bother validating imports
            if (bBuildImportLibraryOnly)
            {
                Arguments.Append(" /DEF");

                // Ensure that the import library references the correct filename for the linked binary.
                Arguments.AppendFormat(" /NAME:\"{0}\"", LinkEnvironment.Config.OutputFilePath.GetFileName());
            }


            // Add delay loaded DLLs.
            if (!bIsBuildingLibrary)
            {
                // Delay-load these DLLs.
                foreach (string DelayLoadDLL in LinkEnvironment.Config.DelayLoadDLLs)
                {
                    Arguments.AppendFormat(" /DELAYLOAD:\"{0}\"", DelayLoadDLL);
                }
            }

            // @todo UE4 DLL: Why do I need LIBPATHs to build only export libraries with /DEF? (tbbmalloc.lib)
            if (!LinkEnvironment.Config.bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary))
            {
                // Add the library paths to the argument list.
                foreach (string LibraryPath in LinkEnvironment.Config.LibraryPaths)
                {
                    Arguments.AppendFormat(" /LIBPATH:\"{0}\"", LibraryPath);
                }

                // Add the excluded default libraries to the argument list.
                foreach (string ExcludedLibrary in LinkEnvironment.Config.ExcludedLibraries)
                {
                    Arguments.AppendFormat(" /NODEFAULTLIB:\"{0}\"", ExcludedLibrary);
                }
            }

            // For targets that are cross-referenced, we don't want to write a LIB file during the link step as that
            // file will clobber the import library we went out of our way to generate during an earlier step.  This
            // file is not needed for our builds, but there is no way to prevent MSVC from generating it when
            // linking targets that have exports.  We don't want this to clobber our LIB file and invalidate the
            // existing timstamp, so instead we simply emit it with a different name
            FileReference ImportLibraryFilePath = FileReference.Combine(LinkEnvironment.Config.IntermediateDirectory,
                                                                        LinkEnvironment.Config.OutputFilePath.GetFileNameWithoutExtension() + ".lib");

            if (LinkEnvironment.Config.bIsCrossReferenced && !bBuildImportLibraryOnly)
            {
                ImportLibraryFilePath += ".suppressed";
            }

            FileItem OutputFile;

            if (bBuildImportLibraryOnly)
            {
                OutputFile = FileItem.GetItemByFileReference(ImportLibraryFilePath);
            }
            else
            {
                OutputFile = FileItem.GetItemByFileReference(LinkEnvironment.Config.OutputFilePath);
                OutputFile.bNeedsHotReloadNumbersDLLCleanUp = LinkEnvironment.Config.bIsBuildingDLL;
            }

            List <FileItem> ProducedItems = new List <FileItem>();

            ProducedItems.Add(OutputFile);

            List <FileItem> PrerequisiteItems = new List <FileItem>();

            // Add the input files to a response file, and pass the response file on the command-line.
            List <string> InputFileNames = new List <string>();

            foreach (FileItem InputFile in LinkEnvironment.InputFiles)
            {
                InputFileNames.Add(string.Format("\"{0}\"", InputFile.AbsolutePath));
                PrerequisiteItems.Add(InputFile);
            }

            if (!bBuildImportLibraryOnly)
            {
                // Add input libraries as prerequisites, too!
                foreach (FileItem InputLibrary in LinkEnvironment.InputLibraries)
                {
                    InputFileNames.Add(string.Format("\"{0}\"", InputLibrary.AbsolutePath));
                    PrerequisiteItems.Add(InputLibrary);
                }
            }

            if (!bIsBuildingLibrary || (LinkEnvironment.Config.bIsBuildingLibrary && bIncludeDependentLibrariesInLibrary))
            {
                foreach (string AdditionalLibrary in LinkEnvironment.Config.AdditionalLibraries)
                {
                    InputFileNames.Add(string.Format("\"{0}\"", AdditionalLibrary));

                    // If the library file name has a relative path attached (rather than relying on additional
                    // lib directories), then we'll add it to our prerequisites list.  This will allow UBT to detect
                    // when the binary needs to be relinked because a dependent external library has changed.
                    //if( !String.IsNullOrEmpty( Path.GetDirectoryName( AdditionalLibrary ) ) )
                    {
                        PrerequisiteItems.Add(FileItem.GetItemByPath(AdditionalLibrary));
                    }
                }
            }

            // Create a response file for the linker
            FileReference ResponseFileName = GetResponseFileName(LinkEnvironment, OutputFile);

            // Never create response files when we are only generating IntelliSense data
            if (!ProjectFileGenerator.bGenerateProjectFiles)
            {
                ResponseFile.Create(ResponseFileName, InputFileNames);
            }
            Arguments.AppendFormat(" @\"{0}\"", ResponseFileName);

            // Add the output file to the command-line.
            Arguments.AppendFormat(" /OUT:\"{0}\"", OutputFile.AbsolutePath);

            if (bBuildImportLibraryOnly || (LinkEnvironment.Config.bHasExports && !bIsBuildingLibrary))
            {
                // An export file is written to the output directory implicitly; add it to the produced items list.
                FileReference ExportFilePath = ImportLibraryFilePath.ChangeExtension(".exp");
                FileItem      ExportFile     = FileItem.GetItemByFileReference(ExportFilePath);
                ProducedItems.Add(ExportFile);
            }

            if (!bIsBuildingLibrary)
            {
                // Xbox 360 LTCG does not seem to produce those.
                if (LinkEnvironment.Config.bHasExports &&
                    (LinkEnvironment.Config.Target.Configuration != CPPTargetConfiguration.Shipping))
                {
                    // Write the import library to the output directory for nFringe support.
                    FileItem ImportLibraryFile = FileItem.GetItemByFileReference(ImportLibraryFilePath);
                    Arguments.AppendFormat(" /IMPLIB:\"{0}\"", ImportLibraryFilePath);
                    ProducedItems.Add(ImportLibraryFile);
                }

                if (LinkEnvironment.Config.bCreateDebugInfo)
                {
                    // Write the PDB file to the output directory.
                    FileReference PDBFilePath = FileReference.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + ".pdb");
                    FileItem      PDBFile     = FileItem.GetItemByFileReference(PDBFilePath);
                    Arguments.AppendFormat(" /PDB:\"{0}\"", PDBFilePath);
                    ProducedItems.Add(PDBFile);

                    // Write the MAP file to the output directory.
#if false
                    if (true)
                    {
                        string   MAPFilePath = Path.Combine(LinkEnvironment.Config.OutputDirectory, Path.GetFileNameWithoutExtension(OutputFile.AbsolutePath) + ".map");
                        FileItem MAPFile     = FileItem.GetItemByFileReference(MAPFilePath);
                        LinkAction.CommandArguments += string.Format(" /MAP:\"{0}\"", MAPFilePath);
                        LinkAction.ProducedItems.Add(MAPFile);
                    }
#endif
                }

                // Add the additional arguments specified by the environment.
                Arguments.Append(LinkEnvironment.Config.AdditionalArguments);
            }

            // Create an action that invokes the linker.
            Action LinkAction = new Action(ActionType.Link);
            LinkAction.CommandDescription = "Link";
            LinkAction.WorkingDirectory   = UnrealBuildTool.EngineSourceDirectory.FullName;
            LinkAction.CommandPath        = bIsBuildingLibrary ? EnvVars.LibraryLinkerPath : EnvVars.LinkerPath;
            LinkAction.CommandArguments   = Arguments.ToString();
            LinkAction.ProducedItems.AddRange(ProducedItems);
            LinkAction.PrerequisiteItems.AddRange(PrerequisiteItems);
            LinkAction.StatusDescription = Path.GetFileName(OutputFile.AbsolutePath);

            // Tell the action that we're building an import library here and it should conditionally be
            // ignored as a prerequisite for other actions
            LinkAction.bProducesImportLibrary = bBuildImportLibraryOnly || LinkEnvironment.Config.bIsBuildingDLL;

            // Only execute linking on the local PC.
            LinkAction.bCanExecuteRemotely = false;

            Log.TraceVerbose("     Linking: " + LinkAction.StatusDescription);
            Log.TraceVerbose("     Command: " + LinkAction.CommandArguments);

            return(OutputFile);
        }
        /// <summary>
        /// Patches a set of actions for use with live coding. The new action list will output object files to a different location.
        /// </summary>
        /// <param name="Actions">Set of actions</param>
        /// <param name="OriginalFileToPatchedFile">Dictionary that receives a map of original object file to patched object file</param>
        public static void PatchActionGraphForLiveCoding(IEnumerable <Action> Actions, Dictionary <FileReference, FileReference> OriginalFileToPatchedFile)
        {
            foreach (Action Action in Actions)
            {
                if (Action.ActionType == ActionType.Compile)
                {
                    if (!Action.CommandPath.GetFileName().Equals("cl-filter.exe", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new BuildException("Unable to patch action graph - unexpected executable in compile action ({0})", Action.CommandPath);
                    }

                    List <string> Arguments = Utils.ParseArgumentList(Action.CommandArguments);

                    // Find the index of the cl-filter argument delimiter
                    int DelimiterIdx = Arguments.IndexOf("--");
                    if (DelimiterIdx == -1)
                    {
                        throw new BuildException("Unable to patch action graph - missing '--' delimiter to cl-filter");
                    }

                    // Fix the dependencies path
                    const string DependenciesPrefix = "-dependencies=";

                    int DependenciesIdx = 0;
                    for (;; DependenciesIdx++)
                    {
                        if (DependenciesIdx == DelimiterIdx)
                        {
                            throw new BuildException("Unable to patch action graph - missing '{0}' argument to cl-filter", DependenciesPrefix);
                        }
                        else if (Arguments[DependenciesIdx].StartsWith(DependenciesPrefix, StringComparison.OrdinalIgnoreCase))
                        {
                            break;
                        }
                    }

                    FileReference OldDependenciesFile     = new FileReference(Arguments[DependenciesIdx].Substring(DependenciesPrefix.Length));
                    FileItem      OldDependenciesFileItem = Action.ProducedItems.First(x => x.Location == OldDependenciesFile);
                    Action.ProducedItems.Remove(OldDependenciesFileItem);

                    FileReference NewDependenciesFile     = OldDependenciesFile.ChangeExtension(".lc.response");
                    FileItem      NewDependenciesFileItem = FileItem.GetItemByFileReference(NewDependenciesFile);
                    Action.ProducedItems.Add(NewDependenciesFileItem);

                    Arguments[DependenciesIdx] = DependenciesPrefix + NewDependenciesFile.FullName;

                    // Fix the response file
                    int ResponseFileIdx = DelimiterIdx + 1;
                    for (; ; ResponseFileIdx++)
                    {
                        if (ResponseFileIdx == Arguments.Count)
                        {
                            throw new BuildException("Unable to patch action graph - missing response file argument to cl-filter");
                        }
                        else if (Arguments[ResponseFileIdx].StartsWith("@", StringComparison.Ordinal))
                        {
                            break;
                        }
                    }

                    FileReference OldResponseFile = new FileReference(Arguments[ResponseFileIdx].Substring(1));
                    FileReference NewResponseFile = new FileReference(OldResponseFile.FullName + ".lc");

                    const string OutputFilePrefix = "/Fo";

                    string[] ResponseLines = FileReference.ReadAllLines(OldResponseFile);
                    for (int Idx = 0; Idx < ResponseLines.Length; Idx++)
                    {
                        string ResponseLine = ResponseLines[Idx];
                        if (ResponseLine.StartsWith(OutputFilePrefix, StringComparison.Ordinal))
                        {
                            FileReference OldOutputFile     = new FileReference(ResponseLine.Substring(3).Trim('\"'));
                            FileItem      OldOutputFileItem = Action.ProducedItems.First(x => x.Location == OldOutputFile);
                            Action.ProducedItems.Remove(OldOutputFileItem);

                            FileReference NewOutputFile     = OldOutputFile.ChangeExtension(".lc.obj");
                            FileItem      NewOutputFileItem = FileItem.GetItemByFileReference(NewOutputFile);
                            Action.ProducedItems.Add(NewOutputFileItem);

                            OriginalFileToPatchedFile[OldOutputFile] = NewOutputFile;

                            ResponseLines[Idx] = OutputFilePrefix + "\"" + NewOutputFile.FullName + "\"";
                            break;
                        }
                    }
                    FileReference.WriteAllLines(NewResponseFile, ResponseLines);

                    Arguments[ResponseFileIdx] = "@" + NewResponseFile.FullName;

                    // Update the final arguments
                    Action.CommandArguments = Utils.FormatCommandLine(Arguments);
                }
            }
        }
Esempio n. 8
0
 public virtual FileReference GetDebugFile(FileReference OutputFile, string DebugExtension)
 {
     //  by default, just change the extension to the debug extension
     return(OutputFile.ChangeExtension(DebugExtension));
 }
Esempio n. 9
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);
        }
Esempio n. 10
0
        public override int Execute(CommandLineArguments Arguments)
        {
            FileReference InputFile = Arguments.GetFileReference("-TimingFile=");

            // If the tracing argument was passed, hand off to the logic to generate a JSON file compatible with
            // chrome://tracing
            if (Arguments.HasOption("-Tracing"))
            {
                ParseTimingDataToTracingFiles(InputFile);
                return(0);
            }

            // Break the input file into the various sections for processing.
            string[]       AllLines    = FileReference.ReadAllLines(InputFile);
            List <string>  Includes    = new List <string>();
            List <string>  Classes     = new List <string>();
            List <string>  Functions   = new List <string>();
            TimingDataType CurrentType = TimingDataType.None;

            foreach (string Line in AllLines)
            {
                if (string.IsNullOrWhiteSpace(Line))
                {
                    continue;
                }

                // Check for a change of type.
                if (Line.StartsWith("Include Headers:", StringComparison.OrdinalIgnoreCase))
                {
                    CurrentType = TimingDataType.Include;
                    continue;
                }
                else if (Line.StartsWith("Class Definitions:", StringComparison.OrdinalIgnoreCase))
                {
                    CurrentType = TimingDataType.Class;
                    continue;
                }
                else if (Line.StartsWith("Function Definitions:", StringComparison.OrdinalIgnoreCase))
                {
                    CurrentType = TimingDataType.Function;
                    continue;
                }

                // Skip the count line, we don't need it.
                if (Regex.IsMatch(Line, @"^\tCount\:\s*\d*$"))
                {
                    continue;
                }

                // If we didn't change types and this isn't the count line and it doesn't match the expected output,
                //  clear the current type and move on.
                Match TimingDataMatch = Regex.Match(Line, TimingDataRegex);
                if (!TimingDataMatch.Success)
                {
                    CurrentType = TimingDataType.None;
                    continue;
                }

                // If we get to here this is a line we want to parse. Add it to the correct collection.
                switch (CurrentType)
                {
                case TimingDataType.Include:
                {
                    Includes.Add(Line);
                    break;
                }

                case TimingDataType.Class:
                {
                    Classes.Add(Line);
                    break;
                }

                case TimingDataType.Function:
                {
                    Functions.Add(Line);
                    break;
                }
                }
            }

            // Build the summary.
            TimingData Summary = new TimingData()
            {
                Name = InputFile.FullName.Replace(".timing.txt", string.Empty), Type = TimingDataType.Summary
            };

            Summary.AddChild(SummarizeParsedTimingData("IncludeTimings", TimingDataType.Include, Includes));
            Summary.AddChild(SummarizeParsedTimingData("ClassTimings", TimingDataType.Class, Classes));
            Summary.AddChild(SummarizeParsedTimingData("FunctionTimings", TimingDataType.Function, Functions));

            // Write out the timing binary file.
            using (BinaryWriter Writer = new BinaryWriter(File.Open(InputFile.ChangeExtension(".timing.bin").FullName, FileMode.Create)))
            {
                Writer.Write(Summary);
            }

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

            // 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);
        }
Esempio n. 12
0
        /// <summary>
        /// Try to parse the project file from the command line
        /// </summary>
        /// <param name="Arguments">The command line arguments</param>
        /// <param name="ProjectFile">The project file that was parsed</param>
        /// <returns>True if the project file was parsed, false otherwise</returns>
        private static bool TryParseProjectFileArgument(CommandLineArguments Arguments, out FileReference ProjectFile)
        {
            string CandidateProjectPath = null;

            // look for -project=<path>, if it does not exist check arguments for anything that has .uproject in it
            if (!Arguments.TryGetValue("-Project=", out CandidateProjectPath))
            {
                // Go through the argument list and try to match poorly (or well..) formed arguments like
                // EngineTest, EngineTest.uproject
                // Collaboration/FooProject
                // by checking for those in the native project list
                for (int Idx = 0; Idx < Arguments.Count; Idx++)
                {
                    if (Arguments[Idx][0] != '-' && Arguments[Idx].EndsWith(".uproject", StringComparison.OrdinalIgnoreCase))
                    {
                        CandidateProjectPath = Arguments[Idx];
                        Arguments.MarkAsUsed(Idx);
                        break;
                    }
                }
            }

            // We have a project file either via -project= or because there was something called .uproject in the arg list
            // so now validate it
            if (!string.IsNullOrEmpty(CandidateProjectPath))
            {
                FileReference CandidateProjectFile = new FileReference(CandidateProjectPath);

                // if the path doesn't exist then check native paths (ueprojectdirs)
                if (!FileReference.Exists(CandidateProjectFile))
                {
                    // clean everything the user provided to just the name and make sure it has the expected extension
                    string ProjectName = CandidateProjectFile.ChangeExtension("uproject").GetFileName();

                    // check native project paths (uprojectdirs)
                    IEnumerable <FileReference> NativeProjectFiles = NativeProjects.EnumerateProjectFiles();

                    CandidateProjectFile = NativeProjectFiles.Where(F => F.GetFileName().Equals(ProjectName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                }

                if (CandidateProjectFile == null || !FileReference.Exists(CandidateProjectFile))
                {
                    // if we didn't find anything then throw an error as the user explicitly provided a uproject
                    throw new Exception(string.Format("Unable to find project file based on argument {0}", CandidateProjectPath));
                }

                Log.TraceVerbose("Resolved project argument {0} to {1}", CandidateProjectPath, CandidateProjectFile);
                ProjectFile = CandidateProjectFile;
                return(true);
            }

            FileReference InstalledProjectFile = UnrealBuildTool.GetInstalledProjectFile();

            if (InstalledProjectFile != null)
            {
                ProjectFile = InstalledProjectFile;
                return(true);
            }

            ProjectFile = null;
            return(false);
        }