Exemplo n.º 1
0
    public static bool CanCreateMapPaks(ProjectParams Param)
    {
        bool UseAsyncLevelLoading = false;
        var  ConfigCache          = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Param.RawProjectPath), UnrealTargetPlatform.HTML5);

        ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseAsyncLevelLoading", out UseAsyncLevelLoading);

        if (Param.Run)
        {
            return(false);
        }

        return(UseAsyncLevelLoading);
    }
Exemplo n.º 2
0
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        // Engine non-ufs (binaries)

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

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

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

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

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

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

                        foreach (StagedFileReference StagePath in StagedFiles)
                        {
                            StageBootstrapExecutable(SC, BootstrapExeName, Executable.Path, StagePath, BootstrapArguments);
                        }
                    }
                }
            }
        }
    }
    // --------------------------------------------------------------------------------
    // --------------------------------------------------------------------------------

    #region AMAZON S3
    public void UploadToS3(DeploymentContext SC, string OutputFilename)
    {
        ConfigHierarchy Ini    = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(SC.RawProjectPath), SC.StageTargetPlatform.PlatformType);
        bool            Upload = false;

        string Region     = "";
        string KeyId      = "";
        string AccessKey  = "";
        string BucketName = "";
        string FolderName = "";

        if (!Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UploadToS3", out Upload) || !Upload)
        {
            return;
        }

        bool AmazonIdentity = Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3Region", out Region) &&
                              Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3KeyID", out KeyId) &&
                              Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3SecretAccessKey", out AccessKey) &&
                              Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3BucketName", out BucketName);

        if (!AmazonIdentity)
        {
            LogInformation("Amazon S3 Incorrectly configured");
            return;
        }

        Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3FolderName", out FolderName);
        if (FolderName == "")
        {
            FolderName = SC.ShortProjectName;
        }
        else
        {
            // strip any before and after folder "/"
            FolderName = Regex.Replace(Regex.Replace(FolderName, "^/+", ""), "/+$", "");
        }

        List <Task> UploadTasks = new List <Task>();
        long        msTimeOut   = 0;

        foreach (KeyValuePair <string, string> Entry in SC.ArchivedFiles)
        {
            FileInfo Info = new FileInfo(Entry.Key);
            UploadTasks.Add(UploadToS3Worker(Info, Region, KeyId, AccessKey, BucketName, FolderName));
            if (msTimeOut < Info.Length)
            {
                msTimeOut = Info.Length;
            }
        }
        msTimeOut /= 100;             // [miliseconds] give 10 secs for each ~MB ( (10s * 1000ms) / ( 1024KB * 1024MB * 1000ms ) )
        if (msTimeOut < (100 * 1000)) // HttpClient: default timeout is 100 sec
        {
            msTimeOut = 100 * 1000;
        }
        LogInformation("Upload Timeout set to: " + (msTimeOut / 1000) + "secs");
        Task.WaitAll(UploadTasks.ToArray(), (int)msTimeOut);         // set timeout [miliseconds]

        string URL = "https://" + BucketName + ".s3.amazonaws.com/" + FolderName + "/" + OutputFilename;

        LogInformation("Your project's shareable link is: " + URL);

        LogInformation("Upload Tasks finished.");
    }
