Exemplo n.º 1
0
		private LinkEnvironment SetupBinaryLinkEnvironment(UEBuildTarget Target, UEToolChain ToolChain, LinkEnvironment LinkEnvironment, CPPEnvironment CompileEnvironment)
		{
			LinkEnvironment BinaryLinkEnvironment = LinkEnvironment.DeepCopy();
			HashSet<UEBuildModule> LinkEnvironmentVisitedModules = new HashSet<UEBuildModule>();
			List<UEBuildBinary> BinaryDependencies = new List<UEBuildBinary>();
			CompileEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type);
			CompileEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type);

			CPPEnvironment BinaryCompileEnvironment = CompileEnvironment.DeepCopy();
			// @Hack: This to prevent UHT from listing CoreUObject.generated.cpp as its dependency.
			// We flag the compile environment when we build UHT so that we don't need to check
			// this for each file when generating their dependencies.
			BinaryCompileEnvironment.bHackHeaderGenerator = (Target.GetAppName() == "UnrealHeaderTool");

			// @todo: This should be in some Windows code somewhere...
			// Set the original file name macro; used in PCLaunch.rc to set the binary metadata fields.
			string OriginalFilename = (Config.OriginalOutputFilePaths != null) ?
				Config.OriginalOutputFilePaths[0].GetFileName() :
				Config.OutputFilePaths[0].GetFileName();
			BinaryCompileEnvironment.Config.Definitions.Add("ORIGINAL_FILE_NAME=\"" + OriginalFilename + "\"");

			foreach (UEBuildModule Module in Modules)
			{
				List<FileItem> LinkInputFiles;
				if (Module.Binary == null || Module.Binary == this)
				{
					// Compile each module.
					Log.TraceVerbose("Compile module: " + Module.Name);
					LinkInputFiles = Module.Compile(Target, ToolChain, CompileEnvironment, BinaryCompileEnvironment);

					// NOTE: Because of 'Shared PCHs', in monolithic builds the same PCH file may appear as a link input
					// multiple times for a single binary.  We'll check for that here, and only add it once.  This avoids
					// a linker warning about redundant .obj files. 
					foreach (FileItem LinkInputFile in LinkInputFiles)
					{
						if (!BinaryLinkEnvironment.InputFiles.Contains(LinkInputFile))
						{
							BinaryLinkEnvironment.InputFiles.Add(LinkInputFile);
						}
					}
				}
				else
				{
					BinaryDependencies.Add(Module.Binary);
				}

				if (!BuildConfiguration.bRunUnrealCodeAnalyzer)
				{
					// Allow the module to modify the link environment for the binary.
					Module.SetupPrivateLinkEnvironment(this, BinaryLinkEnvironment, BinaryDependencies, LinkEnvironmentVisitedModules);
				}
			}


			// Allow the binary dependencies to modify the link environment.
			foreach (UEBuildBinary BinaryDependency in BinaryDependencies)
			{
				BinaryDependency.SetupDependentLinkEnvironment(BinaryLinkEnvironment);
			}

			// Remove the default resource file on Windows (PCLaunch.rc) if the user has specified their own
			if (BinaryLinkEnvironment.InputFiles.Select(Item => Path.GetFileName(Item.AbsolutePath).ToLower()).Any(Name => Name.EndsWith(".res") && !Name.EndsWith(".inl.res") && Name != "pclaunch.rc.res"))
			{
				BinaryLinkEnvironment.InputFiles.RemoveAll(x => Path.GetFileName(x.AbsolutePath).ToLower() == "pclaunch.rc.res");
			}

			// Set the link output file.
			BinaryLinkEnvironment.Config.OutputFilePaths = Config.OutputFilePaths.ToList();

			// Set whether the link is allowed to have exports.
			BinaryLinkEnvironment.Config.bHasExports = Config.bAllowExports;

			// Set the output folder for intermediate files
			BinaryLinkEnvironment.Config.IntermediateDirectory = Config.IntermediateDirectory;

			// Put the non-executable output files (PDB, import library, etc) in the same directory as the production
			BinaryLinkEnvironment.Config.OutputDirectory = Config.OutputFilePaths[0].Directory;

			// Setup link output type
			BinaryLinkEnvironment.Config.bIsBuildingDLL = IsBuildingDll(Config.Type);
			BinaryLinkEnvironment.Config.bIsBuildingLibrary = IsBuildingLibrary(Config.Type);

			BinaryLinkEnvironment.Config.ProjectFile = Target.ProjectFile;

			return BinaryLinkEnvironment;
		}
Exemplo n.º 2
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 );
        }