/// <summary> /// Construct an instance of the given target rules /// </summary> /// <param name="TypeName">Type name of the target rules</param> /// <param name="TargetInfo">Target configuration information to pass to the constructor</param> /// <param name="Arguments">Command line arguments for this target</param> /// <returns>Instance of the corresponding TargetRules</returns> protected TargetRules CreateTargetRulesInstance(string TypeName, TargetInfo TargetInfo, string[] Arguments) { // The build module must define a type named '<TargetName>Target' that derives from our 'TargetRules' type. Type RulesType = CompiledAssembly.GetType(TypeName); if (RulesType == null) { throw new BuildException("Expecting to find a type to be declared in a target rules named '{0}'. This type must derive from the 'TargetRules' type defined by Unreal Build Tool.", TypeName); } // Create an instance of the module's rules object, and set some defaults before calling the constructor. TargetRules Rules = (TargetRules)FormatterServices.GetUninitializedObject(RulesType); Rules.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults; // Find the constructor ConstructorInfo Constructor = RulesType.GetConstructor(new Type[] { typeof(TargetInfo) }); if (Constructor == null) { throw new BuildException("No constructor found on {0} which takes an argument of type TargetInfo.", RulesType.Name); } // Invoke the regular constructor try { Constructor.Invoke(Rules, new object[] { TargetInfo }); } catch (Exception Ex) { throw new BuildException(Ex, "Unable to instantiate instance of '{0}' object type from compiled assembly '{1}'. Unreal Build Tool creates an instance of your module's 'Rules' object in order to find out about your module's requirements. The CLR exception details may provide more information: {2}", TypeName, Path.GetFileNameWithoutExtension(CompiledAssembly.Location), Ex.ToString()); } // Set the default overriddes for the configured target type Rules.SetOverridesForTargetType(); // Parse any additional command-line arguments. These override default settings specified in config files or the .target.cs files. if (Arguments != null) { foreach (object ConfigurableObject in Rules.GetConfigurableObjects()) { CommandLine.ParseArguments(Arguments, ConfigurableObject); } } // Set the final value for the link type in the target rules if (Rules.LinkType == TargetLinkType.Default) { throw new BuildException("TargetRules.LinkType should be inferred from TargetType"); } // Set the default value for whether to use the shared build environment if (Rules.BuildEnvironment == TargetBuildEnvironment.Default) { if (Rules.Type == TargetType.Program && TargetInfo.ProjectFile != null && TargetNameToTargetFile[Rules.Name].IsUnderDirectory(TargetInfo.ProjectFile.Directory)) { Rules.BuildEnvironment = TargetBuildEnvironment.Unique; } else if (UnrealBuildTool.IsEngineInstalled() || Rules.LinkType != TargetLinkType.Monolithic) { Rules.BuildEnvironment = TargetBuildEnvironment.Shared; } else { Rules.BuildEnvironment = TargetBuildEnvironment.Unique; } } // Lean and mean means no Editor and other frills. if (Rules.bCompileLeanAndMeanUE) { Rules.bBuildEditor = false; Rules.bBuildDeveloperTools = Rules.bBuildDeveloperTools ?? false; Rules.bCompileSimplygon = false; Rules.bCompileSimplygonSSF = false; Rules.bCompileSpeedTree = false; } // if the bBuildDeveloperTools switch hasn't been defined, default it to the bCompileAgainstEngine switch. if (!Rules.bBuildDeveloperTools.HasValue) { Rules.bBuildDeveloperTools = Rules.bCompileAgainstEngine; } // Automatically include CoreUObject if (Rules.bCompileAgainstEngine) { Rules.bCompileAgainstCoreUObject = true; } // Must have editor only data if building the editor. if (Rules.bBuildEditor) { Rules.bBuildWithEditorOnlyData = true; } // Apply the override to force debug info to be enabled if (Rules.bForceDebugInfo) { Rules.bDisableDebugInfo = false; Rules.bOmitPCDebugInfoInDevelopment = false; } // Setup the malloc profiler if (Rules.bUseMallocProfiler) { Rules.bOmitFramePointers = false; Rules.GlobalDefinitions.Add("USE_MALLOC_PROFILER=1"); } // Set a macro if we allow using generated inis if (!Rules.bAllowGeneratedIniWhenCooked) { Rules.GlobalDefinitions.Add("DISABLE_GENERATED_INI_WHEN_COOKED=1"); } return(Rules); }
public LuminToolChain(FileReference InProjectFile, bool bInUseLdGold = true, IReadOnlyList <string> InAdditionalArches = null, IReadOnlyList <string> InAdditionalGPUArches = null, bool bAllowMissingNDK = true) : base(CppPlatform.Lumin, InProjectFile, // @todo Lumin: ld gold? true, null, null, true) { AdditionalGPUArches = new List <string>(); if (InAdditionalGPUArches != null) { AdditionalGPUArches.AddRange(InAdditionalGPUArches); } // by default tools chains don't parse arguments, but we want to be able to check the -gpuarchitectures flag defined above. This is // only necessary when LuminToolChain is used during UAT CommandLine.ParseArguments(Environment.GetCommandLineArgs(), this); if (AdditionalGPUArches.Count == 0 && GPUArchitectureArg.Count > 0) { AdditionalGPUArches.AddRange(GPUArchitectureArg); } string MLSDKPath = Environment.GetEnvironmentVariable("MLSDK"); // don't register if we don't have an MLSDK specified if (String.IsNullOrEmpty(MLSDKPath)) { throw new BuildException("MLSDK is not specified; cannot use Lumin toolchain."); } MLSDKPath = MLSDKPath.Replace("\"", ""); string MabuSpec = RunMabuAndReadOutput("-t device --print-spec"); // parse clange version Regex SpecRegex = new Regex("\\s*(?:[a-z]+_lumin_clang-)(\\d)[.](\\d)\\s*"); Match SpecMatch = SpecRegex.Match(MabuSpec); if (SpecMatch.Groups.Count != 3) { throw new BuildException("Could not parse clang version from mabu spec '{0}'", MabuSpec); } string ClangVersion = string.Format("{0}.{1}", SpecMatch.Groups[1].Value, SpecMatch.Groups[2].Value); SetClangVersion(int.Parse(SpecMatch.Groups[1].Value), int.Parse(SpecMatch.Groups[2].Value), 0); string MabuTools = RunMabuAndReadOutput("-t device --print-tools"); Dictionary <string, string> ToolsDict = new Dictionary <string, string>(); using (StringReader Reader = new StringReader(MabuTools)) { string Line = null; while (null != (Line = Reader.ReadLine())) { string[] Split = Line.Split('='); if (Split.Length != 2) { throw new BuildException("Unexpected output from mabu in --print-tools: '{0}'", Line); } ToolsDict.Add(Split[0].Trim(), Split[1].Trim()); } } // set up the path to our toolchains // Clang path used to be in quotes, but some part of FileReference in AndroidToolChain was choking on the quotes. Don't put your MLSDK in a directory with spaces for now, I guess. ClangPath = ToolsDict["CXX"]; ArPathArm64 = "\"" + ToolsDict["AR"] + "\""; // The strip command does not execute through the shell. Hence we don't quote it. StripPath = ToolsDict["STRIP"]; // The objcopy command does not execute through the shell. Hence we don't quote it. ObjCopyPath = ToolsDict["OBJCOPY"]; // force the compiler to be executed through a command prompt instance bExecuteCompilerThroughShell = true; // toolchain params ToolchainParamsArm64 = " --sysroot=\"" + Path.Combine(MLSDKPath, "lumin") + "\""; ToolchainLinkParamsArm = ToolchainParamsArm; ToolchainLinkParamsArm64 = ToolchainParamsArm64; ToolchainLinkParamsx86 = ToolchainParamsx86; ToolchainLinkParamsx64 = ToolchainParamsx64; }
/// <summary> /// /// </summary> /// <param name="ProjectFile"></param> /// <param name="Executable"></param> /// <param name="StageDirectory"></param> /// <param name="PlatformType"></param> public static void GenerateAssetCatalog(FileReference ProjectFile, string Executable, string StageDirectory, UnrealTargetPlatform PlatformType) { // Initialize the toolchain. IOSProjectSettings ProjectSettings = ((IOSPlatform)UEBuildPlatform.GetBuildPlatform(PlatformType)).ReadProjectSettings(null); IOSToolChain ToolChain = new IOSToolChain(ProjectFile, ProjectSettings); // Determine whether the user has modified icons that require a remote Mac to build. CppPlatform Platform = PlatformType == UnrealTargetPlatform.IOS ? CppPlatform.IOS : CppPlatform.TVOS; bool bUserImagesExist = false; ToolChain.GenerateAssetCatalog(Platform, ref bUserImagesExist); // Don't attempt to do anything remotely if the user is using the default UE4 images. if (!bUserImagesExist) { return; } // Also don't attempt to use a remote Mac if packaging for TVOS on PC. if (Platform == CppPlatform.TVOS && BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac) { return; } // Save off the current bUseRPCUtil setting to restore at the end of this function. // At this time, iPhonePackager needs to be called with bUseRPCUtil == true. bool bSaveUseRPCUtil = RemoteToolChain.bUseRPCUtil; // Initialize the remote calling environment, taking into account the user's SSH setting. ToolChain.SetUpGlobalEnvironment(false); // Build the asset catalog ActionGraph. ActionGraph ActionGraph = new ActionGraph(); List <FileItem> OutputFiles = new List <FileItem>(); ToolChain.CompileAssetCatalog(FileItem.GetItemByPath(Executable), Platform, ActionGraph, OutputFiles); ActionGraph.FinalizeActionGraph(); // I'm not sure how to derive the UE4Game and Development arguments programmatically. string[] Arguments = new string[] { "UE4Game", (PlatformType == UnrealTargetPlatform.IOS ? "IOS" : "TVOS"), "Development", "-UniqueBuildEnvironment" }; // Perform all of the setup necessary to actually execute the ActionGraph instance. ReadOnlyBuildVersion Version = new ReadOnlyBuildVersion(BuildVersion.ReadDefault()); List <string[]> TargetSettings = new List <string[]>(); TargetSettings.Add(Arguments); var Targets = new List <UEBuildTarget>(); Dictionary <UEBuildTarget, CPPHeaders> TargetToHeaders = new Dictionary <UEBuildTarget, CPPHeaders>(); List <TargetDescriptor> TargetDescs = new List <TargetDescriptor>(); foreach (string[] TargetSetting in TargetSettings) { TargetDescs.AddRange(TargetDescriptor.ParseCommandLine(TargetSetting, ref ProjectFile)); } foreach (TargetDescriptor TargetDesc in TargetDescs) { UEBuildTarget Target = UEBuildTarget.CreateTarget(TargetDesc, Arguments, false, Version); if (Target == null) { continue; } Targets.Add(Target); TargetToHeaders.Add(Target, null); } bool bIsRemoteCompile = BuildHostPlatform.Current.Platform != UnrealTargetPlatform.Mac; // Create the build configuration object, and read the settings BuildConfiguration BuildConfiguration = new BuildConfiguration(); XmlConfig.ApplyTo(BuildConfiguration); CommandLine.ParseArguments(Arguments, BuildConfiguration); BuildConfiguration.bUseUBTMakefiles = false; Action[] PrerequisiteActions; { HashSet <Action> PrerequisiteActionsSet = new HashSet <Action>(); foreach (FileItem OutputFile in OutputFiles) { ActionGraph.GatherPrerequisiteActions(OutputFile, ref PrerequisiteActionsSet); } PrerequisiteActions = PrerequisiteActionsSet.ToArray(); } // Copy any asset catalog files to the remote Mac, if necessary. foreach (UEBuildTarget Target in Targets) { UEBuildPlatform.GetBuildPlatform(Target.Platform).PreBuildSync(); } // Begin execution of the ActionGraph. Dictionary <UEBuildTarget, List <FileItem> > TargetToOutdatedPrerequisitesMap; List <Action> ActionsToExecute = ActionGraph.GetActionsToExecute(BuildConfiguration, PrerequisiteActions, Targets, TargetToHeaders, true, true, out TargetToOutdatedPrerequisitesMap); string ExecutorName = "Unknown"; bool bSuccess = ActionGraph.ExecuteActions(BuildConfiguration, ActionsToExecute, bIsRemoteCompile, out ExecutorName, "", EHotReload.Disabled); if (bSuccess) { if (bIsRemoteCompile) { // Copy the remotely built AssetCatalog directory locally. foreach (FileItem OutputFile in OutputFiles) { string RemoteDirectory = System.IO.Path.GetDirectoryName(OutputFile.AbsolutePath).Replace("\\", "/"); FileItem LocalExecutable = ToolChain.RemoteToLocalFileItem(FileItem.GetItemByPath(Executable)); string LocalDirectory = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(LocalExecutable.AbsolutePath), "AssetCatalog"); LocalDirectory = StageDirectory; RPCUtilHelper.CopyDirectory(RemoteDirectory, LocalDirectory, RPCUtilHelper.ECopyOptions.DoNotReplace); } } else { // Copy the built AssetCatalog directory to the StageDirectory. foreach (FileItem OutputFile in OutputFiles) { string SourceDirectory = System.IO.Path.GetDirectoryName(OutputFile.AbsolutePath).Replace("\\", "/"); System.IO.DirectoryInfo SourceDirectoryInfo = new System.IO.DirectoryInfo(SourceDirectory); if (!System.IO.Directory.Exists(StageDirectory)) { System.IO.Directory.CreateDirectory(StageDirectory); } System.IO.FileInfo[] SourceFiles = SourceDirectoryInfo.GetFiles(); foreach (System.IO.FileInfo SourceFile in SourceFiles) { string DestinationPath = System.IO.Path.Combine(StageDirectory, SourceFile.Name); SourceFile.CopyTo(DestinationPath, true); } } } } // Restore the former bUseRPCUtil setting. RemoteToolChain.bUseRPCUtil = bSaveUseRPCUtil; }