/// <summary>
        /// Creates a text file with the given contents.  If the contents of the text file aren't changed, it won't write the new contents to
        /// the file to avoid causing an action to be considered outdated.
        /// </summary>
        /// <param name="Location">Path to the intermediate file to create</param>
        /// <param name="Contents">Contents of the new file</param>
        /// <returns>File item for the newly created file</returns>
        public static FileItem CreateIntermediateTextFile(FileReference Location, string Contents)
        {
            // Only write the file if its contents have changed.
            if (!FileReference.Exists(Location))
            {
                DirectoryReference.CreateDirectory(Location.Directory);
                FileReference.WriteAllText(Location, Contents, GetEncodingForString(Contents));
            }
            else
            {
                string CurrentContents = Utils.ReadAllText(Location.FullName);
                if (!String.Equals(CurrentContents, Contents, StringComparison.InvariantCultureIgnoreCase))
                {
                    FileReference BackupFile = new FileReference(Location.FullName + ".old");
                    try
                    {
                        Log.TraceLog("Updating {0}: contents have changed. Saving previous version to {1}.", Location, BackupFile);
                        FileReference.Delete(BackupFile);
                        FileReference.Move(Location, BackupFile);
                    }
                    catch (Exception Ex)
                    {
                        Log.TraceWarning("Unable to rename {0} to {1}", Location, BackupFile);
                        Log.TraceLog("{0}", ExceptionUtils.FormatExceptionDetails(Ex));
                    }
                    FileReference.WriteAllText(Location, Contents, GetEncodingForString(Contents));
                }
            }

            // Reset the file info, in case it already knows about the old file
            FileItem Item = GetItemByFileReference(Location);

            Item.ResetCachedInfo();
            return(Item);
        }
Example #2
0
        /// <summary>
        /// Upload all the files in the workspace for the current project
        /// </summary>
        void UploadWorkspace(DirectoryReference TempDir)
        {
            // Path to the scripts to be uploaded
            FileReference ScriptPathsFileName = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncEngineScripts.txt");

            // Read the list of scripts to be uploaded
            List <string> ScriptPaths = new List <string>();

            foreach (string Line in FileReference.ReadAllLines(ScriptPathsFileName))
            {
                string FileToUpload = Line.Trim();
                if (FileToUpload.Length > 0 && FileToUpload[0] != ';')
                {
                    ScriptPaths.Add(FileToUpload);
                }
            }

            // Fixup the line endings
            List <FileReference> TargetFiles = new List <FileReference>();

            foreach (string ScriptPath in ScriptPaths)
            {
                FileReference SourceFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, ScriptPath.TrimStart('/'));
                if (!FileReference.Exists(SourceFile))
                {
                    throw new BuildException("Missing script required for remote upload: {0}", SourceFile);
                }

                FileReference TargetFile = FileReference.Combine(TempDir, SourceFile.MakeRelativeTo(UnrealBuildTool.EngineDirectory));
                if (!FileReference.Exists(TargetFile) || FileReference.GetLastWriteTimeUtc(TargetFile) < FileReference.GetLastWriteTimeUtc(SourceFile))
                {
                    DirectoryReference.CreateDirectory(TargetFile.Directory);
                    string ScriptText = FileReference.ReadAllText(SourceFile);
                    FileReference.WriteAllText(TargetFile, ScriptText.Replace("\r\n", "\n"));
                }
                TargetFiles.Add(TargetFile);
            }

            // Write a file that protects all the scripts from being overridden by the standard engine filters
            FileReference ScriptUploadList = FileReference.Combine(TempDir, "RsyncEngineScripts-Upload.txt");

            using (StreamWriter Writer = new StreamWriter(ScriptUploadList.FullName))
            {
                foreach (string ScriptPath in ScriptPaths)
                {
                    for (int SlashIdx = ScriptPath.IndexOf('/', 1); SlashIdx != -1; SlashIdx = ScriptPath.IndexOf('/', SlashIdx + 1))
                    {
                        Writer.WriteLine("+ {0}", ScriptPath.Substring(0, SlashIdx));
                    }
                    Writer.WriteLine("+ {0}", ScriptPath);
                }
                Writer.WriteLine("protect *");
            }

            // Write a file that protects all the scripts from being overridden by the standard engine filters
            FileReference ScriptProtectList = FileReference.Combine(TempDir, "RsyncEngineScripts-Protect.txt");

            using (StreamWriter Writer = new StreamWriter(ScriptProtectList.FullName))
            {
                foreach (string ScriptPath in ScriptPaths)
                {
                    Writer.WriteLine("protect {0}", ScriptPath);
                }
            }

            // Upload these files to the remote
            List <FileReference> FilterLocations = new List <FileReference>();

            FilterLocations.Add(ScriptUploadList);
            UploadDirectory(TempDir, GetRemotePath(UnrealBuildTool.EngineDirectory), FilterLocations);

            // Upload the engine files
            List <FileReference> EngineFilters = new List <FileReference>();

            EngineFilters.Add(ScriptProtectList);
            EngineFilters.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncEngine.txt"));
            UploadDirectory(UnrealBuildTool.EngineDirectory, GetRemotePath(UnrealBuildTool.EngineDirectory), EngineFilters);

            // Upload the project files
            if (ProjectFile != null && !ProjectFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
            {
                List <FileReference> ProjectFilters = new List <FileReference>();

                FileReference CustomProjectFilter = FileReference.Combine(ProjectFile.Directory, "Build", "Rsync", "RsyncProject.txt");
                if (FileReference.Exists(CustomProjectFilter))
                {
                    ProjectFilters.Add(CustomProjectFilter);
                }
                ProjectFilters.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Build", "Rsync", "RsyncProject.txt"));

                UploadDirectory(ProjectFile.Directory, GetRemotePath(ProjectFile.Directory), ProjectFilters);
            }
        }
 /// <summary>
 ///
 /// </summary>
 public void Save(FileReference InFile)
 {
     DirectoryReference.CreateDirectory(InFile.Directory);
     FileReference.WriteAllText(InFile, fastJSON.JSON.Instance.ToJSON(this, new fastJSON.JSONParameters {
     }));
 }