Exemplo n.º 4
0
    public Noesis(ReadOnlyTargetRules Target) : base(Target)
    {
        Type = ModuleType.External;

        string NoesisBasePath    = ModuleDirectory + "/NoesisSDK/";
        string NoesisIncludePath = NoesisBasePath + "Include/";
        string NoesisInteractivityIncludePath = NoesisBasePath + "Src/Packages/App/Interactivity/Include/";

        PublicIncludePaths.Add(ModuleDirectory);
        PublicIncludePaths.Add(NoesisIncludePath);
        PublicIncludePaths.Add(NoesisInteractivityIncludePath);

        // Let's try to make sure the right version of the SDK is in the right place.
        const string RequiredVersionName = "2.2.5";

        PublicDefinitions.Add("NOESIS_VERSION_NAME=\"" + RequiredVersionName + "\"");
        if (!Directory.Exists(NoesisBasePath))
        {
            throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName);
        }

        if (!Directory.Exists(NoesisBasePath + "Bin"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Bin directory in " + NoesisBasePath + "Bin. Minimum required version is " + RequiredVersionName);
        }

        if (!Directory.Exists(NoesisBasePath + "Include"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include. Minimum required version is " + RequiredVersionName);
        }

        if (!Directory.Exists(NoesisBasePath + "Lib"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Lib directory in " + NoesisBasePath + "Lib. Minimum required version is " + RequiredVersionName);
        }

        string NoesisSdkVersionInfo;

        try
        {
            NoesisSdkVersionInfo = File.ReadAllText(NoesisBasePath + "version.txt");
        }
        catch (Exception)
        {
            throw new BuildException("Could not find NoesisGUI SDK version.txt in " + NoesisBasePath + "version.txt. Minimum required version is " + RequiredVersionName);
        }

        string[] LineSplit        = NoesisSdkVersionInfo.Split('\n');
        string[] SplitVersion     = LineSplit[1].Split(' ');
        Version  InstalledVersion = new Version(SplitVersion[0]);
        Version  RequiredVersion  = new Version(RequiredVersionName);

        if (InstalledVersion != RequiredVersion)
        {
            throw new BuildException("Wrong version of the NoesisGUI SDK installed in " + NoesisBasePath + ". Required version is " + RequiredVersionName);
        }

        PublicSystemIncludePaths.Add(NoesisIncludePath);

        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            string NoesisLibPath = NoesisBasePath + "Lib/windows_x86_64/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis.lib");

            string NoesisDllPath       = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll";
            string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll";

            if (Target.ProjectFile != null)
            {
                CopyNoesisDll(ModuleDirectory + NoesisDllPath, DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath);
            }

            CopyNoesisDll(ModuleDirectory + NoesisDllPath, ModuleDirectory + "/../.." + NoesisDllTargetPath);

            if (System.IO.File.Exists(Target.RelativeEnginePath + NoesisDllTargetPath))
            {
                System.IO.File.Delete(Target.RelativeEnginePath + NoesisDllTargetPath);
            }

            if (Target.LinkType == TargetLinkType.Monolithic)
            {
                RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath);
            }
            else
            {
                RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath);
            }
        }
        else if (Target.Platform == UnrealTargetPlatform.Mac)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/osx/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.dylib");

            string NoesisDylibPath = "/NoesisSDK/Bin/osx/Noesis.dylib";
            RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath);
        }
        else if (Target.Platform == UnrealTargetPlatform.IOS)
        {
            string NoesisLibPath = NoesisBasePath + "Lib/ios/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis");

            PublicFrameworks.Add("CoreText");
        }
        else if (Target.Platform == UnrealTargetPlatform.Android)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/android_arm/";
            PublicLibraryPaths.Add(NoesisLibPath);
            string NoesisLib64Path = NoesisBasePath + "Bin/android_arm64/";
            PublicLibraryPaths.Add(NoesisLib64Path);
            PublicAdditionalLibraries.Add("Noesis");

            string NoesisAplPath = "/Noesis_APL.xml";
            AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath);
        }
        else if (Target.Platform == UnrealTargetPlatform.PS4)
        {
            string NoesisLibPath = NoesisBasePath + "Lib/ps4/";
            PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.a");
        }
        else if (Target.Platform == UnrealTargetPlatform.XboxOne)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/xbox_one/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis.lib");
        }
        else if (Target.Platform == UnrealTargetPlatform.HTML5)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/wasm/";
            PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.bc");
        }
    }
    public override void GetFilesToDeployOrStage(ProjectParams Params, DeploymentContext SC)
    {
        if (SC.bStageCrashReporter)
        {
            FileReference ReceiptFileName = TargetReceipt.GetDefaultPath(CommandUtils.EngineDirectory, "CrashReportClient", SC.StageTargetPlatform.PlatformType, UnrealTargetConfiguration.Shipping, null);
            if (FileReference.Exists(ReceiptFileName))
            {
                DirectoryReference EngineDir  = CommandUtils.EngineDirectory;
                DirectoryReference ProjectDir = DirectoryReference.FromFile(Params.RawProjectPath);
                TargetReceipt      Receipt    = TargetReceipt.Read(ReceiptFileName, EngineDir, ProjectDir);
                SC.StageBuildProductsFromReceipt(Receipt, true, false);
            }
        }

        // Stage all the build products
        Console.WriteLine("Staging all {0} build products", SC.StageTargets.Count);
        int BuildProductIdx = 0;

        foreach (StageTarget Target in SC.StageTargets)
        {
            Console.WriteLine(" Product {0}: {1}", BuildProductIdx, Target.Receipt.TargetName);
            SC.StageBuildProductsFromReceipt(Target.Receipt, Target.RequireFilesExist, Params.bTreatNonShippingBinariesAsDebugFiles);
            ++BuildProductIdx;
        }

        FileReference SplashImage = FileReference.Combine(SC.ProjectRoot, "Content", "Splash", "Splash.bmp");

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

        // Stage the bootstrap executable
        if (!Params.NoBootstrapExe)
        {
            foreach (StageTarget Target in SC.StageTargets)
            {
                BuildProduct Executable = Target.Receipt.BuildProducts.FirstOrDefault(x => x.Type == BuildProductType.Executable);
                if (Executable != null)
                {
                    // only create bootstraps for executables
                    string FullExecutablePath = Path.GetFullPath(Executable.Path.FullName);
                    if (Executable.Path.FullName.Replace("\\", "/").Contains("/" + TargetPlatformType.ToString() + "/"))
                    {
                        string BootstrapArguments = "";
                        if (!ShouldStageCommandLine(Params, SC))
                        {
                            if (!SC.IsCodeBasedProject)
                            {
                                BootstrapArguments = String.Format("\\\"../../../{0}/{0}.uproject\\\"", SC.ShortProjectName);
                            }
                            else
                            {
                                BootstrapArguments = SC.ShortProjectName;
                            }
                        }

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

                        List <StagedFileReference> StagePaths = SC.FilesToStage.NonUFSFiles.Where(x => x.Value == Executable.Path).Select(x => x.Key).ToList();
                        foreach (StagedFileReference StagePath in StagePaths)
                        {
                            StageBootstrapExecutable(SC, BootstrapExeName + ".sh", FullExecutablePath, StagePath.Name, BootstrapArguments);
                        }
                    }
                }
            }
        }
    }
    public void UploadToS3(DeploymentContext SC)
    {
        ConfigCacheIni Ini    = ConfigCacheIni.CreateConfigCacheIni(SC.StageTargetPlatform.PlatformType, "Engine", DirectoryReference.FromFile(SC.RawProjectPath));
        bool           Upload = false;

        string KeyId      = "";
        string AccessKey  = "";
        string BucketName = "";
        string FolderName = "";

        if (Ini.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UploadToS3", out Upload))
        {
            if (!Upload)
            {
                return;
            }
        }
        else
        {
            return;
        }
        bool AmazonIdentity = Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3KeyID", out KeyId) &&
                              Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3SecretAccessKey", out AccessKey) &&
                              Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3BucketName", out BucketName) &&
                              Ini.GetString("/Script/HTML5PlatformEditor.HTML5TargetSettings", "S3FolderName", out FolderName);

        if (!AmazonIdentity)
        {
            Log("Amazon S3 Incorrectly configured");
            return;
        }

        if (FolderName == "")
        {
            FolderName = SC.ShortProjectName;
        }

        List <Task> UploadTasks = new List <Task>();

        foreach (KeyValuePair <string, string> Entry in SC.ArchivedFiles)
        {
            FileInfo Info = new FileInfo(Entry.Key);
            UploadTasks.Add(Task.Factory.StartNew(() => UploadToS3Worker(Info, KeyId, AccessKey, BucketName, FolderName)));
        }

        Task.WaitAll(UploadTasks.ToArray());

        string URL = "http://" + BucketName + ".s3.amazonaws.com/" + FolderName + "/" + SC.ShortProjectName + ".html";

        Log("Your project's shareable link is: " + URL);

        Log("Upload Tasks finished.");
    }
Exemplo n.º 7
0
    public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL)
    {
        Log("Package {0}", Params.RawProjectPath);

        Log("Setting Emscripten SDK for packaging..");
        HTML5SDKInfo.SetupEmscriptenTemp();
        HTML5SDKInfo.SetUpEmscriptenConfigFile();

        string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5");

        if (!Directory.Exists(PackagePath))
        {
            Directory.CreateDirectory(PackagePath);
        }

        // ini configurations
        var  ConfigCache  = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5);
        bool targetWebGL1 = false;         // inverted checked - this will be going away soon...

        if (ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "TargetWebGL1", out targetWebGL1))
        {
            targetWebGL2 = !targetWebGL1;
        }

        // Debug and Development builds are not uncompressed to:
        // - speed up iteration times
        // - ensure (IndexedDB) data are not cached/used
        // Shipping builds "can be":
        // - compressed
        // - (IndexedDB) cached
        if (Params.ClientConfigsToBuild[0].ToString() == "Shipping")
        {
            ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed);
            ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB);
        }
        Log("HTML5Platform.Automation: TargetWebGL2 = " + targetWebGL2);
        Log("HTML5Platform.Automation: Compressed = " + Compressed);
        Log("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB);

        string FinalDataLocation = Path.Combine(PackagePath, Params.ShortProjectName) + ".data";

        if (HTMLPakAutomation.CanCreateMapPaks(Params))
        {
            HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC);

            // Create Necessary Paks.
            PakAutomation.CreateEnginePak();
            PakAutomation.CreateGamePak();
            PakAutomation.CreateContentDirectoryPak();

            // Create Emscripten Package from Necessary Paks. - This will be the VFS.
            PakAutomation.CreateEmscriptenDataPackage(PackagePath, FinalDataLocation);

            // Create All Map Paks which  will be downloaded on the fly.
            PakAutomation.CreateMapPak();

            // Create Delta Paks if setup.
            List <string> Paks = new List <string>();
            ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks);

            if (Paks != null)
            {
                foreach (var Pak in Paks)
                {
                    var    Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase);
                    string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", ""));
                    string MapTo   = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", ""));
                    PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo);
                }
            }
        }
        else
        {
            // we need to operate in the root
            string PythonPath   = HTML5SDKInfo.Python();
            string PackagerPath = HTML5SDKInfo.EmscriptenPackager();

            using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN))
            {
                using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5")))
                {
                    string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", PackagerPath, FinalDataLocation);
                    RunAndLog(CmdEnv, PythonPath, CmdLine);
                }
            }
        }

        // copy the "Executable" to the package directory
        string ProjectGameExeFilename = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString();
        string GameBasename           = Path.GetFileNameWithoutExtension(ProjectGameExeFilename);

        if (Params.ClientConfigsToBuild[0].ToString() != "Development")
        {
            GameBasename += "-HTML5-" + Params.ClientConfigsToBuild[0].ToString();
        }
        // no extension
        string GameBasepath            = Path.GetDirectoryName(ProjectGameExeFilename);
        string FullGameBasePath        = Path.Combine(GameBasepath, GameBasename);
        string FullPackageGameBasePath = Path.Combine(PackagePath, GameBasename);

        // with extension
        string GameExe                = GameBasename + ".js";
        string FullGameExePath        = Path.Combine(GameBasepath, GameExe);
        string FullPackageGameExePath = Path.Combine(PackagePath, GameExe);

        // ensure the ue4game binary exists, if applicable
        if (!FileExists_NoExceptions(FullGameExePath))
        {
            Log("Failed to find game application " + FullGameExePath);
            throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", FullGameExePath);
        }

        if (FullGameExePath != FullPackageGameExePath)         // TODO: remove this check
        {
            File.Copy(FullGameExePath + ".symbols", FullPackageGameExePath + ".symbols", true);
            File.Copy(FullGameBasePath + ".wasm", FullPackageGameBasePath + ".wasm", true);
            File.Copy(FullGameExePath, FullPackageGameExePath, true);
        }

        File.SetAttributes(FullPackageGameExePath + ".symbols", FileAttributes.Normal);
        File.SetAttributes(FullPackageGameBasePath + ".wasm", FileAttributes.Normal);
        File.SetAttributes(FullPackageGameExePath, FileAttributes.Normal);

        // put the HTML file to the package directory
        string TemplateFile = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/GameX.html.template");
        string OutputFile   = Path.Combine(PackagePath,
                                           (Params.ClientConfigsToBuild[0].ToString() != "Development" ?
                                            (Params.ShortProjectName + "-HTML5-" + Params.ClientConfigsToBuild[0].ToString()) :
                                            Params.ShortProjectName)) + ".html";

        GenerateFileFromTemplate(TemplateFile,
                                 OutputFile,
                                 Params.ShortProjectName,
                                 Params.ClientConfigsToBuild[0].ToString(),
                                 Params.StageCommandline,
                                 !Params.IsCodeBasedProject,
                                 HTML5SDKInfo.HeapSize(ConfigCache, Params.ClientConfigsToBuild[0].ToString()));

        string MacBashTemplateFile = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/RunMacHTML5LaunchHelper.command.template");
        string MacBashOutputFile   = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command");
        string MonoPath            = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh");

        GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath);

        string htaccessTemplate = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5/htaccess.template");
        string htaccesspath     = Path.Combine(PackagePath, ".htaccess");

        if (File.Exists(htaccesspath))
        {
            FileAttributes attributes = File.GetAttributes(htaccesspath);
            if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                attributes &= ~FileAttributes.ReadOnly;
                File.SetAttributes(htaccesspath, attributes);
            }
        }
        File.Copy(htaccessTemplate, htaccesspath, true);

        string JSDir  = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5");
        string OutDir = PackagePath;

        // Gather utlity .js files and combine into one file
        string[] UtilityJavaScriptFiles = Directory.GetFiles(JSDir, "*.js");

        string DestinationFile = OutDir + "/Utility.js";

        File.Delete(DestinationFile);
        foreach (var UtilityFile in UtilityJavaScriptFiles)
        {
            string Data = File.ReadAllText(UtilityFile);
            File.AppendAllText(DestinationFile, Data);
        }

        if (Compressed)
        {
            Log("Build configuration is " + Params.ClientConfigsToBuild[0].ToString() + ", so (gzip) compressing files for web servers.");

            // Compress all files. These are independent tasks which can be threaded.
            List <Task> CompressionTasks = new List <Task>();

            // data file
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FinalDataLocation, FinalDataLocation + "gz")));

            // data file .js driver.
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FinalDataLocation + ".js", FinalDataLocation + ".jsgz")));

            // main game code
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameBasePath + ".wasm", FullPackageGameBasePath + ".wasmgz")));
            // main js.
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameExePath, FullPackageGameExePath + "gz")));

            // symbols file.
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(FullPackageGameExePath + ".symbols", FullPackageGameExePath + ".symbolsgz")));

            // Utility
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(OutDir + "/Utility.js", OutDir + "/Utility.jsgz")));

            Task.WaitAll(CompressionTasks.ToArray());
        }
        else
        {
            Log("Build configuration is " + Params.ClientConfigsToBuild[0].ToString() + ", so not compressing. Build Shipping configuration to compress files to save space.");

            // nuke old compressed files to prevent using stale files
            File.Delete(FinalDataLocation + "gz");
            File.Delete(FinalDataLocation + ".jsgz");
            File.Delete(FullPackageGameExePath + "gz");
            File.Delete(FullPackageGameBasePath + ".wasmgz");
            File.Delete(FullPackageGameExePath + ".symbolsgz");
            File.Delete(OutDir + "/Utility.jsgz");
        }

        File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(OutDir, "HTML5LaunchHelper.exe"), true);
