/// <summary>
		/// Creates a file from a list of strings; each string is placed on a line in the file.
		/// </summary>
		/// <param name="TempFileName">Name of response file</param>
		/// <param name="Lines">List of lines to write to the response file</param>
		public static FileReference Create(FileReference TempFileName, List<string> Lines, CreateOptions Options = CreateOptions.None)
		{
			FileInfo TempFileInfo = new FileInfo(TempFileName.FullName);
			if (TempFileInfo.Exists)
			{
				if ((Options & CreateOptions.WriteEvenIfUnchanged) != CreateOptions.WriteEvenIfUnchanged)
				{
					string Body = string.Join(Environment.NewLine, Lines);
					// Reuse the existing response file if it remains unchanged
					string OriginalBody = File.ReadAllText(TempFileName.FullName);
					if (string.Equals(OriginalBody, Body, StringComparison.Ordinal))
					{
						return TempFileName;
					}
				}
				// Delete the existing file if it exists and requires modification
				TempFileInfo.IsReadOnly = false;
				TempFileInfo.Delete();
				TempFileInfo.Refresh();
			}

			FileItem.CreateIntermediateTextFile(TempFileName, string.Join(Environment.NewLine, Lines));

			return TempFileName;
		}
 public ConfigManager(IKernel kernel, IFileSystem fileSystem, FileReference fileReference, ILogger logger)
 {
     _kernel = kernel;
     _fileSystem = fileSystem;
     _fileReferance = fileReference;
     _logger = logger;
 }
		/// <summary>
		/// Execute the task.
		/// </summary>
		/// <param name="Job">Information about the current job</param>
		/// <param name="BuildProducts">Set of build products produced by this node.</param>
		/// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param>
		/// <returns>True if the task succeeded</returns>
		public override bool Execute(JobContext Job, HashSet<FileReference> BuildProducts, Dictionary<string, HashSet<FileReference>> TagNameToFileSet)
		{
			// Get the full path to the project file
			FileReference ProjectFile = null;
			if(!String.IsNullOrEmpty(Parameters.Project))
			{
				ProjectFile = ResolveFile(Parameters.Project);
			}

			// Get the path to the editor, and check it exists
			FileReference EditorExe;
			if(String.IsNullOrEmpty(Parameters.EditorExe))
			{
                EditorExe = new FileReference(HostPlatform.Current.GetUE4ExePath("UE4Editor-Cmd.exe"));
			}
			else
			{
				EditorExe = ResolveFile(Parameters.EditorExe);
			}

			// Make sure the editor exists
			if(!EditorExe.Exists())
			{
				CommandUtils.LogError("{0} does not exist", EditorExe.FullName);
				return false;
			}

			// Run the commandlet
			CommandUtils.RunCommandlet(ProjectFile, EditorExe.FullName, Parameters.Name, Parameters.Arguments);
			return true;
		}
		/// <summary>
		/// Constructs a new project file object
		/// </summary>
		/// <param name="InitFilePath">The path to the project file on disk</param>
		public MSBuildProjectFile(FileReference InitFilePath)
			: base(InitFilePath)
		{
			// Each project gets its own GUID.  This is stored in the project file and referenced in the solution file.

			// First, check to see if we have an existing file on disk.  If we do, then we'll try to preserve the
			// GUID by loading it from the existing file.
			if (ProjectFilePath.Exists())
			{
				try
				{
					LoadGUIDFromExistingProject();
				}
				catch (Exception)
				{
					// Failed to find GUID, so just create a new one
					ProjectGUID = Guid.NewGuid();
				}
			}

			if (ProjectGUID == Guid.Empty)
			{
				// Generate a brand new GUID
				ProjectGUID = Guid.NewGuid();
			}
		}
 public System.IO.Stream OpenFile(FileReference path)
 {
     path = _workingDirectory + fixPath(path);
     if (File.Exists(path))
         return File.Open(path, FileMode.Open);
     else
         return null;
 }
 public void CreateDirectory(FileReference path)
 {
     path = _workingDirectory + fixPath(path);
     if (!Directory.Exists(path))
     {
         Directory.CreateDirectory(path);
     }
 }
 public void DeleteFile(FileReference path)
 {
     path = _workingDirectory + fixPath(path);
     if (File.Exists(path))
     {
         File.Delete(path);
     }
 }
 public void DeleteDirectory(FileReference path)
 {
     path = _workingDirectory + fixPath(path);
     if (Directory.Exists(path))
     {
         Directory.Delete(path, true);
     }
 }
 public IEnumerable<string> ListDirectoriesInDirectory(FileReference path)
 {
     path = _workingDirectory + fixPath(path);
     if (Directory.Exists(path))
         return Directory.GetDirectories(path);
     else
         return null;
 }
		UProjectInfo(FileReference InFilePath, bool bInIsCodeProject)
		{
			GameName = InFilePath.GetFileNameWithoutExtension();
			FileName = InFilePath.GetFileName();
			FilePath = InFilePath;
			Folder = FilePath.Directory;
			bIsCodeProject = bInIsCodeProject;
		}
Beispiel #11
0
		/// <summary>
		/// Constructs a PluginInfo object
		/// </summary>
		/// <param name="InFile"></param>
		/// <param name="InLoadedFrom">Where this pl</param>
		public PluginInfo(FileReference InFile, PluginLoadedFrom InLoadedFrom)
		{
			Name = Path.GetFileNameWithoutExtension(InFile.FullName);
			File = InFile;
			Directory = File.Directory;
			Descriptor = PluginDescriptor.FromFile(File, InLoadedFrom == PluginLoadedFrom.GameProject);
			LoadedFrom = InLoadedFrom;
		}
 public Stream CreateFile(FileReference path)
 {
     path = fixPath(path);
     if (File.Exists(_workingDirectory + path))
     {
         DeleteFile(path);
     }
     CreateDirectory(path.FileLocation.Substring(0, path.FileLocation.Length - Path.GetFileName(path).Length));
     return File.Create(_workingDirectory + path);
 }
Beispiel #13
0
        public void Construtor_throws_ArgumentNullException_if_changes_have_different_paths()
        {
            var file1 = new FileReference("/path1", DateTime.MinValue, 23);
            var file2 = new FileReference("/path2", DateTime.MinValue, 23);

            var change1 = new Change(ChangeType.Added, null, file1);
            var change2 = new Change(ChangeType.Deleted, file2,  null);

            Assert.Throws<ArgumentException>(() => new ChangeList(new [] { change1, change2 }));
        }
		public static void CookCommandlet(string ProjectName)
		{
			FileReference ProjectFile;
			if(ProjectName.Contains('/') || ProjectName.Contains('\\'))
			{
				ProjectFile = new FileReference(ProjectName);
			}
			else if(!UProjectInfo.TryGetProjectFileName(ProjectName, out ProjectFile))
			{
				throw new AutomationException("Cannot determine project path for {0}", ProjectName);
			}
			CookCommandlet(ProjectFile);
		}
		/// <summary>
		/// Builds a UBT Commandline.
		/// </summary>
		/// <param name="Project">Unreal project to build (optional)</param>
		/// <param name="Target">Target to build.</param>
		/// <param name="Platform">Platform to build for.</param>
		/// <param name="Config">Configuration to build.</param>
		/// <param name="AdditionalArgs">Additional arguments to pass on to UBT.</param>
		public static string UBTCommandline(FileReference Project, string Target, string Platform, string Config, string AdditionalArgs = "")
		{
			string CmdLine;
			if (Project == null)
			{
				CmdLine = String.Format("{0} {1} {2} {3}", Target, Platform, Config, AdditionalArgs);
			}
			else
			{
				CmdLine = String.Format("{0} {1} {2} -Project={3} {4}", Target, Platform, Config, CommandUtils.MakePathSafeToUseWithCommandLine(Project.FullName), AdditionalArgs);
			}
			return CmdLine;
		}
Beispiel #16
0
        public SarifLogger(
            string outputFilePath,
            bool verbose,
            IEnumerable<string> analysisTargets,
            bool computeTargetsHash)
        {
            Verbose = verbose;

            _fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
            _textWriter = new StreamWriter(_fileStream);
            _jsonTextWriter = new JsonTextWriter(_textWriter);

            // for debugging it is nice to have the following line added.
            _jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented;

            _issueLogJsonWriter = new IssueLogJsonWriter(_jsonTextWriter);

            Version version = this.GetType().Assembly.GetName().Version;
            ToolInfo toolInfo = new ToolInfo();
            toolInfo.ToolName = "BinSkim";
            toolInfo.ProductVersion = version.Major.ToString() + "." + version.Minor.ToString();
            toolInfo.FileVersion = version.ToString();
            toolInfo.FullVersion = toolInfo.ProductVersion + " beta pre-release";

            RunInfo runInfo = new RunInfo();
            runInfo.AnalysisTargets = new List<FileReference>();

            foreach (string target in analysisTargets)
            {
                var fileReference = new FileReference()
                {
                    Uri = target.CreateUriForJsonSerialization(),
                };

                if (computeTargetsHash)
                {
                    string sha256Hash = PE.ComputeSha256Hash(target) ?? "[could not compute file hash]";
                    fileReference.Hashes = new List<Hash>(new Hash[]
                    {
                            new Hash()
                            {
                                Value = sha256Hash,
                                Algorithm = "SHA-256",
                            }
                    });
                }
                runInfo.AnalysisTargets.Add(fileReference);
            }
            _issueLogJsonWriter.WriteToolAndRunInfo(toolInfo, runInfo);
        }
        public ResultLogger(
            Assembly assembly, 
            string outputFilePath,
            bool verbose,
            IEnumerable<string> analysisTargets,
            bool computeTargetsHash,
            string prereleaseInfo)
        {
            Verbose = verbose;

            _fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
            _textWriter = new StreamWriter(_fileStream);
            _jsonTextWriter = new JsonTextWriter(_textWriter);

            // for debugging it is nice to have the following line added.
            _jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented;

            _issueLogJsonWriter = new ResultLogJsonWriter(_jsonTextWriter);

            var toolInfo = new ToolInfo();
            toolInfo.InitializeFromAssembly(assembly, prereleaseInfo);

            RunInfo runInfo = new RunInfo();
            runInfo.AnalysisTargets = new List<FileReference>();

            foreach (string target in analysisTargets)
            {
                var fileReference = new FileReference()
                {
                    Uri = target.CreateUriForJsonSerialization(),
                };

                if (computeTargetsHash)
                {
                    string sha256Hash = HashUtilities.ComputeSha256Hash(target) ?? "[could not compute file hash]";
                    fileReference.Hashes = new List<Hash>(new Hash[]
                    {
                            new Hash()
                            {
                                Value = sha256Hash,
                                Algorithm = AlgorithmKind.Sha256,
                            }
                    });
                }
                runInfo.AnalysisTargets.Add(fileReference);
            }
            runInfo.InvocationInfo = Environment.CommandLine;

            _issueLogJsonWriter.WriteToolAndRunInfo(toolInfo, runInfo);
        }
 public StandardFileSystem(FileReference workingDirectory)
 {
     _workingDirectory = workingDirectory;
     if (_workingDirectory[_workingDirectory.Length - 1] != '/' ||
         _workingDirectory[_workingDirectory.Length - 1] != '\\')
     {
         _workingDirectory += Path.DirectorySeparatorChar;
     }
     _workingDirectory = fixPath(workingDirectory);
     if (!Directory.Exists(_workingDirectory))
     {
         throw new System.InvalidProgramException("Working directory does not exist.");
     }
 }
		public WindowsPlatformContext(UnrealTargetPlatform InPlatform, FileReference InProjectFile) : base(InPlatform, InProjectFile)
		{
			if(Platform == UnrealTargetPlatform.Win32)
			{
				// ...check if it was supported from a config.
				ConfigCacheIni Ini = ConfigCacheIni.CreateConfigCacheIni(UnrealTargetPlatform.Win64, "Engine", DirectoryReference.FromFile(ProjectFile));
				string MinimumOS;
				if (Ini.GetString("/Script/WindowsTargetPlatform.WindowsTargetSettings", "MinimumOSVersion", out MinimumOS))
				{
					if (string.IsNullOrEmpty(MinimumOS) == false)
					{
						SupportWindowsXP = MinimumOS == "MSOS_XP";
					}
				}
			}
		}
Beispiel #20
0
        public ReferenceProxy(
            Project project,
            FileReference.EFileType fileType,
            Bam.Core.TokenizedString path,
            Object remoteRef,
            FileReference.ESourceTree sourceTree)
        {
            this.IsA = "PBXReferenceProxy";
            this.Name = "PBXReferenceProxy";
            this.FileType = fileType;
            this.Path = path;
            this.RemoteRef = remoteRef;
            this.SourceTree = sourceTree;

            project.ReferenceProxies.AddUnique(this);
        }
		public UEBuildClient(TargetDescriptor InDesc, TargetRules InRulesObject, RulesAssembly InRulesAssembly, FileReference InTargetCsFilename)
			: base(InDesc, InRulesObject, InRulesAssembly, "UE4Client", InTargetCsFilename)
		{
			if (ShouldCompileMonolithic())
			{
				if (!UnrealBuildTool.IsDesktopPlatform(Platform))
				{
					// We are compiling for a console...
					// We want the output to go into the <GAME>\Binaries folder
					if (!InRulesObject.bOutputToEngineBinaries)
					{
						OutputPaths = OutputPaths.Select(Path => new FileReference(Path.FullName.Replace("Engine\\Binaries", InDesc.TargetName + "\\Binaries"))).ToList();
					}
				}
			}
		}
 /// <summary>
 /// Copies a file.
 /// </summary>
 /// <param name="fileSystem">The file system</param>
 /// <param name="oldFilePath">The file that should be copied</param>
 /// <param name="newFilePath">The file that should be created</param>
 /// <param name="overwrite">If this parameter is true and created file will overwrite an existing file if one existing
 /// otherwise an error will be thrown.</param>
 public static void Copy(this IFileSystem fileSystem, FileReference oldFilePath, FileReference newFilePath, bool overwrite)
 {
     using (Stream oldStream = fileSystem.OpenFile(oldFilePath))
     {
         if (oldStream == null) throw new System.IO.FileNotFoundException("File specified by oldFilePath parameter not found");
         if (!overwrite && fileSystem.FileExists(newFilePath)) throw new System.IO.IOException("File specified by newFilePath parameter already exists.");
         using (Stream newStream = fileSystem.CreateFile(newFilePath))
         {
             byte[] buffer = new byte[256];
             int numRead;
             while ((numRead = oldStream.Read(buffer, 0, 256)) != 0)
             {
                 newStream.Write(buffer, 0, numRead);
             }
         }
     }
 }
        // public virtual bool PrepForUATPackageOrDeploy(FileReference ProjectFile, string ProjectName, string ProjectDirectory, string ExecutablePath, string EngineDirectory, bool bForDistribution, string CookFlavor, bool bIsDataDeploy)
        public override bool PrepForUATPackageOrDeploy(FileReference ProjectFile, string ProjectName, string ProjectDirectory, string ExecutablePath, string EngineDirectory, bool bForDistribution, string CookFlavor, bool bIsDataDeploy)
        {
            // set the icon on the original exe this will be used in the task bar when the bootstrap exe runs
            if (File.Exists(Path.Combine(ProjectDirectory, "Build/Windows/Application.ico")))
            {
                GroupIconResource GroupIcon = null;
                GroupIcon = GroupIconResource.FromIco(Path.Combine(ProjectDirectory, "Build/Windows/Application.ico"));

                // Update the icon on the original exe because this will be used when the game is running in the task bar
                using (ModuleResourceUpdate Update = new ModuleResourceUpdate(ExecutablePath, false))
                {
                    const int IconResourceId = 101;
                    if (GroupIcon != null)
                    {
                        Update.SetIcons(IconResourceId, GroupIcon);
                    }
                }
            }
            return true;
        }
		/// <summary>
		/// Runs Cook commandlet.
		/// </summary>
		/// <param name="ProjectName">Project name.</param>
		/// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param>
		/// <param name="Maps">List of maps to cook, can be null in which case -MapIniSection=AllMaps is used.</param>
		/// <param name="Dirs">List of directories to cook, can be null</param>
        /// <param name="InternationalizationPreset">The name of a prebuilt set of internationalization data to be included.</param>
        /// <param name="CulturesToCook">List of culture names whose localized assets should be cooked, can be null (implying defaults should be used).</param>
		/// <param name="TargetPlatform">Target platform.</param>
		/// <param name="Parameters">List of additional parameters.</param>
		public static void CookCommandlet(FileReference ProjectName, string UE4Exe = "UE4Editor-Cmd.exe", string[] Maps = null, string[] Dirs = null, string InternationalizationPreset = "", string[] CulturesToCook = null, string TargetPlatform = "WindowsNoEditor", string Parameters = "-Unversioned")
		{
            string CommandletArguments = "";

			if (IsNullOrEmpty(Maps))
			{
				// MapsToCook = "-MapIniSection=AllMaps";
			}
			else
			{
				string MapsToCookArg = "-Map=" + CombineCommandletParams(Maps);
                MapsToCookArg.Trim();
                CommandletArguments += (CommandletArguments.Length > 0 ? " " : "") + MapsToCookArg;
			}

			if (!IsNullOrEmpty(Dirs))
			{
				string DirsToCookArg = "-CookDir=" + CombineCommandletParams(Dirs);
                DirsToCookArg.Trim();
                CommandletArguments += (CommandletArguments.Length > 0 ? " " : "") + DirsToCookArg;
            }

            if (!String.IsNullOrEmpty(InternationalizationPreset))
            {
                CommandletArguments += (CommandletArguments.Length > 0 ? " " : "") + InternationalizationPreset;
            }

            if (!IsNullOrEmpty(CulturesToCook))
            {
                string CulturesToCookArg = "-CookCultures=" + CombineCommandletParams(CulturesToCook);
                CulturesToCookArg.Trim();
                CommandletArguments += (CommandletArguments.Length > 0 ? " " : "") + CulturesToCookArg;
            }

            RunCommandlet(ProjectName, UE4Exe, "Cook", String.Format("{0} -TargetPlatform={1} {2}",  CommandletArguments, TargetPlatform, Parameters));
		}