Example #4
0
        /// <summary>
        /// Execute the command, having obtained the appropriate mutex
        /// </summary>
        /// <param name="Arguments">Command line arguments</param>
        /// <returns>Exit code</returns>
        private int ExecuteInternal(CommandLineArguments Arguments)
        {
            // Read the target info
            WriteMetadataTargetInfo TargetInfo = BinaryFormatterUtils.Load <WriteMetadataTargetInfo>(Arguments.GetFileReference("-Input="));
            bool bNoManifestChanges            = Arguments.HasOption("-NoManifestChanges");
            int  VersionNumber = Arguments.GetInteger("-Version=");

            Arguments.CheckAllArgumentsUsed();

            // Make sure the version number is correct
            if (VersionNumber != CurrentVersionNumber)
            {
                throw new BuildException("Version number to WriteMetadataMode is incorrect (expected {0}, got {1})", CurrentVersionNumber, VersionNumber);
            }

            // Check if we need to set a build id
            TargetReceipt Receipt = TargetInfo.Receipt;

            if (String.IsNullOrEmpty(Receipt.Version.BuildId))
            {
                // Check if there's an existing version file. If it exists, try to merge in any manifests that are valid (and reuse the existing build id)
                BuildVersion PreviousVersion;
                if (TargetInfo.VersionFile != null && BuildVersion.TryRead(TargetInfo.VersionFile, out PreviousVersion))
                {
                    // Check if we can reuse the existing manifests. This prevents unnecessary builds when switching between projects.
                    Dictionary <FileReference, ModuleManifest> PreviousFileToManifest = new Dictionary <FileReference, ModuleManifest>();
                    if (TryRecyclingManifests(PreviousVersion.BuildId, TargetInfo.FileToManifest.Keys, PreviousFileToManifest))
                    {
                        // Merge files from the existing manifests with the new ones
                        foreach (KeyValuePair <FileReference, ModuleManifest> Pair in PreviousFileToManifest)
                        {
                            ModuleManifest TargetManifest = TargetInfo.FileToManifest[Pair.Key];
                            MergeManifests(Pair.Value, TargetManifest);
                        }

                        // Update the build id to use the current one
                        Receipt.Version.BuildId = PreviousVersion.BuildId;
                    }
                }

                // If the build id is still not set, generate a new one from a GUID
                if (String.IsNullOrEmpty(Receipt.Version.BuildId))
                {
                    Receipt.Version.BuildId = Guid.NewGuid().ToString();
                }
            }
            else
            {
                // Read all the manifests and merge them into the new ones, if they have the same build id
                foreach (KeyValuePair <FileReference, ModuleManifest> Pair in TargetInfo.FileToManifest)
                {
                    ModuleManifest SourceManifest;
                    if (TryReadManifest(Pair.Key, out SourceManifest) && SourceManifest.BuildId == Receipt.Version.BuildId)
                    {
                        MergeManifests(SourceManifest, Pair.Value);
                    }
                }
            }

            // Update the build id in all the manifests, and write them out
            foreach (KeyValuePair <FileReference, ModuleManifest> Pair in TargetInfo.FileToManifest)
            {
                FileReference ManifestFile = Pair.Key;
                if (!UnrealBuildTool.IsFileInstalled(ManifestFile))
                {
                    ModuleManifest Manifest = Pair.Value;
                    Manifest.BuildId = Receipt.Version.BuildId;

                    if (!FileReference.Exists(ManifestFile))
                    {
                        // If the file doesn't already exist, just write it out
                        DirectoryReference.CreateDirectory(ManifestFile.Directory);
                        Manifest.Write(ManifestFile);
                    }
                    else
                    {
                        // Otherwise write it to a buffer first
                        string OutputText;
                        using (StringWriter Writer = new StringWriter())
                        {
                            Manifest.Write(Writer);
                            OutputText = Writer.ToString();
                        }

                        // And only write it to disk if it's been modified. Note that if a manifest is out of date, we should have generated a new build id causing the contents to differ.
                        string CurrentText = FileReference.ReadAllText(ManifestFile);
                        if (CurrentText != OutputText)
                        {
                            if (bNoManifestChanges)
                            {
                                Log.TraceError("Build modifies {0}. This is not permitted. Before:\n    {1}\nAfter:\n    {2}", ManifestFile, CurrentText.Replace("\n", "\n    "), OutputText.Replace("\n", "\n    "));
                            }
                            else
                            {
                                FileReference.WriteAllText(ManifestFile, OutputText);
                            }
                        }
                    }
                }
            }

            // Write out the version file, if it's changed. Since this file is next to the executable, it may be used by multiple targets, and we should avoid modifying it unless necessary.
            if (TargetInfo.VersionFile != null && !UnrealBuildTool.IsFileInstalled(TargetInfo.VersionFile))
            {
                DirectoryReference.CreateDirectory(TargetInfo.VersionFile.Directory);

                StringWriter Writer = new StringWriter();
                Receipt.Version.Write(Writer);

                string Text = Writer.ToString();
                if (!FileReference.Exists(TargetInfo.VersionFile) || File.ReadAllText(TargetInfo.VersionFile.FullName) != Text)
                {
                    File.WriteAllText(TargetInfo.VersionFile.FullName, Text);
                }
            }

            // Write out the receipt
            if (!UnrealBuildTool.IsFileInstalled(TargetInfo.ReceiptFile))
            {
                DirectoryReference.CreateDirectory(TargetInfo.ReceiptFile.Directory);
                Receipt.Write(TargetInfo.ReceiptFile);
            }

            return(0);
        }
        private bool WriteXcodeWorkspace()
        {
            bool bSuccess = true;

            StringBuilder WorkspaceDataContent = new StringBuilder();

            WorkspaceDataContent.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + ProjectFileGenerator.NewLine);
            WorkspaceDataContent.Append("<Workspace" + ProjectFileGenerator.NewLine);
            WorkspaceDataContent.Append("   version = \"1.0\">" + ProjectFileGenerator.NewLine);

            System.Action <List <MasterProjectFolder> /* Folders */, string /* Ident */> AddProjectsFunction = null;
            AddProjectsFunction = (FolderList, Ident) =>
            {
                int SchemeIndex = 0;
                foreach (XcodeProjectFolder CurFolder in FolderList)
                {
                    WorkspaceDataContent.Append(Ident + "   <Group" + ProjectFileGenerator.NewLine);
                    WorkspaceDataContent.Append(Ident + "      location = \"container:\"      name = \"" + CurFolder.FolderName + "\">" + ProjectFileGenerator.NewLine);

                    AddProjectsFunction(CurFolder.SubFolders, Ident + "   ");

                    List <ProjectFile> ChildProjects = new List <ProjectFile>(CurFolder.ChildProjects);
                    ChildProjects.Sort((ProjectFile A, ProjectFile B) => { return(A.ProjectFilePath.GetFileName().CompareTo(B.ProjectFilePath.GetFileName())); });

                    foreach (ProjectFile CurProject in ChildProjects)
                    {
                        XcodeProjectFile XcodeProject = CurProject as XcodeProjectFile;
                        if (XcodeProject != null)
                        {
                            WorkspaceDataContent.Append(Ident + "      <FileRef" + ProjectFileGenerator.NewLine);
                            WorkspaceDataContent.Append(Ident + "         location = \"group:" + XcodeProject.ProjectFilePath.MakeRelativeTo(ProjectFileGenerator.MasterProjectPath) + "\">" + ProjectFileGenerator.NewLine);
                            WorkspaceDataContent.Append(Ident + "      </FileRef>" + ProjectFileGenerator.NewLine);

                            // Also, update project's schemes index so that the schemes list order match projects order in the navigator
                            FileReference SchemeManagementFile = XcodeProject.ProjectFilePath + "/xcuserdata/" + Environment.UserName + ".xcuserdatad/xcschemes/xcschememanagement.plist";
                            if (FileReference.Exists(SchemeManagementFile))
                            {
                                string SchemeManagementContent = FileReference.ReadAllText(SchemeManagementFile);
                                SchemeManagementContent = SchemeManagementContent.Replace("<key>orderHint</key>\n\t\t\t<integer>1</integer>", "<key>orderHint</key>\n\t\t\t<integer>" + SchemeIndex.ToString() + "</integer>");
                                FileReference.WriteAllText(SchemeManagementFile, SchemeManagementContent);
                                SchemeIndex++;
                            }
                        }
                    }

                    WorkspaceDataContent.Append(Ident + "   </Group>" + ProjectFileGenerator.NewLine);
                }
            };
            AddProjectsFunction(RootFolder.SubFolders, "");

            WorkspaceDataContent.Append("</Workspace>" + ProjectFileGenerator.NewLine);

            string ProjectName = MasterProjectName;

            if (ProjectFilePlatform != XcodeProjectFilePlatform.All)
            {
                ProjectName += ProjectFilePlatform == XcodeProjectFilePlatform.Mac ? "_Mac" : (ProjectFilePlatform == XcodeProjectFilePlatform.iOS ? "_IOS" : "_TVOS");
            }
            string WorkspaceDataFilePath = MasterProjectPath + "/" + ProjectName + ".xcworkspace/contents.xcworkspacedata";

            bSuccess = WriteFileIfChanged(WorkspaceDataFilePath, WorkspaceDataContent.ToString(), new UTF8Encoding());
            if (bSuccess)
            {
                string WorkspaceSettingsFilePath = MasterProjectPath + "/" + ProjectName + ".xcworkspace/xcuserdata/" + Environment.UserName + ".xcuserdatad/WorkspaceSettings.xcsettings";
                bSuccess = WriteWorkspaceSettingsFile(WorkspaceSettingsFilePath);
            }

            return(bSuccess);
        }