//		Task.WaitAll(CompressionTasks);
        PrintRunTime();
    }
        /// <summary>
        /// Runs a commandlet using Engine/Binaries/Win64/UE4Editor-Cmd.exe.
        /// </summary>
        /// <param name="ProjectFile">Project name.</param>
        /// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param>
        /// <param name="Commandlet">Commandlet name.</param>
        /// <param name="Parameters">Command line parameters (without -run=)</param>
        /// <param name="DestLogFile">Log file after completion</param>
        public static void RunCommandlet(FileReference ProjectName, string UE4Exe, string Commandlet, string Parameters, out string DestLogFile)
        {
            LogInformation("Running UE4Editor {0} for project {1}", Commandlet, ProjectName);

            var CWD = Path.GetDirectoryName(UE4Exe);

            string EditorExe = UE4Exe;

            if (String.IsNullOrEmpty(CWD))
            {
                EditorExe = HostPlatform.Current.GetUE4ExePath(UE4Exe);
                CWD       = CombinePaths(CmdEnv.LocalRoot, HostPlatform.Current.RelativeBinariesFolder);
            }

            PushDir(CWD);

            DateTime StartTime = DateTime.UtcNow;

            string LocalLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.EngineSavedFolder, Commandlet));

            LogInformation("Commandlet log file is {0}", LocalLogFile);
            string Args = String.Format(
                "{0} -run={1} {2} -abslog={3} -stdout -CrashForUAT -unattended -NoLogTimes {5}{4}",
                (ProjectName == null) ? "" : CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName.FullName),
                Commandlet,
                String.IsNullOrEmpty(Parameters) ? "" : Parameters,
                CommandUtils.MakePathSafeToUseWithCommandLine(LocalLogFile),
                IsBuildMachine ? "-buildmachine" : "",
                (GlobalCommandLine.Verbose || GlobalCommandLine.AllowStdOutLogVerbosity) ? "-AllowStdOutLogVerbosity " : ""
                );
            ERunOptions Opts = ERunOptions.Default;

            if (GlobalCommandLine.UTF8Output)
            {
                Args += " -UTF8Output";
                Opts |= ERunOptions.UTF8Output;
            }
            IProcessResult RunResult = Run(EditorExe, Args, Options: Opts, Identifier: Commandlet);

            PopDir();

            // If we're running on a Windows build machine, copy any crash dumps into the log folder
            if (HostPlatform.Current.HostEditorPlatform == UnrealTargetPlatform.Win64 && IsBuildMachine)
            {
                DirectoryInfo CrashesDir = new DirectoryInfo(DirectoryReference.Combine(DirectoryReference.FromFile(ProjectName) ?? CommandUtils.EngineDirectory, "Saved", "Crashes").FullName);
                if (CrashesDir.Exists)
                {
                    foreach (DirectoryInfo CrashDir in CrashesDir.EnumerateDirectories())
                    {
                        if (CrashDir.LastWriteTimeUtc > StartTime)
                        {
                            DirectoryInfo OutputCrashesDir = new DirectoryInfo(Path.Combine(CmdEnv.LogFolder, "Crashes", CrashDir.Name));
                            try
                            {
                                CommandUtils.LogInformation("Copying crash data to {0}...", OutputCrashesDir.FullName);
                                OutputCrashesDir.Create();

                                foreach (FileInfo CrashFile in CrashDir.EnumerateFiles())
                                {
                                    CrashFile.CopyTo(Path.Combine(OutputCrashesDir.FullName, CrashFile.Name));
                                }
                            }
                            catch (Exception Ex)
                            {
                                CommandUtils.LogWarning("Unable to copy crash data; skipping. See log for exception details.");
                                CommandUtils.LogVerbose(Tools.DotNETCommon.ExceptionUtils.FormatExceptionDetails(Ex));
                            }
                        }
                    }
                }
            }

            // If we're running on a Mac, dump all the *.crash files that were generated while the editor was running.
            if (HostPlatform.Current.HostEditorPlatform == UnrealTargetPlatform.Mac)
            {
                // If the exit code indicates the main process crashed, introduce a small delay because the crash report is written asynchronously.
                // If we exited normally, still check without waiting in case SCW or some other child process crashed.
                if (RunResult.ExitCode > 128)
                {
                    CommandUtils.LogInformation("Pausing before checking for crash logs...");
                    Thread.Sleep(10 * 1000);
                }

                // Create a list of directories containing crash logs, and add the system log folder
                List <string> CrashDirs = new List <string>();
                CrashDirs.Add("/Library/Logs/DiagnosticReports");

                // Add the user's log directory too
                string HomeDir = Environment.GetEnvironmentVariable("HOME");
                if (!String.IsNullOrEmpty(HomeDir))
                {
                    CrashDirs.Add(Path.Combine(HomeDir, "Library/Logs/DiagnosticReports"));
                }

                // Check each directory for crash logs
                List <FileInfo> CrashFileInfos = new List <FileInfo>();
                foreach (string CrashDir in CrashDirs)
                {
                    try
                    {
                        DirectoryInfo CrashDirInfo = new DirectoryInfo(CrashDir);
                        if (CrashDirInfo.Exists)
                        {
                            CrashFileInfos.AddRange(CrashDirInfo.EnumerateFiles("*.crash", SearchOption.TopDirectoryOnly).Where(x => x.LastWriteTimeUtc >= StartTime));
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // Not all account types can access /Library/Logs/DiagnosticReports
                    }
                }

                // Dump them all to the log
                foreach (FileInfo CrashFileInfo in CrashFileInfos)
                {
                    // snmpd seems to often crash (suspect due to it being starved of CPU cycles during cooks)
                    // also ignore spotlight crash with the excel plugin
                    if (!CrashFileInfo.Name.StartsWith("snmpd_") && !CrashFileInfo.Name.StartsWith("mdworker32_") && !CrashFileInfo.Name.StartsWith("Dock_"))
                    {
                        CommandUtils.LogInformation("Found crash log - {0}", CrashFileInfo.FullName);
                        try
                        {
                            string[] Lines = File.ReadAllLines(CrashFileInfo.FullName);
                            foreach (string Line in Lines)
                            {
                                CommandUtils.LogInformation("Crash: {0}", Line);
                            }
                        }
                        catch (Exception Ex)
                        {
                            CommandUtils.LogWarning("Failed to read file ({0})", Ex.Message);
                        }
                    }
                }
            }

            // Copy the local commandlet log to the destination folder.
            DestLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.LogFolder, Commandlet));
            if (!CommandUtils.CopyFile_NoExceptions(LocalLogFile, DestLogFile))
            {
                CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, LocalLogFile, DestLogFile);
            }
            string ProjectStatsDirectory = CombinePaths((ProjectName == null)? CombinePaths(CmdEnv.LocalRoot, "Engine") : Path.GetDirectoryName(ProjectName.FullName), "Saved", "Stats");

            if (Directory.Exists(ProjectStatsDirectory))
            {
                string DestCookerStats = CmdEnv.LogFolder;
                foreach (var StatsFile in Directory.EnumerateFiles(ProjectStatsDirectory, "*.csv"))
                {
                    if (!CommandUtils.CopyFile_NoExceptions(StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile))))
                    {
                        CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile)));
                    }
                }
            }
//			else
//			{
//				CommandUtils.LogWarning("Failed to find directory {0} will not save stats", ProjectStatsDirectory);
//			}

            // Whether it was copied correctly or not, delete the local log as it was only a temporary file.
            CommandUtils.DeleteFile_NoExceptions(LocalLogFile);

            // Throw an exception if the execution failed. Draw attention to signal exit codes on Posix systems, rather than just printing the exit code
            if (RunResult.ExitCode != 0)
            {
                string ExitCodeDesc = "";
                if (RunResult.ExitCode > 128 && RunResult.ExitCode < 128 + 32)
                {
                    if (RunResult.ExitCode == 139)
                    {
                        ExitCodeDesc = " (segmentation fault)";
                    }
                    else
                    {
                        ExitCodeDesc = String.Format(" (signal {0})", RunResult.ExitCode - 128);
                    }
                }
                throw new CommandletException(DestLogFile, RunResult.ExitCode, "Editor terminated with exit code {0}{1} while running {2}{3}; see log {4}", RunResult.ExitCode, ExitCodeDesc, Commandlet, (ProjectName == null)? "" : String.Format(" for {0}", ProjectName), DestLogFile)
                      {
                          OutputFormat = AutomationExceptionOutputFormat.Minimal
                      };
            }
        }
    public static void CopySharedCookedBuildForTarget(string ProjectFullPath, UnrealTargetPlatform TargetPlatform, string CookPlatform, bool bOnlyCopyAssetRegistry = false)
    {
        var LocalPath = CommandUtils.CombinePaths(Path.GetDirectoryName(ProjectFullPath), "Saved", "SharedIterativeBuild", CookPlatform);

        FileReference ProjectFileRef = new FileReference(ProjectFullPath);
        // get network location
        ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFileRef), TargetPlatform);
        List <string>   CookedBuildPaths;

        if (Hierarchy.GetArray("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPaths) == false)
        {
            CommandUtils.Log("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings");
            return;
        }
        foreach (var CookedBuildPath in CookedBuildPaths)
        {
            if (CopySharedCookedBuildForTargetInternal(CookedBuildPath, CookPlatform, LocalPath, bOnlyCopyAssetRegistry) == true)
            {
                return;
            }
        }

        return;
    }
Exemplo n.º 10
0
    public Noesis(ReadOnlyTargetRules Target) : base(Target)
    {
        Type = ModuleType.External;

        string NoesisBasePath    = ModuleDirectory + "/NoesisSDK/";
        string NoesisIncludePath = NoesisBasePath + "Include/";

        PublicIncludePaths.Add(ModuleDirectory);
        PublicIncludePaths.Add(NoesisIncludePath);

        // Let's try to make sure the right version of the SDK is in the right place.
        const string RequiredRevision    = "(r6972)";
        const string RequiredVersionName = "2.1.0f1";

        if (!Directory.Exists(NoesisBasePath))
        {
            throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName);
        }

        if (!Directory.Exists(NoesisBasePath + "Bin"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Bin directory in " + NoesisBasePath + "Bin. Minimum required version is " + RequiredVersionName);
        }

        if (!Directory.Exists(NoesisBasePath + "Include"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include. Minimum required version is " + RequiredVersionName);
        }

        if (!Directory.Exists(NoesisBasePath + "Lib"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Lib directory in " + NoesisBasePath + "Lib. Minimum required version is " + RequiredVersionName);
        }

        string NoesisSdkVersionInfo;

        try
        {
            NoesisSdkVersionInfo = File.ReadAllText(NoesisBasePath + "version.txt");
        }
        catch (Exception)
        {
            throw new BuildException("Could not find NoesisGUI SDK version.txt in " + NoesisBasePath + "version.txt. Minimum required version is " + RequiredVersionName);
        }

        string[] SplitVersion = NoesisSdkVersionInfo.Split(' ');
        if (String.Compare(SplitVersion[SplitVersion.Length - 1], RequiredRevision) < 0)
        {
            throw new BuildException("Wrong version of the NoesisGUI SDK installed in " + NoesisBasePath + ". Minimum required version is " + RequiredVersionName);
        }

        PublicSystemIncludePaths.Add(NoesisIncludePath);

        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            string NoesisLibPath = NoesisBasePath + "Lib/windows_x86_64/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis.lib");

            string BaseTargetPath = "";
            if (Target.LinkType == TargetLinkType.Monolithic)
            {
                if (Target.ProjectFile != null)
                {
                    BaseTargetPath = DirectoryReference.FromFile(Target.ProjectFile).ToString();
                }
            }
            else
            {
                BaseTargetPath = Target.RelativeEnginePath;
            }

            string NoesisDllPath       = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll";
            string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll";

            if (Target.LinkType == TargetLinkType.Monolithic)
            {
                RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath);
            }
            else
            {
                RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath);
            }

            if (BaseTargetPath != "")
            {
                try
                {
                    if (!System.IO.Directory.Exists(BaseTargetPath + "/Binaries/Win64"))
                    {
                        System.IO.Directory.CreateDirectory(BaseTargetPath + "/Binaries/Win64");
                    }
                    System.IO.File.Copy(ModuleDirectory + NoesisDllPath, BaseTargetPath + NoesisDllTargetPath, true);
                }
                catch (IOException Exception)
                {
                    if (Exception.HResult != -2147024864)                     // 0x80070020: The process cannot access the file ... because it is being used by another process.
                    {
                        throw;
                    }
                }
            }
        }
        else if (Target.Platform == UnrealTargetPlatform.Mac)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/osx/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.dylib");

            string NoesisDylibPath = "/NoesisSDK/Bin/osx/Noesis.dylib";
            RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath);
        }
        else if (Target.Platform == UnrealTargetPlatform.IOS)
        {
            string NoesisLibPath = NoesisBasePath + "Lib/ios/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis");

            PublicAdditionalShadowFiles.Add(Path.Combine(NoesisLibPath, "libNoesis.a"));
        }
        else if (Target.Platform == UnrealTargetPlatform.Android)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/android_arm/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis");

            string NoesisAplPath = "/Noesis_APL.xml";
            AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath);
        }
        else if (Target.Platform == UnrealTargetPlatform.PS4)
        {
            string NoesisLibPath = NoesisBasePath + "Lib/ps4/";
            PublicAdditionalLibraries.Add(NoesisLibPath + "Noesis.a");
        }
        else if (Target.Platform == UnrealTargetPlatform.XboxOne)
        {
            string NoesisLibPath = NoesisBasePath + "Bin/xbox_one/";
            PublicLibraryPaths.Add(NoesisLibPath);
            PublicAdditionalLibraries.Add("Noesis.lib");
        }
    }
