Exemple #1
0
        public override void ExecuteBuild()
        {
            // Parse the target list
            string[] Targets = ParseParamValues("Target");
            if (Targets.Length == 0)
            {
                throw new AutomationException("No targets specified (eg. -Target=\"UE4Editor Win64 Development\")");
            }

            // Parse the archive path
            string ArchivePath = ParseParamValue("Archive");

            if (ArchivePath != null && (!ArchivePath.StartsWith("//") || ArchivePath.Sum(x => (x == '/')? 1 : 0) < 4))
            {
                throw new AutomationException("Archive path is not a valid depot filename");
            }

            // Parse the stream name
            string StreamName = ParseParamValue("Stream");

            if (StreamName == null && ArchivePath != null)
            {
                StreamName = ArchivePath.Substring(0, ArchivePath.IndexOf('/', ArchivePath.IndexOf('/', 2) + 1));
            }

            // Prepare the build agenda
            UE4Build.BuildAgenda Agenda = new UE4Build.BuildAgenda();
            foreach (string Target in Targets)
            {
                string[] Tokens = Target.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                UnrealTargetPlatform      Platform;
                UnrealTargetConfiguration Configuration;
                if (Tokens.Length < 3 || !Enum.TryParse(Tokens[1], true, out Platform) || !Enum.TryParse(Tokens[2], true, out Configuration))
                {
                    throw new AutomationException("Invalid target '{0}' - expected <TargetName> <Platform> <Configuration>");
                }

                Agenda.AddTarget(Tokens[0], Platform, Configuration, InAddArgs: String.Join(" ", Tokens.Skip(3)));
            }

            // Build everything
            UE4Build Builder = new UE4Build(this);

            Builder.Build(Agenda, InUpdateVersionFiles: ArchivePath != null);

            // Include the build products for UAT and UBT if required
            if (ParseParam("WithUAT"))
            {
                Builder.AddUATFilesToBuildProducts();
            }
            if (ParseParam("WithUBT"))
            {
                Builder.AddUBTFilesToBuildProducts();
            }

            // Archive the build products
            if (ArchivePath != null)
            {
                // Create an output folder
                string OutputFolder = Path.Combine(CommandUtils.CmdEnv.LocalRoot, "ArchiveForUGS");
                Directory.CreateDirectory(OutputFolder);

                // Create a temp folder for storing stripped PDB files
                string SymbolsFolder = Path.Combine(OutputFolder, "Symbols");
                Directory.CreateDirectory(SymbolsFolder);

                // Get the Windows toolchain
                Platform WindowsTargetPlatform = Platform.GetPlatform(UnrealTargetPlatform.Win64);

                // Figure out all the files for the archive
                string ZipFileName = Path.Combine(OutputFolder, "Archive.zip");
                using (Ionic.Zip.ZipFile Zip = new Ionic.Zip.ZipFile())
                {
                    Zip.UseZip64WhenSaving = Ionic.Zip.Zip64Option.Always;
                    foreach (string BuildProduct in Builder.BuildProductFiles)
                    {
                        if (!File.Exists(BuildProduct))
                        {
                            throw new AutomationException("Missing build product: {0}", BuildProduct);
                        }
                        if (BuildProduct.EndsWith(".pdb", StringComparison.InvariantCultureIgnoreCase))
                        {
                            string StrippedFileName = CommandUtils.MakeRerootedFilePath(BuildProduct, CommandUtils.CmdEnv.LocalRoot, SymbolsFolder);
                            Directory.CreateDirectory(Path.GetDirectoryName(StrippedFileName));
                            WindowsTargetPlatform.StripSymbols(new FileReference(BuildProduct), new FileReference(StrippedFileName));
                            Zip.AddFile(StrippedFileName, Path.GetDirectoryName(CommandUtils.StripBaseDirectory(StrippedFileName, SymbolsFolder)));
                        }
                        else
                        {
                            Zip.AddFile(BuildProduct, Path.GetDirectoryName(CommandUtils.StripBaseDirectory(BuildProduct, CommandUtils.CmdEnv.LocalRoot)));
                        }
                    }
                    // Create the zip file
                    Console.WriteLine("Writing {0}...", ZipFileName);
                    Zip.Save(ZipFileName);
                }

                // Submit it to Perforce if required
                if (CommandUtils.AllowSubmit)
                {
                    // Delete any existing clientspec for submitting
                    string ClientName = Environment.MachineName + "_BuildForUGS";

                    // Create a brand new one
                    P4ClientInfo Client = new P4ClientInfo();
                    Client.Owner    = CommandUtils.P4Env.User;
                    Client.Host     = Environment.MachineName;
                    Client.Stream   = StreamName;
                    Client.RootPath = Path.Combine(OutputFolder, "Perforce");
                    Client.Name     = ClientName;
                    Client.Options  = P4ClientOption.NoAllWrite | P4ClientOption.NoClobber | P4ClientOption.NoCompress | P4ClientOption.Unlocked | P4ClientOption.NoModTime | P4ClientOption.RmDir;
                    Client.LineEnd  = P4LineEnd.Local;
                    P4.CreateClient(Client, AllowSpew: false);

                    // Create a new P4 connection for this workspace
                    P4Connection SubmitP4 = new P4Connection(Client.Owner, Client.Name, P4Env.ServerAndPort);
                    SubmitP4.Revert("-k //...");

                    // Figure out where the zip file has to go in Perforce
                    P4WhereRecord WhereZipFile = SubmitP4.Where(ArchivePath, false).FirstOrDefault(x => !x.bUnmap && x.Path != null);
                    if (WhereZipFile == null)
                    {
                        throw new AutomationException("Couldn't locate {0} in this workspace");
                    }

                    // Get the latest version of it
                    int NewCL = SubmitP4.CreateChange(Description: String.Format("[CL {0}] Updated binaries", P4Env.Changelist));
                    SubmitP4.Sync(String.Format("-k \"{0}\"", ArchivePath), AllowSpew: false);
                    CommandUtils.CopyFile(ZipFileName, WhereZipFile.Path);
                    SubmitP4.Add(NewCL, String.Format("\"{0}\"", ArchivePath));
                    SubmitP4.Edit(NewCL, String.Format("\"{0}\"", ArchivePath));

                    // Submit it
                    int SubmittedCL;
                    SubmitP4.Submit(NewCL, out SubmittedCL);
                    if (SubmittedCL <= 0)
                    {
                        throw new AutomationException("Submit failed.");
                    }
                    Console.WriteLine("Submitted in changelist {0}", SubmittedCL);
                }
            }
        }
