Beispiel #1
0
        /// <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);
            }
        }
Beispiel #5
0
        /// <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]);
                }
            }
        }