Exemplo n.º 11
0
    static void CopySharedCookedBuildForTarget(ProjectParams Params, TargetPlatformDescriptor TargetPlatform, string CookPlatform)
    {
        string ProjectPath = Params.RawProjectPath.FullName;
        var    LocalPath   = CombinePaths(GetDirectoryName(ProjectPath), "Saved", "SharedIterativeBuild", CookPlatform);

        // get network location
        ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), TargetPlatform.Type);
        string          CookedBuildPath;

        if (Hierarchy.GetString("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPath) == false)
        {
            Log("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings");
            return;
        }

        string BuildRoot = P4Enabled ? P4Env.BuildRootP4.Replace("/", "+") : "";
        int    RecentCL  = P4Enabled ? P4Env.Changelist : 0;

        BuildVersion Version;

        if (BuildVersion.TryRead(out Version))
        {
            RecentCL  = Version.Changelist;
            BuildRoot = Version.BranchName;
        }

        // check to see if we have already synced this build ;)
        var    SyncedBuildFile = CombinePaths(LocalPath, "SyncedBuild.txt");
        string BuildCL         = "Invalid";

        if (File.Exists(SyncedBuildFile))
        {
            BuildCL = File.ReadAllText(SyncedBuildFile);
        }

        if (RecentCL == 0 && CookedBuildPath.Contains("[CL]"))
        {
            Log("Unable to copy shared cooked build: Unable to determine CL number from P4 or UGS, and is required by SharedCookedBuildPath");
            return;
        }

        if (RecentCL == 0 && CookedBuildPath.Contains("[BRANCHNAME]"))
        {
            Log("Unable to copy shared cooked build: Unable to determine BRANCHNAME number from P4 or UGS, and is required by SharedCookedBuildPath");
            return;
        }


        CookedBuildPath = CookedBuildPath.Replace("[CL]", RecentCL.ToString());
        CookedBuildPath = CookedBuildPath.Replace("[BRANCHNAME]", BuildRoot);
        CookedBuildPath = CookedBuildPath.Replace("[PLATFORM]", CookPlatform);

        if (Directory.Exists(CookedBuildPath) == false)
        {
            Log("Unable to copy shared cooked build: Unable to find shared build at location {0} check SharedCookedBuildPath in Engine.ini SharedCookedBuildSettings is correct", CookedBuildPath);
            return;
        }

        Log("Attempting download of latest shared build CL {0} from location {1}", RecentCL, CookedBuildPath);

        if (BuildCL == RecentCL.ToString())
        {
            Log("Already downloaded latest shared build at CL {0}", RecentCL);
            return;
        }
        // delete all the stuff
        Log("Deleting previous shared build because it was out of date");
        CommandUtils.DeleteDirectory(LocalPath);
        Directory.CreateDirectory(LocalPath);


        // find all the files in the staged directory
        string CookedBuildStagedDirectory = Path.GetFullPath(Path.Combine(CookedBuildPath, "Staged"));
        string LocalBuildStagedDirectory  = Path.GetFullPath(Path.Combine(LocalPath, "Staged"));

        if (Directory.Exists(CookedBuildStagedDirectory))
        {
            foreach (string FileName in Directory.EnumerateFiles(CookedBuildStagedDirectory, "*.*", SearchOption.AllDirectories))
            {
                string SourceFileName = Path.GetFullPath(FileName);
                string DestFileName   = SourceFileName.Replace(CookedBuildStagedDirectory, LocalBuildStagedDirectory);
                Directory.CreateDirectory(Path.GetDirectoryName(DestFileName));
                File.Copy(SourceFileName, DestFileName);
            }
        }


        string CookedBuildCookedDirectory = Path.Combine(CookedBuildPath, "Cooked");

        CookedBuildCookedDirectory = Path.GetFullPath(CookedBuildCookedDirectory);
        string LocalBuildCookedDirectory = Path.Combine(LocalPath, "Cooked");

        LocalBuildCookedDirectory = Path.GetFullPath(LocalBuildCookedDirectory);
        if (Directory.Exists(CookedBuildCookedDirectory))
        {
            foreach (string FileName in Directory.EnumerateFiles(CookedBuildCookedDirectory, "*.*", SearchOption.AllDirectories))
            {
                string SourceFileName = Path.GetFullPath(FileName);
                string DestFileName   = SourceFileName.Replace(CookedBuildCookedDirectory, LocalBuildCookedDirectory);
                Directory.CreateDirectory(Path.GetDirectoryName(DestFileName));
                File.Copy(SourceFileName, DestFileName);
            }
        }
        File.WriteAllText(SyncedBuildFile, RecentCL.ToString());
        return;
    }
Exemplo n.º 12
0
        public PrFirebase(ReadOnlyTargetRules Target) : base(Target)
        {
            PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

            ConfigHierarchy EngineConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), Target.Platform);

            bool bFirebaseLoggingInShipping = false;

            EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseLoggingInShipping", out bFirebaseLoggingInShipping);

            bool bFirebaseEnable             = false;
            bool bFirebaseCrashlyticsEnable  = false;
            bool bFirebaseRemoteConfigEnable = false;
            bool bFirebaseAuthEnable         = false;
            bool bFirebasePerformanceEnable  = false;

            EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseEnable", out bFirebaseEnable);
            EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseCrashlyticsEnable", out bFirebaseCrashlyticsEnable);
            EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseRemoteConfigEnable", out bFirebaseRemoteConfigEnable);
            EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebaseAuthEnable", out bFirebaseAuthEnable);
            EngineConfig.TryGetValue("/Script/PrFirebase.PrFirebaseSettings", "bFirebasePerformanceEnable", out bFirebasePerformanceEnable);

            PrivateIncludePaths.AddRange(
                new string[] {
                "PrFirebase/Private"
            });

            PublicDependencyModuleNames.AddRange(
                new string[] {
                "Core",
                "CoreUObject",
                "Engine"
            });

            PrivateIncludePathModuleNames.AddRange(
                new string[] {
                "Settings",
            }
                );

            bool bSymbolsWarning = false;

            if (bFirebaseEnable)
            {
                if (Target.Platform == UnrealTargetPlatform.IOS)
                {
                    bool bGeneratedSYMBundle = false;
                    bool bGeneratedSYMFile   = false;
                    EngineConfig.TryGetValue("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMBundle", out bGeneratedSYMBundle);
                    EngineConfig.TryGetValue("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bGeneratedSYMFile", out bGeneratedSYMFile);

                    if ((!bGeneratedSYMBundle || !bGeneratedSYMFile) && bFirebaseCrashlyticsEnable)
                    {
                        bSymbolsWarning = true;
                    }

                    /* Firebase / Firebase Analytics */
                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "FIRAnalyticsConnector",
                            "../../ThirdParty/iOS/FIRAnalyticsConnector.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "FirebaseAnalytics",
                            "../../ThirdParty/iOS/FirebaseAnalytics.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "FirebaseCore",
                            "../../ThirdParty/iOS/FirebaseCore.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "FirebaseCoreDiagnostics",
                            "../../ThirdParty/iOS/FirebaseCoreDiagnostics.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "FirebaseInstallations",
                            "../../ThirdParty/iOS/FirebaseInstallations.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "GoogleAppMeasurement",
                            "../../ThirdParty/iOS/GoogleAppMeasurement.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "GoogleDataTransport",
                            "../../ThirdParty/iOS/GoogleDataTransport.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "GoogleUtilities",
                            "../../ThirdParty/iOS/GoogleUtilities.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "nanopb",
                            "../../ThirdParty/iOS/nanopb.embeddedframework.zip"
                            )
                        );

                    PublicAdditionalFrameworks.Add(
                        new Framework(
                            "PromisesObjC",
                            "../../ThirdParty/iOS/PromisesObjC.embeddedframework.zip"
                            )
                        );

                    /* Crashlytics */
                    if (bFirebaseCrashlyticsEnable)
                    {
                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebaseCrashlytics",
                                "../../ThirdParty/iOS/FirebaseCrashlytics.embeddedframework.zip"
                                )
                            );
                    }

                    /* Remote Config */
                    if (bFirebaseRemoteConfigEnable)
                    {
                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebaseABTesting",
                                "../../ThirdParty/iOS/FirebaseABTesting.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebaseRemoteConfig",
                                "../../ThirdParty/iOS/FirebaseRemoteConfig.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "Protobuf",
                                "../../ThirdParty/iOS/Protobuf.embeddedframework.zip"
                                )
                            );
                    }

                    /* Performance */
                    if (bFirebasePerformanceEnable)
                    {
                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebaseABTesting",
                                "../../ThirdParty/iOS/FirebaseABTesting.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebasePerformance",
                                "../../ThirdParty/iOS/FirebasePerformance.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebaseRemoteConfig",
                                "../../ThirdParty/iOS/FirebaseRemoteConfig.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "GoogleToolboxForMac",
                                "../../ThirdParty/iOS/GoogleToolboxForMac.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "GTMSessionFetcher",
                                "../../ThirdParty/iOS/GTMSessionFetcher.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "Protobuf",
                                "../../ThirdParty/iOS/Protobuf.embeddedframework.zip"
                                )
                            );
                    }

                    /* Auth */
                    if (bFirebaseAuthEnable)
                    {
                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "FirebaseAuth",
                                "../../ThirdParty/iOS/FirebaseAuth.embeddedframework.zip"
                                )
                            );

                        PublicAdditionalFrameworks.Add(
                            new Framework(
                                "GTMSessionFetcher",
                                "../../ThirdParty/iOS/GTMSessionFetcher.embeddedframework.zip"
                                )
                            );
                    }

                    PublicSystemLibraries.Add("sqlite3");

                    PrivateIncludePaths.Add("PrFirebase/External/iOS");

                    string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
                    AdditionalPropertiesForReceipt.Add("IOSPlugin", Path.Combine(PluginPath, "PrFirebase_UPL_IOS.xml"));
                }
                else if (Target.Platform == UnrealTargetPlatform.Android)
                {
                    PublicDependencyModuleNames.AddRange(
                        new string[]
                    {
                        "Launch"
                    });

                    string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
                    AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(PluginPath, "PrFirebase_UPL_Android.xml"));
                }
                else
                {
                    bFirebaseEnable = false;
                }
            }

            PublicDefinitions.Add("WITH_FIREBASE=" + (bFirebaseEnable ? "1" : "0"));
            PublicDefinitions.Add("WITH_FIREBASE_CRASHLYTICS=" + (bFirebaseEnable && bFirebaseCrashlyticsEnable ? "1" : "0"));
            PublicDefinitions.Add("WITH_FIREBASE_REMOTECONFIG=" + (bFirebaseEnable && bFirebaseRemoteConfigEnable ? "1" : "0"));
            PublicDefinitions.Add("WITH_FIREBASE_AUTH=" + (bFirebaseEnable && bFirebaseAuthEnable ? "1" : "0"));
            PublicDefinitions.Add("WITH_FIREBASE_PERFORMANCE=" + (bFirebaseEnable && bFirebasePerformanceEnable ? "1" : "0"));
            PublicDefinitions.Add("WITH_FIREBASE_SYMBOLS_WARNING=" + (bFirebaseEnable && bSymbolsWarning ? "1" : "0"));

            PublicDefinitions.Add("FIREBASE_LOGGING=" + (bFirebaseLoggingInShipping ? "1" : "0"));
        }
