/// <summary>
        /// Constructor. Compiles a rules assembly from the given source files.
        /// </summary>
        /// <param name="Plugins">All the plugins included in this assembly</param>
        /// <param name="ModuleFiles">List of module files to compile</param>
        /// <param name="TargetFiles">List of target files to compile</param>
        /// <param name="ModuleFileToPluginInfo">Mapping of module file to the plugin that contains it</param>
        /// <param name="AssemblyFileName">The output path for the compiled assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        public RulesAssembly(IReadOnlyList <PluginInfo> Plugins, List <FileReference> ModuleFiles, List <FileReference> TargetFiles, Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo, FileReference AssemblyFileName, RulesAssembly Parent)
        {
            this.Plugins = Plugins;
            this.ModuleFileToPluginInfo = ModuleFileToPluginInfo;
            this.Parent = Parent;

            // Find all the source files
            List <FileReference> AssemblySourceFiles = new List <FileReference>();

            AssemblySourceFiles.AddRange(ModuleFiles);
            AssemblySourceFiles.AddRange(TargetFiles);

            // Compile the assembly
            if (AssemblySourceFiles.Count > 0)
            {
                CompiledAssembly = DynamicCompilation.CompileAndLoadAssembly(AssemblyFileName, AssemblySourceFiles);
            }

            // Setup the module map
            foreach (FileReference ModuleFile in ModuleFiles)
            {
                string ModuleName = ModuleFile.GetFileNameWithoutAnyExtensions();
                if (!ModuleNameToModuleFile.ContainsKey(ModuleName))
                {
                    ModuleNameToModuleFile.Add(ModuleName, ModuleFile);
                }
            }

            // Setup the target map
            foreach (FileReference TargetFile in TargetFiles)
            {
                string TargetName = TargetFile.GetFileNameWithoutAnyExtensions();
                if (!TargetNameToTargetFile.ContainsKey(TargetName))
                {
                    TargetNameToTargetFile.Add(TargetName, TargetFile);
                }
            }

            /// Write any deprecation warnings for methods overriden from a base with the [ObsoleteOverride] attribute. Unlike the [Obsolete] attribute, this ensures the message
            /// is given because the method is implemented, not because it's called.
            if (CompiledAssembly != null)
            {
                foreach (Type CompiledType in CompiledAssembly.GetTypes())
                {
                    foreach (MethodInfo Method in CompiledType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                    {
                        ObsoleteOverrideAttribute Attribute = Method.GetCustomAttribute <ObsoleteOverrideAttribute>(true);
                        if (Attribute != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: {1}", Location, Attribute.Message);
                        }
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Constructor. Compiles a rules assembly from the given source files.
        /// </summary>
        /// <param name="Plugins">All the plugins included in this assembly</param>
        /// <param name="ModuleFiles">List of module files to compile</param>
        /// <param name="TargetFiles">List of target files to compile</param>
        /// <param name="ModuleFileToPluginInfo">Mapping of module file to the plugin that contains it</param>
        /// <param name="AssemblyFileName">The output path for the compiled assembly</param>
        /// <param name="bContainsEngineModules">Whether this assembly contains engine modules. Used to initialize the default value for ModuleRules.bTreatAsEngineModule.</param>
        /// <param name="bUseBackwardsCompatibleDefaults">Whether modules in this assembly should use backwards-compatible defaults.</param>
        /// <param name="bInstalled">Whether the modules and targets in this assembly are installed, and should be created with the bUsePrecompiled flag set</param>
        /// <param name="Parent">The parent rules assembly</param>
        public RulesAssembly(IReadOnlyList <PluginInfo> Plugins, List <FileReference> ModuleFiles, List <FileReference> TargetFiles, Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo, FileReference AssemblyFileName, bool bContainsEngineModules, bool bUseBackwardsCompatibleDefaults, bool bInstalled, RulesAssembly Parent)
        {
            this.Plugins = Plugins;
            this.ModuleFileToPluginInfo          = ModuleFileToPluginInfo;
            this.bContainsEngineModules          = bContainsEngineModules;
            this.bUseBackwardsCompatibleDefaults = bUseBackwardsCompatibleDefaults;
            this.bInstalled = bInstalled;
            this.Parent     = Parent;

            // Find all the source files
            List <FileReference> AssemblySourceFiles = new List <FileReference>();

            AssemblySourceFiles.AddRange(ModuleFiles);
            AssemblySourceFiles.AddRange(TargetFiles);

            // Compile the assembly
            if (AssemblySourceFiles.Count > 0)
            {
                List <string> PreprocessorDefines = GetPreprocessorDefinitions();
                CompiledAssembly = DynamicCompilation.CompileAndLoadAssembly(AssemblyFileName, AssemblySourceFiles, PreprocessorDefines: PreprocessorDefines);
            }

            // Setup the module map
            foreach (FileReference ModuleFile in ModuleFiles)
            {
                string ModuleName = ModuleFile.GetFileNameWithoutAnyExtensions();
                if (!ModuleNameToModuleFile.ContainsKey(ModuleName))
                {
                    ModuleNameToModuleFile.Add(ModuleName, ModuleFile);
                }
            }

            // Setup the target map
            foreach (FileReference TargetFile in TargetFiles)
            {
                string TargetName = TargetFile.GetFileNameWithoutAnyExtensions();
                if (!TargetNameToTargetFile.ContainsKey(TargetName))
                {
                    TargetNameToTargetFile.Add(TargetName, TargetFile);
                }
            }

            // Write any deprecation warnings for methods overriden from a base with the [ObsoleteOverride] attribute. Unlike the [Obsolete] attribute, this ensures the message
            // is given because the method is implemented, not because it's called.
            if (CompiledAssembly != null)
            {
                foreach (Type CompiledType in CompiledAssembly.GetTypes())
                {
                    foreach (MethodInfo Method in CompiledType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                    {
                        ObsoleteOverrideAttribute Attribute = Method.GetCustomAttribute <ObsoleteOverrideAttribute>(true);
                        if (Attribute != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: {1}", Location, Attribute.Message);
                        }
                    }
                    if (CompiledType.BaseType == typeof(ModuleRules))
                    {
                        ConstructorInfo Constructor = CompiledType.GetConstructor(new Type[] { typeof(TargetInfo) });
                        if (Constructor != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: Module constructors should take a ReadOnlyTargetRules argument (rather than a TargetInfo argument) and pass it to the base class constructor from 4.15 onwards. Please update the method signature.", Location);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Constructor. Compiles a rules assembly from the given source files.
        /// </summary>
        /// <param name="Plugins">All the plugins included in this assembly</param>
        /// <param name="ModuleFiles">List of module files to compile</param>
        /// <param name="TargetFiles">List of target files to compile</param>
        /// <param name="ModuleFileToPluginInfo">Mapping of module file to the plugin that contains it</param>
        /// <param name="AssemblyFileName">The output path for the compiled assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        public RulesAssembly(IReadOnlyList <PluginInfo> Plugins, List <FileReference> ModuleFiles, List <FileReference> TargetFiles, Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo, FileReference AssemblyFileName, RulesAssembly Parent)
        {
            this.Plugins = Plugins;
            this.ModuleFileToPluginInfo = ModuleFileToPluginInfo;
            this.Parent = Parent;

            // Find all the source files
            List <FileReference> AssemblySourceFiles = new List <FileReference>();

            AssemblySourceFiles.AddRange(ModuleFiles);
            AssemblySourceFiles.AddRange(TargetFiles);

            // Compile the assembly
            if (AssemblySourceFiles.Count > 0)
            {
                List <string> PreprocessorDefines = new List <string>();
                PreprocessorDefines.Add("WITH_FORWARDED_MODULE_RULES_CTOR");
                PreprocessorDefines.Add("WITH_FORWARDED_TARGET_RULES_CTOR");

                // Define macros for the UE4 version, starting with 4.17
                BuildVersion Version;
                if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version))
                {
                    for (int MinorVersion = 17; MinorVersion <= Version.MinorVersion; MinorVersion++)
                    {
                        PreprocessorDefines.Add(String.Format("UE_4_{0}_OR_LATER", MinorVersion));
                    }
                }

                CompiledAssembly = DynamicCompilation.CompileAndLoadAssembly(AssemblyFileName, AssemblySourceFiles, PreprocessorDefines: PreprocessorDefines);
            }

            // Setup the module map
            foreach (FileReference ModuleFile in ModuleFiles)
            {
                string ModuleName = ModuleFile.GetFileNameWithoutAnyExtensions();
                if (!ModuleNameToModuleFile.ContainsKey(ModuleName))
                {
                    ModuleNameToModuleFile.Add(ModuleName, ModuleFile);
                }
            }

            // Setup the target map
            foreach (FileReference TargetFile in TargetFiles)
            {
                string TargetName = TargetFile.GetFileNameWithoutAnyExtensions();
                if (!TargetNameToTargetFile.ContainsKey(TargetName))
                {
                    TargetNameToTargetFile.Add(TargetName, TargetFile);
                }
            }

            // Write any deprecation warnings for methods overriden from a base with the [ObsoleteOverride] attribute. Unlike the [Obsolete] attribute, this ensures the message
            // is given because the method is implemented, not because it's called.
            if (CompiledAssembly != null)
            {
                foreach (Type CompiledType in CompiledAssembly.GetTypes())
                {
                    foreach (MethodInfo Method in CompiledType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                    {
                        ObsoleteOverrideAttribute Attribute = Method.GetCustomAttribute <ObsoleteOverrideAttribute>(true);
                        if (Attribute != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: {1}", Location, Attribute.Message);
                        }
                    }
                    if (CompiledType.BaseType == typeof(ModuleRules))
                    {
                        ConstructorInfo Constructor = CompiledType.GetConstructor(new Type[] { typeof(TargetInfo) });
                        if (Constructor != null)
                        {
                            FileReference Location;
                            if (!TryGetFileNameFromType(CompiledType, out Location))
                            {
                                Location = new FileReference(CompiledAssembly.Location);
                            }
                            Log.TraceWarning("{0}: warning: Module constructors should take a ReadOnlyTargetRules argument (rather than a TargetInfo argument) and pass it to the base class constructor from 4.15 onwards. Please update the method signature.", Location);
                        }
                    }
                }
            }
        }