Beispiel #25
0
 protected void AssertJobG8Request(Member member, JobAd jobAd, InternalApplication application, FileReference fileReference)
 {
     AssertJobG8Request(member, jobAd, application, fileReference.FileName, GetResumeValue(fileReference));
 }
 /// <summary>
 /// Adds a file to be staged to the given dictionary
 /// </summary>
 /// <param name="FilesToStage">Dictionary of files to be staged</param>
 /// <param name="StagedFile">The staged file location</param>
 /// <param name="InputFile">The input file</param>
 private void AddToDictionary(Dictionary <StagedFileReference, FileReference> FilesToStage, StagedFileReference StagedFile, FileReference InputFile)
 {
     FilesToStage[StagedFile] = InputFile;
 }
    public override void ExecuteBuild()
    {
        // get the project
        var UProjectFileName = ParseParamValue("Project");

        if (UProjectFileName == null)
        {
            throw new AutomationException("Project was not specified via the -project argument.");
        }

        // Get the list of targets
        var TargetList = ParseParamList("Target");

        if (TargetList == null)
        {
            throw new AutomationException("Target was not specified via the -target argument.");
        }

        // get the list of platforms
        var PlatformList = ParseParamList("TargetPlatforms", "Win64");
        List <UnrealTargetPlatform> TargetPlatforms = new List <UnrealTargetPlatform>();

        foreach (string Platform in PlatformList)
        {
            TargetPlatforms.Add((UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), Platform, true));
        }

        // get the list configurations
        var ConfigList = ParseParamList("Config", "Development");
        List <UnrealTargetConfiguration> ConfigsToBuild = new List <UnrealTargetConfiguration>();

        foreach (string Config in ConfigList)
        {
            ConfigsToBuild.Add((UnrealTargetConfiguration)Enum.Parse(typeof(UnrealTargetConfiguration), Config, true));
        }

        // parse any extra parameters
        bool bClean    = ParseParam("Clean");
        int  WorkingCL = ParseParamInt("P4Change");

        FileReference UProjectFileReference = new FileReference(UProjectFileName);

        // add the targets to the agenda
        // verify the targets and add them to the agenda
        var Properties = ProjectUtils.GetProjectProperties(UProjectFileReference);

        UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda();
        foreach (string Target in TargetList)
        {
            SingleTargetProperties TargetData;
            if (!Properties.Targets.TryGetValue((TargetRules.TargetType)Enum.Parse(typeof(TargetRules.TargetType), Target), out TargetData))
            {
                throw new AutomationException("Project does not support specified target: {0}", Target);
            }

            foreach (UnrealTargetPlatform TargetPlatform in TargetPlatforms)
            {
                foreach (UnrealTargetConfiguration TargetConfig in ConfigsToBuild)
                {
                    Agenda.AddTarget(TargetData.TargetName, TargetPlatform, TargetConfig, UProjectFileReference);
                }
            }
        }


        // build it
        UE4Build Build = new UE4Build(this);

        Build.Build(Agenda, InDeleteBuildProducts: bClean, InUpdateVersionFiles: WorkingCL > 0);

        if (WorkingCL > 0)         // only move UAT files if we intend to check in some build products
        {
            Build.AddUATFilesToBuildProducts();
        }
        UE4Build.CheckBuildProducts(Build.BuildProductFiles);

        if (WorkingCL > 0)
        {
            // Sign everything we built
            CodeSign.SignMultipleIfEXEOrDLL(this, Build.BuildProductFiles);

            // Open files for add or edit
            UE4Build.AddBuildProductsToChangelist(WorkingCL, Build.BuildProductFiles);
        }
    }
    public static void RunExportTemplates(FileReference ProjectFile, bool bCheckoutAndSubmit, bool bOnlyLoc, bool bbNoRobomerge, string CommandletOverride)
    {
        string EditorExe = "UE4Editor.exe";

        EditorExe = HostPlatform.Current.GetUE4ExePath(EditorExe);

        string GameBackendFolder = GetGameBackendFolder(ProjectFile);

        if (!DirectoryExists_NoExceptions(GameBackendFolder))
        {
            throw new AutomationException("Error: RunExportTemplates failure. GameBackendFolder not found. {0}", GameBackendFolder);
        }

        string FolderToGenerateIn = GameBackendFolder;

        string Parameters = "-GenerateLoc";

        int WorkingCL = -1;

        if (bCheckoutAndSubmit)
        {
            if (!CommandUtils.P4Enabled)
            {
                throw new AutomationException("Error: RunExportTemplates failure. bCheckoutAndSubmit used without access to P4");
            }

            // Check whether all templates in folder are latest.  If not skip exporting.
            List <string> FilesPreviewSynced;
            CommandUtils.P4.PreviewSync(out FilesPreviewSynced, FolderToGenerateIn + "/...");
            if (FilesPreviewSynced.Count() > 0)
            {
                CommandUtils.LogInformation("Some files in folder {0} are not latest, which means that these files might have already been updated by an earlier exporting job.  Skip this one.", FolderToGenerateIn);
                return;
            }

            String CLDescription = String.Format("RunExportTemplates Updated mcp templates using CL {0}", P4Env.Changelist);
            if (bOnlyLoc)
            {
                CLDescription += " [OnlyLoc]";
            }
            if (!bbNoRobomerge)
            {
                CLDescription += "\r\n#robomerge[ALL] #DisregardExcludedAuthors";
            }

            WorkingCL = CommandUtils.P4.CreateChange(CommandUtils.P4Env.Client, CLDescription);
            CommandUtils.P4.Edit(WorkingCL, FolderToGenerateIn + "/...");
        }

        string Commandlet = string.IsNullOrWhiteSpace(CommandletOverride) ? "ExportTemplatesCommandlet" : CommandletOverride;

        CommandUtils.RunCommandlet(ProjectFile, EditorExe, Commandlet, Parameters);

        if (WorkingCL > 0)
        {
            CommandUtils.P4.RevertUnchanged(WorkingCL);

            if (bOnlyLoc)
            {
                // Revert all folders and files except GeneratedLoc.json
                foreach (string DirPath in Directory.GetDirectories(FolderToGenerateIn))
                {
                    DirectoryInfo Dir = new DirectoryInfo(DirPath);
                    CommandUtils.P4.Revert(WorkingCL, FolderToGenerateIn + "/" + Dir.Name + "/...");
                }

                foreach (string FilePath in Directory.GetFiles(FolderToGenerateIn))
                {
                    FileInfo File = new FileInfo(FilePath);
                    if (File.Name != "GeneratedLoc.json")
                    {
                        CommandUtils.P4.Revert(WorkingCL, FolderToGenerateIn + "/" + File.Name);
                    }
                }
            }

            // If the CL is empty after the RevertUnchanged, the submit call will just delete the CL and return cleanly
            int SubmittedCL;
            CommandUtils.P4.Submit(WorkingCL, out SubmittedCL, false, true);
        }
    }
Beispiel #29
0
    public override void ExecuteBuild()
    {
        // just calling this DesiredTargetVersion because TargetVersion and TargetedVersion get super confusing.
        string DesiredTargetVersionParam = this.ParseParamValue("TargetVersion", null);

        if (string.IsNullOrEmpty(DesiredTargetVersionParam))
        {
            throw new AutomationException("-TargetVersion was not specified.");
        }

        string[] DesiredTargetVersions = DesiredTargetVersionParam.Split('+');

        CommandUtils.LogInformation("Scanning for all csproj's...");
        // Check for all csproj's in the engine dir
        DirectoryReference EngineDir = CommandUtils.EngineDirectory;

        // grab the targeted version.,
        Regex FrameworkRegex         = new Regex("<TargetFrameworkVersion>v(\\d\\.\\d\\.?\\d?)<\\/TargetFrameworkVersion>");
        Regex PossibleAppConfigRegex = new Regex("<TargetFrameworkProfile>(.+)<\\/TargetFrameworkProfile>");
        Regex AppConfigRegex         = new Regex("<supportedRuntime version=\"v(\\d\\.\\d\\.?\\d?)\" sku=\"\\.NETFramework,Version=v(\\d\\.\\d\\.?\\d?),Profile=(.+)\"\\/>");
        Regex DotNetCoreRegex        = new Regex("<TargetFramework>(netcoreapp2.0|netstandard2.0)<\\/TargetFramework>");

        foreach (FileReference CsProj in DirectoryReference.EnumerateFiles(EngineDir, "*.csproj", SearchOption.AllDirectories))
        {
            if (CsProj.ContainsName("ThirdParty", EngineDir) ||
                (CsProj.ContainsName("UE4TemplateProject", EngineDir) && CsProj.GetFileName().Equals("ProjectTemplate.csproj")) ||
                CsProj.GetFileNameWithoutExtension().ToLower().Contains("_mono") ||
                CsProj.GetFileNameWithoutExtension().ToLower().Contains("unrealvs") ||
                CsProj.ContainsName("DatasmithRevitExporter", EngineDir))

            {
                continue;
            }

            // read in the file
            string Contents = File.ReadAllText(CsProj.FullName);
            Match  Match    = DotNetCoreRegex.Match(Contents);
            // Check if we're a _NETCore app, ignore these.
            if (Match.Success)
            {
                continue;
            }


            Match = FrameworkRegex.Match(Contents);
            if (Match.Success)
            {
                string TargetedVersion = Match.Groups[1].Value;
                // make sure we match, throw warning otherwise
                if (!DesiredTargetVersions.Any(DesiredTargetVersion => DesiredTargetVersion.Equals(TargetedVersion, StringComparison.InvariantCultureIgnoreCase)))
                {
                    CommandUtils.LogWarning("Targeted Framework version for project: {0} was not {1}! Targeted Version: {2}", CsProj, String.Join("/", DesiredTargetVersions), TargetedVersion);
                }
            }
            // if we don't have a TargetFrameworkVersion, check for the existence of TargetFrameworkProfile.
            else
            {
                Match = PossibleAppConfigRegex.Match(Contents);
                if (!Match.Success)
                {
                    CommandUtils.LogInformation("No TargetFrameworkVersion or TargetFrameworkProfile found for project {0}, is it a mono project? If not, does it compile properly?", CsProj);
                    continue;
                }

                // look for the app config
                FileReference AppConfigFile = FileReference.Combine(CsProj.Directory, "app.config");
                string        Profile       = Match.Groups[1].Value;
                if (!FileReference.Exists(AppConfigFile))
                {
                    CommandUtils.LogInformation("Found TargetFrameworkProfile but no associated app.config containing the version for project {0}.", CsProj);
                    continue;
                }

                // read in the app config
                Contents = File.ReadAllText(AppConfigFile.FullName);
                Match    = AppConfigRegex.Match(Contents);
                if (!Match.Success)
                {
                    CommandUtils.LogInformation("Couldn't find a supportedRuntime match for the version in the app.config for project {0}.", CsProj);
                    continue;
                }

                // Version1 is the one that appears right after supportedRuntime
                // Version2 is the one in the sku
                // ProfileString should match the TargetFrameworkProfile from the csproj
                string Version1String = Match.Groups[1].Value;
                string Version2String = Match.Groups[2].Value;
                string ProfileString  = Match.Groups[3].Value;

                // not sure how this is possible, but check for it anyway
                if (!ProfileString.Equals(Profile, StringComparison.InvariantCultureIgnoreCase))
                {
                    CommandUtils.LogWarning("The TargetFrameworkProfile in csproj {0} ({1}) doesn't match the sku in it's app.config ({2}).", CsProj, Profile, ProfileString);
                    continue;
                }

                // if the version numbers don't match the app.config is probably corrupt.
                if (!Version1String.Equals(Version2String, StringComparison.InvariantCultureIgnoreCase))
                {
                    CommandUtils.LogWarning("The supportedRunTimeVersion ({0}) and the sku version ({1}) in the app.config for project {2} don't match.", Version1String, Version2String, CsProj);
                    continue;
                }

                // make sure the versions match
                if (!(DesiredTargetVersions.Any(DesiredTargetVersion => DesiredTargetVersion.Equals(Version1String, StringComparison.InvariantCultureIgnoreCase))))
                {
                    CommandUtils.LogWarning("Targeted Framework version for project: {0} was not {1}! Targeted Version: {2}", CsProj, String.Join("/", DesiredTargetVersions), Version1String);
                }
            }
        }
    }
 public SharedCookedBuild(FileReference ProjectFile, IEnumerable <string> TargetPlatforms, SharedCookType BuildType)
 {
     SharedCookedBuildConstructor(ProjectFile, TargetPlatforms, BuildType);
 }