Exemplo n.º 13
0
    private static bool FindBestSharedCookedBuild(ref string FinalCookedBuildPath, string ProjectFullPath, UnrealTargetPlatform TargetPlatform, string CookPlatform, string SharedCookedBuildCL)
    {
        string BuildRoot    = CommandUtils.P4Enabled ? CommandUtils.P4Env.Branch.Replace("/", "+") : "";
        int    CurrentCLInt = CommandUtils.P4Enabled ? CommandUtils.P4Env.Changelist : 0;

        BuildVersion Version;

        if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version))
        {
            CurrentCLInt = Version.Changelist;
            BuildRoot    = Version.BranchName;
        }
        System.GC.Collect();
        string CurrentCL = CurrentCLInt.ToString();


        FileReference ProjectFileRef = new FileReference(ProjectFullPath);
        // get network location
        ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFileRef), TargetPlatform);
        List <string>   CookedBuildPaths;

        if (Hierarchy.GetArray("SharedCookedBuildSettings", "SharedCookedBuildPath", out CookedBuildPaths) == false)
        {
            CommandUtils.LogInformation("Unable to copy shared cooked build: SharedCookedBuildPath not set in Engine.ini SharedCookedBuildSettings");
            return(false);
        }

        const string MetaDataFilename = "\\Metadata\\DevelopmentAssetRegistry.bin";


        if (SharedCookedBuildCL == "usesyncedbuild")
        {
            foreach (string CookedBuildPath in CookedBuildPaths)
            {
                if (CurrentCL == "" && FinalCookedBuildPath.Contains("[CL]"))
                {
                    CommandUtils.LogInformation("Unable to copy shared cooked build: Unable to determine CL number from P4 or UGS, and is required by SharedCookedBuildPath");
                    return(false);
                }

                if (CurrentCL == "" && FinalCookedBuildPath.Contains("[BRANCHNAME]"))
                {
                    CommandUtils.LogInformation("Unable to copy shared cooked build: Unable to determine BRANCHNAME number from P4 or UGS, and is required by SharedCookedBuildPath");
                    return(false);
                }


                FinalCookedBuildPath = FinalCookedBuildPath.Replace("[CL]", CurrentCL.ToString());
                FinalCookedBuildPath = FinalCookedBuildPath.Replace("[BRANCHNAME]", BuildRoot);
                FinalCookedBuildPath = FinalCookedBuildPath.Replace("[PLATFORM]", CookPlatform);

                // make sure that the directory and metadata file exist.  otherwise this build might not be finished yet and we should skip it
                if (Directory.Exists(FinalCookedBuildPath))
                {
                    if (File.Exists(FinalCookedBuildPath + MetaDataFilename))
                    {
                        return(true);
                    }
                }
            }
        }
        else if (SharedCookedBuildCL == "userecentbuild")
        {
            // build our CookedBUildPath into a regex which we can execute on the directories and extract info from



            string BestBuild    = null;
            int    BestCLNumber = 0;

            // find all the recent builds which are valid
            foreach (string CookedBuildPath in CookedBuildPaths)
            {
                int IndexOfFirstParam = CookedBuildPath.IndexOf("[");
                int CustomFolderStart = CookedBuildPath.LastIndexOf("\\", IndexOfFirstParam);

                string CookedBuildDirectory = CookedBuildPath.Substring(0, CustomFolderStart);

                string BuildNameWildcard = CookedBuildPath.Substring(CustomFolderStart);


                BuildNameWildcard += MetaDataFilename;

                FileFilter BuildSearch = new FileFilter();

                // we know the platform and the branch name;
                string BuildRule = BuildNameWildcard;
                BuildRule = BuildRule.Replace("[BRANCHNAME]", BuildRoot);
                BuildRule = BuildRule.Replace("[PLATFORM]", CookPlatform);

                string IncludeRule = BuildRule.Replace("[CL]", "*");
                string ForgetRule  = BuildRule.Replace("[CL]", "*-PF-*");                // get rid of any preflights from the list... they don't count because who knows what they did...

                BuildSearch.AddRule(IncludeRule);
                BuildSearch.AddRule(ForgetRule, FileFilterType.Exclude);

                List <FileReference> ValidBuilds = BuildSearch.ApplyToDirectory(new DirectoryReference(CookedBuildDirectory), false);

                // figure out what the CL is
                string BuildNameRegex = String.Format(".*{0}", CookedBuildPath.Substring(CustomFolderStart));
                BuildNameRegex = BuildNameRegex.Replace("\\", "\\\\");
                BuildNameRegex = BuildNameRegex.Replace("[BRANCHNAME]", BuildRoot);
                BuildNameRegex = BuildNameRegex.Replace("+", "\\+");
                BuildNameRegex = BuildNameRegex.Replace("[PLATFORM]", CookPlatform);
                BuildNameRegex = BuildNameRegex.Replace("[CL]", "(?<CL>.*)");

                Regex ExtractCL = new Regex(BuildNameRegex);

                foreach (FileReference ValidBuild in ValidBuilds)
                {
                    string BuildPath = ValidBuild.FullName.Replace(MetaDataFilename, "");

                    Match CLMatch = ExtractCL.Match(BuildPath);
                    if (CLMatch != null)
                    {
                        string CLNumber    = CLMatch.Result("${CL}");
                        int    CLNumberInt = int.Parse(CLNumber);
                        if (CLNumberInt <= CurrentCLInt)
                        {
                            if (CLNumberInt > BestCLNumber)
                            {
                                BestCLNumber = CLNumberInt;
                                BestBuild    = BuildPath;
                            }
                        }
                    }
                }
            }

            if (string.IsNullOrEmpty(BestBuild))
            {
                return(false);
            }

            FinalCookedBuildPath = BestBuild;
            return(true);
        }


        return(false);
    }
