/// <summary> /// Creates an instance of a module rules descriptor object for the specified module name /// </summary> /// <param name="ModuleName">Name of the module</param> /// <param name="Target">Information about the target associated with this module</param> /// <param name="ReferenceChain">Chain of references leading to this module</param> /// <returns>Compiled module rule info</returns> public ModuleRules CreateModuleRules(string ModuleName, ReadOnlyTargetRules Target, string ReferenceChain) { // Currently, we expect the user's rules object type name to be the same as the module name string ModuleTypeName = ModuleName; // Make sure the module file is known to us FileReference ModuleFileName; if (!ModuleNameToModuleFile.TryGetValue(ModuleName, out ModuleFileName)) { if (Parent == null) { throw new BuildException("Could not find definition for module '{0}' (referenced via {1})", ModuleName, ReferenceChain); } else { return(Parent.CreateModuleRules(ModuleName, Target, ReferenceChain)); } } // The build module must define a type named 'Rules' that derives from our 'ModuleRules' type. Type RulesObjectType = GetModuleRulesTypeInternal(ModuleName); if (RulesObjectType == null) { throw new BuildException("Expecting to find a type to be declared in a module rules named '{0}' in {1}. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.", ModuleTypeName, CompiledAssembly.FullName); } // Create an instance of the module's rules object try { // Create an uninitialized ModuleRules object and set some defaults. ModuleRules RulesObject = (ModuleRules)FormatterServices.GetUninitializedObject(RulesObjectType); RulesObject.Name = ModuleName; RulesObject.File = ModuleFileName; RulesObject.Directory = ModuleFileName.Directory; ModuleFileToPluginInfo.TryGetValue(RulesObject.File, out RulesObject.Plugin); RulesObject.bTreatAsEngineModule = bContainsEngineModules; RulesObject.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults && Target.bUseBackwardsCompatibleDefaults; RulesObject.bPrecompile = (RulesObject.bTreatAsEngineModule || ModuleName.Equals("UE4Game", StringComparison.OrdinalIgnoreCase)) && Target.bPrecompile; RulesObject.bUsePrecompiled = bReadOnly; // Call the constructor ConstructorInfo Constructor = RulesObjectType.GetConstructor(new Type[] { typeof(ReadOnlyTargetRules) }); if (Constructor == null) { throw new BuildException("No valid constructor found for {0}.", ModuleName); } Constructor.Invoke(RulesObject, new object[] { Target }); return(RulesObject); } catch (Exception Ex) { Exception MessageEx = (Ex is TargetInvocationException && Ex.InnerException != null)? Ex.InnerException : Ex; throw new BuildException(Ex, "Unable to instantiate module '{0}': {1}\n(referenced via {2})", ModuleName, MessageEx.ToString(), ReferenceChain); } }
/// <summary> /// Creates an instance of a module rules descriptor object for the specified module name /// </summary> /// <param name="ModuleName">Name of the module</param> /// <param name="Target">Information about the target associated with this module</param> /// <param name="ReferenceChain">Chain of references leading to this module</param> /// <param name="ModuleFileName">The original source file name for the Module.cs file for this module</param> /// <returns>Compiled module rule info</returns> public ModuleRules CreateModuleRules(string ModuleName, ReadOnlyTargetRules Target, string ReferenceChain, out FileReference ModuleFileName) { // Currently, we expect the user's rules object type name to be the same as the module name string ModuleTypeName = ModuleName; // Make sure the module file is known to us if (!ModuleNameToModuleFile.TryGetValue(ModuleName, out ModuleFileName)) { if (Parent == null) { throw new BuildException("Could not find definition for module '{0}' (referenced via {1})", ModuleName, ReferenceChain); } else { return(Parent.CreateModuleRules(ModuleName, Target, ReferenceChain, out ModuleFileName)); } } // The build module must define a type named 'Rules' that derives from our 'ModuleRules' type. Type RulesObjectType = CompiledAssembly.GetType(ModuleName); if (RulesObjectType == null) { // Temporary hack to avoid System namespace collisions // @todo projectfiles: Make rules assemblies require namespaces. RulesObjectType = CompiledAssembly.GetType("UnrealBuildTool.Rules." + ModuleName); } if (RulesObjectType == null) { throw new BuildException("Expecting to find a type to be declared in a module rules named '{0}' in {1}. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.", ModuleTypeName, CompiledAssembly.FullName); } // Create an instance of the module's rules object ModuleRules RulesObject; try { // Create an uninitialized ModuleRules object and initialize some fields on it while we're still supporting the deprecated parameterless constructor. RulesObject = (ModuleRules)FormatterServices.GetUninitializedObject(RulesObjectType); typeof(ModuleRules).GetField("Target").SetValue(RulesObject, Target); // Call the constructor ConstructorInfo Constructor = RulesObjectType.GetConstructor(new Type[] { typeof(ReadOnlyTargetRules) }); if (Constructor == null) { throw new BuildException("No valid constructor found for {0}.", ModuleName); } Constructor.Invoke(RulesObject, new object[] { Target }); } catch (Exception Ex) { Exception MessageEx = (Ex is TargetInvocationException && Ex.InnerException != null)? Ex.InnerException : Ex; throw new BuildException(Ex, "Unable to instantiate module '{0}': {1}\n(referenced via {2})", ModuleName, MessageEx.ToString(), ReferenceChain); } return(RulesObject); }
/// <summary> /// Creates an instance of a module rules descriptor object for the specified module name /// </summary> /// <param name="ModuleName">Name of the module</param> /// <param name="Target">Information about the target associated with this module</param> /// <param name="ModuleFileName">The original source file name for the Module.cs file for this module</param> /// <returns>Compiled module rule info</returns> public ModuleRules CreateModuleRules(string ModuleName, TargetInfo Target, out FileReference ModuleFileName) { // Currently, we expect the user's rules object type name to be the same as the module name string ModuleTypeName = ModuleName; // Make sure the module file is known to us if (!ModuleNameToModuleFile.TryGetValue(ModuleName, out ModuleFileName)) { if (Parent == null) { throw new MissingModuleException(ModuleName); } else { return(Parent.CreateModuleRules(ModuleName, Target, out ModuleFileName)); } } // The build module must define a type named 'Rules' that derives from our 'ModuleRules' type. Type RulesObjectType = CompiledAssembly.GetType(ModuleName); if (RulesObjectType == null) { // Temporary hack to avoid System namespace collisions // @todo projectfiles: Make rules assemblies require namespaces. RulesObjectType = CompiledAssembly.GetType("UnrealBuildTool.Rules." + ModuleName); } if (RulesObjectType == null) { throw new BuildException("Expecting to find a type to be declared in a module rules named '{0}' in {1}. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.", ModuleTypeName, CompiledAssembly.FullName); } // Create an instance of the module's rules object ModuleRules RulesObject; try { RulesObject = (ModuleRules)Activator.CreateInstance(RulesObjectType, Target); } 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}", ModuleTypeName, CompiledAssembly.FullName, Ex.ToString()); } // Update the run-time dependencies path to remove $(PluginDir) and replace with a full path. When the receipt is saved it'll be converted to a $(ProjectDir) or $(EngineDir) equivalent. foreach (RuntimeDependency Dependency in RulesObject.RuntimeDependencies) { const string PluginDirVariable = "$(PluginDir)"; if (Dependency.Path.StartsWith(PluginDirVariable, StringComparison.InvariantCultureIgnoreCase)) { PluginInfo Plugin; if (ModuleFileToPluginInfo.TryGetValue(ModuleFileName, out Plugin)) { Dependency.Path = Plugin.Directory + Dependency.Path.Substring(PluginDirVariable.Length); } } } return(RulesObject); }
/// <summary> /// Creates an instance of a module rules descriptor object for the specified module name /// </summary> /// <param name="ModuleName">Name of the module</param> /// <param name="Target">Information about the target associated with this module</param> /// <param name="ReferenceChain">Chain of references leading to this module</param> /// <returns>Compiled module rule info</returns> public ModuleRules CreateModuleRules(string ModuleName, ReadOnlyTargetRules Target, string ReferenceChain) { // Currently, we expect the user's rules object type name to be the same as the module name string ModuleTypeName = ModuleName; // Make sure the base module file is known to us FileReference ModuleFileName; if (!ModuleNameToModuleFile.TryGetValue(ModuleTypeName, out ModuleFileName)) { if (Parent == null) { throw new BuildException("Could not find definition for module '{0}', (referenced via {1})", ModuleTypeName, ReferenceChain); } else { return(Parent.CreateModuleRules(ModuleName, Target, ReferenceChain)); } } // get the standard Rules object class from the assembly Type BaseRulesObjectType = GetModuleRulesTypeInternal(ModuleTypeName); // look around for platform/group modules that we will use instead of the basic module Type PlatformRulesObjectType = GetModuleRulesTypeInternal(ModuleTypeName + "_" + Target.Platform.ToString()); if (PlatformRulesObjectType == null) { foreach (UnrealPlatformGroup Group in UEBuildPlatform.GetPlatformGroups(Target.Platform)) { // look to see if the group has an override Type GroupRulesObjectType = GetModuleRulesTypeInternal(ModuleName + "_" + Group.ToString()); // we expect only one platform group to be found in the extensions if (GroupRulesObjectType != null && PlatformRulesObjectType != null) { throw new BuildException("Found multiple platform group overrides ({0} and {1}) for module {2} without a platform specific override. Create a platform override with the class hierarchy as needed.", GroupRulesObjectType.Name, PlatformRulesObjectType.Name, ModuleName); } PlatformRulesObjectType = GroupRulesObjectType; } } // Figure out the best rules object to use Type RulesObjectType = PlatformRulesObjectType != null ? PlatformRulesObjectType : BaseRulesObjectType; if (RulesObjectType == null) { throw new BuildException("Expecting to find a type to be declared in a module rules named '{0}' in {1}. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.", ModuleTypeName, CompiledAssembly.FullName); } // Create an instance of the module's rules object try { // Create an uninitialized ModuleRules object and set some defaults. ModuleRules RulesObject = (ModuleRules)FormatterServices.GetUninitializedObject(RulesObjectType); // even if we created a platform-extension version of the module rules, we are pretending to be // the base type, so that no one else needs to manage this RulesObject.Name = ModuleName; RulesObject.File = ModuleFileName; RulesObject.Directory = ModuleFileName.Directory; RulesObject.Context = ModuleFileToContext[RulesObject.File]; RulesObject.Plugin = RulesObject.Context.Plugin; RulesObject.bTreatAsEngineModule = bContainsEngineModules; if (DefaultBuildSettings.HasValue) { RulesObject.DefaultBuildSettings = DefaultBuildSettings.Value; } RulesObject.bPrecompile = (RulesObject.bTreatAsEngineModule || ModuleName.Equals("UE4Game", StringComparison.OrdinalIgnoreCase)) && Target.bPrecompile; RulesObject.bUsePrecompiled = bReadOnly; // go up the type hierarchy (if there is a hierarchy), looking for any extra directories for the module if (RulesObjectType != BaseRulesObjectType && RulesObjectType != typeof(ModuleRules)) { Type SubType = RulesObjectType; RulesObject.DirectoriesForModuleSubClasses = new Dictionary <Type, DirectoryReference>(); RulesObject.SubclassRules = new List <string>(); while (SubType != null && SubType != BaseRulesObjectType) { FileReference SubTypeFileName; if (TryGetFileNameFromType(SubType, out SubTypeFileName)) { RulesObject.DirectoriesForModuleSubClasses.Add(SubType, SubTypeFileName.Directory); RulesObject.SubclassRules.Add(SubTypeFileName.FullName); } SubType = SubType.BaseType; } } // Call the constructor ConstructorInfo Constructor = RulesObjectType.GetConstructor(new Type[] { typeof(ReadOnlyTargetRules) }); if (Constructor == null) { throw new BuildException("No valid constructor found for {0}.", ModuleName); } Constructor.Invoke(RulesObject, new object[] { Target }); return(RulesObject); } catch (Exception Ex) { Exception MessageEx = (Ex is TargetInvocationException && Ex.InnerException != null)? Ex.InnerException : Ex; throw new BuildException(Ex, "Unable to instantiate module '{0}': {1}\n(referenced via {2})", ModuleName, MessageEx.ToString(), ReferenceChain); } }
/// <summary> /// Creates an instance of a module rules descriptor object for the specified module name /// </summary> /// <param name="ModuleName">Name of the module</param> /// <param name="Target">Information about the target associated with this module</param> /// <param name="ModuleFileName">The original source file name for the Module.cs file for this module</param> /// <returns>Compiled module rule info</returns> public ModuleRules CreateModuleRules(string ModuleName, ReadOnlyTargetRules Target, out FileReference ModuleFileName) { // Currently, we expect the user's rules object type name to be the same as the module name string ModuleTypeName = ModuleName; // Make sure the module file is known to us if (!ModuleNameToModuleFile.TryGetValue(ModuleName, out ModuleFileName)) { if (Parent == null) { throw new MissingModuleException(ModuleName); } else { return(Parent.CreateModuleRules(ModuleName, Target, out ModuleFileName)); } } // The build module must define a type named 'Rules' that derives from our 'ModuleRules' type. Type RulesObjectType = CompiledAssembly.GetType(ModuleName); if (RulesObjectType == null) { // Temporary hack to avoid System namespace collisions // @todo projectfiles: Make rules assemblies require namespaces. RulesObjectType = CompiledAssembly.GetType("UnrealBuildTool.Rules." + ModuleName); } if (RulesObjectType == null) { throw new BuildException("Expecting to find a type to be declared in a module rules named '{0}' in {1}. This type must derive from the 'ModuleRules' type defined by Unreal Build Tool.", ModuleTypeName, CompiledAssembly.FullName); } // Create an instance of the module's rules object ModuleRules RulesObject; try { // Create an uninitialized ModuleRules object and initialize some fields on it while we're still supporting the deprecated parameterless constructor. RulesObject = (ModuleRules)FormatterServices.GetUninitializedObject(RulesObjectType); typeof(ModuleRules).GetField("Target").SetValue(RulesObject, Target); // Call the constructor ConstructorInfo Constructor = RulesObjectType.GetConstructor(new Type[] { typeof(ReadOnlyTargetRules) }); if (Constructor != null) { Constructor.Invoke(RulesObject, new object[] { Target }); } else { ConstructorInfo DeprecatedConstructor = RulesObjectType.GetConstructor(new Type[] { typeof(TargetInfo) }); if (DeprecatedConstructor == null) { throw new Exception("No valid constructor found."); } DeprecatedConstructor.Invoke(RulesObject, new object[] { new TargetInfo(Target) }); } } 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}", ModuleTypeName, CompiledAssembly.FullName, Ex.ToString()); } return(RulesObject); }
/// <summary> /// Find all third party and private header includes in public engine headers. /// </summary> public static void FindThirdPartyIncludes(UnrealTargetPlatform Platform, UnrealTargetConfiguration Configuration, string Architecture) { Log.TraceInformation("Looking for third party header includes in public engine header files (this may take a few minutes)..."); TargetInfo Target = new TargetInfo(Platform, Configuration, Architecture); List <string> UncheckedModules = new List <string>(); EngineHeaders = new List <Header>(); ThirdPartyHeaders = new List <Header>(); // Create a rules assembly for the engine RulesAssembly EngineRulesAssembly = RulesCompiler.CreateEngineRulesAssembly(); // Find all modules referenced by the current target List <FileReference> ModuleFileNames = RulesCompiler.FindAllRulesSourceFiles(RulesCompiler.RulesFileType.Module, GameFolders: null, ForeignPlugins: null, AdditionalSearchPaths: null); foreach (FileReference ModuleFileName in ModuleFileNames) { string ModuleName = Path.GetFileNameWithoutExtension(ModuleFileName.GetFileNameWithoutExtension()); try { ModuleRules RulesObject = EngineRulesAssembly.CreateModuleRules(ModuleName, Target); bool bEngineHeaders = RulesObject.Type != ModuleRules.ModuleType.External; foreach (string SystemIncludePath in RulesObject.PublicSystemIncludePaths) { FindHeaders(SystemIncludePath, bEngineHeaders ? EngineHeaders : ThirdPartyHeaders, bEngineHeaders); } foreach (string PublicIncludePath in RulesObject.PublicIncludePaths) { FindHeaders(PublicIncludePath, bEngineHeaders ? EngineHeaders : ThirdPartyHeaders, bEngineHeaders); } } catch (Exception) { // Ignore, some modules may fail here. UncheckedModules.Add(ModuleName); } } // Search for illegal includes. List <IncludePath> ThirdPartyIncludes = new List <IncludePath>(); List <IncludePath> PrivateIncludes = new List <IncludePath>(); CheckIfThirdPartyHeadersAreIncluded(ThirdPartyIncludes, PrivateIncludes); // List all of the included 3rd party headers unless their name matches with any of the engine header. if (ThirdPartyIncludes.Count > 0) { // Remove ambiguous headers for (int IncludeIndex = ThirdPartyIncludes.Count - 1; IncludeIndex >= 0; --IncludeIndex) { if (FindHeader(EngineHeaders, ThirdPartyIncludes[IncludeIndex].OtherHeader.Name) != null) { ThirdPartyIncludes.RemoveAt(IncludeIndex); } } if (ThirdPartyIncludes.Count > 0) { Log.TraceInformation("Warning: Found {0} third party header includes in public engine headers. Third party headers should only be included in private engine headers.", ThirdPartyIncludes.Count); foreach (IncludePath HeaderPath in ThirdPartyIncludes) { if (FindHeader(EngineHeaders, HeaderPath.OtherHeader.Name) == null) { Log.TraceInformation("{0} includes {1}.", HeaderPath.PublicHeaderPath, HeaderPath.OtherHeader.Path); } } } } // List all private engine headers included from public engine headers if (PrivateIncludes.Count > 0) { Log.TraceInformation("Warning: Found {0} private engine header includes in public engine headers. Private engine headers should not be included in public engine headers.", PrivateIncludes.Count); } foreach (IncludePath HeaderPath in PrivateIncludes) { Log.TraceInformation("{0} includes {1}.", HeaderPath.PublicHeaderPath, HeaderPath.OtherHeader.Path); } if (PrivateIncludes.Count == 0 && ThirdPartyIncludes.Count == 0) { Log.TraceInformation("Finished looking for third party includes. Nothing found."); } if (UncheckedModules.Count > 0) { Log.TraceInformation("Warning: The following modules could not be checked (exception while trying to create ModuleRules object):"); for (int ModuleIndex = 0; ModuleIndex < UncheckedModules.Count; ++ModuleIndex) { Log.TraceInformation(" {0}", UncheckedModules[ModuleIndex]); } } }