コード例 #1
0
        /// <summary>
        /// Creates the enterprise rules assembly
        /// </summary>
        /// <param name="bUsePrecompiled">Whether to use a precompiled enterprise and engine folder</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <returns>New rules assembly. Returns null if the enterprise directory is unavailable.</returns>
        public static RulesAssembly CreateEnterpriseRulesAssembly(bool bUsePrecompiled, bool bSkipCompile)
        {
            if (EnterpriseRulesAssembly == null)
            {
                RulesAssembly EngineAssembly = CreateEngineRulesAssembly(bUsePrecompiled, bSkipCompile);
                if (DirectoryReference.Exists(UnrealBuildTool.EnterpriseDirectory))
                {
                    RulesScope EnterpriseScope = new RulesScope("Enterprise", EngineAssembly.Scope);

                    //List<DirectoryReference> EnterpriseDirectories = new List<DirectoryReference>() { UnrealBuildTool.EnterpriseDirectory };

                    IReadOnlyList <PluginInfo> IncludedPlugins = Plugins.ReadEnterprisePlugins(UnrealBuildTool.EnterpriseDirectory);
                    EnterpriseRulesAssembly = CreateEngineOrEnterpriseRulesAssembly(EnterpriseScope, new List <DirectoryReference>()
                    {
                        UnrealBuildTool.EnterpriseDirectory
                    },
                                                                                    ProjectFileGenerator.EnterpriseProjectFileNameBase, IncludedPlugins, UnrealBuildTool.IsEnterpriseInstalled() || bUsePrecompiled, bSkipCompile, EngineAssembly);
                }
                else
                {
                    // If we're asked for the enterprise rules assembly but the enterprise directory is missing, fallback on the engine rules assembly
                    Log.TraceWarning("Trying to build an enterprise target but the enterprise directory is missing. Falling back on engine components only.");
                    return(EngineAssembly);
                }
            }

            return(EnterpriseRulesAssembly);
        }
コード例 #2
0
        /// <summary>
        /// Creates a rules assembly with the given parameters.
        /// </summary>
        /// <param name="PluginFileName">The plugin file to create rules for</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        /// <param name="bContainsEngineModules">Whether the plugin contains engine modules. Used to initialize the default value for ModuleRules.bTreatAsEngineModule.</param>
        /// <returns>The new rules assembly</returns>
        public static RulesAssembly CreatePluginRulesAssembly(FileReference PluginFileName, bool bSkipCompile, RulesAssembly Parent, bool bContainsEngineModules)
        {
            // Check if there's an existing assembly for this project
            RulesAssembly PluginRulesAssembly;

            if (!LoadedAssemblyMap.TryGetValue(PluginFileName, out PluginRulesAssembly))
            {
                // Find all the rules source files
                Dictionary <FileReference, ModuleRulesContext> ModuleFiles = new Dictionary <FileReference, ModuleRulesContext>();
                List <FileReference> TargetFiles = new List <FileReference>();

                // Create a list of plugins for this assembly. If it already exists in the parent assembly, just create an empty assembly.
                List <PluginInfo> ForeignPlugins = new List <PluginInfo>();
                if (Parent == null || !Parent.EnumeratePlugins().Any(x => x.File == PluginFileName))
                {
                    ForeignPlugins.Add(new PluginInfo(PluginFileName, PluginType.External));
                }

                // Create a new scope for the plugin. It should not reference anything else.
                RulesScope Scope = new RulesScope("Plugin", Parent.Scope);

                // Find all the modules
                ModuleRulesContext PluginModuleContext = new ModuleRulesContext(Scope, PluginFileName.Directory);
                PluginModuleContext.bClassifyAsGameModuleForUHT = !bContainsEngineModules;
                FindModuleRulesForPlugins(ForeignPlugins, PluginModuleContext, ModuleFiles);

                // Compile the assembly
                FileReference AssemblyFileName = FileReference.Combine(PluginFileName.Directory, "Intermediate", "Build", "BuildRules", Path.GetFileNameWithoutExtension(PluginFileName.FullName) + "ModuleRules" + FrameworkAssemblyExtension);
                PluginRulesAssembly = new RulesAssembly(Scope, new List <DirectoryReference> {
                    PluginFileName.Directory
                }, ForeignPlugins, ModuleFiles, TargetFiles, AssemblyFileName, bContainsEngineModules, DefaultBuildSettings: null, bReadOnly: false, bSkipCompile: bSkipCompile, Parent: Parent);
                LoadedAssemblyMap.Add(PluginFileName, PluginRulesAssembly);
            }
            return(PluginRulesAssembly);
        }
