public UEBuildClient(TargetDescriptor InDesc, TargetRules InRulesObject, RulesAssembly InRulesAssembly, FileReference InTargetCsFilename)
			: base(InDesc, InRulesObject, InRulesAssembly, "UE4Client", InTargetCsFilename)
		{
			if (ShouldCompileMonolithic())
			{
				if (!UnrealBuildTool.IsDesktopPlatform(Platform))
				{
					// We are compiling for a console...
					// We want the output to go into the <GAME>\Binaries folder
					if (!InRulesObject.bOutputToEngineBinaries)
					{
						OutputPaths = OutputPaths.Select(Path => new FileReference(Path.FullName.Replace("Engine\\Binaries", InDesc.TargetName + "\\Binaries"))).ToList();
					}
				}
			}
		}
		private static void ConditionallyCompileAndLoadRulesAssembly()
		{
			if( String.IsNullOrEmpty( AssemblyName ) )
			{
				throw new BuildException( "Module or target rules data was requested, but not rules assembly name was set yet!" );
			}

			// Did we already have a RulesAssembly and cached data about rules files and modules?  If so, then we'll
			// check to see if we need to flush everything and start over.  This can happen if UBT wants to built
			// different targets in a single invocation, or when generating project files before or after building
			// a target
			LoadedAssemblyData LoadedAssembly;
			if (LoadedAssemblyMap.TryGetValue(AssemblyName, out LoadedAssembly))
			{
				RulesAssembly	ExistingAssembly    = LoadedAssembly.ExistingAssembly;
				List<string>	ExistingGameFolders = LoadedAssembly.ExistingGameFolders;

				// Make sure the game folder list wasn't changed since we last compiled this assembly
				if( ExistingGameFolders != AllGameFolders )	// Quick-check pointers first to avoid iterating
				{
					var AnyGameFoldersDifferent = false;
					if( ExistingGameFolders.Count != AllGameFolders.Count )
					{
						AnyGameFoldersDifferent = true;
					}
					else
					{
						foreach( var NewGameFolder in AllGameFolders )
						{
							if( !ExistingGameFolders.Contains( NewGameFolder ) )
							{
								AnyGameFoldersDifferent = true;
								break;
							}
						}
						foreach( var OldGameFolder in ExistingGameFolders )
						{
							if( !AllGameFolders.Contains( OldGameFolder ) )
							{
								AnyGameFoldersDifferent = true;
								break;
							}
						}
					}

					if( AnyGameFoldersDifferent )
					{
						throw new BuildException( "SetAssemblyNameAndGameFolders() was called with an assembly name that had already been compiled, but with DIFFERENT game folders.  This is not allowed." );
					}
				}

				return;
			}

			var AdditionalSearchPaths = new List<string>();

			if (UnrealBuildTool.HasUProjectFile())
			{
				// Add the game project's source folder
				var ProjectSourceDirectory = Path.Combine( UnrealBuildTool.GetUProjectPath(), "Source" );
				if( Directory.Exists( ProjectSourceDirectory ) )
				{
					AdditionalSearchPaths.Add( ProjectSourceDirectory );
				}
				// Add the games project's intermediate source folder
				var ProjectIntermediateSourceDirectory = Path.Combine(UnrealBuildTool.GetUProjectPath(), "Intermediate", "Source");
				if (Directory.Exists(ProjectIntermediateSourceDirectory))
				{
					AdditionalSearchPaths.Add(ProjectIntermediateSourceDirectory);
				}
			}
			var ModuleFileNames = FindAllRulesSourceFiles(RulesFileType.Module, AdditionalSearchPaths);

			var AssemblySourceFiles = new List<string>();
			AssemblySourceFiles.AddRange( ModuleFileNames );
			if( AssemblySourceFiles.Count == 0 )
			{
				throw new BuildException("No module rules source files were found in any of the module base directories!");
			}
			var TargetFileNames = FindAllRulesSourceFiles(RulesFileType.Target, AdditionalSearchPaths);
			AssemblySourceFiles.AddRange( TargetFileNames );

			// Create a path to the assembly that we'll either load or compile
			string BaseIntermediatePath = UnrealBuildTool.HasUProjectFile() ?
				Path.Combine(UnrealBuildTool.GetUProjectPath(), BuildConfiguration.BaseIntermediateFolder) : BuildConfiguration.BaseIntermediatePath;

			string OutputAssemblyPath = Path.GetFullPath(Path.Combine(BaseIntermediatePath, "BuildRules", AssemblyName + ".dll"));

			RulesAssembly Rules = new RulesAssembly(DynamicCompilation.CompileAndLoadAssembly( OutputAssemblyPath, AssemblySourceFiles ));

			// Setup the module map
			foreach( var CurModuleFileName in ModuleFileNames )
			{
				var CleanFileName = Utils.CleanDirectorySeparators( CurModuleFileName );
				var ModuleName = Path.GetFileNameWithoutExtension( Path.GetFileNameWithoutExtension( CleanFileName ) );	// Strip both extensions
				if( !Rules.ModuleNameToModuleFileMap.ContainsKey( ModuleName ) )
				{
					Rules.ModuleNameToModuleFileMap.Add( ModuleName, CurModuleFileName );
				}
			}

			// Setup the target map
			foreach( var CurTargetFileName in TargetFileNames )
			{
				var CleanFileName = Utils.CleanDirectorySeparators( CurTargetFileName );
				var TargetName = Path.GetFileNameWithoutExtension( Path.GetFileNameWithoutExtension( CleanFileName ) );	// Strip both extensions
				if( !Rules.TargetNameToTargetFileMap.ContainsKey( TargetName ) )
				{
					Rules.TargetNameToTargetFileMap.Add( TargetName, CurTargetFileName );
				}
			}

			// Remember that we loaded this assembly
			var RulesAssemblyName = Path.GetFileNameWithoutExtension( Rules.Rules.Location );
			LoadedAssemblyMap[RulesAssemblyName] = new LoadedAssemblyData(Rules, AllGameFolders);
		}
			public LoadedAssemblyData(RulesAssembly InAssembly, List<string> InGameFolders)
			{
				ExistingAssembly    = InAssembly;
				ExistingGameFolders = InGameFolders;
			}
		/// <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);
				}
			}
		}
		public UEBuildEditor(TargetDescriptor InDesc, TargetRules InRulesObject, RulesAssembly InRulesAssembly, FileReference InTargetCsFilename)
			: base(InDesc, InRulesObject, InRulesAssembly, "UE4Editor", InTargetCsFilename)
		{
		}
		/// <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="ForeignPlugins">List of foreign plugin folders to include in the assembly. May be null.</param>
		public static RulesAssembly CreateProjectRulesAssembly(FileReference ProjectFileName)
		{
			// Check if there's an existing assembly for this project
			RulesAssembly ProjectRulesAssembly;
			if (!LoadedAssemblyMap.TryGetValue(ProjectFileName, out ProjectRulesAssembly))
			{
				// Create the engine rules assembly
				RulesAssembly Parent = CreateEngineRulesAssembly();

				// Find all the rules under the project source directory
				DirectoryReference ProjectDirectory = ProjectFileName.Directory;
				DirectoryReference ProjectSourceDirectory = DirectoryReference.Combine(ProjectDirectory, "Source");
				List<FileReference> ModuleFiles = new List<FileReference>(FindAllRulesFiles(ProjectSourceDirectory, RulesFileType.Module));
				List<FileReference> TargetFiles = new List<FileReference>(FindAllRulesFiles(ProjectSourceDirectory, RulesFileType.Target));

				// Find all the project plugins
				List<PluginInfo> ProjectPlugins = new List<PluginInfo>(Plugins.ReadProjectPlugins(ProjectFileName.Directory));
                ProjectDescriptor Project = ProjectDescriptor.FromFile(ProjectFileName.FullName);
                // Add the project's additional plugin directories plugins too
                ProjectPlugins.AddRange(Plugins.ReadAdditionalPlugins(Project.AdditionalPluginDirectories));
                Dictionary<FileReference, PluginInfo> ModuleFileToPluginInfo = new Dictionary<FileReference, PluginInfo>();
				FindModuleRulesForPlugins(ProjectPlugins, ModuleFiles, ModuleFileToPluginInfo);

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

				// Compile the assembly
				FileReference AssemblyFileName = FileReference.Combine(ProjectDirectory, BuildConfiguration.BaseIntermediateFolder, "BuildRules", ProjectFileName.GetFileNameWithoutExtension() + "ModuleRules.dll");
				ProjectRulesAssembly = new RulesAssembly(ProjectPlugins, ModuleFiles, TargetFiles, ModuleFileToPluginInfo, AssemblyFileName, Parent);
				LoadedAssemblyMap.Add(ProjectFileName, ProjectRulesAssembly);
			}
			return ProjectRulesAssembly;
		}
		/// <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="ForeignPlugins">List of foreign plugin folders to include in the assembly. May be null.</param>
		public static RulesAssembly CreatePluginRulesAssembly(FileReference PluginFileName, RulesAssembly Parent)
		{
			// Check if there's an existing assembly for this project
			RulesAssembly PluginRulesAssembly;
			if (!LoadedAssemblyMap.TryGetValue(PluginFileName, out PluginRulesAssembly))
			{
				// Find all the rules source files
				List<FileReference> ModuleFiles = new List<FileReference>();
				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, PluginLoadedFrom.GameProject));
				}

				// Find all the modules
				Dictionary<FileReference, PluginInfo> ModuleFileToPluginInfo = new Dictionary<FileReference, PluginInfo>();
				FindModuleRulesForPlugins(ForeignPlugins, ModuleFiles, ModuleFileToPluginInfo);

				// Compile the assembly
				FileReference AssemblyFileName = FileReference.Combine(PluginFileName.Directory, BuildConfiguration.BaseIntermediateFolder, "BuildRules", Path.GetFileNameWithoutExtension(PluginFileName.FullName) + "ModuleRules.dll");
				PluginRulesAssembly = new RulesAssembly(ForeignPlugins, ModuleFiles, TargetFiles, ModuleFileToPluginInfo, AssemblyFileName, Parent);
				LoadedAssemblyMap.Add(PluginFileName, PluginRulesAssembly);
			}
			return PluginRulesAssembly;
		}
        /// <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, PluginFileName.Directory, ForeignPlugins, ModuleFiles, TargetFiles, AssemblyFileName, bContainsEngineModules, DefaultBuildSettings: null, bReadOnly: false, bSkipCompile: bSkipCompile, Parent: Parent);
                LoadedAssemblyMap.Add(PluginFileName, PluginRulesAssembly);
            }
            return(PluginRulesAssembly);
        }
		/// <summary>
		/// Creates the engine rules assembly
		/// </summary>
		/// <param name="ForeignPlugins">List of plugins to include in this assembly</param>
		/// <returns>New rules assembly</returns>
		public static RulesAssembly CreateEngineRulesAssembly()
		{
			if (EngineRulesAssembly == null)
			{
				// Find all the rules files
				List<FileReference> ModuleFiles = new List<FileReference>(FindAllRulesFiles(UnrealBuildTool.EngineSourceDirectory, RulesFileType.Module));
				List<FileReference> TargetFiles = new List<FileReference>(FindAllRulesFiles(UnrealBuildTool.EngineSourceDirectory, RulesFileType.Target));

				// Add all the plugin modules too
				IReadOnlyList<PluginInfo> EnginePlugins = Plugins.ReadEnginePlugins(UnrealBuildTool.EngineDirectory);
				Dictionary<FileReference, PluginInfo> ModuleFileToPluginInfo = new Dictionary<FileReference, PluginInfo>();
				FindModuleRulesForPlugins(EnginePlugins, ModuleFiles, ModuleFileToPluginInfo);

				// Create a path to the assembly that we'll either load or compile
				FileReference AssemblyFileName = FileReference.Combine(UnrealBuildTool.EngineDirectory, BuildConfiguration.BaseIntermediateFolder, "BuildRules", "UE4Rules.dll");
				EngineRulesAssembly = new RulesAssembly(EnginePlugins, ModuleFiles, TargetFiles, ModuleFileToPluginInfo, AssemblyFileName, null);
			}
			return EngineRulesAssembly;
		}
        /// <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);
            }

            // Create the assembly
            FileReference EngineAssemblyFileName = FileReference.Combine(RootDirectories[0], "Intermediate", "Build", "BuildRules", AssemblyPrefix + "Rules" + FrameworkAssemblyExtension);
            RulesAssembly EngineAssembly         = new RulesAssembly(Scope, RootDirectories[0], 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(RootDirectories[0], "Intermediate", "Build", "BuildRules", AssemblyPrefix + "ProgramRules" + FrameworkAssemblyExtension);
            RulesAssembly ProgramAssembly         = new RulesAssembly(ProgramsScope, RootDirectories[0], new List <PluginInfo>().AsReadOnly(), ProgramModuleFiles, ProgramTargetFiles, ProgramAssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: BuildSettingsVersion.Latest, bReadOnly: bReadOnly, bSkipCompile: bSkipCompile, Parent: EngineAssembly);

            // Return the combined assembly
            return(ProgramAssembly);
        }
        /// <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 rules/plugins under the project source directories
                foreach (DirectoryReference ProjectDirectory in UnrealBuildTool.GetAllProjectDirectories(ProjectFileName))
                {
                    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 (string AdditionalPluginDirectory in Project.AdditionalPluginDirectories)
                    {
                        ProjectPlugins.AddRange(Plugins.ReadAdditionalPlugins(MainProjectDirectory, 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, MainProjectDirectory, ProjectPlugins, ModuleFiles, TargetFiles, AssemblyFileName, bContainsEngineModules: false, DefaultBuildSettings: null, bReadOnly: UnrealBuildTool.IsProjectInstalled(), bSkipCompile: bSkipCompile, Parent: Parent);
                }
                LoadedAssemblyMap.Add(ProjectFileName, ProjectRulesAssembly);
            }
            return(ProjectRulesAssembly);
        }
