static public bool ExecuteCompileCommand(string Command, string RPCCommand) { switch (Command.ToLowerInvariant()) { case "clean": Program.Log("Cleaning temporary files from PC ... "); Program.Log(" ... cleaning: " + Config.PCStagingRootDir); FileOperations.DeleteDirectory(new DirectoryInfo(Config.PCStagingRootDir)); break; case "rpc": ExecuteRemoteCommand(RPCCommand); break; case "getipa": { Program.Log("Fetching IPA from Mac..."); string IpaDestFilename = Config.GetIPAPath(".ipa"); FileOperations.DownloadFile(MacName, MacStagingRootDir + "/" + Config.IPAFilenameOnMac, IpaDestFilename); Program.Log("... Saved IPA to '{0}'", Path.GetFullPath(IpaDestFilename)); } break; case "getstubipa": { Program.Log("Fetching stub IPA from Mac..."); string IpaDestFilename = Config.GetIPAPath(".stub"); FileOperations.DownloadFile(MacName, MacStagingRootDir + "/" + Config.IPAFilenameOnMac, IpaDestFilename); Program.Log("... Saved stub IPA to '{0}'", Path.GetFullPath(IpaDestFilename)); } break; case "stagemacfiles": Program.Log("Copying all staged files to Mac " + MacName + " ..."); FileOperations.BatchUploadFolder(MacName, Config.PCStagingRootDir, MacStagingRootDir, false); FileOperations.BatchUploadFolder(MacName, Config.PCXcodeStagingDir, MacXcodeStagingDir, false); break; case "exportcertificate": CompileTime.ExportCertificate(); break; default: return(false); } return(true); }
/** * Creates the application directory on the Mac */ static public void CreateApplicationDirOnMac() { DateTime StartTime = DateTime.Now; // Cleans out the intermediate folders on both ends CompileTime.ExecuteRemoteCommand("DeleteIPA"); CompileTime.ExecuteRemoteCommand("DeleteMacStagingFiles"); Program.ExecuteCommand("Clean", null); //@TODO: mnoland 10/5/2010 // Need to come up with a way to prevent this from causing an error on the remote machine // CompileTime.ExecuteRemoteCommand("Clean"); // Stage files Program.Log("Staging files before copying to Mac ..."); CopyFilesNeededForMakeApp(); // Copy staged files from PC to Mac Program.ExecuteCommand("StageMacFiles", null); // Set the executable bit on the EXE CompileTime.ExecuteRemoteCommand("SetExec"); // Install the provision (necessary for MakeApp to succeed) CompileTime.ExecuteRemoteCommand("EnsureProvisionDirExists"); CompileTime.ExecuteRemoteCommand("InstallProvision"); // strip the symbols if desired or required if (Config.bForceStripSymbols || Config.bForDistribution) { CompileTime.ExecuteRemoteCommand("Strip"); } // sign the exe, etc... CompileTime.ExecuteRemoteCommand("PrePackage"); if (!Config.bUseRPCUtil) { CompileTime.ExecuteRemoteCommand("DeleteKeyChain", true); CompileTime.ExecuteRemoteCommand("CreateKeyChain"); } CompileTime.ExecuteRemoteCommand("MakeApp"); if (!Config.bUseRPCUtil) { CompileTime.ExecuteRemoteCommand("DeleteKeyChain"); } Program.Log(String.Format("Finished creating .app directory on Mac (took {0:0.00} s)", (DateTime.Now - StartTime).TotalSeconds)); }
/** * Packages an IPA on the Mac */ static public void PackageIPAOnMac() { // Create the .app structure on the Mac (and codesign, etc...) CreateApplicationDirOnMac(); DateTime StartTime = DateTime.Now; // zip up CompileTime.ExecuteRemoteCommand("Zip"); // fetch the IPA if (Config.bCreateStubSet) { Program.ExecuteCommand("GetStubIPA", null); } else { Program.ExecuteCommand("GetIPA", null); } Program.Log(String.Format("Finished packaging into IPA (took {0:0.00} s)", (DateTime.Now - StartTime).TotalSeconds)); }
static public void DangerouslyFastMode() { CompileTime.ExecuteRemoteCommand("MakeApp"); }
static int Main(string[] args) { // remember the working directory at start, as the game path could be relative to this path string InitialCurrentDirectory = Environment.CurrentDirectory; // set the working directory to the location of the application (so relative paths always work) Environment.CurrentDirectory = Path.GetDirectoryName(Application.ExecutablePath); AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); // A simple, top-level try-catch block try { if (!ParseCommandLine(ref args)) { Log("Usage: iPhonePackager <Command> <GameName> [RPCCommand &| Switch]"); Log(""); Log("Common commands:"); Log(" ... RepackageIPA GameName"); Log(" ... PackageIPA GameName"); Log(" ... PackageApp GameName"); Log(" ... Deploy PathToIPA"); Log(" ... RepackageFromStage GameName"); Log(" ... Devices"); Log(" ... Validate"); Log(" ... Install"); Log(""); Log("Configuration switches:"); Log(" -stagedir <path> sets the directory to copy staged files from (defaults to none)"); Log(" -project <path> path to the project being packaged"); Log(" -compress=fast|best|none packaging compression level (defaults to none)"); Log(" -strip strip symbols during packaging"); Log(" -config game configuration (e.g., Shipping, Development, etc...)"); Log(" -distribution packaging for final distribution"); Log(" -createstub packaging stub IPA for later repackaging"); Log(" -mac <MacName> overrides the machine to use for any Mac operations"); Log(" -arch <Architecture> sets the architecture to use (blank for default, -simulator for simulator builds)"); Log(" -device <DeviceID> sets the device to install the IPA on"); Log(""); Log("Commands: RPC, Clean"); Log(" StageMacFiles, GetIPA, Deploy, Install, Uninstall"); Log(""); Log("RPC Commands: SetExec, InstallProvision, MakeApp, DeleteIPA, Copy, Kill, Strip, Zip, GenDSYM"); Log(""); Log("Sample commandlines:"); Log(" ... iPhonePackager Deploy UDKGame Release"); Log(" ... iPhonePackager RPC SwordGame Shipping MakeApp"); return((int)ErrorCodes.Error_Arguments); } Log("Executing iPhonePackager " + String.Join(" ", args)); Log("CWD: " + Directory.GetCurrentDirectory()); Log("Initial Dir: " + InitialCurrentDirectory); Log("Env CWD: " + Environment.CurrentDirectory); // Ensure shipping configuration for final distributions if (Config.bForDistribution && (GameConfiguration != "Shipping")) { Program.Warning("Distribution builds should be made in the Shipping configuration!"); } // process the GamePath (if could be ..\Samples\MyDemo\ or ..\Samples\MyDemo\MyDemo.uproject GameName = Path.GetFileNameWithoutExtension(GamePath); if (GameName.Equals("UE4", StringComparison.InvariantCultureIgnoreCase) || GameName.Equals("Engine", StringComparison.InvariantCultureIgnoreCase)) { GameName = "UE4Game"; } // setup configuration if (!Config.Initialize(InitialCurrentDirectory, GamePath)) { return((int)ErrorCodes.Error_Arguments); } switch (MainCommand.ToLowerInvariant()) { case "validate": // check to see if iTunes is installed string dllPath = ""; if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix) { dllPath = "/Applications/Xcode.app/Contents/MacOS/Xcode"; } else { dllPath = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apple Inc.\\Apple Mobile Device Support\\Shared", "iTunesMobileDeviceDLL", null) as string; if (String.IsNullOrEmpty(dllPath) || !File.Exists(dllPath)) { dllPath = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Apple Inc.\\Apple Mobile Device Support\\Shared", "MobileDeviceDLL", null) as string; } } if (String.IsNullOrEmpty(dllPath) || !File.Exists(dllPath)) { Error("iTunes Not Found!!", (int)ErrorCodes.Error_SDKNotFound); } else { // validate there is a useable provision and cert MobileProvision Provision; X509Certificate2 Cert; bool bHasOverrides; bool bNameMatch; bool foundPlist = CodeSignatureBuilder.FindRequiredFiles(out Provision, out Cert, out bHasOverrides, out bNameMatch); if (!foundPlist) { Error("Could not find a valid plist file!!", (int)ErrorCodes.Error_InfoPListNotFound); } else if (Provision == null && Cert == null) { Error("No Provision or cert found!!", (int)ErrorCodes.Error_ProvisionAndCertificateNotFound); } else if (Provision == null) { Error("No Provision found!!", (int)ErrorCodes.Error_ProvisionNotFound); } else if (Cert == null) { Error("No Signing Certificate found!!", (int)ErrorCodes.Error_CertificateNotFound); } } break; case "packageapp": if (CheckArguments()) { if (Config.bCreateStubSet) { Error("packageapp cannot be used with the -createstub switch"); Program.ReturnCode = (int)ErrorCodes.Error_Arguments; } else { // Create the .app on the Mac CompileTime.CreateApplicationDirOnMac(); } } break; case "repackagefromstage": if (CheckArguments()) { if (Config.bCreateStubSet) { Error("repackagefromstage cannot be used with the -createstub switches"); Program.ReturnCode = (int)ErrorCodes.Error_Arguments; } else { bool bProbablyCreatedStub = Utilities.GetEnvironmentVariable("ue.IOSCreateStubIPA", true); if (!bProbablyCreatedStub) { Warning("ue.IOSCreateStubIPA is currently FALSE, which means you may be repackaging with an out of date stub IPA!"); } CookTime.RepackageIPAFromStub(); } } break; // this is the "super fast just move executable" mode for quick programmer iteration case "dangerouslyfast": if (CheckArguments()) { CompileTime.DangerouslyFastMode(); } break; case "packageipa": if (CheckArguments()) { CompileTime.PackageIPAOnMac(); } break; case "install": GameName = ""; if (Config.bProvision) { ToolsHub.TryInstallingMobileProvision(Config.Provision, false); } if (Config.bCert) { ToolsHub.TryInstallingCertificate_PromptForKey(Config.Certificate, false); } CodeSignatureBuilder.FindCertificates(); CodeSignatureBuilder.FindProvisions(Config.OverrideBundleName); break; case "certificates": { CodeSignatureBuilder.FindCertificates(); CodeSignatureBuilder.FindProvisions(Config.OverrideBundleName); } break; case "resigntool": RunInVisualMode(delegate { return(new GraphicalResignTool()); }); break; case "certrequest": RunInVisualMode(delegate { return(new GenerateSigningRequestDialog()); }); break; case "gui": RunInVisualMode(delegate { return(ToolsHub.CreateShowingTools()); }); break; case "devices": ListDevices(); break; default: // Commands by themself default to packaging for the device if (CheckArguments()) { ExecuteCommand(MainCommand, MainRPCCommand); } break; } } catch (Exception Ex) { Error("Application exception: " + Ex.ToString()); if (ReturnCode == 0) { Program.ReturnCode = (int)ErrorCodes.Error_Unknown; } } finally { if (DeploymentHelper.DeploymentServerProcess != null) { DeploymentHelper.DeploymentServerProcess.Close(); } } Environment.ExitCode = ReturnCode; return(ReturnCode); }
static public void ExecuteCommand(string Command, string RPCCommand) { if (ReturnCode > 0) { Warning("Error in previous command; suppressing: " + Command + " " + RPCCommand ?? ""); return; } if (Config.bVerbose) { Log(""); Log("----------"); Log(String.Format("Executing command '{0}' {1}...", Command, (RPCCommand != null) ? ("'" + RPCCommand + "' ") : "")); } try { bool bHandledCommand = CookTime.ExecuteCookCommand(Command, RPCCommand); if (!bHandledCommand) { bHandledCommand = CompileTime.ExecuteCompileCommand(Command, RPCCommand); } if (!bHandledCommand) { bHandledCommand = DeploymentHelper.ExecuteDeployCommand(Command, GamePath, RPCCommand); } if (!bHandledCommand) { bHandledCommand = true; switch (Command) { case "configure": if (Config.bForDistribution) { Error("configure cannot be used with -distribution"); Program.ReturnCode = (int)ErrorCodes.Error_Arguments; } else { RunInVisualMode(delegate { return(new ConfigureMobileGame()); }); } break; default: bHandledCommand = false; break; } } if (!bHandledCommand) { Error("Unknown command"); Program.ReturnCode = (int)ErrorCodes.Error_UnknownCommand; } } catch (Exception Ex) { Error("Error while executing command: " + Ex.ToString()); if (Program.ReturnCode == 0) { Program.ReturnCode = (int)ErrorCodes.Error_Unknown; } } Console.WriteLine(); }
public static bool Initialize(string InitialCurrentDirectory, string GamePath) { bool bIsEpicInternal = File.Exists(@"..\..\EpicInternal.txt"); // if the path is a directory (relative to where the game was launched from), then get the absolute directory string FullGamePath = Path.GetFullPath(Path.Combine(InitialCurrentDirectory, GamePath)); string OrigGamePath = GamePath; if (Directory.Exists(FullGamePath)) { GameDirectory = FullGamePath; } // is it a file? if so, just use the file's directory else if (File.Exists(FullGamePath)) { GameDirectory = Path.GetDirectoryName(FullGamePath); } // else we assume old school game name and look for it else { if (Program.GameName == "UE4Game") { GameDirectory = Path.GetFullPath(Path.Combine(Config.RootRelativePath, GamePath)); } else { GameDirectory = Path.GetFullPath(Path.Combine(Config.RootRelativePath, Program.GameName)); } } if (!Directory.Exists(GameDirectory)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(); Console.WriteLine("Unable to find a game or program {0}. You may need to specify a path to the program", OrigGamePath); Console.ResetColor(); return(false); } // special case handling for anything inside Engine/Source, it will go to the Engine/Binaries directory, not the Game's binaries directory if (OrigGamePath.Replace("\\", "/").Contains("Engine/Source")) { BinariesDirectory = Path.Combine(RootRelativePath, @"Engine\Binaries\" + Config.OSString + @"\"); } else if (!OrigGamePath.Contains(@"Binaries\" + Config.OSString)) { // no sense in adding Binaries\IOS when it's already there. This is a special case to handle packaging UnrealLaunchDaemon from the command line. BinariesDirectory = Path.Combine(GameDirectory, @"Binaries\" + Config.OSString + @"\"); } else { BinariesDirectory = GameDirectory; } // Root directory on PC for staging files to copy to Mac Config.PCStagingRootDir = String.Format(@"{0}-Deploy\{1}\{2}{3}\", IntermediateDirectory, Program.GameName, Program.GameConfiguration, Program.Architecture); // make a directory for the shared XcodeSupportFiles directory Config.PCXcodeStagingDir = Path.Combine(Config.PCStagingRootDir, @"..\XcodeSupportFiles"); // Code signing identity // Rules: // An environment variable wins if set // Otherwise for internal development builds, an internal identity is used // Otherwise, developer or distribution are used // Distro builds won't succeed on a machine with multiple distro certs installed unless the environment variable is set. Config.CodeSigningIdentity = Config.bForDistribution ? "iPhone Distribution" : "iPhone Developer"; if (Config.bForDistribution) { Config.CodeSigningIdentity = Utilities.GetEnvironmentVariable("ue.IOSDistributionSigningIdentity", Config.CodeSigningIdentity); } else { Config.CodeSigningIdentity = Utilities.GetEnvironmentVariable("ue.IOSDeveloperSigningIdentity", Config.CodeSigningIdentity); } // Remember to also change the default min version in UBT (iPhoneToolChain.cs) Config.MinOSVersion = Utilities.GetEnvironmentVariable("ue3.iPhone_MinOSVersion", "6.0"); // look for the signing prefix environment variable string DefaultPrefix = ""; if (bIsEpicInternal) { // default Epic to "Epic_" prefix DefaultPrefix = "Epic_"; } if (Config.bForDistribution) { DefaultPrefix = "Distro_"; } Config.SigningPrefix = Utilities.GetEnvironmentVariable("ue.IOSSigningPrefix", DefaultPrefix); // Windows doesn't allow environment vars to be set to blank so detect "none" and treat it as such if (Config.SigningPrefix == "none") { Config.SigningPrefix = Config.bForDistribution ? "Distro_" : ""; } CompileTime.ConfigurePaths(); return(true); }