コード例 #3
0
 /// <summary>
 /// Checks whether this scope contains another scope
 /// </summary>
 /// <param name="Other">The other scope to check</param>
 /// <returns>True if this scope contains the other scope</returns>
 public bool Contains(RulesScope Other)
 {
     for (RulesScope Scope = this; Scope != null; Scope = Scope.Parent)
     {
         if (Scope == Other)
         {
             return(true);
         }
     }
     return(false);
 }
コード例 #4
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="Other">The context to copy from</param>
 public ModuleRulesContext(ModuleRulesContext Other)
 {
     this.Scope = Other.Scope;
     this.DefaultOutputBaseDir = Other.DefaultOutputBaseDir;
     this.Plugin                      = Other.Plugin;
     this.bCanHotReload               = Other.bCanHotReload;
     this.bCanBuildDebugGame          = Other.bCanBuildDebugGame;
     this.bCanUseForSharedPCH         = Other.bCanUseForSharedPCH;
     this.bClassifyAsGameModuleForUHT = Other.bClassifyAsGameModuleForUHT;
     this.DefaultUHTModuleType        = Other.DefaultUHTModuleType;
 }
コード例 #5
0
        /// <summary>
        /// Creates the engine rules assembly
        /// </summary>
        /// <param name="bUsePrecompiled">Whether to use a precompiled engine</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <returns>New rules assembly</returns>
        public static RulesAssembly CreateEngineRulesAssembly(bool bUsePrecompiled, bool bSkipCompile)
        {
            if (EngineRulesAssembly == null)
            {
                List <PluginInfo> IncludedPlugins = new List <PluginInfo>();

                // search for all engine plugins
                IncludedPlugins.AddRange(Plugins.ReadEnginePlugins(UnrealBuildTool.EngineDirectory));

                RulesScope EngineScope = new RulesScope("Engine", null);

                EngineRulesAssembly = CreateEngineOrEnterpriseRulesAssembly(EngineScope, UnrealBuildTool.GetAllEngineDirectories().ToList(), ProjectFileGenerator.EngineProjectFileNameBase, IncludedPlugins, UnrealBuildTool.IsEngineInstalled() || bUsePrecompiled, bSkipCompile, null);
            }
            return(EngineRulesAssembly);
        }
コード例 #6
0
        /// <summary>
        /// Creates the engine rules assembly
        /// </summary>
        /// <param name="bUsePrecompiled">Whether to use a precompiled engine</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <returns>New rules assembly</returns>
        public static RulesAssembly CreateEngineRulesAssembly(bool bUsePrecompiled, bool bSkipCompile)
        {
            if (EngineRulesAssembly == null)
            {
                List <PluginInfo> IncludedPlugins = new List <PluginInfo>();

                // look in the platform extensions engine directories for plugins
                List <DirectoryReference> RootDirectories = new List <DirectoryReference>();
                RootDirectories.AddRange(UnrealBuildTool.GetAllEngineDirectories());

                // search for all engine plugins
                foreach (DirectoryReference RootDir in RootDirectories)
                {
                    IncludedPlugins.AddRange(Plugins.ReadEnginePlugins(RootDir));
                }

                RulesScope EngineScope = new RulesScope("Engine", null);

                EngineRulesAssembly = CreateEngineOrEnterpriseRulesAssembly(EngineScope, RootDirectories, ProjectFileGenerator.EngineProjectFileNameBase, IncludedPlugins, UnrealBuildTool.IsEngineInstalled() || bUsePrecompiled, bSkipCompile, null);
            }
            return(EngineRulesAssembly);
        }