Beispiel #12
0
        /// <summary>
        /// Creates a rules assembly with the given parameters.
        /// </summary>
        /// <param name="PluginFileName">The plugin file to create rules for</param>
        /// <param name="Parent">The parent rules assembly</param>
        /// <returns>The new rules assembly</returns>
        public static RulesAssembly CreatePluginRulesAssembly(FileReference PluginFileName, RulesAssembly Parent)
        {
            // Check if there's an existing assembly for this project
            RulesAssembly PluginRulesAssembly;

            if (!LoadedAssemblyMap.TryGetValue(PluginFileName, out PluginRulesAssembly))
            {
                // Find all the rules source files
                List <FileReference> ModuleFiles = new List <FileReference>();
                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, PluginLoadedFrom.GameProject));
                }

                // Find all the modules
                Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo = new Dictionary <FileReference, PluginInfo>();
                FindModuleRulesForPlugins(ForeignPlugins, ModuleFiles, ModuleFileToPluginInfo);

                // Compile the assembly
                FileReference AssemblyFileName = FileReference.Combine(PluginFileName.Directory, "Intermediate", "Build", "BuildRules", Path.GetFileNameWithoutExtension(PluginFileName.FullName) + "ModuleRules.dll");
                PluginRulesAssembly = new RulesAssembly(ForeignPlugins, ModuleFiles, TargetFiles, ModuleFileToPluginInfo, AssemblyFileName, Parent);
                LoadedAssemblyMap.Add(PluginFileName, PluginRulesAssembly);
            }
            return(PluginRulesAssembly);
        }
