2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Diagnostics ;
using System.IO ;
using System.Linq ;
2014-04-29 11:21:18 -04:00
using System.Text.RegularExpressions ;
2014-03-14 14:13:41 -04:00
using System.Xml ;
namespace UnrealBuildTool
{
2014-05-22 01:20:24 -04:00
/** Type of module. Mirrored in UHT as EBuildModuleType */
2014-03-14 14:13:41 -04:00
public enum UEBuildModuleType
{
2014-05-22 01:20:24 -04:00
Unknown ,
Runtime ,
Developer ,
Editor ,
ThirdParty ,
Program ,
Game ,
}
public static class UEBuildModuleTypeExtensions
{
public static bool IsEngineModule ( this UEBuildModuleType ModuleType )
{
return ModuleType ! = UEBuildModuleType . Game ;
}
2014-03-14 14:13:41 -04:00
}
2015-03-27 07:15:32 -04:00
/ * *
* Distribution level of module .
* Note : The name of each entry is used to search for / create folders
* /
public enum UEBuildModuleDistribution
{
/// Binaries can be distributed to everyone
Public ,
/// Can be used by UE4 but not required
CarefullyRedist ,
/// Epic Employees and Contractors
NotForLicensees ,
/// Epic Employees only
NoRedist ,
}
2014-03-14 14:13:41 -04:00
/** A unit of code compilation and linking. */
public abstract class UEBuildModule
{
2014-05-22 01:20:24 -04:00
/** Known module folders */
public static readonly string RuntimeFolder = String . Format ( "{0}Runtime{0}" , Path . DirectorySeparatorChar ) ;
public static readonly string DeveloperFolder = String . Format ( "{0}Developer{0}" , Path . DirectorySeparatorChar ) ;
public static readonly string EditorFolder = String . Format ( "{0}Editor{0}" , Path . DirectorySeparatorChar ) ;
public static readonly string ProgramsFolder = String . Format ( "{0}Programs{0}" , Path . DirectorySeparatorChar ) ;
2015-04-21 15:16:38 -04:00
public static UEBuildModuleType GetModuleTypeFromDescriptor ( ModuleDescriptor Module )
2014-05-29 17:37:45 -04:00
{
2015-04-21 15:16:38 -04:00
switch ( Module . Type )
2014-05-29 17:37:45 -04:00
{
2015-04-21 15:16:38 -04:00
case ModuleHostType . Developer :
return UEBuildModuleType . Developer ;
case ModuleHostType . Editor :
case ModuleHostType . EditorNoCommandlet :
return UEBuildModuleType . Editor ;
case ModuleHostType . Program :
return UEBuildModuleType . Program ;
case ModuleHostType . Runtime :
case ModuleHostType . RuntimeNoCommandlet :
return UEBuildModuleType . Runtime ;
default :
throw new BuildException ( "Unhandled module type {0}" , Module . Type . ToString ( ) ) ;
2014-05-29 17:37:45 -04:00
}
}
public static UEBuildModuleType GetEngineModuleTypeBasedOnLocation ( string ModuleName , UEBuildModuleType ModuleType , string ModuleFileRelativeToEngineDirectory )
2014-05-22 01:20:24 -04:00
{
if ( ModuleFileRelativeToEngineDirectory . IndexOf ( UEBuildModule . RuntimeFolder , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ModuleType = UEBuildModuleType . Runtime ;
}
else if ( ModuleFileRelativeToEngineDirectory . IndexOf ( UEBuildModule . DeveloperFolder , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ModuleType = UEBuildModuleType . Developer ;
}
else if ( ModuleFileRelativeToEngineDirectory . IndexOf ( UEBuildModule . EditorFolder , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ModuleType = UEBuildModuleType . Editor ;
}
else if ( ModuleFileRelativeToEngineDirectory . IndexOf ( UEBuildModule . ProgramsFolder , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ModuleType = UEBuildModuleType . Program ;
}
return ModuleType ;
}
2015-03-27 07:15:32 -04:00
/ * *
* Checks what distribution level a particular path should have by checking for key folders anywhere in it
* /
public static UEBuildModuleDistribution GetModuleDistributionLevelBasedOnLocation ( string FilePath )
{
// Get full path to ensure all folder separators are the same
FilePath = Path . GetFullPath ( FilePath ) ;
// Check from highest to lowest (don't actually need to check 'Everyone')
for ( var DistributionLevel = UEBuildModuleDistribution . NoRedist ; DistributionLevel > UEBuildModuleDistribution . Public ; DistributionLevel - - )
{
var DistributionFolderName = String . Format ( "{0}{1}{0}" , Path . DirectorySeparatorChar , DistributionLevel . ToString ( ) ) ;
if ( FilePath . IndexOf ( DistributionFolderName , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
return DistributionLevel ;
}
if ( DistributionLevel = = UEBuildModuleDistribution . NotForLicensees )
{
// Extra checks for PS4 and XboxOne folders, which are equivalent to NotForLicensees
var PS4FolderName = String . Format ( "{0}ps4{0}" , Path . DirectorySeparatorChar ) ;
var XboxFolderName = String . Format ( "{0}xboxone{0}" , Path . DirectorySeparatorChar ) ;
if ( FilePath . IndexOf ( PS4FolderName , StringComparison . InvariantCultureIgnoreCase ) > = 0
| | FilePath . IndexOf ( XboxFolderName , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
return UEBuildModuleDistribution . NotForLicensees ;
}
}
}
return UEBuildModuleDistribution . Public ;
}
/ * *
* Determines the distribution level of a module based on its directory and includes .
* /
private void SetupModuleDistributionLevel ( )
{
List < string > PathsToCheck = new List < string > ( ) ;
PathsToCheck . Add ( ModuleDirectory ) ;
PathsToCheck . AddRange ( PublicIncludePaths ) ;
PathsToCheck . AddRange ( PrivateIncludePaths ) ;
// Not sure if these two are necessary as paths will usually be in basic includes too
PathsToCheck . AddRange ( PublicSystemIncludePaths ) ;
PathsToCheck . AddRange ( PublicLibraryPaths ) ;
DistributionLevel = UEBuildModuleDistribution . Public ;
// Keep checking as long as we haven't reached the maximum level
for ( int PathIndex = 0 ; PathIndex < PathsToCheck . Count & & DistributionLevel ! = UEBuildModuleDistribution . NoRedist ; + + PathIndex )
{
DistributionLevel = Utils . Max ( DistributionLevel , UEBuildModule . GetModuleDistributionLevelBasedOnLocation ( PathsToCheck [ PathIndex ] ) ) ;
}
}
2014-09-11 03:21:51 -04:00
/** Converts an optional string list parameter to a well-defined hash set. */
protected static HashSet < string > HashSetFromOptionalEnumerableStringParameter ( IEnumerable < string > InEnumerableStrings )
2014-03-14 14:13:41 -04:00
{
2014-09-11 03:21:51 -04:00
return InEnumerableStrings = = null ? new HashSet < string > ( ) : new HashSet < string > ( InEnumerableStrings ) ;
2014-03-14 14:13:41 -04:00
}
/** The target which owns this module. */
public readonly UEBuildTarget Target ;
/** The name that uniquely identifies the module. */
public readonly string Name ;
/** The type of module being built. Used to switch between debug/development and precompiled/source configurations. */
public UEBuildModuleType Type ;
2015-03-27 07:15:32 -04:00
/** The distribution level of the module being built. Used to check where build products are placed. */
public UEBuildModuleDistribution DistributionLevel ;
2014-03-14 14:13:41 -04:00
/** Path to the module directory */
public readonly string ModuleDirectory ;
2014-07-21 04:28:22 -04:00
/** Is this module allowed to be redistributed. */
private readonly bool? IsRedistributableOverride ;
/ * *
* Tells if this module can be redistributed .
*
* @returns True if this module can be redistributed . False otherwise .
* /
public bool IsRedistributable ( )
{
return IsRedistributableOverride . HasValue
? IsRedistributableOverride . Value
: ( Type ! = UEBuildModuleType . Developer & & Type ! = UEBuildModuleType . Editor ) ;
}
2014-03-14 14:13:41 -04:00
/** The binary the module will be linked into for the current target. Only set after UEBuildBinary.BindModules is called. */
public UEBuildBinary Binary = null ;
/** Whether this module is included in the current target. Only set after UEBuildBinary.BindModules is called. */
public bool bIncludedInTarget = false ;
2014-04-30 07:59:06 -04:00
2014-09-11 03:21:51 -04:00
protected readonly HashSet < string > PublicDefinitions ;
protected readonly HashSet < string > PublicIncludePaths ;
protected readonly HashSet < string > PrivateIncludePaths ;
protected readonly HashSet < string > PublicSystemIncludePaths ;
protected readonly HashSet < string > PublicLibraryPaths ;
protected readonly HashSet < string > PublicAdditionalLibraries ;
protected readonly HashSet < string > PublicFrameworks ;
protected readonly HashSet < string > PublicWeakFrameworks ;
protected readonly HashSet < UEBuildFramework > PublicAdditionalFrameworks ;
protected readonly HashSet < string > PublicAdditionalShadowFiles ;
protected readonly HashSet < UEBuildBundleResource > PublicAdditionalBundleResources ;
2014-03-14 14:13:41 -04:00
/** Names of modules with header files that this module's public interface needs access to. */
2014-09-11 03:21:51 -04:00
protected HashSet < string > PublicIncludePathModuleNames ;
2014-03-14 14:13:41 -04:00
/** Names of modules that this module's public interface depends on. */
2014-09-11 03:21:51 -04:00
protected HashSet < string > PublicDependencyModuleNames ;
2014-03-14 14:13:41 -04:00
/** Names of DLLs that this module should delay load */
2014-09-11 03:21:51 -04:00
protected HashSet < string > PublicDelayLoadDLLs ;
2014-03-14 14:13:41 -04:00
/** Names of modules with header files that this module's private implementation needs access to. */
2014-09-11 03:21:51 -04:00
protected HashSet < string > PrivateIncludePathModuleNames ;
2014-03-14 14:13:41 -04:00
/** Names of modules that this module's private implementation depends on. */
2014-09-11 03:21:51 -04:00
protected HashSet < string > PrivateDependencyModuleNames ;
2014-03-14 14:13:41 -04:00
/** If any of this module's dependent modules circularly reference this module, then they must be added to this list */
public HashSet < string > CircularlyReferencedDependentModules
{
get ;
protected set ;
}
/** Extra modules this module may require at run time */
2014-09-11 03:21:51 -04:00
protected HashSet < string > DynamicallyLoadedModuleNames ;
2014-03-14 14:13:41 -04:00
/** Extra modules this module may require at run time, that are on behalf of another platform (i.e. shader formats and the like) */
2014-09-11 03:21:51 -04:00
protected HashSet < string > PlatformSpecificDynamicallyLoadedModuleNames ;
2014-03-14 14:13:41 -04:00
2015-04-03 10:25:57 -04:00
/** Files which this module depends on at runtime. */
public List < RuntimeDependency > RuntimeDependencies ;
2014-03-14 14:13:41 -04:00
public UEBuildModule (
UEBuildTarget InTarget ,
string InName ,
UEBuildModuleType InType ,
string InModuleDirectory ,
2014-07-21 04:28:22 -04:00
bool? InIsRedistributableOverride ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPublicDefinitions = null ,
IEnumerable < string > InPublicIncludePaths = null ,
IEnumerable < string > InPublicSystemIncludePaths = null ,
IEnumerable < string > InPublicLibraryPaths = null ,
IEnumerable < string > InPublicAdditionalLibraries = null ,
IEnumerable < string > InPublicFrameworks = null ,
2014-06-18 15:57:40 -04:00
IEnumerable < string > InPublicWeakFrameworks = null ,
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
IEnumerable < UEBuildFramework > InPublicAdditionalFrameworks = null ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPublicAdditionalShadowFiles = null ,
2014-07-28 14:55:48 -04:00
IEnumerable < UEBuildBundleResource > InPublicAdditionalBundleResources = null ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPublicIncludePathModuleNames = null ,
IEnumerable < string > InPublicDependencyModuleNames = null ,
IEnumerable < string > InPublicDelayLoadDLLs = null ,
IEnumerable < string > InPrivateIncludePaths = null ,
IEnumerable < string > InPrivateIncludePathModuleNames = null ,
IEnumerable < string > InPrivateDependencyModuleNames = null ,
IEnumerable < string > InCircularlyReferencedDependentModules = null ,
IEnumerable < string > InDynamicallyLoadedModuleNames = null ,
2015-04-03 10:25:57 -04:00
IEnumerable < string > InPlatformSpecificDynamicallyLoadedModuleNames = null ,
IEnumerable < RuntimeDependency > InRuntimeDependencies = null
2014-03-14 14:13:41 -04:00
)
{
Target = InTarget ;
Name = InName ;
Type = InType ;
ModuleDirectory = InModuleDirectory ;
2014-09-11 03:21:51 -04:00
PublicDefinitions = HashSetFromOptionalEnumerableStringParameter ( InPublicDefinitions ) ;
PublicIncludePaths = HashSetFromOptionalEnumerableStringParameter ( InPublicIncludePaths ) ;
PublicSystemIncludePaths = HashSetFromOptionalEnumerableStringParameter ( InPublicSystemIncludePaths ) ;
PublicLibraryPaths = HashSetFromOptionalEnumerableStringParameter ( InPublicLibraryPaths ) ;
PublicAdditionalLibraries = HashSetFromOptionalEnumerableStringParameter ( InPublicAdditionalLibraries ) ;
PublicFrameworks = HashSetFromOptionalEnumerableStringParameter ( InPublicFrameworks ) ;
PublicWeakFrameworks = HashSetFromOptionalEnumerableStringParameter ( InPublicWeakFrameworks ) ;
PublicAdditionalFrameworks = InPublicAdditionalFrameworks = = null ? new HashSet < UEBuildFramework > ( ) : new HashSet < UEBuildFramework > ( InPublicAdditionalFrameworks ) ;
PublicAdditionalShadowFiles = HashSetFromOptionalEnumerableStringParameter ( InPublicAdditionalShadowFiles ) ;
PublicAdditionalBundleResources = InPublicAdditionalBundleResources = = null ? new HashSet < UEBuildBundleResource > ( ) : new HashSet < UEBuildBundleResource > ( InPublicAdditionalBundleResources ) ;
PublicIncludePathModuleNames = HashSetFromOptionalEnumerableStringParameter ( InPublicIncludePathModuleNames ) ;
PublicDependencyModuleNames = HashSetFromOptionalEnumerableStringParameter ( InPublicDependencyModuleNames ) ;
PublicDelayLoadDLLs = HashSetFromOptionalEnumerableStringParameter ( InPublicDelayLoadDLLs ) ;
PrivateIncludePaths = HashSetFromOptionalEnumerableStringParameter ( InPrivateIncludePaths ) ;
PrivateIncludePathModuleNames = HashSetFromOptionalEnumerableStringParameter ( InPrivateIncludePathModuleNames ) ;
PrivateDependencyModuleNames = HashSetFromOptionalEnumerableStringParameter ( InPrivateDependencyModuleNames ) ;
CircularlyReferencedDependentModules = new HashSet < string > ( HashSetFromOptionalEnumerableStringParameter ( InCircularlyReferencedDependentModules ) ) ;
DynamicallyLoadedModuleNames = HashSetFromOptionalEnumerableStringParameter ( InDynamicallyLoadedModuleNames ) ;
PlatformSpecificDynamicallyLoadedModuleNames = HashSetFromOptionalEnumerableStringParameter ( InPlatformSpecificDynamicallyLoadedModuleNames ) ;
2015-04-03 10:25:57 -04:00
RuntimeDependencies = ( InRuntimeDependencies = = null ) ? new List < RuntimeDependency > ( ) : new List < RuntimeDependency > ( InRuntimeDependencies ) ;
2014-07-21 04:28:22 -04:00
IsRedistributableOverride = InIsRedistributableOverride ;
2014-03-14 14:13:41 -04:00
2015-03-27 07:15:32 -04:00
SetupModuleDistributionLevel ( ) ;
2014-03-14 14:13:41 -04:00
Target . RegisterModule ( this ) ;
}
/** Adds a public definition */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicDefinition ( string Definition )
2014-03-14 14:13:41 -04:00
{
PublicDefinitions . Add ( Definition ) ;
}
/** Adds a public include path. */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicIncludePath ( string PathName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicIncludePaths . Contains ( PathName ) )
{
return ;
}
}
PublicIncludePaths . Add ( PathName ) ;
}
/** Adds a public library path */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicLibraryPath ( string PathName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicLibraryPaths . Contains ( PathName ) )
{
return ;
}
}
PublicLibraryPaths . Add ( PathName ) ;
}
/** Adds a public additional library */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicAdditionalLibrary ( string LibraryName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicAdditionalLibraries . Contains ( LibraryName ) )
{
return ;
}
}
PublicAdditionalLibraries . Add ( LibraryName ) ;
}
/** Adds a public framework */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicFramework ( string LibraryName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicFrameworks . Contains ( LibraryName ) )
{
return ;
}
}
PublicFrameworks . Add ( LibraryName ) ;
}
2014-06-18 15:57:40 -04:00
/** Adds a public weak framework */
public virtual void AddPublicWeakFramework ( string LibraryName , bool bCheckForDuplicates = true )
{
if ( bCheckForDuplicates = = true )
{
if ( PublicWeakFrameworks . Contains ( LibraryName ) )
{
return ;
}
}
PublicWeakFrameworks . Add ( LibraryName ) ;
}
2014-03-14 14:13:41 -04:00
/** Adds a public additional framework */
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
public virtual void AddPublicAdditionalFramework ( UEBuildFramework Framework , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
if ( PublicAdditionalFrameworks . Contains ( Framework ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
PublicAdditionalFrameworks . Add ( Framework ) ;
2014-03-14 14:13:41 -04:00
}
/** Adds a file that will be synced to a remote machine if a remote build is being executed */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicAdditionalShadowFile ( string FileName )
2014-03-14 14:13:41 -04:00
{
PublicAdditionalShadowFiles . Add ( FileName ) ;
}
2014-07-28 14:55:48 -04:00
/** Adds a file or folder that will be copied to Mac or iOS app bundle */
public virtual void AddAdditionalBundleResource ( UEBuildBundleResource Resource , bool bCheckForDuplicates = true )
{
if ( bCheckForDuplicates = = true )
{
if ( PublicAdditionalBundleResources . Contains ( Resource ) )
{
return ;
}
}
PublicAdditionalBundleResources . Add ( Resource ) ;
}
2014-03-14 14:13:41 -04:00
/** Adds a public include path module. */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicIncludePathModule ( string ModuleName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicIncludePathModuleNames . Contains ( ModuleName ) )
{
return ;
}
}
PublicIncludePathModuleNames . Add ( ModuleName ) ;
}
/** Adds a public dependency module. */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicDependencyModule ( string ModuleName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicDependencyModuleNames . Contains ( ModuleName ) )
{
return ;
}
}
PublicDependencyModuleNames . Add ( ModuleName ) ;
}
/** Adds a dynamically loaded module. */
2014-04-30 07:59:06 -04:00
public virtual void AddDynamicallyLoadedModule ( string ModuleName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( DynamicallyLoadedModuleNames . Contains ( ModuleName ) )
{
return ;
}
}
DynamicallyLoadedModuleNames . Add ( ModuleName ) ;
}
/** Adds a dynamically loaded module platform specifc. */
2014-04-30 07:59:06 -04:00
public virtual void AddPlatformSpecificDynamicallyLoadedModule ( string ModuleName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PlatformSpecificDynamicallyLoadedModuleNames . Contains ( ModuleName ) )
{
return ;
}
}
PlatformSpecificDynamicallyLoadedModuleNames . Add ( ModuleName ) ;
}
/** Adds a public delay load DLL */
2014-04-30 07:59:06 -04:00
public virtual void AddPublicDelayLoadDLLs ( string DelayLoadDLLName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PublicDelayLoadDLLs . Contains ( DelayLoadDLLName ) )
{
return ;
}
}
PublicDelayLoadDLLs . Add ( DelayLoadDLLName ) ;
}
/** Adds a private include path. */
2014-04-30 07:59:06 -04:00
public virtual void AddPrivateIncludePath ( string PathName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PrivateIncludePaths . Contains ( PathName ) )
{
return ;
}
}
PrivateIncludePaths . Add ( PathName ) ;
}
/** Adds a private include path module. */
2014-04-30 07:59:06 -04:00
public virtual void AddPrivateIncludePathModule ( string ModuleName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PrivateIncludePathModuleNames . Contains ( ModuleName ) )
{
return ;
}
}
PrivateIncludePathModuleNames . Add ( ModuleName ) ;
}
/** Adds a dependency module. */
2014-04-30 07:59:06 -04:00
public virtual void AddPrivateDependencyModule ( string ModuleName , bool bCheckForDuplicates = true )
2014-03-14 14:13:41 -04:00
{
if ( bCheckForDuplicates = = true )
{
if ( PrivateDependencyModuleNames . Contains ( ModuleName ) )
{
return ;
}
}
PrivateDependencyModuleNames . Add ( ModuleName ) ;
}
/** Tells the module that a specific dependency is circularly reference */
2014-04-30 07:59:06 -04:00
public virtual void AddCircularlyReferencedDependentModule ( string ModuleName )
2014-03-14 14:13:41 -04:00
{
CircularlyReferencedDependentModules . Add ( ModuleName ) ;
}
/** Adds an extra module name */
2014-04-30 07:59:06 -04:00
public virtual void AddExtraModuleName ( string ModuleName )
2014-03-14 14:13:41 -04:00
{
DynamicallyLoadedModuleNames . Add ( ModuleName ) ;
}
/ * *
* Clears all public include paths .
* /
internal void ClearPublicIncludePaths ( )
{
PublicIncludePaths . Clear ( ) ;
}
/ * *
* Clears all public library paths .
* This is to allow a given platform the opportunity to remove set libraries .
* /
internal void ClearPublicLibraryPaths ( )
{
PublicLibraryPaths . Clear ( ) ;
}
/ * *
* Clears all public additional libraries from the module .
* This is to allow a given platform the opportunity to remove set libraries .
* /
internal void ClearPublicAdditionalLibraries ( )
{
PublicAdditionalLibraries . Clear ( ) ;
}
/// <summary>
/// If present, remove the given library from the PublicAdditionalLibraries array
/// </summary>
/// <param name="InLibrary">The library to remove from the list</param>
internal void RemovePublicAdditionalLibrary ( string InLibrary )
{
PublicAdditionalLibraries . Remove ( InLibrary ) ;
}
/ * *
* If found , remove the given entry from the definitions of the module .
* /
internal void RemovePublicDefinition ( string InDefintion )
{
PublicDefinitions . Remove ( InDefintion ) ;
}
/** Sets up the environment for compiling any module that includes the public interface of this module. */
protected virtual void SetupPublicCompileEnvironment (
UEBuildBinary SourceBinary ,
bool bIncludePathsOnly ,
2015-03-21 11:34:08 -04:00
HashSet < string > IncludePaths ,
HashSet < string > SystemIncludePaths ,
List < string > Definitions ,
List < UEBuildFramework > AdditionalFrameworks ,
Dictionary < UEBuildModule , bool > VisitedModules
2014-03-14 14:13:41 -04:00
)
{
// 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.
2014-08-21 07:33:21 -04:00
AddIncludePathsWithChecks ( IncludePaths , PublicIncludePaths ) ;
AddIncludePathsWithChecks ( SystemIncludePaths , PublicSystemIncludePaths ) ;
2014-03-14 14:13:41 -04:00
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 )
{
2014-09-02 14:26:49 -04:00
string BinaryPath = Binary . Config . OutputFilePaths [ 0 ] ;
string SourceBinaryPath = SourceBinary . Config . OutputFilePaths [ 0 ] ;
2014-03-14 14:13:41 -04:00
if ( ProjectFileGenerator . bGenerateProjectFiles | | ( Binary . Config . Type = = UEBuildBinaryType . StaticLibrary ) )
{
// When generating IntelliSense files, never add dllimport/dllexport specifiers as it
// simply confuses the compiler
2014-07-31 09:34:11 -04:00
Definitions . Add ( Name . ToUpperInvariant ( ) + "_API=" ) ;
2014-03-14 14:13:41 -04:00
}
else if ( Binary = = SourceBinary )
{
if ( Binary . Config . bAllowExports )
{
2014-09-02 14:26:49 -04:00
Log . TraceVerbose ( "{0}: Exporting {1} from {2}" , Path . GetFileNameWithoutExtension ( SourceBinaryPath ) , Name , Path . GetFileNameWithoutExtension ( BinaryPath ) ) ;
2014-07-31 09:34:11 -04:00
Definitions . Add ( Name . ToUpperInvariant ( ) + "_API=DLLEXPORT" ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-09-02 14:26:49 -04:00
Log . TraceVerbose ( "{0}: Not importing/exporting {1} (binary: {2})" , Path . GetFileNameWithoutExtension ( SourceBinaryPath ) , Name , Path . GetFileNameWithoutExtension ( BinaryPath ) ) ;
2014-07-31 09:34:11 -04:00
Definitions . Add ( Name . ToUpperInvariant ( ) + "_API=" ) ;
2014-03-14 14:13:41 -04:00
}
}
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 )
{
2014-09-02 14:26:49 -04:00
Log . TraceVerbose ( "{0}: Include paths only for {1} (binary: {2})" , Path . GetFileNameWithoutExtension ( SourceBinaryPath ) , Name , Path . GetFileNameWithoutExtension ( BinaryPath ) ) ;
2014-07-31 09:34:11 -04:00
Definitions . Add ( Name . ToUpperInvariant ( ) + "_API=" ) ;
2014-03-14 14:13:41 -04:00
}
else if ( Binary . Config . bAllowExports )
{
2014-09-02 14:26:49 -04:00
Log . TraceVerbose ( "{0}: Importing {1} from {2}" , Path . GetFileNameWithoutExtension ( SourceBinaryPath ) , Name , Path . GetFileNameWithoutExtension ( BinaryPath ) ) ;
2014-07-31 09:34:11 -04:00
Definitions . Add ( Name . ToUpperInvariant ( ) + "_API=DLLIMPORT" ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-09-02 14:26:49 -04:00
Log . TraceVerbose ( "{0}: Not importing/exporting {1} (binary: {2})" , Path . GetFileNameWithoutExtension ( SourceBinaryPath ) , Name , Path . GetFileNameWithoutExtension ( BinaryPath ) ) ;
2014-07-31 09:34:11 -04:00
Definitions . Add ( Name . ToUpperInvariant ( ) + "_API=" ) ;
2014-03-14 14:13:41 -04:00
}
}
}
if ( ! bIncludePathsOnly )
{
// Recurse on this module's public dependencies.
foreach ( var DependencyName in PublicDependencyModuleNames )
{
var DependencyModule = Target . GetModuleByName ( DependencyName ) ;
2015-03-21 11:34:08 -04:00
DependencyModule . SetupPublicCompileEnvironment ( SourceBinary , bIncludePathsOnly , IncludePaths , SystemIncludePaths , Definitions , AdditionalFrameworks , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
}
}
// 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 ) ;
2015-03-21 11:34:08 -04:00
IncludePathModule . SetupPublicCompileEnvironment ( SourceBinary , bInnerIncludePathsOnly , IncludePaths , SystemIncludePaths , Definitions , AdditionalFrameworks , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
}
2014-05-19 06:57:00 -04:00
// Add the module's directory to the include path, so we can root #includes to it
2014-06-23 07:57:23 -04:00
IncludePaths . Add ( Utils . CleanDirectorySeparators ( Utils . MakePathRelativeTo ( ModuleDirectory , Path . Combine ( ProjectFileGenerator . RootRelativePath , "Engine/Source" ) ) , '/' ) ) ;
2014-07-01 11:28:39 -04:00
// Add the additional frameworks so that the compiler can know about their #include paths
AdditionalFrameworks . AddRange ( PublicAdditionalFrameworks ) ;
2014-12-04 11:18:56 -05:00
// Remember the module so we can refer to it when needed
foreach ( var Framework in PublicAdditionalFrameworks )
{
Framework . OwningModule = this ;
}
2014-03-14 14:13:41 -04:00
}
}
2014-08-21 07:33:21 -04:00
2014-08-22 08:28:48 -04:00
static Regex VCMacroRegex = new Regex ( @"\$\([A-Za-z0-9_]+\)" ) ;
2014-08-22 08:23:53 -04:00
/** Checks if path contains a VC macro */
protected bool DoesPathContainVCMacro ( string Path )
{
2014-08-22 08:28:48 -04:00
return VCMacroRegex . IsMatch ( Path ) ;
2014-08-22 08:23:53 -04:00
}
2014-08-21 07:33:21 -04:00
/** Adds PathsToAdd to IncludePaths, performing path normalization and ignoring duplicates. */
2014-09-11 03:21:51 -04:00
protected void AddIncludePathsWithChecks ( HashSet < string > IncludePaths , HashSet < string > PathsToAdd )
2014-08-21 07:33:21 -04:00
{
2014-09-11 05:47:22 -04:00
if ( ProjectFileGenerator . bGenerateProjectFiles )
2014-08-21 07:33:21 -04:00
{
2014-09-11 05:47:22 -04:00
// Extra checks are switched off for IntelliSense generation as they provide
// no additional value and cause performance impact.
IncludePaths . UnionWith ( PathsToAdd ) ;
}
else
{
foreach ( var Path in PathsToAdd )
2014-08-21 07:33:21 -04:00
{
2014-09-11 05:47:22 -04:00
var NormalizedPath = Path . TrimEnd ( '/' ) ;
// If path doesn't exist, it may contain VC macro (which is passed directly to and expanded by compiler).
if ( Directory . Exists ( NormalizedPath ) | | DoesPathContainVCMacro ( NormalizedPath ) )
{
IncludePaths . Add ( NormalizedPath ) ;
}
2014-08-21 07:33:21 -04:00
}
}
}
2014-03-14 14:13:41 -04:00
/** Sets up the environment for compiling this module. */
protected virtual void SetupPrivateCompileEnvironment (
2015-03-21 11:34:08 -04:00
HashSet < string > IncludePaths ,
HashSet < string > SystemIncludePaths ,
List < string > Definitions ,
List < UEBuildFramework > AdditionalFrameworks
2014-03-14 14:13:41 -04:00
)
{
var VisitedModules = new Dictionary < UEBuildModule , bool > ( ) ;
2014-10-30 17:10:56 -04:00
if ( this . Type = = UEBuildModuleType . Game )
{
Definitions . Add ( "DEPRECATED_FORGAME=DEPRECATED" ) ;
}
2014-03-14 14:13:41 -04:00
// Add this module's private include paths and definitions.
2014-08-21 07:33:21 -04:00
AddIncludePathsWithChecks ( IncludePaths , PrivateIncludePaths ) ;
2014-03-14 14:13:41 -04:00
// Allow the module's public dependencies to modify the compile environment.
bool bIncludePathsOnly = false ;
2015-03-21 11:34:08 -04:00
SetupPublicCompileEnvironment ( Binary , bIncludePathsOnly , IncludePaths , SystemIncludePaths , Definitions , AdditionalFrameworks , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
// Also allow the module's private dependencies to modify the compile environment.
foreach ( var DependencyName in PrivateDependencyModuleNames )
{
var DependencyModule = Target . GetModuleByName ( DependencyName ) ;
2015-03-21 11:34:08 -04:00
DependencyModule . SetupPublicCompileEnvironment ( Binary , bIncludePathsOnly , IncludePaths , SystemIncludePaths , Definitions , AdditionalFrameworks , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
}
// Add include paths from modules with header files that our private files need access to, but won't necessarily be importing
foreach ( var IncludePathModuleName in PrivateIncludePathModuleNames )
{
bool bInnerIncludePathsOnly = true ;
var IncludePathModule = Target . GetModuleByName ( IncludePathModuleName ) ;
2015-03-21 11:34:08 -04:00
IncludePathModule . SetupPublicCompileEnvironment ( Binary , bInnerIncludePathsOnly , IncludePaths , SystemIncludePaths , Definitions , AdditionalFrameworks , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
}
}
/** Sets up the environment for linking any module that includes the public interface of this module. */
protected virtual void SetupPublicLinkEnvironment (
UEBuildBinary SourceBinary ,
2015-03-21 11:34:08 -04:00
List < string > LibraryPaths ,
List < string > AdditionalLibraries ,
List < string > Frameworks ,
List < string > WeakFrameworks ,
List < UEBuildFramework > AdditionalFrameworks ,
List < string > AdditionalShadowFiles ,
List < UEBuildBundleResource > AdditionalBundleResources ,
List < string > DelayLoadDLLs ,
List < UEBuildBinary > BinaryDependencies ,
Dictionary < UEBuildModule , bool > VisitedModules
2014-03-14 14:13:41 -04:00
)
{
// 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 = = UEBuildBinaryType . StaticLibrary ) ;
bool bIsModuleBinaryAStaticLibrary = ( Binary ! = null & & Binary . Config . Type = = UEBuildBinaryType . 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 UEBuildExternalModule ! = null ) ;
bool bIsInStaticLibrary = ( DependencyModule . Binary ! = null & & DependencyModule . Binary . Config . Type = = UEBuildBinaryType . StaticLibrary ) ;
if ( bIsExternalModule | | bIsInStaticLibrary )
{
2015-03-21 11:34:08 -04:00
DependencyModule . SetupPublicLinkEnvironment ( SourceBinary , LibraryPaths , AdditionalLibraries , Frameworks , WeakFrameworks ,
AdditionalFrameworks , AdditionalShadowFiles , AdditionalBundleResources , DelayLoadDLLs , BinaryDependencies , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
}
}
}
// Add this module's public include library paths and additional libraries.
LibraryPaths . AddRange ( PublicLibraryPaths ) ;
AdditionalLibraries . AddRange ( PublicAdditionalLibraries ) ;
Frameworks . AddRange ( PublicFrameworks ) ;
2014-06-18 15:57:40 -04:00
WeakFrameworks . AddRange ( PublicWeakFrameworks ) ;
2014-07-28 14:55:48 -04:00
AdditionalBundleResources . AddRange ( PublicAdditionalBundleResources ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
// Remember the module so we can refer to it when needed
foreach ( var Framework in PublicAdditionalFrameworks )
{
Framework . OwningModule = this ;
}
2014-03-14 14:13:41 -04:00
AdditionalFrameworks . AddRange ( PublicAdditionalFrameworks ) ;
AdditionalShadowFiles . AddRange ( PublicAdditionalShadowFiles ) ;
DelayLoadDLLs . AddRange ( PublicDelayLoadDLLs ) ;
}
}
}
/** Sets up the environment for linking this module. */
public virtual void SetupPrivateLinkEnvironment (
2015-03-21 11:34:08 -04:00
LinkEnvironment LinkEnvironment ,
List < UEBuildBinary > BinaryDependencies ,
Dictionary < UEBuildModule , bool > VisitedModules
2014-03-14 14:13:41 -04:00
)
{
// Allow the module's public dependencies to add library paths and additional libraries to the link environment.
2015-03-21 11:34:08 -04:00
SetupPublicLinkEnvironment ( Binary , LinkEnvironment . Config . LibraryPaths , LinkEnvironment . Config . AdditionalLibraries , LinkEnvironment . Config . Frameworks , LinkEnvironment . Config . WeakFrameworks ,
LinkEnvironment . Config . AdditionalFrameworks , LinkEnvironment . Config . AdditionalShadowFiles , LinkEnvironment . Config . AdditionalBundleResources , LinkEnvironment . Config . DelayLoadDLLs , BinaryDependencies , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
// Also allow the module's public and private dependencies to modify the link environment.
List < string > AllDependencyModuleNames = new List < string > ( PrivateDependencyModuleNames ) ;
AllDependencyModuleNames . AddRange ( PublicDependencyModuleNames ) ;
foreach ( var DependencyName in AllDependencyModuleNames )
{
var DependencyModule = Target . GetModuleByName ( DependencyName ) ;
2015-03-21 11:34:08 -04:00
DependencyModule . SetupPublicLinkEnvironment ( Binary , LinkEnvironment . Config . LibraryPaths , LinkEnvironment . Config . AdditionalLibraries , LinkEnvironment . Config . Frameworks , LinkEnvironment . Config . WeakFrameworks ,
LinkEnvironment . Config . AdditionalFrameworks , LinkEnvironment . Config . AdditionalShadowFiles , LinkEnvironment . Config . AdditionalBundleResources , LinkEnvironment . Config . DelayLoadDLLs , BinaryDependencies , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
}
}
/** Compiles the module, and returns a list of files output by the compiler. */
2015-04-10 11:19:40 -04:00
public abstract List < FileItem > Compile ( CPPEnvironment GlobalCompileEnvironment , CPPEnvironment CompileEnvironment ) ;
2014-03-14 14:13:41 -04:00
// Object interface.
public override string ToString ( )
{
return Name ;
}
/ * *
* Gets all of the modules referenced by this module
*
* @param ReferencedModules Hash of all referenced modules
* @param OrderedModules Ordered list of the referenced modules
* @param bIncludeDynamicallyLoaded True if dynamically loaded modules ( and all of their dependent modules ) should be included .
2014-07-31 09:34:11 -04:00
* @param bForceCircular True if circular dependencies should be processed
* @param bOnlyDirectDependencies True to return only this module ' s direct dependencies
2014-03-14 14:13:41 -04:00
* /
2015-03-21 11:34:08 -04:00
public virtual void GetAllDependencyModules ( Dictionary < string , UEBuildModule > ReferencedModules , List < UEBuildModule > OrderedModules , bool bIncludeDynamicallyLoaded , bool bForceCircular , bool bOnlyDirectDependencies )
2014-03-14 14:13:41 -04:00
{
}
2015-03-20 08:25:23 -04:00
/ * *
* Gets all of the modules precompiled along with this module
*
* @param Modules Set of all the precompiled modules
* /
public virtual void RecursivelyAddPrecompiledModules ( List < UEBuildModule > Modules )
{
}
2014-03-14 14:13:41 -04:00
/ * *
* Gathers and binds binaries for this module and all of it ' s dependent modules
* /
2015-04-11 13:09:16 -04:00
public virtual void RecursivelyProcessUnboundModules ( )
2014-03-14 14:13:41 -04:00
{
}
/ * *
* Recursively adds modules that are referenced only for include paths ( not actual dependencies ) .
*
* @param Target The target we are currently building
* @param bPublicIncludesOnly True to only add modules for public includes , false to add all include path modules . Regardless of what you pass here , recursive adds will only add public include path modules .
* /
public virtual void RecursivelyAddIncludePathModules ( UEBuildTarget Target , bool bPublicIncludesOnly )
{
}
} ;
/** A module that is never compiled by us, and is only used to group include paths and libraries into a dependency unit. */
class UEBuildExternalModule : UEBuildModule
{
public UEBuildExternalModule (
UEBuildTarget InTarget ,
UEBuildModuleType InType ,
string InName ,
string InModuleDirectory ,
2014-07-21 04:28:22 -04:00
bool? InIsRedistributableOverride ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPublicDefinitions = null ,
IEnumerable < string > InPublicIncludePaths = null ,
IEnumerable < string > InPublicSystemIncludePaths = null ,
IEnumerable < string > InPublicLibraryPaths = null ,
IEnumerable < string > InPublicAdditionalLibraries = null ,
IEnumerable < string > InPublicFrameworks = null ,
2014-06-18 15:57:40 -04:00
IEnumerable < string > InPublicWeakFrameworks = null ,
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
IEnumerable < UEBuildFramework > InPublicAdditionalFrameworks = null ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPublicAdditionalShadowFiles = null ,
2014-07-28 14:55:48 -04:00
IEnumerable < UEBuildBundleResource > InPublicAdditionalBundleResources = null ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPublicDependencyModuleNames = null ,
2015-04-03 10:25:57 -04:00
IEnumerable < string > InPublicDelayLoadDLLs = null , // Delay loaded DLLs that should be setup when including this module
IEnumerable < RuntimeDependency > InRuntimeDependencies = null
2014-03-14 14:13:41 -04:00
)
: base (
InTarget : InTarget ,
InType : InType ,
InName : InName ,
InModuleDirectory : InModuleDirectory ,
2014-07-28 14:55:48 -04:00
InIsRedistributableOverride : InIsRedistributableOverride ,
2014-03-14 14:13:41 -04:00
InPublicDefinitions : InPublicDefinitions ,
InPublicIncludePaths : InPublicIncludePaths ,
InPublicSystemIncludePaths : InPublicSystemIncludePaths ,
InPublicLibraryPaths : InPublicLibraryPaths ,
InPublicAdditionalLibraries : InPublicAdditionalLibraries ,
InPublicFrameworks : InPublicFrameworks ,
2014-06-18 15:57:40 -04:00
InPublicWeakFrameworks : InPublicWeakFrameworks ,
InPublicAdditionalFrameworks : InPublicAdditionalFrameworks ,
2014-03-14 14:13:41 -04:00
InPublicAdditionalShadowFiles : InPublicAdditionalShadowFiles ,
2014-07-28 14:55:48 -04:00
InPublicAdditionalBundleResources : InPublicAdditionalBundleResources ,
2014-03-14 14:13:41 -04:00
InPublicDependencyModuleNames : InPublicDependencyModuleNames ,
2015-04-03 10:25:57 -04:00
InPublicDelayLoadDLLs : InPublicDelayLoadDLLs ,
InRuntimeDependencies : InRuntimeDependencies
2014-03-14 14:13:41 -04:00
)
{
bIncludedInTarget = true ;
}
// UEBuildModule interface.
2015-04-10 11:19:40 -04:00
public override List < FileItem > Compile ( CPPEnvironment GlobalCompileEnvironment , CPPEnvironment CompileEnvironment )
2014-03-14 14:13:41 -04:00
{
return new List < FileItem > ( ) ;
}
} ;
2014-12-17 12:37:39 -05:00
/** A module that is compiled from C++ code. */
2014-03-14 14:13:41 -04:00
public class UEBuildModuleCPP : UEBuildModule
{
2014-04-28 04:53:09 -04:00
public class AutoGenerateCppInfoClass
2014-04-23 20:18:55 -04:00
{
2014-08-02 09:44:00 -04:00
public class BuildInfoClass
2014-04-23 20:18:55 -04:00
{
2014-09-22 09:46:58 -04:00
/** The wildcard of the *.generated.cpp file which was generated for the module */
public readonly string FileWildcard ;
2014-04-23 20:18:55 -04:00
2014-09-22 09:46:58 -04:00
public BuildInfoClass ( string InWildcard )
2014-08-02 09:44:00 -04:00
{
2014-09-22 09:46:58 -04:00
Debug . Assert ( InWildcard ! = null ) ;
2014-08-02 09:44:00 -04:00
2014-09-22 09:46:58 -04:00
FileWildcard = InWildcard ;
2014-08-02 09:44:00 -04:00
}
}
/** Information about how to build the .generated.cpp files. If this is null, then we're not building .generated.cpp files for this module. */
public BuildInfoClass BuildInfo ;
public AutoGenerateCppInfoClass ( BuildInfoClass InBuildInfo )
{
BuildInfo = InBuildInfo ;
2014-04-23 20:18:55 -04:00
}
}
2014-08-02 09:44:00 -04:00
/** Information about the .generated.cpp file. If this is null then this module doesn't have any UHT-produced code. */
2014-04-28 04:53:09 -04:00
public AutoGenerateCppInfoClass AutoGenerateCppInfo = null ;
2014-04-23 20:18:55 -04:00
2014-04-28 04:53:09 -04:00
public class SourceFilesClass
2014-04-23 20:18:55 -04:00
{
public readonly List < FileItem > MissingFiles = new List < FileItem > ( ) ;
public readonly List < FileItem > CPPFiles = new List < FileItem > ( ) ;
public readonly List < FileItem > CFiles = new List < FileItem > ( ) ;
public readonly List < FileItem > CCFiles = new List < FileItem > ( ) ;
public readonly List < FileItem > MMFiles = new List < FileItem > ( ) ;
public readonly List < FileItem > RCFiles = new List < FileItem > ( ) ;
public readonly List < FileItem > OtherFiles = new List < FileItem > ( ) ;
2014-04-28 04:53:09 -04:00
public int Count
{
get
{
return MissingFiles . Count +
CPPFiles . Count +
CFiles . Count +
CCFiles . Count +
MMFiles . Count +
RCFiles . Count +
OtherFiles . Count ;
}
}
2014-04-23 20:18:55 -04:00
}
2014-10-30 10:07:51 -04:00
/ * *
* Adds additional source cpp files for this module .
*
* @param Files Files to add .
* /
public void AddAdditionalCPPFiles ( IEnumerable < FileItem > Files )
{
SourceFilesToBuild . CPPFiles . AddRange ( Files ) ;
}
2014-05-29 16:51:44 -04:00
/** A list of the absolute paths of source files to be built in this module. */
public readonly SourceFilesClass SourceFilesToBuild = new SourceFilesClass ( ) ;
2015-04-20 18:05:25 -04:00
/** The directory for this module's generated code */
public readonly string GeneratedCodeDirectory ;
2014-03-14 14:13:41 -04:00
/** The preprocessor definitions used to compile this module's private implementation. */
2014-09-11 03:21:51 -04:00
HashSet < string > Definitions ;
2014-03-14 14:13:41 -04:00
/// When set, allows this module to report compiler definitions and include paths for Intellisense
IntelliSenseGatherer IntelliSenseGatherer ;
/** Whether this module contains performance critical code. */
ModuleRules . CodeOptimization OptimizeCode = ModuleRules . CodeOptimization . Default ;
/ * * Whether this module should use a "shared PCH" header if possible . Disable this for modules that have lots of global includes
in a private PCH header ( e . g . game modules ) * /
public bool bAllowSharedPCH = true ;
/ * * Header file name for a shared PCH provided by this module . Must be a valid relative path to a public C + + header file .
This should only be set for header files that are included by a significant number of other C + + modules . * /
public string SharedPCHHeaderFile = String . Empty ;
/** Use run time type information */
public bool bUseRTTI = false ;
/** Enable buffer security checks. This should usually be enabled as it prevents severe security risks. */
public bool bEnableBufferSecurityChecks = true ;
/** If true and unity builds are enabled, this module will build without unity. */
public bool bFasterWithoutUnity = false ;
/** Overrides BuildConfiguration.MinFilesUsingPrecompiledHeader if non-zero. */
public int MinFilesUsingPrecompiledHeaderOverride = 0 ;
/** Enable exception handling */
public bool bEnableExceptions = false ;
2014-12-04 05:35:51 -05:00
public List < string > IncludeSearchPaths = new List < string > ( ) ;
2014-04-23 20:18:55 -04:00
public class ProcessedDependenciesClass
{
/** The file, if any, which is used as the unique PCH for this module */
public FileItem UniquePCHHeaderFile = null ;
}
2014-03-14 14:13:41 -04:00
2014-04-23 20:18:55 -04:00
/** The processed dependencies for the class */
public ProcessedDependenciesClass ProcessedDependencies = null ;
2014-03-14 14:13:41 -04:00
2014-12-17 12:37:39 -05:00
/** @hack to skip adding definitions to compile environment. They will be baked into source code by external code. */
public bool bSkipDefinitionsForCompileEnvironment = false ;
2014-05-29 16:51:44 -04:00
/** Categorizes source files into per-extension buckets */
private static void CategorizeSourceFiles ( IEnumerable < FileItem > InSourceFiles , SourceFilesClass OutSourceFiles )
{
foreach ( var SourceFile in InSourceFiles )
{
string Extension = Path . GetExtension ( SourceFile . AbsolutePath ) . ToUpperInvariant ( ) ;
if ( ! SourceFile . bExists )
{
OutSourceFiles . MissingFiles . Add ( SourceFile ) ;
}
else if ( Extension = = ".CPP" )
{
OutSourceFiles . CPPFiles . Add ( SourceFile ) ;
}
else if ( Extension = = ".C" )
{
OutSourceFiles . CFiles . Add ( SourceFile ) ;
}
else if ( Extension = = ".CC" )
{
OutSourceFiles . CCFiles . Add ( SourceFile ) ;
}
else if ( Extension = = ".MM" | | Extension = = ".M" )
{
OutSourceFiles . MMFiles . Add ( SourceFile ) ;
}
else if ( Extension = = ".RC" )
{
OutSourceFiles . RCFiles . Add ( SourceFile ) ;
}
else
{
OutSourceFiles . OtherFiles . Add ( SourceFile ) ;
}
}
}
2014-03-14 14:13:41 -04:00
public UEBuildModuleCPP (
UEBuildTarget InTarget ,
string InName ,
UEBuildModuleType InType ,
string InModuleDirectory ,
2015-04-20 18:05:25 -04:00
string InGeneratedCodeDirectory ,
2014-07-21 04:28:22 -04:00
bool? InIsRedistributableOverride ,
2014-03-14 14:13:41 -04:00
IntelliSenseGatherer InIntelliSenseGatherer ,
IEnumerable < FileItem > InSourceFiles ,
IEnumerable < string > InPublicIncludePaths ,
IEnumerable < string > InPublicSystemIncludePaths ,
2015-01-09 14:43:46 -05:00
IEnumerable < string > InPublicLibraryPaths ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InDefinitions ,
IEnumerable < string > InPublicIncludePathModuleNames ,
IEnumerable < string > InPublicDependencyModuleNames ,
IEnumerable < string > InPublicDelayLoadDLLs ,
IEnumerable < string > InPublicAdditionalLibraries ,
IEnumerable < string > InPublicFrameworks ,
2014-06-18 15:57:40 -04:00
IEnumerable < string > InPublicWeakFrameworks ,
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
IEnumerable < UEBuildFramework > InPublicAdditionalFrameworks ,
2014-04-30 14:09:06 -04:00
IEnumerable < string > InPublicAdditionalShadowFiles ,
2014-07-28 14:55:48 -04:00
IEnumerable < UEBuildBundleResource > InPublicAdditionalBundleResources ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPrivateIncludePaths ,
IEnumerable < string > InPrivateIncludePathModuleNames ,
IEnumerable < string > InPrivateDependencyModuleNames ,
IEnumerable < string > InCircularlyReferencedDependentModules ,
IEnumerable < string > InDynamicallyLoadedModuleNames ,
IEnumerable < string > InPlatformSpecificDynamicallyLoadedModuleNames ,
2015-04-03 10:25:57 -04:00
IEnumerable < RuntimeDependency > InRuntimeDependencies ,
2014-03-14 14:13:41 -04:00
ModuleRules . CodeOptimization InOptimizeCode ,
bool InAllowSharedPCH ,
string InSharedPCHHeaderFile ,
bool InUseRTTI ,
bool InEnableBufferSecurityChecks ,
bool InFasterWithoutUnity ,
int InMinFilesUsingPrecompiledHeaderOverride ,
bool InEnableExceptions ,
2014-05-29 16:51:44 -04:00
bool bInBuildSourceFiles
2014-03-14 14:13:41 -04:00
)
: base ( InTarget ,
InName ,
InType ,
InModuleDirectory ,
2014-07-21 04:28:22 -04:00
InIsRedistributableOverride ,
2014-03-14 14:13:41 -04:00
InDefinitions ,
InPublicIncludePaths ,
InPublicSystemIncludePaths ,
2015-01-09 14:43:46 -05:00
InPublicLibraryPaths ,
2014-03-14 14:13:41 -04:00
InPublicAdditionalLibraries ,
InPublicFrameworks ,
2014-06-18 15:57:40 -04:00
InPublicWeakFrameworks ,
2014-03-14 14:13:41 -04:00
InPublicAdditionalFrameworks ,
2014-04-30 14:09:06 -04:00
InPublicAdditionalShadowFiles ,
2014-07-28 14:55:48 -04:00
InPublicAdditionalBundleResources ,
2014-03-14 14:13:41 -04:00
InPublicIncludePathModuleNames ,
InPublicDependencyModuleNames ,
InPublicDelayLoadDLLs ,
InPrivateIncludePaths ,
InPrivateIncludePathModuleNames ,
InPrivateDependencyModuleNames ,
InCircularlyReferencedDependentModules ,
InDynamicallyLoadedModuleNames ,
2015-04-03 10:25:57 -04:00
InPlatformSpecificDynamicallyLoadedModuleNames ,
InRuntimeDependencies
2014-03-14 14:13:41 -04:00
)
{
2015-04-20 18:05:25 -04:00
GeneratedCodeDirectory = InGeneratedCodeDirectory ;
2014-03-14 14:13:41 -04:00
IntelliSenseGatherer = InIntelliSenseGatherer ;
2014-04-23 20:18:55 -04:00
2014-05-29 16:51:44 -04:00
if ( bInBuildSourceFiles )
2014-04-23 20:18:55 -04:00
{
2014-05-29 16:51:44 -04:00
CategorizeSourceFiles ( InSourceFiles , SourceFilesToBuild ) ;
2014-04-23 20:18:55 -04:00
}
2014-09-11 03:21:51 -04:00
Definitions = HashSetFromOptionalEnumerableStringParameter ( InDefinitions ) ;
2014-03-14 14:13:41 -04:00
foreach ( var Def in Definitions )
{
Log . TraceVerbose ( "Compile Env {0}: {1}" , Name , Def ) ;
}
OptimizeCode = InOptimizeCode ;
bAllowSharedPCH = InAllowSharedPCH ;
SharedPCHHeaderFile = InSharedPCHHeaderFile ;
bUseRTTI = InUseRTTI ;
bEnableBufferSecurityChecks = InEnableBufferSecurityChecks ;
bFasterWithoutUnity = InFasterWithoutUnity ;
MinFilesUsingPrecompiledHeaderOverride = InMinFilesUsingPrecompiledHeaderOverride ;
bEnableExceptions = InEnableExceptions ;
}
// UEBuildModule interface.
2015-04-10 11:19:40 -04:00
public override List < FileItem > Compile ( CPPEnvironment GlobalCompileEnvironment , CPPEnvironment CompileEnvironment )
2014-03-14 14:13:41 -04:00
{
2014-06-09 11:12:01 -04:00
var BuildPlatform = UEBuildPlatform . GetBuildPlatformForCPPTargetPlatform ( CompileEnvironment . Config . Target . Platform ) ;
2014-03-14 14:13:41 -04:00
var LinkInputFiles = new List < FileItem > ( ) ;
if ( ProjectFileGenerator . bGenerateProjectFiles & & IntelliSenseGatherer = = null )
{
// Nothing to do for IntelliSense, bail out early
return LinkInputFiles ;
}
2014-04-23 20:18:55 -04:00
var ModuleCompileEnvironment = CreateModuleCompileEnvironment ( CompileEnvironment ) ;
2014-12-04 05:35:51 -05:00
IncludeSearchPaths = ModuleCompileEnvironment . Config . CPPIncludeInfo . IncludePaths . ToList ( ) ;
IncludeSearchPaths . AddRange ( ModuleCompileEnvironment . Config . CPPIncludeInfo . SystemIncludePaths . ToList ( ) ) ;
2014-03-14 14:13:41 -04:00
if ( IntelliSenseGatherer ! = null )
{
// Update project file's set of preprocessor definitions and include paths
IntelliSenseGatherer . AddIntelliSensePreprocessorDefinitions ( ModuleCompileEnvironment . Config . Definitions ) ;
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
IntelliSenseGatherer . AddInteliiSenseIncludePaths ( ModuleCompileEnvironment . Config . CPPIncludeInfo . SystemIncludePaths , bAddingSystemIncludes : true ) ;
IntelliSenseGatherer . AddInteliiSenseIncludePaths ( ModuleCompileEnvironment . Config . CPPIncludeInfo . IncludePaths , bAddingSystemIncludes : false ) ;
2014-03-14 14:13:41 -04:00
// Bail out. We don't need to actually compile anything while generating project files.
return LinkInputFiles ;
}
2014-04-23 20:18:55 -04:00
// Throw an error if the module's source file list referenced any non-existent files.
2014-05-29 16:51:44 -04:00
if ( SourceFilesToBuild . MissingFiles . Count > 0 )
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
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 ,
2014-05-29 16:51:44 -04:00
string . Join ( "\n" , SourceFilesToBuild . MissingFiles . Select ( M = > M . AbsolutePath ) )
2014-04-23 20:18:55 -04:00
) ;
2014-03-14 14:13:41 -04:00
}
// 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
2014-05-29 16:51:44 -04:00
if ( SourceFilesToBuild . RCFiles . Count < = 0 )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
string DefRC = Utils . CleanDirectorySeparators ( Path . GetFullPath ( Path . Combine ( Directory . GetCurrentDirectory ( ) , "Runtime/Launch/Resources/Windows/PCLaunch.rc" ) ) ) ;
2014-03-14 14:13:41 -04:00
FileItem Item = FileItem . GetItemByFullPath ( DefRC ) ;
2014-05-29 16:51:44 -04:00
SourceFilesToBuild . RCFiles . Add ( Item ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-20 13:02:34 -04:00
// Always compile in the API version resource separately. This is required for the module manager to detect compatible API versions.
2014-07-31 09:34:11 -04:00
string ModuleVersionRC = Utils . CleanDirectorySeparators ( Path . GetFullPath ( Path . Combine ( Directory . GetCurrentDirectory ( ) , "Runtime/Core/Resources/Windows/ModuleVersionResource.rc.inl" ) ) ) ;
2014-06-20 13:02:34 -04:00
FileItem ModuleVersionItem = FileItem . GetItemByFullPath ( ModuleVersionRC ) ;
2014-07-31 09:34:11 -04:00
if ( ! SourceFilesToBuild . RCFiles . Contains ( ModuleVersionItem ) )
{
SourceFilesToBuild . RCFiles . Add ( ModuleVersionItem ) ;
}
2014-03-14 14:13:41 -04:00
}
2014-07-31 09:34:11 -04:00
{
// Process all of the header file dependencies for this module
this . CachePCHUsageForModuleSourceFiles ( ModuleCompileEnvironment ) ;
// Make sure our RC files have cached includes.
foreach ( var RCFile in SourceFilesToBuild . RCFiles )
{
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
RCFile . CachedCPPIncludeInfo = ModuleCompileEnvironment . Config . CPPIncludeInfo ;
2014-07-31 09:34:11 -04:00
}
}
2014-03-14 14:13:41 -04:00
// Check to see if this is an Engine module (including program or plugin modules). That is, the module is located under the "Engine" folder
var IsGameModule = ! Utils . IsFileUnderDirectory ( this . ModuleDirectory , Path . Combine ( ProjectFileGenerator . EngineRelativePath ) ) ;
// 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 ( MinFilesUsingPrecompiledHeaderOverride ! = 0 )
{
MinFilesUsingPrecompiledHeader = 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 ;
}
// Should we use unity build mode for this module?
2014-11-04 05:27:19 -05:00
bool bModuleUsesUnityBuild = BuildConfiguration . bUseUnityBuild | | BuildConfiguration . bForceUnityBuild ;
if ( ! BuildConfiguration . bForceUnityBuild )
2014-03-14 14:13:41 -04:00
{
2014-11-04 05:27:19 -05:00
if ( bFasterWithoutUnity )
{
bModuleUsesUnityBuild = false ;
}
else if ( IsGameModule & & SourceFilesToBuild . CPPFiles . Count < BuildConfiguration . MinGameModuleSourceFilesForUnityBuild )
{
// 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
bModuleUsesUnityBuild = false ;
}
2014-03-14 14:13:41 -04:00
}
2014-04-24 15:04:34 -04:00
// The environment with which to compile the CPP files
var CPPCompileEnvironment = ModuleCompileEnvironment ;
2014-03-14 14:13:41 -04:00
// Precompiled header support.
bool bWasModuleCodeCompiled = false ;
2014-06-09 11:12:01 -04:00
if ( BuildPlatform . ShouldUsePCHFiles ( CompileEnvironment . Config . Target . Platform , CompileEnvironment . Config . Target . Configuration ) )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
var PCHGenTimerStart = DateTime . UtcNow ;
2014-03-14 14:13:41 -04:00
// 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 ;
2015-04-10 11:19:40 -04:00
if ( BuildConfiguration . bUseSharedPCHs & & CompileEnvironment . Config . bIsBuildingLibrary )
2014-03-14 14:13:41 -04:00
{
2015-04-10 11:19:40 -04:00
Log . TraceVerbose ( "Module '{0}' was not allowed to use Shared PCHs, because we're compiling to a library" , this . Name ) ;
2014-03-14 14:13:41 -04:00
}
2015-04-10 11:19:40 -04:00
bool bUseSharedPCHFiles = BuildConfiguration . bUseSharedPCHs & & ! CompileEnvironment . Config . bIsBuildingLibrary & & GlobalCompileEnvironment . SharedPCHHeaderFiles . Count > 0 ;
2014-03-14 14:13:41 -04:00
2014-07-31 09:34:11 -04:00
if ( bUseSharedPCHFiles )
2014-07-16 12:13:57 -04:00
{
2014-07-31 09:34:11 -04:00
string SharingPCHHeaderFilePath = null ;
bool bIsASharedPCHModule = bUseSharedPCHFiles & & GlobalCompileEnvironment . SharedPCHHeaderFiles . Any ( PCH = > PCH . Module = = this ) ;
if ( bIsASharedPCHModule )
2014-06-04 08:05:42 -04:00
{
2014-07-31 09:34:11 -04:00
SharingPCHHeaderFilePath = Path . GetFullPath ( Path . Combine ( ProjectFileGenerator . RootRelativePath , "Engine" , "Source" , this . SharedPCHHeaderFile ) ) ;
2014-06-04 08:05:42 -04:00
}
2014-07-16 12:13:57 -04:00
2015-04-10 11:19:40 -04:00
// We can't use a shared PCH file when compiling a module
2014-07-31 09:34:11 -04:00
// with exports, because the shared PCH can only have imports in it to work correctly.
2015-04-10 11:19:40 -04:00
bool bCanModuleUseOwnSharedPCH = bAllowSharedPCH & & bIsASharedPCHModule & & ! Binary . Config . bAllowExports & & ProcessedDependencies . UniquePCHHeaderFile . AbsolutePath . Equals ( SharingPCHHeaderFilePath , StringComparison . InvariantCultureIgnoreCase ) ;
2014-07-31 09:34:11 -04:00
if ( bAllowSharedPCH & & ( ! bIsASharedPCHModule | | bCanModuleUseOwnSharedPCH ) )
2014-07-16 12:13:57 -04:00
{
2014-07-31 09:34:11 -04:00
// Figure out which shared PCH tier we're in
var DirectDependencyModules = new List < UEBuildModule > ( ) ;
{
var ReferencedModules = new Dictionary < string , UEBuildModule > ( StringComparer . InvariantCultureIgnoreCase ) ;
2015-03-21 11:34:08 -04:00
this . GetAllDependencyModules ( ReferencedModules , DirectDependencyModules , bIncludeDynamicallyLoaded : false , bForceCircular : false , bOnlyDirectDependencies : true ) ;
2014-07-31 09:34:11 -04:00
}
2014-07-16 12:13:57 -04:00
2014-07-31 09:34:11 -04:00
int LargestSharedPCHHeaderFileIndex = - 1 ;
foreach ( var DependencyModule in DirectDependencyModules )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
// These Shared PCHs are ordered from least complex to most complex. We'll start at the last one and search backwards.
for ( var SharedPCHHeaderFileIndex = GlobalCompileEnvironment . SharedPCHHeaderFiles . Count - 1 ; SharedPCHHeaderFileIndex > LargestSharedPCHHeaderFileIndex ; - - SharedPCHHeaderFileIndex )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
var CurSharedPCHHeaderFile = GlobalCompileEnvironment . SharedPCHHeaderFiles [ SharedPCHHeaderFileIndex ] ;
2014-03-14 14:13:41 -04:00
2014-07-31 09:34:11 -04:00
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 ;
2014-03-14 14:13:41 -04:00
}
}
2014-07-31 09:34:11 -04:00
if ( LargestSharedPCHHeaderFileIndex = = GlobalCompileEnvironment . SharedPCHHeaderFiles . Count - 1 )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
// We've determined that the module is using our most complex PCH header, so we can early-out
break ;
2014-03-14 14:13:41 -04:00
}
}
2014-07-31 09:34:11 -04:00
// 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 ) )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
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 ) ;
2014-03-14 14:13:41 -04:00
}
2014-12-17 09:40:26 -05:00
// Keep track of how many modules make use of this PCH for performance diagnostics
var LargestSharedPCHHeader = GlobalCompileEnvironment . SharedPCHHeaderFiles [ LargestSharedPCHHeaderFileIndex ] ;
+ + LargestSharedPCHHeader . NumModulesUsingThisPCH ;
2014-03-14 14:13:41 -04:00
}
2014-07-31 09:34:11 -04:00
else
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
Log . TraceVerbose ( "Module '{0}' cannot create or use Shared PCHs, because it needs its own private PCH" , this . Name ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-04-23 20:18:55 -04:00
// The precompiled header environment for all source files in this module that use a precompiled header, if we even need one
PrecompileHeaderEnvironment ModulePCHEnvironment = null ;
2014-03-14 14:13:41 -04:00
// 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.
2014-05-29 16:51:44 -04:00
if ( SharedPCHHeaderFile ! = null | | SourceFilesToBuild . CPPFiles . Count > = MinFilesUsingPrecompiledHeader )
2014-03-14 14:13:41 -04:00
{
2014-04-24 15:04:34 -04:00
FileItem PCHToUse ;
2014-03-14 14:13:41 -04:00
if ( SharedPCHHeaderFile ! = null )
{
2014-05-29 16:51:44 -04:00
ModulePCHEnvironment = ApplySharedPCH ( GlobalCompileEnvironment , CompileEnvironment , ModuleCompileEnvironment , SourceFilesToBuild . CPPFiles , ref SharedPCHHeaderFile ) ;
2014-04-23 20:18:55 -04:00
if ( ModulePCHEnvironment ! = null )
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
// @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
2014-07-31 09:34:11 -04:00
// include it first during the build phase. This could create problems with deterministic builds, or turn up compile
2014-04-23 20:18:55 -04:00
// errors unexpectedly due to compile environment differences.
2014-07-16 12:13:57 -04:00
Log . TraceVerbose ( "Module " + Name + " uses existing Shared PCH '" + ModulePCHEnvironment . PrecompiledHeaderIncludeFilename + "' (from module " + ModulePCHEnvironment . ModuleName + ")" ) ;
2014-04-23 20:18:55 -04:00
}
2014-04-24 15:04:34 -04:00
PCHToUse = SharedPCHHeaderFile ;
}
else
{
PCHToUse = ProcessedDependencies . UniquePCHHeaderFile ;
}
if ( PCHToUse ! = null )
{
// Update all CPPFiles to point to the PCH
2014-05-29 16:51:44 -04:00
foreach ( var CPPFile in SourceFilesToBuild . CPPFiles )
2014-04-23 20:18:55 -04:00
{
2014-04-24 15:04:34 -04:00
CPPFile . PCHHeaderNameInCode = PCHToUse . AbsolutePath ;
CPPFile . PrecompiledHeaderIncludeFilename = PCHToUse . AbsolutePath ;
2014-03-14 14:13:41 -04:00
}
}
// A shared PCH was not already set up for us, so set one up.
if ( ModulePCHEnvironment = = null )
{
2014-04-23 20:18:55 -04:00
var PCHHeaderFile = ProcessedDependencies . UniquePCHHeaderFile ;
2014-03-14 14:13:41 -04:00
var PCHModuleName = this . Name ;
if ( SharedPCHHeaderFile ! = null )
{
PCHHeaderFile = SharedPCHHeaderFile ;
PCHModuleName = SharedPCHModuleName ;
}
2014-05-29 16:51:44 -04:00
var PCHHeaderNameInCode = SourceFilesToBuild . CPPFiles [ 0 ] . PCHHeaderNameInCode ;
2014-03-14 14:13:41 -04:00
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 ) ;
2014-07-16 12:13:57 -04:00
Log . TraceVerbose ( "Module " + Name + " uses new Shared PCH '" + ModulePCHEnvironment . PrecompiledHeaderIncludeFilename + "'" ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-07-16 12:13:57 -04:00
Log . TraceVerbose ( "Module " + Name + " uses a Unique PCH '" + ModulePCHEnvironment . PrecompiledHeaderIncludeFilename + "'" ) ;
2014-03-14 14:13:41 -04:00
}
}
}
2014-07-16 12:13:57 -04:00
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." ) ;
}
2014-03-14 14:13:41 -04:00
// 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.
2014-05-22 04:16:41 -04:00
var ModulePCHCompileEnvironment = ModuleCompileEnvironment . DeepCopy ( ) ;
2014-04-23 20:18:55 -04:00
ModulePCHCompileEnvironment . Config . PrecompiledHeaderAction = PrecompiledHeaderAction . Include ;
ModulePCHCompileEnvironment . Config . PrecompiledHeaderIncludeFilename = ModulePCHEnvironment . PrecompiledHeaderIncludeFilename . AbsolutePath ;
ModulePCHCompileEnvironment . Config . PCHHeaderNameInCode = ModulePCHEnvironment . PCHHeaderNameInCode ;
2014-03-14 14:13:41 -04:00
2014-04-23 20:18:55 -04:00
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 ;
2014-03-14 14:13:41 -04:00
}
2014-05-29 16:51:44 -04:00
var CPPFilesToBuild = SourceFilesToBuild . CPPFiles ;
2014-03-14 14:13:41 -04:00
if ( bModuleUsesUnityBuild )
{
// unity files generated for only the set of files which share the same PCH environment
2014-07-31 09:34:11 -04:00
CPPFilesToBuild = Unity . GenerateUnityCPPs ( Target , CPPFilesToBuild , ModulePCHCompileEnvironment , Name ) ;
2014-03-14 14:13:41 -04:00
}
// Check if there are enough unity files to warrant pch generation (and we haven't already generated the shared one)
2014-07-16 12:13:57 -04:00
if ( ModulePCHEnvironment . PrecompiledHeaderFile = = null )
2014-03-14 14:13:41 -04:00
{
2014-07-16 12:13:57 -04:00
if ( SharedPCHHeaderFile ! = null | | CPPFilesToBuild . Count > = MinFilesUsingPrecompiledHeader )
2014-03-14 14:13:41 -04:00
{
2014-07-16 12:13:57 -04:00
bool bAllowDLLExports = true ;
var PCHOutputDirectory = ModuleCompileEnvironment . Config . OutputDirectory ;
var PCHModuleName = this . Name ;
2014-03-14 14:13:41 -04:00
2014-07-16 12:13:57 -04:00
if ( SharedPCHHeaderFile ! = null )
{
// Disallow DLLExports when generating shared PCHs. These headers aren't able to export anything, because they're potentially shared between many modules.
bAllowDLLExports = false ;
2014-03-14 14:13:41 -04:00
2014-07-16 12:13:57 -04:00
// Save shared PCHs to a specific folder
PCHOutputDirectory = Path . Combine ( CompileEnvironment . Config . OutputDirectory , "SharedPCHs" ) ;
2014-03-14 14:13:41 -04:00
2014-07-16 12:13:57 -04:00
// Use a fake module name for "shared" PCHs. It may be used by many modules, so we don't want to use this module's name.
PCHModuleName = "Shared" ;
}
var PCHOutput = PrecompileHeaderEnvironment . GeneratePCHCreationAction (
2014-07-31 09:34:11 -04:00
Target ,
2014-07-16 12:13:57 -04:00
CPPFilesToBuild [ 0 ] . PCHHeaderNameInCode ,
ModulePCHEnvironment . PrecompiledHeaderIncludeFilename ,
ModuleCompileEnvironment ,
PCHOutputDirectory ,
PCHModuleName ,
bAllowDLLExports ) ;
ModulePCHEnvironment . PrecompiledHeaderFile = PCHOutput . PrecompiledHeaderFile ;
2014-03-14 14:13:41 -04:00
2014-07-16 12:13:57 -04:00
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." ) ;
}
2014-03-14 14:13:41 -04:00
}
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 ;
2014-04-24 15:04:34 -04:00
// Use this compile environment from now on
CPPCompileEnvironment = ModulePCHCompileEnvironment ;
2014-03-14 14:13:41 -04:00
}
2014-04-24 15:04:34 -04:00
2014-07-31 09:34:11 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileFiles ( Target , CPPFilesToBuild , Name ) . ObjectFiles ) ;
2014-03-14 14:13:41 -04:00
bWasModuleCodeCompiled = true ;
}
if ( BuildConfiguration . bPrintPerformanceInfo )
{
2014-07-31 09:34:11 -04:00
var PCHGenTime = ( DateTime . UtcNow - PCHGenTimerStart ) . TotalSeconds ;
TotalPCHGenTime + = PCHGenTime ;
2014-03-14 14:13:41 -04:00
}
}
2014-05-29 16:51:44 -04:00
if ( ! bWasModuleCodeCompiled & & SourceFilesToBuild . CPPFiles . Count > 0 )
2014-03-14 14:13:41 -04:00
{
2014-05-29 16:51:44 -04:00
var CPPFilesToCompile = SourceFilesToBuild . CPPFiles ;
2014-04-23 20:18:55 -04:00
if ( bModuleUsesUnityBuild )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
CPPFilesToCompile = Unity . GenerateUnityCPPs ( Target , CPPFilesToCompile , CPPCompileEnvironment , Name ) ;
2014-03-14 14:13:41 -04:00
}
2014-07-31 09:34:11 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileFiles ( Target , CPPFilesToCompile , Name ) . ObjectFiles ) ;
2014-04-23 20:18:55 -04:00
}
2014-08-02 09:44:00 -04:00
if ( AutoGenerateCppInfo ! = null & & AutoGenerateCppInfo . BuildInfo ! = null & & ! CPPCompileEnvironment . bHackHeaderGenerator )
2014-04-23 20:18:55 -04:00
{
2014-09-22 09:46:58 -04:00
string [ ] GeneratedFiles = Directory . GetFiles ( Path . GetDirectoryName ( AutoGenerateCppInfo . BuildInfo . FileWildcard ) , Path . GetFileName ( AutoGenerateCppInfo . BuildInfo . FileWildcard ) ) ;
foreach ( string GeneratedFilename in GeneratedFiles )
{
var GeneratedCppFileItem = FileItem . GetItemByPath ( GeneratedFilename ) ;
2014-04-23 20:18:55 -04:00
2014-09-22 09:46:58 -04:00
CachePCHUsageForModuleSourceFile ( this . Target , CPPCompileEnvironment , GeneratedCppFileItem ) ;
2014-07-31 09:34:11 -04:00
2015-01-07 14:16:46 -05:00
// @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?)
2014-09-22 09:46:58 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileFiles ( Target , new List < FileItem > { GeneratedCppFileItem } , Name ) . ObjectFiles ) ;
}
2014-03-14 14:13:41 -04:00
}
// Compile C files directly.
2014-07-31 09:34:11 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileFiles ( Target , SourceFilesToBuild . CFiles , Name ) . ObjectFiles ) ;
2014-03-14 14:13:41 -04:00
// Compile CC files directly.
2014-07-31 09:34:11 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileFiles ( Target , SourceFilesToBuild . CCFiles , Name ) . ObjectFiles ) ;
2014-03-14 14:13:41 -04:00
// Compile MM files directly.
2014-07-31 09:34:11 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileFiles ( Target , SourceFilesToBuild . MMFiles , Name ) . ObjectFiles ) ;
2014-03-14 14:13:41 -04:00
// Compile RC files.
2014-07-31 09:34:11 -04:00
LinkInputFiles . AddRange ( CPPCompileEnvironment . CompileRCFiles ( Target , SourceFilesToBuild . RCFiles ) . ObjectFiles ) ;
2014-03-14 14:13:41 -04:00
2014-04-23 20:18:55 -04:00
return LinkInputFiles ;
}
2014-04-24 15:04:34 -04:00
private PrecompileHeaderEnvironment ApplySharedPCH ( CPPEnvironment GlobalCompileEnvironment , CPPEnvironment CompileEnvironment , CPPEnvironment ModuleCompileEnvironment , List < FileItem > CPPFiles , ref FileItem SharedPCHHeaderFile )
2014-04-23 20:18:55 -04:00
{
// Check to see if we have a PCH header already setup that we can use
2014-04-24 15:04:34 -04:00
var SharedPCHHeaderFileCopy = SharedPCHHeaderFile ;
var SharedPCHEnvironment = GlobalCompileEnvironment . SharedPCHEnvironments . Find ( Env = > Env . PrecompiledHeaderIncludeFilename = = SharedPCHHeaderFileCopy ) ;
2014-04-23 20:18:55 -04:00
if ( SharedPCHEnvironment = = null )
2014-07-31 09:34:11 -04:00
{
2014-04-23 20:18:55 -04:00
return null ;
2014-07-31 09:34:11 -04:00
}
2014-04-23 20:18:55 -04:00
// Don't mix CLR modes
if ( SharedPCHEnvironment . CLRMode ! = ModuleCompileEnvironment . Config . CLRMode )
2014-03-14 14:13:41 -04:00
{
2014-07-16 12:13:57 -04:00
Log . TraceVerbose ( "Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because CLR modes don't match" , Name , SharedPCHEnvironment . PrecompiledHeaderIncludeFilename . AbsolutePath , SharedPCHEnvironment . ModuleName ) ;
2014-04-24 15:04:34 -04:00
SharedPCHHeaderFile = null ;
2014-04-23 20:18:55 -04:00
return null ;
}
2014-12-15 11:34:00 -05:00
// Don't mix RTTI modes
if ( bUseRTTI )
{
Log . TraceVerbose ( "Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because RTTI modes don't match" , Name , SharedPCHEnvironment . PrecompiledHeaderIncludeFilename . AbsolutePath , SharedPCHEnvironment . ModuleName ) ;
SharedPCHHeaderFile = null ;
return null ;
}
2014-04-23 20:18:55 -04:00
// Don't mix non-optimized code with optimized code (PCHs won't be compatible)
var SharedPCHCodeOptimization = SharedPCHEnvironment . OptimizeCode ;
var ModuleCodeOptimization = ModuleCompileEnvironment . Config . OptimizeCode ;
2014-06-09 11:12:01 -04:00
if ( CompileEnvironment . Config . Target . Configuration ! = CPPTargetConfiguration . Debug )
2014-04-23 20:18:55 -04:00
{
if ( SharedPCHCodeOptimization = = ModuleRules . CodeOptimization . InNonDebugBuilds )
2014-03-14 14:13:41 -04:00
{
2014-04-23 20:18:55 -04:00
SharedPCHCodeOptimization = ModuleRules . CodeOptimization . Always ;
}
2014-03-14 14:13:41 -04:00
2014-04-23 20:18:55 -04:00
if ( ModuleCodeOptimization = = ModuleRules . CodeOptimization . InNonDebugBuilds )
{
ModuleCodeOptimization = ModuleRules . CodeOptimization . Always ;
2014-03-14 14:13:41 -04:00
}
}
2014-04-23 20:18:55 -04:00
if ( SharedPCHCodeOptimization ! = ModuleCodeOptimization )
{
2014-07-16 12:13:57 -04:00
Log . TraceVerbose ( "Module {0} cannot use existing Shared PCH '{1}' (from module '{2}') because optimization levels don't match" , Name , SharedPCHEnvironment . PrecompiledHeaderIncludeFilename . AbsolutePath , SharedPCHEnvironment . ModuleName ) ;
2014-04-24 15:04:34 -04:00
SharedPCHHeaderFile = null ;
2014-04-23 20:18:55 -04:00
return null ;
}
return SharedPCHEnvironment ;
}
2014-07-31 09:34:11 -04:00
public static FileItem CachePCHUsageForModuleSourceFile ( UEBuildTarget Target , CPPEnvironment ModuleCompileEnvironment , FileItem CPPFile )
{
2014-08-19 08:19:14 -04:00
if ( ! CPPFile . bExists )
{
throw new BuildException ( "Required source file not found: " + CPPFile . AbsolutePath ) ;
}
2014-07-31 09:34:11 -04:00
var PCHCacheTimerStart = DateTime . UtcNow ;
var BuildPlatform = UEBuildPlatform . GetBuildPlatformForCPPTargetPlatform ( ModuleCompileEnvironment . Config . Target . Platform ) ;
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
var IncludePathsToSearch = ModuleCompileEnvironment . Config . CPPIncludeInfo . GetIncludesPathsToSearch ( CPPFile ) ;
2014-07-31 09:34:11 -04:00
// Store the module compile environment along with the .cpp file. This is so that we can use it later on when looking
// for header dependencies
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
CPPFile . CachedCPPIncludeInfo = ModuleCompileEnvironment . Config . CPPIncludeInfo ;
2014-07-31 09:34:11 -04:00
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
var PCHFile = CachePCHUsageForCPPFile ( Target , CPPFile , BuildPlatform , IncludePathsToSearch , ModuleCompileEnvironment . Config . CPPIncludeInfo . IncludeFileSearchDictionary ) ;
2014-07-31 09:34:11 -04:00
if ( BuildConfiguration . bPrintPerformanceInfo )
{
var PCHCacheTime = ( DateTime . UtcNow - PCHCacheTimerStart ) . TotalSeconds ;
TotalPCHCacheTime + = PCHCacheTime ;
}
return PCHFile ;
}
public void CachePCHUsageForModuleSourceFiles ( CPPEnvironment ModuleCompileEnvironment )
2014-04-23 20:18:55 -04:00
{
2014-07-18 14:20:08 -04:00
if ( ProcessedDependencies = = null )
2014-04-23 20:18:55 -04:00
{
2014-07-31 09:34:11 -04:00
var PCHCacheTimerStart = DateTime . UtcNow ;
var BuildPlatform = UEBuildPlatform . GetBuildPlatformForCPPTargetPlatform ( ModuleCompileEnvironment . Config . Target . Platform ) ;
bool bFoundAProblemWithPCHs = false ;
2014-07-18 14:20:08 -04:00
FileItem UniquePCH = null ;
2015-01-07 14:16:46 -05:00
foreach ( var CPPFile in SourceFilesToBuild . CPPFiles ) // @todo ubtmake: We're not caching CPPEnvironments for .c/.mm files, etc. Even though they don't use PCHs, they still have #includes! This can break dependency checking!
2014-07-18 14:20:08 -04:00
{
2014-07-31 09:34:11 -04:00
// Build a single list of include paths to search.
2015-01-07 14:16:46 -05:00
var IncludePathsToSearch = ModuleCompileEnvironment . Config . CPPIncludeInfo . GetIncludesPathsToSearch ( CPPFile ) ;
2014-07-31 09:34:11 -04:00
// Store the module compile environment along with the .cpp file. This is so that we can use it later on when looking
// for header dependencies
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
CPPFile . CachedCPPIncludeInfo = ModuleCompileEnvironment . Config . CPPIncludeInfo ;
2014-07-31 09:34:11 -04:00
2014-07-18 14:20:08 -04:00
// Find headers used by the source file.
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
var PCH = UEBuildModuleCPP . CachePCHUsageForCPPFile ( Target , CPPFile , BuildPlatform , IncludePathsToSearch , ModuleCompileEnvironment . Config . CPPIncludeInfo . IncludeFileSearchDictionary ) ;
2014-07-31 09:34:11 -04:00
if ( PCH = = null )
{
throw new BuildException ( "Source file \"{0}\" is not including any headers. We expect all modules to include a header file for precompiled header generation. Please add an #include statement." , CPPFile . AbsolutePath ) ;
}
if ( UniquePCH = = null )
{
UniquePCH = PCH ;
}
2015-01-07 14:16:46 -05:00
else if ( ! UniquePCH . Info . Name . Equals ( PCH . Info . Name , StringComparison . InvariantCultureIgnoreCase ) ) // @todo ubtmake: We do a string compare on the file name (not path) here, because sometimes the include resolver will pick an Intermediate copy of a PCH header file and throw off our comparisons
2014-07-31 09:34:11 -04:00
{
// OK, looks like we have multiple source files including a different header file first. We'll keep track of this and print out
// helpful information afterwards.
bFoundAProblemWithPCHs = true ;
}
2014-07-18 14:20:08 -04:00
}
2014-04-23 20:18:55 -04:00
2014-07-18 14:20:08 -04:00
ProcessedDependencies = new ProcessedDependenciesClass { UniquePCHHeaderFile = UniquePCH } ;
2014-07-31 09:34:11 -04:00
if ( bFoundAProblemWithPCHs )
{
// Map from pch header string to the source files that use that PCH
var UsageMapPCH = new Dictionary < string , List < FileItem > > ( StringComparer . InvariantCultureIgnoreCase ) ;
2015-01-07 14:16:46 -05:00
foreach ( var CPPFile in SourceFilesToBuild . CPPFiles )
2014-07-31 09:34:11 -04:00
{
// Create a new entry if not in the pch usage map
UsageMapPCH . GetOrAddNew ( CPPFile . PrecompiledHeaderIncludeFilename ) . Add ( CPPFile ) ;
}
if ( BuildConfiguration . bPrintDebugInfo )
{
Log . TraceVerbose ( "{0} PCH files for module {1}:" , UsageMapPCH . Count , Name ) ;
int MostFilesIncluded = 0 ;
foreach ( var CurPCH in UsageMapPCH )
{
if ( CurPCH . Value . Count > MostFilesIncluded )
{
MostFilesIncluded = CurPCH . Value . Count ;
}
Log . TraceVerbose ( " {0} ({1} files including it: {2}, ...)" , CurPCH . Key , CurPCH . Value . Count , CurPCH . Value [ 0 ] . AbsolutePath ) ;
}
}
if ( UsageMapPCH . Count > 1 )
{
// Keep track of the PCH file that is most used within this module
string MostFilesAreIncludingPCH = string . Empty ;
int MostFilesIncluded = 0 ;
foreach ( var CurPCH in UsageMapPCH . Where ( PCH = > PCH . Value . Count > MostFilesIncluded ) )
{
MostFilesAreIncludingPCH = CurPCH . Key ;
MostFilesIncluded = CurPCH . Value . Count ;
}
// Find all of the files that are not including our "best" PCH header
var FilesNotIncludingBestPCH = new StringBuilder ( ) ;
foreach ( var CurPCH in UsageMapPCH . Where ( PCH = > PCH . Key ! = MostFilesAreIncludingPCH ) )
{
foreach ( var SourceFile in CurPCH . Value )
{
FilesNotIncludingBestPCH . AppendFormat ( "{0} (including {1})\n" , SourceFile . AbsolutePath , CurPCH . Key ) ;
}
}
// Bail out and let the user know which source files may need to be fixed up
throw new BuildException (
"All source files in module \"{0}\" must include the same precompiled header first. Currently \"{1}\" is included by most of the source files. The following source files are not including \"{1}\" as their first include:\n\n{2}" ,
Name ,
MostFilesAreIncludingPCH ,
FilesNotIncludingBestPCH ) ;
}
}
if ( BuildConfiguration . bPrintPerformanceInfo )
{
var PCHCacheTime = ( DateTime . UtcNow - PCHCacheTimerStart ) . TotalSeconds ;
TotalPCHCacheTime + = PCHCacheTime ;
}
2014-07-18 14:20:08 -04:00
}
2014-04-23 20:18:55 -04:00
}
2014-07-31 09:34:11 -04:00
private static FileItem CachePCHUsageForCPPFile ( UEBuildTarget Target , FileItem CPPFile , IUEBuildPlatform BuildPlatform , List < string > IncludePathsToSearch , Dictionary < string , FileItem > IncludeFileSearchDictionary )
2014-04-23 20:18:55 -04:00
{
2015-01-07 14:16:46 -05:00
// @todo ubtmake: We don't really need to scan every file looking for PCH headers, just need one. The rest is just for error checking.
// @todo ubtmake: We don't need all of the direct includes either. We just need the first, unless we want to check for errors.
2014-07-31 09:34:11 -04:00
bool HasUObjects ;
List < DependencyInclude > DirectIncludeFilenames = CPPEnvironment . GetDirectIncludeDependencies ( Target , CPPFile , BuildPlatform , bOnlyCachedDependencies : false , HasUObjects : out HasUObjects ) ;
2014-04-23 20:18:55 -04:00
if ( BuildConfiguration . bPrintDebugInfo )
{
Log . TraceVerbose ( "Found direct includes for {0}: {1}" , Path . GetFileName ( CPPFile . AbsolutePath ) , string . Join ( ", " , DirectIncludeFilenames . Select ( F = > F . IncludeName ) ) ) ;
}
if ( DirectIncludeFilenames . Count = = 0 )
2014-07-18 14:20:08 -04:00
{
2014-04-23 20:18:55 -04:00
return null ;
2014-07-18 14:20:08 -04:00
}
2014-04-23 20:18:55 -04:00
var FirstInclude = DirectIncludeFilenames [ 0 ] ;
// The pch header should always be the first include in the source file.
// NOTE: This is not an absolute path. This is just the literal include string from the source file!
CPPFile . PCHHeaderNameInCode = FirstInclude . IncludeName ;
// Resolve the PCH header to an absolute path.
// Check NullOrEmpty here because if the file could not be resolved we need to throw an exception
if ( ! string . IsNullOrEmpty ( FirstInclude . IncludeResolvedName ) & &
// ignore any preexisting resolve cache if we are not configured to use it.
BuildConfiguration . bUseIncludeDependencyResolveCache & &
// if we are testing the resolve cache, we force UBT to resolve every time to look for conflicts
! BuildConfiguration . bTestIncludeDependencyResolveCache )
{
CPPFile . PrecompiledHeaderIncludeFilename = FirstInclude . IncludeResolvedName ;
return FileItem . GetItemByFullPath ( CPPFile . PrecompiledHeaderIncludeFilename ) ;
}
// search the include paths to resolve the file.
2014-07-31 09:34:11 -04:00
FileItem PrecompiledHeaderIncludeFile = CPPEnvironment . FindIncludedFile ( CPPFile . PCHHeaderNameInCode , ! BuildConfiguration . bCheckExternalHeadersForModification , IncludePathsToSearch , IncludeFileSearchDictionary ) ;
2014-04-23 20:18:55 -04:00
if ( PrecompiledHeaderIncludeFile = = null )
2014-07-18 16:34:12 -04:00
{
2014-07-31 09:34:11 -04:00
throw new BuildException ( "The first include statement in source file '{0}' is trying to include the file '{1}' as the precompiled header, but that file could not be located in any of the module's include search paths." , CPPFile . AbsolutePath , CPPFile . PCHHeaderNameInCode ) ;
2014-07-18 16:34:12 -04:00
}
2014-04-23 20:18:55 -04:00
2014-07-31 09:34:11 -04:00
CPPEnvironment . IncludeDependencyCache [ Target ] . CacheResolvedIncludeFullPath ( CPPFile , 0 , PrecompiledHeaderIncludeFile . AbsolutePath ) ;
2014-04-23 20:18:55 -04:00
CPPFile . PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFile . AbsolutePath ;
return PrecompiledHeaderIncludeFile ;
}
/// <summary>
/// Creates a compile environment from a base environment based on the module settings.
/// </summary>
/// <param name="BaseCompileEnvironment">An existing environment to base the module compile environment on.</param>
/// <returns>The new module compile environment.</returns>
public CPPEnvironment CreateModuleCompileEnvironment ( CPPEnvironment BaseCompileEnvironment )
{
2014-05-22 04:16:41 -04:00
var Result = BaseCompileEnvironment . DeepCopy ( ) ;
2014-04-23 20:18:55 -04:00
// Override compile environment
Result . Config . bFasterWithoutUnity = bFasterWithoutUnity ;
Result . Config . OptimizeCode = OptimizeCode ;
Result . Config . bUseRTTI = bUseRTTI ;
Result . Config . bEnableBufferSecurityChecks = bEnableBufferSecurityChecks ;
Result . Config . bFasterWithoutUnity = bFasterWithoutUnity ;
Result . Config . MinFilesUsingPrecompiledHeaderOverride = MinFilesUsingPrecompiledHeaderOverride ;
Result . Config . bEnableExceptions = bEnableExceptions ;
2014-09-23 13:55:06 -04:00
Result . Config . bUseStaticCRT = ( Target . Rules ! = null & & Target . Rules . bUseStaticCRT ) ;
2014-04-23 20:18:55 -04:00
Result . Config . OutputDirectory = Path . Combine ( Binary . Config . IntermediateDirectory , Name ) ;
2014-07-08 13:49:35 -04:00
// Switch the optimization flag if we're building a game module. Also pass the definition for building in DebugGame along (see ModuleManager.h for notes).
2014-08-26 11:26:50 -04:00
if ( Target . Configuration = = UnrealTargetConfiguration . DebugGame )
2014-04-23 20:18:55 -04:00
{
2015-04-21 11:27:37 -04:00
if ( ! Utils . IsFileUnderDirectory ( ModuleDirectory , BuildConfiguration . RelativeEnginePath ) )
2014-08-26 11:26:50 -04:00
{
Result . Config . Target . Configuration = CPPTargetConfiguration . Debug ;
Result . Config . Definitions . Add ( "UE_BUILD_DEVELOPMENT_WITH_DEBUGGAME=1" ) ;
}
2014-04-23 20:18:55 -04:00
}
// Add the module's private definitions.
Result . Config . Definitions . AddRange ( Definitions ) ;
// Setup the compile environment for the module.
2015-03-21 11:34:08 -04:00
SetupPrivateCompileEnvironment ( Result . Config . CPPIncludeInfo . IncludePaths , Result . Config . CPPIncludeInfo . SystemIncludePaths , Result . Config . Definitions , Result . Config . AdditionalFrameworks ) ;
2014-04-23 20:18:55 -04:00
2014-12-17 12:37:39 -05:00
// @hack to skip adding definitions to compile environment, they will be baked into source code files
if ( bSkipDefinitionsForCompileEnvironment )
{
Result . Config . Definitions . Clear ( ) ;
2014-12-18 16:32:27 -05:00
Result . Config . CPPIncludeInfo . IncludePaths = new HashSet < string > ( BaseCompileEnvironment . Config . CPPIncludeInfo . IncludePaths ) ;
2014-12-17 12:37:39 -05:00
}
2014-04-23 20:18:55 -04:00
return Result ;
2014-03-14 14:13:41 -04:00
}
2014-04-23 20:18:55 -04:00
public HashSet < FileItem > _AllClassesHeaders = new HashSet < FileItem > ( ) ;
public HashSet < FileItem > _PublicUObjectHeaders = new HashSet < FileItem > ( ) ;
public HashSet < FileItem > _PrivateUObjectHeaders = new HashSet < FileItem > ( ) ;
2014-07-18 14:20:08 -04:00
private UHTModuleInfo CachedModuleUHTInfo = null ;
2014-04-23 20:18:55 -04:00
2014-07-31 09:34:11 -04:00
/// Total time spent generating PCHs for modules (not actually compiling, but generating the PCH's input data)
public static double TotalPCHGenTime = 0.0 ;
/// Time spent caching which PCH header is included by each module and source file
public static double TotalPCHCacheTime = 0.0 ;
2014-07-16 12:14:22 -04:00
2014-03-14 14:13:41 -04:00
/// <summary>
/// If any of this module's source files contain UObject definitions, this will return those header files back to the caller
/// </summary>
/// <param name="PublicUObjectClassesHeaders">All UObjects headers in the module's Classes folder (legacy)</param>
/// <param name="PublicUObjectHeaders">Dependent UObject headers in Public source folders</param>
/// <param name="PrivateUObjectHeaders">Dependent UObject headers not in Public source folders</param>
/// <returns>
2014-07-18 14:20:08 -04:00
public UHTModuleInfo GetUHTModuleInfo ( )
2014-03-14 14:13:41 -04:00
{
2014-07-18 14:20:08 -04:00
if ( CachedModuleUHTInfo ! = null )
{
return CachedModuleUHTInfo ;
}
2014-04-23 20:18:55 -04:00
2014-04-29 21:53:54 -04:00
var ClassesFolder = Path . Combine ( this . ModuleDirectory , "Classes" ) ;
var PublicFolder = Path . Combine ( this . ModuleDirectory , "Public" ) ;
2014-04-29 11:21:18 -04:00
2014-07-31 09:34:11 -04:00
var BuildPlatform = UEBuildPlatform . GetBuildPlatform ( Target . Platform ) ;
2014-04-29 21:53:54 -04:00
var ClassesFiles = Directory . GetFiles ( this . ModuleDirectory , "*.h" , SearchOption . AllDirectories ) ;
foreach ( var ClassHeader in ClassesFiles )
2014-03-14 14:13:41 -04:00
{
2014-07-31 09:34:11 -04:00
// Check to see if we know anything about this file. If we have up-to-date cached information about whether it has
// UObjects or not, we can skip doing a test here.
2014-04-29 21:53:54 -04:00
var UObjectHeaderFileItem = FileItem . GetExistingItemByPath ( ClassHeader ) ;
2014-07-31 09:34:11 -04:00
bool HasUObjects ;
var DirectIncludes = CPPEnvironment . GetDirectIncludeDependencies ( Target , UObjectHeaderFileItem , BuildPlatform , bOnlyCachedDependencies : false , HasUObjects : out HasUObjects ) ;
Debug . Assert ( DirectIncludes ! = null ) ;
2015-04-10 06:02:22 -04:00
2014-07-31 09:34:11 -04:00
if ( HasUObjects )
{
if ( UObjectHeaderFileItem . AbsolutePath . StartsWith ( ClassesFolder ) )
{
_AllClassesHeaders . Add ( UObjectHeaderFileItem ) ;
}
else if ( UObjectHeaderFileItem . AbsolutePath . StartsWith ( PublicFolder ) )
{
_PublicUObjectHeaders . Add ( UObjectHeaderFileItem ) ;
}
else
{
_PrivateUObjectHeaders . Add ( UObjectHeaderFileItem ) ;
}
2014-04-23 20:18:55 -04:00
}
}
2014-07-31 09:34:11 -04:00
CachedModuleUHTInfo = new UHTModuleInfo
{
2014-03-14 14:13:41 -04:00
ModuleName = this . Name ,
ModuleDirectory = this . ModuleDirectory ,
2014-05-22 01:20:24 -04:00
ModuleType = this . Type . ToString ( ) ,
2014-04-29 21:53:54 -04:00
PublicUObjectClassesHeaders = _AllClassesHeaders . ToList ( ) ,
PublicUObjectHeaders = _PublicUObjectHeaders . ToList ( ) ,
2015-04-10 06:02:22 -04:00
PrivateUObjectHeaders = _PrivateUObjectHeaders . ToList ( ) ,
GeneratedCodeVersion = this . Target . Rules . GetGeneratedCodeVersion ( )
2014-03-14 14:13:41 -04:00
} ;
2014-04-23 20:18:55 -04:00
2014-07-18 14:20:08 -04:00
return CachedModuleUHTInfo ;
2014-03-14 14:13:41 -04:00
}
2014-07-31 09:34:11 -04:00
2015-03-21 11:34:08 -04:00
public override void GetAllDependencyModules ( Dictionary < string , UEBuildModule > ReferencedModules , List < UEBuildModule > OrderedModules , bool bIncludeDynamicallyLoaded , bool bForceCircular , bool bOnlyDirectDependencies )
2014-03-14 14:13:41 -04:00
{
var AllModuleNames = new List < string > ( ) ;
AllModuleNames . AddRange ( PrivateDependencyModuleNames ) ;
AllModuleNames . AddRange ( PublicDependencyModuleNames ) ;
if ( bIncludeDynamicallyLoaded )
{
AllModuleNames . AddRange ( DynamicallyLoadedModuleNames ) ;
AllModuleNames . AddRange ( PlatformSpecificDynamicallyLoadedModuleNames ) ;
}
foreach ( var DependencyName in AllModuleNames )
{
if ( ! ReferencedModules . ContainsKey ( DependencyName ) )
{
// Don't follow circular back-references!
bool bIsCircular = CircularlyReferencedDependentModules . Contains ( DependencyName ) ;
if ( bForceCircular | | ! bIsCircular )
{
var Module = Target . GetModuleByName ( DependencyName ) ;
ReferencedModules [ DependencyName ] = Module ;
2014-07-31 09:34:11 -04:00
if ( ! bOnlyDirectDependencies )
{
// Recurse into dependent modules first
2015-03-21 11:34:08 -04:00
Module . GetAllDependencyModules ( ReferencedModules , OrderedModules , bIncludeDynamicallyLoaded , bForceCircular , bOnlyDirectDependencies ) ;
2014-07-31 09:34:11 -04:00
}
2014-03-14 14:13:41 -04:00
OrderedModules . Add ( Module ) ;
}
}
}
}
2015-03-20 08:25:23 -04:00
public override void RecursivelyAddPrecompiledModules ( List < UEBuildModule > Modules )
{
if ( ! Modules . Contains ( this ) )
{
Modules . Add ( this ) ;
// Get the dependent modules
List < string > DependentModuleNames = new List < string > ( ) ;
DependentModuleNames . AddRange ( PrivateDependencyModuleNames ) ;
DependentModuleNames . AddRange ( PublicDependencyModuleNames ) ;
DependentModuleNames . AddRange ( DynamicallyLoadedModuleNames ) ;
DependentModuleNames . AddRange ( PlatformSpecificDynamicallyLoadedModuleNames ) ;
// Find modules for each of them, and add their dependencies too
foreach ( string DependentModuleName in DependentModuleNames )
{
UEBuildModule DependentModule = Target . FindOrCreateModuleByName ( DependentModuleName ) ;
DependentModule . RecursivelyAddPrecompiledModules ( Modules ) ;
}
}
}
2014-03-14 14:13:41 -04:00
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 ) ;
}
}
2015-04-11 13:09:16 -04:00
public override void RecursivelyProcessUnboundModules ( )
2014-03-14 14:13:41 -04:00
{
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 )
{
2015-04-11 13:09:16 -04:00
bool bIsCrossTarget = PlatformSpecificDynamicallyLoadedModuleNames . Contains ( DependencyName ) & & ! DynamicallyLoadedModuleNames . Contains ( DependencyName ) ;
2014-03-14 14:13:41 -04:00
2015-04-11 13:09:16 -04:00
// Get the binary that this module should be bound to
UEBuildBinary BinaryToBindTo = Target . FindOrAddBinaryForModule ( DependencyName , bIsCrossTarget ) ;
2014-03-14 14:13:41 -04:00
2015-04-11 13:09:16 -04:00
// Bind this module
DependencyModule . Binary = BinaryToBindTo ;
DependencyModule . bIncludedInTarget = true ;
2014-03-14 14:13:41 -04:00
2015-04-11 13:09:16 -04:00
// Also add binaries for this module's dependencies
DependencyModule . RecursivelyProcessUnboundModules ( ) ;
2014-03-14 14:13:41 -04:00
}
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 ) ;
}
}
2015-04-17 15:21:14 -04:00
}
2014-03-14 14:13:41 -04:00
/** A module that is compiled from C++ CLR code. */
class UEBuildModuleCPPCLR : UEBuildModuleCPP
{
/** The assemblies referenced by the module's private implementation. */
2014-09-11 03:21:51 -04:00
HashSet < string > PrivateAssemblyReferences ;
2014-03-14 14:13:41 -04:00
public UEBuildModuleCPPCLR (
UEBuildTarget InTarget ,
string InName ,
UEBuildModuleType InType ,
string InModuleDirectory ,
2015-04-20 18:05:25 -04:00
string InGeneratedCodeDirectory ,
2014-07-21 04:28:22 -04:00
bool? InIsRedistributableOverride ,
2014-03-14 14:13:41 -04:00
IntelliSenseGatherer InIntelliSenseGatherer ,
IEnumerable < FileItem > InSourceFiles ,
IEnumerable < string > InPublicIncludePaths ,
IEnumerable < string > InPublicSystemIncludePaths ,
IEnumerable < string > InDefinitions ,
IEnumerable < string > InPrivateAssemblyReferences ,
IEnumerable < string > InPublicIncludePathModuleNames ,
IEnumerable < string > InPublicDependencyModuleNames ,
IEnumerable < string > InPublicDelayLoadDLLs ,
IEnumerable < string > InPublicAdditionalLibraries ,
IEnumerable < string > InPublicFrameworks ,
2014-06-18 15:57:40 -04:00
IEnumerable < string > InPublicWeakFrameworks ,
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
IEnumerable < UEBuildFramework > InPublicAdditionalFrameworks ,
2014-04-30 14:09:06 -04:00
IEnumerable < string > InPublicAdditionalShadowFiles ,
2014-07-28 14:55:48 -04:00
IEnumerable < UEBuildBundleResource > InPublicAdditionalBundleResources ,
2014-03-14 14:13:41 -04:00
IEnumerable < string > InPrivateIncludePaths ,
IEnumerable < string > InPrivateIncludePathModuleNames ,
IEnumerable < string > InPrivateDependencyModuleNames ,
IEnumerable < string > InCircularlyReferencedDependentModules ,
IEnumerable < string > InDynamicallyLoadedModuleNames ,
IEnumerable < string > InPlatformSpecificDynamicallyLoadedModuleNames ,
2015-04-03 10:25:57 -04:00
IEnumerable < RuntimeDependency > InRuntimeDependencies ,
2014-03-14 14:13:41 -04:00
ModuleRules . CodeOptimization InOptimizeCode ,
bool InAllowSharedPCH ,
string InSharedPCHHeaderFile ,
bool InUseRTTI ,
bool InEnableBufferSecurityChecks ,
bool InFasterWithoutUnity ,
int InMinFilesUsingPrecompiledHeaderOverride ,
bool InEnableExceptions ,
2014-05-29 16:51:44 -04:00
bool bInBuildSourceFiles
2014-03-14 14:13:41 -04:00
)
2015-04-20 18:05:25 -04:00
: base ( InTarget , InName , InType , InModuleDirectory , InGeneratedCodeDirectory , InIsRedistributableOverride , InIntelliSenseGatherer ,
2015-01-09 14:43:46 -05:00
InSourceFiles , InPublicIncludePaths , InPublicSystemIncludePaths , null , InDefinitions ,
2014-07-28 14:55:48 -04:00
InPublicIncludePathModuleNames , InPublicDependencyModuleNames , InPublicDelayLoadDLLs , InPublicAdditionalLibraries , InPublicFrameworks , InPublicWeakFrameworks , InPublicAdditionalFrameworks , InPublicAdditionalShadowFiles , InPublicAdditionalBundleResources ,
2014-03-14 14:13:41 -04:00
InPrivateIncludePaths , InPrivateIncludePathModuleNames , InPrivateDependencyModuleNames ,
2015-04-03 10:25:57 -04:00
InCircularlyReferencedDependentModules , InDynamicallyLoadedModuleNames , InPlatformSpecificDynamicallyLoadedModuleNames , InRuntimeDependencies , InOptimizeCode ,
2014-12-02 04:37:53 -05:00
InAllowSharedPCH , InSharedPCHHeaderFile , InUseRTTI , InEnableBufferSecurityChecks , InFasterWithoutUnity , InMinFilesUsingPrecompiledHeaderOverride ,
2014-06-09 11:51:22 -04:00
InEnableExceptions , bInBuildSourceFiles )
2014-03-14 14:13:41 -04:00
{
2014-09-11 03:21:51 -04:00
PrivateAssemblyReferences = HashSetFromOptionalEnumerableStringParameter ( InPrivateAssemblyReferences ) ;
2014-03-14 14:13:41 -04:00
}
// UEBuildModule interface.
2015-04-10 11:19:40 -04:00
public override List < FileItem > Compile ( CPPEnvironment GlobalCompileEnvironment , CPPEnvironment CompileEnvironment )
2014-03-14 14:13:41 -04:00
{
2014-05-22 04:16:41 -04:00
var ModuleCLREnvironment = CompileEnvironment . DeepCopy ( ) ;
2014-03-14 14:13:41 -04:00
// Setup the module environment for the project CLR mode
ModuleCLREnvironment . Config . CLRMode = CPPCLRMode . CLREnabled ;
// Add the private assembly references to the compile environment.
foreach ( var PrivateAssemblyReference in PrivateAssemblyReferences )
{
ModuleCLREnvironment . AddPrivateAssembly ( PrivateAssemblyReference ) ;
}
// Pass the CLR compilation environment to the standard C++ module compilation code.
2015-04-10 11:19:40 -04:00
return base . Compile ( GlobalCompileEnvironment , ModuleCLREnvironment ) ;
2014-03-14 14:13:41 -04:00
}
public override void SetupPrivateLinkEnvironment (
2015-03-21 11:34:08 -04:00
LinkEnvironment LinkEnvironment ,
List < UEBuildBinary > BinaryDependencies ,
Dictionary < UEBuildModule , bool > VisitedModules
2014-03-14 14:13:41 -04:00
)
{
2015-03-21 11:34:08 -04:00
base . SetupPrivateLinkEnvironment ( LinkEnvironment , BinaryDependencies , VisitedModules ) ;
2014-03-14 14:13:41 -04:00
// Setup the link environment for linking a CLR binary.
LinkEnvironment . Config . CLRMode = CPPCLRMode . CLREnabled ;
}
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
public class UEBuildFramework
{
public UEBuildFramework ( string InFrameworkName )
{
FrameworkName = InFrameworkName ;
}
2014-07-01 11:28:39 -04:00
public UEBuildFramework ( string InFrameworkName , string InFrameworkZipPath )
{
FrameworkName = InFrameworkName ;
FrameworkZipPath = InFrameworkZipPath ;
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
public UEBuildFramework ( string InFrameworkName , string InFrameworkZipPath , string InCopyBundledAssets )
{
FrameworkName = InFrameworkName ;
FrameworkZipPath = InFrameworkZipPath ;
CopyBundledAssets = InCopyBundledAssets ;
}
public UEBuildModule OwningModule = null ;
public string FrameworkName = null ;
public string FrameworkZipPath = null ;
public string CopyBundledAssets = null ;
}
2014-07-28 14:55:48 -04:00
public class UEBuildBundleResource
{
2014-11-21 13:41:17 -05:00
public UEBuildBundleResource ( string InResourcePath , string InBundleContentsSubdir = "Resources" , bool bInShouldLog = true )
2014-07-28 14:55:48 -04:00
{
ResourcePath = InResourcePath ;
BundleContentsSubdir = InBundleContentsSubdir ;
2014-11-21 13:41:17 -05:00
bShouldLog = bInShouldLog ;
2014-07-28 14:55:48 -04:00
}
public string ResourcePath = null ;
public string BundleContentsSubdir = null ;
2014-11-21 13:41:17 -05:00
public bool bShouldLog = true ;
2014-07-28 14:55:48 -04:00
}
Experimental UnrealBuildTool makefile support
UnrealBuildTool 'Makefiles' allow for very fast iterative builds.
- New BuildConfiguration.xml setting added: "bUseExperimentalFastBuildIteration" (disabled by default)
- Turning this on causes Unreal Build Tool to emit 'UBT Makefiles' for targets when they're built the first time.
- Subsequent builds will load these Makefiles and begin outdatedness checking and build invocation very quickly.
- The caveat is that if source files are added or removed to the project, UBT will need to gather information about those in order for your build to complete successfully.
- Currently, you must run the project file generator after adding/removing source files to tell UBT to re-gather this information.
- Events that can invalidate the 'UBT Makefile':
- Adding/removing .cpp files
- Adding/removing .h files with UObjects
- Adding new UObject types to a file that didn't previously have any
- Changing global build settings (most settings in this file qualify.)
- Changed code that affects how Unreal Header Tool works
- You can force regeneration of the 'UBT Makefile' by passing the '-Gather' argument, or simply regenerating project files
- New command-line parameters added:
- "-Gather": Tells UBT to always perform the gather step (slower but will catch project structural changes)
- "-NoGather": Disables the gather step, unless UBT detects that it must be done. This is the default when bUseExperimentalFastBuildIteration is enabled
- "-GatherOnly": Runs the gather step and saves a UBTMakefile, but doesn't build anything
- "-Assemble": Tells UBT to also assemble build products. This always defaults to enabled
- "-NoAssemble": Tells UBT to skip the assemble step, whether we gathered build products or not
- "-AssembleOnly": Tells UBT to only assemble build products and not to gather, unless UBT determines it must
Other changes:
- UBT now keeps track of which targets it was building in an intermediate file, to help it invalidate cached includes in subsequent runs when the targets are different
- C++ includes are now stored in a class separate from the C++ compile enviroment (for easier serialization)
- The method that UBT uses to find the CoreUObject module timestamp was rewritten
- Various '@todo ubtmake' comments added to tag possible remaining Makefile tasks
- The 'FileItem' class had some member variable comments and code cleaned up, while making it serializable
- Cleaned up the comments and member variables in the "Action" class, while making it serializable
- Some UBT classes are now "serializable". This is because we need to store the data in UBTMakefiles.
- Removed support for Actions to tinker with Stdout and Stderror (was not used for anything)
- Moved PrecompileHeaderEnvironment class to the UEBuildModule.cs source file
- Plugin intermediate include directories are now selected on demand rather than cached early
- Toolchain code for gathering prerequisite headers is now shared in a single function (AddPrerequisiteSourceFile)
- Removed Action.StatusDetailedDescription, was not used for anything
- Removed UEBuildConfiguration.bExcludePlugins, was not used for anything
- Removed ECompilationResult.FailedDueToHeaderChange, was not used for anything
[CL 2254472 by Mike Fricker in Main branch]
2014-08-13 08:17:43 -04:00
public class PrecompileHeaderEnvironment
{
/** The name of the module this PCH header is a member of */
public readonly string ModuleName ;
/ * * PCH header file name as it appears in an # include statement in source code ( might include partial , or no relative path . )
This is needed by some compilers to use PCH features . * /
public string PCHHeaderNameInCode ;
/** The source header file that this precompiled header will be generated for */
public readonly FileItem PrecompiledHeaderIncludeFilename ;
/** Whether this precompiled header will be built with CLR features enabled. We won't mix and match CLR PCHs with non-CLR PCHs */
public readonly CPPCLRMode CLRMode ;
/** Whether this precompiled header will be built with code optimization enabled. */
public readonly ModuleRules . CodeOptimization OptimizeCode ;
/** The PCH file we're generating */
public FileItem PrecompiledHeaderFile = null ;
/ * * Object files emitted from the compiler when generating this precompiled header . These will be linked into modules that
include this PCH * /
public readonly List < FileItem > OutputObjectFiles = new List < FileItem > ( ) ;
public PrecompileHeaderEnvironment ( string InitModuleName , string InitPCHHeaderNameInCode , FileItem InitPrecompiledHeaderIncludeFilename , CPPCLRMode InitCLRMode , ModuleRules . CodeOptimization InitOptimizeCode )
{
ModuleName = InitModuleName ;
PCHHeaderNameInCode = InitPCHHeaderNameInCode ;
PrecompiledHeaderIncludeFilename = InitPrecompiledHeaderIncludeFilename ;
CLRMode = InitCLRMode ;
OptimizeCode = InitOptimizeCode ;
}
/// <summary>
/// Creates a precompiled header action to generate a new pch file
/// </summary>
/// <param name="PCHHeaderNameInCode">The precompiled header name as it appeared in an #include statement</param>
/// <param name="PrecompiledHeaderIncludeFilename">Name of the header used for pch.</param>
/// <param name="ProjectCPPEnvironment">The environment the C/C++ files in the project are compiled with.</param>
/// <param name="OutputDirectory">The folder to save the generated PCH file to</param>
/// <param name="ModuleName">Name of the module this PCH is being generated for</param>
/// <param name="bAllowDLLExports">True if we should allow DLLEXPORT definitions for this PCH</param>
/// <returns>the compilation output result of the created pch.</returns>
public static CPPOutput GeneratePCHCreationAction ( UEBuildTarget Target , string PCHHeaderNameInCode , FileItem PrecompiledHeaderIncludeFilename , CPPEnvironment ProjectCPPEnvironment , string OutputDirectory , string ModuleName , bool bAllowDLLExports )
{
// Find the header file to be precompiled. Don't skip external headers
if ( PrecompiledHeaderIncludeFilename . bExists )
{
// Create a Dummy wrapper around the PCH to avoid problems with #pragma once on clang
var ToolChain = UEToolChain . GetPlatformToolChain ( ProjectCPPEnvironment . Config . Target . Platform ) ;
string PCHGuardDefine = Path . GetFileNameWithoutExtension ( PrecompiledHeaderIncludeFilename . AbsolutePath ) . ToUpper ( ) ;
string LocalPCHHeaderNameInCode = ToolChain . ConvertPath ( PrecompiledHeaderIncludeFilename . AbsolutePath ) ;
string TmpPCHHeaderContents = String . Format ( "#ifndef __AUTO_{0}_H__\n#define __AUTO_{0}_H__\n//Last Write: {2}\n#include \"{1}\"\n#endif//__AUTO_{0}_H__" , PCHGuardDefine , LocalPCHHeaderNameInCode , PrecompiledHeaderIncludeFilename . LastWriteTime ) ;
string DummyPath = Path . Combine (
ProjectCPPEnvironment . Config . OutputDirectory ,
Path . GetFileName ( PrecompiledHeaderIncludeFilename . AbsolutePath ) ) ;
FileItem DummyPCH = FileItem . CreateIntermediateTextFile ( DummyPath , TmpPCHHeaderContents ) ;
// Create a new C++ environment that is used to create the PCH.
var ProjectPCHEnvironment = ProjectCPPEnvironment . DeepCopy ( ) ;
ProjectPCHEnvironment . Config . PrecompiledHeaderAction = PrecompiledHeaderAction . Create ;
ProjectPCHEnvironment . Config . PrecompiledHeaderIncludeFilename = PrecompiledHeaderIncludeFilename . AbsolutePath ;
ProjectPCHEnvironment . Config . PCHHeaderNameInCode = PCHHeaderNameInCode ;
ProjectPCHEnvironment . Config . OutputDirectory = OutputDirectory ;
if ( ! bAllowDLLExports )
{
for ( var CurDefinitionIndex = 0 ; CurDefinitionIndex < ProjectPCHEnvironment . Config . Definitions . Count ; + + CurDefinitionIndex )
{
// We change DLLEXPORT to DLLIMPORT for "shared" PCH headers
var OldDefinition = ProjectPCHEnvironment . Config . Definitions [ CurDefinitionIndex ] ;
if ( OldDefinition . EndsWith ( "=DLLEXPORT" ) )
{
ProjectPCHEnvironment . Config . Definitions [ CurDefinitionIndex ] = OldDefinition . Replace ( "DLLEXPORT" , "DLLIMPORT" ) ;
}
}
}
// Cache our CPP environment so that we can check for outdatedness quickly. Only files that have includes need this.
DummyPCH . CachedCPPIncludeInfo = ProjectPCHEnvironment . Config . CPPIncludeInfo ;
Log . TraceVerbose ( "Found PCH file \"{0}\"." , PrecompiledHeaderIncludeFilename ) ;
// Create the action to compile the PCH file.
return ProjectPCHEnvironment . CompileFiles ( Target , new List < FileItem > ( ) { DummyPCH } , ModuleName ) ;
}
throw new BuildException ( "Couldn't find PCH file \"{0}\"." , PrecompiledHeaderIncludeFilename ) ;
}
}
2014-03-14 14:13:41 -04:00
}