Пример #1
0
        public override void RecursivelyAddIncludePathModules( UEBuildTarget Target, bool bPublicIncludesOnly )
        {
            var AllIncludePathModuleNames = new List<string>();
            AllIncludePathModuleNames.AddRange( PublicIncludePathModuleNames );
            if( !bPublicIncludesOnly )
            {
                AllIncludePathModuleNames.AddRange( PrivateIncludePathModuleNames );
            }
            foreach( var IncludePathModuleName in AllIncludePathModuleNames )
            {
                var IncludePathModule = Target.FindOrCreateModuleByName( IncludePathModuleName );

                // No need to do anything here.  We just want to make sure that we've instantiated our representation of the
                // module so that we can find it later when processing include path module names.  Unlike actual dependency
                // modules, these include path modules may never be "bound" (have Binary or bIncludedInTarget member variables set)

                // We'll also need to make sure we know about all dependent public include path modules, too!
                IncludePathModule.RecursivelyAddIncludePathModules( Target, bPublicIncludesOnly:true );
            }
        }
Пример #2
0
		private static void RecursivelyCreateIncludePathModulesByName(UEBuildTarget Target, List<string> ModuleNames, ref List<UEBuildModule> Modules)
		{
			// Check whether the module list is already set. We set this immediately (via the ref) to avoid infinite recursion.
			if (Modules == null)
			{
				Modules = new List<UEBuildModule>();
				foreach (string ModuleName in ModuleNames)
				{
					UEBuildModule Module = Target.FindOrCreateModuleByName(ModuleName);
					RecursivelyCreateIncludePathModulesByName(Target, Module.Rules.PublicIncludePathModuleNames, ref Module.PublicIncludePathModules);
					Modules.Add(Module);
				}
			}
		}
