/// <summary>
        ///
        /// </summary>
        /// <param name="InDirectory"></param>
        /// <param name="InTargetPlatform"></param>
        /// <param name="OutRSAKeys"></param>
        /// <param name="OutAESKey"></param>
        public static void ParseEncryptionIni(DirectoryReference InDirectory, UnrealTargetPlatform InTargetPlatform, out String[] OutRSAKeys, out String OutAESKey)
        {
            OutAESKey  = String.Empty;
            OutRSAKeys = null;

            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InDirectory, InTargetPlatform);

            bool bSigningEnabled;

            Ini.GetBool("Core.Encryption", "SignPak", out bSigningEnabled);

            if (bSigningEnabled)
            {
                OutRSAKeys = new string[3];
                Ini.GetString("Core.Encryption", "rsa.privateexp", out OutRSAKeys[0]);
                Ini.GetString("Core.Encryption", "rsa.modulus", out OutRSAKeys[1]);
                Ini.GetString("Core.Encryption", "rsa.publicexp", out OutRSAKeys[2]);

                if (String.IsNullOrEmpty(OutRSAKeys[0]) || String.IsNullOrEmpty(OutRSAKeys[1]) || String.IsNullOrEmpty(OutRSAKeys[2]))
                {
                    OutRSAKeys = null;
                }
            }

            bool bEncryptionEnabled;

            Ini.GetBool("Core.Encryption", "EncryptPak", out bEncryptionEnabled);

            if (bEncryptionEnabled)
            {
                Ini.GetString("Core.Encryption", "aes.key", out OutAESKey);
            }
        }
Esempio n. 2
0
        public static List <string> GetShippingArchitectures(ConfigHierarchy Ini)
        {
            List <string> ProjectArches = new List <string>();
            bool          bBuild        = true;

            if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForArmV7", out bBuild) && bBuild)
            {
                ProjectArches.Add("armv7");
            }
            if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForArm64", out bBuild) && bBuild)
            {
                ProjectArches.Add("arm64");
            }
            if (Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForArmV7S", out bBuild) && bBuild)
            {
                ProjectArches.Add("armv7s");
            }

            // force armv7 if something went wrong
            if (ProjectArches.Count == 0)
            {
                ProjectArches.Add("armv7");
                ProjectArches.Add("arm64");
            }
            return(ProjectArches);
        }
Esempio n. 3
0
        public HTML5ToolChain(FileReference InProjectFile)
            : base(CppPlatform.HTML5)
        {
            if (!HTML5SDKInfo.IsSDKInstalled())
            {
                throw new BuildException("HTML5 SDK is not installed; cannot use toolchain.");
            }

            // ini configs
            // - normal ConfigCache w/ UnrealBuildTool.ProjectFile takes all game config ini files
            //   (including project config ini files)
            // - but, during packaging, if -remoteini is used -- need to use UnrealBuildTool.GetRemoteIniPath()
            //   (note: ConfigCache can take null ProjectFile)
            string             EngineIniPath = UnrealBuildTool.GetRemoteIniPath();
            DirectoryReference ProjectDir    = !String.IsNullOrEmpty(EngineIniPath) ? new DirectoryReference(EngineIniPath)
                                                                                                : DirectoryReference.FromFile(InProjectFile);
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDir, UnrealTargetPlatform.HTML5);

//			Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableSIMD", out enableSIMD);
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading);
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "OffscreenCanvas", out bMultithreading_UseOffscreenCanvas);
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LLVMWasmBackend", out useLLVMwasmBackend);
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableTracing", out bEnableTracing);

            if (useLLVMwasmBackend)
            {
                libExt = ".a";                  // experimental - LLVMWasmBackend
            }

            // TODO: remove this "fix" when emscripten supports WASM with SIMD
            enableSIMD = false;

            Log.TraceInformation("HTML5ToolChain: EnableSIMD = " + enableSIMD);
            Log.TraceInformation("HTML5ToolChain: EnableMultithreading " + enableMultithreading);
            Log.TraceInformation("HTML5ToolChain: OffscreenCanvas " + bMultithreading_UseOffscreenCanvas);
            Log.TraceInformation("HTML5ToolChain: LLVMWasmBackend " + useLLVMwasmBackend);
            Log.TraceInformation("HTML5ToolChain: EnableTracing = " + bEnableTracing);

            PrintOnce = new VerbosePrint(PrintOnceOn);             // reset

            Log.TraceInformation("Setting Emscripten SDK: located in " + HTML5SDKInfo.EMSCRIPTEN_ROOT);
            string TempDir = HTML5SDKInfo.SetupEmscriptenTemp();

            HTML5SDKInfo.SetUpEmscriptenConfigFile();

            if (Environment.GetEnvironmentVariable("EMSDK") == null)             // If EMSDK is present, Emscripten is already configured by the developer
            {
                // If not using preset emsdk, configure our generated .emscripten config, instead of autogenerating one in the user's home directory.
                Environment.SetEnvironmentVariable("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN);
                Environment.SetEnvironmentVariable("EM_CACHE", HTML5SDKInfo.EMSCRIPTEN_CACHE);
                Environment.SetEnvironmentVariable("EMCC_TEMP_DIR", TempDir);
            }

            Log.TraceInformation("*** Emscripten Config File: " + Environment.GetEnvironmentVariable("EM_CONFIG"));
        }
Esempio n. 4
0
        private string GetElfName(FileReference InNMakeOutputPath)
        {
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InNMakeOutputPath.Directory.ParentDirectory.ParentDirectory, UnrealTargetPlatform.Lumin);
            bool            bUseMobileRendering = false;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseMobileRendering", out bUseMobileRendering);
            bool bUseVulkan = false;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseVulkan", out bUseVulkan);

            string OutputFileName = string.Format("{0}-arm64-{1}{2}", InNMakeOutputPath.GetFileNameWithoutExtension(), !(bUseMobileRendering || bUseVulkan) ? "lumingl4" : "lumin", InNMakeOutputPath.GetExtension());

            return(OutputFileName);
        }
Esempio n. 5
0
        public HTML5ToolChain(FileReference InProjectFile)
            : base(CppPlatform.HTML5, WindowsCompiler.VisualStudio2015, false, false)
        {
            if (!HTML5SDKInfo.IsSDKInstalled())
            {
                throw new BuildException("HTML5 SDK is not installed; cannot use toolchain.");
            }

            // ini configs
            // - normal ConfigCache w/ UnrealBuildTool.ProjectFile takes all game config ini files
            //   (including project config ini files)
            // - but, during packaging, if -remoteini is used -- need to use UnrealBuildTool.GetRemoteIniPath()
            //   (note: ConfigCache can take null ProjectFile)
            string             EngineIniPath = UnrealBuildTool.GetRemoteIniPath();
            DirectoryReference ProjectDir    = !String.IsNullOrEmpty(EngineIniPath) ? new DirectoryReference(EngineIniPath)
                                                                                                : DirectoryReference.FromFile(InProjectFile);
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDir, UnrealTargetPlatform.HTML5);

            // these will be going away...
            bool targetingAsmjs = true;            // inverted check
            bool targetWebGL1   = false;           // inverted check

            if (Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetAsmjs", out targetingAsmjs))
            {
                targetingWasm = !targetingAsmjs;
            }
            if (Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetWebGL1", out targetWebGL1))
            {
                targetWebGL2 = !targetWebGL1;
            }
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableSIMD", out enableSIMD);
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading);
            Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableTracing", out bEnableTracing);
            Log.TraceInformation("HTML5ToolChain: TargetWasm = " + targetingWasm);
            Log.TraceInformation("HTML5ToolChain: TargetWebGL2 = " + targetWebGL2);
            Log.TraceInformation("HTML5ToolChain: EnableSIMD = " + enableSIMD);
            Log.TraceInformation("HTML5ToolChain: EnableMultithreading " + enableMultithreading);
            Log.TraceInformation("HTML5ToolChain: EnableTracing = " + bEnableTracing);

            // TODO: remove this "fix" when emscripten supports (SIMD & pthreads) + WASM
            if (targetingWasm)
            {
                enableSIMD = false;

                // TODO: double check Engine/Source/Runtime/Core/Private/HTML5/HTML5PlatformProcess.cpp::SupportsMultithreading()
                enableMultithreading = false;
            }
            PrintOnce = new VerbosePrint(PrintOnceOn); // reset
        }
        protected XElement GetIdentity(out string IdentityName)
        {
            // Read the PackageName from config
            var PackageName = Regex.Replace(GetConfigString("PackageName", "ProjectName", "DefaultUE4Project"), "[^-.A-Za-z0-9]", "");

            if (string.IsNullOrWhiteSpace(PackageName))
            {
                Log.TraceError("Invalid package name {0}. Package names must only contain letters, numbers, dash, and period and must be at least one character long.", PackageName);
                Log.TraceError("Consider using the setting [{0}]:PackageName to provide a specific value.", IniSection_PlatformTargetSettings);
            }

            var PublisherName = GetConfigString("PublisherName", "CompanyDistinguishedName", "CN=NoPublisher");
            var VersionNumber = GetConfigString("PackageVersion", "ProjectVersion", "1.0.0.0");

            VersionNumber = ValidatePackageVersion(VersionNumber);

            // If specified in the project settings attempt to retrieve the current build number and increment the version number by that amount, accounting for overflows
            bool bIncludeEngineVersionInPackageVersion;

            if (EngineIni.GetBool(IniSection_PlatformTargetSettings, "bIncludeEngineVersionInPackageVersion", out bIncludeEngineVersionInPackageVersion) && bIncludeEngineVersionInPackageVersion)
            {
                VersionNumber = IncludeBuildVersionInPackageVersion(VersionNumber);
            }

            IdentityName = PackageName;

            return(new XElement(GetName("Identity", Schema2010NS),
                                new XAttribute("Name", PackageName),
                                new XAttribute("Publisher", PublisherName),
                                new XAttribute("Version", VersionNumber)));
        }