Beispiel #31
0
        /// <summary>
        /// Export the build graph to a Json file, for parallel execution by the build system
        /// </summary>
        /// <param name="File">Output file to write</param>
        /// <param name="Trigger">The trigger whose nodes to run. Null for the default nodes.</param>
        /// <param name="CompletedNodes">Set of nodes which have been completed</param>
        public void Export(FileReference File, ManualTrigger Trigger, HashSet <Node> CompletedNodes)
        {
            // Find all the nodes which we're actually going to execute. We'll use this to filter the graph.
            HashSet <Node> NodesToExecute = new HashSet <Node>();

            foreach (Node Node in Agents.SelectMany(x => x.Nodes))
            {
                if (!CompletedNodes.Contains(Node) && Node.IsBehind(Trigger))
                {
                    NodesToExecute.Add(Node);
                }
            }

            // Open the output file
            using (JsonWriter JsonWriter = new JsonWriter(File.FullName))
            {
                JsonWriter.WriteObjectStart();

                // Write all the agents
                JsonWriter.WriteArrayStart("Groups");
                foreach (Agent Agent in Agents)
                {
                    Node[] Nodes = Agent.Nodes.Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger).ToArray();
                    if (Nodes.Length > 0)
                    {
                        JsonWriter.WriteObjectStart();
                        JsonWriter.WriteValue("Name", Agent.Name);
                        JsonWriter.WriteArrayStart("Agent Types");
                        foreach (string AgentType in Agent.PossibleTypes)
                        {
                            JsonWriter.WriteValue(AgentType);
                        }
                        JsonWriter.WriteArrayEnd();
                        JsonWriter.WriteArrayStart("Nodes");
                        foreach (Node Node in Nodes)
                        {
                            JsonWriter.WriteObjectStart();
                            JsonWriter.WriteValue("Name", Node.Name);
                            JsonWriter.WriteValue("DependsOn", String.Join(";", Node.GetDirectOrderDependencies().Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger)));
                            JsonWriter.WriteValue("RunEarly", Node.bRunEarly);
                            JsonWriter.WriteObjectStart("Notify");
                            JsonWriter.WriteValue("Default", String.Join(";", Node.NotifyUsers));
                            JsonWriter.WriteValue("Submitters", String.Join(";", Node.NotifySubmitters));
                            JsonWriter.WriteValue("Warnings", Node.bNotifyOnWarnings);
                            JsonWriter.WriteObjectEnd();
                            JsonWriter.WriteObjectEnd();
                        }
                        JsonWriter.WriteArrayEnd();
                        JsonWriter.WriteObjectEnd();
                    }
                }
                JsonWriter.WriteArrayEnd();

                // Write all the badges
                JsonWriter.WriteArrayStart("Badges");
                foreach (Badge Badge in Badges)
                {
                    Node[] Dependencies = Badge.Nodes.Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger).ToArray();
                    if (Dependencies.Length > 0)
                    {
                        // Reduce that list to the smallest subset of direct dependencies
                        HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies);
                        foreach (Node Dependency in Dependencies)
                        {
                            DirectDependencies.ExceptWith(Dependency.OrderDependencies);
                        }

                        JsonWriter.WriteObjectStart();
                        JsonWriter.WriteValue("Name", Badge.Name);
                        if (!String.IsNullOrEmpty(Badge.Project))
                        {
                            JsonWriter.WriteValue("Project", Badge.Project);
                        }
                        if (Badge.Change != 0)
                        {
                            JsonWriter.WriteValue("Change", Badge.Change);
                        }
                        JsonWriter.WriteValue("AllDependencies", String.Join(";", Agents.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name)));
                        JsonWriter.WriteValue("DirectDependencies", String.Join(";", DirectDependencies.Select(x => x.Name)));
                        JsonWriter.WriteObjectEnd();
                    }
                }
                JsonWriter.WriteArrayEnd();

                // Write all the triggers and reports.
                JsonWriter.WriteArrayStart("Reports");
                foreach (Report Report in NameToReport.Values)
                {
                    Node[] Dependencies = Report.Nodes.Where(x => NodesToExecute.Contains(x) && x.ControllingTrigger == Trigger).ToArray();
                    if (Dependencies.Length > 0)
                    {
                        // Reduce that list to the smallest subset of direct dependencies
                        HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies);
                        foreach (Node Dependency in Dependencies)
                        {
                            DirectDependencies.ExceptWith(Dependency.OrderDependencies);
                        }

                        JsonWriter.WriteObjectStart();
                        JsonWriter.WriteValue("Name", Report.Name);
                        JsonWriter.WriteValue("AllDependencies", String.Join(";", Agents.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name)));
                        JsonWriter.WriteValue("DirectDependencies", String.Join(";", DirectDependencies.Select(x => x.Name)));
                        JsonWriter.WriteValue("Notify", String.Join(";", Report.NotifyUsers));
                        JsonWriter.WriteValue("IsTrigger", false);
                        JsonWriter.WriteObjectEnd();
                    }
                }
                foreach (ManualTrigger DownstreamTrigger in NameToTrigger.Values)
                {
                    if (DownstreamTrigger.Parent == Trigger)
                    {
                        // Find all the nodes that this trigger is dependent on
                        HashSet <Node> Dependencies = new HashSet <Node>();
                        foreach (Node NodeToExecute in NodesToExecute)
                        {
                            if (NodeToExecute.IsBehind(DownstreamTrigger))
                            {
                                Dependencies.UnionWith(NodeToExecute.OrderDependencies.Where(x => x.ControllingTrigger == Trigger));
                            }
                        }

                        // Reduce that list to the smallest subset of direct dependencies
                        HashSet <Node> DirectDependencies = new HashSet <Node>(Dependencies);
                        foreach (Node Dependency in Dependencies)
                        {
                            DirectDependencies.ExceptWith(Dependency.OrderDependencies);
                        }

                        // Write out the object
                        JsonWriter.WriteObjectStart();
                        JsonWriter.WriteValue("Name", DownstreamTrigger.Name);
                        JsonWriter.WriteValue("AllDependencies", String.Join(";", Agents.SelectMany(x => x.Nodes).Where(x => Dependencies.Contains(x)).Select(x => x.Name)));
                        JsonWriter.WriteValue("DirectDependencies", String.Join(";", Dependencies.Where(x => DirectDependencies.Contains(x)).Select(x => x.Name)));
                        JsonWriter.WriteValue("Notify", String.Join(";", DownstreamTrigger.NotifyUsers));
                        JsonWriter.WriteValue("IsTrigger", true);
                        JsonWriter.WriteObjectEnd();
                    }
                }
                JsonWriter.WriteArrayEnd();

                JsonWriter.WriteObjectEnd();
            }
        }
		/// <summary>
		/// Checks if the editor is currently running and this is a hot-reload
		/// </summary>
		/// <param name="ResetPlatform"></param>
		/// <param name="ResetConfiguration"></param>
		/// <param name="TargetDesc"></param>
		/// <returns></returns>
		private static bool ShouldDoHotReloadFromIDE(TargetDescriptor TargetDesc)
		{
			if (UnrealBuildTool.CommandLineContains("-NoHotReloadFromIDE"))
			{
				// Hot reload disabled through command line, possibly running from UAT
				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
			bool bIsEditorTarget = TargetDesc.TargetName.EndsWith("Editor", StringComparison.InvariantCultureIgnoreCase) || TargetDesc.bIsEditorRecompile;

			if (!ProjectFileGenerator.bGenerateProjectFiles && !UEBuildConfiguration.bGenerateManifest && bIsEditorTarget)
			{
				List<FileReference> EditorProcessFilenames = UEBuildTarget.MakeExecutablePaths(UnrealBuildTool.EngineDirectory, "UE4Editor", TargetDesc.Platform, TargetDesc.Configuration, "", UnrealTargetConfiguration.Development, false, null, null);
				if (EditorProcessFilenames.Count != 1)
				{
					throw new BuildException("ShouldDoHotReload cannot handle multiple binaries returning from UEBuildTarget.MakeExecutablePaths");
				}

				string EditorProcessFilename = EditorProcessFilenames[0].CanonicalName;
				if (TargetDesc.Platform == UnrealTargetPlatform.Mac && !EditorProcessFilename.Contains(".app/contents/macos/"))
				{
					EditorProcessFilename += ".app/contents/macos/" + Path.GetFileNameWithoutExtension(EditorProcessFilename);
				}
					
				BuildHostPlatform.ProcessInfo[] Processes = BuildHostPlatform.Current.GetProcesses();
				string EditorRunsDir = Path.Combine(UnrealBuildTool.EngineDirectory.FullName, "Intermediate", "EditorRuns");

				if (!Directory.Exists(EditorRunsDir))
				{
					return false;
				}

				FileInfo[] EditorRunsFiles = new DirectoryInfo(EditorRunsDir).GetFiles();

				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).CanonicalName == EditorProcessFilename;
					}
				}
			}
			return bIsRunning;
		}
		private static bool ParseRocketCommandlineArg(string InArg, ref string OutGameName, ref FileReference ProjectFile)
		{
			string LowercaseArg = InArg.ToLowerInvariant();

			string ProjectArg = null;
            FileReference TryProjectFile;
			if (LowercaseArg.StartsWith("-project="))
			{
				if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux)
				{
					ProjectArg = InArg.Substring(9).Trim(new Char[] { ' ', '"', '\'' });
				}
				else
				{
					ProjectArg = InArg.Substring(9);
				}
			}
			else if (LowercaseArg.EndsWith(".uproject"))
			{
				ProjectArg = InArg;
			}
			else if (LowercaseArg.StartsWith("-remoteini="))
			{
				RemoteIniPath = InArg.Substring(11);
			}
			else
            if (UProjectInfo.TryGetProjectForTarget(LowercaseArg, out TryProjectFile))
            {
                ProjectFile = TryProjectFile;
                OutGameName = InArg;
                return true;
            }
            else
            {
				return false;
			}

			if (ProjectArg != null && ProjectArg.Length > 0)
			{
				string ProjectPath = Path.GetDirectoryName(ProjectArg);
				OutGameName = Path.GetFileNameWithoutExtension(ProjectArg);

				if (Path.IsPathRooted(ProjectPath) == false)
				{
					if (Directory.Exists(ProjectPath) == false)
					{
						// If it is *not* rooted, then we potentially received a path that is 
						// relative to Engine/Binaries/[PLATFORM] rather than Engine/Source
						if (ProjectPath.StartsWith("../") || ProjectPath.StartsWith("..\\"))
						{
							string AlternativeProjectpath = ProjectPath.Substring(3);
							if (Directory.Exists(AlternativeProjectpath))
							{
								ProjectPath = AlternativeProjectpath;
								ProjectArg = ProjectArg.Substring(3);
								Debug.Assert(ProjectArg.Length > 0);
							}
						}
					}
				}

				ProjectFile = new FileReference(ProjectArg);
			}

			return true;
		}
		static public bool FileExists(FileReference File)
		{
			DirectoryCache FoundDirectoryCache = FindOrCreateDirectoryCache(File.Directory);
			return FoundDirectoryCache.HasFile(File);
		}
        public override ExitCode Execute()
        {
            string[] Arguments = this.Params;

            ProjectName    = ParseParamValue("project", ProjectName);
            Targets        = ParseParamValue("target", Targets);
            Platforms      = ParseParamValue("platform", Platforms);
            Configurations = ParseParamValue("configuration", Configurations);
            Clean          = ParseParam("clean") || Clean;

            if (string.IsNullOrEmpty(Targets))
            {
                throw new AutomationException("No target specified with -target. Use -help to see all options");
            }

            bool NoTools = ParseParam("notools");

            IEnumerable <string> TargetList = Targets.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);
            IEnumerable <UnrealTargetConfiguration> ConfigurationList = null;
            IEnumerable <UnrealTargetPlatform>      PlatformList      = null;

            try
            {
                ConfigurationList = Configurations.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)
                                    .Select(C => (UnrealTargetConfiguration)Enum.Parse(typeof(UnrealTargetConfiguration), C, true)).ToArray();
            }
            catch (Exception Ex)
            {
                LogError("Failed to parse configuration string. {0}", Ex.Message);
                return(ExitCode.Error_Arguments);
            }

            try
            {
                PlatformList = Platforms.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries)
                               .Select(C =>
                {
                    UnrealTargetPlatform Platform;
                    if (!UnrealTargetPlatform.TryParse(C, out Platform))
                    {
                        throw new AutomationException("No such platform {0}", C);
                    }
                    return(Platform);
                }).ToArray();
            }
            catch (Exception Ex)
            {
                LogError("Failed to parse configuration string. {0}", Ex.Message);
                return(ExitCode.Error_Arguments);
            }

            FileReference ProjectFile = null;

            if (!string.IsNullOrEmpty(ProjectName))
            {
                ProjectFile = ProjectUtils.FindProjectFileFromName(ProjectName);

                if (ProjectFile == null)
                {
                    throw new AutomationException("Unable to find uproject file for {0}", ProjectName);
                }

                string SourceDirectoryName = Path.Combine(ProjectFile.Directory.FullName, "Source");

                if (Directory.Exists(SourceDirectoryName))
                {
                    IEnumerable <string> TargetScripts = Directory.EnumerateFiles(SourceDirectoryName, "*.Target.cs");

                    foreach (string TargetName in TargetList)
                    {
                        string TargetScript = TargetScripts.Where(S => S.IndexOf(TargetName, StringComparison.OrdinalIgnoreCase) >= 0).FirstOrDefault();

                        if (TargetScript == null && (
                                TargetName.Equals("Client", StringComparison.OrdinalIgnoreCase) ||
                                TargetName.Equals("Game", StringComparison.OrdinalIgnoreCase)
                                )
                            )
                        {
                            // if there's no ProjectGame.Target.cs or ProjectClient.Target.cs then
                            // fallback to Project.Target.cs
                            TargetScript = TargetScripts.Where(S => S.IndexOf(ProjectName + ".", StringComparison.OrdinalIgnoreCase) >= 0).FirstOrDefault();
                        }

                        if (TargetScript == null)
                        {
                            throw new AutomationException("No Target.cs file for target {0} in project {1}", TargetName, ProjectName);
                        }

                        string FullName = Path.GetFileName(TargetScript);
                        TargetNames[TargetName] = Regex.Replace(FullName, ".Target.cs", "", RegexOptions.IgnoreCase);
                    }
                }
            }
            else
            {
                Log.TraceWarning("No project specified, will build vanilla UE4 binaries");
            }

            // Handle content-only projects or when no project was specified
            if (TargetNames.Keys.Count == 0)
            {
                foreach (string TargetName in TargetList)
                {
                    TargetNames[TargetName] = string.Format("UE4{0}", TargetName);
                }
            }

            UE4Build Build = new UE4Build(this);

            UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda();

            string EditorTarget = TargetList.Where(T => T.EndsWith("Editor", StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            IEnumerable <string> OtherTargets = TargetList.Where(T => T != EditorTarget);

            UnrealTargetPlatform CurrentPlatform = HostPlatform.Current.HostEditorPlatform;

            if (!NoTools)
            {
                Agenda.AddTarget("UnrealHeaderTool", CurrentPlatform, UnrealTargetConfiguration.Development);
            }

            if (string.IsNullOrEmpty(EditorTarget) == false)
            {
                string TargetName = TargetNames[EditorTarget];

                Agenda.AddTarget(TargetName, CurrentPlatform, UnrealTargetConfiguration.Development, ProjectFile);

                if (!NoTools)
                {
                    Agenda.AddTarget("ShaderCompileWorker", CurrentPlatform, UnrealTargetConfiguration.Development);
                    Agenda.AddTarget("UnrealLightmass", CurrentPlatform, UnrealTargetConfiguration.Development);
                    Agenda.AddTarget("UnrealPak", CurrentPlatform, UnrealTargetConfiguration.Development);
                    Agenda.AddTarget("CrashReportClient", CurrentPlatform, UnrealTargetConfiguration.Shipping);
                }
            }

            foreach (string Target in OtherTargets)
            {
                string TargetName = TargetNames[Target];

                bool IsServer = Target.EndsWith("Server", StringComparison.OrdinalIgnoreCase);

                IEnumerable <UnrealTargetPlatform> PlatformsToBuild = IsServer ? new UnrealTargetPlatform[] { CurrentPlatform } : PlatformList;

                foreach (UnrealTargetPlatform Platform in PlatformsToBuild)
                {
                    foreach (UnrealTargetConfiguration Config in ConfigurationList)
                    {
                        Agenda.AddTarget(TargetName, Platform, Config);
                    }
                }
            }

            // Set clean and log
            foreach (var Target in Agenda.Targets)
            {
                if (Clean)
                {
                    Target.Clean = Clean;
                }

                Log.TraceInformation("Will {0}build {1}", Clean ? "clean and " : "", Target);
            }

            Build.Build(Agenda, InUpdateVersionFiles: false);

            return(ExitCode.Success);
        }
 /// <summary>
 /// Stage a single file
 /// </summary>
 /// <param name="FileType">The type for the staged file</param>
 /// <param name="InputFile">The source file</param>
 /// <param name="OutputFile">The staged file location</param>
 public void StageFile(StagedFileType FileType, FileReference InputFile, StagedFileReference OutputFile)
 {
     FilesToStage.Add(FileType, OutputFile, InputFile);
 }
    public void StageRuntimeDependenciesFromReceipt(TargetReceipt Receipt, bool RequireDependenciesToExist, bool bUsingPakFile)
    {
        // Patterns to exclude from wildcard searches. Any maps and assets must be cooked.
        List <string> ExcludePatterns = new List <string>();

        ExcludePatterns.Add(".../*.umap");
        ExcludePatterns.Add(".../*.uasset");

        // Also stage any additional runtime dependencies, like ThirdParty DLLs
        foreach (RuntimeDependency RuntimeDependency in Receipt.RuntimeDependencies)
        {
            // allow missing files if needed
            if ((RequireDependenciesToExist && RuntimeDependency.Type != StagedFileType.DebugNonUFS) || FileReference.Exists(RuntimeDependency.Path))
            {
                StageFile(RuntimeDependency.Type, RuntimeDependency.Path);
            }
        }
    }
        /// <summary>
        /// Generates a report listing the most frequently referenced opaque symbols in each module
        /// </summary>
        /// <param name="Files">The files to include in the report</param>
        /// <param name="ReportFileLocation">Output file for the report</param>
        /// <param name="Log">Writer for log output</param>
        public static void Generate(FileReference ReportFileLocation, DirectoryReference InputDir, HashSet <SourceFile> PreprocessedFiles, LineBasedTextWriter Log)
        {
            Log.WriteLine("Writing {0}...", ReportFileLocation.FullName);

            // Get a count of files referencing each symbol
            Dictionary <Symbol, int> SymbolToRefCount       = new Dictionary <Symbol, int>();
            Dictionary <Symbol, int> SymbolToOpaqueRefCount = new Dictionary <Symbol, int>();

            foreach (SourceFile PreprocessedFile in PreprocessedFiles)
            {
                if (PreprocessedFile.Fragments != null)
                {
                    HashSet <Symbol> Symbols          = new HashSet <Symbol>();
                    HashSet <Symbol> NonOpaqueSymbols = new HashSet <Symbol>();
                    foreach (SourceFragment Fragment in PreprocessedFile.Fragments)
                    {
                        foreach (KeyValuePair <Symbol, SymbolReferenceType> Pair in Fragment.ReferencedSymbols)
                        {
                            Symbols.Add(Pair.Key);
                            if (Pair.Value != SymbolReferenceType.Opaque)
                            {
                                NonOpaqueSymbols.Add(Pair.Key);
                            }
                        }
                    }

                    foreach (Symbol Symbol in Symbols)
                    {
                        int Count;
                        SymbolToRefCount.TryGetValue(Symbol, out Count);
                        SymbolToRefCount[Symbol] = Count + 1;

                        int OpaqueCount;
                        SymbolToOpaqueRefCount.TryGetValue(Symbol, out OpaqueCount);
                        SymbolToOpaqueRefCount[Symbol] = NonOpaqueSymbols.Contains(Symbol) ? OpaqueCount : OpaqueCount + 1;
                    }
                }
            }

            // Build a map of module to symbols
            MultiValueDictionary <BuildModule, Symbol> ModuleToSymbols = new MultiValueDictionary <BuildModule, Symbol>();

            foreach (Symbol Symbol in SymbolToRefCount.Keys)
            {
                SourceFile File = Symbol.Fragment.File;
                if (File.Module != null)
                {
                    ModuleToSymbols.Add(File.Module, Symbol);
                }
            }

            // Write out a CSV report containing the list of symbols and number of files referencing them
            using (StreamWriter Writer = new StreamWriter(ReportFileLocation.FullName))
            {
                Writer.WriteLine("Module,Symbol,Fwd,RefCount,OpaqueRefCount");
                foreach (BuildModule Module in ModuleToSymbols.Keys)
                {
                    foreach (Symbol Symbol in ModuleToSymbols[Module].OrderByDescending(x => SymbolToOpaqueRefCount[x]))
                    {
                        Writer.WriteLine("{0},{1},{2},{3},{4}", Module.Name, Symbol.Name, Symbol.ForwardDeclaration, SymbolToRefCount[Symbol], SymbolToOpaqueRefCount[Symbol]);
                    }
                }
            }
        }
Beispiel #39
0
 protected void AssertJobG8Request(AnonymousContact contact, JobAd jobAd, InternalApplication application, FileReference fileReference)
 {
     AssertJobG8Request(contact, jobAd, application, fileReference.FileName, GetResumeValue(fileReference));
 }
Beispiel #40
0
    public override void ExecuteBuild()
    {
        int WorkingCL = -1;

        if (P4Enabled && AllowSubmit)
        {
            string CmdLine = "";
            foreach (var Arg in Params)
            {
                CmdLine += Arg.ToString() + " ";
            }
            WorkingCL = P4.CreateChange(P4Env.Client, String.Format("MegaXGE build from changelist {0} - Params: {1}", P4Env.Changelist, CmdLine));
        }

        LogInformation("************************* MegaXGE");

        bool   Clean             = ParseParam("Clean");
        string CleanToolLocation = CombinePaths(CmdEnv.LocalRoot, "Engine", "Build", "Batchfiles", "Clean.bat");

        bool ShowProgress = ParseParam("Progress");

        var UE4Build = new UE4Build(this);

        var Agenda = new UE4Build.BuildAgenda();

        // we need to always build UHT when we use mega XGE
        var ProgramTargets = new string[]
        {
            "UnrealHeaderTool",
        };

        Agenda.AddTargets(ProgramTargets, UnrealTargetPlatform.Win64, UnrealTargetConfiguration.Development);
        if (Clean)
        {
            LogSetProgress(ShowProgress, "Cleaning previous builds...");
            foreach (var CurTarget in ProgramTargets)
            {
                string Args = String.Format("{0} {1} {2}", CurTarget, UnrealTargetPlatform.Win64.ToString(), UnrealTargetConfiguration.Development.ToString());
                RunAndLog(CmdEnv, CleanToolLocation, Args);
            }
        }

        LogInformation("*************************");
        for (int Arg = 1; Arg < 100; Arg++)
        {
            string Parm   = String.Format("Target{0}", Arg);
            string Target = ParseParamValue(Parm, "");
            if (String.IsNullOrEmpty(Target))
            {
                break;
            }

            FileReference ProjectFile = null;

            string ProjectFileParam = ParseParamValue(String.Format("Project{0}", Arg), null);
            if (ProjectFileParam != null)
            {
                ProjectFile = new FileReference(ProjectFileParam);
                if (!FileReference.Exists(ProjectFile))
                {
                    throw new AutomationException("Project file '{0}' could not be found");
                }
            }

            var Parts = Target.Split(' ');

            string JustTarget = Parts[0];
            if (String.IsNullOrEmpty(JustTarget))
            {
                throw new AutomationException("BUILD FAILED target option '{0}' not parsed.", Target);
            }
            var Targets = JustTarget.Split('|');
            if (Targets.Length < 1)
            {
                throw new AutomationException("BUILD FAILED target option '{0}' not parsed.", Target);
            }

            var Platforms      = new List <UnrealTargetPlatform>();
            var Configurations = new List <UnrealTargetConfiguration>();

            for (int Part = 1; Part < Parts.Length; Part++)
            {
                if (!String.IsNullOrEmpty(Parts[Part]))
                {
                    var SubParts = Parts[Part].Split('|');

                    foreach (var SubPart in SubParts)
                    {
                        UnrealTargetPlatform Platform;
                        if (UnrealTargetPlatform.TryParse(SubPart, out Platform))
                        {
                            Platforms.Add(Platform);
                        }
                        else
                        {
                            switch (SubPart.ToUpperInvariant())
                            {
                            case "DEBUG":
                                Configurations.Add(UnrealTargetConfiguration.Debug);
                                break;

                            case "DEBUGGAME":
                                Configurations.Add(UnrealTargetConfiguration.DebugGame);
                                break;

                            case "DEVELOPMENT":
                                Configurations.Add(UnrealTargetConfiguration.Development);
                                break;

                            case "SHIPPING":
                                Configurations.Add(UnrealTargetConfiguration.Shipping);
                                break;

                            case "TEST":
                                Configurations.Add(UnrealTargetConfiguration.Test);
                                break;

                            default:
                                throw new AutomationException("BUILD FAILED target option {0} not recognized.", SubPart);
                            }
                        }
                    }
                }
            }
            if (Platforms.Count < 1)
            {
                Platforms.Add(UnrealTargetPlatform.Win64);
            }
            if (Configurations.Count < 1)
            {
                Configurations.Add(UnrealTargetConfiguration.Development);
            }
            foreach (var Platform in Platforms)
            {
                foreach (var CurTarget in Targets)
                {
                    foreach (var Configuration in Configurations)
                    {
                        Agenda.AddTargets(new string[] { CurTarget }, Platform, Configuration, ProjectFile);
                        LogInformation("Target {0} {1} {2}", CurTarget, Platform.ToString(), Configuration.ToString());
                        if (Clean)
                        {
                            string Args = String.Format("{0} {1} {2}", CurTarget, Platform.ToString(), Configuration.ToString());
                            RunAndLog(CmdEnv, CleanToolLocation, Args);
                        }
                    }
                }
            }
        }
        LogInformation("*************************");

        UE4Build.Build(Agenda, InUpdateVersionFiles: IsBuildMachine, InUseParallelExecutor: ParseParam("useparallelexecutor"), InShowProgress: ShowProgress);

        //      if (WorkingCL > 0) // only move UAT files if we intend to check in some build products
        //      {
        //          UE4Build.CopyUATFilesAndAddToBuildProducts();
        //      }

        UE4Build.CheckBuildProducts(UE4Build.BuildProductFiles);

        if (WorkingCL > 0)
        {
            // Sign everything we built
            CodeSign.SignMultipleIfEXEOrDLL(this, UE4Build.BuildProductFiles);

            // Open files for add or edit
            UE4Build.AddBuildProductsToChangelist(WorkingCL, UE4Build.BuildProductFiles);

            int SubmittedCL;
            P4.Submit(WorkingCL, out SubmittedCL, true, true);
        }

        PrintRunTime();
    }
Beispiel #41
0
        /// <summary>
        /// Writes a preprocessed build graph to a script file
        /// </summary>
        /// <param name="File">The file to load</param>
        /// <param name="SchemaFile">Schema file for validation</param>
        public void Write(FileReference File, FileReference SchemaFile)
        {
            XmlWriterSettings Settings = new XmlWriterSettings();

            Settings.Indent      = true;
            Settings.IndentChars = "\t";

            using (XmlWriter Writer = XmlWriter.Create(File.FullName, Settings))
            {
                Writer.WriteStartElement("BuildGraph", "http://www.epicgames.com/BuildGraph");

                if (SchemaFile != null)
                {
                    Writer.WriteAttributeString("schemaLocation", "http://www.w3.org/2001/XMLSchema-instance", "http://www.epicgames.com/BuildGraph " + SchemaFile.MakeRelativeTo(File.Directory));
                }

                foreach (Agent Agent in Agents)
                {
                    Agent.Write(Writer, null);
                }

                foreach (ManualTrigger ControllingTrigger in Agents.SelectMany(x => x.Nodes).Where(x => x.ControllingTrigger != null).Select(x => x.ControllingTrigger).Distinct())
                {
                    Writer.WriteStartElement("Trigger");
                    Writer.WriteAttributeString("Name", ControllingTrigger.QualifiedName);
                    foreach (Agent Agent in Agents)
                    {
                        Agent.Write(Writer, ControllingTrigger);
                    }
                    Writer.WriteEndElement();
                }

                foreach (KeyValuePair <string, Node[]> Aggregate in AggregateNameToNodes)
                {
                    Writer.WriteStartElement("Aggregate");
                    Writer.WriteAttributeString("Name", Aggregate.Key);
                    Writer.WriteAttributeString("Requires", String.Join(";", Aggregate.Value.Select(x => x.Name)));
                    Writer.WriteEndElement();
                }

                foreach (Report Report in NameToReport.Values)
                {
                    Writer.WriteStartElement("Report");
                    Writer.WriteAttributeString("Name", Report.Name);
                    Writer.WriteAttributeString("Requires", String.Join(";", Report.Nodes.Select(x => x.Name)));
                    Writer.WriteEndElement();
                }

                foreach (Badge Badge in Badges)
                {
                    Writer.WriteStartElement("Badge");
                    Writer.WriteAttributeString("Name", Badge.Name);
                    if (Badge.Project != null)
                    {
                        Writer.WriteAttributeString("Project", Badge.Project);
                    }
                    if (Badge.Change != 0)
                    {
                        Writer.WriteAttributeString("Change", Badge.Change.ToString());
                    }
                    Writer.WriteAttributeString("Requires", String.Join(";", Badge.Nodes.Select(x => x.Name)));
                    Writer.WriteEndElement();
                }

                Writer.WriteEndElement();
            }
        }
 public static string GetGameBackendFolder(FileReference ProjectFile)
 {
     return(Path.Combine(ProjectFile.Directory.FullName, "Content", "Backend"));
 }
    public List <ISharedCookedBuild> FindBestBuilds()
    {
        // Attempt manifest searching first
        ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), UnrealTargetPlatform.Win64);

        IReadOnlyList <string> RawSharedCookedSources = null;

        Hierarchy.TryGetValues("SharedCookedBuildSettings", "SharedCookedSources", out RawSharedCookedSources);
        if (RawSharedCookedSources == null)
        {
            throw new AutomationException("Unable to locate shared cooked builds. SharedCookedSources not set in Engine.ini [SharedCookedBuildSettings]");
        }

        List <Dictionary <string, string> > ParsedSharedCookSources = new List <Dictionary <string, string> >();

        foreach (string RawConfig in RawSharedCookedSources)
        {
            Dictionary <string, string> ParsedSource = null;
            if (ConfigHierarchy.TryParse(RawConfig, out ParsedSource))
            {
                ParsedSharedCookSources.Add(ParsedSource);
            }
        }

        List <ISharedCookedBuild> CandidateBuilds = new List <ISharedCookedBuild>();

        // If existing sync is present, stick to it. Read version out of sync file
        foreach (string Platform in TargetPlatforms)
        {
            FileReference SyncedBuildFile = new FileReference(CommandUtils.CombinePaths(InstallPath.FullName, Platform, SyncedBuildFileName));
            if (FileReference.Exists(SyncedBuildFile))
            {
                string[] SyncedBuildInfo = FileReference.ReadAllLines(SyncedBuildFile);
                int      SyncedCL        = int.Parse(SyncedBuildInfo[0]);
                if (IsValidCL(SyncedCL, BuildType, LocalSync))
                {
                    CandidateBuilds.Add(new ExistingSharedCookedBuild()
                    {
                        CL = SyncedCL, Platform = Platform
                    });
                }
            }
        }

        foreach (Dictionary <string, string> Source in ParsedSharedCookSources)
        {
            SharedCookSource SourceType = (SharedCookSource)Enum.Parse(typeof(SharedCookSource), Source["Type"], true);
            foreach (string Platform in TargetPlatforms)
            {
                if (SourceType == SharedCookSource.Manifest)
                {
                    CandidateBuilds.AddRange(FindValidManifestBuilds(Source["Path"], Platform));
                }
                else if (SourceType == SharedCookSource.LooseFiles)
                {
                    CandidateBuilds.AddRange(FindValidLooseBuilds(Source["Path"], Platform));
                }
            }
        }

        // Strip all failed searches
        CandidateBuilds.RemoveAll(x => x == null);

        // Make sure we have a matching CL for all target platforms, regardless of source
        List <int> OrderedDistinctCLs = CandidateBuilds.Select(x => x.CL).Distinct().OrderByDescending(i => i).ToList();
        int        BestCL             = -1;

        foreach (int CL in OrderedDistinctCLs)
        {
            // Ensure we have a platform for each
            HashSet <string> CLPlatforms = new HashSet <string>(CandidateBuilds.Where(x => x.CL == CL).Select(x => x.Platform).ToList());
            if (CLPlatforms.SetEquals(TargetPlatforms))
            {
                BestCL = CL;
                break;
            }
        }

        if (BestCL < 0)
        {
            CommandUtils.LogError("Could not locate valid shared cooked build for all target platforms");
            CommandUtils.LogError("Current CL: {0}, Current Code CL: {1}", LocalSync.Changelist, LocalSync.CompatibleChangelist);
        }

        return(CandidateBuilds.Where(x => x.CL == BestCL).ToList());
    }
        /// <summary>
        /// Execute the task.
        /// </summary>
        /// <param name="Job">Information about the current job</param>
        /// <param name="BuildProducts">Set of build products produced by this node.</param>
        /// <param name="TagNameToFileSet">Mapping from tag names to the set of files they include</param>
        public override void Execute(JobContext Job, HashSet <FileReference> BuildProducts, Dictionary <string, HashSet <FileReference> > TagNameToFileSet)
        {
            // Parse all the source patterns
            FilePattern SourcePattern = new FilePattern(CommandUtils.RootDirectory, Parameters.From);

            // Parse the target pattern
            FilePattern TargetPattern = new FilePattern(CommandUtils.RootDirectory, Parameters.To);

            // Apply the filter to the source files
            HashSet <FileReference> Files = null;

            if (!String.IsNullOrEmpty(Parameters.Files))
            {
                SourcePattern = SourcePattern.AsDirectoryPattern();
                Files         = ResolveFilespec(SourcePattern.BaseDirectory, Parameters.Files, TagNameToFileSet);
            }

            // Build the file mapping
            Dictionary <FileReference, FileReference> TargetFileToSourceFile = FilePattern.CreateMapping(Files, ref SourcePattern, ref TargetPattern);

            //  If we're not overwriting, remove any files where the destination file already exists.
            if (!Parameters.Overwrite)
            {
                TargetFileToSourceFile = TargetFileToSourceFile.Where(File =>
                {
                    if (FileReference.Exists(File.Key))
                    {
                        CommandUtils.LogInformation("Not copying existing file {0}", File.Key);
                        return(false);
                    }
                    return(true);
                }).ToDictionary(Pair => Pair.Key, Pair => Pair.Value);
            }

            // Check we got some files
            if (TargetFileToSourceFile.Count == 0)
            {
                CommandUtils.LogInformation("No files found matching '{0}'", SourcePattern);
                return;
            }

            // If the target is on a network share, retry creating the first directory until it succeeds
            DirectoryReference FirstTargetDirectory = TargetFileToSourceFile.First().Key.Directory;

            if (!DirectoryReference.Exists(FirstTargetDirectory))
            {
                const int MaxNumRetries = 15;
                for (int NumRetries = 0;; NumRetries++)
                {
                    try
                    {
                        DirectoryReference.CreateDirectory(FirstTargetDirectory);
                        if (NumRetries == 1)
                        {
                            Log.TraceInformation("Created target directory {0} after 1 retry.", FirstTargetDirectory);
                        }
                        else if (NumRetries > 1)
                        {
                            Log.TraceInformation("Created target directory {0} after {1} retries.", FirstTargetDirectory, NumRetries);
                        }
                        break;
                    }
                    catch (Exception Ex)
                    {
                        if (NumRetries == 0)
                        {
                            Log.TraceInformation("Unable to create directory '{0}' on first attempt. Retrying {1} times...", FirstTargetDirectory, MaxNumRetries);
                        }

                        Log.TraceLog("  {0}", Ex);

                        if (NumRetries >= 15)
                        {
                            throw new AutomationException(Ex, "Unable to create target directory '{0}' after {1} retries.", FirstTargetDirectory, NumRetries);
                        }

                        Thread.Sleep(2000);
                    }
                }
            }

            // Copy them all
            KeyValuePair <FileReference, FileReference>[] FilePairs = TargetFileToSourceFile.ToArray();
            CommandUtils.LogInformation("Copying {0} file{1} from {2} to {3}...", FilePairs.Length, (FilePairs.Length == 1)? "" : "s", SourcePattern.BaseDirectory, TargetPattern.BaseDirectory);
            foreach (KeyValuePair <FileReference, FileReference> FilePair in FilePairs)
            {
                CommandUtils.LogLog("  {0} -> {1}", FilePair.Value, FilePair.Key);
            }
            CommandUtils.ThreadedCopyFiles(FilePairs.Select(x => x.Value.FullName).ToList(), FilePairs.Select(x => x.Key.FullName).ToList(), bQuiet: true);

            // Update the list of build products
            BuildProducts.UnionWith(TargetFileToSourceFile.Keys);

            // Apply the optional output tag to them
            foreach (string TagName in FindTagNamesFromList(Parameters.Tag))
            {
                FindOrAddTagSet(TagNameToFileSet, TagName).UnionWith(TargetFileToSourceFile.Keys);
            }
        }
        /// <summary>
        /// Find all the build products created by compiling the given project file
        /// </summary>
        /// <param name="ProjectFiles">Initial project file to read. All referenced projects will also be read.</param>
        /// <param name="InitialProperties">Mapping of property name to value</param>
        /// <param name="OutBuildProducts">Receives a set of build products on success</param>
        /// <param name="OutReferences">Receives a set of non-private references on success</param>
        /// <returns>True if the build products were found, false otherwise.</returns>
        static bool FindBuildProducts(HashSet <FileReference> ProjectFiles, Dictionary <string, string> InitialProperties, out HashSet <FileReference> OutBuildProducts, out HashSet <FileReference> OutReferences)
        {
            // Read all the project information into a dictionary
            Dictionary <FileReference, CsProjectInfo> FileToProjectInfo = new Dictionary <FileReference, CsProjectInfo>();

            foreach (FileReference ProjectFile in ProjectFiles)
            {
                if (!ReadProjectsRecursively(ProjectFile, InitialProperties, FileToProjectInfo))
                {
                    OutBuildProducts = null;
                    OutReferences    = null;
                    return(false);
                }
            }

            // Find all the build products and references
            HashSet <FileReference> BuildProducts = new HashSet <FileReference>();
            HashSet <FileReference> References    = new HashSet <FileReference>();

            foreach (KeyValuePair <FileReference, CsProjectInfo> Pair in FileToProjectInfo)
            {
                CsProjectInfo ProjectInfo = Pair.Value;

                // Add the standard build products
                DirectoryReference OutputDir = ProjectInfo.GetOutputDir(Pair.Key.Directory);
                ProjectInfo.AddBuildProducts(OutputDir, BuildProducts);

                // Add the referenced assemblies
                foreach (KeyValuePair <FileReference, bool> Reference in ProjectInfo.References)
                {
                    FileReference OtherAssembly = Reference.Key;
                    if (Reference.Value)
                    {
                        // Add reference from the output dir
                        FileReference OutputFile = FileReference.Combine(OutputDir, OtherAssembly.GetFileName());
                        BuildProducts.Add(OutputFile);

                        FileReference OutputSymbolFile = OutputFile.ChangeExtension(".pdb");
                        if (OutputSymbolFile.Exists())
                        {
                            BuildProducts.Add(OutputSymbolFile);
                        }
                    }
                    else
                    {
                        // Add reference directly
                        References.Add(OtherAssembly);
                        FileReference SymbolFile = OtherAssembly.ChangeExtension(".pdb");
                        if (SymbolFile.Exists())
                        {
                            References.Add(SymbolFile);
                        }
                    }
                }

                // Add build products from all the referenced projects. MSBuild only copy the directly referenced build products, not recursive references or other assemblies.
                foreach (CsProjectInfo OtherProjectInfo in ProjectInfo.ProjectReferences.Where(x => x.Value).Select(x => FileToProjectInfo[x.Key]))
                {
                    OtherProjectInfo.AddBuildProducts(OutputDir, BuildProducts);
                }
            }

            // Update the output set
            OutBuildProducts = BuildProducts;
            OutReferences    = References;
            return(true);
        }