コード例 #7
0
        /// <summary>
        /// Creates a rules assembly with the given parameters.
        /// </summary>
        /// <param name="ProjectFileName">The project file to create rules for. Null for the engine.</param>
        /// <param name="bUsePrecompiled">Whether to use a precompiled engine</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <returns>New rules assembly</returns>
        public static RulesAssembly CreateProjectRulesAssembly(FileReference ProjectFileName, bool bUsePrecompiled, bool bSkipCompile)
        {
            // Check if there's an existing assembly for this project
            RulesAssembly ProjectRulesAssembly;

            if (!LoadedAssemblyMap.TryGetValue(ProjectFileName, out ProjectRulesAssembly))
            {
                ProjectDescriptor Project = ProjectDescriptor.FromFile(ProjectFileName);

                // Create the parent assembly
                RulesAssembly Parent;
                if (Project.IsEnterpriseProject)
                {
                    Parent = CreateEnterpriseRulesAssembly(bUsePrecompiled, bSkipCompile);
                }
                else
                {
                    Parent = CreateEngineRulesAssembly(bUsePrecompiled, bSkipCompile);
                }

                DirectoryReference MainProjectDirectory = ProjectFileName.Directory;
                //DirectoryReference MainProjectSourceDirectory = DirectoryReference.Combine(MainProjectDirectory, "Source");

                // Create a scope for things in this assembly
                RulesScope Scope = new RulesScope("Project", Parent.Scope);

                // Create a new context for modules created by this assembly
                ModuleRulesContext DefaultModuleContext = new ModuleRulesContext(Scope, MainProjectDirectory);
                DefaultModuleContext.bCanBuildDebugGame          = true;
                DefaultModuleContext.bCanHotReload               = true;
                DefaultModuleContext.bClassifyAsGameModuleForUHT = true;
                DefaultModuleContext.bCanUseForSharedPCH         = false;

                // gather modules from project and platforms
                Dictionary <FileReference, ModuleRulesContext> ModuleFiles = new Dictionary <FileReference, ModuleRulesContext>();
                List <FileReference> TargetFiles = new List <FileReference>();

                // Find all the project directories
                List <DirectoryReference> ProjectDirectories = new List <DirectoryReference>(UnrealBuildTool.GetAllProjectDirectories(ProjectFileName));
                if (Project.AdditionalRootDirectories != null)
                {
                    ProjectDirectories.AddRange(Project.AdditionalRootDirectories);
                }

                // Find all the rules/plugins under the project source directories
                foreach (DirectoryReference ProjectDirectory in ProjectDirectories)
                {
                    DirectoryReference ProjectSourceDirectory = DirectoryReference.Combine(ProjectDirectory, "Source");

                    AddModuleRulesWithContext(ProjectSourceDirectory, DefaultModuleContext, ModuleFiles);
                    TargetFiles.AddRange(FindAllRulesFiles(ProjectSourceDirectory, RulesFileType.Target));
                }

                // Find all the project plugins
                List <PluginInfo> ProjectPlugins = new List <PluginInfo>();
                ProjectPlugins.AddRange(Plugins.ReadProjectPlugins(MainProjectDirectory));

                // Add the project's additional plugin directories plugins too
                if (Project.AdditionalPluginDirectories != null)
                {
                    foreach (DirectoryReference AdditionalPluginDirectory in Project.AdditionalPluginDirectories)
                    {
                        ProjectPlugins.AddRange(Plugins.ReadAdditionalPlugins(AdditionalPluginDirectory));
                    }
                }

                // Find all the plugin module rules
                FindModuleRulesForPlugins(ProjectPlugins, DefaultModuleContext, ModuleFiles);

                // Add the games project's intermediate source folder
                DirectoryReference ProjectIntermediateSourceDirectory = DirectoryReference.Combine(MainProjectDirectory, "Intermediate", "Source");
                if (DirectoryReference.Exists(ProjectIntermediateSourceDirectory))
                {
                    AddModuleRulesWithContext(ProjectIntermediateSourceDirectory, DefaultModuleContext, ModuleFiles);
                    TargetFiles.AddRange(FindAllRulesFiles(ProjectIntermediateSourceDirectory, RulesFileType.Target));
                }

                // Compile the assembly. If there are no module or target files, just use the parent assembly.
                FileReference AssemblyFileName = FileReference.Combine(MainProjectDirectory, "Intermediate", "Build", "BuildRules", ProjectFileName.GetFileNameWithoutExtension() + "ModuleRules" + FrameworkAssemblyExtension);
                if (ModuleFiles.Count == 0 && TargetFiles.Count == 0)
                {
                    ProjectRulesAssembly = Parent;
                }
                else
                {
                    ProjectRulesAssembly = new RulesAssembly(Scope, new List <DirectoryReference> {
                        MainProjectDirectory
                    }, ProjectPlugins, ModuleFiles, TargetFiles, AssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: null, bReadOnly: UnrealBuildTool.IsProjectInstalled(), bSkipCompile: bSkipCompile, Parent: Parent);
                }
                LoadedAssemblyMap.Add(ProjectFileName, ProjectRulesAssembly);
            }
            return(ProjectRulesAssembly);
        }