Esempio n. 7
0
        private bool GetRemoveDebugInfo()
        {
            ConfigHierarchy Ini   = GetConfigCacheIni(ConfigHierarchyType.Engine);
            bool            Value = false;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bRemoveDebugInfo", out Value);
            return(Value);
        }
Esempio n. 8
0
        public bool UseVulkan()
        {
            ConfigHierarchy Ini   = GetConfigCacheIni(ConfigHierarchyType.Engine);
            bool            Value = false;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseVulkan", out Value);
            return(Value);
        }
Esempio n. 9
0
        protected static bool DoProjectSettingsMatchDefault(UnrealTargetPlatform Platform, DirectoryReference ProjectDirectoryName, string Section, string[] BoolKeys, string[] IntKeys, string[] StringKeys)
        {
            ConfigHierarchy ProjIni    = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectDirectoryName, Platform);
            ConfigHierarchy DefaultIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, (DirectoryReference)null, Platform);

            // look at all bool values
            if (BoolKeys != null)
            {
                foreach (string Key in BoolKeys)
                {
                    bool Default = false, Project = false;
                    DefaultIni.GetBool(Section, Key, out Default);
                    ProjIni.GetBool(Section, Key, out Project);
                    if (Default != Project)
                    {
                        Log.TraceInformationOnce(Key + " is not set to default. (" + Default + " vs. " + Project + ")");
                        return(false);
                    }
                }
            }

            // look at all int values
            if (IntKeys != null)
            {
                foreach (string Key in IntKeys)
                {
                    int Default = 0, Project = 0;
                    DefaultIni.GetInt32(Section, Key, out Default);
                    ProjIni.GetInt32(Section, Key, out Project);
                    if (Default != Project)
                    {
                        Log.TraceInformationOnce(Key + " is not set to default. (" + Default + " vs. " + Project + ")");
                        return(false);
                    }
                }
            }

            // look for all string values
            if (StringKeys != null)
            {
                foreach (string Key in StringKeys)
                {
                    string Default = "", Project = "";
                    DefaultIni.GetString(Section, Key, out Default);
                    ProjIni.GetString(Section, Key, out Project);
                    if (Default != Project)
                    {
                        Log.TraceInformationOnce(Key + " is not set to default. (" + Default + " vs. " + Project + ")");
                        return(false);
                    }
                }
            }

            // if we get here, we match all important settings
            return(true);
        }
Esempio n. 10
0
        public bool UseVulkan()
        {
            // @todo Lumin: Switch to Lumin once we have sub-platform ini
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), UnrealTargetPlatform.Android);
            // go by string
            bool bUseVulkan = true;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseVulkan", out bUseVulkan);

            return(bUseVulkan);
        }
Esempio n. 11
0
        public bool UseVulkan()
        {
            DirectoryReference DirRef = (!string.IsNullOrEmpty(UnrealBuildTool.GetRemoteIniPath()) ? new DirectoryReference(UnrealBuildTool.GetRemoteIniPath()) : (ProjectFile != null ? ProjectFile.Directory : null));
            ConfigHierarchy    Ini    = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirRef, UnrealTargetPlatform.Lumin);
            // go by string
            bool bUseVulkan = true;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseVulkan", out bUseVulkan);

            return(bUseVulkan);
        }
Esempio n. 12
0
        private manifestApplicationComponentType GetApplicationType()
        {
            ConfigHierarchy Ini   = GetConfigCacheIni(ConfigHierarchyType.Engine);
            bool            Value = false;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bIsScreensApp", out Value);
            if (Value)
            {
                return(manifestApplicationComponentType.ScreensImmersive);
            }
            return(manifestApplicationComponentType.Fullscreen);
        }
Esempio n. 13
0
        private string GetApplicationType()
        {
            ConfigHierarchy Ini   = GetConfigCacheIni(ConfigHierarchyType.Engine);
            bool            Value = false;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bIsScreensApp", out Value);
            if (Value)
            {
                return("ScreensImmersive");
            }
            return("Fullscreen");
        }
Esempio n. 14
0
        /// <summary>
        /// Setup the target environment for building
        /// </summary>
        /// <param name="InBuildTarget"> The target being built</param>
        public override void SetUpEnvironment(UEBuildTarget InBuildTarget)
        {
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("PLATFORM_IOS=1");
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("PLATFORM_APPLE=1");

            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_TTS=0");
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_SPEECH_RECOGNITION=0");
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_DATABASE_SUPPORT=0");
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_EDITOR=0");
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("USE_NULL_RHI=0");
            InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("REQUIRES_ALIGNED_INT_ACCESS");

            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), UnrealTargetPlatform.IOS);

            Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableRemoteNotificationsSupport", out bNotificationsEnabled);
            if (bNotificationsEnabled)
            {
                InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("NOTIFICATIONS_ENABLED=1");
            }
            else
            {
                InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("NOTIFICATIONS_ENABLED=0");
            }

            if (GetActiveArchitecture() == "-simulator")
            {
                InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_SIMULATOR=1");
            }
            else
            {
                InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_SIMULATOR=0");
            }

            // we assume now we are building with IOS8 or later
            if (UEBuildConfiguration.bCompileAgainstEngine)
            {
                InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("HAS_METAL=1");
                InBuildTarget.ExtraModuleNames.Add("MetalRHI");
            }
            else
            {
                InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("HAS_METAL=0");
            }

            InBuildTarget.GlobalLinkEnvironment.Config.AdditionalFrameworks.Add(new UEBuildFramework("GameKit"));
            InBuildTarget.GlobalLinkEnvironment.Config.AdditionalFrameworks.Add(new UEBuildFramework("StoreKit"));
        }
Esempio n. 15
0
        public override bool HasSpecificDefaultBuildConfig(UnrealTargetPlatform Platform, DirectoryReference ProjectPath)
        {
            ConfigHierarchy Ini        = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, ProjectPath, UnrealTargetPlatform.Lumin);
            bool            bUseVulkan = true;

            Ini.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bUseVulkan", out bUseVulkan);

            List <string> ConfigBoolKeys = new List <string>();

            if (!bUseVulkan)
            {
                ConfigBoolKeys.Add("bUseMobileRendering");
            }

            // look up Android specific settings
            if (!DoProjectSettingsMatchDefault(UnrealTargetPlatform.Lumin, ProjectPath, "/Script/LuminRuntimeSettings.LuminRuntimeSettings", ConfigBoolKeys.ToArray(), null, null))
            {
                return(false);
            }

            return(true);
        }
Esempio n. 16
0
        public static bool UseTegraGraphicsDebugger(FileReference ProjectFile)
        {
            if (!HaveTegraGraphicsDebugger.HasValue)
            {
                string ProgramsDir = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
                string NVDir       = ProgramsDir + "/NVIDIA Corporation";
                try
                {
                    string[] TegraDebuggerDirs = Directory.GetDirectories(NVDir, "Tegra Graphics Debugger *");
                    if (TegraDebuggerDirs.Length > 0)
                    {
                        TegraDebuggerDir          = TegraDebuggerDirs[0].Replace('\\', '/');
                        HaveTegraGraphicsDebugger = true;
                        string[] V = TegraDebuggerDir.Split(' ').Last().Split('.');
                        TegraDebuggerVersion    = new int[2];
                        TegraDebuggerVersion[0] = Int32.Parse(V[0]);
                        TegraDebuggerVersion[1] = Int32.Parse(V[1]);
                    }
                    else
                    {
                        HaveTegraGraphicsDebugger = false;
                    }
                }
                catch (System.IO.IOException)
                {
                    HaveTegraGraphicsDebugger = false;
                }
            }
            bool bBuild = false;
            // TODO: do we need this?
            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), UnrealTargetPlatform.Lumin);

            Ini.GetBool(
                "/Script/LuminRuntimeSettings.LuminRuntimeSettings",
                "bBuildWithNvTegraGfxDebugger",
                out bBuild);
            return(HaveTegraGraphicsDebugger.Value && bBuild);
        }