Пример #3
0
		// UEBuildModule interface.
		public override List<FileItem> Compile(UEBuildTarget Target, UEToolChain ToolChain, CPPEnvironment GlobalCompileEnvironment, CPPEnvironment CompileEnvironment)
		{
			UEBuildPlatform BuildPlatform = UEBuildPlatform.GetBuildPlatformForCPPTargetPlatform(CompileEnvironment.Config.Target.Platform);

			List<FileItem> LinkInputFiles = new List<FileItem>();
			if (ProjectFileGenerator.bGenerateProjectFiles && IntelliSenseGatherer == null)
			{
				// Nothing to do for IntelliSense, bail out early
				return LinkInputFiles;
			}

			CPPEnvironment ModuleCompileEnvironment = CreateModuleCompileEnvironment(Target, CompileEnvironment);
			IncludeSearchPaths = ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths.ToList();
			IncludeSearchPaths.AddRange(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths.ToList());

			if (IntelliSenseGatherer != null)
			{
				// Update project file's set of preprocessor definitions and include paths
				IntelliSenseGatherer.AddIntelliSensePreprocessorDefinitions(ModuleCompileEnvironment.Config.Definitions);
				IntelliSenseGatherer.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths, bAddingSystemIncludes: true);
				IntelliSenseGatherer.AddInteliiSenseIncludePaths(ModuleCompileEnvironment.Config.CPPIncludeInfo.IncludePaths, bAddingSystemIncludes: false);

				// Bail out.  We don't need to actually compile anything while generating project files.
				return LinkInputFiles;
			}

			// Throw an error if the module's source file list referenced any non-existent files.
			if (SourceFilesToBuild.MissingFiles.Count > 0)
			{
				throw new BuildException(
					"UBT ERROR: Module \"{0}\" references non-existent files:\n{1} (perhaps a file was added to the project but not checked in)",
					Name,
					string.Join("\n", SourceFilesToBuild.MissingFiles.Select(M => M.AbsolutePath))
				);
			}

			// For an executable or a static library do not use the default RC file - 
			// If the executable wants it, it will be in their source list anyway.
			// The issue here is that when making a monolithic game, the processing
			// of the other game modules will stomp the game-specific rc file.
			if (Binary.Config.Type == UEBuildBinaryType.DynamicLinkLibrary)
			{
				// Add default PCLaunch.rc file if this module has no own resource file specified
				if (SourceFilesToBuild.RCFiles.Count <= 0)
				{
					FileReference DefRC = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Launch", "Resources", "Windows", "PCLaunch.rc");
					FileItem Item = FileItem.GetItemByFileReference(DefRC);
					SourceFilesToBuild.RCFiles.Add(Item);
				}

				// Always compile in the API version resource separately. This is required for the module manager to detect compatible API versions.
				FileReference ModuleVersionRC = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Runtime", "Core", "Resources", "Windows", "ModuleVersionResource.rc.inl");
				FileItem ModuleVersionItem = FileItem.GetItemByFileReference(ModuleVersionRC);
				if (!SourceFilesToBuild.RCFiles.Contains(ModuleVersionItem))
				{
					SourceFilesToBuild.RCFiles.Add(ModuleVersionItem);
				}
			}


			{
				// Process all of the header file dependencies for this module
				this.CachePCHUsageForModuleSourceFiles(Target, ModuleCompileEnvironment);

				// Make sure our RC files have cached includes.  
				foreach (FileItem RCFile in SourceFilesToBuild.RCFiles)
				{
					RCFile.CachedCPPIncludeInfo = ModuleCompileEnvironment.Config.CPPIncludeInfo;
				}
			}


			// Check to see if this is an Engine module (including program or plugin modules).  That is, the module is located under the "Engine" folder
			bool IsPluginModule = ModuleDirectory.IsUnderDirectory(DirectoryReference.Combine(Target.ProjectDirectory, "Plugins"));
			bool IsGameModule = !IsPluginModule && !ModuleDirectory.IsUnderDirectory(UnrealBuildTool.EngineDirectory);

			// Should we force a precompiled header to be generated for this module?  Usually, we only bother with a
			// precompiled header if there are at least several source files in the module (after combining them for unity
			// builds.)  But for game modules, it can be convenient to always have a precompiled header to single-file
			// changes to code is really quick to compile.
			int MinFilesUsingPrecompiledHeader = BuildConfiguration.MinFilesUsingPrecompiledHeader;
			if (Rules.MinFilesUsingPrecompiledHeaderOverride != 0)
			{
				MinFilesUsingPrecompiledHeader = Rules.MinFilesUsingPrecompiledHeaderOverride;
			}
			else if (IsGameModule && BuildConfiguration.bForcePrecompiledHeaderForGameModules)
			{
				// This is a game module with only a small number of source files, so go ahead and force a precompiled header
				// to be generated to make incremental changes to source files as fast as possible for small projects.
				MinFilesUsingPrecompiledHeader = 1;
			}


			// Engine modules will always use unity build mode unless MinSourceFilesForUnityBuildOverride is specified in
			// the module rules file.  By default, game modules only use unity of they have enough source files for that
			// to be worthwhile.  If you have a lot of small game modules, consider specifying MinSourceFilesForUnityBuildOverride=0
			// in the modules that you don't typically iterate on source files in very frequently.
			int MinSourceFilesForUnityBuild = 0;
			if (Rules.MinSourceFilesForUnityBuildOverride != 0)
			{
				MinSourceFilesForUnityBuild = Rules.MinSourceFilesForUnityBuildOverride;
			}
			else if (IsGameModule)
			{
				// Game modules with only a small number of source files are usually better off having faster iteration times
				// on single source file changes, so we forcibly disable unity build for those modules
				MinSourceFilesForUnityBuild = BuildConfiguration.MinGameModuleSourceFilesForUnityBuild;
			}


			// Should we use unity build mode for this module?
			bool bModuleUsesUnityBuild = false;
			if (BuildConfiguration.bUseUnityBuild || BuildConfiguration.bForceUnityBuild)
			{
				if (BuildConfiguration.bForceUnityBuild)
				{
					Log.TraceVerbose("Module '{0}' using unity build mode (bForceUnityBuild enabled for this module)", this.Name);
					bModuleUsesUnityBuild = true;
				}
				else if (Rules.bFasterWithoutUnity)
				{
					Log.TraceVerbose("Module '{0}' not using unity build mode (bFasterWithoutUnity enabled for this module)", this.Name);
					bModuleUsesUnityBuild = false;
				}
				else if (SourceFilesToBuild.CPPFiles.Count < MinSourceFilesForUnityBuild)
				{
					Log.TraceVerbose("Module '{0}' not using unity build mode (module with fewer than {1} source files)", this.Name, MinSourceFilesForUnityBuild);
					bModuleUsesUnityBuild = false;
				}
				else
				{
					Log.TraceVerbose("Module '{0}' using unity build mode (enabled in BuildConfiguration)", this.Name);
					bModuleUsesUnityBuild = true;
				}
			}
			else
			{
				Log.TraceVerbose("Module '{0}' not using unity build mode (disabled in BuildConfiguration)", this.Name);
			}

			// The environment with which to compile the CPP files
			CPPEnvironment CPPCompileEnvironment = ModuleCompileEnvironment;

			// Precompiled header support.
			bool bWasModuleCodeCompiled = false;
			if (BuildPlatform.ShouldUsePCHFiles(CompileEnvironment.Config.Target.Platform, CompileEnvironment.Config.Target.Configuration))
			{
				DateTime PCHGenTimerStart = DateTime.UtcNow;

				// The code below will figure out whether this module will either use a "unique PCH" (private PCH that will only be included by
				// this module's code files), or a "shared PCH" (potentially included by many code files in many modules.)  Only one or the other
				// will be used.
				FileItem SharedPCHHeaderFile = null;

				// In the case of a shared PCH, we also need to keep track of which module that PCH's header file is a member of
				string SharedPCHModuleName = String.Empty;

				if (BuildConfiguration.bUseSharedPCHs && CompileEnvironment.Config.bIsBuildingLibrary)
				{
					Log.TraceVerbose("Module '{0}' was not allowed to use Shared PCHs, because we're compiling to a library", this.Name);
				}

				bool bUseSharedPCHFiles = BuildConfiguration.bUseSharedPCHs && !CompileEnvironment.Config.bIsBuildingLibrary && GlobalCompileEnvironment.SharedPCHHeaderFiles.Count > 0;

				if (bUseSharedPCHFiles)
				{
					FileReference SharingPCHHeaderFilePath = null;
					bool bIsASharedPCHModule = bUseSharedPCHFiles && GlobalCompileEnvironment.SharedPCHHeaderFiles.Any(PCH => PCH.Module == this);
					if (bIsASharedPCHModule)
					{
						SharingPCHHeaderFilePath = FileReference.Combine(UnrealBuildTool.EngineSourceDirectory, Rules.SharedPCHHeaderFile);
					}

					// We can't use a shared PCH file when compiling a module
					// with exports, because the shared PCH can only have imports in it to work correctly.
					bool bAllowSharedPCH = (Rules.PCHUsage == ModuleRules.PCHUsageMode.NoSharedPCHs) ? false : true;
					bool bCanModuleUseOwnSharedPCH = bAllowSharedPCH && bIsASharedPCHModule && !Binary.Config.bAllowExports && ProcessedDependencies.UniquePCHHeaderFile.Reference == SharingPCHHeaderFilePath;
					if (bAllowSharedPCH && (!bIsASharedPCHModule || bCanModuleUseOwnSharedPCH))
					{
						// Figure out which shared PCH tier we're in
						List<UEBuildModule> ReferencedModules = new List<UEBuildModule>();
						{
							this.GetAllDependencyModules(ReferencedModules, new HashSet<UEBuildModule>(), bIncludeDynamicallyLoaded: false, bForceCircular: false, bOnlyDirectDependencies: true);
						}

						int LargestSharedPCHHeaderFileIndex = -1;
						foreach (UEBuildModule DependencyModule in ReferencedModules)
						{
							// These Shared PCHs are ordered from least complex to most complex.  We'll start at the last one and search backwards.
							for (int SharedPCHHeaderFileIndex = GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1; SharedPCHHeaderFileIndex > LargestSharedPCHHeaderFileIndex; --SharedPCHHeaderFileIndex)
							{
								SharedPCHHeaderInfo CurSharedPCHHeaderFile = GlobalCompileEnvironment.SharedPCHHeaderFiles[SharedPCHHeaderFileIndex];

								if (DependencyModule == CurSharedPCHHeaderFile.Module ||
									(bIsASharedPCHModule && CurSharedPCHHeaderFile.Module == this))	// If we ourselves are a shared PCH module, always at least use our own module as our shared PCH header if we can't find anything better
								{
									SharedPCHModuleName = CurSharedPCHHeaderFile.Module.Name;
									SharedPCHHeaderFile = CurSharedPCHHeaderFile.PCHHeaderFile;
									LargestSharedPCHHeaderFileIndex = SharedPCHHeaderFileIndex;
									break;
								}
							}

							if (LargestSharedPCHHeaderFileIndex == GlobalCompileEnvironment.SharedPCHHeaderFiles.Count - 1)
							{
								// We've determined that the module is using our most complex PCH header, so we can early-out
								break;
							}
						}

						// Did we not find a shared PCH header that is being included by this module?  This could happen if the module is not including Core.h, even indirectly.
						if (String.IsNullOrEmpty(SharedPCHModuleName))
						{
							throw new BuildException("Module {0} doesn't use a Shared PCH!  Please add a dependency on a Shared PCH module to this module's dependency list", this.Name);
						}

						// Keep track of how many modules make use of this PCH for performance diagnostics
						SharedPCHHeaderInfo LargestSharedPCHHeader = GlobalCompileEnvironment.SharedPCHHeaderFiles[LargestSharedPCHHeaderFileIndex];
						++LargestSharedPCHHeader.NumModulesUsingThisPCH;

						// Don't allow game modules to use engine PCHs in DebugGame - the optimization settings aren't correct. 
						// @todo: we should be creating shared PCHs ahead of time, and only using them if our settings match. as it is, the first modules compiled
						// (which are currently plugins) get to call the shots for how the shared PCH gets built, and that might be a game plugin built in debug...
						if(Target.Configuration == UnrealTargetConfiguration.DebugGame && SharedPCHHeaderFile.Reference.IsUnderDirectory(UnrealBuildTool.EngineDirectory) && !RulesFile.IsUnderDirectory(UnrealBuildTool.EngineDirectory))
						{
							SharedPCHModuleName = null;
							SharedPCHHeaderFile = null;
						}
					}
					else
					{
						Log.TraceVerbose("Module '{0}' cannot create or use Shared PCHs, because it needs its own private PCH", this.Name);
					}
				}


				// The precompiled header environment for all source files in this module that use a precompiled header, if we even need one
				PrecompileHeaderEnvironment ModulePCHEnvironment = null;

				// If there was one header that was included first by enough C++ files, use it as the precompiled header.
				// Only use precompiled headers for projects with enough files to make the PCH creation worthwhile.
				if (SharedPCHHeaderFile != null || SourceFilesToBuild.CPPFiles.Count >= MinFilesUsingPrecompiledHeader)
				{
					FileItem PCHToUse;

					if (SharedPCHHeaderFile != null)
					{
						ModulePCHEnvironment = ApplySharedPCH(GlobalCompileEnvironment, CompileEnvironment, ModuleCompileEnvironment, SourceFilesToBuild.CPPFiles, ref SharedPCHHeaderFile);
						if (ModulePCHEnvironment != null)
						{
							// @todo SharedPCH: Ideally we would exhaustively check for a compatible compile environment (definitions, imports/exports, etc)
							//    Currently, it's possible for the shared PCH to be compiled differently depending on which module UBT happened to have
							//    include it first during the build phase.  This could create problems with deterministic builds, or turn up compile
							//    errors unexpectedly due to compile environment differences.
							Log.TraceVerbose("Module " + Name + " uses existing Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "' (from module " + ModulePCHEnvironment.ModuleName + ")");
						}

						PCHToUse = SharedPCHHeaderFile;
					}
					else
					{
						PCHToUse = ProcessedDependencies.UniquePCHHeaderFile;
					}

					if (PCHToUse != null)
					{
						// Update all CPPFiles to point to the PCH
						foreach (FileItem CPPFile in SourceFilesToBuild.CPPFiles)
						{
							CPPFile.PCHHeaderNameInCode = PCHToUse.AbsolutePath;
							CPPFile.PrecompiledHeaderIncludeFilename = PCHToUse.Reference;
						}
					}

					// A shared PCH was not already set up for us, so set one up.
					if (ModulePCHEnvironment == null && SourceFilesToBuild.CPPFiles.Count > 0)
					{
						FileItem PCHHeaderFile = ProcessedDependencies.UniquePCHHeaderFile;
						string PCHModuleName = this.Name;
						if (SharedPCHHeaderFile != null)
						{
							PCHHeaderFile = SharedPCHHeaderFile;
							PCHModuleName = SharedPCHModuleName;
						}
						string PCHHeaderNameInCode = SourceFilesToBuild.CPPFiles[0].PCHHeaderNameInCode;

						ModulePCHEnvironment = new PrecompileHeaderEnvironment(PCHModuleName, PCHHeaderNameInCode, PCHHeaderFile, ModuleCompileEnvironment.Config.CLRMode, ModuleCompileEnvironment.Config.OptimizeCode);

						if (SharedPCHHeaderFile != null)
						{
							// Add to list of shared PCH environments
							GlobalCompileEnvironment.SharedPCHEnvironments.Add(ModulePCHEnvironment);
							Log.TraceVerbose("Module " + Name + " uses new Shared PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'");
						}
						else
						{
							Log.TraceVerbose("Module " + Name + " uses a Unique PCH '" + ModulePCHEnvironment.PrecompiledHeaderIncludeFilename + "'");
						}
					}
				}
				else
				{
					Log.TraceVerbose("Module " + Name + " doesn't use a Shared PCH, and only has " + SourceFilesToBuild.CPPFiles.Count.ToString() + " source file(s).  No Unique PCH will be generated.");
				}

				// Compile the C++ source or the unity C++ files that use a PCH environment.
				if (ModulePCHEnvironment != null)
				{
					// Setup a new compile environment for this module's source files.  It's pretty much the exact same as the
					// module's compile environment, except that it will include a PCH file.

					CPPEnvironment ModulePCHCompileEnvironment = ModuleCompileEnvironment.DeepCopy();
					ModulePCHCompileEnvironment.Config.PrecompiledHeaderAction = PrecompiledHeaderAction.Include;
					ModulePCHCompileEnvironment.Config.PrecompiledHeaderIncludeFilename = ModulePCHEnvironment.PrecompiledHeaderIncludeFilename.Reference;
					ModulePCHCompileEnvironment.Config.PCHHeaderNameInCode = ModulePCHEnvironment.PCHHeaderNameInCode;

					if (SharedPCHHeaderFile != null)
					{
						// Shared PCH headers need to be force included, because we're basically forcing the module to use
						// the precompiled header that we want, instead of the "first include" in each respective .cpp file
						ModulePCHCompileEnvironment.Config.bForceIncludePrecompiledHeader = true;
					}

					List<FileItem> CPPFilesToBuild = SourceFilesToBuild.CPPFiles;
					if (bModuleUsesUnityBuild)
					{
						// unity files generated for only the set of files which share the same PCH environment
						CPPFilesToBuild = Unity.GenerateUnityCPPs(ToolChain, Target, CPPFilesToBuild, ModulePCHCompileEnvironment, Name);
					}

					// Check if there are enough unity files to warrant pch generation (and we haven't already generated the shared one)
					if (ModulePCHEnvironment.PrecompiledHeaderFile == null)
					{
						if (SharedPCHHeaderFile != null || CPPFilesToBuild.Count >= MinFilesUsingPrecompiledHeader)
						{
                            CPPOutput PCHOutput;
							if (SharedPCHHeaderFile == null)
							{
								PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
									ToolChain,
									Target,
									CPPFilesToBuild[0].PCHHeaderNameInCode,
									ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
									ModuleCompileEnvironment,
									ModuleCompileEnvironment.Config.OutputDirectory,
									ModuleCompileEnvironment.Config.PCHOutputDirectory,
									Name,
									true);
							}
							else
							{
								UEBuildModuleCPP SharedPCHModule = (UEBuildModuleCPP)Target.FindOrCreateModuleByName(SharedPCHModuleName);

								CPPEnvironment SharedPCHCompileEnvironment = GlobalCompileEnvironment.DeepCopy();
								SharedPCHCompileEnvironment.Config.bEnableShadowVariableWarning = SharedPCHModule.Rules.bEnableShadowVariableWarnings;

								List<UEBuildModule> Modules = new List<UEBuildModule>();
								Dictionary<UEBuildModule, bool> ModuleToIncludePathsOnlyFlag = new Dictionary<UEBuildModule, bool>();
								SharedPCHModule.FindModulesInPublicCompileEnvironment(Modules, ModuleToIncludePathsOnlyFlag);

								foreach (UEBuildModule Module in Modules)
								{
									Module.AddModuleToCompileEnvironment(
										Binary,
										ModuleToIncludePathsOnlyFlag[Module],
										SharedPCHCompileEnvironment.Config.CPPIncludeInfo.IncludePaths,
										SharedPCHCompileEnvironment.Config.CPPIncludeInfo.SystemIncludePaths,
										SharedPCHCompileEnvironment.Config.Definitions,
										SharedPCHCompileEnvironment.Config.AdditionalFrameworks);
								}
                                
								PCHOutput = PrecompileHeaderEnvironment.GeneratePCHCreationAction(
									ToolChain,
									Target,
									CPPFilesToBuild[0].PCHHeaderNameInCode,
									ModulePCHEnvironment.PrecompiledHeaderIncludeFilename,
									SharedPCHCompileEnvironment,
									DirectoryReference.Combine(CompileEnvironment.Config.OutputDirectory, "SharedPCHs"),
									(CompileEnvironment.Config.PCHOutputDirectory == null)? null : DirectoryReference.Combine(CompileEnvironment.Config.PCHOutputDirectory, "SharedPCHs"),
									"Shared",
									false);
							}

							ModulePCHEnvironment.PrecompiledHeaderFile = PCHOutput.PrecompiledHeaderFile;

							ModulePCHEnvironment.OutputObjectFiles.Clear();
							ModulePCHEnvironment.OutputObjectFiles.AddRange(PCHOutput.ObjectFiles);
						}
						else if (CPPFilesToBuild.Count < MinFilesUsingPrecompiledHeader)
						{
							Log.TraceVerbose("Module " + Name + " doesn't use a Shared PCH, and only has " + CPPFilesToBuild.Count.ToString() + " unity source file(s).  No Unique PCH will be generated.");
						}
					}

					if (ModulePCHEnvironment.PrecompiledHeaderFile != null)
					{
						// Link in the object files produced by creating the precompiled header.
						LinkInputFiles.AddRange(ModulePCHEnvironment.OutputObjectFiles);

						// if pch action was generated for the environment then use pch
						ModulePCHCompileEnvironment.PrecompiledHeaderFile = ModulePCHEnvironment.PrecompiledHeaderFile;

						// Use this compile environment from now on
						CPPCompileEnvironment = ModulePCHCompileEnvironment;
					}

					LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, CPPFilesToBuild, Name).ObjectFiles);
					bWasModuleCodeCompiled = true;
				}

				if (BuildConfiguration.bPrintPerformanceInfo)
				{
					double PCHGenTime = (DateTime.UtcNow - PCHGenTimerStart).TotalSeconds;
					TotalPCHGenTime += PCHGenTime;
				}
			}

			if (!bWasModuleCodeCompiled && SourceFilesToBuild.CPPFiles.Count > 0)
			{
				List<FileItem> CPPFilesToCompile = SourceFilesToBuild.CPPFiles;
				if (bModuleUsesUnityBuild)
				{
					CPPFilesToCompile = Unity.GenerateUnityCPPs(ToolChain, Target, CPPFilesToCompile, CPPCompileEnvironment, Name);
				}
				LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, CPPFilesToCompile, Name).ObjectFiles);
			}

			if (AutoGenerateCppInfo != null && AutoGenerateCppInfo.BuildInfo != null && !CPPCompileEnvironment.bHackHeaderGenerator)
			{
				string[] GeneratedFiles = Directory.GetFiles(Path.GetDirectoryName(AutoGenerateCppInfo.BuildInfo.FileWildcard), Path.GetFileName(AutoGenerateCppInfo.BuildInfo.FileWildcard));
				foreach (string GeneratedFilename in GeneratedFiles)
				{
					FileItem GeneratedCppFileItem = FileItem.GetItemByPath(GeneratedFilename);

					CachePCHUsageForModuleSourceFile(Target, CPPCompileEnvironment, GeneratedCppFileItem);

					// @todo ubtmake: Check for ALL other places where we might be injecting .cpp or .rc files for compiling without caching CachedCPPIncludeInfo first (anything platform specific?)
					LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, new List<FileItem> { GeneratedCppFileItem }, Name).ObjectFiles);
				}
			}

			// Compile C files directly.
			LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.CFiles, Name).ObjectFiles);

			// Compile CC files directly.
			LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.CCFiles, Name).ObjectFiles);

			// Compile MM files directly.
			LinkInputFiles.AddRange(ToolChain.CompileCPPFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.MMFiles, Name).ObjectFiles);

			// Compile RC files.
			LinkInputFiles.AddRange(ToolChain.CompileRCFiles(Target, CPPCompileEnvironment, SourceFilesToBuild.RCFiles).ObjectFiles);

			return LinkInputFiles;
		}