Beispiel #46
0
        /// <summary>
        /// Entry point for the commandlet
        /// </summary>
        public override void ExecuteBuild()
        {
            string OutputDir = ParseParamValue("OutputDir");
            string ContentOnlyPlatformsString = ParseParamValue("ContentOnlyPlatforms");
            IEnumerable <UnrealTargetPlatform> ContentOnlyPlatforms = Enumerable.Empty <UnrealTargetPlatform>();

            if (!String.IsNullOrWhiteSpace(ContentOnlyPlatformsString))
            {
                ContentOnlyPlatforms = ContentOnlyPlatformsString.Split(';').Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => (UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), x));
            }
            string AnalyticsTypeOverride = ParseParamValue("AnalyticsTypeOverride");

            // Write InstalledBuild.txt to indicate Engine is installed
            string InstalledBuildFile = CommandUtils.CombinePaths(OutputDir, "Engine/Build/InstalledBuild.txt");

            CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(InstalledBuildFile));
            CommandUtils.WriteAllText(InstalledBuildFile, "");

            string         OutputEnginePath     = Path.Combine(OutputDir, "Engine");
            string         OutputBaseEnginePath = Path.Combine(OutputEnginePath, "Config", "BaseEngine.ini");
            FileAttributes OutputAttributes     = FileAttributes.ReadOnly;
            List <String>  IniLines             = new List <String>();

            // Should always exist but if not, we don't need extra line
            if (File.Exists(OutputBaseEnginePath))
            {
                OutputAttributes = File.GetAttributes(OutputBaseEnginePath);
                IniLines.Add("");
            }
            else
            {
                CommandUtils.CreateDirectory(CommandUtils.GetDirectoryName(OutputBaseEnginePath));
                CommandUtils.WriteAllText(OutputBaseEnginePath, "");
                OutputAttributes = File.GetAttributes(OutputBaseEnginePath) | OutputAttributes;
            }

            // Create list of platform configurations installed in a Rocket build
            List <InstalledPlatformInfo.InstalledPlatformConfiguration> InstalledConfigs = new List <InstalledPlatformInfo.InstalledPlatformConfiguration>();

            foreach (UnrealTargetPlatform CodeTargetPlatform in Enum.GetValues(typeof(UnrealTargetPlatform)))
            {
                UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(CodeTargetPlatform, true);
                if (BuildPlatform != null)
                {
                    string Architecture = BuildPlatform.CreateContext(null).GetActiveArchitecture();

                    // Try to parse additional Architectures from the command line
                    string Architectures    = ParseParamValue(CodeTargetPlatform.ToString() + "Architectures");
                    string GPUArchitectures = ParseParamValue(CodeTargetPlatform.ToString() + "GPUArchitectures");

                    // Build a list of pre-compiled architecture combinations for this platform if any
                    List <string> AllArchNames;

                    if (!String.IsNullOrWhiteSpace(Architectures) && !String.IsNullOrWhiteSpace(GPUArchitectures))
                    {
                        AllArchNames = (from Arch in Architectures.Split('+')
                                        from GPUArch in GPUArchitectures.Split('+')
                                        select "-" + Arch + "-" + GPUArch).ToList();
                    }
                    else if (!String.IsNullOrWhiteSpace(Architectures))
                    {
                        AllArchNames = Architectures.Split('+').ToList();
                    }
                    else
                    {
                        AllArchNames = new List <string>();
                    }

                    // Check whether this platform should only be used for content based projects
                    EProjectType ProjectType = ContentOnlyPlatforms.Contains(CodeTargetPlatform) ? EProjectType.Content : EProjectType.Any;

                    // Allow Content only platforms to be shown as options in all projects
                    bool bCanBeDisplayed = ProjectType == EProjectType.Content;
                    foreach (UnrealTargetConfiguration CodeTargetConfiguration in Enum.GetValues(typeof(UnrealTargetConfiguration)))
                    {
                        // Need to check for development receipt as we use that for the Engine code in DebugGame
                        UnrealTargetConfiguration EngineConfiguration = (CodeTargetConfiguration == UnrealTargetConfiguration.DebugGame) ? UnrealTargetConfiguration.Development : CodeTargetConfiguration;
                        string ReceiptFileName = TargetReceipt.GetDefaultPath(OutputEnginePath, "UE4Game", CodeTargetPlatform, EngineConfiguration, Architecture);

                        if (File.Exists(ReceiptFileName))
                        {
                            // Strip the output folder so that this can be used on any machine
                            ReceiptFileName = new FileReference(ReceiptFileName).MakeRelativeTo(new DirectoryReference(OutputDir));

                            // If we have pre-compiled architectures for this platform then add an entry for each of these -
                            // there isn't a receipt for each architecture like some other platforms
                            if (AllArchNames.Count > 0)
                            {
                                foreach (string Arch in AllArchNames)
                                {
                                    InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, TargetRules.TargetType.Game, Arch, ReceiptFileName, ProjectType, bCanBeDisplayed));
                                }
                            }
                            else
                            {
                                InstalledConfigs.Add(new InstalledPlatformInfo.InstalledPlatformConfiguration(CodeTargetConfiguration, CodeTargetPlatform, TargetRules.TargetType.Game, Architecture, ReceiptFileName, ProjectType, bCanBeDisplayed));
                            }
                        }
                    }
                }
            }

            UnrealBuildTool.InstalledPlatformInfo.WriteConfigFileEntries(InstalledConfigs, ref IniLines);

            if (!String.IsNullOrEmpty(AnalyticsTypeOverride))
            {
                // Write Custom Analytics type setting
                IniLines.Add("");
                IniLines.Add("[Analytics]");
                IniLines.Add(String.Format("UE4TypeOverride=\"{0}\"", AnalyticsTypeOverride));
            }

            // Make sure we can write to the the config file
            File.SetAttributes(OutputBaseEnginePath, OutputAttributes & ~FileAttributes.ReadOnly);
            File.AppendAllLines(OutputBaseEnginePath, IniLines);
            File.SetAttributes(OutputBaseEnginePath, OutputAttributes);
        }
        public CsvRecordService(FileReference fileReference)
        {
            FileReference = fileReference;

            CsvUtility.ConstructTextSchema(CsvFolder, CsvNamePart);
        }
    /// <summary>
    /// Stage a single file to its default location
    /// </summary>
    /// <param name="FileType">The type of file being staged</param>
    /// <param name="InputFile">Path to the file</param>
    public void StageFile(StagedFileType FileType, FileReference InputFile)
    {
        StagedFileReference OutputFile = GetStagedFileLocation(InputFile);

        StageFile(FileType, InputFile, OutputFile);
    }
Beispiel #49
0
 /// <summary>
 /// Runs UpdateGameProject commandlet.
 /// </summary>
 /// <param name="ProjectName">Project name.</param>
 /// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param>
 /// <param name="Parameters">List of additional parameters.</param>
 public static void UpdateGameProjectCommandlet(FileReference ProjectName, string UE4Exe = "UE4Editor-Cmd.exe", string Parameters = "")
 {
     RunCommandlet(ProjectName, UE4Exe, "UpdateGameProject", Parameters);
 }