Esempio n. 17
0
        /// <summary>
        /// Parse crypto settings from INI file
        /// </summary>
        public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform)
        {
            CryptoSettings Settings = new CryptoSettings();

            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform);

            Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired);

            // For now, we'll just not parse any keys if data crypto is disabled for this platform. In the future, we might want to use
            // these keys for non-data purposes (other general purpose encryption maybe?)
            if (!Settings.bDataCryptoRequired)
            {
                return(Settings);
            }

            {
                // Start by parsing the legacy encryption.ini settings
                Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform);
                Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning);

                string[] SigningKeyStrings = new string[3];
                Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]);
                Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]);
                Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]);

                if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2]))
                {
                    SigningKeyStrings = null;
                }
                else
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[0]), 64);
                    Settings.SigningKey.PrivateKey.Modulus  = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[1]), 64);
                    Settings.SigningKey.PublicKey.Exponent  = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[2]), 64);
                    Settings.SigningKey.PublicKey.Modulus   = Settings.SigningKey.PrivateKey.Modulus;

                    if ((Settings.SigningKey.PrivateKey.Exponent.Length > 64) ||
                        (Settings.SigningKey.PrivateKey.Modulus.Length > 64) ||
                        (Settings.SigningKey.PublicKey.Exponent.Length > 64) ||
                        (Settings.SigningKey.PublicKey.Modulus.Length > 64))
                    {
                        throw new Exception(string.Format("[{0}] Signing keys parsed from encryption.ini are too long. They must be a maximum of 64 bytes long!", InProjectDirectory));
                    }
                }

                Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption);
                Settings.bEnablePakFullAssetEncryption = false;
                Settings.bEnablePakUAssetEncryption    = false;
                Settings.bEnablePakIniEncryption       = Settings.bEnablePakIndexEncryption;

                string EncryptionKeyString;
                Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString);
                Settings.EncryptionKey = new EncryptionKey();

                if (EncryptionKeyString.Length > 0)
                {
                    if (EncryptionKeyString.Length < 32)
                    {
                        Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too short. It must be 32 bytes, so will be padded with 0s, giving sub-optimal security!");
                    }
                    else if (EncryptionKeyString.Length > 32)
                    {
                        Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too long. It must be 32 bytes, so will be truncated!");
                    }

                    Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString, 32);
                }
            }

            Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform);
            string SectionName = "/Script/CryptoKeys.CryptoKeysSettings";
            ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName);

            // If we have new format crypto keys, read them in over the top of the legacy settings
            if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0)
            {
                Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning);
                Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption);
                Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption);
                Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption);
                Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption);

                // Parse encryption key
                string EncryptionKeyString;
                Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString);
                if (!string.IsNullOrEmpty(EncryptionKeyString))
                {
                    Settings.EncryptionKey     = new EncryptionKey();
                    Settings.EncryptionKey.Key = System.Convert.FromBase64String(EncryptionKeyString);
                }

                // Parse signing key
                string PrivateExponent, PublicExponent, Modulus;
                Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent);
                Ini.GetString(SectionName, "SigningModulus", out Modulus);
                Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent);

                if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus))
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PublicKey.Exponent  = System.Convert.FromBase64String(PublicExponent);
                    Settings.SigningKey.PublicKey.Modulus   = System.Convert.FromBase64String(Modulus);
                    Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent);
                    Settings.SigningKey.PrivateKey.Modulus  = Settings.SigningKey.PublicKey.Modulus;
                }
            }

            return(Settings);
        }
        /// <summary>
        /// Parse crypto settings from INI file
        /// </summary>
        public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform)
        {
            CryptoSettings Settings = new CryptoSettings();

            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform);

            Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired);
            Ini.GetBool("PlatformCrypto", "PakSigningRequired", out Settings.PakSigningRequired);
            Ini.GetBool("PlatformCrypto", "PakEncryptionRequired", out Settings.PakEncryptionRequired);

            {
                // Start by parsing the legacy encryption.ini settings
                Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform);
                Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning);

                string[] SigningKeyStrings = new string[3];
                Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]);
                Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]);
                Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]);

                if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2]))
                {
                    SigningKeyStrings = null;
                }
                else
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[0]), 64);
                    Settings.SigningKey.PrivateKey.Modulus  = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[1]), 64);
                    Settings.SigningKey.PublicKey.Exponent  = ParseHexStringToByteArray(ProcessSigningKeyInputStrings(SigningKeyStrings[2]), 64);
                    Settings.SigningKey.PublicKey.Modulus   = Settings.SigningKey.PrivateKey.Modulus;

                    if ((Settings.SigningKey.PrivateKey.Exponent.Length > 64) ||
                        (Settings.SigningKey.PrivateKey.Modulus.Length > 64) ||
                        (Settings.SigningKey.PublicKey.Exponent.Length > 64) ||
                        (Settings.SigningKey.PublicKey.Modulus.Length > 64))
                    {
                        throw new Exception(string.Format("[{0}] Signing keys parsed from encryption.ini are too long. They must be a maximum of 64 bytes long!", InProjectDirectory));
                    }
                }

                Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption);
                Settings.bEnablePakFullAssetEncryption = false;
                Settings.bEnablePakUAssetEncryption    = false;
                Settings.bEnablePakIniEncryption       = Settings.bEnablePakIndexEncryption;

                string EncryptionKeyString;
                Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString);
                Settings.EncryptionKey = new EncryptionKey();

                if (EncryptionKeyString.Length > 0)
                {
                    if (EncryptionKeyString.Length < 32)
                    {
                        Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too short. It must be 32 bytes, so will be padded with 0s, giving sub-optimal security!");
                    }
                    else if (EncryptionKeyString.Length > 32)
                    {
                        Log.WriteLine(LogEventType.Warning, "AES key parsed from encryption.ini is too long. It must be 32 bytes, so will be truncated!");
                    }

                    Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString, 32);
                }
            }

            Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform);
            string SectionName = "/Script/CryptoKeys.CryptoKeysSettings";
            ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName);

            // If we have new format crypto keys, read them in over the top of the legacy settings
            if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0)
            {
                Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning);
                Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption);
                Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption);
                Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption);
                Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption);

                // Parse encryption key
                string EncryptionKeyString;
                Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString);
                if (!string.IsNullOrEmpty(EncryptionKeyString))
                {
                    Settings.EncryptionKey      = new EncryptionKey();
                    Settings.EncryptionKey.Key  = System.Convert.FromBase64String(EncryptionKeyString);
                    Settings.EncryptionKey.Guid = Guid.Empty.ToString();
                    Settings.EncryptionKey.Name = "Embedded";
                }

                // Parse secondary encryption keys
                List <EncryptionKey> SecondaryEncryptionKeys = new List <EncryptionKey>();
                List <string>        SecondaryEncryptionKeyStrings;

                if (Ini.GetArray(SectionName, "SecondaryEncryptionKeys", out SecondaryEncryptionKeyStrings))
                {
                    foreach (string KeySource in SecondaryEncryptionKeyStrings)
                    {
                        EncryptionKey NewKey = new EncryptionKey();
                        SecondaryEncryptionKeys.Add(NewKey);

                        Regex Search = new Regex("\\(Guid=(?\'Guid\'.*),Name=\\\"(?\'Name\'.*)\\\",Key=\\\"(?\'Key\'.*)\\\"\\)");
                        Match Match  = Search.Match(KeySource);
                        if (Match.Success)
                        {
                            foreach (string GroupName in Search.GetGroupNames())
                            {
                                string Value = Match.Groups[GroupName].Value;
                                if (GroupName == "Guid")
                                {
                                    NewKey.Guid = Value;
                                }
                                else if (GroupName == "Name")
                                {
                                    NewKey.Name = Value;
                                }
                                else if (GroupName == "Key")
                                {
                                    NewKey.Key = System.Convert.FromBase64String(Value);
                                }
                            }
                        }
                    }
                }

                Settings.SecondaryEncryptionKeys = SecondaryEncryptionKeys.ToArray();

                // Parse signing key
                string PrivateExponent, PublicExponent, Modulus;
                Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent);
                Ini.GetString(SectionName, "SigningModulus", out Modulus);
                Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent);

                if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus))
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PublicKey.Exponent  = System.Convert.FromBase64String(PublicExponent);
                    Settings.SigningKey.PublicKey.Modulus   = System.Convert.FromBase64String(Modulus);
                    Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent);
                    Settings.SigningKey.PrivateKey.Modulus  = Settings.SigningKey.PublicKey.Modulus;
                }
            }

            // Parse project dynamic keychain keys
            if (InProjectDirectory != null)
            {
                ConfigHierarchy GameIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, InProjectDirectory, InTargetPlatform);
                if (GameIni != null)
                {
                    string Filename;
                    if (GameIni.GetString("ContentEncryption", "ProjectKeyChain", out Filename))
                    {
                        FileReference ProjectKeyChainFile = FileReference.Combine(InProjectDirectory, "Content", Filename);
                        if (FileReference.Exists(ProjectKeyChainFile))
                        {
                            List <EncryptionKey> EncryptionKeys = new List <EncryptionKey>();

                            if (Settings.SecondaryEncryptionKeys != null)
                            {
                                EncryptionKeys.AddRange(Settings.SecondaryEncryptionKeys);
                            }

                            string[] Lines = FileReference.ReadAllLines(ProjectKeyChainFile);
                            foreach (string Line in Lines)
                            {
                                string[] KeyParts = Line.Split(':');
                                if (KeyParts.Length == 4)
                                {
                                    EncryptionKey NewKey = new EncryptionKey();

                                    NewKey.Name = KeyParts[0];
                                    NewKey.Guid = KeyParts[2];
                                    NewKey.Key  = System.Convert.FromBase64String(KeyParts[3]);

                                    EncryptionKey ExistingKey = EncryptionKeys.Find((EncryptionKey OtherKey) => { return(OtherKey.Guid == NewKey.Guid); });
                                    if (ExistingKey != null && !CompareKey(ExistingKey.Key, NewKey.Key))
                                    {
                                        throw new Exception("Found multiple encryption keys with the same guid but different AES keys while merging secondary keys from the project key-chain!");
                                    }

                                    EncryptionKeys.Add(NewKey);
                                }
                            }

                            Settings.SecondaryEncryptionKeys = EncryptionKeys.ToArray();
                        }
                    }
                }
            }

            if (!Settings.bDataCryptoRequired)
            {
                CryptoSettings NewSettings = new CryptoSettings();
                NewSettings.SecondaryEncryptionKeys = Settings.SecondaryEncryptionKeys;
                Settings = NewSettings;
            }
            else
            {
                if (!Settings.PakSigningRequired)
                {
                    Settings.bEnablePakSigning = false;
                    Settings.SigningKey        = null;
                }

                if (!Settings.PakEncryptionRequired)
                {
                    Settings.bEnablePakFullAssetEncryption = false;
                    Settings.bEnablePakIndexEncryption     = false;
                    Settings.bEnablePakIniEncryption       = false;
                    Settings.EncryptionKey = null;
                    Settings.SigningKey    = null;
                }
            }

            // Check if we have a valid signing key that is of the old short form
            if (Settings.SigningKey != null && Settings.SigningKey.IsValid() && Settings.SigningKey.IsUnsecureLegacyKey())
            {
                Log.TraceWarningOnce("Project signing keys found in '{0}' are of the old insecure short format. Please regenerate them using the project crypto settings panel in the editor!", InProjectDirectory);
            }

            // Validate the settings we have read
            if (Settings.bDataCryptoRequired && Settings.bEnablePakSigning && (Settings.SigningKey == null || !Settings.SigningKey.IsValid()))
            {
                Log.TraceWarningOnce("Pak signing is enabled, but no valid signing keys were found. Please generate a key in the editor project crypto settings. Signing will be disabled");
                Settings.bEnablePakSigning = false;
            }

            if (Settings.bDataCryptoRequired && Settings.IsAnyEncryptionEnabled() && (Settings.EncryptionKey == null || !Settings.EncryptionKey.IsValid()))
            {
                Log.TraceWarningOnce("Pak encryption is enabled, but no valid encryption key was found. Please generate a key in the editor project crypto settings. Encryption will be disabled");
                Settings.bEnablePakUAssetEncryption    = false;
                Settings.bEnablePakFullAssetEncryption = false;
                Settings.bEnablePakIndexEncryption     = false;
                Settings.bEnablePakIniEncryption       = false;
            }

            return(Settings);
        }