コード例 #8
0
        /// <summary>
        /// Creates a rules assembly
        /// </summary>
        /// <param name="Scope">Scope for items created from this assembly</param>
        /// <param name="RootDirectories">The root directories to create rules for</param>
        /// <param name="AssemblyPrefix">A prefix for the assembly file name</param>
        /// <param name="Plugins">List of plugins to include in this assembly</param>
        /// <param name="bReadOnly">Whether the assembly should be marked as installed</param>
        /// <param name="bSkipCompile">Whether to skip compilation for this assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        /// <returns>New rules assembly</returns>
        private static RulesAssembly CreateEngineOrEnterpriseRulesAssembly(RulesScope Scope, List <DirectoryReference> RootDirectories, string AssemblyPrefix, IReadOnlyList <PluginInfo> Plugins, bool bReadOnly, bool bSkipCompile, RulesAssembly Parent)
        {
            // Scope hierarchy
            RulesScope PluginsScope  = new RulesScope(Scope.Name + " Plugins", Scope);
            RulesScope ProgramsScope = new RulesScope(Scope.Name + " Programs", PluginsScope);

            // Find the shared modules, excluding the programs directory. These are used to create an assembly with the bContainsEngineModules flag set to true.
            Dictionary <FileReference, ModuleRulesContext> ModuleFileToContext = new Dictionary <FileReference, ModuleRulesContext>();
            ModuleRulesContext DefaultModuleContext = new ModuleRulesContext(Scope, RootDirectories[0]);

            foreach (DirectoryReference RootDirectory in RootDirectories)
            {
                using (Timeline.ScopeEvent("Finding engine modules"))
                {
                    DirectoryReference SourceDirectory = DirectoryReference.Combine(RootDirectory, "Source");

                    AddEngineModuleRulesWithContext(SourceDirectory, "Runtime", DefaultModuleContext, UHTModuleType.EngineRuntime, ModuleFileToContext);
                    AddEngineModuleRulesWithContext(SourceDirectory, "Developer", DefaultModuleContext, UHTModuleType.EngineDeveloper, ModuleFileToContext);
                    AddEngineModuleRulesWithContext(SourceDirectory, "Editor", DefaultModuleContext, UHTModuleType.EngineEditor, ModuleFileToContext);
                    AddEngineModuleRulesWithContext(SourceDirectory, "ThirdParty", DefaultModuleContext, UHTModuleType.EngineThirdParty, ModuleFileToContext);
                }
            }

            // Add all the plugin modules too (don't need to loop over RootDirectories since the plugins come in already found
            using (Timeline.ScopeEvent("Finding plugin modules"))
            {
                ModuleRulesContext PluginsModuleContext = new ModuleRulesContext(PluginsScope, RootDirectories[0]);
                FindModuleRulesForPlugins(Plugins, PluginsModuleContext, ModuleFileToContext);
            }

            // Get the path to store any generated assemblies
            DirectoryReference AssemblyDir = RootDirectories[0];

            if (UnrealBuildTool.IsFileInstalled(FileReference.Combine(AssemblyDir, AssemblyPrefix)))
            {
                DirectoryReference UserDir = Utils.GetUserSettingDirectory();
                if (UserDir != null)
                {
                    ReadOnlyBuildVersion Version = ReadOnlyBuildVersion.Current;
                    AssemblyDir = DirectoryReference.Combine(UserDir, "UnrealEngine", String.Format("{0}.{1}", Version.MajorVersion, Version.MinorVersion));
                }
            }

            // Create the assembly
            FileReference EngineAssemblyFileName = FileReference.Combine(AssemblyDir, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "Rules" + FrameworkAssemblyExtension);
            RulesAssembly EngineAssembly         = new RulesAssembly(Scope, RootDirectories, Plugins, ModuleFileToContext, new List <FileReference>(), EngineAssemblyFileName, bContainsEngineModules: true, DefaultBuildSettings: BuildSettingsVersion.Latest, bReadOnly: bReadOnly, bSkipCompile: bSkipCompile, Parent: Parent);

            List <FileReference> ProgramTargetFiles = new List <FileReference>();
            Dictionary <FileReference, ModuleRulesContext> ProgramModuleFiles = new Dictionary <FileReference, ModuleRulesContext>();

            foreach (DirectoryReference RootDirectory in RootDirectories)
            {
                DirectoryReference SourceDirectory   = DirectoryReference.Combine(RootDirectory, "Source");
                DirectoryReference ProgramsDirectory = DirectoryReference.Combine(SourceDirectory, "Programs");

                // Also create a scope for them, and update the UHT module type
                ModuleRulesContext ProgramsModuleContext = new ModuleRulesContext(ProgramsScope, RootDirectory);
                ProgramsModuleContext.DefaultUHTModuleType = UHTModuleType.Program;

                using (Timeline.ScopeEvent("Finding program modules"))
                {
                    // Find all the rules files
                    AddModuleRulesWithContext(ProgramsDirectory, ProgramsModuleContext, ProgramModuleFiles);
                }

                using (Timeline.ScopeEvent("Finding program targets"))
                {
                    ProgramTargetFiles.AddRange(FindAllRulesFiles(SourceDirectory, RulesFileType.Target));
                }
            }

            // Create a path to the assembly that we'll either load or compile
            FileReference ProgramAssemblyFileName = FileReference.Combine(AssemblyDir, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "ProgramRules" + FrameworkAssemblyExtension);
            RulesAssembly ProgramAssembly         = new RulesAssembly(ProgramsScope, RootDirectories, new List <PluginInfo>().AsReadOnly(), ProgramModuleFiles, ProgramTargetFiles, ProgramAssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: BuildSettingsVersion.Latest, bReadOnly: bReadOnly, bSkipCompile: bSkipCompile, Parent: EngineAssembly);

            // Return the combined assembly
            return(ProgramAssembly);
        }