Пример #4
0
        public override void RecursivelyProcessUnboundModules(UEBuildTarget Target, ref Dictionary<string, UEBuildBinary> Binaries, UEBuildBinary ExecutableBinary)
        {
            // Make sure this module is bound to a binary
            if( !bIncludedInTarget )
            {
                throw new BuildException( "Module '{0}' should already have been bound to a binary!", Name );
            }

            var AllModuleNames = new List<string>();
            AllModuleNames.AddRange( PrivateDependencyModuleNames );
            AllModuleNames.AddRange( PublicDependencyModuleNames );
            AllModuleNames.AddRange( DynamicallyLoadedModuleNames );
            AllModuleNames.AddRange( PlatformSpecificDynamicallyLoadedModuleNames );

            foreach( var DependencyName in AllModuleNames )
            {
                var DependencyModule = Target.FindOrCreateModuleByName(DependencyName);

                // Skip modules that are included with the target (externals)
                if( !DependencyModule.bIncludedInTarget )
                {
                    if( !Binaries.ContainsKey( DependencyModule.Name ) )
                    {
                        UEBuildBinary BinaryToBindTo;
                        if (Target.ShouldCompileMonolithic())
                        {
                            // When linking monolithically, any unbound modules will be linked into the main executable
                            BinaryToBindTo = ExecutableBinary;
                        }
                        else
                        {
                            // Is this a Rocket module?
                            bool bIsRocketModule = RulesCompiler.IsRocketProjectModule(DependencyName);

                            // Is this a plugin module?
                            var PluginInfo = Plugins.GetPluginInfoForModule( DependencyName );

                            string OutputFilePath = Target.MakeBinaryPath(DependencyModule.Name, Target.GetAppName() + "-" + DependencyModule.Name, UEBuildBinaryType.DynamicLinkLibrary, Target.Rules.Type, bIsRocketModule, PluginInfo, "");

                            // If it's an engine module, output intermediates to the engine intermediates directory.
                            string IntermediateDirectory = Binary.Config.IntermediateDirectory;
                            if (PluginInfo == null && IntermediateDirectory != Target.EngineIntermediateDirectory && Path.GetFullPath(DependencyModule.ModuleDirectory).StartsWith(Path.GetFullPath(BuildConfiguration.RelativeEnginePath)))
                            {
                                IntermediateDirectory = Target.EngineIntermediateDirectory;
                            }

                            // When using modular linkage, unbound modules will be linked into their own DLL files
                            UEBuildBinaryConfiguration Config = new UEBuildBinaryConfiguration( InType: UEBuildBinaryType.DynamicLinkLibrary,
                                                                                                InOutputFilePath: OutputFilePath,
                                                                                                InIntermediateDirectory: IntermediateDirectory,
                                                                                                bInAllowExports: true,
                                                                                                InModuleNames: new List<string> { DependencyModule.Name },
                                                                                                InTargetName: Target.GetAppName(),
                                                                                                bInIsCrossTarget: PlatformSpecificDynamicallyLoadedModuleNames.Contains(DependencyName) && !DynamicallyLoadedModuleNames.Contains(DependencyName),
                                                                                                InTargetConfiguration: Target.Configuration,
                                                                                                bInCompileMonolithic: Target.ShouldCompileMonolithic() );

                            // Fix up the binary path if this is module specifies an alternate output directory
                            Config.OutputFilePath = DependencyModule.FixupOutputPath(Config.OutputFilePath);

                            BinaryToBindTo = new UEBuildBinaryCPP( Target, Config );
                        }

                        Binaries[ DependencyModule.Name ] = BinaryToBindTo;

                        // Bind this module
                        DependencyModule.Binary = BinaryToBindTo;
                        DependencyModule.bIncludedInTarget = true;

                        // Also add binaries for this module's dependencies
                        DependencyModule.RecursivelyProcessUnboundModules( Target, ref Binaries, ExecutableBinary );
                    }
                }

                if (Target.ShouldCompileMonolithic() == false)
                {
                    // Check to see if there is a circular relationship between the module and it's referencer
                    if( DependencyModule.Binary != null )
                    {
                        if( CircularlyReferencedDependentModules.Contains( DependencyName ) )
                        {
                            DependencyModule.Binary.SetCreateImportLibrarySeparately( true );
                        }
                    }
                }
            }

            // Also make sure module entries are created for any module that is pulled in as an "include path" module.
            // These modules are never linked in unless they were referenced as an actual dependency of a different module,
            // but we still need to keep track of them so that we can find their include paths when setting up our
            // module's include paths.
            RecursivelyAddIncludePathModules( Target, bPublicIncludesOnly:false );
        }