Exemplo n.º 14
0
    public Noesis(ReadOnlyTargetRules Target) : base(Target)
    {
        Type = ModuleType.External;

        string NoesisBasePath    = ModuleDirectory + "/NoesisSDK/";
        string NoesisIncludePath = NoesisBasePath + "Include/";
        string NoesisInteractivityIncludePath = NoesisBasePath + "Src/Packages/App/Interactivity/Include/";

        PublicIncludePaths.Add(ModuleDirectory);
        PublicIncludePaths.Add(NoesisIncludePath);
        PublicIncludePaths.Add(NoesisInteractivityIncludePath);

        if (!Directory.Exists(NoesisBasePath))
        {
            throw new BuildException("Could not find NoesisGUI SDK in " + NoesisBasePath + ".");
        }

        if (!Directory.Exists(NoesisBasePath + "Include"))
        {
            throw new BuildException("Could not find NoesisGUI SDK Include directory in " + NoesisBasePath + "Include.");
        }

        PublicSystemIncludePaths.Add(NoesisIncludePath);

        UnrealTargetPlatform Platform;

        if (Target.Platform == UnrealTargetPlatform.Win64)
        {
            PublicAdditionalLibraries.Add(NoesisBasePath + "Lib/windows_x86_64/Noesis.lib");

            string NoesisDllPath       = "/NoesisSDK/Bin/windows_x86_64/Noesis.dll";
            string NoesisDllTargetPath = "/Binaries/Win64/Noesis.dll";

            if (Target.ProjectFile != null)
            {
                System.Console.WriteLine("Copying Noesis.dll to {0}", DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath);
                CopyNoesisDll(ModuleDirectory + NoesisDllPath, DirectoryReference.FromFile(Target.ProjectFile).ToString() + NoesisDllTargetPath);
            }

            System.Console.WriteLine("Copying Noesis.dll to {0}", System.IO.Path.GetFullPath(ModuleDirectory + "/../.." + NoesisDllTargetPath));
            CopyNoesisDll(ModuleDirectory + NoesisDllPath, ModuleDirectory + "/../.." + NoesisDllTargetPath);

            if (System.IO.File.Exists(Target.RelativeEnginePath + NoesisDllTargetPath))
            {
                System.IO.File.Delete(Target.RelativeEnginePath + NoesisDllTargetPath);
            }

            if (Target.LinkType == TargetLinkType.Monolithic)
            {
                RuntimeDependencies.Add("$(ProjectDir)" + NoesisDllTargetPath);
            }
            else
            {
                RuntimeDependencies.Add("$(EngineDir)" + NoesisDllTargetPath);
            }
        }
        else if (Target.Platform == UnrealTargetPlatform.Linux)
        {
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/linunx_x86_64/libNoesis.so");
        }
        else if (Target.Platform == UnrealTargetPlatform.Mac)
        {
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/macos/Noesis.dylib");

            string NoesisDylibPath = "/NoesisSDK/Bin/macos/Noesis.dylib";
            RuntimeDependencies.Add(ModuleDirectory + NoesisDylibPath);
        }
        else if (Target.Platform == UnrealTargetPlatform.IOS)
        {
            PublicDefinitions.Add("NS_STATIC_LIBRARY");
            PublicAdditionalLibraries.Add(NoesisBasePath + "Lib/ios/libNoesis.a");

            PublicFrameworks.Add("CoreText");
        }
        else if (Target.Platform == UnrealTargetPlatform.Android)
        {
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_arm/libNoesis.so");
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_arm64/libNoesis.so");
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_x86/libNoesis.so");
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/android_x86_64/libNoesis.so");

            string NoesisAplPath = "/Noesis_APL.xml";
            AdditionalPropertiesForReceipt.Add("AndroidPlugin", ModuleDirectory + NoesisAplPath);
        }
        else if (Target.Platform == UnrealTargetPlatform.PS4)
        {
            PublicDefinitions.Add("NS_STATIC_LIBRARY");
            PublicAdditionalLibraries.Add(NoesisBasePath + "Lib/ps4/Noesis.a");
        }
        else if (Target.Platform == UnrealTargetPlatform.XboxOne)
        {
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/xbox_one/Noesis.lib");
        }
        else if (UnrealTargetPlatform.TryParse("HTML5", out Platform) && Target.Platform == Platform)
        {
            PublicAdditionalLibraries.Add(NoesisBasePath + "Bin/wasm/Noesis.bc");
        }
    }