Beispiel #13
0
        /// <summary>
        /// Creates a rules assembly
        /// </summary>
        /// <param name="RootDirectory">The root directory 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="bInstalled">Whether the assembly should be marked as installed</param>
        /// <param name="Parent">The parent rules assembly</param>
        /// <returns>New rules assembly</returns>
        private static RulesAssembly CreateEngineOrEnterpriseRulesAssembly(DirectoryReference RootDirectory, string AssemblyPrefix, IReadOnlyList <PluginInfo> Plugins, bool bInstalled, RulesAssembly Parent)
        {
            DirectoryReference SourceDirectory   = DirectoryReference.Combine(RootDirectory, "Source");
            DirectoryReference ProgramsDirectory = DirectoryReference.Combine(SourceDirectory, "Programs");

            // Find the shared modules, excluding the programs directory. These are used to create an assembly with the bContainsEngineModules flag set to true.
            List <FileReference> EngineModuleFiles = new List <FileReference>();

            foreach (DirectoryReference SubDirectory in DirectoryLookupCache.EnumerateDirectories(SourceDirectory))
            {
                if (SubDirectory != ProgramsDirectory)
                {
                    EngineModuleFiles.AddRange(FindAllRulesFiles(SubDirectory, RulesFileType.Module));
                }
            }

            // Add all the plugin modules too
            Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo = new Dictionary <FileReference, PluginInfo>();

            FindModuleRulesForPlugins(Plugins, EngineModuleFiles, ModuleFileToPluginInfo);

            // Create the assembly
            FileReference EngineAssemblyFileName = FileReference.Combine(RootDirectory, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "Rules" + FrameworkAssemblyExtension);
            RulesAssembly EngineAssembly         = new RulesAssembly(Plugins, EngineModuleFiles, new List <FileReference>(), ModuleFileToPluginInfo, EngineAssemblyFileName, bContainsEngineModules: true, bUseBackwardsCompatibleDefaults: false, bInstalled: bInstalled, Parent: Parent);

            // Find all the rules files
            List <FileReference> ProgramModuleFiles = new List <FileReference>(FindAllRulesFiles(ProgramsDirectory, RulesFileType.Module));
            List <FileReference> ProgramTargetFiles = new List <FileReference>(FindAllRulesFiles(SourceDirectory, RulesFileType.Target));

            // Create a path to the assembly that we'll either load or compile
            FileReference ProgramAssemblyFileName = FileReference.Combine(RootDirectory, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "ProgramRules" + FrameworkAssemblyExtension);
            RulesAssembly ProgramAssembly         = new RulesAssembly(new List <PluginInfo>().AsReadOnly(), ProgramModuleFiles, ProgramTargetFiles, new Dictionary <FileReference, PluginInfo>(), ProgramAssemblyFileName, bContainsEngineModules: false, bUseBackwardsCompatibleDefaults: false, bInstalled: bInstalled, Parent: EngineAssembly);

            // Return the combined assembly
            return(ProgramAssembly);
        }