Esempio n. 19
0
        public string GenerateManifest(string ProjectName, bool bForDistribution, string Architecture)
        {
            ConfigHierarchy GameIni        = GetConfigCacheIni(ConfigHierarchyType.Game);
            string          ProjectVersion = string.Empty;

            GameIni.GetString("/Script/EngineSettings.GeneralProjectSettings", "ProjectVersion", out ProjectVersion);
            if (string.IsNullOrEmpty(ProjectVersion))
            {
                ProjectVersion = "1.0.0.0";
            }

            ConfigHierarchy EngineIni = GetConfigCacheIni(ConfigHierarchyType.Engine);
            int             VersionCode;

            EngineIni.GetInt32("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "VersionCode", out VersionCode);

            bool bInternetRequired;

            EngineIni.GetBool("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "bInternetRequired", out bInternetRequired);

            StringBuilder Text = new StringBuilder();

            string PackageName            = GetPackageName(ProjectName);
            string ApplicationDisplayName = GetApplicationDisplayName(ProjectName);
            string TargetExecutableName   = "bin/" + ProjectName;

            Text.AppendLine(string.Format("<manifest xmlns:ml=\"magicleap\" ml:package=\"{0}\" ml:version_name=\"{1}\" ml:version_code=\"{2}\">", PackageName, ProjectVersion, VersionCode));
            // @mltodo: query sdk_version
            Text.AppendLine(string.Format("\t<application ml:visible_name=\"{0}\" ml:is_debuggable=\"{1}\" ml:sdk_version=\"1.0\" ml:minimum_os=\"mlos_1.0\" ml:internet_required=\"{2}\">", ApplicationDisplayName, bForDistribution ? "false" : "true", bInternetRequired ? "true" : "false"));
            Text.AppendLine(string.Format("\t\t<component ml:name=\".fullscreen\" ml:visible_name=\"{0}\" ml:binary_name=\"{1}\" ml:type=\"{2}\">", ApplicationDisplayName, TargetExecutableName, GetApplicationType()));

            List <string> AppPrivileges;

            EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "AppPrivileges", out AppPrivileges);
            if (AppPrivileges != null)
            {
                foreach (string Privilege in AppPrivileges)
                {
                    string TrimmedPrivilege = Privilege.Trim(' ');
                    if (TrimmedPrivilege != "")
                    {
                        string PrivilegeString = string.Format("\t\t\t<uses-privilege ml:name=\"{0}\"/>", TrimmedPrivilege);
                        if (!Text.ToString().Contains(PrivilegeString))
                        {
                            Text.AppendLine(PrivilegeString);
                        }
                    }
                }
            }

            string IconTag = string.Format("<icon ml:name=\"fullscreen\" ml:model_folder=\"{0}\" ml:portal_folder=\"{1}\"/>", GetIconModelStagingPath(), GetIconPortalStagingPath());

            Text.AppendLine(string.Format("\t\t\t{0}", IconTag));

            List <string> ExtraComponentNodes;

            EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "ExtraComponentNodes", out ExtraComponentNodes);
            if (ExtraComponentNodes != null)
            {
                foreach (string ComponentNode in ExtraComponentNodes)
                {
                    Text.AppendLine(string.Format("\t\t\t{0}", ComponentNode));
                }
            }

            Text.AppendLine("\t\t</component>");

            List <string> ExtraApplicationNodes;

            EngineIni.GetArray("/Script/LuminRuntimeSettings.LuminRuntimeSettings", "ExtraApplicationNodes", out ExtraApplicationNodes);
            if (ExtraApplicationNodes != null)
            {
                foreach (string ApplicationNode in ExtraApplicationNodes)
                {
                    Text.AppendLine(string.Format("\t\t{0}", ApplicationNode));
                }
            }

            Text.AppendLine(string.Format("\t\t{0}", IconTag));
            Text.AppendLine("\t</application>");
            Text.AppendLine("</manifest>");

            // allow plugins to modify final manifest HERE
            XDocument XDoc;

            try
            {
                XDoc = XDocument.Parse(Text.ToString());
            }
            catch (Exception e)
            {
                throw new BuildException("LuminManifest.xml is invalid {0}\n{1}", e, Text.ToString());
            }

            UPL.ProcessPluginNode(Architecture, "luminManifestUpdates", "", ref XDoc);
            return(XDoc.ToString());
        }
Esempio n. 20
0
        /// <summary>
        /// Parse crypto settings from INI file
        /// </summary>
        public static CryptoSettings ParseCryptoSettings(DirectoryReference InProjectDirectory, UnrealTargetPlatform InTargetPlatform)
        {
            CryptoSettings Settings = new CryptoSettings();

            ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, InProjectDirectory, InTargetPlatform);

            Ini.GetBool("PlatformCrypto", "PlatformRequiresDataCrypto", out Settings.bDataCryptoRequired);

            // For now, we'll just not parse any keys if data crypto is disabled for this platform. In the future, we might want to use
            // these keys for non-data purposes (other general purpose encryption maybe?)
            if (!Settings.bDataCryptoRequired)
            {
                return(Settings);
            }

            {
                // Start by parsing the legacy encryption.ini settings
                Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Encryption, InProjectDirectory, InTargetPlatform);
                Ini.GetBool("Core.Encryption", "SignPak", out Settings.bEnablePakSigning);

                string[] SigningKeyStrings = new string[3];
                Ini.GetString("Core.Encryption", "rsa.privateexp", out SigningKeyStrings[0]);
                Ini.GetString("Core.Encryption", "rsa.modulus", out SigningKeyStrings[1]);
                Ini.GetString("Core.Encryption", "rsa.publicexp", out SigningKeyStrings[2]);

                if (String.IsNullOrEmpty(SigningKeyStrings[0]) || String.IsNullOrEmpty(SigningKeyStrings[1]) || String.IsNullOrEmpty(SigningKeyStrings[2]))
                {
                    SigningKeyStrings = null;
                }
                else
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PrivateKey.Exponent = ParseHexStringToByteArray(SigningKeyStrings[0]);
                    Settings.SigningKey.PrivateKey.Modulus  = ParseHexStringToByteArray(SigningKeyStrings[1]);
                    Settings.SigningKey.PublicKey.Exponent  = ParseHexStringToByteArray(SigningKeyStrings[2]);
                    Settings.SigningKey.PublicKey.Modulus   = Settings.SigningKey.PrivateKey.Modulus;
                }

                Ini.GetBool("Core.Encryption", "EncryptPak", out Settings.bEnablePakIndexEncryption);
                Settings.bEnablePakFullAssetEncryption = false;
                Settings.bEnablePakUAssetEncryption    = false;
                Settings.bEnablePakIniEncryption       = Settings.bEnablePakIndexEncryption;

                string EncryptionKeyString;
                Ini.GetString("Core.Encryption", "aes.key", out EncryptionKeyString);
                Settings.EncryptionKey     = new EncryptionKey();
                Settings.EncryptionKey.Key = ParseAnsiStringToByteArray(EncryptionKeyString);
            }

            Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.Crypto, InProjectDirectory, InTargetPlatform);
            string SectionName = "/Script/CryptoKeys.CryptoKeysSettings";
            ConfigHierarchySection CryptoSection = Ini.FindSection(SectionName);

            // If we have new format crypto keys, read them in over the top of the legacy settings
            if (CryptoSection != null && CryptoSection.KeyNames.Count() > 0)
            {
                Ini.GetBool(SectionName, "bEnablePakSigning", out Settings.bEnablePakSigning);
                Ini.GetBool(SectionName, "bEncryptPakIniFiles", out Settings.bEnablePakIniEncryption);
                Ini.GetBool(SectionName, "bEncryptPakIndex", out Settings.bEnablePakIndexEncryption);
                Ini.GetBool(SectionName, "bEncryptUAssetFiles", out Settings.bEnablePakUAssetEncryption);
                Ini.GetBool(SectionName, "bEncryptAllAssetFiles", out Settings.bEnablePakFullAssetEncryption);

                // Parse encryption key
                string EncryptionKeyString;
                Ini.GetString(SectionName, "EncryptionKey", out EncryptionKeyString);
                if (!string.IsNullOrEmpty(EncryptionKeyString))
                {
                    Settings.EncryptionKey     = new EncryptionKey();
                    Settings.EncryptionKey.Key = System.Convert.FromBase64String(EncryptionKeyString);

                    if (Settings.EncryptionKey.Key.Length != 32)
                    {
                        throw new Exception("The encryption key specified in the crypto config file must be 32 bytes long!");
                    }
                }

                // Parse signing key
                string PrivateExponent, PublicExponent, Modulus;
                Ini.GetString(SectionName, "SigningPrivateExponent", out PrivateExponent);
                Ini.GetString(SectionName, "SigningModulus", out Modulus);
                Ini.GetString(SectionName, "SigningPublicExponent", out PublicExponent);

                if (!String.IsNullOrEmpty(PrivateExponent) && !String.IsNullOrEmpty(PublicExponent) && !String.IsNullOrEmpty(Modulus))
                {
                    Settings.SigningKey = new SigningKeyPair();
                    Settings.SigningKey.PublicKey.Exponent  = System.Convert.FromBase64String(PublicExponent);
                    Settings.SigningKey.PublicKey.Modulus   = System.Convert.FromBase64String(Modulus);
                    Settings.SigningKey.PrivateKey.Exponent = System.Convert.FromBase64String(PrivateExponent);
                    Settings.SigningKey.PrivateKey.Modulus  = Settings.SigningKey.PublicKey.Modulus;
                }
            }

            return(Settings);
        }