コード例 #9
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="Name">Name of this scope</param>
 /// <param name="Parent">The parent scope</param>
 public RulesScope(string Name, RulesScope Parent)
 {
     this.Name   = Name;
     this.Parent = Parent;
 }
コード例 #10
0
        /// <summary>
        /// Constructor. Compiles a rules assembly from the given source files.
        /// </summary>
        /// <param name="Scope">The scope of items created by this assembly</param>
        /// <param name="BaseDir">The base directory for this assembly</param>
        /// <param name="Plugins">All the plugins included in this assembly</param>
        /// <param name="ModuleFileToContext">List of module files to compile</param>
        /// <param name="TargetFiles">List of target files to compile</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="DefaultBuildSettings">Optional override for the default build settings version for modules created from this assembly.</param>
        /// <param name="bReadOnly">Whether the modules and targets in this assembly are installed, and should be created with the bUsePrecompiled flag set</param>
        /// <param name="bSkipCompile">Whether to skip compiling this assembly</param>
        /// <param name="Parent">The parent rules assembly</param>
        internal RulesAssembly(RulesScope Scope, DirectoryReference BaseDir, IReadOnlyList <PluginInfo> Plugins, Dictionary <FileReference, ModuleRulesContext> ModuleFileToContext, List <FileReference> TargetFiles, FileReference AssemblyFileName, bool bContainsEngineModules, BuildSettingsVersion?DefaultBuildSettings, bool bReadOnly, bool bSkipCompile, RulesAssembly Parent)
        {
            this.Scope                  = Scope;
            this.BaseDir                = BaseDir;
            this.Plugins                = Plugins;
            this.ModuleFileToContext    = ModuleFileToContext;
            this.bContainsEngineModules = bContainsEngineModules;
            this.DefaultBuildSettings   = DefaultBuildSettings;
            this.bReadOnly              = bReadOnly;
            this.Parent                 = Parent;

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

            AssemblySourceFiles.UnionWith(ModuleFileToContext.Keys);
            AssemblySourceFiles.UnionWith(TargetFiles);

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

            // Setup the module map
            foreach (FileReference ModuleFile in ModuleFileToContext.Keys)
            {
                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);
                        }
                    }
                }
            }
        }
コード例 #11
0
 /// <summary>
 /// Constructor
 /// </summary>
 public ModuleRulesContext(RulesScope Scope, DirectoryReference DefaultOutputBaseDir)
 {
     this.Scope = Scope;
     this.DefaultOutputBaseDir = DefaultOutputBaseDir;
     this.bCanUseForSharedPCH  = true;
 }