Beispiel #14
0
        /// <summary>
        /// Creates a rules assembly
        /// </summary>
        /// <param name="RootDirectory">The root directory 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="Parent">The parent rules assembly</param>
        /// <returns>New rules assembly</returns>
        private static RulesAssembly CreateRulesAssembly(DirectoryReference RootDirectory, string AssemblyPrefix, IReadOnlyList <PluginInfo> Plugins, RulesAssembly Parent)
        {
            DirectoryReference SourceDirectory = DirectoryReference.Combine(RootDirectory, "Source");

            // Find all the rules files
            List <FileReference> ModuleFiles = new List <FileReference>(FindAllRulesFiles(SourceDirectory, RulesFileType.Module));
            List <FileReference> TargetFiles = new List <FileReference>(FindAllRulesFiles(SourceDirectory, RulesFileType.Target));

            // Add all the plugin modules too
            Dictionary <FileReference, PluginInfo> ModuleFileToPluginInfo = new Dictionary <FileReference, PluginInfo>();

            FindModuleRulesForPlugins(Plugins, ModuleFiles, ModuleFileToPluginInfo);

            // Create a path to the assembly that we'll either load or compile
            FileReference AssemblyFileName = FileReference.Combine(RootDirectory, "Intermediate", "Build", "BuildRules", AssemblyPrefix + "Rules" + FrameworkAssemblyExtension);

            return(new RulesAssembly(Plugins, ModuleFiles, TargetFiles, ModuleFileToPluginInfo, AssemblyFileName, Parent));
        }
 public UEBuildServer(TargetDescriptor InDesc, TargetRules InRulesObject, RulesAssembly InRulesAssembly, FileReference InTargetCsFilename)
     : base(InDesc, InRulesObject, InRulesAssembly, "UE4Server", InTargetCsFilename)
 {
 }
        /// <summary>
        /// Main entry point
        /// </summary>
        /// <param name="Arguments">Command-line arguments</param>
        /// <returns>One of the values of ECompilationResult</returns>
        public override int Execute(CommandLineArguments Arguments)
        {
            Arguments.ApplyTo(this);

            // Create the build configuration object, and read the settings
            BuildConfiguration BuildConfiguration = new BuildConfiguration();

            XmlConfig.ApplyTo(BuildConfiguration);
            Arguments.ApplyTo(BuildConfiguration);

            // Parse all the targets being built
            List <TargetDescriptor> TargetDescriptors = TargetDescriptor.ParseCommandLine(Arguments, BuildConfiguration.bUsePrecompiled, bSkipRulesCompile);

            if (TargetDescriptors.Count == 0)
            {
                throw new BuildException("No targets specified to clean");
            }

            // Also add implicit descriptors for cleaning UnrealBuildTool
            if (!BuildConfiguration.bDoNotBuildUHT)
            {
                const string UnrealHeaderToolTarget = "UnrealHeaderTool";

                // Get a list of project files to clean UHT for
                List <FileReference> ProjectFiles = new List <FileReference>();
                foreach (TargetDescriptor TargetDesc in TargetDescriptors)
                {
                    if (TargetDesc.Name != UnrealHeaderToolTarget && !RemoteMac.HandlesTargetPlatform(TargetDesc.Platform))
                    {
                        if (ProjectFiles.Count == 0)
                        {
                            ProjectFiles.Add(null);
                        }
                        if (TargetDesc.ProjectFile != null && !ProjectFiles.Contains(TargetDesc.ProjectFile))
                        {
                            ProjectFiles.Add(TargetDesc.ProjectFile);
                        }
                    }
                }

                // Add descriptors for cleaning UHT with all these projects
                if (ProjectFiles.Count > 0)
                {
                    UnrealTargetConfiguration Configuration = BuildConfiguration.bForceDebugUnrealHeaderTool ? UnrealTargetConfiguration.Debug : UnrealTargetConfiguration.Development;
                    string Architecture = UEBuildPlatform.GetBuildPlatform(BuildHostPlatform.Current.Platform).GetDefaultArchitecture(null);
                    foreach (FileReference ProjectFile in ProjectFiles)
                    {
                        TargetDescriptors.Add(new TargetDescriptor(ProjectFile, UnrealHeaderToolTarget, BuildHostPlatform.Current.Platform, Configuration, Architecture, null));
                    }
                }
            }

            // Output the list of targets that we're cleaning
            Log.TraceInformation("Cleaning {0} binaries...", StringUtils.FormatList(TargetDescriptors.Select(x => x.Name).Distinct()));

            // Loop through all the targets, and clean them all
            HashSet <FileReference>      FilesToDelete       = new HashSet <FileReference>();
            HashSet <DirectoryReference> DirectoriesToDelete = new HashSet <DirectoryReference>();

            for (int Idx = 0; Idx < TargetDescriptors.Count; ++Idx)
            {
                TargetDescriptor TargetDescriptor = TargetDescriptors[Idx];

                // Create the rules assembly
                RulesAssembly RulesAssembly = RulesCompiler.CreateTargetRulesAssembly(TargetDescriptor.ProjectFile, TargetDescriptor.Name, bSkipRulesCompile, BuildConfiguration.bUsePrecompiled, TargetDescriptor.ForeignPlugin);

                // Create the rules object
                ReadOnlyTargetRules Target = new ReadOnlyTargetRules(RulesAssembly.CreateTargetRules(TargetDescriptor.Name, TargetDescriptor.Platform, TargetDescriptor.Configuration, TargetDescriptor.Architecture, TargetDescriptor.ProjectFile, TargetDescriptor.AdditionalArguments));

                if (!bSkipPreBuildTargets && Target.PreBuildTargets.Count > 0)
                {
                    foreach (TargetInfo PreBuildTarget in Target.PreBuildTargets)
                    {
                        TargetDescriptor NewTarget = TargetDescriptor.FromTargetInfo(PreBuildTarget);
                        if (!TargetDescriptors.Contains(NewTarget))
                        {
                            TargetDescriptors.Add(NewTarget);
                        }
                    }
                }

                // Find the base folders that can contain binaries
                List <DirectoryReference> BaseDirs = new List <DirectoryReference>();
                BaseDirs.Add(UnrealBuildTool.EngineDirectory);
                BaseDirs.Add(UnrealBuildTool.EnterpriseDirectory);
                foreach (FileReference Plugin in Plugins.EnumeratePlugins(Target.ProjectFile))
                {
                    BaseDirs.Add(Plugin.Directory);
                }
                if (Target.ProjectFile != null)
                {
                    BaseDirs.Add(Target.ProjectFile.Directory);
                }

                // If we're running a precompiled build, remove anything under the engine folder
                BaseDirs.RemoveAll(x => RulesAssembly.IsReadOnly(x));

                // Get all the names which can prefix build products
                List <string> NamePrefixes = new List <string>();
                if (Target.Type != TargetType.Program)
                {
                    NamePrefixes.Add(UEBuildTarget.GetAppNameForTargetType(Target.Type));
                }
                NamePrefixes.Add(Target.Name);

                // Get the suffixes for this configuration
                List <string> NameSuffixes = new List <string>();
                if (Target.Configuration == Target.UndecoratedConfiguration)
                {
                    NameSuffixes.Add("");
                }
                NameSuffixes.Add(String.Format("-{0}-{1}", Target.Platform.ToString(), Target.Configuration.ToString()));
                if (!String.IsNullOrEmpty(Target.Architecture))
                {
                    NameSuffixes.AddRange(NameSuffixes.ToArray().Select(x => x + Target.Architecture));
                }

                // Add all the makefiles and caches to be deleted
                FilesToDelete.Add(TargetMakefile.GetLocation(Target.ProjectFile, Target.Name, Target.Platform, Target.Configuration));
                FilesToDelete.UnionWith(SourceFileMetadataCache.GetFilesToClean(Target.ProjectFile));

                // Add all the intermediate folders to be deleted
                foreach (DirectoryReference BaseDir in BaseDirs)
                {
                    foreach (string NamePrefix in NamePrefixes)
                    {
                        DirectoryReference GeneratedCodeDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, "Inc");
                        if (DirectoryReference.Exists(GeneratedCodeDir))
                        {
                            DirectoriesToDelete.Add(GeneratedCodeDir);
                        }

                        DirectoryReference IntermediateDir = DirectoryReference.Combine(BaseDir, "Intermediate", "Build", Target.Platform.ToString(), NamePrefix, Target.Configuration.ToString());
                        if (DirectoryReference.Exists(IntermediateDir))
                        {
                            DirectoriesToDelete.Add(IntermediateDir);
                        }
                    }
                }

                // List of additional files and directories to clean, specified by the target platform
                List <FileReference>      AdditionalFilesToDelete       = new List <FileReference>();
                List <DirectoryReference> AdditionalDirectoriesToDelete = new List <DirectoryReference>();

                // Add all the build products from this target
                string[] NamePrefixesArray = NamePrefixes.Distinct().ToArray();
                string[] NameSuffixesArray = NameSuffixes.Distinct().ToArray();
                foreach (DirectoryReference BaseDir in BaseDirs)
                {
                    DirectoryReference BinariesDir = DirectoryReference.Combine(BaseDir, "Binaries", Target.Platform.ToString());
                    if (DirectoryReference.Exists(BinariesDir))
                    {
                        UEBuildPlatform.GetBuildPlatform(Target.Platform).FindBuildProductsToClean(BinariesDir, NamePrefixesArray, NameSuffixesArray, AdditionalFilesToDelete, AdditionalDirectoriesToDelete);
                    }
                }

                // Get all the additional intermediate folders created by this platform
                UEBuildPlatform.GetBuildPlatform(Target.Platform).FindAdditionalBuildProductsToClean(Target, AdditionalFilesToDelete, AdditionalDirectoriesToDelete);

                // Add the platform's files and directories to the main list
                FilesToDelete.UnionWith(AdditionalFilesToDelete);
                DirectoriesToDelete.UnionWith(AdditionalDirectoriesToDelete);
            }

            // Delete all the directories, then all the files. By sorting the list of directories before we delete them, we avoid spamming the log if a parent directory is deleted first.
            foreach (DirectoryReference DirectoryToDelete in DirectoriesToDelete.OrderBy(x => x.FullName))
            {
                if (DirectoryReference.Exists(DirectoryToDelete))
                {
                    Log.TraceVerbose("    Deleting {0}{1}...", DirectoryToDelete, Path.DirectorySeparatorChar);
                    try
                    {
                        FileUtils.ForceDeleteDirectory(DirectoryToDelete);
                    }
                    catch (Exception Ex)
                    {
                        throw new BuildException(Ex, "Unable to delete {0} ({1})", DirectoryToDelete, Ex.Message.TrimEnd());
                    }
                }
            }

            foreach (FileReference FileToDelete in FilesToDelete.OrderBy(x => x.FullName))
            {
                if (FileReference.Exists(FileToDelete))
                {
                    Log.TraceVerbose("    Deleting " + FileToDelete);
                    try
                    {
                        FileUtils.ForceDeleteFile(FileToDelete);
                    }
                    catch (Exception Ex)
                    {
                        throw new BuildException(Ex, "Unable to delete {0} ({1})", FileToDelete, Ex.Message.TrimEnd());
                    }
                }
            }

            // Also clean all the remote targets
            for (int Idx = 0; Idx < TargetDescriptors.Count; Idx++)
            {
                TargetDescriptor TargetDescriptor = TargetDescriptors[Idx];
                if (RemoteMac.HandlesTargetPlatform(TargetDescriptor.Platform))
                {
                    RemoteMac RemoteMac = new RemoteMac(TargetDescriptor.ProjectFile);
                    RemoteMac.Clean(TargetDescriptor);
                }
            }

            return(0);
        }