Beispiel #50
0
        /// <summary>
        /// Runs a commandlet using Engine/Binaries/Win64/UE4Editor-Cmd.exe.
        /// </summary>
        /// <param name="ProjectFile">Project name.</param>
        /// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param>
        /// <param name="Commandlet">Commandlet name.</param>
        /// <param name="Parameters">Command line parameters (without -run=)</param>
        public static void RunCommandlet(FileReference ProjectName, string UE4Exe, string Commandlet, string Parameters = null)
        {
            Log("Running UE4Editor {0} for project {1}", Commandlet, ProjectName);

            var CWD = Path.GetDirectoryName(UE4Exe);

            string EditorExe = UE4Exe;

            if (String.IsNullOrEmpty(CWD))
            {
                EditorExe = HostPlatform.Current.GetUE4ExePath(UE4Exe);
                CWD       = CombinePaths(CmdEnv.LocalRoot, HostPlatform.Current.RelativeBinariesFolder);
            }

            PushDir(CWD);

            DateTime StartTime = DateTime.UtcNow;

            string LocalLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.EngineSavedFolder, Commandlet));

            Log("Commandlet log file is {0}", LocalLogFile);
            string Args = String.Format(
                "{0} -run={1} {2} -abslog={3} -stdout -CrashForUAT -unattended {5}{4}",
                (ProjectName == null) ? "" : CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName.FullName),
                Commandlet,
                String.IsNullOrEmpty(Parameters) ? "" : Parameters,
                CommandUtils.MakePathSafeToUseWithCommandLine(LocalLogFile),
                IsBuildMachine ? "-buildmachine" : "",
                (GlobalCommandLine.Verbose || GlobalCommandLine.AllowStdOutLogVerbosity) ? "-AllowStdOutLogVerbosity " : ""
                );
            ERunOptions Opts = ERunOptions.Default;

            if (GlobalCommandLine.UTF8Output)
            {
                Args += " -UTF8Output";
                Opts |= ERunOptions.UTF8Output;
            }
            var RunResult = Run(EditorExe, Args, Options: Opts, Identifier: Commandlet);

            PopDir();

            // If we're running on a Mac, dump all the *.crash files that were generated while the editor was running.
            if (HostPlatform.Current.HostEditorPlatform == UnrealTargetPlatform.Mac)
            {
                // If the exit code indicates the main process crashed, introduce a small delay because the crash report is written asynchronously.
                // If we exited normally, still check without waiting in case SCW or some other child process crashed.
                if (RunResult.ExitCode > 128)
                {
                    CommandUtils.Log("Pausing before checking for crash logs...");
                    Thread.Sleep(10 * 1000);
                }

                // Create a list of directories containing crash logs, and add the system log folder
                List <string> CrashDirs = new List <string>();
                CrashDirs.Add("/Library/Logs/DiagnosticReports");

                // Add the user's log directory too
                string HomeDir = Environment.GetEnvironmentVariable("HOME");
                if (!String.IsNullOrEmpty(HomeDir))
                {
                    CrashDirs.Add(Path.Combine(HomeDir, "Library/Logs/DiagnosticReports"));
                }

                // Check each directory for crash logs
                List <FileInfo> CrashFileInfos = new List <FileInfo>();
                foreach (string CrashDir in CrashDirs)
                {
                    try
                    {
                        DirectoryInfo CrashDirInfo = new DirectoryInfo(CrashDir);
                        if (CrashDirInfo.Exists)
                        {
                            CrashFileInfos.AddRange(CrashDirInfo.EnumerateFiles("*.crash", SearchOption.TopDirectoryOnly).Where(x => x.LastWriteTimeUtc >= StartTime));
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // Not all account types can access /Library/Logs/DiagnosticReports
                    }
                }

                // Dump them all to the log
                foreach (FileInfo CrashFileInfo in CrashFileInfos)
                {
                    // snmpd seems to often crash (suspect due to it being starved of CPU cycles during cooks)
                    if (!CrashFileInfo.Name.StartsWith("snmpd_"))
                    {
                        CommandUtils.Log("Found crash log - {0}", CrashFileInfo.FullName);
                        try
                        {
                            string[] Lines = File.ReadAllLines(CrashFileInfo.FullName);
                            foreach (string Line in Lines)
                            {
                                CommandUtils.Log("Crash: {0}", Line);
                            }
                        }
                        catch (Exception Ex)
                        {
                            CommandUtils.LogWarning("Failed to read file ({0})", Ex.Message);
                        }
                    }
                }
            }

            // Copy the local commandlet log to the destination folder.
            string DestLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.LogFolder, Commandlet));

            if (!CommandUtils.CopyFile_NoExceptions(LocalLogFile, DestLogFile))
            {
                CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, LocalLogFile, DestLogFile);
            }
            string ProjectStatsDirectory = CombinePaths((ProjectName == null)? CombinePaths(CmdEnv.LocalRoot, "Engine") : Path.GetDirectoryName(ProjectName.FullName), "Saved", "Stats");

            if (Directory.Exists(ProjectStatsDirectory))
            {
                string DestCookerStats = CmdEnv.LogFolder;
                foreach (var StatsFile in Directory.EnumerateFiles(ProjectStatsDirectory, "*.csv"))
                {
                    if (!CommandUtils.CopyFile_NoExceptions(StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile))))
                    {
                        CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile)));
                    }
                }
            }
//			else
//			{
//				CommandUtils.LogWarning("Failed to find directory {0} will not save stats", ProjectStatsDirectory);
//			}

            // Whether it was copied correctly or not, delete the local log as it was only a temporary file.
            CommandUtils.DeleteFile_NoExceptions(LocalLogFile);

            // Throw an exception if the execution failed. Draw attention to signal exit codes on Posix systems, rather than just printing the exit code
            if (RunResult.ExitCode != 0)
            {
                string ExitCodeDesc = "";
                if (RunResult.ExitCode > 128 && RunResult.ExitCode < 128 + 32)
                {
                    if (RunResult.ExitCode == 139)
                    {
                        ExitCodeDesc = " (segmentation fault)";
                    }
                    else
                    {
                        ExitCodeDesc = String.Format(" (signal {0})", RunResult.ExitCode - 128);
                    }
                }
                throw new CommandletException(DestLogFile, RunResult.ExitCode, "Editor terminated with exit code {0}{1} while running {2}{3}; see log {4}", RunResult.ExitCode, ExitCodeDesc, Commandlet, (ProjectName == null)? "" : String.Format(" for {0}", ProjectName), DestLogFile);
            }
        }