Example #6
0
        /// <summary>
        /// Build a target remotely
        /// </summary>
        /// <param name="TargetDesc">Descriptor for the target to build</param>
        /// <param name="RemoteLogFile">Path to store the remote log file</param>
        /// <returns>True if the build succeeded, false otherwise</returns>
        public bool Build(TargetDescriptor TargetDesc, FileReference RemoteLogFile)
        {
            // Get the directory for working files
            DirectoryReference BaseDir = DirectoryReference.FromFile(TargetDesc.ProjectFile) ?? UnrealBuildTool.EngineDirectory;
            DirectoryReference TempDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Remote", TargetDesc.Name, TargetDesc.Platform.ToString(), TargetDesc.Configuration.ToString());

            DirectoryReference.CreateDirectory(TempDir);

            // Compile the rules assembly
            RulesCompiler.CreateTargetRulesAssembly(TargetDesc.ProjectFile, TargetDesc.Name, false, false, TargetDesc.ForeignPlugin);

            // Path to the local manifest file. This has to be translated from the remote format after the build is complete.
            List <FileReference> LocalManifestFiles = new List <FileReference>();

            // Path to the remote manifest file
            FileReference RemoteManifestFile = FileReference.Combine(TempDir, "Manifest.xml");

            // Prepare the arguments we will pass to the remote build
            List <string> RemoteArguments = new List <string>();

            RemoteArguments.Add(TargetDesc.Name);
            RemoteArguments.Add(TargetDesc.Platform.ToString());
            RemoteArguments.Add(TargetDesc.Configuration.ToString());
            RemoteArguments.Add("-SkipRulesCompile");                                                      // Use the rules assembly built locally
            RemoteArguments.Add(String.Format("-XmlConfigCache={0}", GetRemotePath(XmlConfig.CacheFile))); // Use the XML config cache built locally, since the remote won't have it
            RemoteArguments.Add(String.Format("-Log={0}", GetRemotePath(RemoteLogFile)));
            RemoteArguments.Add(String.Format("-Manifest={0}", GetRemotePath(RemoteManifestFile)));

            if (TargetDesc.ProjectFile != null)
            {
                RemoteArguments.Add(String.Format("-Project={0}", GetRemotePath(TargetDesc.ProjectFile)));
            }

            foreach (string LocalArgument in TargetDesc.AdditionalArguments)
            {
                int EqualsIdx = LocalArgument.IndexOf('=');
                if (EqualsIdx == -1)
                {
                    RemoteArguments.Add(LocalArgument);
                    continue;
                }

                string Key   = LocalArgument.Substring(0, EqualsIdx);
                string Value = LocalArgument.Substring(EqualsIdx + 1);

                if (Key.Equals("-Log", StringComparison.InvariantCultureIgnoreCase))
                {
                    // We are already writing to the local log file. The remote will produce a different log (RemoteLogFile)
                    continue;
                }
                if (Key.Equals("-Manifest", StringComparison.InvariantCultureIgnoreCase))
                {
                    LocalManifestFiles.Add(new FileReference(Value));
                    continue;
                }

                string RemoteArgument = LocalArgument;
                foreach (RemoteMapping Mapping in Mappings)
                {
                    if (Value.StartsWith(Mapping.LocalDirectory.FullName, StringComparison.InvariantCultureIgnoreCase))
                    {
                        RemoteArgument = String.Format("{0}={1}", Key, GetRemotePath(Value));
                        break;
                    }
                }
                RemoteArguments.Add(RemoteArgument);
            }

            // Handle any per-platform setup that is required
            if (TargetDesc.Platform == UnrealTargetPlatform.IOS || TargetDesc.Platform == UnrealTargetPlatform.TVOS)
            {
                // Always generate a .stub
                RemoteArguments.Add("-CreateStub");

                // Get the provisioning data for this project
                IOSProvisioningData ProvisioningData = ((IOSPlatform)UEBuildPlatform.GetBuildPlatform(TargetDesc.Platform)).ReadProvisioningData(TargetDesc.ProjectFile);
                if (ProvisioningData == null || ProvisioningData.MobileProvisionFile == null)
                {
                    throw new BuildException("Unable to find mobile provision for {0}. See log for more information.", TargetDesc.Name);
                }

                // Create a local copy of the provision
                FileReference MobileProvisionFile = FileReference.Combine(TempDir, ProvisioningData.MobileProvisionFile.GetFileName());
                if (FileReference.Exists(MobileProvisionFile))
                {
                    FileReference.SetAttributes(MobileProvisionFile, FileAttributes.Normal);
                }
                FileReference.Copy(ProvisioningData.MobileProvisionFile, MobileProvisionFile, true);
                Log.TraceInformation("[Remote] Uploading {0}", MobileProvisionFile);
                UploadFile(MobileProvisionFile);

                // Extract the certificate for the project. Try to avoid calling IPP if we already have it.
                FileReference CertificateFile = FileReference.Combine(TempDir, "Certificate.p12");

                FileReference CertificateInfoFile     = FileReference.Combine(TempDir, "Certificate.txt");
                string        CertificateInfoContents = String.Format("{0}\n{1}", ProvisioningData.MobileProvisionFile, FileReference.GetLastWriteTimeUtc(ProvisioningData.MobileProvisionFile).Ticks);

                if (!FileReference.Exists(CertificateFile) || !FileReference.Exists(CertificateInfoFile) || FileReference.ReadAllText(CertificateInfoFile) != CertificateInfoContents)
                {
                    Log.TraceInformation("[Remote] Exporting certificate for {0}...", ProvisioningData.MobileProvisionFile);

                    StringBuilder Arguments = new StringBuilder("ExportCertificate");
                    if (TargetDesc.ProjectFile == null)
                    {
                        Arguments.AppendFormat(" \"{0}\"", UnrealBuildTool.EngineSourceDirectory);
                    }
                    else
                    {
                        Arguments.AppendFormat(" \"{0}\"", TargetDesc.ProjectFile.Directory);
                    }
                    Arguments.AppendFormat(" -provisionfile \"{0}\"", ProvisioningData.MobileProvisionFile);
                    Arguments.AppendFormat(" -outputcertificate \"{0}\"", CertificateFile);
                    if (TargetDesc.Platform == UnrealTargetPlatform.TVOS)
                    {
                        Arguments.Append(" -tvos");
                    }

                    ProcessStartInfo StartInfo = new ProcessStartInfo();
                    StartInfo.FileName  = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "DotNET", "IOS", "IPhonePackager.exe").FullName;
                    StartInfo.Arguments = Arguments.ToString();
                    if (Utils.RunLocalProcessAndLogOutput(StartInfo) != 0)
                    {
                        throw new BuildException("IphonePackager failed.");
                    }

                    FileReference.WriteAllText(CertificateInfoFile, CertificateInfoContents);
                }

                // Upload the certificate to the remote
                Log.TraceInformation("[Remote] Uploading {0}", CertificateFile);
                UploadFile(CertificateFile);

                // Tell the remote UBT instance to use them
                RemoteArguments.Add(String.Format("-ImportProvision={0}", GetRemotePath(MobileProvisionFile)));
                RemoteArguments.Add(String.Format("-ImportCertificate={0}", GetRemotePath(CertificateFile)));
                RemoteArguments.Add(String.Format("-ImportCertificatePassword=A"));
            }

            // Upload the workspace files
            UploadWorkspace(TempDir);

            // Fixup permissions on any shell scripts
            Execute(RemoteBaseDir, String.Format("chmod +x {0}/Build/BatchFiles/Mac/*.sh", EscapeShellArgument(GetRemotePath(UnrealBuildTool.EngineDirectory))));

            // Execute the compile
            Log.TraceInformation("[Remote] Executing build");

            StringBuilder BuildCommandLine = new StringBuilder("Engine/Build/BatchFiles/Mac/Build.sh");

            foreach (string RemoteArgument in RemoteArguments)
            {
                BuildCommandLine.AppendFormat(" {0}", EscapeShellArgument(RemoteArgument));
            }

            int Result = Execute(GetRemotePath(UnrealBuildTool.RootDirectory), BuildCommandLine.ToString());

            if (Result != 0)
            {
                if (RemoteLogFile != null)
                {
                    Log.TraceInformation("[Remote] Downloading {0}", RemoteLogFile);
                    DownloadFile(RemoteLogFile);
                }
                return(false);
            }

            // Download the manifest
            Log.TraceInformation("[Remote] Downloading {0}", RemoteManifestFile);
            DownloadFile(RemoteManifestFile);

            // Convert the manifest to local form
            BuildManifest Manifest = Utils.ReadClass <BuildManifest>(RemoteManifestFile.FullName);

            for (int Idx = 0; Idx < Manifest.BuildProducts.Count; Idx++)
            {
                Manifest.BuildProducts[Idx] = GetLocalPath(Manifest.BuildProducts[Idx]).FullName;
            }

            // Download the files from the remote
            if (TargetDesc.AdditionalArguments.Any(x => x.Equals("-GenerateManifest", StringComparison.InvariantCultureIgnoreCase)))
            {
                LocalManifestFiles.Add(FileReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "Build", "Manifest.xml"));
            }
            else
            {
                Log.TraceInformation("[Remote] Downloading build products");

                List <FileReference> FilesToDownload = new List <FileReference>();
                FilesToDownload.Add(RemoteLogFile);
                FilesToDownload.AddRange(Manifest.BuildProducts.Select(x => new FileReference(x)));
                DownloadFiles(FilesToDownload);
            }

            // Write out all the local manifests
            foreach (FileReference LocalManifestFile in LocalManifestFiles)
            {
                Log.TraceInformation("[Remote] Writing {0}", LocalManifestFile);
                Utils.WriteClass <BuildManifest>(Manifest, LocalManifestFile.FullName, "");
            }
            return(true);
        }