Exemple #2
0
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        // Engine non-ufs (binaries)

        if (SC.bStageCrashReporter)
        {
            FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(CommandUtils.EngineDirectory, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, null);
            if (FileReference.Exists(ReceiptFileName))
            {
                DirectoryReference EngineDir  = CommandUtils.EngineDirectory;
                DirectoryReference ProjectDir = DirectoryReference.FromFile(Params.RawProjectPath);
                TargetReceipt      Receipt    = TargetReceipt.Read(ReceiptFileName, EngineDir, ProjectDir);
                SC.StageBuildProductsFromReceipt(Receipt, true, false);
            }
        }

        // Stage all the build products
        foreach (StageTarget Target in SC.StageTargets)
        {
            SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles);
        }

        // Copy the splash screen, windows specific
        FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp");

        if (FileReference.Exists(SplashImage))
        {
            SC.StageFile(StagedFileType.NonUFS, SplashImage);
        }

        // Stage the bootstrap executable
        if (!Params.NoBootstrapExe)
        {
            foreach (StageTarget Target in SC.StageTargets)
            {
                BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable);
                if (Executable != null)
                {
                    // only create bootstraps for executables
                    List <StagedFileReference> StagedFiles = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList();
                    if (StagedFiles.Count > 0 && Executable.Path.HasExtension(".exe"))
                    {
                        string BootstrapArguments = "";
                        if (!ShouldStageCommandLine(Params, SC))
                        {
                            if (!SC.IsCodeBasedProject)
                            {
                                BootstrapArguments = String.Format("..\\..\\..\\{0}\\{0}.uproject", SC.ShortProjectName);
                            }
                            else
                            {
                                BootstrapArguments = SC.ShortProjectName;
                            }
                        }

                        string BootstrapExeName;
                        if (SC.StageTargetConfigurations.Count > 1)
                        {
                            BootstrapExeName = Executable.Path.GetFileName();
                        }
                        else if (Params.IsCodeBasedProject)
                        {
                            BootstrapExeName = Target.Receipt.TargetName + ".exe";
                        }
                        else
                        {
                            BootstrapExeName = SC.ShortProjectName + ".exe";
                        }

                        foreach (StagedFileReference StagePath in StagedFiles)
                        {
                            StageBootstrapExecutable(SC, BootstrapExeName, Executable.Path, StagePath, BootstrapArguments);
                        }
                    }
                }
            }
        }
    }