Exemplo n.º 15
0
    public override IProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params)
    {
        // look for browser
        string BrowserPath = Params.Devices[0].Replace("HTML5@", "");

        // open the webpage
        Int32 ServerPort = 8000;         // HTML5LaunchHelper default

        var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5);

        ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort);         // LaunchOn via Editor or FrontEnd
        string WorkingDirectory = Path.GetDirectoryName(ClientApp);
        string url = Path.GetFileName(ClientApp) + ".html";

        // WARNING: splitting the following situation
        // if cookonthefly is used: tell the browser to use the PROXY at DEFAULT_HTTP_FILE_SERVING_PORT
        // leave the normal HTML5LaunchHelper port (ServerPort) alone -- otherwise it will collide with the PROXY port
        if (ClientCmdLine.Contains("filehostip"))
        {
            url += "?cookonthefly=true";
            Int32 ProxyPort = 41898;             // DEFAULT_HTTP_FILE_SERVING_PORT
            url = String.Format("http://localhost:{0}/{1}", ProxyPort, url);
        }
        else
        {
            url = String.Format("http://localhost:{0}/{1}", ServerPort, url);
        }

        // Check HTML5LaunchHelper source for command line args

        var LowerBrowserPath = BrowserPath.ToLower();
        var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory().FullName, "UE4_HTML5", "user");

        string BrowserCommandline = url;

        if (LowerBrowserPath.Contains("chrome"))
        {
            ProfileDirectory = Path.Combine(ProfileDirectory, "chrome");
            // removing [--enable-logging] otherwise, chrome breaks with a bunch of the following errors:
            // > ERROR:process_info.cc(631)] range at 0x7848406c00000000, size 0x1a4 fully unreadable
            // leaving this note here for future reference: UE-45078
            BrowserCommandline += "  " + String.Format("--user-data-dir=\\\"{0}\\\"   --no-first-run", ProfileDirectory);
        }
        else if (LowerBrowserPath.Contains("firefox"))
        {
            ProfileDirectory    = Path.Combine(ProfileDirectory, "firefox");
            BrowserCommandline += "  " + String.Format("-no-remote -profile \\\"{0}\\\"", ProfileDirectory);
        }

        if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux)
        {
            // TODO: test on other platforms to remove this if() check
            if (!Directory.Exists(ProfileDirectory))
            {
                Directory.CreateDirectory(ProfileDirectory);
            }
        }

        string LauncherArguments = string.Format(" -Browser=\"{0}\" + -BrowserCommandLine=\"{1}\" -ServerPort=\"{2}\" -ServerRoot=\"{3}\" ",
                                                 new object[] { BrowserPath, BrowserCommandline, ServerPort, WorkingDirectory });

        var            LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe");
        IProcessResult BrowserProcess   = Run(LaunchHelperPath, LauncherArguments, null, ClientRunFlags | ERunOptions.NoWaitForExit);

        return(BrowserProcess);
    }
    public static bool CanCreateMapPaks(ProjectParams Param)
    {
        bool UseAsyncLevelLoading = false;
        var  ConfigCache          = new UnrealBuildTool.ConfigCacheIni(UnrealTargetPlatform.HTML5, "Engine", DirectoryReference.FromFile(Param.RawProjectPath), new DirectoryReference(CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine")));

        ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "UseAsyncLevelLoading", out UseAsyncLevelLoading);

        if (Param.Run)
        {
            return(false);
        }

        return(UseAsyncLevelLoading);
    }
    public override void Package(ProjectParams Params, DeploymentContext SC, int WorkingCL)
    {
        LogInformation("Package {0}", Params.RawProjectPath);

        LogInformation("Setting Emscripten SDK for packaging..");
        HTML5SDKInfo.SetupEmscriptenTemp();
        HTML5SDKInfo.SetUpEmscriptenConfigFile();

        // ----------------------------------------
        // ini configurations
        ConfigHierarchy ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5);

        ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableMultithreading", out enableMultithreading);
        ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "OffscreenCanvas", out bMultithreading_UseOffscreenCanvas);

        // Debug and Development builds are not compressed to:
        // - speed up iteration times
        // - ensure (IndexedDB) data are not cached/used
        // Shipping builds "can be":
        // - compressed
        // - (IndexedDB) cached
        string ProjectConfiguration = Params.ClientConfigsToBuild[0].ToString();

        if (ProjectConfiguration == "Shipping")
        {
            ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "Compressed", out Compressed);
            ConfigCache.GetBool("/Script/HTML5PlatformEditor.HTML5TargetSettings", "EnableIndexedDB", out enableIndexedDB);
        }
        LogInformation("HTML5Platform.Automation: Compressed = " + Compressed);
        LogInformation("HTML5Platform.Automation: EnableIndexedDB = " + enableIndexedDB);
        LogInformation("HTML5Platform.Automation: Multithreading = " + enableMultithreading);
        LogInformation("HTML5Platform.Automation: OffscreenCanvas = " + bMultithreading_UseOffscreenCanvas);

        // ----------------------------------------
        // package directory
        string PackagePath = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Binaries", "HTML5");

        if (!Directory.Exists(PackagePath))
        {
            Directory.CreateDirectory(PackagePath);
        }
        string _ProjectNameExtra  = ProjectConfiguration != "Development" ? "-HTML5-" + ProjectConfiguration : "";
        string _ProjectFullpath   = Params.GetProjectExeForPlatform(UnrealTargetPlatform.HTML5).ToString();
        string _ProjectFilename   = Path.GetFileNameWithoutExtension(_ProjectFullpath) + _ProjectNameExtra;
        string SrcUE4GameBasename = Path.Combine(Path.GetDirectoryName(_ProjectFullpath), _ProjectFilename);
        string UE4GameBasename    = Path.Combine(PackagePath, _ProjectFilename);
        string ProjectBasename    = Path.Combine(PackagePath, Params.ShortProjectName + _ProjectNameExtra);

        if (Params.IsCodeBasedProject && Params.HasClientCookedTargets)
        {
            UE4GameBasename = Params.ClientCookedTargets[0];
        }

        // ----------------------------------------
        // packaging
        if (HTMLPakAutomation.CanCreateMapPaks(Params))
        {
            HTMLPakAutomation PakAutomation = new HTMLPakAutomation(Params, SC);

            // Create Necessary Paks.
            PakAutomation.CreateEnginePak();
            PakAutomation.CreateGamePak();
            PakAutomation.CreateContentDirectoryPak();

            // Create Emscripten Package from Necessary Paks. - This will be the VFS.
            PakAutomation.CreateEmscriptenDataPackage(PackagePath, ProjectBasename + ".data");

            // Create All Map Paks which  will be downloaded on the fly.
            PakAutomation.CreateMapPak();

            // Create Delta Paks if setup.
            List <string> Paks = new List <string>();
            ConfigCache.GetArray("/Script/HTML5PlatformEditor.HTML5TargetSettings", "LevelTransitions", out Paks);

            if (Paks != null)
            {
                foreach (var Pak in Paks)
                {
                    var    Matched = Regex.Matches(Pak, "\"[^\"]+\"", RegexOptions.IgnoreCase);
                    string MapFrom = Path.GetFileNameWithoutExtension(Matched[0].ToString().Replace("\"", ""));
                    string MapTo   = Path.GetFileNameWithoutExtension(Matched[1].ToString().Replace("\"", ""));
                    PakAutomation.CreateDeltaMapPaks(MapFrom, MapTo);
                }
            }
        }
        else
        {
            // we need to operate in the root
            string PythonPath     = HTML5SDKInfo.Python().FullName;
            string EmPackagerPath = HTML5SDKInfo.EmscriptenPackager();

            using (new ScopedEnvVar("EM_CONFIG", HTML5SDKInfo.DOT_EMSCRIPTEN))
            {
                using (new PushedDirectory(Path.Combine(Params.BaseStageDirectory, "HTML5")))
                {
                    string CmdLine = string.Format("\"{0}\" \"{1}\" --preload . --js-output=\"{1}.js\" --no-heap-copy", EmPackagerPath, ProjectBasename + ".data");
                    RunAndLog(CmdEnv, PythonPath, CmdLine);
                }
            }
        }


        // ----------------------------------------
        // copy to package directory

        // ensure the ue4game binary exists, if applicable
        if (!FileExists_NoExceptions(SrcUE4GameBasename + ".js"))
        {
            LogInformation("Failed to find game application " + SrcUE4GameBasename + ".js");
            throw new AutomationException(ExitCode.Error_MissingExecutable, "Stage Failed. Could not find application {0}. You may need to build the UE4 project with your target configuration and platform.", SrcUE4GameBasename + ".js");
        }

        if (!Params.IsCodeBasedProject)
        {
            // template project - need to copy over UE4Game.*
            File.Copy(SrcUE4GameBasename + ".wasm", UE4GameBasename + ".wasm", true);
            File.Copy(SrcUE4GameBasename + ".js", UE4GameBasename + ".js", true);

            File.SetAttributes(UE4GameBasename + ".wasm", FileAttributes.Normal);
            File.SetAttributes(UE4GameBasename + ".js", FileAttributes.Normal);

            if (File.Exists(SrcUE4GameBasename + ".js.symbols"))
            {
                File.Copy(SrcUE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbols", true);
                File.SetAttributes(UE4GameBasename + ".js.symbols", FileAttributes.Normal);
            }

            if (enableMultithreading)
            {
                File.Copy(SrcUE4GameBasename + ".js.mem", UE4GameBasename + ".js.mem", true);
                File.SetAttributes(UE4GameBasename + ".js.mem", FileAttributes.Normal);

                File.Copy(SrcUE4GameBasename + ".worker.js", UE4GameBasename + ".worker.js", true);
                File.SetAttributes(UE4GameBasename + ".worker.js", FileAttributes.Normal);
            }
            else
            {
                // nuke possibly old deployed .worker.js, which is not needed for singlethreaded build.
                File.Delete(UE4GameBasename + ".worker.js");
            }
        }
        // else, c++ projects will compile "to" PackagePath

        // note: ( ProjectBasename + ".data" ) already created above (!HTMLPakAutomation.CanCreateMapPaks())


        // ----------------------------------------
        // generate HTML files to the package directory

        // custom HTML, JS (if any), and CSS (if any) template files
        string LocalBuildPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/HTML5");
        string BuildPath      = Path.Combine(Path.GetDirectoryName(Params.RawProjectPath.FullName), "Build", "HTML5");
        string TemplateFile   = CombinePaths(BuildPath, "project_template.html");

        if (!File.Exists(TemplateFile))
        {
            // fall back to default UE4 template files
            BuildPath    = LocalBuildPath;
            TemplateFile = CombinePaths(BuildPath, "project_template.html");
        }
        GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".html", Params, SC, ConfigCache);

        TemplateFile = CombinePaths(BuildPath, "project_template.js");
        if (File.Exists(TemplateFile))
        {
            GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".UE4.js", Params, SC, ConfigCache);
        }

        TemplateFile = CombinePaths(BuildPath, "project_template.css");
        if (File.Exists(TemplateFile))
        {
            GenerateFileFromTemplate(TemplateFile, ProjectBasename + ".css", Params, SC, ConfigCache);
        }


        // ----------------------------------------
        // (development) support files
        string MacBashTemplateFile = CombinePaths(LocalBuildPath, "RunMacHTML5LaunchHelper_template.command");
        string MacBashOutputFile   = Path.Combine(PackagePath, "RunMacHTML5LaunchHelper.command");
        string MonoPath            = CombinePaths(CmdEnv.LocalRoot, "Engine/Build/BatchFiles/Mac/SetupMono.sh");

        GenerateMacCommandFromTemplate(MacBashTemplateFile, MacBashOutputFile, MonoPath);
        // ........................................
        string htaccesspath = Path.Combine(PackagePath, ".htaccess");

        if (File.Exists(htaccesspath))
        {
            FileAttributes attributes = File.GetAttributes(htaccesspath);
            if ((attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
            {
                attributes &= ~FileAttributes.ReadOnly;
                File.SetAttributes(htaccesspath, attributes);
            }
        }
        File.Copy(CombinePaths(LocalBuildPath, "htaccess_template.txt"), htaccesspath, true);


        // ----------------------------------------
        // final copies

        // Gather utlity .js files and combine into one file
        string DestinationFile = PackagePath + "/Utility.js";

        File.Delete(DestinationFile);
        // spelling this out - one file at a time (i.e. don't slurp in project_template.js)
        File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "json2.js")));
        File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "jstorage.js")));
        File.AppendAllText(DestinationFile, File.ReadAllText(CombinePaths(LocalBuildPath, "moz_binarystring.js")));

        if (Compressed)
        {
            LogInformation("Build configuration is " + ProjectConfiguration + ", so (gzip) compressing files for web servers.");

            // Compress all files. These are independent tasks which can be threaded.
            List <Task> CompressionTasks = new List <Task>();

            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".wasm", UE4GameBasename + ".wasmgz")));                                            // main game code
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js", UE4GameBasename + ".jsgz")));                                                // main js (emscripten)
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(PackagePath + "/Utility.js", PackagePath + "/Utility.jsgz")));                                        // Utility
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data", ProjectBasename + ".datagz")));                                            // DATA file
            CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".data.js", ProjectBasename + ".data.jsgz")));                                      // DATA file .js driver (emscripten)
            if (File.Exists(UE4GameBasename + ".js.symbols"))
            {
                CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js.symbols", UE4GameBasename + ".js.symbolsgz")));                    // symbols fil.
            }
            if (File.Exists(ProjectBasename + ".UE4.js"))
            {
                CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".UE4.js", ProjectBasename + ".UE4.jsgz")));                                    // UE4 js
            }
            if (File.Exists(ProjectBasename + ".css"))
            {
                CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(ProjectBasename + ".css", ProjectBasename + ".cssgz")));                                                  // UE4 css
            }
            if (enableMultithreading)
            {
                CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".js.mem", UE4GameBasename + ".js.memgz")));                                    // mem init file
                CompressionTasks.Add(Task.Factory.StartNew(() => CompressFile(UE4GameBasename + ".worker.js", UE4GameBasename + ".worker.jsgz")));                              // pthread file
            }
            Task.WaitAll(CompressionTasks.ToArray());
        }
        else
        {
            LogInformation("Build configuration is " + ProjectConfiguration + ", so not compressing. Build Shipping configuration to compress files to save space.");

            // nuke old compressed files to prevent using stale files
            File.Delete(UE4GameBasename + ".wasmgz");
            File.Delete(UE4GameBasename + ".jsgz");
            File.Delete(UE4GameBasename + ".js.symbolsgz");
            File.Delete(UE4GameBasename + ".js.memgz");
            File.Delete(UE4GameBasename + ".worker.jsgz");
            File.Delete(PackagePath + "/Utility.jsgz");
            File.Delete(ProjectBasename + ".datagz");
            File.Delete(ProjectBasename + ".data.jsgz");
            File.Delete(ProjectBasename + ".UE4.jsgz");
            File.Delete(ProjectBasename + ".cssgz");
        }

        File.Copy(CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe"), CombinePaths(PackagePath, "HTML5LaunchHelper.exe"), true);
//		Task.WaitAll(CompressionTasks);
        PrintRunTime();
    }
        /**
         * Notify stakeholders of the commandlet results
         */
        void SendCompletionMessage(bool bWasSuccessful, String MessageBody)
        {
            if (StakeholdersEmailAddresses != null)
            {
                MailMessage Message = new System.Net.Mail.MailMessage();
                Message.Priority = MailPriority.High;
                Message.From     = new MailAddress("*****@*****.**");

                string Branch = "Unknown";
                if (P4Enabled)
                {
                    Branch = P4Env.Branch;
                }

                foreach (String NextStakeHolder in StakeholdersEmailAddresses)
                {
                    Message.To.Add(new MailAddress(NextStakeHolder));
                }

                ConfigHierarchy Ini = ConfigCache.ReadHierarchy(ConfigHierarchyType.EditorPerProjectUserSettings, DirectoryReference.FromFile(ProjectFullPath), UnrealTargetPlatform.Win64);
                List <string>   Emails;
                Ini.GetArray("RebuildHLODSettings", "EmailNotification", out Emails);
                foreach (var Email in Emails)
                {
                    Message.CC.Add(new MailAddress(Email));
                }

                Message.Subject = String.Format("Nightly HLOD rebuild {0} for {1}", bWasSuccessful ? "[SUCCESS]" : "[FAILED]", Branch);
                Message.Body    = MessageBody;

                /*Attachment Attach = new Attachment();
                 * Message.Attachments.Add()*/
                try
                {
                                    #pragma warning disable CS0618 // Mono 4.6.x obsoletes this class
                    SmtpClient MailClient = new SmtpClient("smtp.epicgames.net");
                    MailClient.Send(Message);
                                    #pragma warning restore CS0618
                }
                catch (Exception Ex)
                {
                    LogError("Failed to send notify email to {0} ({1})", String.Join(", ", StakeholdersEmailAddresses.ToArray()), Ex.Message);
                }
            }
        }
    // --------------------------------------------------------------------------------
    // RunProjectCommand.Automation.cs

    public override IProcessResult RunClient(ERunOptions ClientRunFlags, string ClientApp, string ClientCmdLine, ProjectParams Params)
    {
        // look for browser
        string BrowserPath = Params.Devices[0].Replace("HTML5@", "");

        // open the webpage
        Int32 ServerPort = 8000;         // HTML5LaunchHelper default

        var ConfigCache = UnrealBuildTool.ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Params.RawProjectPath), UnrealTargetPlatform.HTML5);

        ConfigCache.GetInt32("/Script/HTML5PlatformEditor.HTML5TargetSettings", "DeployServerPort", out ServerPort);         // LaunchOn via Editor or FrontEnd
        string WorkingDirectory = Path.GetDirectoryName(ClientApp);
        string url = Path.GetFileName(ClientApp) + ".html";