Example #7
0
 /// <summary>
 ///
 /// </summary>
 public void Save(FileReference InFile)
 {
     FileReference.WriteAllText(InFile, fastJSON.JSON.Instance.ToJSON(this, new fastJSON.JSONParameters {
     }));
 }
        public override int Execute(CommandLineArguments Arguments)
        {
            FileReference ManifestFile = Arguments.GetFileReference("-ManifestFile=");

            string[] ParsedFileNames = FileReference.ReadAllLines(ManifestFile);

            // Load all the file timing data and summarize them for the aggregate.
            FileTimingData = new TimingData()
            {
                Name = "Files", Type = TimingDataType.Summary
            };
            Parallel.ForEach(ParsedFileNames, new ParallelOptions()
            {
                MaxDegreeOfParallelism = 4
            }, ParseTimingDataFile);

            // Create aggregate summary. Duration is the duration of the files in the aggregate.
            string     AggregateName = Arguments.GetString("-Name=");
            TimingData AggregateData = new TimingData()
            {
                Name = AggregateName, Type = TimingDataType.Aggregate
            };

            AggregateData.AddChild(FileTimingData);

            // Group the includes, classes, and functions by name and sum them up then add to the aggregate.
            GroupTimingDataOnName(AggregateData, "Include Timings", AggregateIncludes);
            GroupTimingDataOnName(AggregateData, "Class Timings", AggregateClasses);
            GroupTimingDataOnName(AggregateData, "Function Timings", AggregateFunctions);

            // Write out aggregate summary.
            string OutputFile = Path.Combine(ManifestFile.Directory.FullName, String.Format("{0}.timing.bin", AggregateName));

            using (BinaryWriter Writer = new BinaryWriter(File.Open(OutputFile, FileMode.Create)))
            {
                // Write out the aggregate data.
                Writer.Write(AggregateData);

                // Write the look up table for the compressed binary blobs.
                int Offset = 0;
                Writer.Write(CompressedFiles.Count);
                foreach (KeyValuePair <string, byte[]> CompressedFile in CompressedFiles)
                {
                    Writer.Write(CompressedFile.Key);
                    Writer.Write(Offset);
                    Writer.Write(CompressedFile.Value.Length);
                    Writer.Write(DecompressedFileSizes[CompressedFile.Key]);
                    Offset += CompressedFile.Value.Length;
                }

                // Write the compressed binary blobs.
                foreach (KeyValuePair <string, byte[]> CompressedFile in CompressedFiles)
                {
                    Writer.Write(CompressedFile.Value);
                }
            }

            if (Arguments.HasValue("-CompileTimingFile="))
            {
                FileReference CompileTimingFile          = Arguments.GetFileReference("-CompileTimingFile=");
                Dictionary <string, double> CompileTimes = new Dictionary <string, double>();
                foreach (KeyValuePair <string, TimingData> TimingData in FileTimingData.Children)
                {
                    CompileTimes.Add(Json.EscapeString(TimingData.Key), TimingData.Value.InclusiveDuration);
                }
                string JsonCompileTimes = Json.Serialize(CompileTimes);
                FileReference.WriteAllText(CompileTimingFile, JsonCompileTimes);
            }

            return(0);
        }