Esempio n. 21
0
        public override void SetUpProjectEnvironment(UnrealTargetConfiguration Configuration, TargetInfo Target = null)
        {
            if (!bInitializedProject)
            {
                base.SetUpProjectEnvironment(Configuration, Target);

                // update the configuration based on the project file
                // look in ini settings for what platforms to compile for
                ConfigHierarchy Ini        = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), Platform);
                string          MinVersion = "IOS_8";
                if (Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MinimumiOSVersion", out MinVersion))
                {
                    switch (MinVersion)
                    {
                    case "IOS_61":
                        Log.TraceWarningOnce("IOS 6 is no longer supported in UE4 as 4.11");
                        RunTimeIOSVersion = "8.0";
                        break;

                    case "IOS_7":
                        Log.TraceWarningOnce("IOS 7 is no longer supported in UE4 as 4.14");
                        RunTimeIOSVersion = "8.0";
                        break;

                    case "IOS_8":
                        RunTimeIOSVersion = "8.0";
                        break;

                    case "IOS_9":
                        RunTimeIOSVersion = "9.0";
                        break;

                    case "IOS_10":
                        RunTimeIOSVersion = "10.0";
                        break;
                    }
                }

                bool biPhoneAllowed = true;
                bool biPadAllowed   = true;
                Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsIPhone", out biPhoneAllowed);
                Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bSupportsIPad", out biPadAllowed);
                if (biPhoneAllowed && biPadAllowed)
                {
                    RunTimeIOSDevices = "1,2";
                }
                else if (biPadAllowed)
                {
                    RunTimeIOSDevices = "2";
                }
                else if (biPhoneAllowed)
                {
                    RunTimeIOSDevices = "1";
                }

                NonShippingArchitectures = String.Join(",", GetNonShippingArchitectures(Ini));

                ShippingArchitectures = String.Join(",", GetShippingArchitectures(Ini));

                // determine if we need to generate the dsym
                Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMFile", out BuildConfiguration.bGeneratedSYMFile);
                Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMBundle", out BuildConfiguration.bGeneratedSYMBundle);

                // determie if bitcode should be generated for the shipping code
                Ini.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bShipForBitcode", out bShipForBitcode);

                // @todo tvos: We probably want to handle TVOS versions here
                Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalLinkerFlags", out AdditionalLinkerFlags);
                Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "AdditionalShippingLinkerFlags", out AdditionalShippingLinkerFlags);

                Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "MobileProvision", out MobileProvision);
                Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "SigningCertificate", out SigningCertificate);

                // bundle identifier
                Ini.GetString("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "BundleIdentifier", out BundleIdentifier);

                bInitializedProject = true;
            }

            ProvisionData Data     = new ProvisionData();
            string        BundleId = BundleIdentifier.Replace("[PROJECT_NAME]", ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game")).Replace("_", "");
            bool          bIsTVOS  = GetCodesignPlatformName() == "appletvos";

            if (!ProvisionCache.ContainsKey(BundleId + " " + bIsTVOS.ToString() + " " + bForDistribtion.ToString()))
            {
                Certificate = SigningCertificate;
                Provision   = MobileProvision;
                if (!string.IsNullOrEmpty(SigningCertificate))
                {
                    // verify the certificate
                    Process IPPProcess = new Process();
                    if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                    {
                        string IPPCmd = "\"" + UnrealBuildTool.EngineDirectory + "/Binaries/DotNET/IOS/IPhonePackager.exe\" certificates " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + BundleId + (bForDistribtion ? " -distribution" : "");
                        IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                        IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "/Build/BatchFiles/Mac/RunMono.sh";
                        IPPProcess.StartInfo.Arguments        = IPPCmd;
                        IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                        IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    }
                    else
                    {
                        string IPPCmd = "certificates " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + BundleId + (bForDistribtion ? " -distribution" : "");
                        IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                        IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "\\Binaries\\DotNET\\IOS\\IPhonePackager.exe";
                        IPPProcess.StartInfo.Arguments        = IPPCmd;
                        IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                        IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    }
                    Utils.RunLocalProcess(IPPProcess);
                }
                else
                {
                    Certificate      = bForDistribtion ? "iPhone Distribution" : "iPhone Developer";
                    bHaveCertificate = true;
                }

                if (string.IsNullOrEmpty(MobileProvision) || // no provision specified
                    !File.Exists((BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac ? (Environment.GetEnvironmentVariable("HOME") + "/Library/MobileDevice/Provisioning Profiles/") : (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/")) + MobileProvision) || // file doesn't exist
                    !bHaveCertificate)    // certificate doesn't exist
                {
                    Certificate = "";
                    Provision   = "";
                    Log.TraceLog("Provision not specified or not found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", searching for compatible match...");
                    Process IPPProcess = new Process();
                    if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac)
                    {
                        string IPPCmd = "\"" + UnrealBuildTool.EngineDirectory + "/Binaries/DotNET/IOS/IPhonePackager.exe\" signing_match " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + BundleId + (bIsTVOS ? " -tvos" : "") + (bForDistribtion ? " -distribution" : "");
                        IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                        IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "/Build/BatchFiles/Mac/RunMono.sh";
                        IPPProcess.StartInfo.Arguments        = IPPCmd;
                        IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                        IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    }
                    else
                    {
                        string IPPCmd = "signing_match " + ((ProjectFile != null) ? ("\"" + ProjectFile.ToString() + "\"") : "Engine") + " -bundlename " + BundleId + (bIsTVOS ? " -tvos" : "") + (bForDistribtion ? " -distribution" : "");
                        IPPProcess.StartInfo.WorkingDirectory = UnrealBuildTool.EngineDirectory.ToString();
                        IPPProcess.StartInfo.FileName         = UnrealBuildTool.EngineDirectory + "\\Binaries\\DotNET\\IOS\\IPhonePackager.exe";
                        IPPProcess.StartInfo.Arguments        = IPPCmd;
                        IPPProcess.OutputDataReceived        += new DataReceivedEventHandler(IPPDataReceivedHandler);
                        IPPProcess.ErrorDataReceived         += new DataReceivedEventHandler(IPPDataReceivedHandler);
                    }
                    Utils.RunLocalProcess(IPPProcess);
                    Log.TraceLog("Provision found for " + ((ProjectFile != null) ? ProjectFile.GetFileNameWithoutAnyExtensions() : "UE4Game") + ", Provision: " + Provision + " Certificate: " + Certificate);
                }
                // add to the dictionary
                Data.MobileProvision = Provision;
                Data.Certificate     = Certificate.Replace("\"", "");

                // read the provision to get the UUID
                string filename = (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Mac ? (Environment.GetEnvironmentVariable("HOME") + "/Library/MobileDevice/Provisioning Profiles/") : (Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Apple Computer/MobileDevice/Provisioning Profiles/")) + Data.MobileProvision;
                if (File.Exists(filename))
                {
                    string AllText = File.ReadAllText(filename);
                    int    idx     = AllText.IndexOf("<key>UUID</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx      += "<string>".Length;
                            Data.UUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                    idx = AllText.IndexOf("<key>com.apple.developer.team-identifier</key>");
                    if (idx > 0)
                    {
                        idx = AllText.IndexOf("<string>", idx);
                        if (idx > 0)
                        {
                            idx          += "<string>".Length;
                            Data.TeamUUID = AllText.Substring(idx, AllText.IndexOf("</string>", idx) - idx);
                        }
                    }
                }
                else
                {
                    Log.TraceLog("No matching provision file was discovered. Please ensure you have a compatible provision installed.");
                }
                ProvisionCache.Add(BundleId + " " + bIsTVOS.ToString() + " " + bForDistribtion.ToString(), Data);
            }
            else
            {
                Data = ProvisionCache[BundleId + " " + bIsTVOS.ToString() + " " + bForDistribtion.ToString()];
            }
            MobileProvision     = Data.MobileProvision;
            SigningCertificate  = Data.Certificate;
            MobileProvisionUUID = Data.UUID;
            TeamUUID            = Data.TeamUUID;
        }
Esempio n. 22
0
        public List <string> CreateManifest(string InManifestName, string InOutputPath, string InIntermediatePath, FileReference InProjectFile, string InProjectDirectory, List <UnrealTargetConfiguration> InTargetConfigs, List <string> InExecutables)
        {
            // Verify we can find the SDK.
            string SDKDirectory = GetSDKDirectory();

            if (string.IsNullOrEmpty(SDKDirectory))
            {
                return(null);
            }

            // Check parameter values are valid.
            if (InTargetConfigs.Count != InExecutables.Count)
            {
                Log.TraceError("The number of target configurations ({0}) and executables ({1}) passed to manifest generation do not match.", InTargetConfigs.Count, InExecutables.Count);
                return(null);
            }
            if (InTargetConfigs.Count < 1)
            {
                Log.TraceError("The number of target configurations is zero, so we cannot generate a manifest.");
                return(null);
            }

            if (!CreateCheckDirectory(InOutputPath))
            {
                Log.TraceError("Failed to create output directory \"{0}\".", InOutputPath);
                return(null);
            }
            if (!CreateCheckDirectory(InIntermediatePath))
            {
                Log.TraceError("Failed to create intermediate directory \"{0}\".", InIntermediatePath);
                return(null);
            }

            OutputPath       = InOutputPath;
            IntermediatePath = InIntermediatePath;
            ProjectFile      = InProjectFile;
            ProjectPath      = InProjectDirectory;
            UpdatedFilePaths = new List <string>();

            // Load up INI settings. We'll use engine settings to retrieve the manifest configuration, but these may reference
            // values in either game or engine settings, so we'll keep both.
            GameIni   = ConfigCache.ReadHierarchy(ConfigHierarchyType.Game, DirectoryReference.FromFile(InProjectFile), ConfigPlatform);
            EngineIni = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(InProjectFile), ConfigPlatform);

            // Load and verify/clean culture list
            {
                List <string> CulturesToStageWithDuplicates;
                GameIni.GetArray("/Script/UnrealEd.ProjectPackagingSettings", "CulturesToStage", out CulturesToStageWithDuplicates);
                GameIni.GetString("/Script/UnrealEd.ProjectPackagingSettings", "DefaultCulture", out DefaultCulture);
                if (CulturesToStageWithDuplicates == null || CulturesToStageWithDuplicates.Count < 1)
                {
                    Log.TraceError("At least one culture must be selected to stage.");
                    return(null);
                }

                CulturesToStage = CulturesToStageWithDuplicates.Distinct().ToList();
            }
            if (DefaultCulture == null || DefaultCulture.Length < 1)
            {
                DefaultCulture = CulturesToStage[0];
                Log.TraceWarning("A default culture must be selected to stage. Using {0}.", DefaultCulture);
            }
            if (!CulturesToStage.Contains(DefaultCulture))
            {
                DefaultCulture = CulturesToStage[0];
                Log.TraceWarning("The default culture must be one of the staged cultures. Using {0}.", DefaultCulture);
            }

            List <string> PerCultureValues;

            if (EngineIni.GetArray(IniSection_PlatformTargetSettings, "PerCultureResources", out PerCultureValues))
            {
                foreach (string CultureCombinedValues in PerCultureValues)
                {
                    Dictionary <string, string> SeparatedCultureValues;
                    if (!ConfigHierarchy.TryParse(CultureCombinedValues, out SeparatedCultureValues))
                    {
                        Log.TraceWarning("Invalid per-culture resource value: {0}", CultureCombinedValues);
                        continue;
                    }

                    string StageId      = SeparatedCultureValues["StageId"];
                    int    CultureIndex = CulturesToStage.FindIndex(x => x == StageId);
                    if (CultureIndex >= 0)
                    {
                        CulturesToStage[CultureIndex] = SeparatedCultureValues["CultureId"];
                        if (DefaultCulture == StageId)
                        {
                            DefaultCulture = SeparatedCultureValues["CultureId"];
                        }
                    }
                }
            }
            // Only warn if shipping, we can run without translated cultures they're just needed for cert
            else if (InTargetConfigs.Contains(UnrealTargetConfiguration.Shipping))
            {
                Log.TraceInformation("Staged culture mappings not setup in the editor. See Per Culture Resources in the {0} Target Settings.", Platform.ToString());
            }

            // Clean out the resources intermediate path so that we know there are no stale binary files.
            string IntermediateResourceDirectory = Path.Combine(IntermediatePath, BuildResourceSubPath);

            RecursivelyForceDeleteDirectory(IntermediateResourceDirectory);
            if (!CreateCheckDirectory(IntermediateResourceDirectory))
            {
                Log.TraceError("Could not create directory {0}.", IntermediateResourceDirectory);
                return(null);
            }

            // Construct a single resource writer for the default (no-culture) values
            string DefaultResourceIntermediatePath = Path.Combine(IntermediateResourceDirectory, "resources.resw");

            DefaultResourceWriter = new UEResXWriter(DefaultResourceIntermediatePath);

            // Construct the ResXWriters for each culture
            PerCultureResourceWriters = new Dictionary <string, UEResXWriter>();
            foreach (string Culture in CulturesToStage)
            {
                string IntermediateStringResourcePath = Path.Combine(IntermediateResourceDirectory, Culture);
                string IntermediateStringResourceFile = Path.Combine(IntermediateStringResourcePath, "resources.resw");
                if (!CreateCheckDirectory(IntermediateStringResourcePath))
                {
                    Log.TraceWarning("Culture {0} resources not staged.", Culture);
                    CulturesToStage.Remove(Culture);
                    if (Culture == DefaultCulture)
                    {
                        DefaultCulture = CulturesToStage[0];
                        Log.TraceWarning("Default culture skipped. Using {0} as default culture.", DefaultCulture);
                    }
                    continue;
                }
                PerCultureResourceWriters.Add(Culture, new UEResXWriter(IntermediateStringResourceFile));
            }



            // Create the manifest document
            string IdentityName        = null;
            var    ManifestXmlDocument = new XDocument(GetManifest(InTargetConfigs, InExecutables, out IdentityName));

            // Export manifest to the intermediate directory then compare the contents to any existing target manifest
            // and replace if there are differences.
            string ManifestIntermediatePath = Path.Combine(IntermediatePath, InManifestName);
            string ManifestTargetPath       = Path.Combine(OutputPath, InManifestName);

            ManifestXmlDocument.Save(ManifestIntermediatePath);
            CompareAndReplaceModifiedTarget(ManifestIntermediatePath, ManifestTargetPath);
            ProcessManifest(InTargetConfigs, InExecutables, InManifestName, ManifestTargetPath, ManifestIntermediatePath);

            // Clean out any resource directories that we aren't staging
            string TargetResourcePath = Path.Combine(OutputPath, BuildResourceSubPath);

            if (Directory.Exists(TargetResourcePath))
            {
                List <string> TargetResourceDirectories = new List <string>(Directory.GetDirectories(TargetResourcePath, "*.*", SearchOption.AllDirectories));
                foreach (string ResourceDirectory in TargetResourceDirectories)
                {
                    if (!CulturesToStage.Contains(Path.GetFileName(ResourceDirectory)))
                    {
                        RecursivelyForceDeleteDirectory(ResourceDirectory);
                    }
                }
            }

            // Export the resource tables starting with the default culture
            string DefaultResourceTargetPath = Path.Combine(OutputPath, BuildResourceSubPath, "resources.resw");

            DefaultResourceWriter.Close();
            CompareAndReplaceModifiedTarget(DefaultResourceIntermediatePath, DefaultResourceTargetPath);

            foreach (var Writer in PerCultureResourceWriters)
            {
                Writer.Value.Close();

                string IntermediateStringResourceFile = Path.Combine(IntermediateResourceDirectory, Writer.Key, "resources.resw");
                string TargetStringResourceFile       = Path.Combine(OutputPath, BuildResourceSubPath, Writer.Key, "resources.resw");

                CompareAndReplaceModifiedTarget(IntermediateStringResourceFile, TargetStringResourceFile);
            }

            // Copy all the binary resources into the target directory.
            CopyResourcesToTargetDir();

            // The resource database is dependent on everything else calculated here (manifest, resource string tables, binary resources).
            // So if any file has been updated we'll need to run the config.
            if (UpdatedFilePaths.Count > 0)
            {
                // Create resource index configuration
                string PriExecutable            = GetMakePriBinaryPath();
                string ResourceConfigFile       = Path.Combine(IntermediatePath, "priconfig.xml");
                bool   bEnableAutoResourcePacks = false;
                EngineIni.GetBool(IniSection_PlatformTargetSettings, "bEnableAutoResourcePacks", out bEnableAutoResourcePacks);

                // If the game is not going to support language resource packs then merge the culture qualifiers.
                if (bEnableAutoResourcePacks || CulturesToStage.Count <= 1)
                {
                    RunExternalProgram(PriExecutable, "createconfig /cf \"" + ResourceConfigFile + "\" /dq " + DefaultCulture + " /o");
                }
                else
                {
                    RunExternalProgram(PriExecutable, "createconfig /cf \"" + ResourceConfigFile + "\" /dq " + String.Join("_", CulturesToStage) + " /o");
                }

                // Modify configuration to restrict indexing to the Resources directory (saves time and space)
                XmlDocument PriConfig = new XmlDocument();
                PriConfig.Load(ResourceConfigFile);

                // If the game is not going to support resource packs then remove the autoResourcePackages.
                if (!bEnableAutoResourcePacks)
                {
                    XmlNode PackagingNode = PriConfig.SelectSingleNode("/resources/packaging");
                    PackagingNode.ParentNode.RemoveChild(PackagingNode);
                }

                // The previous implementation using startIndexAt="Resources" did not produce the expected ResourceMapSubtree hierarchy, so this manually specifies all resources in a .resfiles instead.
                string ResourcesResFile = Path.Combine(IntermediatePath, "resources.resfiles");

                XmlNode      PriIndexNode  = PriConfig.SelectSingleNode("/resources/index");
                XmlAttribute PriStartIndex = PriIndexNode.Attributes["startIndexAt"];
                PriStartIndex.Value = ResourcesResFile;

                // Swap the default folder indexer-config to a RESFILES indexer-config.
                XmlElement FolderIndexerConfigNode = PriConfig.SelectSingleNode("/resources/index/indexer-config[@type='folder']") as XmlElement;
                FolderIndexerConfigNode.SetAttribute("type", "RESFILES");
                FolderIndexerConfigNode.RemoveAttribute("foldernameAsQualifier");
                FolderIndexerConfigNode.RemoveAttribute("filenameAsQualifier");

                PriConfig.Save(ResourceConfigFile);

                IEnumerable <string>      Resources     = Directory.EnumerateFiles(Path.Combine(OutputPath, BuildResourceSubPath), "*.*", SearchOption.AllDirectories);
                System.Text.StringBuilder ResourcesList = new System.Text.StringBuilder();
                foreach (string Resource in Resources)
                {
                    ResourcesList.AppendLine(Resource.Replace(OutputPath, "").TrimStart('\\'));
                }
                File.WriteAllText(ResourcesResFile, ResourcesList.ToString());

                // Remove previous pri files so we can enumerate which ones are new since the resource generator could produce a file for each staged language.
                IEnumerable <string> OldPriFiles = Directory.EnumerateFiles(IntermediatePath, "*.pri");
                foreach (string OldPri in OldPriFiles)
                {
                    try
                    {
                        File.Delete(OldPri);
                    }
                    catch (Exception)
                    {
                        Log.TraceError("Could not delete file {0}.", OldPri);
                    }
                }

                // Generate the resource index
                string ResourceLogFile   = Path.Combine(IntermediatePath, "ResIndexLog.xml");
                string ResourceIndexFile = Path.Combine(IntermediatePath, "resources.pri");

                string MakePriCommandLine = "new /pr \"" + OutputPath + "\" /cf \"" + ResourceConfigFile + "\" /mn \"" + ManifestTargetPath + "\" /il \"" + ResourceLogFile + "\" /of \"" + ResourceIndexFile + "\" /o";

                if (IdentityName != null)
                {
                    MakePriCommandLine += " /indexName \"" + IdentityName + "\"";
                }
                RunExternalProgram(PriExecutable, MakePriCommandLine);

                // Remove any existing pri target files that were not generated by this latest update
                IEnumerable <string> NewPriFiles    = Directory.EnumerateFiles(IntermediatePath, "*.pri");
                IEnumerable <string> TargetPriFiles = Directory.EnumerateFiles(OutputPath, "*.pri");
                foreach (string TargetPri in TargetPriFiles)
                {
                    if (!NewPriFiles.Contains(TargetPri))
                    {
                        try
                        {
                            File.Delete(TargetPri);
                        }
                        catch (Exception)
                        {
                            Log.TraceError("Could not remove stale file {0}.", TargetPri);
                        }
                    }
                }

                // Stage all the modified pri files to the output directory
                foreach (string NewPri in NewPriFiles)
                {
                    string NewResourceIndexFile   = Path.Combine(IntermediatePath, Path.GetFileName(NewPri));
                    string FinalResourceIndexFile = Path.Combine(OutputPath, Path.GetFileName(NewPri));
                    CompareAndReplaceModifiedTarget(NewResourceIndexFile, FinalResourceIndexFile);
                }
            }

            return(UpdatedFilePaths);
        }
        /// <summary>
        /// Checks if the editor is currently running and this is a hot-reload
        /// </summary>
        public static bool ShouldDoHotReloadFromIDE(BuildConfiguration BuildConfiguration, TargetDescriptor TargetDesc)
        {
            // Check if Hot-reload is disabled globally for this project
            ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(TargetDesc.ProjectFile), TargetDesc.Platform);
            bool            bAllowHotReloadFromIDE;

            if (Hierarchy.TryGetValue("BuildConfiguration", "bAllowHotReloadFromIDE", out bAllowHotReloadFromIDE) && !bAllowHotReloadFromIDE)
            {
                return(false);
            }

            if (!BuildConfiguration.bAllowHotReloadFromIDE)
            {
                return(false);
            }

            // Check if we're using LiveCode instead
            ConfigHierarchy EditorPerProjectHierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(TargetDesc.ProjectFile), TargetDesc.Platform);
            bool            bEnableLiveCode;

            if (EditorPerProjectHierarchy.GetBool("/Script/LiveCoding.LiveCodingSettings", "bEnabled", out bEnableLiveCode) && bEnableLiveCode)
            {
                return(false);
            }

            bool bIsRunning = false;

            // @todo ubtmake: Kind of cheating here to figure out if an editor target.  At this point we don't have access to the actual target description, and
            // this code must be able to execute before we create or load module rules DLLs so that hot reload can work with bUseUBTMakefiles
            if (TargetDesc.Name.EndsWith("Editor", StringComparison.OrdinalIgnoreCase))
            {
                string EditorBaseFileName = "UE4Editor";
                if (TargetDesc.Configuration != UnrealTargetConfiguration.Development)
                {
                    EditorBaseFileName = String.Format("{0}-{1}-{2}", EditorBaseFileName, TargetDesc.Platform, TargetDesc.Configuration);
                }

                FileReference EditorLocation;
                if (TargetDesc.Platform == UnrealTargetPlatform.Win64)
                {
                    EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Win64", String.Format("{0}.exe", EditorBaseFileName));
                }
                else if (TargetDesc.Platform == UnrealTargetPlatform.Mac)
                {
                    EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Mac", String.Format("{0}.app/Contents/MacOS/{0}", EditorBaseFileName));
                }
                else if (TargetDesc.Platform == UnrealTargetPlatform.Linux)
                {
                    EditorLocation = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Binaries", "Linux", EditorBaseFileName);
                }
                else
                {
                    throw new BuildException("Unknown editor filename for this platform");
                }

                using (Timeline.ScopeEvent("Finding editor processes for hot-reload"))
                {
                    DirectoryReference EditorRunsDir = DirectoryReference.Combine(UnrealBuildTool.EngineDirectory, "Intermediate", "EditorRuns");
                    if (!DirectoryReference.Exists(EditorRunsDir))
                    {
                        return(false);
                    }

                    if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64)
                    {
                        foreach (FileReference EditorInstanceFile in DirectoryReference.EnumerateFiles(EditorRunsDir))
                        {
                            int ProcessId;
                            if (!Int32.TryParse(EditorInstanceFile.GetFileName(), out ProcessId))
                            {
                                FileReference.Delete(EditorInstanceFile);
                                continue;
                            }

                            Process RunningProcess;
                            try
                            {
                                RunningProcess = Process.GetProcessById(ProcessId);
                            }
                            catch
                            {
                                RunningProcess = null;
                            }

                            if (RunningProcess == null)
                            {
                                FileReference.Delete(EditorInstanceFile);
                                continue;
                            }

                            FileReference MainModuleFile;
                            try
                            {
                                MainModuleFile = new FileReference(RunningProcess.MainModule.FileName);
                            }
                            catch
                            {
                                MainModuleFile = null;
                            }

                            if (!bIsRunning && EditorLocation == MainModuleFile)
                            {
                                bIsRunning = true;
                            }
                        }
                    }
                    else
                    {
                        FileInfo[] EditorRunsFiles = new DirectoryInfo(EditorRunsDir.FullName).GetFiles();
                        BuildHostPlatform.ProcessInfo[] Processes = BuildHostPlatform.Current.GetProcesses();

                        foreach (FileInfo File in EditorRunsFiles)
                        {
                            int PID;
                            BuildHostPlatform.ProcessInfo Proc = null;
                            if (!Int32.TryParse(File.Name, out PID) || (Proc = Processes.FirstOrDefault(P => P.PID == PID)) == default(BuildHostPlatform.ProcessInfo))
                            {
                                // Delete stale files (it may happen if editor crashes).
                                File.Delete();
                                continue;
                            }

                            // Don't break here to allow clean-up of other stale files.
                            if (!bIsRunning)
                            {
                                // Otherwise check if the path matches.
                                bIsRunning = new FileReference(Proc.Filename) == EditorLocation;
                            }
                        }
                    }
                }
            }
            return(bIsRunning);
        }
Esempio n. 24
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="Platform"></param>
        /// <param name="PlatformGameConfig"></param>
        /// <param name="AppName"></param>
        /// <param name="MobileProvisionFile"></param>
        /// <param name="bForDistribution"></param>
        /// <param name="IntermediateDir"></param>
        public static void WriteEntitlements(UnrealTargetPlatform Platform, ConfigHierarchy PlatformGameConfig,
                                             string AppName, FileReference MobileProvisionFile, bool bForDistribution, string IntermediateDir)
        {
            // get some info from the mobileprovisioning file
            // the iCloud identifier and the bundle id may differ
            string iCloudContainerIdentifier       = "";
            string iCloudContainerIdentifiersXML   = "<array><string>iCloud.$(CFBundleIdentifier)</string></array>";
            string UbiquityContainerIdentifiersXML = "<array><string>iCloud.$(CFBundleIdentifier)</string></array>";
            string iCloudServicesXML             = "<array><string>CloudKit</string><string>CloudDocuments</string></array>";
            string UbiquityKVStoreIdentifiersXML = "\t<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>";

            string OutputFileName = Path.Combine(IntermediateDir, AppName + ".entitlements");

            if (MobileProvisionFile != null && File.Exists(MobileProvisionFile.FullName))
            {
                Console.WriteLine("Write entitlements from provisioning file {0}", MobileProvisionFile);

                MobileProvisionContents MobileProvisionContent = MobileProvisionContents.Read(MobileProvisionFile);

                iCloudContainerIdentifier     = MobileProvisionContent.GetNodeValueByName("com.apple.developer.icloud-container-identifiers");
                iCloudContainerIdentifiersXML = MobileProvisionContent.GetNodeXMLValueByName("com.apple.developer.icloud-container-identifiers");

                string entitlementXML = MobileProvisionContent.GetNodeXMLValueByName("com.apple.developer.icloud-services");

                if (!entitlementXML.Contains("*") || Platform == UnrealTargetPlatform.TVOS)
                {
                    // for iOS, replace the generic value (*) with the default
                    iCloudServicesXML = entitlementXML;
                }

                entitlementXML = MobileProvisionContent.GetNodeXMLValueByName("com.apple.developer.ubiquity-container-identifiers");
                if (!entitlementXML.Contains("*") || !bForDistribution)
                {
                    // for distribution, replace the generic value (*) with the default
                    UbiquityContainerIdentifiersXML = entitlementXML;
                }

                entitlementXML = MobileProvisionContent.GetNodeXMLValueByName("com.apple.developer.ubiquity-kvstore-identifier");
                if (!entitlementXML.Contains("*") || !bForDistribution)
                {
                    // for distribution, replace the generic value (*) with the default
                    UbiquityKVStoreIdentifiersXML = entitlementXML;
                }
            }
            else
            {
                Console.WriteLine("Couldn't locate the mobile provisioning file {0}", MobileProvisionFile);
            }

            // write the entitlements file
            {
                bool bCloudKitSupported = false;
                PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableCloudKitSupport", out bCloudKitSupported);
                Directory.CreateDirectory(Path.GetDirectoryName(OutputFileName));
                // we need to have something so Xcode will compile, so we just set the get-task-allow, since we know the value,
                // which is based on distribution or not (true means debuggable)
                StringBuilder Text = new StringBuilder();
                Text.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
                Text.AppendLine("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
                Text.AppendLine("<plist version=\"1.0\">");
                Text.AppendLine("<dict>");
                Text.AppendLine("\t<key>get-task-allow</key>");
                Text.AppendLine(string.Format("\t<{0}/>", bForDistribution ? "false" : "true"));
                if (bCloudKitSupported)
                {
                    if (iCloudContainerIdentifiersXML != "")
                    {
                        Text.AppendLine("\t<key>com.apple.developer.icloud-container-identifiers</key>");
                        Text.AppendLine(iCloudContainerIdentifiersXML);
                    }

                    if (iCloudServicesXML != "")
                    {
                        Text.AppendLine("\t<key>com.apple.developer.icloud-services</key>");
                        Text.AppendLine(iCloudServicesXML);
                    }

                    if (UbiquityContainerIdentifiersXML != "")
                    {
                        Text.AppendLine("\t<key>com.apple.developer.ubiquity-container-identifiers</key>");
                        Text.AppendLine(UbiquityContainerIdentifiersXML);
                    }

                    if (UbiquityKVStoreIdentifiersXML != "")
                    {
                        Text.AppendLine("\t<key>com.apple.developer.ubiquity-kvstore-identifier</key>");
                        Text.AppendLine(UbiquityKVStoreIdentifiersXML);
                    }

                    Text.AppendLine("\t<key>com.apple.developer.icloud-container-environment</key>");
                    Text.AppendLine(string.Format("\t<string>{0}</string>", bForDistribution ? "Production" : "Development"));
                }

                bool bRemoteNotificationsSupported = false;
                PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableRemoteNotificationsSupport", out bRemoteNotificationsSupported);

                // for TVOS we need push notifications when building for distribution with CloudKit
                if (bCloudKitSupported && bForDistribution && Platform == UnrealTargetPlatform.TVOS)
                {
                    bRemoteNotificationsSupported = true;
                }

                if (bRemoteNotificationsSupported)
                {
                    Text.AppendLine("\t<key>aps-environment</key>");
                    Text.AppendLine(string.Format("\t<string>{0}</string>", bForDistribution ? "production" : "development"));
                }

                // for Sign in with Apple
                bool bSignInWithAppleSupported = false;
                PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableSignInWithAppleSupport", out bSignInWithAppleSupported);

                if (bSignInWithAppleSupported)
                {
                    Text.AppendLine("\t<key>com.apple.developer.applesignin</key>");
                    Text.AppendLine("\t<array><string>Default</string></array>");
                }

                // Add Multi-user support for tvOS
                bool bRunAsCurrentUser = false;
                PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bRunAsCurrentUser", out bRunAsCurrentUser);

                if (bRunAsCurrentUser && Platform == UnrealTargetPlatform.TVOS)
                {
                    Text.AppendLine("\t<key>com.apple.developer.user-management</key>");
                    Text.AppendLine("\t<array><string>runs-as-current-user</string></array>");
                }


                // End of entitlements
                Text.AppendLine("</dict>");
                Text.AppendLine("</plist>");

                if (File.Exists(OutputFileName))
                {
                    // read existing file
                    string ExisitingFileContents = File.ReadAllText(OutputFileName);
                    bool   bFileChanged          = !ExisitingFileContents.Equals(Text.ToString(), StringComparison.Ordinal);
                    // overwrite file if there are content changes
                    if (bFileChanged)
                    {
                        File.WriteAllText(OutputFileName, Text.ToString());
                    }
                }
                else
                {
                    File.WriteAllText(OutputFileName, Text.ToString());
                }
            }

            // create a pList key named ICloudContainerIdentifier
            // to be used at run-time when intializing the CloudKit services
            if (iCloudContainerIdentifier != "")
            {
                string PListFile = IntermediateDir + "/" + AppName + "-Info.plist";
                if (File.Exists(PListFile))
                {
                    string    OldPListData = File.ReadAllText(PListFile);
                    XDocument XDoc;
                    try
                    {
                        XDoc = XDocument.Parse(OldPListData);
                        if (XDoc.DocumentType != null)
                        {
                            XDoc.DocumentType.InternalSubset = null;
                        }

                        XElement dictElement = XDoc.Root.Element("dict");
                        if (dictElement != null)
                        {
                            XElement containerIdKeyNew   = new XElement("key", "ICloudContainerIdentifier");
                            XElement containerIdValueNew = new XElement("string", iCloudContainerIdentifier);

                            XElement containerIdKey = dictElement.Elements("key").FirstOrDefault(x => x.Value == "ICloudContainerIdentifier");
                            if (containerIdKey != null)
                            {
                                // if ICloudContainerIdentifier already exists in the pList file, update its value
                                XElement containerIdValue = containerIdKey.ElementsAfterSelf("string").FirstOrDefault();
                                if (containerIdValue != null)
                                {
                                    containerIdValue.Value = iCloudContainerIdentifier;
                                }
                                else
                                {
                                    containerIdKey.AddAfterSelf(containerIdValueNew);
                                }
                            }
                            else
                            {
                                // add ICloudContainerIdentifier to the pList
                                dictElement.Add(containerIdKeyNew);
                                dictElement.Add(containerIdValueNew);
                            }

                            XDoc.Save(PListFile);
                        }
                    }
                    catch (Exception e)
                    {
                        throw new BuildException("plist is invalid {0}\n{1}", e, OldPListData);
                    }
                }
            }
        }