public override void AddFilesToManifest(BuildManifest Manifest, STBuildBinary Binary) { // ok, this is pretty awful, we want the import libraries that go with the editor, only on the PC if (STBuildTool.BuildingRocket() && Path.GetFileNameWithoutExtension(Binary.Config.OutputFilePath).StartsWith("UE4Editor-", StringComparison.InvariantCultureIgnoreCase) && Path.GetExtension(Binary.Config.OutputFilePath).EndsWith("dll", StringComparison.InvariantCultureIgnoreCase) && Binary.Config.Type == STBuildBinaryType.DynamicLinkLibrary) { // ok, this is pretty awful, we want the import libraries that go with the editor, only on the PC Manifest.AddBuildProduct(Path.Combine(Binary.Config.IntermediateDirectory, Path.GetFileNameWithoutExtension(Binary.Config.OutputFilePath) + ".lib"), ""); } }
/// <summary> /// Process all modules that aren't yet bound, creating binaries for modules that don't yet have one (if needed), /// and updating modules for circular dependencies. /// </summary> /// <param name="ExecutableBinary">The executable binary, which links against all unbound modules when building monolithically</param> /// <returns>List of newly-created binaries (may be empty)</returns> public override List<STBuildBinary> ProcessUnboundModules(STBuildBinary ExecutableBinary) { var Binaries = new Dictionary<string, STBuildBinary>(StringComparer.InvariantCultureIgnoreCase); if (Config.bHasModuleRules) { foreach (var ModuleName in ModuleNames) { var Module = Target.FindOrCreateModuleByName(ModuleName); Module.RecursivelyProcessUnboundModules(Target, ref Binaries, ExecutableBinary); } } else { // There's only one module in this case, so just bind it to this binary foreach (var ModuleName in ModuleNames) { Binaries.Add(ModuleName, this); } } // Now build a final list of newly-created binaries that were bound to. The hash may contain duplicates, so // we filter those out here. var BinaryList = new List<STBuildBinary>(); foreach (var CurBinary in Binaries.Values) { // Never include ourselves in the new binary list (monolithic case) if (CurBinary != this) { if (!BinaryList.Contains(CurBinary)) { BinaryList.Add(CurBinary); } } } return BinaryList; }
/// <summary> /// Process all modules that aren't yet bound, creating binaries for modules that don't yet have one (if needed), /// and updating modules for circular dependencies. /// </summary> /// <param name="ExecutableBinary">The executable binary, which links against all unbound modules when building monolithically</param> /// <returns>List of newly-created binaries (may be empty)</returns> public virtual List<STBuildBinary> ProcessUnboundModules(STBuildBinary ExecutableBinary) { return null; }
public virtual void AddFilesToManifest(BuildManifest Manifest, STBuildBinary Binary) { }
/** Sets up the environment for linking any module that includes the public interface of this module. */ protected virtual void SetupPublicLinkEnvironment( STBuildBinary SourceBinary, ref List<string> LibraryPaths, ref List<string> AdditionalLibraries, ref List<string> Frameworks, ref List<string> WeakFrameworks, ref List<STBuildFramework> AdditionalFrameworks, ref List<string> AdditionalShadowFiles, ref List<STBuildBundleResource> AdditionalBundleResources, ref List<string> DelayLoadDLLs, ref List<STBuildBinary> BinaryDependencies, ref Dictionary<STBuildModule, bool> VisitedModules ) { // There may be circular dependencies in compile dependencies, so we need to avoid reentrance. if (!VisitedModules.ContainsKey(this)) { VisitedModules.Add(this, true); // Only process modules that are included in the current target. if (bIncludedInTarget) { // Add this module's binary to the binary dependencies. if (Binary != null && Binary != SourceBinary && !BinaryDependencies.Contains(Binary)) { BinaryDependencies.Add(Binary); } // If this module belongs to a static library that we are not currently building, recursively add the link environment settings for all of its dependencies too. // Keep doing this until we reach a module that is not part of a static library (or external module, since they have no associated binary). // Static libraries do not contain the symbols for their dependencies, so we need to recursively gather them to be linked into other binary types. bool bIsBuildingAStaticLibrary = (SourceBinary != null && SourceBinary.Config.Type == STBuildBinaryType.StaticLibrary); bool bIsModuleBinaryAStaticLibrary = (Binary != null && Binary.Config.Type == STBuildBinaryType.StaticLibrary); if (!bIsBuildingAStaticLibrary && bIsModuleBinaryAStaticLibrary) { // Gather all dependencies and recursively call SetupPublicLinkEnvironmnet List<string> AllDependencyModuleNames = new List<string>(PrivateDependencyModuleNames); AllDependencyModuleNames.AddRange(PublicDependencyModuleNames); foreach (var DependencyName in AllDependencyModuleNames) { var DependencyModule = Target.GetModuleByName(DependencyName); bool bIsExternalModule = (DependencyModule as STBuildExternalModule != null); bool bIsInStaticLibrary = (DependencyModule.Binary != null && DependencyModule.Binary.Config.Type == STBuildBinaryType.StaticLibrary); if (bIsExternalModule || bIsInStaticLibrary) { DependencyModule.SetupPublicLinkEnvironment(SourceBinary, ref LibraryPaths, ref AdditionalLibraries, ref Frameworks, ref WeakFrameworks, ref AdditionalFrameworks, ref AdditionalShadowFiles, ref AdditionalBundleResources, ref DelayLoadDLLs, ref BinaryDependencies, ref VisitedModules); } } } // Add this module's public include library paths and additional libraries. LibraryPaths.AddRange(PublicLibraryPaths); AdditionalLibraries.AddRange(PublicAdditionalLibraries); Frameworks.AddRange(PublicFrameworks); WeakFrameworks.AddRange(PublicWeakFrameworks); AdditionalBundleResources.AddRange(PublicAdditionalBundleResources); // Remember the module so we can refer to it when needed foreach (var Framework in PublicAdditionalFrameworks) { Framework.OwningModule = this; } AdditionalFrameworks.AddRange(PublicAdditionalFrameworks); AdditionalShadowFiles.AddRange(PublicAdditionalShadowFiles); DelayLoadDLLs.AddRange(PublicDelayLoadDLLs); } } }
/** Sets up the environment for compiling any module that includes the public interface of this module. */ protected virtual void SetupPublicCompileEnvironment( STBuildBinary SourceBinary, bool bIncludePathsOnly, ref HashSet<string> IncludePaths, ref HashSet<string> SystemIncludePaths, ref List<string> Definitions, ref List<STBuildFramework> AdditionalFrameworks, ref Dictionary<STBuildModule, bool> VisitedModules ) { // There may be circular dependencies in compile dependencies, so we need to avoid reentrance. if (!VisitedModules.ContainsKey(this)) { VisitedModules.Add(this, true); // Add this module's public include paths and definitions. AddIncludePathsWithChecks(IncludePaths, PublicIncludePaths); AddIncludePathsWithChecks(SystemIncludePaths, PublicSystemIncludePaths); Definitions.AddRange(PublicDefinitions); // If this module is being built into a DLL or EXE, set up an IMPORTS or EXPORTS definition for it. if (Binary != null) { string BinaryPath = Binary.Config.OutputFilePaths[0]; string SourceBinaryPath = SourceBinary.Config.OutputFilePaths[0]; if (ProjectFileGenerator.bGenerateProjectFiles || (Binary.Config.Type == STBuildBinaryType.StaticLibrary)) { // When generating IntelliSense files, never add dllimport/dllexport specifiers as it // simply confuses the compiler Definitions.Add(Name.ToUpperInvariant() + "_API="); } else if (Binary == SourceBinary) { if (Binary.Config.bAllowExports) { Log.TraceVerbose("{0}: Exporting {1} from {2}", Path.GetFileNameWithoutExtension(SourceBinaryPath), Name, Path.GetFileNameWithoutExtension(BinaryPath)); Definitions.Add(Name.ToUpperInvariant() + "_API=DLLEXPORT"); } else { Log.TraceVerbose("{0}: Not importing/exporting {1} (binary: {2})", Path.GetFileNameWithoutExtension(SourceBinaryPath), Name, Path.GetFileNameWithoutExtension(BinaryPath)); Definitions.Add(Name.ToUpperInvariant() + "_API="); } } else { // @todo SharedPCH: Public headers included from modules that are not importing the module of that public header, seems invalid. // Those public headers have no business having APIs in them. OnlineSubsystem has some public headers like this. Without changing // this, we need to suppress warnings at compile time. if (bIncludePathsOnly) { Log.TraceVerbose("{0}: Include paths only for {1} (binary: {2})", Path.GetFileNameWithoutExtension(SourceBinaryPath), Name, Path.GetFileNameWithoutExtension(BinaryPath)); Definitions.Add(Name.ToUpperInvariant() + "_API="); } else if (Binary.Config.bAllowExports) { Log.TraceVerbose("{0}: Importing {1} from {2}", Path.GetFileNameWithoutExtension(SourceBinaryPath), Name, Path.GetFileNameWithoutExtension(BinaryPath)); Definitions.Add(Name.ToUpperInvariant() + "_API=DLLIMPORT"); } else { Log.TraceVerbose("{0}: Not importing/exporting {1} (binary: {2})", Path.GetFileNameWithoutExtension(SourceBinaryPath), Name, Path.GetFileNameWithoutExtension(BinaryPath)); Definitions.Add(Name.ToUpperInvariant() + "_API="); } } } if (!bIncludePathsOnly) { // Recurse on this module's public dependencies. foreach (var DependencyName in PublicDependencyModuleNames) { var DependencyModule = Target.GetModuleByName(DependencyName); DependencyModule.SetupPublicCompileEnvironment(SourceBinary, bIncludePathsOnly, ref IncludePaths, ref SystemIncludePaths, ref Definitions, ref AdditionalFrameworks, ref VisitedModules); } } // Now add an include paths from modules with header files that we need access to, but won't necessarily be importing foreach (var IncludePathModuleName in PublicIncludePathModuleNames) { bool bInnerIncludePathsOnly = true; var IncludePathModule = Target.GetModuleByName(IncludePathModuleName); IncludePathModule.SetupPublicCompileEnvironment(SourceBinary, bInnerIncludePathsOnly, ref IncludePaths, ref SystemIncludePaths, ref Definitions, ref AdditionalFrameworks, ref VisitedModules); } // Add the module's directory to the include path, so we can root #includes to it IncludePaths.Add(Utils.CleanDirectorySeparators(Utils.MakePathRelativeTo(ModuleDirectory, Path.Combine(ProjectFileGenerator.RootRelativePath, "Engine/Source")), '/')); // Add the additional frameworks so that the compiler can know about their #include paths AdditionalFrameworks.AddRange(PublicAdditionalFrameworks); } }
/** * Gathers and binds binaries for this module and all of it's dependent modules * * @param Target The target we are currently building * @param Binaries Dictionary of all binaries we've gathered so far * @param ExecutableBinary The binary for the target's main executable (used only when linking monolithically) * @param bBuildOnlyModules True to build only specific modules, false for all * @param ModulesToBuild The specific modules to build */ public virtual void RecursivelyProcessUnboundModules(STBuildTarget Target, ref Dictionary<string, STBuildBinary> Binaries, STBuildBinary ExecutableBinary) { }
public override void RecursivelyProcessUnboundModules(STBuildTarget Target, ref Dictionary<string, STBuildBinary> Binaries, STBuildBinary ExecutableBinary) { try { // 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)) { STBuildBinary BinaryToBindTo; if (Target.ShouldCompileMonolithic()) { // When linking monolithically, any unbound modules will be linked into the main executable BinaryToBindTo = ExecutableBinary; } else { // Is this a plugin module? var PluginInfo = Plugins.GetPluginInfoForModule(DependencyName); string[] OutputFilePaths = Target.MakeBinaryPaths(DependencyModule.Name, Target.GetAppName() + "-" + DependencyModule.Name, STBuildBinaryType.DynamicLinkLibrary, Target.TargetType, PluginInfo, ""); // If it's an engine module, output intermediates to the engine intermediates directory. string IntermediateDirectory = Binary.Config.IntermediateDirectory; if (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 STBuildBinaryConfiguration Config = new STBuildBinaryConfiguration(InType: STBuildBinaryType.DynamicLinkLibrary, InOutputFilePaths: OutputFilePaths, 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 for (int Index = 0; Index < Config.OutputFilePaths.Length; Index++) { Config.OutputFilePaths[Index] = DependencyModule.FixupOutputPath(Config.OutputFilePaths[Index]); } BinaryToBindTo = new STBuildBinaryCPP(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); } catch (System.Exception ex) { throw new ModuleProcessingException(this, ex); } }
public override void AddFilesToManifest(BuildManifest Manifest, STBuildBinary Binary) { if (BuildConfiguration.bCreateStubIPA) { string StubFile = Path.Combine (Path.GetDirectoryName (Binary.Config.OutputFilePath), Path.GetFileNameWithoutExtension (Binary.Config.OutputFilePath) + ".stub"); Manifest.AddBuildProduct(StubFile); } }
private void GenerateLinkerFixupsContents(STBuildBinary ExecutableBinary, List<string> LinkerFixupsFileContents, CPPEnvironment CompileEnvironment, string HeaderFilename, string LinkerFixupsName, List<string> PrivateDependencyModuleNames) { LinkerFixupsFileContents.Add("#include \"" + HeaderFilename + "\""); // To reduce the size of the command line for the compiler, we're going to put all definitions inside of the cpp file. foreach (var Definition in CompileEnvironment.Config.Definitions) { string MacroName; string MacroValue = String.Empty; int EqualsIndex = Definition.IndexOf('='); if (EqualsIndex >= 0) { MacroName = Definition.Substring(0, EqualsIndex); MacroValue = Definition.Substring(EqualsIndex + 1); } else { MacroName = Definition; } LinkerFixupsFileContents.Add("#ifndef " + MacroName); LinkerFixupsFileContents.Add(String.Format("\t#define {0} {1}", MacroName, MacroValue)); LinkerFixupsFileContents.Add("#endif"); } // Add a function that is not referenced by anything that invokes all the empty functions in the different static libraries LinkerFixupsFileContents.Add("void " + LinkerFixupsName + "()"); LinkerFixupsFileContents.Add("{"); // Fill out the body of the function with the empty function calls. This is what causes the static libraries to be considered relevant var DependencyModules = ExecutableBinary.GetAllDependencyModules(bIncludeDynamicallyLoaded: false, bForceCircular: false); foreach (string ModuleName in DependencyModules.OfType<STBuildModuleCPP>().Where(CPPModule => CPPModule.AutoGenerateCppInfo != null).Select(CPPModule => CPPModule.Name).Distinct()) { LinkerFixupsFileContents.Add(" extern void EmptyLinkFunctionForGeneratedCode" + ModuleName + "();"); LinkerFixupsFileContents.Add(" EmptyLinkFunctionForGeneratedCode" + ModuleName + "();"); } foreach (var DependencyModuleName in PrivateDependencyModuleNames) { LinkerFixupsFileContents.Add(" extern void EmptyLinkFunctionForStaticInitialization" + DependencyModuleName + "();"); LinkerFixupsFileContents.Add(" EmptyLinkFunctionForStaticInitialization" + DependencyModuleName + "();"); } // End the function body that was started above LinkerFixupsFileContents.Add("}"); }
/// <summary> /// Binds artificial module to given binary. /// </summary> /// <param name="Module">Module to bind.</param> /// <param name="Binary">Binary to bind.</param> private void BindArtificialModuleToBinary(STBuildModuleCPP Module, STBuildBinary Binary) { Module.Binary = Binary; Module.bIncludedInTarget = true; // Process dependencies for this new module Module.CachePCHUsageForModuleSourceFiles(Module.CreateModuleCompileEnvironment(GlobalCompileEnvironment)); // Add module to binary Binary.AddModule(Module.Name); }