Example #9
0
        private bool WriteXcodeWorkspace()
        {
            bool bSuccess = true;

            StringBuilder WorkspaceDataContent = new StringBuilder();

            WorkspaceDataContent.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + ProjectFileGenerator.NewLine);
            WorkspaceDataContent.Append("<Workspace" + ProjectFileGenerator.NewLine);
            WorkspaceDataContent.Append("   version = \"1.0\">" + ProjectFileGenerator.NewLine);

            List <XcodeProjectFile> BuildableProjects = new List <XcodeProjectFile>();

            System.Action <List <MasterProjectFolder> /* Folders */, string /* Ident */> AddProjectsFunction = null;
            AddProjectsFunction = (FolderList, Ident) =>
            {
                foreach (XcodeProjectFolder CurFolder in FolderList)
                {
                    WorkspaceDataContent.Append(Ident + "   <Group" + ProjectFileGenerator.NewLine);
                    WorkspaceDataContent.Append(Ident + "      location = \"container:\"      name = \"" + CurFolder.FolderName + "\">" + ProjectFileGenerator.NewLine);

                    AddProjectsFunction(CurFolder.SubFolders, Ident + "   ");

                    // Filter out anything that isn't an XC project, and that shouldn't be in the workspace
                    IEnumerable <XcodeProjectFile> SupportedProjects =
                        CurFolder.ChildProjects
                        .Where(P => P is XcodeProjectFile)
                        .Select(P => P as XcodeProjectFile)
                        .Where(P => P.ShouldIncludeProjectInWorkspace())
                        .OrderBy(P => P.ProjectFilePath.GetFileName());


                    foreach (XcodeProjectFile XcodeProject in SupportedProjects)
                    {
                        WorkspaceDataContent.Append(Ident + "      <FileRef" + ProjectFileGenerator.NewLine);
                        WorkspaceDataContent.Append(Ident + "         location = \"group:" + XcodeProject.ProjectFilePath.MakeRelativeTo(ProjectFileGenerator.MasterProjectPath) + "\">" + ProjectFileGenerator.NewLine);
                        WorkspaceDataContent.Append(Ident + "      </FileRef>" + ProjectFileGenerator.NewLine);
                    }

                    BuildableProjects.AddRange(SupportedProjects);

                    WorkspaceDataContent.Append(Ident + "   </Group>" + ProjectFileGenerator.NewLine);
                }
            };
            AddProjectsFunction(RootFolder.SubFolders, "");

            WorkspaceDataContent.Append("</Workspace>" + ProjectFileGenerator.NewLine);

            // Also, update project's schemes index so that the schemes are in a sensible order
            // (Game, Editor, Client, Server, Programs)
            int SchemeIndex = 0;

            BuildableProjects.Sort((ProjA, ProjB) => {
                var TargetA = ProjA.ProjectTargets.OrderBy(T => T.TargetRules.Type).FirstOrDefault();
                var TargetB = ProjB.ProjectTargets.OrderBy(T => T.TargetRules.Type).FirstOrDefault();

                var TypeA = TargetA != null ? TargetA.TargetRules.Type : TargetType.Program;
                var TypeB = TargetB != null ? TargetB.TargetRules.Type : TargetType.Program;

                if (TypeA != TypeB)
                {
                    return(TypeA.CompareTo(TypeB));
                }

                return(TargetA.Name.CompareTo(TargetB.Name));
            });

            foreach (XcodeProjectFile XcodeProject in BuildableProjects)
            {
                FileReference SchemeManagementFile = XcodeProject.ProjectFilePath + "/xcuserdata/" + Environment.UserName + ".xcuserdatad/xcschemes/xcschememanagement.plist";
                if (FileReference.Exists(SchemeManagementFile))
                {
                    string SchemeManagementContent = FileReference.ReadAllText(SchemeManagementFile);
                    SchemeManagementContent = SchemeManagementContent.Replace("<key>orderHint</key>\n\t\t\t<integer>1</integer>", "<key>orderHint</key>\n\t\t\t<integer>" + SchemeIndex.ToString() + "</integer>");
                    FileReference.WriteAllText(SchemeManagementFile, SchemeManagementContent);
                    SchemeIndex++;
                }
            }

            string ProjectName = MasterProjectName;

            if (ProjectFilePlatform != XcodeProjectFilePlatform.All)
            {
                ProjectName += ProjectFilePlatform == XcodeProjectFilePlatform.Mac ? "_Mac" : (ProjectFilePlatform == XcodeProjectFilePlatform.iOS ? "_IOS" : "_TVOS");
            }
            string WorkspaceDataFilePath = MasterProjectPath + "/" + ProjectName + ".xcworkspace/contents.xcworkspacedata";

            bSuccess = WriteFileIfChanged(WorkspaceDataFilePath, WorkspaceDataContent.ToString(), new UTF8Encoding());
            if (bSuccess)
            {
                string WorkspaceSettingsFilePath = MasterProjectPath + "/" + ProjectName + ".xcworkspace/xcuserdata/" + Environment.UserName + ".xcuserdatad/WorkspaceSettings.xcsettings";
                bSuccess = WriteWorkspaceSettingsFile(WorkspaceSettingsFilePath);
            }

            return(bSuccess);
        }