// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.IO; using Tools.DotNETCommon; namespace UnrealBuildTool { /// /// HTML5-specific target settings /// public class HTML5TargetRules { /// /// Constructor /// public HTML5TargetRules() { XmlConfig.ApplyTo(this); } /// /// Use LLVM Wasm backend /// public string libExt = HTML5ToolChain.libExt; } /// /// Read-only wrapper for HTML5-specific target settings /// public class ReadOnlyHTML5TargetRules { /// /// The private mutable settings object /// private HTML5TargetRules Inner; /// /// Constructor /// /// The settings object to wrap public ReadOnlyHTML5TargetRules(HTML5TargetRules Inner) { this.Inner = Inner; } /// /// Accessors for fields on the inner TargetRules instance /// #region Read-only accessor properties #if !__MonoCS__ #pragma warning disable CS1591 #endif public string libExt { get { return Inner.libExt; } } #if !__MonoCS__ #pragma warning restore CS1591 #endif #endregion } class HTML5Platform : UEBuildPlatform { /// /// Architecture to build for. /// [XmlConfigFile] public static string HTML5Architecture = ""; HTML5PlatformSDK SDK; public HTML5Platform(HTML5PlatformSDK InSDK) : base(UnrealTargetPlatform.HTML5) { SDK = InSDK; } /// /// Whether the required external SDKs are installed for this platform. Could be either a manual install or an AutoSDK. /// public override SDKStatus HasRequiredSDKsInstalled() { return SDK.HasRequiredSDKsInstalled(); } // The current architecture - affects everything about how UBT operates on HTML5 public override string GetDefaultArchitecture(FileReference ProjectFile) { // by default, use an empty architecture (which is really just a modifier to the platform for some paths/names) return HTML5Platform.HTML5Architecture; } public override void ResetTarget(TargetRules Target) { ValidateTarget(Target); } public override void ValidateTarget(TargetRules Target) { Target.bCompileAPEX = false; Target.bCompileNvCloth = false; Target.bCompilePhysX = true; Target.bCompileForSize = false; // {true:[all:-Oz], false:[developer:-O2, shipping:-O3]} WARNING: need emscripten version >= 1.37.13 Target.bUsePCHFiles = false; Target.bDeployAfterCompile = true; } public override bool CanUseXGE() { return false; // NOTE: setting to true may break CIS builds... } /// /// Determines if the given name is a build product for a target. /// /// The name to check /// Target or application names that may appear at the start of the build product name (eg. "UE4Editor", "ShooterGameEditor") /// Suffixes which may appear at the end of the build product name /// True if the string matches the name of a build product, false otherwise public override bool IsBuildProduct(string FileName, string[] NamePrefixes, string[] NameSuffixes) { return IsBuildProductName(FileName, NamePrefixes, NameSuffixes, ".js") || IsBuildProductName(FileName, NamePrefixes, NameSuffixes, HTML5ToolChain.libExt); } /// /// Get the extension to use for the given binary type /// /// The binary type being built /// string The binary extension (ie 'exe' or 'dll') public override string GetBinaryExtension(UEBuildBinaryType InBinaryType) { switch (InBinaryType) { case UEBuildBinaryType.DynamicLinkLibrary: return ".js"; case UEBuildBinaryType.Executable: return ".js"; case UEBuildBinaryType.StaticLibrary: return HTML5ToolChain.libExt; } return base.GetBinaryExtension(InBinaryType); } /// /// Get the extensions to use for debug info for the given binary type /// /// The target being built /// The binary type being built /// string[] The debug info extensions (i.e. 'pdb') public override string[] GetDebugInfoExtensions(ReadOnlyTargetRules InTarget, UEBuildBinaryType InBinaryType) { return new string [] {}; } /// /// Whether this platform should build a monolithic binary /// public override bool ShouldCompileMonolithicBinary(UnrealTargetPlatform InPlatform) { // This platform currently always compiles monolithic return true; } /// /// Modify the rules for a newly created module, where the target is a different host platform. /// This is not required - but allows for hiding details of a particular platform. /// /// The name of the module /// The module rules /// The target being build public override void ModifyModuleRulesForOtherPlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target) { if (Target.Platform == UnrealTargetPlatform.Win32 || Target.Platform == UnrealTargetPlatform.Win64 || Target.Platform == UnrealTargetPlatform.Mac || Target.Platform == UnrealTargetPlatform.Linux) { // allow standalone tools to use targetplatform modules, without needing Engine if ((!Target.bBuildRequiresCookedData && ModuleName == "Engine" && Target.bBuildDeveloperTools) || (Target.bForceBuildTargetPlatforms && ModuleName == "TargetPlatform")) { Rules.DynamicallyLoadedModuleNames.Add("HTML5TargetPlatform"); } } } /// /// Modify the rules for a newly created module, in a target that's being built for this platform. /// This is not required - but allows for hiding details of a particular platform. /// /// The name of the module /// The module rules /// The target being build public override void ModifyModuleRulesForActivePlatform(string ModuleName, ModuleRules Rules, ReadOnlyTargetRules Target) { if (ModuleName == "Core") { Rules.PublicIncludePaths.Add("Runtime/Core/Public/HTML5"); Rules.PublicDependencyModuleNames.Add("zlib"); } else if (ModuleName == "Engine") { Rules.PrivateDependencyModuleNames.Add("zlib"); Rules.PrivateDependencyModuleNames.Add("UElibPNG"); Rules.PublicDependencyModuleNames.Add("UEOgg"); Rules.PublicDependencyModuleNames.Add("Vorbis"); } } /// /// Setup the target environment for building /// /// Settings for the target being compiled /// The compile environment for this target /// The link environment for this target public override void SetUpEnvironment(ReadOnlyTargetRules Target, CppCompileEnvironment CompileEnvironment, LinkEnvironment LinkEnvironment) { CompileEnvironment.Definitions.Add("PLATFORM_HTML5=1"); // @todo needed? CompileEnvironment.Definitions.Add("UNICODE"); CompileEnvironment.Definitions.Add("_UNICODE"); CompileEnvironment.Definitions.Add("WITH_AUTOMATION_WORKER=0"); CompileEnvironment.Definitions.Add("WITH_OGGVORBIS=1"); CompileEnvironment.Definitions.Add("USE_SCENE_LOCK=0"); } /// /// Whether this platform should create debug information or not /// /// The target being built /// true if debug info should be generated, false if not public override bool ShouldCreateDebugInfo(ReadOnlyTargetRules Target) { switch (Target.Configuration) { case UnrealTargetConfiguration.Development: case UnrealTargetConfiguration.Shipping: case UnrealTargetConfiguration.Test: return !Target.bOmitPCDebugInfoInDevelopment; case UnrealTargetConfiguration.Debug: default: // We don't need debug info for Emscripten, and it causes a bunch of issues with linking return true; }; } /// /// Setup the binaries for this specific platform. /// /// The target being built /// public override void AddExtraModules(ReadOnlyTargetRules Target, List ExtraModuleNames) { ExtraModuleNames.Add("HTML5PlatformFeatures"); } /// /// Creates a toolchain instance for the given platform. /// /// The target being built /// New toolchain instance. public override UEToolChain CreateToolChain(ReadOnlyTargetRules Target) { return new HTML5ToolChain(Target.ProjectFile); } /// /// Deploys the given target /// /// Receipt for the target being deployed public override void Deploy(TargetReceipt Receipt) { } } class HTML5PlatformSDK : UEBuildPlatformSDK { // platforms can choose if they prefer a correct the the AutoSDK install over the manual install. protected override bool PreferAutoSDK() { // HTML5 build tools are included in UE4 at: Engine/Extras/ThirdPartyNotUE/emsdk/emscripten/ return false; } public override string GetSDKTargetPlatformName() { return "HTML5"; } /// /// Whether the required external SDKs are installed for this platform /// protected override SDKStatus HasRequiredManualSDKInternal() { if (!HTML5SDKInfo.IsSDKInstalled()) { return SDKStatus.Invalid; } return SDKStatus.Valid; } } class HTML5PlatformFactory : UEBuildPlatformFactory { public override UnrealTargetPlatform TargetPlatform { get { return UnrealTargetPlatform.HTML5; } } /// /// Register the platform with the UEBuildPlatform class /// public override void RegisterBuildPlatforms() { HTML5PlatformSDK SDK = new HTML5PlatformSDK(); SDK.ManageAndValidateSDK(); // Make sure the SDK is installed if ((ProjectFileGenerator.bGenerateProjectFiles == true) || (SDK.HasRequiredSDKsInstalled() == SDKStatus.Valid)) { // make sure we have the HTML5 files; if not, then this user doesn't really have HTML5 access/files, no need to compile HTML5! FileReference HTML5TargetPlatformFile = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Developer", "HTML5", "HTML5TargetPlatform", "HTML5TargetPlatform.Build.cs"); if (!FileReference.Exists(HTML5TargetPlatformFile)) { Log.TraceWarning("Missing required components (.... HTML5TargetPlatformFile, others here...). Check source control filtering, or try resyncing."); } else { // Register this build platform for HTML5 Log.TraceVerbose(" Registering for {0}", UnrealTargetPlatform.HTML5.ToString()); UEBuildPlatform.RegisterBuildPlatform(new HTML5Platform(SDK)); } } } } }