private void GenerateScript(DeploymentContext context, ILogger buildLogger) { try { using (context.Tracer.Step("Generating deployment script")) { var scriptGenerator = new Executable(DeploymentScriptGeneratorToolPath, RepositoryPath, DeploymentSettings.GetCommandIdleTimeout()); // Set home path to the user profile so cache directories created by azure-cli are created there scriptGenerator.SetHomePath(System.Environment.GetEnvironmentVariable("APPDATA")); var scriptGeneratorCommand = String.Format(ScriptGeneratorCommandFormat, RepositoryPath, ScriptGeneratorCommandArguments); buildLogger.Log(Resources.Log_DeploymentScriptGeneratorCommand, scriptGeneratorCommand); scriptGenerator.ExecuteWithProgressWriter(buildLogger, context.Tracer, _ => false, _ => false, scriptGeneratorCommand); } } catch (CommandLineException ex) { context.Tracer.TraceError(ex); // HACK: Log an empty error to the global logger (post receive hook console output). // The reason we don't log the real exception is because the 'live output' running // msbuild has already been captured. context.GlobalLogger.LogError(); // Add the output stream and the error stream to the log for better // debugging buildLogger.Log(ex.Output, LogEntryType.Error); buildLogger.Log(ex.Error, LogEntryType.Error); throw; } }
public override void BeforeDeploy(DeploymentContext context, Action<ProgressReport> reportProgress) { var logger = context.GetLoggerFor(this); // find an app_online.htm file in the package var appOnline = context.Package.GetFiles().SingleOrDefault(f => f.Path.EndsWith(APP_ONLINE_FILE)); if (appOnline == null) { return; } var tempFilePath = Path.Combine(context.WorkingFolder, appOnline.Path); var destinationFilePath = Path.Combine(context.TargetInstallationFolder, APP_OFFLINE_FILE); if (!File.Exists(tempFilePath)) { return; } logger.Info("Copying app_offline.htm to destination"); reportProgress(new ProgressReport(context, GetType(), "Copying app_offline.htm to destination")); if (!_fileSystem.Directory.Exists(Path.GetDirectoryName(destinationFilePath))) { _fileSystem.Directory.CreateDirectory(Path.GetDirectoryName(destinationFilePath)); } if (!_fileSystem.File.Exists(destinationFilePath)) { _fileSystem.File.Copy(tempFilePath, destinationFilePath); } WaitForAppToUnload(); }
/// <summary> /// Performs a deployment. /// </summary> /// <param name="context">The deployment context.</param> public void Deploy(DeploymentContext context) { if (string.IsNullOrEmpty(Filename)) return; var normalPath = Filename.Replace('/', Path.DirectorySeparatorChar); var destination = Path.Combine(context.DestinationPath, normalPath); Directory.CreateDirectory(Path.GetDirectoryName(destination)); if (File.Exists(destination)) { try { File.Delete(destination); } catch { return; } } try { context.ExtractFile(Filename, destination); } catch { return; } }
public override void AfterDeploy(DeploymentContext context) { var logger = context.GetLoggerFor(this); if (!EnvironmentIsValidForPackage(context)) { return; } // if no such service then install it using (var service = ServiceController.GetServices().SingleOrDefault(s => s.ServiceName == context.Package.Id)) { if (service == null) { var pathToExecutable = Path.Combine(context.TargetInstallationFolder, context.Package.Id + ".exe"); logger.InfoFormat("Installing service {0} from {1}", context.Package.Title, pathToExecutable); System.Configuration.Install.ManagedInstallerClass.InstallHelper(new[] {pathToExecutable}); } } using (var service = ServiceController.GetServices().SingleOrDefault(s => s.ServiceName == context.Package.Id)) { // todo: recursively shut down dependent services if (!service.Status.Equals(ServiceControllerStatus.Stopped) && !service.Status.Equals(ServiceControllerStatus.StopPending)) { return; } ChangeServiceStateTo(service, ServiceControllerStatus.Running, service.Start, logger); } }
public HTMLPakAutomation(ProjectParams InParam, DeploymentContext InSC) { Params = InParam; SC = InSC; var PakOrderFileLocationBase = CommandUtils.CombinePaths(SC.ProjectRoot, "Build", SC.FinalCookPlatform, "FileOpenOrder"); PakOrderFileLocation = CommandUtils.CombinePaths(PakOrderFileLocationBase, "GameOpenOrder.log"); if (!CommandUtils.FileExists_NoExceptions(PakOrderFileLocation)) { // Use a fall back, it doesn't matter if this file exists or not. GameOpenOrder.log is preferred however PakOrderFileLocation = CommandUtils.CombinePaths(PakOrderFileLocationBase, "EditorOpenOrder.log"); } string PakPath = Path.Combine(new string[] { Path.GetDirectoryName(Params.RawProjectPath), "Binaries", "HTML5", SC.ShortProjectName}); if (Directory.Exists(PakPath)) { Directory.Delete(PakPath,true); } // read in the json file. string JsonFile = CommandUtils.CombinePaths(new string[] { SC.ProjectRoot, "Saved", "Cooked", "HTML5", Params.ShortProjectName, "MapDependencyGraph.json" }); string text = File.ReadAllText(JsonFile); DependencyJson = fastJSON.JSON.Instance.ToObject<Dictionary<string, object>>(text); }
public override void GetFilesToArchive(ProjectParams Params, DeploymentContext SC) { if (SC.StageTargetConfigurations.Count != 1) { throw new AutomationException("iOS is currently only able to package one target configuration at a time, but StageTargetConfigurations contained {0} configurations", SC.StageTargetConfigurations.Count); } string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath), "Binaries", "HTML5"); string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data"; // copy the "Executable" to the archive directory string GameExe = Path.GetFileNameWithoutExtension(Params.ProjectGameExeFilename); if (Params.ClientConfigsToBuild[0].ToString() != "Development") { GameExe += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString(); } GameExe += ".js"; // put the HTML file to the package directory string OutputFile = Path.Combine(PackagePath, (Params.ClientConfigsToBuild[0].ToString() != "Development" ? (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) : Params.ShortProjectName)) + ".html"; SC.ArchiveFiles(PackagePath, Path.GetFileName(FinalDataLocation)); SC.ArchiveFiles(PackagePath, Path.GetFileName(FinalDataLocation + ".js")); SC.ArchiveFiles(PackagePath, Path.GetFileName(GameExe)); SC.ArchiveFiles(PackagePath, Path.GetFileName(GameExe + ".mem")); SC.ArchiveFiles(PackagePath, Path.GetFileName("json2.js")); SC.ArchiveFiles(PackagePath, Path.GetFileName("jstorage.js")); SC.ArchiveFiles(PackagePath, Path.GetFileName("moz_binarystring.js")); SC.ArchiveFiles(PackagePath, Path.GetFileName(OutputFile)); }
public static void ApplyStagingManifest(ProjectParams Params, DeploymentContext SC) { MaybeConvertToLowerCase(Params, SC); if (SC.Stage && !Params.NoCleanStage && !Params.SkipStage) { DeleteDirectory(SC.StageDirectory); } if (ShouldCreatePak(Params, SC)) { if (Params.Manifests && DoesChunkPakManifestExist(Params, SC)) { CreatePaksUsingChunkManifests(Params, SC); } else { CreatePakUsingStagingManifest(Params, SC); } } if (!SC.Stage || Params.SkipStage) { return; } DumpManifest(SC, CombinePaths(CmdEnv.LogFolder, "FinalCopy" + (SC.DedicatedServer ? "_Server" : "")), !Params.UsePak(SC.StageTargetPlatform)); CopyUsingStagingManifest(Params, SC); var ThisPlatform = SC.StageTargetPlatform; ThisPlatform.PostStagingFileCopy(Params, SC); }
public void OnDeploymentTaskStarting(DeploymentTask deploymentTask, DeploymentContext deploymentContext) { if (deploymentTask.TargetEnvironmentName == ProductionEnvironmentName && deploymentTask.ProjectConfigurationName != ProductionProjectConfigurationName) { throw new InvalidOperationException(string.Format("Can't deploy project ('{0}') with non-production configuration ('{1}') to the production environment!", deploymentTask.ProjectName, deploymentTask.ProjectConfigurationName)); } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "*", false, null, CommandUtils.CombinePaths(SC.RelativeProjectRootForStage, "Binaries", SC.PlatformDir), false); if (SC.bStageCrashReporter) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "CrashReportClient", false); } }
public override bool HookValidForPackage(DeploymentContext context) { Site site; LocateMsDeploy(context.GetLoggerFor(this)); var iis7SiteInstance = FindIis7Website(context.Package.Title); return context.Package.Tags.ToLower().Split(' ', ',', ';').Contains("website") && !string.IsNullOrEmpty(MsWebDeployPath) && TryFindIis7Website(context.Package.Id, out site); }
public override void BeforeDeploy(DeploymentContext context) { var logger = context.GetLoggerFor(this); if (!EnvironmentIsValidForPackage(context)) { return; } ShutdownRequiredServices(context, logger); }
private int StageExecutable(string Ext, DeploymentContext SC, string InPath, string Wildcard = "*", bool bRecursive = true, string[] ExcludeWildcard = null, string NewPath = null, bool bAllowNone = false, StagedFileType InStageFileType = StagedFileType.NonUFS, string NewName = null) { int Result = SC.StageFiles(InStageFileType, InPath, Wildcard + Ext, bRecursive, ExcludeWildcard, NewPath, bAllowNone, true, (NewName == null) ? null : (NewName + Ext)); if (Result > 0) { SC.StageFiles(StagedFileType.DebugNonUFS, InPath, Wildcard + "pdb", bRecursive, ExcludeWildcard, NewPath, true, true, (NewName == null) ? null : (NewName + "pdb")); SC.StageFiles(StagedFileType.DebugNonUFS, InPath, Wildcard + "map", bRecursive, ExcludeWildcard, NewPath, true, true, (NewName == null) ? null : (NewName + "map")); } return Result; }
public override void BeforeDeploy(DeploymentContext context) { var logger = context.GetLoggerFor(this); var appPools = GetApplicationPoolsForWebsite(context.Package.Title); foreach (var appPool in appPools) { logger.InfoFormat("Stopping application pool {0}", appPool.Name); appPool.Stop(); } }
public override List<string> GetExecutableNames(DeploymentContext SC, bool bIsRun = false) { List<string> Exes = base.GetExecutableNames(SC, bIsRun); // replace the binary name to match what was staged if (bIsRun && !SC.IsCodeBasedProject) { Exes[0] = CommandUtils.CombinePaths(SC.StageProjectRoot, "Binaries", SC.PlatformDir, SC.ShortProjectName); } return Exes; }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // Engine non-ufs (binaries) if (SC.bStageCrashReporter) { StageExecutable("exe", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "CrashReportClient."); } // Stage all the build products foreach(TargetReceipt Receipt in SC.StageTargetReceipts) { SC.StageBuildProductsFromReceipt(Receipt); } // Copy the splash screen, windows specific SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Splash"), "Splash.bmp", false, null, null, true); // Stage the bootstrap executable if(!Params.NoBootstrapExe) { foreach(TargetReceipt Receipt in SC.StageTargetReceipts) { BuildProduct Executable = Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if(Executable != null) { // only create bootstraps for executables if (SC.NonUFSStagingFiles.ContainsKey(Executable.Path) && Path.GetExtension(Executable.Path) == ".exe") { string BootstrapArguments = ""; if (!SC.IsCodeBasedProject && !ShouldStageCommandLine(Params, SC)) { BootstrapArguments = String.Format("..\\..\\..\\{0}\\{0}.uproject", SC.ShortProjectName); } string BootstrapExeName; if(SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Path.GetFileName(Executable.Path); } else if(Params.IsCodeBasedProject) { BootstrapExeName = Receipt.GetProperty("TargetName", SC.ShortProjectName) + ".exe"; } else { BootstrapExeName = SC.ShortProjectName + ".exe"; } StageBootstrapExecutable(SC, BootstrapExeName, Executable.Path, SC.NonUFSStagingFiles[Executable.Path], BootstrapArguments); } } } } }
/// <summary> /// Performs a deployment. /// </summary> /// <param name="context">The deployment context.</param> public void Deploy(DeploymentContext context) { var id = context.PluginDefinition.PluginIdentity; var ctx = context.PluginConfiguration.GetContext(ExportContext); var item = ctx.PluginExports.Where(x => string.Compare(id, x.PluginIdentity) == 0).FirstOrDefault(); if (item == null) ctx.PluginExports.Add(item = new PluginExportConfiguration() { PluginIdentity = id }); item.IsActive = true; if (!item.ExportProviders.Contains(Filename)) item.ExportProviders.Add(Filename); }
public ProgressReport(DeploymentContext deploymentContext, Type reportingType, string packageId, string version, string installationTaskId, string message, string level="Info", Exception exception=null) { Level = level; PackageId = packageId; Version = version; InstallationTaskId = installationTaskId; Message = message; Exception = exception; Context = deploymentContext; ReportingType = reportingType; }
public static void ApplyArchiveManifest(ProjectParams Params, DeploymentContext SC) { if (SC.ArchivedFiles.Count > 0) { foreach (var Pair in SC.ArchivedFiles) { string Src = Pair.Key; string Dest = CombinePaths(SC.ArchiveDirectory, Pair.Value); CopyFileIncremental(Src, Dest); } } }
public static void ApplyStagingManifest(ProjectParams Params, DeploymentContext SC) { MaybeConvertToLowerCase(Params, SC); if (SC.Stage && !Params.NoCleanStage && !Params.SkipStage && !Params.IterativeDeploy) { try { DeleteDirectory(SC.StageDirectory); } catch (Exception Ex) { // Delete cooked data (if any) as it may be incomplete / corrupted. Log("Failed to delete staging directory "+SC.StageDirectory); AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_FailedToDeleteStagingDirectory); throw Ex; } } else { try { // delete old pak files DeletePakFiles(SC.StageDirectory); } catch (Exception Ex) { // Delete cooked data (if any) as it may be incomplete / corrupted. Log("Failed to delete pak files in "+SC.StageDirectory); AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_FailedToDeleteStagingDirectory); throw Ex; } } if (ShouldCreatePak(Params, SC)) { if (Params.Manifests && DoesChunkPakManifestExist(Params, SC)) { CreatePaksUsingChunkManifests(Params, SC); } else { CreatePakUsingStagingManifest(Params, SC); } } if (!SC.Stage || Params.SkipStage) { return; } DumpManifest(SC, CombinePaths(CmdEnv.LogFolder, "FinalCopy" + (SC.DedicatedServer ? "_Server" : "")), !Params.UsePak(SC.StageTargetPlatform)); CopyUsingStagingManifest(Params, SC); var ThisPlatform = SC.StageTargetPlatform; ThisPlatform.PostStagingFileCopy(Params, SC); }
public override void AfterDeploy(DeploymentContext context) { var logger = context.GetLoggerFor(this); logger.Info("Removing app_offline.htm to destination"); var appOfflineFilePath = Path.Combine(context.TargetInstallationFolder, APP_OFFLINE_FILE); if (_fileSystem.File.Exists(appOfflineFilePath)) { _fileSystem.File.Delete(appOfflineFilePath); } }
public override void Deploy(DeploymentContext context) { if (!EnvironmentIsValidForPackage(context)) { return; } // services are installed in a '\services' subfolder context.TargetInstallationFolder = Path.Combine(_serviceInstallationPath, context.Package.Id); CopyAllFilesToDestination(context); }
public static void CreateArchiveManifest(ProjectParams Params, DeploymentContext SC) { if (!Params.Archive) { return; } var ThisPlatform = SC.StageTargetPlatform; ThisPlatform.GetFilesToArchive(Params, SC); //@todo add any archive meta data files as needed }
public override void Deploy(ProjectParams Params, DeploymentContext SC) { string AdbCommand = GetAdbCommand(Params); string ApkName = GetFinalApkName(Params, SC.StageExecutables[0], false); string DeviceObbName = GetDeviceObbName(ApkName); string PackageName = GetPackageInfo(ApkName, false); // install the apk string UninstallCommandline = AdbCommand + "uninstall " + PackageName; RunAndLog(CmdEnv, CmdEnv.CmdExe, UninstallCommandline); string InstallCommandline = AdbCommand + "install \"" + ApkName + "\""; RunAndLog(CmdEnv, CmdEnv.CmdExe, InstallCommandline); // copy files to device if we were staging if (SC.Stage) { // cache some strings string BaseCommandline = AdbCommand + "push"; string RemoteDir = "/mnt/sdcard/" + Params.ShortProjectName; string UE4GameRemoteDir = "/mnt/sdcard/" + Params.ShortProjectName; // make sure device is at a clean state Run(CmdEnv.CmdExe, AdbCommand + "shell rm -rf " + RemoteDir); Run(CmdEnv.CmdExe, AdbCommand + "shell rm -rf " + UE4GameRemoteDir); string[] Files = Directory.GetFiles(SC.StageDirectory, "*", SearchOption.AllDirectories); // copy each UFS file foreach (string Filename in Files) { // don't push the apk, we install it if (Path.GetExtension(Filename).Equals(".apk", StringComparison.InvariantCultureIgnoreCase)) { continue; } string FinalRemoteDir = RemoteDir; // handle the special case of the UE4Commandline.txt when using content only game (UE4Game) if (!Params.IsCodeBasedProject && Path.GetFileName(Filename).Equals("UE4CommandLine.txt", StringComparison.InvariantCultureIgnoreCase)) { FinalRemoteDir = "/mnt/sdcard/UE4Game"; } string RemoteFilename = Filename.Replace(SC.StageDirectory, FinalRemoteDir).Replace("\\", "/"); string Commandline = string.Format("{0} \"{1}\" \"{2}\"", BaseCommandline, Filename, RemoteFilename); Run(CmdEnv.CmdExe, Commandline); } // delete the .obb file, since it will cause nothing we just deployed to be used Run(CmdEnv.CmdExe, AdbCommand + "shell rm -f " + DeviceObbName); } }
public bool Deploy(string taskId, IPackage package, CancellationTokenSource cancellationToken, Action<ProgressReport> reportProgress) { var unpackFolder = Path.Combine(AgentSettings.AgentProgramDataPath, _agentSettingsManager.Settings.UnpackingLocation); var workingFolder = Path.Combine(unpackFolder, package.GetFullName()); var targetInstallationFolder = Path.Combine(_agentSettingsManager.Settings.BaseInstallationPath, package.Id); using (var deploymentContext = new DeploymentContext(package, _agentSettingsManager, workingFolder, targetInstallationFolder, taskId)) { var logger = deploymentContext.GetLoggerFor(this); var frameworks = package.GetSupportedFrameworks(); foreach (var framework in frameworks) { logger.DebugFormat("package supports {0}", framework.FullName); } try { reportProgress(ProgressReport.Info(deploymentContext, this, package.Id, package.Version.Version.ToString(), taskId, "Extracting package to temp folder...")); new NuGetPackageExtractor(Logger).Extract(package, workingFolder); } catch (Exception ex) { logger.Fatal("Could not extract package", ex); } try { BeforeDeploy(deploymentContext, reportProgress); PerformDeploy(deploymentContext, reportProgress); AfterDeploy(deploymentContext, reportProgress); reportProgress(ProgressReport.Info(deploymentContext, this, package.Id, package.Version.Version.ToString(), taskId, "Deployment complete")); return true; } catch (Exception ex) { logger.Error("An error occurred", ex); reportProgress(ProgressReport.Error(deploymentContext, this, package.Id, package.Version.Version.ToString(), taskId, "Deployment failed", ex)); return false; } finally { deploymentContext.RemoveAppender(); } } }
public override void AfterDeploy(DeploymentContext context, Action<ProgressReport> reportProgress) { var logger = context.GetLoggerFor(this); logger.Info("Removing app_offline.htm from destination"); reportProgress(new ProgressReport(context, GetType(), "Removing app_offline.htm from destination")); var appOfflineFilePath = Path.Combine(context.TargetInstallationFolder, APP_OFFLINE_FILE); if (_fileSystem.File.Exists(appOfflineFilePath)) { _fileSystem.File.Delete(appOfflineFilePath); } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { SC.bIsCombiningMultiplePlatforms = true; string SavedPlatformDir = SC.PlatformDir; foreach (UnrealTargetPlatform DesktopPlatform in GetStagePlatforms()) { Platform SubPlatform = Platform.Platforms[DesktopPlatform]; SC.PlatformDir = DesktopPlatform.ToString(); SubPlatform.GetFilesToDeployOrStage(Params, SC); } SC.PlatformDir = SavedPlatformDir; SC.bIsCombiningMultiplePlatforms = false; }
private void SafeCleanWebConfig(DeploymentContext context) { try { var git = new GitExecutable(Environment.RepositoryPath, DeploymentSettings.GetCommandIdleTimeout()); string webConfigPath = Path.Combine(ProjectPath, "web.config"); git.Execute("clean -f " + webConfigPath); } catch (Exception ex) { context.Logger.Log(ex); } }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { SC.bIsCombiningMultiplePlatforms = true; string SavedPlatformDir = SC.PlatformDir; foreach (UnrealTargetPlatform DesktopPlatform in GetStagePlatforms()) { Platform SubPlatform = Platform.GetPlatform(DesktopPlatform); SC.PlatformDir = DesktopPlatform.ToString(); SubPlatform.Package(Params, SC, WorkingCL); } SC.PlatformDir = SavedPlatformDir; SC.bIsCombiningMultiplePlatforms = false; }
public override void AfterDeploy(DeploymentContext context, Action<ProgressReport> reportProgress) { var logger = context.GetLoggerFor(this); reportProgress(new ProgressReport(context, GetType(), "Starting application pool(s)")); var appPools = GetApplicationPoolsForWebsite(context.Package.Title); foreach(var appPool in appPools) { if (appPool.State == ObjectState.Stopped) { logger.InfoFormat("Starting application pool {0}", appPool.Name); appPool.Start(); } } }
public override void AfterDeploy(DeploymentContext context, Action<ProgressReport> reportProgress) { var logger = context.GetLoggerFor(this); if (!EnvironmentIsValidForPackage(context)) { return; } reportProgress(new ProgressReport(context, GetType(), "Starting service")); var pathToExecutable = Path.Combine(Path.Combine(_serviceInstallationPath, context.Package.Id), context.Package.Id + ".exe"); var serviceName = DetermineServiceName(context, pathToExecutable, logger); // if no such service then install it using (var service = GetServiceByNameOrDisplayName(serviceName)) { if (service == null) { logger.InfoFormat("Installing service {0} from {1}", serviceName, pathToExecutable); ManagedInstallerClass.InstallHelper(new[] {pathToExecutable}); serviceName = DetermineServiceName(context, pathToExecutable, logger); } } // check that installation succeeded using (var service = GetServiceByNameOrDisplayName(serviceName)) { // it didn't... installutil might be presenting a credentials dialog on the terminal if (service == null) { throw new InstallException( string.Format( "The executable {0} was installed, so a service named '{1}' was expected but it could not be found", Path.GetFileNameWithoutExtension(pathToExecutable), serviceName)); } } using (var service = GetServiceByNameOrDisplayName(serviceName)) { if (!service.Status.Equals(ServiceControllerStatus.Stopped) && !service.Status.Equals(ServiceControllerStatus.StopPending)) { return; } ChangeServiceStateTo(service, ServiceControllerStatus.Running, service.Start, logger); } }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { 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 Console.WriteLine("Staging all {0} build products", SC.StageTargets.Count); int BuildProductIdx = 0; foreach (StageTarget Target in SC.StageTargets) { Console.WriteLine(" Product {0}: {1}", BuildProductIdx, Target.Receipt.TargetName); SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles); ++BuildProductIdx; } 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 string FullExecutablePath = Path.GetFullPath(Executable.Path.FullName); if (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); } else if (Params.IsCodeBasedProject) { BootstrapExeName = Target.Receipt.TargetName; } else { BootstrapExeName = SC.ShortProjectName; } List <StagedFileReference> StagePaths = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList(); foreach (StagedFileReference StagePath in StagePaths) { //#nv begin #Blast Linux build StageBootstrapExecutable(SC, Target, BootstrapExeName + ".sh", FullExecutablePath, StagePath.Name, BootstrapArguments); //@third party code - NVSTUDIOS Set LD_LIBRARY_PATH //nv end } } } } } }
/// <summary> /// Allow platform specific work prior to touching the staging directory /// </summary> /// <param name="Params"></param> /// <param name="SC"></param> public virtual void PreStage(ProjectParams Params, DeploymentContext SC) { // do nothing on most platforms }
public void OnDeploymentTaskStarting(DeploymentInfo deploymentInfo, DeploymentTask deploymentTask, DeploymentContext deploymentContext) { if (deploymentInfo.TargetEnvironmentName == ProductionEnvironmentName && deploymentInfo.ProjectConfigurationName != ProductionProjectConfigurationName) { throw new InvalidOperationException(string.Format( "Can't deploy project ('{0}') with non-production configuration ('{1}') to the production environment!", deploymentInfo.ProjectName, deploymentInfo.ProjectConfigurationName)); } }
private void StageAppBundle(DeploymentContext SC, StagedFileType InStageFileType, string InPath, string NewName) { SC.StageFiles(InStageFileType, InPath, "*", true, null, NewName, false, true, null); }
public virtual List <string> GetExecutableNames(DeploymentContext SC, bool bIsRun = false) { var ExecutableNames = new List <String>(); string Ext = AutomationTool.Platform.GetExeExtension(SC.StageTargetPlatform.TargetPlatformType); if (!String.IsNullOrEmpty(SC.CookPlatform)) { if (SC.StageExecutables.Count() > 0) { foreach (var StageExecutable in SC.StageExecutables) { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(StageExecutable); if (!SC.IsCodeBasedProject) { ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } else { ExecutableNames.Add(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext)); } } } //@todo, probably the rest of this can go away once everything passes it through else if (SC.DedicatedServer) { if (!SC.IsCodeBasedProject) { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName("UE4Server"); ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } else { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(SC.ShortProjectName + "Server"); string ClientApp = CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext); var TestApp = CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir, SC.ShortProjectName + "Server" + Ext); string Game = "Game"; //@todo, this is sketchy, someone might ask what the exe is before it is compiled if (!FileExists_NoExceptions(ClientApp) && !FileExists_NoExceptions(TestApp) && SC.ShortProjectName.EndsWith(Game, StringComparison.InvariantCultureIgnoreCase)) { ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(SC.ShortProjectName.Substring(0, SC.ShortProjectName.Length - Game.Length) + "Server"); ClientApp = CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext); } ExecutableNames.Add(ClientApp); } } else { if (!SC.IsCodeBasedProject) { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName("UE4Game"); ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } else { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName(SC.ShortProjectName); ExecutableNames.Add(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir, ExeName + Ext)); } } } else { string ExeName = SC.StageTargetPlatform.GetPlatformExecutableName("UE4Editor"); ExecutableNames.Add(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir, ExeName + Ext)); } return(ExecutableNames); }
/// <summary> /// Deploy the application on the current platform /// </summary> /// <param name="Params"></param> /// <param name="SC"></param> public virtual void Deploy(ProjectParams Params, DeploymentContext SC) { LogWarning("{0} does not implement Deploy...", PlatformType); }
/// <summary> /// Allow platform to do platform specific work on archived project before it's deployed. /// </summary> /// <param name="Params"></param> /// <param name="SC"></param> public virtual void ProcessArchivedProject(ProjectParams Params, DeploymentContext SC) { }
/// <summary> /// Package files for the current platform. /// </summary> /// <param name="ProjectPath"></param> /// <param name="ProjectExeFilename"></param> public virtual void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { throw new AutomationException("{0} does not yet implement Packaging.", PlatformType); }
public void OnDeploymentTaskFinished(DeploymentInfo deploymentInfo, DeploymentTask deploymentTask, DeploymentContext deploymentContext) { // do nothing }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { // package up the program PrintRunTime(); }
/// <summary> /// Deploy the application on the current platform /// </summary> /// <param name="Params"></param> /// <param name="SC"></param> public override void Deploy(ProjectParams Params, DeploymentContext SC) { if (BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Linux) { foreach (string DeviceAddress in Params.DeviceNames) { string CookPlatformName = GetCookPlatform(Params.DedicatedServer, Params.Client); string SourcePath = CombinePaths(Params.BaseStageDirectory, CookPlatformName); if (!Directory.Exists(SourcePath)) { throw new AutomationException(string.Format("Source directory \"{0}\" must exist.", SourcePath)); } string DestPath = "./" + Params.ShortProjectName; List <FileReference> Exes = GetExecutableNames(SC); string BinaryName = ""; if (Exes.Count > 0) { // if stage directory does not end with "\\", insert one string Separator = ""; if (Params.BaseStageDirectory.Length > 0 && (Params.BaseStageDirectory.EndsWith("/") || Params.BaseStageDirectory.EndsWith("\\"))) { Separator = "/"; } BinaryName = Exes[0].FullName.Replace(Params.BaseStageDirectory, DestPath + Separator); BinaryName = BinaryName.Replace("\\", "/"); } // stage a shell script that makes running easy // Starting from 0, finds the first valid X11 connection xset is able to query // if it fails to find one it'll default to 0 and fail to connect. string Script = String.Format(@"#!/bin/bash VALID_DISPLAY=0 for i in `seq 0 16`; do DISPLAY=:$i xset -q > /dev/null 2>&1 if [ $? -eq 0 ] then VALID_DISPLAY=$i break fi done export DISPLAY=:$VALID_DISPLAY chmod +x {0} {0} $@ ", BinaryName, BinaryName); Script = Script.Replace("\r\n", "\n"); string ScriptFile = Path.Combine(SourcePath, "..", LaunchOnHelperShellScriptName); File.WriteAllText(ScriptFile, Script); if (!Params.IterativeDeploy) { // non-null input is essential, since RedirectStandardInput=true is needed for PLINK, see http://stackoverflow.com/questions/1910592/process-waitforexit-on-console-vs-windows-forms RunAndLog(CmdEnv, PlinkPath, String.Format("-batch -l {0} -pw {1} {2} rm -rf {3} && mkdir -p {3}", Params.DeviceUsername, Params.DevicePassword, Params.DeviceNames[0], DestPath), Input: ""); } else { // still make sure that the path exists RunAndLog(CmdEnv, PlinkPath, String.Format("-batch -l {0} -pw {1} {2} mkdir -p {3}", Params.DeviceUsername, Params.DevicePassword, Params.DeviceNames[0], DestPath), Input: ""); } // copy the contents RunAndLog(CmdEnv, PScpPath, String.Format("-batch -pw {0} -r \"{1}\" {2}", Params.DevicePassword, SourcePath, Params.DeviceUsername + "@" + DeviceAddress + ":" + DestPath)); // copy the helper script RunAndLog(CmdEnv, PScpPath, String.Format("-batch -pw {0} -r \"{1}\" {2}", Params.DevicePassword, ScriptFile, Params.DeviceUsername + "@" + DeviceAddress + ":" + DestPath)); string RemoteScriptFile = DestPath + "/" + LaunchOnHelperShellScriptName; // non-null input is essential, since RedirectStandardInput=true is needed for PLINK, see http://stackoverflow.com/questions/1910592/process-waitforexit-on-console-vs-windows-forms RunAndLog(CmdEnv, PlinkPath, String.Format(" -batch -l {0} -pw {1} {2} chmod +x {3}", Params.DeviceUsername, Params.DevicePassword, Params.DeviceNames[0], RemoteScriptFile), Input: ""); } } }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { // package up the program, potentially with an installer for Mac PrintRunTime(); }
public override void ProcessArchivedProject(ProjectParams Params, DeploymentContext SC) { string ExeName = SC.StageExecutables[0]; string BundlePath = CombinePaths(SC.ArchiveDirectory, SC.ShortProjectName + ".app"); if (SC.bIsCombiningMultiplePlatforms) { // when combining multiple platforms, don't merge the content into the .app, use the one in the Binaries directory BundlePath = CombinePaths(SC.ArchiveDirectory, SC.ShortProjectName, "Binaries", "Mac", ExeName + ".app"); if (!Directory.Exists(BundlePath)) { // if the .app wasn't there, just skip out (we don't require executables when combining) return; } } string TargetPath = CombinePaths(BundlePath, "Contents", "UE4"); if (!SC.bIsCombiningMultiplePlatforms) { if (!Directory.Exists(BundlePath)) { string SourceBundlePath = CombinePaths(SC.ArchiveDirectory, SC.ShortProjectName, "Binaries", "Mac", ExeName + ".app"); if (!Directory.Exists(SourceBundlePath)) { SourceBundlePath = CombinePaths(SC.ArchiveDirectory, "Engine", "Binaries", "Mac", ExeName + ".app"); } Directory.Move(SourceBundlePath, BundlePath); } if (DirectoryExists(TargetPath)) { Directory.Delete(TargetPath, true); } // First, move all files and folders inside he app bundle string[] StagedFiles = Directory.GetFiles(SC.ArchiveDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string FilePath in StagedFiles) { string TargetFilePath = CombinePaths(TargetPath, Path.GetFileName(FilePath)); Directory.CreateDirectory(Path.GetDirectoryName(TargetFilePath)); File.Move(FilePath, TargetFilePath); } string[] StagedDirectories = Directory.GetDirectories(SC.ArchiveDirectory, "*", SearchOption.TopDirectoryOnly); foreach (string DirPath in StagedDirectories) { string DirName = Path.GetFileName(DirPath); if (!DirName.EndsWith(".app")) { string TargetDirPath = CombinePaths(TargetPath, DirName); Directory.CreateDirectory(Path.GetDirectoryName(TargetDirPath)); Directory.Move(DirPath, TargetDirPath); } } } // Update executable name, icon and entry in Info.plist string UE4GamePath = CombinePaths(BundlePath, "Contents", "MacOS", ExeName); if (ExeName != SC.ShortProjectName && File.Exists(UE4GamePath)) { string GameExePath = CombinePaths(BundlePath, "Contents", "MacOS", SC.ShortProjectName); File.Delete(GameExePath); File.Move(UE4GamePath, GameExePath); string DefaultIconPath = CombinePaths(BundlePath, "Contents", "Resources", "UE4.icns"); string CustomIconSrcPath = CombinePaths(BundlePath, "Contents", "Resources", "Application.icns"); string CustomIconDestPath = CombinePaths(BundlePath, "Contents", "Resources", SC.ShortProjectName + ".icns"); if (File.Exists(CustomIconSrcPath)) { File.Delete(DefaultIconPath); File.Move(CustomIconSrcPath, CustomIconDestPath); } else { File.Move(DefaultIconPath, CustomIconDestPath); } string InfoPlistPath = CombinePaths(BundlePath, "Contents", "Info.plist"); string InfoPlistContents = File.ReadAllText(InfoPlistPath); InfoPlistContents = InfoPlistContents.Replace(ExeName, SC.ShortProjectName); InfoPlistContents = InfoPlistContents.Replace("<string>UE4</string>", "<string>" + SC.ShortProjectName + "</string>"); File.Delete(InfoPlistPath); File.WriteAllText(InfoPlistPath, InfoPlistContents); } if (!SC.bIsCombiningMultiplePlatforms) { // creating this directory when the content isn't moved into the application causes it // to fail to load, and isn't needed Directory.CreateDirectory(CombinePaths(TargetPath, ExeName.StartsWith("UE4Game") ? "Engine" : SC.ShortProjectName, "Binaries", "Mac")); } }
/// <summary> /// Get the files to deploy, specific to this platform, typically binaries /// </summary> /// <param name="SC">Deployment Context</param> public virtual void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { throw new AutomationException("{0} does not yet implement GetFilesToDeployOrStage.", PlatformType); }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { if (Params.StageNonMonolithic) { if (SC.DedicatedServer) { if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Development)) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UE4Server.app")); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4Server-" + SC.ShortProjectName + ".dylib"); } if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Test)) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UE4Server-Mac-Test.app")); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4Server-" + SC.ShortProjectName + "-Mac-Test.dylib"); } if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Shipping)) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UE4Server-Mac-Shipping.app")); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4Server-" + SC.ShortProjectName + "-Mac-Shipping.dylib"); } SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Plugins"), "UE4Server-*.dylib", true); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins"), "UE4Server-*.dylib", true); } else { if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Development)) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UE4.app")); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4-" + SC.ShortProjectName + ".dylib"); } if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Test)) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UE4-Mac-Test.app")); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4-" + SC.ShortProjectName + "-Mac-Test.dylib"); } if (SC.StageTargetConfigurations.Contains(UnrealTargetConfiguration.Shipping)) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UE4-Mac-Shipping.app")); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir), "UE4-" + SC.ShortProjectName + "-Mac-Shipping.dylib"); } SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Plugins"), "UE4-*.dylib", true); SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Plugins"), "UE4-*.dylib", true, null, null, true); } } else { // the first app is the "main" one, the rest are marked as debug files for exclusion from chunking/distribution StagedFileType WorkingFileType = StagedFileType.NonUFS; List <string> Exes = GetExecutableNames(SC); foreach (var Exe in Exes) { string AppBundlePath = ""; if (Exe.StartsWith(CombinePaths(SC.RuntimeProjectRootDir, "Binaries", SC.PlatformDir))) { AppBundlePath = CombinePaths(SC.ShortProjectName, "Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"); StageAppBundle(SC, WorkingFileType, CombinePaths(SC.ProjectRoot, "Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"), AppBundlePath); } else if (Exe.StartsWith(CombinePaths(SC.RuntimeRootDir, "Engine/Binaries", SC.PlatformDir))) { AppBundlePath = CombinePaths("Engine/Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"); string AbsoluteBundlePath = CombinePaths(SC.LocalRoot, AppBundlePath); // ensure the ue4game binary exists, if applicable if (!SC.IsCodeBasedProject && !Directory.Exists(AbsoluteBundlePath) && !SC.bIsCombiningMultiplePlatforms) { Log("Failed to find app bundle " + AbsoluteBundlePath); AutomationTool.ErrorReporter.Error("Stage Failed.", (int)AutomationTool.ErrorCodes.Error_MissingExecutable); throw new AutomationException("Could not find app bundle {0}. You may need to build the UE4 project with your target configuration and platform.", AbsoluteBundlePath); } StageAppBundle(SC, WorkingFileType, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, Path.GetFileNameWithoutExtension(Exe) + ".app"), AppBundlePath); } if (!string.IsNullOrEmpty(AppBundlePath)) { SC.StageFiles(WorkingFileType, CombinePaths(SC.ProjectRoot, "Build/Mac"), "Application.icns", false, null, CombinePaths(AppBundlePath, "Contents/Resources"), true); if (Params.bUsesSteam) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Source/ThirdParty/Steamworks/Steamv132/sdk/redistributable_bin/osx32"), "libsteam_api.dylib", false, null, CombinePaths(AppBundlePath, "Contents/MacOS"), true); } } // the first app is the "main" one, the rest are marked as debug files for exclusion from chunking/distribution WorkingFileType = StagedFileType.DebugNonUFS; } } // Copy the splash screen, Mac specific SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Splash"), "Splash.bmp", false, null, null, true); // CEF3 files if (Params.bUsesCEF3) { SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries/ThirdParty/CEF3/Mac/"), "*", true, null, null, true); string UnrealCEFSubProcessPath = CombinePaths("Engine/Binaries", SC.PlatformDir, "UnrealCEFSubProcess.app"); StageAppBundle(SC, StagedFileType.NonUFS, CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir, "UnrealCEFSubProcess.app"), UnrealCEFSubProcessPath); } }
public override bool ShouldStageCommandLine(ProjectParams Params, DeploymentContext SC) { return(false); }
public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC) { // Engine non-ufs (binaries) if (SC.bStageCrashReporter) { StageExecutable("exe", SC, CommandUtils.CombinePaths(SC.LocalRoot, "Engine/Binaries", SC.PlatformDir), "CrashReportClient."); } // Stage all the build products foreach (BuildReceipt Receipt in SC.StageTargetReceipts) { SC.StageBuildProductsFromReceipt(Receipt); } // Copy the splash screen, windows specific SC.StageFiles(StagedFileType.NonUFS, CombinePaths(SC.ProjectRoot, "Content/Splash"), "Splash.bmp", false, null, null, true); /*foreach (string StageExePath in GetExecutableNames(SC)) * { * // set the icon on the original exe this will be used in the task bar when the bootstrap exe runs * if (InternalUtils.SafeFileExists(CombinePaths(SC.ProjectRoot, "Build/Windows/Application.ico"))) * { * GroupIconResource GroupIcon = null; * GroupIcon = GroupIconResource.FromIco(CombinePaths(SC.ProjectRoot, "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(StageExePath, false)) * { * const int IconResourceId = 101; * if (GroupIcon != null) * { * Update.SetIcons(IconResourceId, GroupIcon); * } * } * } * }*/ // Stage the bootstrap executable if (!Params.NoBootstrapExe) { foreach (BuildReceipt Receipt in SC.StageTargetReceipts) { BuildProduct Executable = Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable); if (Executable != null) { // only create bootstraps for executables if (SC.NonUFSStagingFiles.ContainsKey(Executable.Path) && Path.GetExtension(Executable.Path) == ".exe") { string BootstrapArguments = ""; if (!SC.IsCodeBasedProject && !ShouldStageCommandLine(Params, SC)) { BootstrapArguments = String.Format("..\\..\\..\\{0}\\{0}.uproject", SC.ShortProjectName); } string BootstrapExeName; if (SC.StageTargetConfigurations.Count > 1) { BootstrapExeName = Path.GetFileName(Executable.Path); } else if (Params.IsCodeBasedProject) { BootstrapExeName = Receipt.GetProperty("TargetName", SC.ShortProjectName) + ".exe"; } else { BootstrapExeName = SC.ShortProjectName + ".exe"; } StageBootstrapExecutable(SC, BootstrapExeName, Executable.Path, SC.NonUFSStagingFiles[Executable.Path], BootstrapArguments); } } } } }
public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL) { string[] Architectures = UnrealBuildTool.AndroidToolChain.GetAllArchitectures(); string[] GPUArchitectures = UnrealBuildTool.AndroidToolChain.GetAllGPUArchitectures(); bool bMakeSeparateApks = UnrealBuildTool.Android.UEDeployAndroid.ShouldMakeSeparateApks(); foreach (string Architecture in Architectures) { foreach (string GPUArchitecture in GPUArchitectures) { string ApkName = GetFinalApkName(Params, SC.StageExecutables[0], true, bMakeSeparateApks ? Architecture : "", bMakeSeparateApks ? GPUArchitecture : ""); string BatchName = GetFinalBatchName(ApkName, Params, bMakeSeparateApks ? Architecture : "", bMakeSeparateApks ? GPUArchitecture : ""); // packaging just takes a pak file and makes it the .obb UEBuildConfiguration.bOBBinAPK = Params.OBBinAPK; // Make sure this setting is sync'd pre-build var Deploy = UEBuildDeploy.GetBuildDeploy(UnrealTargetPlatform.Android); if (!Params.Prebuilt) { string CookFlavor = SC.FinalCookPlatform.IndexOf("_") > 0 ? SC.FinalCookPlatform.Substring(SC.FinalCookPlatform.IndexOf("_")) : ""; string SOName = GetSONameWithoutArchitecture(Params, SC.StageExecutables[0]); Deploy.PrepForUATPackageOrDeploy(Params.ShortProjectName, SC.ProjectRoot, SOName, SC.LocalRoot + "/Engine", Params.Distribution, CookFlavor); } // first, look for a .pak file in the staged directory string[] PakFiles = Directory.GetFiles(SC.StageDirectory, "*.pak", SearchOption.AllDirectories); bool bHasPakFile = PakFiles.Length >= 1; // for now, we only support 1 pak/obb file if (PakFiles.Length > 1) { string ErrorString = String.Format("Can't package for Android with 0 or more than 1 pak file (found {0} pak files in {1})", PakFiles.Length, SC.StageDirectory); ErrorReporter.Error(ErrorString, (int)ErrorCodes.Error_OnlyOneObbFileSupported); throw new AutomationException(ErrorString); } string LocalObbName = GetFinalObbName(ApkName); string DeviceObbName = GetDeviceObbName(ApkName); // Always delete the target OBB file if it exists if (File.Exists(LocalObbName)) { File.Delete(LocalObbName); } if (!Params.OBBinAPK && bHasPakFile) { Log("Creating {0} from {1}", LocalObbName, PakFiles[0]); File.Copy(PakFiles[0], LocalObbName); } Log("Writing bat for install with {0}", Params.OBBinAPK ? "OBB in APK" : "OBB separate"); string PackageName = GetPackageInfo(ApkName, false); // make a batch file that can be used to install the .apk and .obb files string[] BatchLines = new string[] { "setlocal", "set ADB=%ANDROID_HOME%\\platform-tools\\adb.exe", "set DEVICE=", "if not \"%1\"==\"\" set DEVICE=-s %1", "for /f \"delims=\" %%A in ('adb " + GetStorageQueryCommand() + "') do @set STORAGE=%%A", "%ADB% %DEVICE% uninstall " + PackageName, "%ADB% %DEVICE% install " + Path.GetFileName(ApkName), "@if \"%ERRORLEVEL%\" NEQ \"0\" goto Error", "%ADB% %DEVICE% shell rm -r %STORAGE%/" + Params.ShortProjectName, "%ADB% %DEVICE% shell rm -r %STORAGE%/UE4Game/UE4CommandLine.txt", // we need to delete the commandline in UE4Game or it will mess up loading "%ADB% %DEVICE% shell rm -r %STORAGE%/obb/" + PackageName, Params.OBBinAPK || !bHasPakFile ? "" : "%ADB% %DEVICE% push " + Path.GetFileName(LocalObbName) + " %STORAGE%/" + DeviceObbName, Params.OBBinAPK || !bHasPakFile ? "" : "if \"%ERRORLEVEL%\" NEQ \"0\" goto Error", "goto:eof", ":Error", "@echo.", "@echo There was an error installing the game or the obb file. Look above for more info.", "@echo.", "@echo Things to try:", "@echo Check that the device (and only the device) is listed with \"%ADB$ devices\" from a command prompt.", "@echo Make sure all Developer options look normal on the device", "@echo Check that the device has an SD card.", "@pause" }; File.WriteAllLines(BatchName, BatchLines); } } PrintRunTime(); }
public override bool ShouldStageCommandLine(ProjectParams Params, DeploymentContext SC) { return(false); // !String.IsNullOrEmpty(Params.StageCommandline) || !String.IsNullOrEmpty(Params.RunCommandline) || (!Params.IsCodeBasedProject && Params.NoBootstrapExe); }
/// <summary> /// Determines whether we should stage a UE4CommandLine.txt for this platform /// </summary> public virtual bool ShouldStageCommandLine(ProjectParams Params, DeploymentContext SC) { return(true); }
/// <summary> /// Returns platform specific command line options for UnrealPak /// </summary> public virtual string GetPlatformPakCommandLine(ProjectParams Params, DeploymentContext SC) { return(""); }
public virtual bool RetrieveDeployedManifests(ProjectParams Params, DeploymentContext SC, string DeviceName, out List <string> UFSManifests, out List <string> NonUFSManifests) { UFSManifests = null; NonUFSManifests = null; return(false); }
public override void Deploy(ProjectParams Params, DeploymentContext SC) { string DeviceArchitecture = GetBestDeviceArchitecture(Params); string GPUArchitecture = ""; string AdbCommand = GetAdbCommand(Params); string ApkName = GetFinalApkName(Params, SC.StageExecutables[0], true, DeviceArchitecture, GPUArchitecture); // make sure APK is up to date (this is fast if so) var Deploy = UEBuildDeploy.GetBuildDeploy(UnrealTargetPlatform.Android); if (!Params.Prebuilt) { string CookFlavor = SC.FinalCookPlatform.IndexOf("_") > 0 ? SC.FinalCookPlatform.Substring(SC.FinalCookPlatform.IndexOf("_")) : ""; string SOName = GetSONameWithoutArchitecture(Params, SC.StageExecutables[0]); Deploy.PrepForUATPackageOrDeploy(Params.ShortProjectName, SC.ProjectRoot, SOName, SC.LocalRoot + "/Engine", Params.Distribution, CookFlavor); } // check the APK exists if (!File.Exists(ApkName)) { ErrorReporter.Error(String.Format("Could not find apk '{0}'", ApkName), (int)ErrorCodes.Error_AppNotFound); throw new AutomationException("Could not find apk '{0}'", ApkName); } // now we can use the apk to get more info string PackageName = GetPackageInfo(ApkName, false); // try uninstalling an old app with the same identifier. string UninstallCommandline = AdbCommand + "uninstall " + PackageName; int SuccessCode = 0; RunAndLog(CmdEnv, CmdEnv.CmdExe, UninstallCommandline, out SuccessCode); // install the apk SuccessCode = 0; string InstallCommandline = AdbCommand + "install \"" + ApkName + "\""; string InstallOutput = RunAndLog(CmdEnv, CmdEnv.CmdExe, InstallCommandline, out SuccessCode); int FailureIndex = InstallOutput.IndexOf("Failure"); // adb install doesn't always return an error code on failure, and instead prints "Failure", followed by an error code. if (SuccessCode != 0 || FailureIndex != -1) { string ErrorMessage = String.Format("Installation of apk '{0}' failed", ApkName); if (FailureIndex != -1) { string FailureString = InstallOutput.Substring(FailureIndex + 7).Trim(); if (FailureString != "") { ErrorMessage += ": " + FailureString; } } ErrorReporter.Error(ErrorMessage, (int)ErrorCodes.Error_AppInstallFailed); throw new AutomationException(ErrorMessage); } // update the ue4commandline.txt // update and deploy ue4commandline.txt // always delete the existing commandline text file, so it doesn't reuse an old one string IntermediateCmdLineFile = CombinePaths(SC.StageDirectory, "UE4CommandLine.txt"); Project.WriteStageCommandline(IntermediateCmdLineFile, Params, SC); // Setup the OBB name and add the storage path (queried from the device) to it string DeviceStorageQueryCommand = GetStorageQueryCommand(); ProcessResult Result = Run(CmdEnv.CmdExe, AdbCommand + DeviceStorageQueryCommand, null, ERunOptions.AppMustExist); String StorageLocation = Result.Output.Trim(); string DeviceObbName = StorageLocation + "/" + GetDeviceObbName(ApkName); // copy files to device if we were staging if (SC.Stage) { // cache some strings string BaseCommandline = AdbCommand + "push"; string RemoteDir = StorageLocation + "/" + Params.ShortProjectName; string UE4GameRemoteDir = StorageLocation + "/" + Params.ShortProjectName; // make sure device is at a clean state Run(CmdEnv.CmdExe, AdbCommand + "shell rm -r " + RemoteDir); Run(CmdEnv.CmdExe, AdbCommand + "shell rm -r " + UE4GameRemoteDir); // Copy UFS files.. string[] Files = Directory.GetFiles(SC.StageDirectory, "*", SearchOption.AllDirectories); System.Array.Sort(Files); // Find all the files we exclude from copying. And include // the directories we need to individually copy. HashSet <string> ExcludedFiles = new HashSet <string>(); SortedSet <string> IndividualCopyDirectories = new SortedSet <string>((IComparer <string>) new LongestFirst()); foreach (string Filename in Files) { bool Exclude = false; // Don't push the apk, we install it Exclude |= Path.GetExtension(Filename).Equals(".apk", StringComparison.InvariantCultureIgnoreCase); // For excluded files we add the parent dirs to our // tracking of stuff to individually copy. if (Exclude) { ExcludedFiles.Add(Filename); // We include all directories up to the stage root in having // to individually copy the files. for (string FileDirectory = Path.GetDirectoryName(Filename); !FileDirectory.Equals(SC.StageDirectory); FileDirectory = Path.GetDirectoryName(FileDirectory)) { if (!IndividualCopyDirectories.Contains(FileDirectory)) { IndividualCopyDirectories.Add(FileDirectory); } } if (!IndividualCopyDirectories.Contains(SC.StageDirectory)) { IndividualCopyDirectories.Add(SC.StageDirectory); } } } // The directories are sorted above in "deepest" first. We can // therefore start copying those individual dirs which will // recreate the tree. As the subtrees will get copied at each // possible individual level. HashSet <string> EntriesToDeploy = new HashSet <string>(); foreach (string DirectoryName in IndividualCopyDirectories) { string[] Entries = Directory.GetFileSystemEntries(DirectoryName, "*", SearchOption.TopDirectoryOnly); foreach (string Entry in Entries) { // We avoid excluded files and the individual copy dirs // (the individual copy dirs will get handled as we iterate). if (ExcludedFiles.Contains(Entry) || IndividualCopyDirectories.Contains(Entry)) { continue; } else { EntriesToDeploy.Add(Entry); } } } if (EntriesToDeploy.Count == 0) { EntriesToDeploy.Add(SC.StageDirectory); } // We now have a minimal set of file & dir entries we need // to deploy. Files we deploy will get individually copied // and dirs will get the tree copies by default (that's // what ADB does). HashSet <ProcessResult> DeployCommands = new HashSet <ProcessResult>(); foreach (string Entry in EntriesToDeploy) { string FinalRemoteDir = RemoteDir; string RemotePath = Entry.Replace(SC.StageDirectory, FinalRemoteDir).Replace("\\", "/"); string Commandline = string.Format("{0} \"{1}\" \"{2}\"", BaseCommandline, Entry, RemotePath); // We run deploy commands in parallel to maximize the connection // throughput. DeployCommands.Add( Run(CmdEnv.CmdExe, Commandline, null, ERunOptions.Default | ERunOptions.NoWaitForExit)); // But we limit the parallel commands to avoid overwhelming // memory resources. if (DeployCommands.Count == DeployMaxParallelCommands) { while (DeployCommands.Count > DeployMaxParallelCommands / 2) { Thread.Sleep(10); DeployCommands.RemoveWhere( delegate(ProcessResult r) { return(r.HasExited); }); } } } foreach (ProcessResult deploy_result in DeployCommands) { deploy_result.WaitForExit(); } // delete the .obb file, since it will cause nothing we just deployed to be used Run(CmdEnv.CmdExe, AdbCommand + "shell rm " + DeviceObbName); } else if (SC.Archive) { // deploy the obb if there is one string ObbPath = Path.Combine(SC.StageDirectory, GetFinalObbName(ApkName)); if (File.Exists(ObbPath)) { // cache some strings string BaseCommandline = AdbCommand + "push"; string Commandline = string.Format("{0} \"{1}\" \"{2}\"", BaseCommandline, ObbPath, DeviceObbName); Run(CmdEnv.CmdExe, Commandline); } } else { // cache some strings string BaseCommandline = AdbCommand + "push"; string RemoteDir = StorageLocation + "/" + Params.ShortProjectName; string FinalRemoteDir = RemoteDir; /* * // handle the special case of the UE4Commandline.txt when using content only game (UE4Game) * if (!Params.IsCodeBasedProject) * { * FinalRemoteDir = "/mnt/sdcard/UE4Game"; * } */ string RemoteFilename = IntermediateCmdLineFile.Replace(SC.StageDirectory, FinalRemoteDir).Replace("\\", "/"); string Commandline = string.Format("{0} \"{1}\" \"{2}\"", BaseCommandline, IntermediateCmdLineFile, RemoteFilename); Run(CmdEnv.CmdExe, Commandline); } }
public virtual bool SignExecutables(DeploymentContext SC, ProjectParams Params) { return(true); }
/// <summary> /// Called after CopyUsingStagingManifest. Does anything platform specific that requires a final list of staged files. /// e.g. PlayGo emulation control file generation for PS4. /// </summary> /// <param name="Params"></param> /// <param name="SC"></param> public virtual void PostStagingFileCopy(ProjectParams Params, DeploymentContext SC) { }
//#nv begin #Blast Linux build void StageBootstrapExecutable(DeploymentContext SC, StageTarget Target, string ExeName, string TargetFile, string StagedRelativeTargetPath, string StagedArguments) //@third party code - NVSTUDIOS Set LD_LIBRARY_PATH //nv end { // create a temp script file location DirectoryReference IntermediateDir = DirectoryReference.Combine(SC.ProjectRoot, "Intermediate", "Staging"); FileReference IntermediateFile = FileReference.Combine(IntermediateDir, ExeName); DirectoryReference.CreateDirectory(IntermediateDir); // make sure slashes are good StagedRelativeTargetPath = StagedRelativeTargetPath.Replace("\\", "/"); // make contents StringBuilder Script = new StringBuilder(); string EOL = "\n"; Script.Append("#!/bin/sh" + EOL); // allow running from symlinks Script.AppendFormat("UE4_TRUE_SCRIPT_NAME=$(echo \\\"$0\\\" | xargs readlink -f)" + EOL); Script.AppendFormat("UE4_PROJECT_ROOT=$(dirname \"$UE4_TRUE_SCRIPT_NAME\")" + EOL); Script.AppendFormat("chmod +x \"$UE4_PROJECT_ROOT/{0}\"" + EOL, StagedRelativeTargetPath); //#nv begin #Blast Linux build //The Blast .so files are not loaded by dlopen so we we need to setup the search paths //Really UE should be doing this for all dependent libraries, but they usually statically link HashSet <string> LDLibraryPaths = new HashSet <string>(); DirectoryReference TargetFileDir = (new FileReference(TargetFile)).Directory; DirectoryReference SourceEngineDir = SC.LocalRoot; DirectoryReference SourceProjectDir = SC.ProjectRoot; foreach (var RuntimeDependency in Target.Receipt.RuntimeDependencies) { foreach (FileReference File in CommandUtils.ResolveFilespec(CommandUtils.RootDirectory, RuntimeDependency.Path.FullName, new string[] { })) { if (FileReference.Exists(File) && File.GetExtension().Equals(".so", StringComparison.OrdinalIgnoreCase)) { string FileRelativePath = null; DirectoryReference SharedLibFolder = File.Directory; if (SharedLibFolder.IsUnderDirectory(SourceProjectDir)) { FileRelativePath = Path.Combine(SharedLibFolder.MakeRelativeTo(SourceProjectDir), SC.RelativeProjectRootForStage.ToString()); } else if (SharedLibFolder.IsUnderDirectory(SourceEngineDir)) { FileRelativePath = SharedLibFolder.MakeRelativeTo(SourceEngineDir); } if (FileRelativePath != null) { FileRelativePath = Path.Combine("$UE4_PROJECT_ROOT", FileRelativePath); FileRelativePath = FileRelativePath.Replace("\\", "/"); //Escape spaces FileRelativePath = FileRelativePath.Replace(" ", @"\ "); LDLibraryPaths.Add(FileRelativePath); } } } } if (LDLibraryPaths.Count > 0) { Script.AppendFormat("export LD_LIBRARY_PATH={0}" + EOL, string.Join(":", LDLibraryPaths)); } //nv end Script.AppendFormat("\"$UE4_PROJECT_ROOT/{0}\" {1} $@ " + EOL, StagedRelativeTargetPath, StagedArguments); // write out the FileReference.WriteAllText(IntermediateFile, Script.ToString()); if (Utils.IsRunningOnMono) { var Result = CommandUtils.Run("sh", string.Format("-c 'chmod +x \\\"{0}\\\"'", IntermediateFile)); if (Result.ExitCode != 0) { throw new AutomationException(string.Format("Failed to chmod \"{0}\"", IntermediateFile)); } } SC.StageFile(StagedFileType.NonUFS, IntermediateFile, new StagedFileReference(ExeName)); }
/// <summary> /// Get the files to deploy, specific to this platform, typically binaries /// </summary> /// <param name="SC">Deployment Context</param> public virtual void GetFilesToArchive(ProjectParams Params, DeploymentContext SC) { SC.ArchiveFiles(SC.StageDirectory); }
/// <summary> /// Returns true if the platform wants patches to generate a small .pak file containing the difference /// of current data against a shipped pak file. /// </summary> /// <returns></returns> public virtual bool GetPlatformPatchesWithDiffPak(ProjectParams Params, DeploymentContext SC) { return(true); }
public abstract Task Build(DeploymentContext context);
public DeploymentStarategyProvider(DeploymentContext deploymentContext) { _deploymentContext = deploymentContext; }