// UE-64628: seems proxy port is no longer used anymore -- leaving details here for future reference...
//		// WARNING: splitting the following situation
//		// if cookonthefly is used: tell the browser to use the PROXY at DEFAULT_HTTP_FILE_SERVING_PORT
//		// leave the normal HTML5LaunchHelper port (ServerPort) alone -- otherwise it will collide with the PROXY port
        if (ClientCmdLine.Contains("filehostip"))
        {
            url += "?cookonthefly=true";
//			Int32 ProxyPort = 41898; // DEFAULT_HTTP_FILE_SERVING_PORT
//			url = String.Format("http://localhost:{0}/{1}", ProxyPort, url);
        }
//		else
//		{
        url = String.Format("http://localhost:{0}/{1}", ServerPort, url);
//		}

        // Check HTML5LaunchHelper source for command line args

        var LowerBrowserPath = BrowserPath.ToLower();
        var ProfileDirectory = Path.Combine(Utils.GetUserSettingDirectory().FullName, "UE4_HTML5", "user");

        string BrowserCommandline = url;

        if (LowerBrowserPath.Contains("chrome"))
        {
            ProfileDirectory = Path.Combine(ProfileDirectory, "chrome");
            // removing [--enable-logging] otherwise, chrome breaks with a bunch of the following errors:
            // > ERROR:process_info.cc(631)] range at 0x7848406c00000000, size 0x1a4 fully unreadable
            // leaving this note here for future reference: UE-45078
            BrowserCommandline += "  " + String.Format("--user-data-dir=\\\"{0}\\\"   --no-first-run", ProfileDirectory);
        }
        else if (LowerBrowserPath.Contains("firefox"))
        {
            ProfileDirectory    = Path.Combine(ProfileDirectory, "firefox");
            BrowserCommandline += "  " + String.Format("-no-remote -profile \\\"{0}\\\"", ProfileDirectory);
        }
        else if (LowerBrowserPath.Contains("safari"))
        {
            // NOT SUPPORTED: cannot have a separate UE4 profile for safari
            // -- this "can" be done with a different user (e.g. guest) account...
            //    (which is not a turn key solution that can be done within UE4)
            // -- some have tried using symlinks to "mimic" this
            //    https://discussions.apple.com/thread/3327990
            // -- but, none of these are fool proof with an existing/running safari instance

            // -- also, "Safari Extensions JS" has been officially deprecated as of Safari 12
            //    (in favor of using "Safari App Extension")
            //    https://developer.apple.com/documentation/safariextensions

            // this means, Safari "LaunchOn" (UE4 Editor -> Launch -> Safari) will run with your FULL
            // Safari profile -- so, all of your "previously opened" tabs will all also be opened...
        }

        // TODO: test on other platforms to remove this first if() check
        if (UnrealBuildTool.BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux)
        {
            if (!Directory.Exists(ProfileDirectory))
            {
                Directory.CreateDirectory(ProfileDirectory);
            }
        }

        string LauncherArguments = string.Format(" -Browser=\"{0}\" + -BrowserCommandLine=\"{1}\" -ServerPort=\"{2}\" -ServerRoot=\"{3}\" ",
                                                 new object[] { BrowserPath, BrowserCommandline, ServerPort, WorkingDirectory });

        var            LaunchHelperPath = CombinePaths(CmdEnv.LocalRoot, "Engine/Binaries/DotNET/HTML5LaunchHelper.exe");
        IProcessResult BrowserProcess   = Run(LaunchHelperPath, LauncherArguments, null, ClientRunFlags | ERunOptions.NoWaitForExit);

        return(BrowserProcess);
    }
Exemplo n.º 20
0
    public List <ISharedCookedBuild> FindBestBuilds()
    {
        // Attempt manifest searching first
        ConfigHierarchy Hierarchy = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(ProjectFile), UnrealTargetPlatform.Win64);

        IEnumerable <string> RawSharedCookedSources = null;

        Hierarchy.TryGetValues("SharedCookedBuildSettings", "SharedCookedSources", out RawSharedCookedSources);
        if (RawSharedCookedSources == null)
        {
            throw new AutomationException("Unable to locate shared cooked builds. SharedCookedSources not set in Engine.ini [SharedCookedBuildSettings]");
        }

        List <Dictionary <string, string> > ParsedSharedCookSources = new List <Dictionary <string, string> >();

        foreach (string RawConfig in RawSharedCookedSources)
        {
            Dictionary <string, string> ParsedSource = null;
            if (ConfigHierarchy.TryParse(RawConfig, out ParsedSource))
            {
                ParsedSharedCookSources.Add(ParsedSource);
            }
        }

        List <ISharedCookedBuild> CandidateBuilds = new List <ISharedCookedBuild>();

        // If existing sync is present, stick to it. Read version out of sync file
        foreach (string Platform in TargetPlatforms)
        {
            FileReference SyncedBuildFile = new FileReference(CommandUtils.CombinePaths(InstallPath.FullName, Platform, SyncedBuildFileName));
            if (FileReference.Exists(SyncedBuildFile))
            {
                string[] SyncedBuildInfo = FileReference.ReadAllLines(SyncedBuildFile);
                int      SyncedCL        = int.Parse(SyncedBuildInfo[0]);
                if (IsValidCL(SyncedCL, BuildType, LocalSync))
                {
                    CandidateBuilds.Add(new ExistingSharedCookedBuild()
                    {
                        CL = SyncedCL, Platform = Platform
                    });
                }
            }
        }

        foreach (Dictionary <string, string> Source in ParsedSharedCookSources)
        {
            SharedCookSource SourceType = (SharedCookSource)Enum.Parse(typeof(SharedCookSource), Source["Type"], true);
            foreach (string Platform in TargetPlatforms)
            {
                if (SourceType == SharedCookSource.Manifest)
                {
                    CandidateBuilds.AddRange(FindValidManifestBuilds(Source["Path"], Platform));
                }
                else if (SourceType == SharedCookSource.LooseFiles)
                {
                    CandidateBuilds.AddRange(FindValidLooseBuilds(Source["Path"], Platform));
                }
            }
        }

        // Strip all failed searches
        CandidateBuilds.RemoveAll(x => x == null);

        // Make sure we have a matching CL for all target platforms, regardless of source
        List <int> OrderedDistinctCLs = CandidateBuilds.Select(x => x.CL).Distinct().OrderByDescending(i => i).ToList();
        int        BestCL             = -1;

        foreach (int CL in OrderedDistinctCLs)
        {
            // Ensure we have a platform for each
            HashSet <string> CLPlatforms = new HashSet <string>(CandidateBuilds.Where(x => x.CL == CL).Select(x => x.Platform).ToList());
            if (CLPlatforms.SetEquals(TargetPlatforms))
            {
                BestCL = CL;
                break;
            }
        }

        if (BestCL < 0)
        {
            CommandUtils.LogError("Could not locate valid shared cooked build for all target platforms");
            CommandUtils.LogError("Current CL: {0}, Current Code CL: {1}", LocalSync.Changelist, LocalSync.CompatibleChangelist);
        }

        return(CandidateBuilds.Where(x => x.CL == BestCL).ToList());
    }
    public OnlineSubsystemApple(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

        if (Target.Platform == UnrealTargetPlatform.IOS || Target.Platform == UnrealTargetPlatform.TVOS)
        {
            ConfigHierarchy PlatformGameConfig = ConfigCache.ReadHierarchy(ConfigHierarchyType.Engine, DirectoryReference.FromFile(Target.ProjectFile), UnrealTargetPlatform.IOS);
            PlatformGameConfig.GetBool("/Script/IOSRuntimeSettings.IOSRuntimeSettings", "bEnableSignInWithAppleSupport", out bSignInWithAppleSupported);
        }
        else if (Target.Platform == UnrealTargetPlatform.Mac)
        {
            // TODO: Mark.Fitt enable Mac support
        }

        PrivateIncludePaths.Add("Private");

        PublicDefinitions.Add("ONLINESUBSYSTEMAPPLE_PACKAGE=1");
        PublicDefinitions.Add("ONLINESUBSYSTEMAPPLE_IDENTITY_ENABLE_SIWA=" + (bSignInWithAppleSupported ? "1" : "0"));

        PrivateDependencyModuleNames.AddRange(
            new string[] {
            "Core",
            "CoreUObject",
            "Engine",
            "OnlineSubsystem",
        });

        if (Target.Platform == UnrealTargetPlatform.Mac || Target.Platform == UnrealTargetPlatform.IOS || Target.Platform == UnrealTargetPlatform.TVOS)
        {
            if (bSignInWithAppleSupported)
            {
                PublicWeakFrameworks.Add("AuthenticationServices");
            }
        }
    }