// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.IO; namespace UnrealBuildTool { class LinuxPlatformContext : UEBuildPlatformContext { public LinuxPlatformContext(FileReference InProjectFile) : base(UnrealTargetPlatform.Linux, InProjectFile) { } /// /// The current architecture /// public override string GetActiveArchitecture() { return LinuxPlatform.DefaultArchitecture; } /// /// 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, TargetInfo Target) { bool bBuildShaderFormats = UEBuildConfiguration.bForceBuildShaderFormats; if (!UEBuildConfiguration.bBuildRequiresCookedData) { if (ModuleName == "TargetPlatform") { bBuildShaderFormats = true; } } // allow standalone tools to use target platform modules, without needing Engine if (ModuleName == "TargetPlatform") { if (UEBuildConfiguration.bForceBuildTargetPlatforms) { Rules.DynamicallyLoadedModuleNames.Add("LinuxTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("LinuxNoEditorTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("LinuxServerTargetPlatform"); Rules.DynamicallyLoadedModuleNames.Add("AllDesktopTargetPlatform"); } if (bBuildShaderFormats) { // Rules.DynamicallyLoadedModuleNames.Add("ShaderFormatD3D"); Rules.DynamicallyLoadedModuleNames.Add("ShaderFormatOpenGL"); } } } /// /// Gives the platform a chance to 'override' the configuration settings /// that are overridden on calls to RunUBT. /// /// The UnrealTargetConfiguration being built public override void ResetBuildConfiguration(UnrealTargetConfiguration Configuration) { ValidateUEBuildConfiguration(); } /// /// Validate configuration for this platform /// NOTE: This function can/will modify BuildConfiguration! /// /// The CPPTargetPlatform being built /// The CPPTargetConfiguration being built /// true if debug info is getting create, false if not public override void ValidateBuildConfiguration(CPPTargetConfiguration Configuration, CPPTargetPlatform Platform, bool bCreateDebugInfo) { UEBuildConfiguration.bCompileSimplygon = false; } /// /// Validate the UEBuildConfiguration for this platform /// This is called BEFORE calling UEBuildConfiguration to allow setting /// various fields used in that function such as CompileLeanAndMean... /// public override void ValidateUEBuildConfiguration() { if (ProjectFileGenerator.bGenerateProjectFiles && !ProjectFileGenerator.bGeneratingRocketProjectFiles) { // When generating non-Rocket project files we need intellisense generator to include info from all modules, // including editor-only third party libs UEBuildConfiguration.bCompileLeanAndMeanUE = false; } BuildConfiguration.bUseUnityBuild = true; // Don't stop compilation at first error... BuildConfiguration.bStopXGECompilationAfterErrors = true; BuildConfiguration.bUseSharedPCHs = false; } /// /// Setup the target environment for building /// /// The target being built public override void SetUpEnvironment(UEBuildTarget InBuildTarget) { InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("PLATFORM_LINUX=1"); InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("LINUX=1"); InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("WITH_DATABASE_SUPPORT=0"); //@todo linux: valid? if (GetActiveArchitecture().StartsWith("arm")) { InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Add("REQUIRES_ALIGNED_INT_ACCESS"); } // link with Linux libraries. InBuildTarget.GlobalLinkEnvironment.Config.AdditionalLibraries.Add("pthread"); // Disable Simplygon support if compiling against the NULL RHI. if (InBuildTarget.GlobalCompileEnvironment.Config.Definitions.Contains("USE_NULL_RHI=1")) { UEBuildConfiguration.bCompileSimplygon = false; } if (InBuildTarget.TargetType == TargetRules.TargetType.Server) { // Localization shouldn't be needed on servers by default, and ICU is pretty heavy UEBuildConfiguration.bCompileICU = false; } } /// /// Whether this platform should create debug information or not /// /// The UnrealTargetPlatform being built /// The UnrealTargetConfiguration being built /// bool true if debug info should be generated, false if not public override bool ShouldCreateDebugInfo(UnrealTargetConfiguration Configuration) { switch (Configuration) { case UnrealTargetConfiguration.Development: case UnrealTargetConfiguration.Shipping: case UnrealTargetConfiguration.Test: case UnrealTargetConfiguration.Debug: default: return true; }; } /// /// Creates a toolchain instance for the given platform. /// /// The platform to create a toolchain for /// New toolchain instance. public override UEToolChain CreateToolChain(CPPTargetPlatform Platform) { return new LinuxToolChain(this); } /// /// Create a build deployment handler /// /// The project file of the target being deployed. Used to find any deployment specific settings. /// The output deployment handler /// True if the platform requires a deployment handler, false otherwise public override UEBuildDeploy CreateDeploymentHandler() { return null; } } class LinuxPlatform : UEBuildPlatform { /// /// Linux architecture (compiler target triplet) /// // FIXME: for now switching between architectures is hard-coded public const string DefaultArchitecture = "x86_64-unknown-linux-gnu"; //static private string DefaultArchitecture = "arm-unknown-linux-gnueabihf"; LinuxPlatformSDK SDK; /// /// Constructor /// public LinuxPlatform(LinuxPlatformSDK InSDK) : base(UnrealTargetPlatform.Linux, CPPTargetPlatform.Linux) { 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(); } /// /// Allows the platform to override whether the architecture name should be appended to the name of binaries. /// /// True if the architecture name should be appended to the binary public override bool RequiresArchitectureSuffix() { // Linux ignores architecture-specific names, although it might be worth it to prepend architecture return false; } public override bool CanUseXGE() { // [RCL] 2015-08-04 FIXME: modular (cross-)builds (e.g. editor, UT server) fail with XGE as FixDeps step apparently depends on artifacts (object files) which aren't listed among its prerequisites. return false; } /// /// Get the extension to use for the given binary type /// /// The binary type being built /// string The binary extension (i.e. 'exe' or 'dll') public override string GetBinaryExtension(UEBuildBinaryType InBinaryType) { switch (InBinaryType) { case UEBuildBinaryType.DynamicLinkLibrary: return ".so"; case UEBuildBinaryType.Executable: return ""; case UEBuildBinaryType.StaticLibrary: return ".a"; case UEBuildBinaryType.Object: return ".o"; case UEBuildBinaryType.PrecompiledHeader: return ".gch"; } return base.GetBinaryExtension(InBinaryType); } /// /// Get the extension to use for debug info for the given binary type /// /// The binary type being built /// string The debug info extension (i.e. 'pdb') public override string GetDebugInfoExtension(UEBuildBinaryType InBinaryType) { return ""; } /// /// Whether PDB files should be used /// /// The CPPTargetPlatform being built /// The CPPTargetConfiguration being built /// true if debug info is getting create, false if not /// bool true if PDB files should be used, false if not public override bool ShouldUsePDBFiles(CPPTargetPlatform Platform, CPPTargetConfiguration Configuration, bool bCreateDebugInfo) { 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, TargetInfo Target) { if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64)) { if (!UEBuildConfiguration.bBuildRequiresCookedData) { if (ModuleName == "Engine") { if (UEBuildConfiguration.bBuildDeveloperTools) { Rules.PlatformSpecificDynamicallyLoadedModuleNames.Add("LinuxTargetPlatform"); Rules.PlatformSpecificDynamicallyLoadedModuleNames.Add("LinuxNoEditorTargetPlatform"); Rules.PlatformSpecificDynamicallyLoadedModuleNames.Add("LinuxServerTargetPlatform"); } } } // allow standalone tools to use targetplatform modules, without needing Engine if (UEBuildConfiguration.bForceBuildTargetPlatforms && ModuleName == "TargetPlatform") { Rules.PlatformSpecificDynamicallyLoadedModuleNames.Add("LinuxTargetPlatform"); Rules.PlatformSpecificDynamicallyLoadedModuleNames.Add("LinuxNoEditorTargetPlatform"); Rules.PlatformSpecificDynamicallyLoadedModuleNames.Add("LinuxServerTargetPlatform"); } } } /// /// Creates a context for the given project on the current platform. /// /// The project file for the current target /// New platform context object public override UEBuildPlatformContext CreateContext(FileReference ProjectFile) { return new LinuxPlatformContext(ProjectFile); } } class LinuxPlatformSDK : UEBuildPlatformSDK { /// /// This is the SDK version we support /// static private Dictionary ExpectedSDKVersions = new Dictionary() { { "x86_64-unknown-linux-gnu", "v6_clang-3.6.0_ld-2.24_glibc-2.12.2" }, { "arm-unknown-linux-gnueabihf", "arm-unknown-linux-gnueabihf_v5_clang-3.5.0-ld-2.23.1-glibc-2.13" }, }; /// /// Platform name (embeds architecture for now) /// static private string TargetPlatformName = "Linux_x64"; /// /// Whether platform supports switching SDKs during runtime /// /// true if supports protected override bool PlatformSupportsAutoSDKs() { return true; } /// /// Returns platform-specific name used in SDK repository /// /// path to SDK Repository public override string GetSDKTargetPlatformName() { return TargetPlatformName; } /// /// Returns SDK string as required by the platform /// /// Valid SDK string protected override string GetRequiredSDKString() { string SDKString; if (!ExpectedSDKVersions.TryGetValue(LinuxPlatform.DefaultArchitecture, out SDKString)) { throw new BuildException("LinuxPlatform::GetRequiredSDKString: no toolchain set up for architecture '{0}'", LinuxPlatform.DefaultArchitecture); } return SDKString; } protected override String GetRequiredScriptVersionString() { return "3.0"; } protected override bool PreferAutoSDK() { // having LINUX_ROOT set (for legacy reasons or for convenience of cross-compiling certain third party libs) should not make UBT skip AutoSDKs return true; } /// /// Whether the required external SDKs are installed for this platform /// protected override SDKStatus HasRequiredManualSDKInternal() { if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Linux) { return SDKStatus.Valid; } string BaseLinuxPath = Environment.GetEnvironmentVariable("LINUX_ROOT"); // we don't have an LINUX_ROOT specified if (String.IsNullOrEmpty(BaseLinuxPath)) return SDKStatus.Invalid; // paths to our toolchains BaseLinuxPath = BaseLinuxPath.Replace("\"", ""); string ClangPath = Path.Combine(BaseLinuxPath, @"bin\Clang++.exe"); if (File.Exists(ClangPath)) return SDKStatus.Valid; return SDKStatus.Invalid; } } class LinuxPlatformFactory : UEBuildPlatformFactory { /// /// Register the platform with the UEBuildPlatform class /// public override void RegisterBuildPlatforms() { LinuxPlatformSDK SDK = new LinuxPlatformSDK(); SDK.ManageAndValidateSDK(); if ((ProjectFileGenerator.bGenerateProjectFiles == true) || (SDK.HasRequiredSDKsInstalled() == SDKStatus.Valid)) { bool bRegisterBuildPlatform = true; string EngineSourcePath = Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine", "Source"); string LinuxTargetPlatformFile = Path.Combine(EngineSourcePath, "Developer", "Linux", "LinuxTargetPlatform", "LinuxTargetPlatform.Build.cs"); if (File.Exists(LinuxTargetPlatformFile) == false) { bRegisterBuildPlatform = false; } if (bRegisterBuildPlatform == true) { // Register this build platform for Linux if (BuildConfiguration.bPrintDebugInfo) { Console.WriteLine(" Registering for {0}", UnrealTargetPlatform.Linux.ToString()); } UEBuildPlatform.RegisterBuildPlatform(new LinuxPlatform(SDK)); UEBuildPlatform.RegisterPlatformWithGroup(UnrealTargetPlatform.Linux, UnrealPlatformGroup.Unix); } } } } }