Beispiel #51
0
    public override void ExecuteBuild()
    {
        // Get the list of platform names
        string[]             FeaturePacks    = ParseParamValue("FeaturePacks").Split(';');
        string               TempDir         = ParseParamValue("TempDir");
        UnrealTargetPlatform HostPlatform    = BuildHostPlatform.Current.Platform;
        string               TargetPlatforms = ParseParamValue("TargetPlatforms");
        string               SavedDir        = ParseParamValue("SavedDir");


        // Get paths to everything within the temporary directory
        string EditorExe       = CommandUtils.GetEditorCommandletExe(TempDir, HostPlatform);
        string RelativePakPath = "Engine/DerivedDataCache/Compressed.ddp";
        string OutputPakFile   = CommandUtils.CombinePaths(TempDir, RelativePakPath);
        string OutputCsvFile   = Path.ChangeExtension(OutputPakFile, ".csv");


        List <string> ProjectPakFiles  = new List <string>();
        List <string> FeaturePackPaths = new List <string>();

        // loop through all the projects first and bail out if one of them doesn't exist.
        foreach (string FeaturePack in FeaturePacks)
        {
            if (!String.IsNullOrWhiteSpace(FeaturePack))
            {
                string FeaturePackPath = CommandUtils.CombinePaths(CommandUtils.RootDirectory.FullName, FeaturePack);
                if (!CommandUtils.FileExists(FeaturePackPath))
                {
                    throw new AutomationException("Could not find project: " + FeaturePack);
                }
                FeaturePackPaths.Add(FeaturePackPath);
            }
        }

        // loop through all the paths and generate ddc data for them
        foreach (string FeaturePackPath in FeaturePackPaths)
        {
            string            ProjectSpecificPlatforms = TargetPlatforms;
            FileReference     FileRef  = new FileReference(FeaturePackPath);
            string            GameName = FileRef.GetFileNameWithoutAnyExtensions();
            ProjectDescriptor Project  = ProjectDescriptor.FromFile(FileRef);

            if (Project.TargetPlatforms != null && Project.TargetPlatforms.Length > 0)
            {
                // Restrict target platforms used to those specified in project file
                List <string> FilteredPlatforms = new List <string>();

                // Always include the editor platform for cooking
                string EditorCookPlatform = Platform.GetPlatform(HostPlatform).GetEditorCookPlatform();
                if (TargetPlatforms.Contains(EditorCookPlatform))
                {
                    FilteredPlatforms.Add(EditorCookPlatform);
                }

                foreach (string TargetPlatform in Project.TargetPlatforms)
                {
                    if (TargetPlatforms.Contains(TargetPlatform))
                    {
                        FilteredPlatforms.Add(TargetPlatform);
                    }
                }
                if (FilteredPlatforms.Count == 0)
                {
                    LogInformation("Did not find any project specific platforms for FeaturePack {0} out of supplied TargetPlatforms {1}, skipping it!", GameName, ProjectSpecificPlatforms);
                    continue;
                }
                ProjectSpecificPlatforms = CommandUtils.CombineCommandletParams(FilteredPlatforms.Distinct().ToArray());
            }
            CommandUtils.LogInformation("Generating DDC data for {0} on {1}", GameName, ProjectSpecificPlatforms);
            CommandUtils.DDCCommandlet(FileRef, EditorExe, null, ProjectSpecificPlatforms, "-fill -DDC=CreateInstalledEnginePak -ProjectOnly");

            string ProjectPakFile = CommandUtils.CombinePaths(Path.GetDirectoryName(OutputPakFile), String.Format("Compressed-{0}.ddp", GameName));
            CommandUtils.DeleteFile(ProjectPakFile);
            CommandUtils.RenameFile(OutputPakFile, ProjectPakFile);

            string ProjectCsvFile = Path.ChangeExtension(ProjectPakFile, ".csv");
            CommandUtils.DeleteFile(ProjectCsvFile);
            CommandUtils.RenameFile(OutputCsvFile, ProjectCsvFile);

            ProjectPakFiles.Add(Path.GetFileName(ProjectPakFile));
        }

        // Generate DDC for the editor, and merge all the other PAK files in
        CommandUtils.LogInformation("Generating DDC data for engine content on {0}", TargetPlatforms);
        CommandUtils.DDCCommandlet(null, EditorExe, null, TargetPlatforms, "-fill -DDC=CreateInstalledEnginePak " + CommandUtils.MakePathSafeToUseWithCommandLine("-MergePaks=" + String.Join("+", ProjectPakFiles)));

        string SavedPakFile = CommandUtils.CombinePaths(SavedDir, RelativePakPath);

        CommandUtils.CopyFile(OutputPakFile, SavedPakFile);
    }
    public DeploymentContext(
        FileReference RawProjectPathOrName,
        DirectoryReference InLocalRoot,
        DirectoryReference BaseStageDirectory,
        DirectoryReference BaseArchiveDirectory,
        Platform InSourcePlatform,
        Platform InTargetPlatform,
        List <UnrealTargetConfiguration> InTargetConfigurations,
        IEnumerable <StageTarget> InStageTargets,
        List <String> InStageExecutables,
        bool InServer,
        bool InCooked,
        bool InStageCrashReporter,
        bool InStage,
        bool InCookOnTheFly,
        bool InArchive,
        bool InProgram,
        bool IsClientInsteadOfNoEditor,
        bool InForceChunkManifests,
        bool InSeparateDebugStageDirectory
        )
    {
        bStageCrashReporter       = InStageCrashReporter;
        RawProjectPath            = RawProjectPathOrName;
        DedicatedServer           = InServer;
        LocalRoot                 = InLocalRoot;
        CookSourcePlatform        = InSourcePlatform;
        StageTargetPlatform       = InTargetPlatform;
        StageTargetConfigurations = new List <UnrealTargetConfiguration>(InTargetConfigurations);
        StageTargets              = new List <StageTarget>(InStageTargets);
        StageExecutables          = InStageExecutables;
        IsCodeBasedProject        = ProjectUtils.IsCodeBasedUProjectFile(RawProjectPath, StageTargetConfigurations);
        ShortProjectName          = ProjectUtils.GetShortProjectName(RawProjectPath);
        Stage   = InStage;
        Archive = InArchive;

        if (CookSourcePlatform != null && InCooked)
        {
            CookPlatform = CookSourcePlatform.GetCookPlatform(DedicatedServer, IsClientInsteadOfNoEditor);
        }
        else if (CookSourcePlatform != null && InProgram)
        {
            CookPlatform = CookSourcePlatform.GetCookPlatform(false, false);
        }
        else
        {
            CookPlatform = "";
        }

        if (StageTargetPlatform != null && InCooked)
        {
            FinalCookPlatform = StageTargetPlatform.GetCookPlatform(DedicatedServer, IsClientInsteadOfNoEditor);
        }
        else if (StageTargetPlatform != null && InProgram)
        {
            FinalCookPlatform = StageTargetPlatform.GetCookPlatform(false, false);
        }
        else
        {
            FinalCookPlatform = "";
        }

        PlatformDir = StageTargetPlatform.PlatformType.ToString();

        if (BaseStageDirectory != null)
        {
            StageDirectory      = DirectoryReference.Combine(BaseStageDirectory, FinalCookPlatform);
            DebugStageDirectory = InSeparateDebugStageDirectory? DirectoryReference.Combine(BaseStageDirectory, FinalCookPlatform + "Debug") : StageDirectory;
        }

        if (BaseArchiveDirectory != null)
        {
            ArchiveDirectory = DirectoryReference.Combine(BaseArchiveDirectory, FinalCookPlatform);
        }

        if (!FileReference.Exists(RawProjectPath))
        {
            throw new AutomationException("Can't find uproject file {0}.", RawProjectPathOrName);
        }

        EngineRoot  = DirectoryReference.Combine(LocalRoot, "Engine");
        ProjectRoot = RawProjectPath.Directory;

        RelativeProjectRootForStage = new StagedDirectoryReference(ShortProjectName);

        ProjectArgForCommandLines = CommandUtils.MakePathSafeToUseWithCommandLine(RawProjectPath.FullName);
        CookSourceRuntimeRootDir  = RuntimeRootDir = LocalRoot;
        RuntimeProjectRootDir     = ProjectRoot;

        if (Stage)
        {
            CommandUtils.CreateDirectory(StageDirectory.FullName);

            RuntimeRootDir            = StageDirectory;
            CookSourceRuntimeRootDir  = DirectoryReference.Combine(BaseStageDirectory, CookPlatform);
            RuntimeProjectRootDir     = DirectoryReference.Combine(StageDirectory, RelativeProjectRootForStage.Name);
            ProjectArgForCommandLines = CommandUtils.MakePathSafeToUseWithCommandLine(UProjectCommandLineArgInternalRoot + RelativeProjectRootForStage.Name + "/" + ShortProjectName + ".uproject");
        }
        if (Archive)
        {
            CommandUtils.CreateDirectory(ArchiveDirectory.FullName);
        }
        ProjectArgForCommandLines = ProjectArgForCommandLines.Replace("\\", "/");
        ProjectBinariesFolder     = DirectoryReference.Combine(ProjectUtils.GetClientProjectBinariesRootPath(RawProjectPath, TargetType.Game, IsCodeBasedProject), PlatformDir);

        // Build a list of restricted folder names. This will comprise all other restricted platforms, plus standard restricted folder names such as NoRedist, NotForLicensees, etc...
        RestrictedFolderNames.UnionWith(PlatformExports.GetPlatformFolderNames());
        foreach (UnrealTargetPlatform StagePlatform in StageTargetPlatform.GetStagePlatforms())
        {
            RestrictedFolderNames.ExceptWith(PlatformExports.GetIncludedFolderNames(StagePlatform));
        }
        RestrictedFolderNames.UnionWith(FileFilter.RestrictedFolderNames);
        RestrictedFolderNames.Remove(new FileSystemName(StageTargetPlatform.IniPlatformType.ToString()));

        // Read the game config files
        ConfigHierarchy GameConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, ProjectRoot, InTargetPlatform.PlatformType);

        // Read the list of directories to remap when staging
        List <string> RemapDirectoriesList;

        if (GameConfig.GetArray("Staging", "RemapDirectories", out RemapDirectoriesList))
        {
            foreach (string RemapDirectory in RemapDirectoriesList)
            {
                Dictionary <string, string> Properties;
                if (!ConfigHierarchy.TryParse(RemapDirectory, out Properties))
                {
                    throw new AutomationException("Unable to parse '{0}'", RemapDirectory);
                }

                string FromDir;
                if (!Properties.TryGetValue("From", out FromDir))
                {
                    throw new AutomationException("Missing 'From' property in '{0}'", RemapDirectory);
                }

                string ToDir;
                if (!Properties.TryGetValue("To", out ToDir))
                {
                    throw new AutomationException("Missing 'To' property in '{0}'", RemapDirectory);
                }

                RemapDirectories.Add(Tuple.Create(new StagedDirectoryReference(FromDir), new StagedDirectoryReference(ToDir)));
            }
        }

        // Read the list of directories to whitelist from restricted folder warnings
        List <string> WhitelistDirectoriesList;

        if (GameConfig.GetArray("Staging", "WhitelistDirectories", out WhitelistDirectoriesList))
        {
            foreach (string WhitelistDirectory in WhitelistDirectoriesList)
            {
                WhitelistDirectories.Add(new StagedDirectoryReference(WhitelistDirectory));
            }
        }

        // Read the list of files which are whitelisted to be staged
        ReadConfigFileList(GameConfig, "Staging", "WhitelistConfigFiles", WhitelistConfigFiles);
        ReadConfigFileList(GameConfig, "Staging", "BlacklistConfigFiles", BlacklistConfigFiles);

        // If we were configured to use manifests across the whole project, then this platform should use manifests.
        // Otherwise, read whether we are generating chunks from the ProjectPackagingSettings ini.
        if (InForceChunkManifests)
        {
            PlatformUsesChunkManifests = true;
        }
        else
        {
            ConfigHierarchy GameIni  = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, ProjectRoot, InTargetPlatform.PlatformType);
            String          IniPath  = "/Script/UnrealEd.ProjectPackagingSettings";
            bool            bSetting = false;
            if (GameIni.GetBool(IniPath, "bGenerateChunks", out bSetting))
            {
                PlatformUsesChunkManifests = bSetting;
            }
        }
    }
 /// <summary>
 /// Default constructor
 /// </summary>
 public CompileEnvironment(FileReference InCompiler, CompilerType InCompilerType)
 {
     Compiler     = InCompiler;
     CompilerType = InCompilerType;
 }
    public int ArchiveFiles(string InPath, string Wildcard = "*", bool bRecursive = true, string[] ExcludeWildcard = null, string NewPath = null)
    {
        int FilesAdded = 0;

        if (CommandUtils.DirectoryExists(InPath))
        {
            var All = CommandUtils.FindFiles(Wildcard, bRecursive, InPath);

            var Exclude = new HashSet <string>();
            if (ExcludeWildcard != null)
            {
                foreach (var Excl in ExcludeWildcard)
                {
                    var Remove = CommandUtils.FindFiles(Excl, bRecursive, InPath);
                    foreach (var File in Remove)
                    {
                        Exclude.Add(CommandUtils.CombinePaths(File));
                    }
                }
            }
            foreach (var AllFile in All)
            {
                var FileToCopy = CommandUtils.CombinePaths(AllFile);
                if (Exclude.Contains(FileToCopy))
                {
                    continue;
                }

                if (!bIsCombiningMultiplePlatforms)
                {
                    FileReference InputFile = new FileReference(FileToCopy);

                    bool OtherPlatform = false;
                    foreach (UnrealTargetPlatform Plat in Enum.GetValues(typeof(UnrealTargetPlatform)))
                    {
                        if (Plat != StageTargetPlatform.PlatformType && Plat != UnrealTargetPlatform.Unknown)
                        {
                            var Search = FileToCopy;
                            if (InputFile.IsUnderDirectory(LocalRoot))
                            {
                                Search = InputFile.MakeRelativeTo(LocalRoot);
                            }
                            else if (InputFile.IsUnderDirectory(ProjectRoot))
                            {
                                Search = InputFile.MakeRelativeTo(ProjectRoot);
                            }
                            if (Search.IndexOf(CommandUtils.CombinePaths("/" + Plat.ToString() + "/"), 0, StringComparison.InvariantCultureIgnoreCase) >= 0)
                            {
                                OtherPlatform = true;
                                break;
                            }
                        }
                    }
                    if (OtherPlatform)
                    {
                        continue;
                    }
                }

                string Dest;
                if (!FileToCopy.StartsWith(InPath))
                {
                    throw new AutomationException("Can't archive {0}; it was supposed to start with {1}", FileToCopy, InPath);
                }

                // If the specified a new directory, first we deal with that, then apply the other things
                // this is used to collapse the sandbox, among other things
                if (NewPath != null)
                {
                    Dest = FileToCopy.Substring(InPath.Length);
                    if (Dest.StartsWith("/") || Dest.StartsWith("\\"))
                    {
                        Dest = Dest.Substring(1);
                    }
                    Dest = CommandUtils.CombinePaths(NewPath, Dest);
                }
                else
                {
                    Dest = FileToCopy.Substring(InPath.Length);
                }

                if (Dest.StartsWith("/") || Dest.StartsWith("\\"))
                {
                    Dest = Dest.Substring(1);
                }

                if (ArchivedFiles.ContainsKey(FileToCopy))
                {
                    if (ArchivedFiles[FileToCopy] != Dest)
                    {
                        throw new AutomationException("Can't archive {0}: it was already in the files to archive with a different destination '{1}'", FileToCopy, Dest);
                    }
                }
                else
                {
                    ArchivedFiles.Add(FileToCopy, Dest);
                }

                FilesAdded++;
            }
        }

        return(FilesAdded);
    }
		public static ECompilationResult RunUBT(string[] Arguments, FileReference ProjectFile)
		{
			bool bSuccess = true;


			DateTime RunUBTInitStartTime = DateTime.UtcNow;


			// Reset global configurations
			ActionGraph.ResetAllActions();

			// We need to allow the target platform to perform the 'reset' as well...
			UnrealTargetPlatform ResetPlatform = UnrealTargetPlatform.Unknown;
			UnrealTargetConfiguration ResetConfiguration;
			UEBuildTarget.ParsePlatformAndConfiguration(Arguments, out ResetPlatform, out ResetConfiguration);
			UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatform(ResetPlatform);
			UEBuildPlatformContext BuildPlatformContext = BuildPlatform.CreateContext(ProjectFile);
			BuildPlatformContext.ResetBuildConfiguration(ResetConfiguration);

			// now that we have the platform, we can set the intermediate path to include the platform/architecture name
			BuildConfiguration.PlatformIntermediateFolder = Path.Combine(BuildConfiguration.BaseIntermediateFolder, ResetPlatform.ToString(), BuildPlatformContext.GetActiveArchitectureFolderName());

			string ExecutorName = "Unknown";
			ECompilationResult BuildResult = ECompilationResult.Succeeded;

			UEToolChain ToolChain = BuildPlatformContext.CreateToolChainForDefaultCppPlatform();

			Thread CPPIncludesThread = null;

			try
			{
				List<string[]> TargetSettings = ParseCommandLineFlags(Arguments);

				int ArgumentIndex;
				// action graph implies using the dependency resolve cache
				bool GeneratingActionGraph = Utils.ParseCommandLineFlag(Arguments, "-graph", out ArgumentIndex);
				if (GeneratingActionGraph)
				{
					BuildConfiguration.bUseIncludeDependencyResolveCache = true;
				}

				bool CreateStub = Utils.ParseCommandLineFlag(Arguments, "-nocreatestub", out ArgumentIndex);
				if (CreateStub || (String.IsNullOrEmpty(Environment.GetEnvironmentVariable("uebp_LOCAL_ROOT")) && BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac))
				{
					BuildConfiguration.bCreateStubIPA = false;
				}


				if (BuildConfiguration.bPrintPerformanceInfo)
				{
					double RunUBTInitTime = (DateTime.UtcNow - RunUBTInitStartTime).TotalSeconds;
					Log.TraceInformation("RunUBT initialization took " + RunUBTInitTime + "s");
				}

				List<TargetDescriptor> TargetDescs = new List<TargetDescriptor>();
				{
					DateTime TargetDescstStartTime = DateTime.UtcNow;

					foreach (string[] TargetSetting in TargetSettings)
					{
						TargetDescs.AddRange(UEBuildTarget.ParseTargetCommandLine(TargetSetting, ref ProjectFile));
					}

					if (BuildConfiguration.bPrintPerformanceInfo)
					{
						double TargetDescsTime = (DateTime.UtcNow - TargetDescstStartTime).TotalSeconds;
						Log.TraceInformation("Target descriptors took " + TargetDescsTime + "s");
					}
				}

				if (UnrealBuildTool.bIsInvalidatingMakefilesOnly)
				{
					Log.TraceInformation("Invalidating makefiles only in this run.");
					if (TargetDescs.Count != 1)
					{
						Log.TraceError("You have to provide one target name for makefile invalidation.");
						return ECompilationResult.OtherCompilationError;
					}

					InvalidateMakefiles(TargetDescs[0]);
					return ECompilationResult.Succeeded;
				}

				bool bNoHotReload = UnrealBuildTool.CommandLineContains("-NoHotReload");
				UEBuildConfiguration.bHotReloadFromIDE = !bNoHotReload && UEBuildConfiguration.bAllowHotReloadFromIDE && TargetDescs.Count == 1 && !TargetDescs[0].bIsEditorRecompile && ShouldDoHotReloadFromIDE(TargetDescs[0]);
				bool bIsHotReload = !bNoHotReload && (UEBuildConfiguration.bHotReloadFromIDE || (TargetDescs.Count == 1 && TargetDescs[0].OnlyModules.Count > 0 && TargetDescs[0].ForeignPlugins.Count == 0));
				TargetDescriptor HotReloadTargetDesc = bIsHotReload ? TargetDescs[0] : null;

				if (ProjectFileGenerator.bGenerateProjectFiles)
				{
					// Create empty timestamp file to record when was the last time we regenerated projects.
					Directory.CreateDirectory(Path.GetDirectoryName(ProjectFileGenerator.ProjectTimestampFile));
					File.Create(ProjectFileGenerator.ProjectTimestampFile).Dispose();
				}

				if (!ProjectFileGenerator.bGenerateProjectFiles)
				{
					if (BuildConfiguration.bUseUBTMakefiles)
					{
						// Only the modular editor and game targets will share build products.  Unfortunately, we can't determine at
						// at this point whether we're dealing with modular or monolithic game binaries, so we opt to always invalidate
						// cached includes if the target we're switching to is either a game target (has project file) or "UE4Editor".
						bool bMightHaveSharedBuildProducts = 
							ProjectFile != null ||	// Is this a game? (has a .uproject file for the target)
							TargetDescs[ 0 ].TargetName.Equals( "UE4Editor", StringComparison.InvariantCultureIgnoreCase );	// Is the engine?
						if( bMightHaveSharedBuildProducts )
						{
							bool bIsBuildingSameTargetsAsLastTime = false;

							string TargetCollectionName = MakeTargetCollectionName(TargetDescs);

							string LastBuiltTargetsFileName = bIsHotReload ? "HotReloadLastBuiltTargets.txt" : "LastBuiltTargets.txt";
							string LastBuiltTargetsFilePath = Path.Combine(BuildConfiguration.BaseIntermediatePath, LastBuiltTargetsFileName);
							if (File.Exists(LastBuiltTargetsFilePath) && Utils.ReadAllText(LastBuiltTargetsFilePath) == TargetCollectionName)
							{
								// @todo ubtmake: Because we're using separate files for hot reload vs. full compiles, it's actually possible that includes will
								// become out of date without us knowing if the developer ping-pongs between hot reloading target A and building target B normally.
								// To fix this we can not use a different file name for last built targets, but the downside is slower performance when
								// performing the first hot reload after compiling normally (forces full include dependency scan)
								bIsBuildingSameTargetsAsLastTime = true;
							}

							// Save out the name of the targets we're building
							if (!bIsBuildingSameTargetsAsLastTime)
							{
								Directory.CreateDirectory(Path.GetDirectoryName(LastBuiltTargetsFilePath));
								File.WriteAllText(LastBuiltTargetsFilePath, TargetCollectionName, Encoding.UTF8);
							}

							if (!bIsBuildingSameTargetsAsLastTime)
							{
								// Can't use super fast include checking unless we're building the same set of targets as last time, because
								// we might not know about all of the C++ include dependencies for already-up-to-date shared build products
								// between the targets
								bNeedsFullCPPIncludeRescan = true;
								Log.TraceInformation("Performing full C++ include scan ({0} a new target)", bIsHotReload ? "hot reloading" : "building");
							}
						}
					}
				}



				UBTMakefile UBTMakefile = null;
				{
					// If we're generating project files, then go ahead and wipe out the existing UBTMakefile for every target, to make sure that
					// it gets a full dependency scan next time.
					// NOTE: This is just a safeguard and doesn't have to be perfect.  We also check for newer project file timestamps in LoadUBTMakefile()
					FileReference UBTMakefilePath = UnrealBuildTool.GetUBTMakefilePath(TargetDescs);
					if (ProjectFileGenerator.bGenerateProjectFiles)	// @todo ubtmake: This is only hit when generating IntelliSense for project files.  Probably should be done right inside ProjectFileGenerator.bat
					{													// @todo ubtmake: Won't catch multi-target cases as GPF always builds one target at a time for Intellisense
						// Delete the UBTMakefile
						if (UBTMakefilePath.Exists())
						{
							UEBuildTarget.CleanFile(UBTMakefilePath.FullName);
						}
					}

					// Make sure the gather phase is executed if we're not actually building anything
					if (ProjectFileGenerator.bGenerateProjectFiles || UEBuildConfiguration.bGenerateManifest || UEBuildConfiguration.bCleanProject || BuildConfiguration.bXGEExport || UEBuildConfiguration.bGenerateExternalFileList || GeneratingActionGraph)
					{
						UnrealBuildTool.bIsGatheringBuild_Unsafe = true;
					}

					// Were we asked to run in 'assembler only' mode?  If so, let's check to see if that's even possible by seeing if
					// we have a valid UBTMakefile already saved to disk, ready for us to load.
					if (UnrealBuildTool.bIsAssemblingBuild_Unsafe && !UnrealBuildTool.bIsGatheringBuild_Unsafe)
					{
						// @todo ubtmake: Mildly terrified of BuildConfiguration/UEBuildConfiguration globals that were set during the Prepare phase but are not set now.  We may need to save/load all of these, otherwise
						//		we'll need to call SetupGlobalEnvironment on all of the targets (maybe other stuff, too.  See PreBuildStep())

						// Try to load the UBTMakefile.  It will only be loaded if it has valid content and is not determined to be out of date.    
						string ReasonNotLoaded;
						UBTMakefile = LoadUBTMakefile(UBTMakefilePath, ProjectFile, out ReasonNotLoaded);

						// Invalid makefile if only modules have changed
						if (UBTMakefile != null && !TargetDescs.SelectMany(x => x.OnlyModules)
								.Select(x => new Tuple<string, bool>(x.OnlyModuleName.ToLower(), string.IsNullOrWhiteSpace(x.OnlyModuleSuffix)))
								.SequenceEqual(
									UBTMakefile.Targets.SelectMany(x => x.OnlyModules)
									.Select(x => new Tuple<string, bool>(x.OnlyModuleName.ToLower(), string.IsNullOrWhiteSpace(x.OnlyModuleSuffix)))
								)
							)
						{
							UBTMakefile = null;
							ReasonNotLoaded = "modules to compile have changed";
						}

						// Invalid makefile if foreign plugins have changed
						if (UBTMakefile != null && !TargetDescs.SelectMany(x => x.ForeignPlugins)
								.Select(x => new Tuple<string, bool>(x.FullName.ToLower(), string.IsNullOrWhiteSpace(x.FullName)))
								.SequenceEqual(
									UBTMakefile.Targets.SelectMany(x => x.ForeignPlugins)
									.Select(x => new Tuple<string, bool>(x.FullName.ToLower(), string.IsNullOrWhiteSpace(x.FullName)))
								)
							)
						{
							UBTMakefile = null;
							ReasonNotLoaded = "foreign plugins have changed";
						}

						if (UBTMakefile == null)
						{
							// If the Makefile couldn't be loaded, then we're not going to be able to continue in "assembler only" mode.  We'll do both
							// a 'gather' and 'assemble' in the same run.  This will take a while longer, but subsequent runs will be fast!
							UnrealBuildTool.bIsGatheringBuild_Unsafe = true;

							FileItem.ClearCaches();

							Log.TraceInformation("Creating makefile for {0}{1}{2} ({3})",
								bIsHotReload ? "hot reloading " : "",
								TargetDescs[0].TargetName,
								TargetDescs.Count > 1 ? (" (and " + (TargetDescs.Count - 1).ToString() + " more)") : "",
								ReasonNotLoaded);

							// Invalidate UHT makefiles too
							ExternalExecution.bInvalidateUHTMakefile = true;
						}
					}

					// OK, after this point it is safe to access the UnrealBuildTool.IsGatheringBuild and UnrealBuildTool.IsAssemblingBuild properties.
					// These properties will not be changing again during this session/
					bIsSafeToCheckIfGatheringOrAssemblingBuild = true;
				}


				List<UEBuildTarget> Targets;
				if (UBTMakefile != null && !IsGatheringBuild && IsAssemblingBuild)
				{
					// If we've loaded a makefile, then we can fill target information from this file!
					Targets = UBTMakefile.Targets;
				}
				else
				{
					DateTime TargetInitStartTime = DateTime.UtcNow;

					Targets = new List<UEBuildTarget>();
					foreach (TargetDescriptor TargetDesc in TargetDescs)
					{
						UEBuildTarget Target = UEBuildTarget.CreateTarget(TargetDesc);
						if ((Target == null) && (UEBuildConfiguration.bCleanProject))
						{
							continue;
						}
						Targets.Add(Target);
					}

					if (BuildConfiguration.bPrintPerformanceInfo)
					{
						double TargetInitTime = (DateTime.UtcNow - TargetInitStartTime).TotalSeconds;
						Log.TraceInformation("Target init took " + TargetInitTime + "s");
					}
				}

				// Build action lists for all passed in targets.
				List<FileItem> OutputItemsForAllTargets = new List<FileItem>();
				Dictionary<string, List<UHTModuleInfo>> TargetNameToUObjectModules = new Dictionary<string, List<UHTModuleInfo>>(StringComparer.InvariantCultureIgnoreCase);
				foreach (UEBuildTarget Target in Targets)
				{
					if (bIsHotReload)
					{
						// Don't produce new DLLs if there's been no code changes
						UEBuildConfiguration.bSkipLinkingWhenNothingToCompile = true;
						Log.TraceInformation("Compiling game modules for hot reload");
					}

					// When in 'assembler only' mode, we'll load this cache later on a worker thread.  It takes a long time to load!
					if (!(!UnrealBuildTool.IsGatheringBuild && UnrealBuildTool.IsAssemblingBuild))
					{
						// Load the direct include dependency cache.
						CPPEnvironment.IncludeDependencyCache.Add(Target, DependencyCache.Create(DependencyCache.GetDependencyCachePathForTarget(Target)));
					}

					// We don't need this dependency cache in 'gather only' mode
					if (BuildConfiguration.bUseUBTMakefiles &&
						!(UnrealBuildTool.IsGatheringBuild && !UnrealBuildTool.IsAssemblingBuild))
					{
						// Load the cache that contains the list of flattened resolved includes for resolved source files
						// @todo ubtmake: Ideally load this asynchronously at startup and only block when it is first needed and not finished loading
						CPPEnvironment.FlatCPPIncludeDependencyCache.Add(Target, FlatCPPIncludeDependencyCache.Create(Target));
					}

					if (UnrealBuildTool.IsGatheringBuild)
					{
						List<FileItem> TargetOutputItems;
						List<UHTModuleInfo> TargetUObjectModules;
						BuildResult = Target.Build(ToolChain, out TargetOutputItems, out TargetUObjectModules);
						if (BuildResult != ECompilationResult.Succeeded)
						{
							break;
						}

						OutputItemsForAllTargets.AddRange(TargetOutputItems);

						// Update mapping of the target name to the list of UObject modules in this target
						TargetNameToUObjectModules[Target.GetTargetName()] = TargetUObjectModules;

						if ((BuildConfiguration.bXGEExport && UEBuildConfiguration.bGenerateManifest) || (!ProjectFileGenerator.bGenerateProjectFiles && !UEBuildConfiguration.bGenerateManifest && !UEBuildConfiguration.bCleanProject))
						{
							// Generate an action graph if we were asked to do that.  The graph generation needs access to the include dependency cache, so
							// we generate it before saving and cleaning that up.
							if (GeneratingActionGraph)
							{
								// The graph generation feature currently only works with a single target at a time.  This is because of how we need access
								// to include dependencies for the target, but those aren't kept around as we process multiple targets
								if (TargetSettings.Count != 1)
								{
									throw new BuildException("ERROR: The '-graph' option only works with a single target at a time");
								}
								ActionGraph.FinalizeActionGraph();
								List<Action> ActionsToExecute = ActionGraph.AllActions;

								ActionGraph.ActionGraphVisualizationType VisualizationType = ActionGraph.ActionGraphVisualizationType.OnlyCPlusPlusFilesAndHeaders;
								ActionGraph.SaveActionGraphVisualization(Target, Path.Combine(BuildConfiguration.BaseIntermediatePath, Target.GetTargetName() + ".gexf"), Target.GetTargetName(), VisualizationType, ActionsToExecute);
							}
						}
					}
				}

				if (BuildResult == ECompilationResult.Succeeded &&
					(
						(BuildConfiguration.bXGEExport && UEBuildConfiguration.bGenerateManifest) ||
						(!GeneratingActionGraph && !ProjectFileGenerator.bGenerateProjectFiles && !UEBuildConfiguration.bGenerateManifest && !UEBuildConfiguration.bCleanProject && !UEBuildConfiguration.bGenerateExternalFileList && !UEBuildConfiguration.bListBuildFolders)
					))
				{
					if (UnrealBuildTool.IsGatheringBuild)
					{
						ActionGraph.FinalizeActionGraph();

						UBTMakefile = new UBTMakefile();
						UBTMakefile.AllActions = ActionGraph.AllActions;

						// For now simply treat all object files as the root target.
						{
							HashSet<Action> PrerequisiteActionsSet = new HashSet<Action>();
							foreach (FileItem OutputItem in OutputItemsForAllTargets)
							{
								ActionGraph.GatherPrerequisiteActions(OutputItem, ref PrerequisiteActionsSet);
							}
							UBTMakefile.PrerequisiteActions = PrerequisiteActionsSet.ToArray();
						}

						foreach (System.Collections.DictionaryEntry EnvironmentVariable in Environment.GetEnvironmentVariables())
						{
							UBTMakefile.EnvironmentVariables.Add(Tuple.Create((string)EnvironmentVariable.Key, (string)EnvironmentVariable.Value));
						}
						UBTMakefile.TargetNameToUObjectModules = TargetNameToUObjectModules;
						UBTMakefile.Targets = Targets;
						UBTMakefile.SourceFileWorkingSet = Unity.SourceFileWorkingSet;
						UBTMakefile.CandidateSourceFilesForWorkingSet = Unity.CandidateSourceFilesForWorkingSet;

						if (BuildConfiguration.bUseUBTMakefiles)
						{
							// We've been told to prepare to build, so let's go ahead and save out our action graph so that we can use in a later invocation 
							// to assemble the build.  Even if we are configured to assemble the build in this same invocation, we want to save out the
							// Makefile so that it can be used on subsequent 'assemble only' runs, for the fastest possible iteration times
							// @todo ubtmake: Optimization: We could make 'gather + assemble' mode slightly faster by saving this while busy compiling (on our worker thread)
							SaveUBTMakefile(TargetDescs, UBTMakefile);
						}
					}

					if (UnrealBuildTool.IsAssemblingBuild)
					{
						// If we didn't build the graph in this session, then we'll need to load a cached one
						if (!UnrealBuildTool.IsGatheringBuild && BuildResult.Succeeded())
						{
							ActionGraph.AllActions = UBTMakefile.AllActions;

							// Patch action history for hot reload when running in assembler mode.  In assembler mode, the suffix on the output file will be
							// the same for every invocation on that makefile, but we need a new suffix each time.
							if (bIsHotReload)
							{
								PatchActionHistoryForHotReloadAssembling(HotReloadTargetDesc.OnlyModules);
							}


							foreach (Tuple<string, string> EnvironmentVariable in UBTMakefile.EnvironmentVariables)
							{
								// @todo ubtmake: There may be some variables we do NOT want to clobber.
								Environment.SetEnvironmentVariable(EnvironmentVariable.Item1, EnvironmentVariable.Item2);
							}

							// Execute all the pre-build steps
							foreach(UEBuildTarget Target in Targets)
							{
								if(!Target.ExecuteCustomPreBuildSteps())
								{
									BuildResult = ECompilationResult.OtherCompilationError;
									break;
								}
							}

							// If any of the targets need UHT to be run, we'll go ahead and do that now
							if(BuildResult.Succeeded())
							{
								foreach (UEBuildTarget Target in Targets)
								{
									List<UHTModuleInfo> TargetUObjectModules;
									if (UBTMakefile.TargetNameToUObjectModules.TryGetValue(Target.GetTargetName(), out TargetUObjectModules))
									{
										if (TargetUObjectModules.Count > 0)
										{
											// Execute the header tool
											FileReference ModuleInfoFileName = FileReference.Combine(Target.ProjectIntermediateDirectory, Target.GetTargetName() + ".uhtmanifest");
											ECompilationResult UHTResult = ECompilationResult.OtherCompilationError;
											if (!ExternalExecution.ExecuteHeaderToolIfNecessary(ToolChain, Target, GlobalCompileEnvironment: null, UObjectModules: TargetUObjectModules, ModuleInfoFileName: ModuleInfoFileName, UHTResult: ref UHTResult))
											{
												Log.TraceInformation("UnrealHeaderTool failed for target '" + Target.GetTargetName() + "' (platform: " + Target.Platform.ToString() + ", module info: " + ModuleInfoFileName + ").");
												BuildResult = UHTResult;
												break;
											}
										}
									}
								}
							}
						}

						if (BuildResult.Succeeded())
						{
							// Make sure any old DLL files from in-engine recompiles aren't lying around.  Must be called after the action graph is finalized.
							ActionGraph.DeleteStaleHotReloadDLLs();

							if (!bIsHotReload && String.IsNullOrEmpty(BuildConfiguration.SingleFileToCompile))
							{
								// clean up any stale modules
								foreach (UEBuildTarget Target in Targets)
								{
									if (Target.OnlyModules == null || Target.OnlyModules.Count == 0)
									{
										Target.CleanStaleModules();
									}
								}
							}

							ToolChain.PreBuildSync();

                            // Plan the actions to execute for the build.
                            Dictionary<UEBuildTarget, List<FileItem>> TargetToOutdatedPrerequisitesMap;
                            List<Action> ActionsToExecute = ActionGraph.GetActionsToExecute(UBTMakefile.PrerequisiteActions, Targets, out TargetToOutdatedPrerequisitesMap);

                            // Display some stats to the user.
                            Log.TraceVerbose(
                                    "{0} actions, {1} outdated and requested actions",
                                    ActionGraph.AllActions.Count,
                                    ActionsToExecute.Count
                                    );

							// Cache indirect includes for all outdated C++ files.  We kick this off as a background thread so that it can
							// perform the scan while we're compiling.  It usually only takes up to a few seconds, but we don't want to hurt
							// our best case UBT iteration times for this task which can easily be performed asynchronously
							if (BuildConfiguration.bUseUBTMakefiles && TargetToOutdatedPrerequisitesMap.Count > 0)
							{
								CPPIncludesThread = CreateThreadForCachingCPPIncludes(TargetToOutdatedPrerequisitesMap);
								CPPIncludesThread.Start();
							}

							// If we're not touching any shared files (ie. anything under Engine), allow the build ids to be recycled between applications.
							HashSet<FileReference> OutputFiles = new HashSet<FileReference>(ActionsToExecute.SelectMany(x => x.ProducedItems.Select(y => y.Reference)));
							foreach (UEBuildTarget Target in Targets)
							{
								if(!Target.TryRecycleVersionManifests(OutputFiles))
								{
									Target.InvalidateVersionManifests();
								}
							}

							// Execute the actions.
							string TargetInfoForTelemetry = String.Join("|", Targets.Select(x => String.Format("{0} {1} {2}{3}", x.TargetName, x.Platform, x.Configuration, BuildConfiguration.bUseUnityBuild? "" : " NonUnity")));
							bSuccess = ActionGraph.ExecuteActions(ActionsToExecute, out ExecutorName, TargetInfoForTelemetry, bIsHotReload);

							// if the build succeeded, write the receipts and do any needed syncing
							if (bSuccess)
							{
								if(!BuildConfiguration.bDisableLinking)
								{
									foreach (UEBuildTarget Target in Targets)
									{
										Target.WriteReceipts();
										ToolChain.PostBuildSync(Target);
									}
								}
								if (ActionsToExecute.Count == 0 && UEBuildConfiguration.bSkipLinkingWhenNothingToCompile)
								{
									BuildResult = ECompilationResult.UpToDate;
								}
							}
							else
							{
								BuildResult = ECompilationResult.OtherCompilationError;
							}
						}

						// Execute all the post-build steps
						if(BuildResult.Succeeded())
						{
							foreach(UEBuildTarget Target in Targets)
							{
								if(!Target.ExecuteCustomPostBuildSteps())
								{
									BuildResult = ECompilationResult.OtherCompilationError;
									break;
								}
							}
						}
					}
				}
			}
			catch (BuildException Exception)
			{
				// Output the message only, without the call stack
				Log.TraceInformation(Exception.Message);
				BuildResult = ECompilationResult.OtherCompilationError;
			}
			catch (Exception Exception)
			{
				Log.TraceInformation("ERROR: {0}", Exception);
				BuildResult = ECompilationResult.OtherCompilationError;
			}

			// Wait until our CPPIncludes dependency scanner thread has finished
			if (CPPIncludesThread != null)
			{
				CPPIncludesThread.Join();
			}

			// Save the include dependency cache.
			{
				// NOTE: It's very important that we save the include cache, even if a build exception was thrown (compile error, etc), because we need to make sure that
				//    any C++ include dependencies that we computed for out of date source files are saved.  Remember, the build may fail *after* some build products
				//    are successfully built.  If we didn't save our dependency cache after build failures, source files for those build products that were successsfully
				//    built before the failure would not be considered out of date on the next run, so this is our only chance to cache C++ includes for those files!

				foreach (DependencyCache DependencyCache in CPPEnvironment.IncludeDependencyCache.Values)
				{
					DependencyCache.Save();
				}
				CPPEnvironment.IncludeDependencyCache.Clear();

				foreach (FlatCPPIncludeDependencyCache FlatCPPIncludeDependencyCache in CPPEnvironment.FlatCPPIncludeDependencyCache.Values)
				{
					FlatCPPIncludeDependencyCache.Save();
				}
				CPPEnvironment.FlatCPPIncludeDependencyCache.Clear();
			}

			// Figure out how long we took to execute.
			double BuildDuration = (DateTime.UtcNow - StartTime).TotalSeconds;
			if (ExecutorName == "Local" || ExecutorName == "Distcc" || ExecutorName == "SNDBS")
			{
				Log.WriteLineIf(BuildConfiguration.bLogDetailedActionStats || BuildConfiguration.bPrintDebugInfo,
					LogEventType.Console,
					"Cumulative action seconds ({0} processors): {1:0.00} building projects, {2:0.00} compiling, {3:0.00} creating app bundles, {4:0.00} generating debug info, {5:0.00} linking, {6:0.00} other",
					System.Environment.ProcessorCount,
					TotalBuildProjectTime,
					TotalCompileTime,
					TotalCreateAppBundleTime,
					TotalGenerateDebugInfoTime,
					TotalLinkTime,
					TotalOtherActionsTime
				);

				Log.TraceInformation("Total build time: {0:0.00} seconds", BuildDuration);

				// reset statistics
				TotalBuildProjectTime = 0;
				TotalCompileTime = 0;
				TotalCreateAppBundleTime = 0;
				TotalGenerateDebugInfoTime = 0;
				TotalLinkTime = 0;
				TotalOtherActionsTime = 0;
			}
			else
			{
				if (ExecutorName == "XGE")
				{
					Log.TraceInformation("XGE execution time: {0:0.00} seconds", BuildDuration);
				}
			}

			return BuildResult;
		}
        /// <summary>
        /// Writes a response file which will compile the given source file
        /// </summary>
        /// <param name="ResponseFile">The response file to write to</param>
        /// <param name="SourceFile">The source file to compile</param>
        public void WriteResponseFile(FileReference ResponseFile, FileReference SourceFile)
        {
            using (StreamWriter Writer = new StreamWriter(ResponseFile.FullName))
            {
                foreach (CompileOption Option in Options)
                {
                    if (CompilerType == CompilerType.Clang)
                    {
                        Writer.WriteLine(Option.ToString().Replace('\\', '/'));
                    }
                    else
                    {
                        Writer.WriteLine(Option.ToString());
                    }
                }

                foreach (string Definition in Definitions)
                {
                    if (CompilerType == CompilerType.Clang)
                    {
                        Writer.WriteLine("-D {0}", Utility.QuoteArgument(Definition));
                    }
                    else
                    {
                        Writer.WriteLine("/D {0}", Utility.QuoteArgument(Definition));
                    }
                }

                foreach (DirectoryReference IncludePath in IncludePaths)
                {
                    if (CompilerType == CompilerType.Clang)
                    {
                        Writer.WriteLine("-I {0}", Utility.QuoteArgument(IncludePath.FullName.Replace('\\', '/')));
                    }
                    else
                    {
                        Writer.WriteLine("/I {0}", Utility.QuoteArgument(IncludePath.FullName));
                    }
                }

                foreach (FileReference ForceIncludeFile in ForceIncludeFiles)
                {
                    if (CompilerType == CompilerType.Clang)
                    {
                        Writer.WriteLine("-include {0}", Utility.QuoteArgument(ForceIncludeFile.FullName.Replace('\\', '/')));
                    }
                    else
                    {
                        Writer.WriteLine("/FI{0}", Utility.QuoteArgument(ForceIncludeFile.FullName));
                    }
                }

                if (CompilerType == CompilerType.Clang)
                {
                    Writer.WriteLine(Utility.QuoteArgument(SourceFile.FullName.Replace('\\', '/')));
                }
                else
                {
                    Writer.WriteLine("/Tp\"{0}\"", SourceFile.FullName);
                }
            }
        }
		/// <summary>
		/// Loads a UBTMakefile from disk
		/// </summary>
		/// <param name="MakefilePath">Path to the makefile to load</param>
		/// <param name="ReasonNotLoaded">If the function returns null, this string will contain the reason why</param>
		/// <returns>The loaded makefile, or null if it failed for some reason.  On failure, the 'ReasonNotLoaded' variable will contain information about why</returns>
		static UBTMakefile LoadUBTMakefile(FileReference MakefilePath, FileReference ProjectFile, out string ReasonNotLoaded)
		{
			// Check the directory timestamp on the project files directory.  If the user has generated project files more
			// recently than the UBTMakefile, then we need to consider the file to be out of date
			FileInfo UBTMakefileInfo = new FileInfo(MakefilePath.FullName);
			if (!UBTMakefileInfo.Exists)
			{
				// UBTMakefile doesn't even exist, so we won't bother loading it
				ReasonNotLoaded = "no existing makefile";
				return null;
			}

			// Check the build version
			FileInfo BuildVersionFileInfo = new FileInfo(BuildVersion.GetDefaultFileName());
			if(BuildVersionFileInfo.Exists && UBTMakefileInfo.LastWriteTime.CompareTo(BuildVersionFileInfo.LastWriteTime) < 0)
			{
				Log.TraceVerbose("Existing makefile is older than Build.version, ignoring it");
				ReasonNotLoaded = "Build.version is newer";
				return null;
			}

			// @todo ubtmake: This will only work if the directory timestamp actually changes with every single GPF.  Force delete existing files before creating new ones?  Eh... really we probably just want to delete + create a file in that folder
			//			-> UPDATE: Seems to work OK right now though on Windows platform, maybe due to GUID changes
			// @todo ubtmake: Some platforms may not save any files into this folder.  We should delete + generate a "touch" file to force the directory timestamp to be updated (or just check the timestamp file itself.  We could put it ANYWHERE, actually)

			// Installed Build doesn't need to check engine projects for outdatedness
			if (!UnrealBuildTool.IsEngineInstalled())
			{
				if (ProjectFileGenerator.IntermediateProjectFilesPath.Exists())
				{
					DateTime EngineProjectFilesLastUpdateTime = new FileInfo(ProjectFileGenerator.ProjectTimestampFile).LastWriteTime;
					if (UBTMakefileInfo.LastWriteTime.CompareTo(EngineProjectFilesLastUpdateTime) < 0)
					{
						// Engine project files are newer than UBTMakefile
						Log.TraceVerbose("Existing makefile is older than generated engine project files, ignoring it");
						ReasonNotLoaded = "project files are newer";
						return null;
					}
				}
			}

			// Check the game project directory too
			if (ProjectFile != null)
			{
				string ProjectFilename = ProjectFile.FullName;
				FileInfo ProjectFileInfo = new FileInfo(ProjectFilename);
				if (!ProjectFileInfo.Exists || UBTMakefileInfo.LastWriteTime.CompareTo(ProjectFileInfo.LastWriteTime) < 0)
				{
					// .uproject file is newer than UBTMakefile
					Log.TraceVerbose("Makefile is older than .uproject file, ignoring it");
					ReasonNotLoaded = ".uproject file is newer";
					return null;
				}

				DirectoryReference MasterProjectRelativePath = ProjectFile.Directory;
				string GameIntermediateProjectFilesPath = Path.Combine(MasterProjectRelativePath.FullName, "Intermediate", "ProjectFiles");
				if (Directory.Exists(GameIntermediateProjectFilesPath))
				{
					DateTime GameProjectFilesLastUpdateTime = new DirectoryInfo(GameIntermediateProjectFilesPath).LastWriteTime;
					if (UBTMakefileInfo.LastWriteTime.CompareTo(GameProjectFilesLastUpdateTime) < 0)
					{
						// Game project files are newer than UBTMakefile
						Log.TraceVerbose("Makefile is older than generated game project files, ignoring it");
						ReasonNotLoaded = "game project files are newer";
						return null;
					}
				}
			}

			// Check to see if UnrealBuildTool.exe was compiled more recently than the UBTMakefile
			DateTime UnrealBuildToolTimestamp = new FileInfo(Assembly.GetExecutingAssembly().Location).LastWriteTime;
			if (UBTMakefileInfo.LastWriteTime.CompareTo(UnrealBuildToolTimestamp) < 0)
			{
				// UnrealBuildTool.exe was compiled more recently than the UBTMakefile
				Log.TraceVerbose("Makefile is older than UnrealBuildTool.exe, ignoring it");
				ReasonNotLoaded = "UnrealBuildTool.exe is newer";
				return null;
			}

			// Check to see if any BuildConfiguration files have changed since the last build
			if (XmlConfigLoader.NewestXmlTimestamp > UBTMakefileInfo.LastWriteTime)
			{
				Log.TraceVerbose("Makefile is older than BuildConfiguration.xml, ignoring it" );
				ReasonNotLoaded = "BuildConfiguration.xml is newer";
				return null;
			}

			UBTMakefile LoadedUBTMakefile = null;

			try
			{
				DateTime LoadUBTMakefileStartTime = DateTime.UtcNow;

				using (FileStream Stream = new FileStream(UBTMakefileInfo.FullName, FileMode.Open, FileAccess.Read))
				{
					BinaryFormatter Formatter = new BinaryFormatter();
					LoadedUBTMakefile = Formatter.Deserialize(Stream) as UBTMakefile;
				}

				if (BuildConfiguration.bPrintPerformanceInfo)
				{
					double LoadUBTMakefileTime = (DateTime.UtcNow - LoadUBTMakefileStartTime).TotalSeconds;
					Log.TraceInformation("LoadUBTMakefile took " + LoadUBTMakefileTime + "s");
				}
			}
			catch (Exception Ex)
			{
				Log.TraceWarning("Failed to read makefile: {0}", Ex.Message);
				ReasonNotLoaded = "couldn't read existing makefile";
				return null;
			}

			if (!LoadedUBTMakefile.IsValidMakefile())
			{
				Log.TraceWarning("Loaded makefile appears to have invalid contents, ignoring it ({0})", UBTMakefileInfo.FullName);
				ReasonNotLoaded = "existing makefile appears to be invalid";
				return null;
			}

			// Check if any of the target's Build.cs files are newer than the makefile
			foreach (UEBuildTarget Target in LoadedUBTMakefile.Targets)
			{
				string TargetCsFilename = Target.TargetCsFilename.FullName;
				if (TargetCsFilename != null)
				{
					FileInfo TargetCsFile = new FileInfo(TargetCsFilename);
					bool bTargetCsFileExists = TargetCsFile.Exists;
					if (!bTargetCsFileExists || TargetCsFile.LastWriteTime > UBTMakefileInfo.LastWriteTime)
					{
						Log.TraceVerbose("{0} has been {1} since makefile was built, ignoring it ({2})", TargetCsFilename, bTargetCsFileExists ? "changed" : "deleted", UBTMakefileInfo.FullName);
						ReasonNotLoaded = string.Format("changes to target files");
						return null;
					}
				}

				IEnumerable<string> BuildCsFilenames = Target.GetAllModuleBuildCsFilenames();
				foreach (string BuildCsFilename in BuildCsFilenames)
				{
					if (BuildCsFilename != null)
					{
						FileInfo BuildCsFile = new FileInfo(BuildCsFilename);
						bool bBuildCsFileExists = BuildCsFile.Exists;
						if (!bBuildCsFileExists || BuildCsFile.LastWriteTime > UBTMakefileInfo.LastWriteTime)
						{
							Log.TraceVerbose("{0} has been {1} since makefile was built, ignoring it ({2})", BuildCsFilename, bBuildCsFileExists ? "changed" : "deleted", UBTMakefileInfo.FullName);
							ReasonNotLoaded = string.Format("changes to module files");
							return null;
						}
					}
				}
			}

			// We do a check to see if any modules' headers have changed which have
			// acquired or lost UHT types.  If so, which should be rare,
			// we'll just invalidate the entire makefile and force it to be rebuilt.
			foreach (UEBuildTarget Target in LoadedUBTMakefile.Targets)
			{
				// Get all H files in processed modules newer than the makefile itself
				HashSet<string> HFilesNewerThanMakefile =
					new HashSet<string>(
						Target.FlatModuleCsData
						.SelectMany(x => x.Value.ModuleSourceFolder != null ? Directory.EnumerateFiles(x.Value.ModuleSourceFolder.FullName, "*.h", SearchOption.AllDirectories) : Enumerable.Empty<string>())
						.Where(y => Directory.GetLastWriteTimeUtc(y) > UBTMakefileInfo.LastWriteTimeUtc)
						.OrderBy(z => z).Distinct()
					);

				// Get all H files in all modules processed in the last makefile build
				HashSet<string> AllUHTHeaders = new HashSet<string>(Target.FlatModuleCsData.Select(x => x.Value).SelectMany(x => x.UHTHeaderNames));

				// Check whether any headers have been deleted. If they have, we need to regenerate the makefile since the module might now be empty. If we don't,
				// and the file has been moved to a different module, we may include stale generated headers.
				foreach (string FileName in AllUHTHeaders)
				{
					if (!File.Exists(FileName))
					{
						Log.TraceVerbose("File processed by UHT was deleted ({0}); invalidating makefile", FileName);
						ReasonNotLoaded = string.Format("UHT file was deleted");
						return null;
					}
				}

				// Makefile is invalid if:
				// * There are any newer files which contain no UHT data, but were previously in the makefile
				// * There are any newer files contain data which needs processing by UHT, but weren't not previously in the makefile
				foreach (string Filename in HFilesNewerThanMakefile)
				{
					bool bContainsUHTData = CPPEnvironment.DoesFileContainUObjects(Filename);
					bool bWasProcessed = AllUHTHeaders.Contains(Filename);
					if (bContainsUHTData != bWasProcessed)
					{
						Log.TraceVerbose("{0} {1} contain UHT types and now {2} , ignoring it ({3})", Filename, bWasProcessed ? "used to" : "didn't", bWasProcessed ? "doesn't" : "does", UBTMakefileInfo.FullName);
						ReasonNotLoaded = string.Format("new files with reflected types");
						return null;
					}
				}
			}

			// If adaptive unity build is enabled, do a check to see if there are any source files that became part of the
			// working set since the Makefile was created (or, source files were removed from the working set.)  If anything
			// changed, then we'll force a new Makefile to be created so that we have fresh unity build blobs.  We always
			// want to make sure that source files in the working set are excluded from those unity blobs (for fastest possible
			// iteration times.)
			if (BuildConfiguration.bUseAdaptiveUnityBuild)
			{
				// Check if any source files in the working set no longer belong in it
				foreach(FileItem SourceFile in LoadedUBTMakefile.SourceFileWorkingSet)
				{
					if(!UnrealBuildTool.ShouldSourceFileBePartOfWorkingSet(SourceFile.AbsolutePath) && File.GetLastWriteTimeUtc(SourceFile.AbsolutePath) > UBTMakefileInfo.LastWriteTimeUtc)
					{
						Log.TraceVerbose("{0} was part of source working set and now is not; invalidating makefile ({1})", SourceFile.AbsolutePath, UBTMakefileInfo.FullName);
						ReasonNotLoaded = string.Format("working set of source files changed");
						return null;
					}
				}

				// Check if any source files that are eligable for being in the working set have been modified
				foreach (FileItem SourceFile in LoadedUBTMakefile.CandidateSourceFilesForWorkingSet)
				{
					if(UnrealBuildTool.ShouldSourceFileBePartOfWorkingSet(SourceFile.AbsolutePath) && File.GetLastWriteTimeUtc(SourceFile.AbsolutePath) > UBTMakefileInfo.LastWriteTimeUtc)
					{
						Log.TraceVerbose("{0} was part of source working set and now is not; invalidating makefile ({1})", SourceFile.AbsolutePath, UBTMakefileInfo.FullName);
						ReasonNotLoaded = string.Format("working set of source files changed");
						return null;
					}
				}
			}

			ReasonNotLoaded = null;
			return LoadedUBTMakefile;
		}
        /// <summary>
        /// Reads an exported XGE task list
        /// </summary>
        /// <param name="TaskListFile">File to read from</param>
        /// <param name="FileToEnvironment">Mapping from source file to compile environment</param>
        public static void ReadTaskList(FileReference TaskListFile, DirectoryReference BaseDir, out Dictionary <FileReference, CompileEnvironment> FileToEnvironment)
        {
            XmlDocument Document = new XmlDocument();

            Document.Load(TaskListFile.FullName);

            // Read the standard include paths from the INCLUDE environment variable in the script
            List <DirectoryReference> StandardIncludePaths = new List <DirectoryReference>();

            foreach (XmlNode Node in Document.SelectNodes("BuildSet/Environments/Environment/Variables/Variable"))
            {
                XmlAttribute NameAttr = Node.Attributes["Name"];
                if (NameAttr != null && String.Compare(NameAttr.InnerText, "INCLUDE") == 0)
                {
                    foreach (string IncludePath in Node.Attributes["Value"].InnerText.Split(';'))
                    {
                        StandardIncludePaths.Add(new DirectoryReference(IncludePath));
                    }
                }
            }

            // Read all the individual compiles
            Dictionary <FileReference, CompileEnvironment> NewFileToEnvironment = new Dictionary <FileReference, CompileEnvironment>();

            foreach (XmlNode Node in Document.SelectNodes("BuildSet/Environments/Environment/Tools/Tool"))
            {
                XmlAttribute ToolPathAttr = Node.Attributes["Path"];
                if (ToolPathAttr != null)
                {
                    // Get the full path to the tool
                    FileReference ToolLocation = new FileReference(ToolPathAttr.InnerText);

                    // Get the compiler type
                    CompilerType CompilerType;
                    if (GetCompilerType(ToolLocation, out CompilerType))
                    {
                        string Name   = Node.Attributes["Name"].InnerText;
                        string Params = Node.Attributes["Params"].InnerText;

                        // Construct the compile environment
                        CompileEnvironment Environment = new CompileEnvironment(ToolLocation, CompilerType);

                        // Parse a list of tokens
                        List <string> Tokens = new List <string>();
                        ParseArgumentTokens(CompilerType, Params, Tokens);

                        // Parse it into a list of options, removing any that don't apply
                        List <FileReference> SourceFiles = new List <FileReference>();
                        List <FileReference> OutputFiles = new List <FileReference>();
                        for (int Idx = 0; Idx < Tokens.Count; Idx++)
                        {
                            if (Tokens[Idx] == "/Fo" || Tokens[Idx] == "/Fp" || Tokens[Idx] == "-o")
                            {
                                OutputFiles.Add(new FileReference(Tokens[++Idx]));
                            }
                            else if (Tokens[Idx].StartsWith("/Fo") || Tokens[Idx].StartsWith("/Fp"))
                            {
                                OutputFiles.Add(new FileReference(Tokens[Idx].Substring(3)));
                            }
                            else if (Tokens[Idx] == "/D" || Tokens[Idx] == "-D")
                            {
                                Environment.Definitions.Add(Tokens[++Idx]);
                            }
                            else if (Tokens[Idx].StartsWith("/D"))
                            {
                                Environment.Definitions.Add(Tokens[Idx].Substring(2));
                            }
                            else if (Tokens[Idx] == "/I" || Tokens[Idx] == "-I")
                            {
                                Environment.IncludePaths.Add(new DirectoryReference(DirectoryReference.Combine(BaseDir, Tokens[++Idx].Replace("//", "/")).FullName.ToLowerInvariant()));
                            }
                            else if (Tokens[Idx].StartsWith("-I"))
                            {
                                Environment.IncludePaths.Add(new DirectoryReference(DirectoryReference.Combine(BaseDir, Tokens[Idx].Substring(2).Replace("//", "/")).FullName.ToLowerInvariant()));
                            }
                            else if (Tokens[Idx].StartsWith("/FI"))
                            {
                                Environment.ForceIncludeFiles.Add(new FileReference(Tokens[Idx].Substring(3)));
                            }
                            else if (Tokens[Idx] == "-include")
                            {
                                Environment.ForceIncludeFiles.Add(new FileReference(Tokens[++Idx]));
                            }
                            else if (Tokens[Idx] == "-Xclang" || Tokens[Idx] == "-target" || Tokens[Idx] == "--target" || Tokens[Idx] == "-x" || Tokens[Idx] == "-o")
                            {
                                Environment.Options.Add(new CompileOption(Tokens[Idx], Tokens[++Idx]));
                            }
                            else if (Tokens[Idx].StartsWith("/") || Tokens[Idx].StartsWith("-"))
                            {
                                Environment.Options.Add(new CompileOption(Tokens[Idx], null));
                            }
                            else
                            {
                                SourceFiles.Add(FileReference.Combine(BaseDir, Tokens[Idx]));
                            }
                        }

                        // Make sure we're not compiling a precompiled header
                        if (!OutputFiles.Any(x => x.HasExtension(".gch")) && !Environment.Options.Any(x => x.Name.StartsWith("/Yc")))
                        {
                            // Add all the standard include paths
                            Environment.IncludePaths.AddRange(StandardIncludePaths);

                            // Add to the output map if there are any source files. Use the extension to distinguish between a source file and linker invocation on Clang.
                            foreach (FileReference SourceFile in SourceFiles)
                            {
                                if (!SourceFile.HasExtension(".a"))
                                {
                                    if (NewFileToEnvironment.ContainsKey(SourceFile))
                                    {
                                        Console.WriteLine("Source file {0} is compiled with multiple environments", SourceFile);
                                    }
                                    else
                                    {
                                        NewFileToEnvironment.Add(SourceFile, Environment);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            FileToEnvironment = NewFileToEnvironment;
        }
	public override void ExecuteBuild()
	{
		// get the project
		var UProjectFileName = ParseParamValue("Project");
		if (UProjectFileName == null)
		{
			throw new AutomationException("Project was not specified via the -project argument.");
		}

		// Get the list of targets
		var TargetList = ParseParamList("Target");
		if (TargetList == null)
		{
			throw new AutomationException("Target was not specified via the -target argument.");
		}

		// get the list of platforms
		var PlatformList = ParseParamList("TargetPlatforms", "Win64");
		List<UnrealTargetPlatform> TargetPlatforms = new List<UnrealTargetPlatform>();
		foreach(string Platform in PlatformList)
		{
			TargetPlatforms.Add((UnrealTargetPlatform)Enum.Parse(typeof(UnrealTargetPlatform), Platform, true));
		}

		// get the list configurations
		var ConfigList = ParseParamList("Config", "Development");
		List<UnrealTargetConfiguration> ConfigsToBuild = new List<UnrealTargetConfiguration>();
		foreach(string Config in ConfigList)
		{
			ConfigsToBuild.Add((UnrealTargetConfiguration)Enum.Parse(typeof(UnrealTargetConfiguration), Config, true));
		}

		// parse any extra parameters
		bool bClean = ParseParam("Clean");
		int WorkingCL = ParseParamInt("P4Change");

        FileReference UProjectFileReference = new FileReference( UProjectFileName);

		// add the targets to the agenda
		// verify the targets and add them to the agenda
		var Properties = ProjectUtils.GetProjectProperties(UProjectFileReference);
		UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda();
		foreach (string Target in TargetList)
		{
			SingleTargetProperties TargetData;
			if (!Properties.Targets.TryGetValue((TargetRules.TargetType)Enum.Parse(typeof(TargetRules.TargetType), Target), out TargetData))
			{
				throw new AutomationException("Project does not support specified target: {0}", Target);
			}

			foreach (UnrealTargetPlatform TargetPlatform in TargetPlatforms)
			{
				if (TargetData.Rules.SupportsPlatform(TargetPlatform))
				{
                    List<UnrealTargetConfiguration> SupportedConfigurations = new List<UnrealTargetConfiguration>();
                    TargetData.Rules.GetSupportedConfigurations(ref SupportedConfigurations, true);

					foreach (UnrealTargetConfiguration TargetConfig in ConfigsToBuild)
					{
						if (SupportedConfigurations.Contains(TargetConfig))
						{
                            Agenda.AddTarget(TargetData.TargetName, TargetPlatform, TargetConfig, UProjectFileReference);
						}
						else
						{
							Log("{0} doesn't support the {1} configuration. It will not be built.", TargetData.TargetName, TargetConfig);
						}
					}
				}
				else
				{
					Log("{0} doesn't support the {1} platform. It will not be built.", TargetData.TargetName, TargetPlatform);
				}
			}
		}


		// build it
		UE4Build Build = new UE4Build(this);
		Build.Build(Agenda, InDeleteBuildProducts: bClean, InUpdateVersionFiles: WorkingCL > 0);

		if (WorkingCL > 0) // only move UAT files if we intend to check in some build products
		{
			Build.AddUATFilesToBuildProducts();
		}
		UE4Build.CheckBuildProducts(Build.BuildProductFiles);

		if (WorkingCL > 0)
		{
			// Sign everything we built
			CodeSign.SignMultipleIfEXEOrDLL(this, Build.BuildProductFiles);

			// Open files for add or edit
			UE4Build.AddBuildProductsToChangelist(WorkingCL, Build.BuildProductFiles);
		}

	}
    public DeploymentContext(
        FileReference RawProjectPathOrName,
        string InLocalRoot,
        string BaseStageDirectory,
        string BaseArchiveDirectory,
        string CookFlavor,
        Platform InSourcePlatform,
        Platform InTargetPlatform,
        List <UnrealTargetConfiguration> InTargetConfigurations,
        IEnumerable <StageTarget> InStageTargets,
        List <String> InStageExecutables,
        bool InServer,
        bool InCooked,
        bool InStageCrashReporter,
        bool InStage,
        bool InCookOnTheFly,
        bool InArchive,
        bool InProgram,
        bool IsClientInsteadOfNoEditor,
        bool bInUseWebsocketNetDriver = false
        )
    {
        bStageCrashReporter       = InStageCrashReporter;
        RawProjectPath            = RawProjectPathOrName;
        DedicatedServer           = InServer;
        LocalRoot                 = CommandUtils.CombinePaths(InLocalRoot);
        CookSourcePlatform        = InSourcePlatform;
        StageTargetPlatform       = InTargetPlatform;
        StageTargetConfigurations = new List <UnrealTargetConfiguration>(InTargetConfigurations);
        StageTargets              = new List <StageTarget>(InStageTargets);
        StageExecutables          = InStageExecutables;
        IsCodeBasedProject        = ProjectUtils.IsCodeBasedUProjectFile(RawProjectPath);
        ShortProjectName          = ProjectUtils.GetShortProjectName(RawProjectPath);
        Stage   = InStage;
        Archive = InArchive;
        bUseWebsocketNetDriver = bInUseWebsocketNetDriver;

        if (CookSourcePlatform != null && InCooked)
        {
            CookPlatform = CookSourcePlatform.GetCookPlatform(DedicatedServer, IsClientInsteadOfNoEditor, CookFlavor);
        }
        else if (CookSourcePlatform != null && InProgram)
        {
            CookPlatform = CookSourcePlatform.GetCookPlatform(false, false, "");
        }
        else
        {
            CookPlatform = "";
        }

        if (StageTargetPlatform != null && InCooked)
        {
            FinalCookPlatform = StageTargetPlatform.GetCookPlatform(DedicatedServer, IsClientInsteadOfNoEditor, CookFlavor);
        }
        else if (StageTargetPlatform != null && InProgram)
        {
            FinalCookPlatform = StageTargetPlatform.GetCookPlatform(false, false, "");
        }
        else
        {
            FinalCookPlatform = "";
        }

        PlatformDir = StageTargetPlatform.PlatformType.ToString();

        StageDirectory   = CommandUtils.CombinePaths(BaseStageDirectory, FinalCookPlatform);
        ArchiveDirectory = CommandUtils.CombinePaths(BaseArchiveDirectory, FinalCookPlatform);

        if (!CommandUtils.FileExists(RawProjectPath.FullName))
        {
            throw new AutomationException("Can't find uproject file {0}.", RawProjectPathOrName);
        }

        ProjectRoot = CommandUtils.CombinePaths(CommandUtils.GetDirectoryName(RawProjectPath.FullName));

        if (!CommandUtils.DirectoryExists(ProjectRoot))
        {
            throw new AutomationException("Project Directory {0} doesn't exist.", ProjectRoot);
        }

        RelativeProjectRootForStage = ShortProjectName;

        ProjectArgForCommandLines = CommandUtils.MakePathSafeToUseWithCommandLine(RawProjectPath.FullName);
        CookSourceRuntimeRootDir  = RuntimeRootDir = LocalRoot;
        RuntimeProjectRootDir     = ProjectRoot;

        RelativeProjectRootForUnrealPak = CommandUtils.CombinePaths(RelativeProjectRootForStage).Replace("\\", "/");
        if (RelativeProjectRootForUnrealPak.StartsWith("/"))
        {
            RelativeProjectRootForUnrealPak = RelativeProjectRootForUnrealPak.Substring(1);
            RelativeProjectRootForStage     = RelativeProjectRootForStage.Substring(1);
        }

        SourceRelativeProjectRoot = RelativeProjectRootForStage; // for foreign projects this doesn't make much sense, but it turns into a noop on staging files
        if (ProjectRoot.StartsWith(LocalRoot, StringComparison.InvariantCultureIgnoreCase))
        {
            SourceRelativeProjectRoot = ProjectRoot.Substring(LocalRoot.Length);
        }
        if (SourceRelativeProjectRoot.StartsWith("/") || SourceRelativeProjectRoot.StartsWith("\\"))
        {
            SourceRelativeProjectRoot = SourceRelativeProjectRoot.Substring(1);
        }

        if (Stage)
        {
            CommandUtils.CreateDirectory(StageDirectory);
            StageProjectRoot = CommandUtils.CombinePaths(StageDirectory, RelativeProjectRootForStage);

            RuntimeRootDir            = StageDirectory;
            CookSourceRuntimeRootDir  = CommandUtils.CombinePaths(BaseStageDirectory, CookPlatform);
            RuntimeProjectRootDir     = StageProjectRoot;
            ProjectArgForCommandLines = CommandUtils.MakePathSafeToUseWithCommandLine(UProjectCommandLineArgInternalRoot + RelativeProjectRootForStage + "/" + ShortProjectName + ".uproject");
        }
        if (Archive)
        {
            CommandUtils.CreateDirectory(ArchiveDirectory);
        }
        ProjectArgForCommandLines = ProjectArgForCommandLines.Replace("\\", "/");
        ProjectBinariesFolder     = CommandUtils.CombinePaths(ProjectUtils.GetClientProjectBinariesRootPath(RawProjectPath, TargetRules.TargetType.Game, IsCodeBasedProject), PlatformDir);
    }