Exemple #3
0
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        // Stage all the build products
        foreach (StageTarget Target in SC.StageTargets)
        {
            SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles);
        }

        if (SC.bStageCrashReporter)
        {
            StagedDirectoryReference CrashReportClientPath = StagedDirectoryReference.Combine("Engine/Binaries", SC.PlatformDir, "CrashReportClient.app");
            StageAppBundle(SC, DirectoryReference.Combine(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "CrashReportClient.app"), CrashReportClientPath);
        }

        // Find the app bundle path
        List <FileReference> Exes = GetExecutableNames(SC);

        foreach (var Exe in Exes)
        {
            StagedDirectoryReference AppBundlePath = null;
            if (Exe.IsUnderDirectory(DirectoryReference.Combine(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir)))
            {
                AppBundlePath = StagedDirectoryReference.Combine(SC.ShortProjectName, "Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe.FullName) + ".app");
            }
            else if (Exe.IsUnderDirectory(DirectoryReference.Combine(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir)))
            {
                AppBundlePath = StagedDirectoryReference.Combine("Engine/Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe.FullName) + ".app");
            }

            // Copy the custom icon and Steam dylib, if needed
            if (AppBundlePath != null)
            {
                FileReference AppIconsFile = FileReference.Combine(SC.ProjectRoot, "Build", "Mac", "Application.icns");
                if (FileReference.Exists(AppIconsFile))
                {
                    SC.StageFile(StagedFileType.NonUFS, AppIconsFile, StagedFileReference.Combine(AppBundlePath, "Contents", "Resources", "Application.icns"));
                }
            }
        }

        // Copy the splash screen, Mac specific
        FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp");

        if (FileReference.Exists(SplashImage))
        {
            SC.StageFile(StagedFileType.NonUFS, SplashImage);
        }

        // Stage the bootstrap executable
        if (!Params.NoBootstrapExe)
        {
            foreach (StageTarget Target in SC.StageTargets)
            {
                BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable);
                if (Executable != null)
                {
                    // only create bootstraps for executables
                    List <StagedFileReference> StagedFiles = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList();
                    if (StagedFiles.Count > 0 && Executable.Path.FullName.Replace("\\", "/").Contains("/" + TargetPlatformType.ToString() + "/"))
                    {
                        string BootstrapArguments = "";
                        if (!ShouldStageCommandLine(Params, SC))
                        {
                            if (!SC.IsCodeBasedProject)
                            {
                                BootstrapArguments = String.Format("../../../{0}/{0}.uproject", SC.ShortProjectName);
                            }
                            else
                            {
                                BootstrapArguments = SC.ShortProjectName;
                            }
                        }

                        string BootstrapExeName;
                        if (SC.StageTargetConfigurations.Count > 1)
                        {
                            BootstrapExeName = Path.GetFileName(Executable.Path.FullName) + ".app";
                        }
                        else if (Params.IsCodeBasedProject)
                        {
                            BootstrapExeName = Target.Receipt.TargetName + ".app";
                        }
                        else
                        {
                            BootstrapExeName = SC.ShortProjectName + ".app";
                        }

                        string AppPath = Executable.Path.FullName.Substring(0, Executable.Path.FullName.LastIndexOf(".app/") + 4);
                        foreach (var DestPath in StagedFiles)
                        {
                            string AppRelativePath = DestPath.Name.Substring(0, DestPath.Name.LastIndexOf(".app/") + 4);
                            StageBootstrapExecutable(SC, BootstrapExeName, AppPath, AppRelativePath, BootstrapArguments);
                        }
                    }
                }
            }
        }

        // Copy the ShaderCache files, if they exist
        FileReference DrawCacheFile = FileReference.Combine(SC.ProjectRoot, "Content", "DrawCache.ushadercache");

        if (FileReference.Exists(DrawCacheFile))
        {
            SC.StageFile(StagedFileType.UFS, DrawCacheFile);
        }

        FileReference ByteCodeCacheFile = FileReference.Combine(SC.ProjectRoot, "Content", "ByteCodeCache.ushadercode");

        if (FileReference.Exists(ByteCodeCacheFile))
        {
            SC.StageFile(StagedFileType.UFS, ByteCodeCacheFile);
        }

        {
            // Stage any *.metallib files as NonUFS.
            // Get the final output directory for cooked data
            DirectoryReference CookOutputDir;
            if (!String.IsNullOrEmpty(Params.CookOutputDir))
            {
                CookOutputDir = DirectoryReference.Combine(new DirectoryReference(Params.CookOutputDir), SC.CookPlatform);
            }
            else if (Params.CookInEditor)
            {
                CookOutputDir = DirectoryReference.Combine(SC.ProjectRoot, "Saved", "EditorCooked", SC.CookPlatform);
            }
            else
            {
                CookOutputDir = DirectoryReference.Combine(SC.ProjectRoot, "Saved", "Cooked", SC.CookPlatform);
            }
            if (DirectoryReference.Exists(CookOutputDir))
            {
                List <FileReference> CookedFiles = DirectoryReference.EnumerateFiles(CookOutputDir, "*.metallib", SearchOption.AllDirectories).ToList();
                foreach (FileReference CookedFile in CookedFiles)
                {
                    SC.StageFile(StagedFileType.NonUFS, CookedFile, new StagedFileReference(CookedFile.MakeRelativeTo(CookOutputDir)));
                }
            }
        }
    }