2015-04-26 07:33:29 -04: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.IO ;
using AutomationTool ;
using UnrealBuildTool ;
using System.Reflection ;
2014-06-16 12:05:56 -04:00
using System.Xml ;
2014-08-18 13:29:39 -04:00
using System.Linq ;
2014-06-16 12:05:56 -04:00
public class ECJobPropsUtils
{
2014-08-22 13:39:55 -04:00
public static HashSet < string > ErrorsFromProps ( string Filename )
{
var Result = new HashSet < string > ( ) ;
XmlDocument Doc = new XmlDocument ( ) ;
Doc . Load ( Filename ) ;
foreach ( XmlElement ChildNode in Doc . FirstChild . ChildNodes )
{
if ( ChildNode . Name = = "propertySheet" )
{
foreach ( XmlElement PropertySheetChild in ChildNode . ChildNodes )
{
if ( PropertySheetChild . Name = = "property" )
{
bool IsDiag = false ;
foreach ( XmlElement PropertySheetChildDiag in PropertySheetChild . ChildNodes )
{
if ( PropertySheetChildDiag . Name = = "propertyName" & & PropertySheetChildDiag . InnerText = = "ec_diagnostics" )
{
IsDiag = true ;
}
if ( IsDiag & & PropertySheetChildDiag . Name = = "propertySheet" )
{
foreach ( XmlElement PropertySheetChildDiagSheet in PropertySheetChildDiag . ChildNodes )
{
if ( PropertySheetChildDiagSheet . Name = = "property" )
{
bool IsError = false ;
foreach ( XmlElement PropertySheetChildDiagSheetElem in PropertySheetChildDiagSheet . ChildNodes )
{
if ( PropertySheetChildDiagSheetElem . Name = = "propertyName" & & PropertySheetChildDiagSheetElem . InnerText . StartsWith ( "error-" ) )
{
IsError = true ;
}
if ( IsError & & PropertySheetChildDiagSheetElem . Name = = "propertySheet" )
{
foreach ( XmlElement PropertySheetChildDiagSheetElemInner in PropertySheetChildDiagSheetElem . ChildNodes )
{
if ( PropertySheetChildDiagSheetElemInner . Name = = "property" )
{
bool IsMessage = false ;
foreach ( XmlElement PropertySheetChildDiagSheetElemInner2 in PropertySheetChildDiagSheetElemInner . ChildNodes )
{
if ( PropertySheetChildDiagSheetElemInner2 . Name = = "propertyName" & & PropertySheetChildDiagSheetElemInner2 . InnerText = = "message" )
{
IsMessage = true ;
}
if ( IsMessage & & PropertySheetChildDiagSheetElemInner2 . Name = = "value" )
{
if ( ! PropertySheetChildDiagSheetElemInner2 . InnerText . Contains ( "LogTailsAndChanges" )
& & ! PropertySheetChildDiagSheetElemInner2 . InnerText . Contains ( "-MyJobStepId=" )
& & ! PropertySheetChildDiagSheetElemInner2 . InnerText . Contains ( "CommandUtils.Run: Run: Took " )
)
{
Result . Add ( PropertySheetChildDiagSheetElemInner2 . InnerText ) ;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
return Result ;
}
2014-06-16 12:05:56 -04:00
}
public class TestECJobErrorParse : BuildCommand
{
2014-08-22 13:39:55 -04:00
public override void ExecuteBuild ( )
{
Log ( "*********************** TestECJobErrorParse" ) ;
2014-06-16 12:05:56 -04:00
2014-08-22 13:39:55 -04:00
string Filename = CombinePaths ( @"P:\Builds\UE4\GUBP\++depot+UE4-2104401-RootEditor_Failed\Engine\Saved\Logs" , "RootEditor_Failed.log" ) ;
var Errors = ECJobPropsUtils . ErrorsFromProps ( Filename ) ;
foreach ( var ThisError in Errors )
{
Log ( "Error: {0}" , ThisError ) ;
}
}
2014-06-16 12:05:56 -04:00
}
2014-03-14 14:13:41 -04:00
public class GUBP : BuildCommand
{
2014-08-22 13:39:55 -04:00
public string StoreName = null ;
2015-04-17 13:21:04 -04:00
public string BranchName ;
2014-08-22 13:39:55 -04:00
public int CL = 0 ;
public int TimeIndex = 0 ;
public bool bSignBuildProducts = false ;
public bool bHasTests = false ;
public List < UnrealTargetPlatform > ActivePlatforms = null ;
public BranchInfo Branch = null ;
public bool bOrthogonalizeEditorPlatforms = false ;
public List < UnrealTargetPlatform > HostPlatforms ;
public bool bFake = false ;
public static bool bNoIOSOnPC = false ;
public static bool bForceIncrementalCompile = false ;
public static string ECProject = null ;
public string EmailHint ;
static public bool bPreflightBuild = false ;
public int PreflightShelveCL = 0 ;
static public string PreflightMangleSuffix = "" ;
2014-12-17 11:37:40 -05:00
public GUBPBranchHacker . BranchOptions BranchOptions = null ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Dictionary < string , GUBPNode > GUBPNodes ;
Dictionary < string , bool > GUBPNodesCompleted ;
Dictionary < string , string > GUBPNodesControllingTrigger ;
Dictionary < string , string > GUBPNodesControllingTriggerDotName ;
2014-04-23 17:37:20 -04:00
2014-08-22 13:39:55 -04:00
class NodeHistory
{
public int LastSucceeded = 0 ;
public int LastFailed = 0 ;
public List < int > InProgress = new List < int > ( ) ;
public string InProgressString = "" ;
public List < int > Failed = new List < int > ( ) ;
public string FailedString = "" ;
public List < int > AllStarted = new List < int > ( ) ;
public List < int > AllSucceeded = new List < int > ( ) ;
public List < int > AllFailed = new List < int > ( ) ;
} ;
2014-04-23 17:37:20 -04:00
2014-08-22 13:39:55 -04:00
Dictionary < string , NodeHistory > GUBPNodesHistory ;
2014-04-23 17:37:20 -04:00
2014-08-22 13:39:55 -04:00
public abstract class GUBPNodeAdder
{
public virtual void AddNodes ( GUBP bp , UnrealTargetPlatform InHostPlatform )
{
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
private static List < GUBPNodeAdder > Adders ;
2015-04-28 18:30:10 -04:00
Type [ ] GetTypesFromAssembly ( Assembly Asm )
{
Type [ ] AllTypesWeCanGet ;
try
{
AllTypesWeCanGet = Asm . GetTypes ( ) ;
}
catch ( ReflectionTypeLoadException Exc )
{
AllTypesWeCanGet = Exc . Types ;
}
return AllTypesWeCanGet ;
}
2014-08-22 13:39:55 -04:00
private void AddCustomNodes ( UnrealTargetPlatform InHostPlatform )
{
if ( Adders = = null )
{
Adders = new List < GUBPNodeAdder > ( ) ;
Assembly [ ] LoadedAssemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( var Dll in LoadedAssemblies )
{
2015-04-28 18:30:10 -04:00
Type [ ] AllTypes = GetTypesFromAssembly ( Dll ) ;
2014-08-22 13:39:55 -04:00
foreach ( var PotentialConfigType in AllTypes )
{
if ( PotentialConfigType ! = typeof ( GUBPNodeAdder ) & & typeof ( GUBPNodeAdder ) . IsAssignableFrom ( PotentialConfigType ) )
{
GUBPNodeAdder Config = Activator . CreateInstance ( PotentialConfigType ) as GUBPNodeAdder ;
if ( Config ! = null )
{
Adders . Add ( Config ) ;
}
}
}
}
}
foreach ( var Adder in Adders )
{
Adder . AddNodes ( this , InHostPlatform ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public abstract class GUBPBranchHacker
{
public class BranchOptions
{
public List < UnrealTargetPlatform > PlatformsToRemove = new List < UnrealTargetPlatform > ( ) ;
2015-02-24 18:49:02 -05:00
public List < string > ExcludeNodes = new List < string > ( ) ;
public List < UnrealTargetPlatform > ExcludePlatformsForEditor = new List < UnrealTargetPlatform > ( ) ;
2015-04-21 15:21:51 -04:00
public List < UnrealTargetPlatform > RemovePlatformFromPromotable = new List < UnrealTargetPlatform > ( ) ;
2015-05-05 11:24:13 -04:00
public List < string > PromotablesWithoutTools = new List < string > ( ) ;
2015-05-06 18:54:54 -04:00
public List < string > NodesToRemovePseudoDependencies = new List < string > ( ) ;
2015-05-12 18:36:53 -04:00
public List < string > EnhanceAgentRequirements = new List < string > ( ) ;
2014-09-10 12:30:17 -04:00
public bool bNoAutomatedTesting = false ;
2014-09-29 21:43:13 -04:00
public bool bNoDocumentation = false ;
2015-03-27 08:02:21 -04:00
public bool bNoInstalledEngine = false ;
2015-03-04 08:31:40 -05:00
public bool bMakeFormalBuildWithoutLabelPromotable = false ;
2015-05-16 18:58:05 -04:00
public bool bNoMonolithicDependenciesForCooks = false ;
2015-05-17 09:45:42 -04:00
public bool bNoEditorDependenciesForTools = false ;
2015-04-17 14:13:52 -04:00
public Dictionary < string , sbyte > FrequencyBarriers = new Dictionary < string , sbyte > ( ) ;
2015-01-27 14:24:55 -05:00
public int QuantumOverride = 0 ;
2014-08-22 13:39:55 -04:00
}
public virtual void ModifyOptions ( GUBP bp , ref BranchOptions Options , string Branch )
{
}
}
2014-05-13 11:30:38 -04:00
2014-08-22 13:39:55 -04:00
private static List < GUBPBranchHacker > BranchHackers ;
private GUBPBranchHacker . BranchOptions GetBranchOptions ( string Branch )
{
if ( BranchHackers = = null )
{
BranchHackers = new List < GUBPBranchHacker > ( ) ;
Assembly [ ] LoadedAssemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( var Dll in LoadedAssemblies )
{
2015-04-28 18:30:10 -04:00
Type [ ] AllTypes = GetTypesFromAssembly ( Dll ) ;
2014-08-22 13:39:55 -04:00
foreach ( var PotentialConfigType in AllTypes )
{
if ( PotentialConfigType ! = typeof ( GUBPBranchHacker ) & & typeof ( GUBPBranchHacker ) . IsAssignableFrom ( PotentialConfigType ) )
{
GUBPBranchHacker Config = Activator . CreateInstance ( PotentialConfigType ) as GUBPBranchHacker ;
if ( Config ! = null )
{
BranchHackers . Add ( Config ) ;
}
}
}
}
}
var Result = new GUBPBranchHacker . BranchOptions ( ) ;
foreach ( var Hacker in BranchHackers )
{
Hacker . ModifyOptions ( this , ref Result , Branch ) ;
}
return Result ;
}
2014-05-13 11:30:38 -04:00
2014-08-22 13:39:55 -04:00
public abstract class GUBPEmailHacker
2014-08-28 17:00:26 -04:00
{
2014-08-22 13:39:55 -04:00
public virtual List < string > AddEmails ( GUBP bp , string Branch , string NodeName )
{
return new List < string > ( ) ;
}
public virtual List < string > ModifyEmail ( string Email , GUBP bp , string Branch , string NodeName )
{
return new List < string > { Email } ;
}
public virtual List < string > FinalizeEmails ( List < string > Emails , GUBP bp , string Branch , string NodeName )
{
return Emails ;
}
2014-08-28 16:40:17 -04:00
public virtual bool VetoEmailingCausers ( GUBP bp , string Branch , string NodeName )
{
return false ; // People who have submitted since last-green will be included unless vetoed by overriding this method.
}
2014-08-28 17:00:26 -04:00
}
2014-04-23 18:27:56 -04:00
2014-08-22 13:39:55 -04:00
private static List < GUBPEmailHacker > EmailHackers ;
2014-08-28 16:40:17 -04:00
private string HackEmails ( string Emails , string Causers , string Branch , string NodeName )
2014-08-22 13:39:55 -04:00
{
string OnlyEmail = ParseParamValue ( "OnlyEmail" ) ;
if ( ! String . IsNullOrEmpty ( OnlyEmail ) )
{
return OnlyEmail ;
}
EmailHint = ParseParamValue ( "EmailHint" ) ;
if ( EmailHint = = null )
{
EmailHint = "" ;
2014-12-17 11:37:40 -05:00
}
2014-08-22 13:39:55 -04:00
if ( EmailHackers = = null )
{
EmailHackers = new List < GUBPEmailHacker > ( ) ;
Assembly [ ] LoadedAssemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( var Dll in LoadedAssemblies )
{
2015-04-28 18:30:10 -04:00
Type [ ] AllTypes = GetTypesFromAssembly ( Dll ) ;
2014-08-22 13:39:55 -04:00
foreach ( var PotentialConfigType in AllTypes )
{
if ( PotentialConfigType ! = typeof ( GUBPEmailHacker ) & & typeof ( GUBPEmailHacker ) . IsAssignableFrom ( PotentialConfigType ) )
{
GUBPEmailHacker Config = Activator . CreateInstance ( PotentialConfigType ) as GUBPEmailHacker ;
if ( Config ! = null )
{
EmailHackers . Add ( Config ) ;
}
}
}
}
}
List < string > Result = new List < string > ( Emails . Split ( ' ' ) ) ;
2014-08-28 16:40:17 -04:00
if ( ! EmailHackers . Any ( x = > x . VetoEmailingCausers ( this , Branch , NodeName ) ) )
{
Result . AddRange ( Causers . Split ( ' ' ) ) ;
}
2014-08-22 13:39:55 -04:00
foreach ( var EmailHacker in EmailHackers )
{
Result . AddRange ( EmailHacker . AddEmails ( this , Branch , NodeName ) ) ;
}
foreach ( var EmailHacker in EmailHackers )
{
var NewResult = new List < string > ( ) ;
foreach ( var Email in Result )
{
NewResult . AddRange ( EmailHacker . ModifyEmail ( Email , this , Branch , NodeName ) ) ;
}
Result = NewResult ;
}
foreach ( var EmailHacker in EmailHackers )
{
Result = EmailHacker . FinalizeEmails ( Result , this , Branch , NodeName ) ;
}
string FinalEmails = "" ;
int Count = 0 ;
foreach ( var Email in Result )
{
FinalEmails = GUBPNode . MergeSpaceStrings ( FinalEmails , Email ) ;
Count + + ;
}
return FinalEmails ;
}
public abstract class GUBPFrequencyHacker
{
public virtual int GetNodeFrequency ( GUBP bp , string Branch , string NodeName , int BaseFrequency )
{
return new int ( ) ;
}
}
private static List < GUBPFrequencyHacker > FrequencyHackers ;
private int HackFrequency ( GUBP bp , string Branch , string NodeName , int BaseFrequency )
{
int Frequency = BaseFrequency ;
if ( FrequencyHackers = = null )
{
FrequencyHackers = new List < GUBPFrequencyHacker > ( ) ;
Assembly [ ] LoadedAssemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( var Dll in LoadedAssemblies )
{
2015-04-28 18:30:10 -04:00
Type [ ] AllTypes = GetTypesFromAssembly ( Dll ) ;
2014-08-22 13:39:55 -04:00
foreach ( var PotentialConfigType in AllTypes )
{
if ( PotentialConfigType ! = typeof ( GUBPFrequencyHacker ) & & typeof ( GUBPFrequencyHacker ) . IsAssignableFrom ( PotentialConfigType ) )
{
GUBPFrequencyHacker Config = Activator . CreateInstance ( PotentialConfigType ) as GUBPFrequencyHacker ;
if ( Config ! = null )
{
FrequencyHackers . Add ( Config ) ;
}
}
}
}
}
foreach ( var FrequencyHacker in FrequencyHackers )
{
Frequency = FrequencyHacker . GetNodeFrequency ( bp , Branch , NodeName , BaseFrequency ) ;
}
return Frequency ;
}
public abstract class GUBPNode
{
public List < string > FullNamesOfDependencies = new List < string > ( ) ;
public List < string > FullNamesOfPseudosependencies = new List < string > ( ) ; //these are really only used for sorting. We want the editor to fail before the monolithics. Think of it as "can't possibly be useful without".
2014-10-27 07:59:33 -04:00
public List < string > FullNamesOfDependedOn = new List < string > ( ) ;
2014-08-22 13:39:55 -04:00
public List < string > BuildProducts = null ;
2014-11-03 11:46:48 -05:00
public List < string > DependentPromotions = new List < string > ( ) ;
2014-08-22 13:39:55 -04:00
public List < string > AllDependencyBuildProducts = null ;
2014-12-17 11:37:40 -05:00
public List < string > AllDependencies = null ;
2015-02-10 14:58:32 -05:00
public List < string > CompletedDependencies = new List < string > ( ) ;
2014-08-22 13:39:55 -04:00
public string AgentSharingGroup = "" ;
public int ComputedDependentCISFrequencyQuantumShift = - 1 ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public virtual string GetFullName ( )
{
throw new AutomationException ( "Unimplemented GetFullName." ) ;
}
2015-04-01 13:36:26 -04:00
public virtual string GetDisplayGroupName ( )
{
return GetFullName ( ) ;
}
2014-08-22 13:39:55 -04:00
public virtual string GameNameIfAnyForTempStorage ( )
{
return "" ;
}
public virtual string RootIfAnyForTempStorage ( )
{
return "" ;
}
public virtual void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
public virtual void PostLoadFromSharedTempStorage ( GUBP bp )
{
}
public virtual void DoFakeBuild ( GUBP bp ) // this is used to more rapidly test a build system, it does nothing but save a record of success as a build product
{
BuildProducts = new List < string > ( ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
public virtual bool IsSticky ( )
{
return false ;
}
public virtual bool SendSuccessEmail ( )
{
return false ;
}
public virtual bool RunInEC ( )
{
return true ;
}
2014-10-15 08:26:52 -04:00
public virtual bool IsTest ( )
{
return false ;
}
2014-08-22 13:39:55 -04:00
public virtual bool IsAggregate ( )
{
return false ;
}
2014-11-03 11:46:48 -05:00
public virtual bool IsPromotableAggregate ( )
{
return false ;
}
public virtual bool IsSeparatePromotable ( )
{
return false ;
}
2014-12-17 11:37:40 -05:00
public virtual string NodeHostPlatform ( )
{
return "" ;
}
2014-08-22 13:39:55 -04:00
public virtual int AgentMemoryRequirement ( GUBP bp )
{
return 0 ;
}
public virtual int TimeoutInMinutes ( )
{
return 90 ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
/// <summary>
/// When triggered by CIS (instead of a person) this dictates how often this node runs.
/// The builder has a increasing index, specified with -TimeIndex=N
/// If N mod (1 lshift CISFrequencyQuantumShift()) is not 0, the node is skipped
/// </summary>
public virtual int CISFrequencyQuantumShift ( GUBP bp )
{
return 0 ;
}
/// <summary>
/// As above the maximum of all ancestors and pseudoancestors
/// </summary>
public int DependentCISFrequencyQuantumShift ( )
{
if ( ComputedDependentCISFrequencyQuantumShift < 0 )
{
throw new AutomationException ( "Asked for frequency shift before it was computed." ) ;
}
return ComputedDependentCISFrequencyQuantumShift ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public virtual float Priority ( )
{
return 100.0f ;
}
public virtual bool TriggerNode ( )
{
return false ;
}
public virtual void SetAsExplicitTrigger ( )
{
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
public virtual string ECAgentString ( )
{
return "" ;
}
public virtual string ECProcedureInfix ( )
{
return "" ;
}
public virtual string ECProcedure ( )
{
if ( IsSticky ( ) & & AgentSharingGroup ! = "" )
{
throw new AutomationException ( "Node {0} is both agent sharing and sitcky." , GetFullName ( ) ) ;
}
return String . Format ( "GUBP{0}_UAT_Node{1}{2}" , ECProcedureInfix ( ) , IsSticky ( ) ? "" : "_Parallel" , AgentSharingGroup ! = "" ? "_AgentShare" : "" ) ;
}
public virtual string ECProcedureParams ( )
{
2014-09-03 10:12:50 -04:00
var Result = String . Format ( ", {{actualParameterName => 'Sticky', value => '{0}'}}" , IsSticky ( ) ? 1 : 0 ) ;
2014-08-22 13:39:55 -04:00
if ( AgentSharingGroup ! = "" )
{
2014-09-03 10:12:50 -04:00
Result + = String . Format ( ", {{actualParameterName => 'AgentSharingGroup', value => '{0}'}}" , AgentSharingGroup ) ;
2014-08-22 13:39:55 -04:00
}
return Result ;
}
public static string MergeSpaceStrings ( params string [ ] EmailLists )
{
var Emails = new List < string > ( ) ;
foreach ( var EmailList in EmailLists )
{
if ( ! String . IsNullOrEmpty ( EmailList ) )
{
List < string > Parts = new List < string > ( EmailList . Split ( ' ' ) ) ;
foreach ( var Email in Parts )
{
if ( ! string . IsNullOrEmpty ( Email ) & & ! Emails . Contains ( Email ) )
{
Emails . Add ( Email ) ;
}
}
}
}
string Result = "" ;
foreach ( var Email in Emails )
{
if ( Result ! = "" )
{
Result + = " " ;
}
Result + = Email ;
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public void SaveRecordOfSuccessAndAddToBuildProducts ( string Contents = "Just a record of success." )
{
string RecordOfSuccess = CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Saved" , "Logs" , GetFullName ( ) + "_Success.log" ) ;
CommandUtils . CreateDirectory ( Path . GetDirectoryName ( RecordOfSuccess ) ) ;
CommandUtils . WriteAllText ( RecordOfSuccess , Contents ) ;
AddBuildProduct ( RecordOfSuccess ) ;
}
public void AddDependency ( string Node )
{
if ( ! FullNamesOfDependencies . Contains ( Node ) )
{
FullNamesOfDependencies . Add ( Node ) ;
}
}
public void AddPseudodependency ( string Node )
{
if ( ! FullNamesOfPseudosependencies . Contains ( Node ) )
{
FullNamesOfPseudosependencies . Add ( Node ) ;
}
}
2015-02-10 14:58:32 -05:00
public void AddCompletedDependency ( string Node )
{
if ( ! CompletedDependencies . Contains ( Node ) )
{
CompletedDependencies . Add ( Node ) ;
}
}
2014-08-22 13:39:55 -04:00
public void RemovePseudodependency ( string Node )
{
if ( FullNamesOfPseudosependencies . Contains ( Node ) )
{
FullNamesOfPseudosependencies . Remove ( Node ) ;
}
}
public void AddBuildProduct ( string Filename )
{
if ( ! CommandUtils . FileExists_NoExceptions ( true , Filename ) )
{
throw new AutomationException ( "Cannot add build product {0} because it does not exist." , Filename ) ;
}
FileInfo Info = new FileInfo ( Filename ) ;
if ( ! BuildProducts . Contains ( Info . FullName ) )
{
BuildProducts . Add ( Info . FullName ) ;
}
}
public void AddDependentBuildProduct ( string Filename )
{
if ( ! CommandUtils . FileExists_NoExceptions ( true , Filename ) )
{
throw new AutomationException ( "Cannot add build product {0} because it does not exist." , Filename ) ;
}
FileInfo Info = new FileInfo ( Filename ) ;
if ( ! AllDependencyBuildProducts . Contains ( Info . FullName ) )
{
AllDependencyBuildProducts . Add ( Info . FullName ) ;
}
}
public void AddAllDependent ( string Node )
{
if ( ! AllDependencies . Contains ( Node ) )
{
AllDependencies . Add ( Node ) ;
}
}
public void RemoveOveralppingBuildProducts ( )
{
foreach ( var ToRemove in AllDependencyBuildProducts )
{
BuildProducts . Remove ( ToRemove ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
public class VersionFilesNode : GUBPNode
{
public static string StaticGetFullName ( )
{
return "VersionFiles" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override void DoBuild ( GUBP bp )
{
var UE4Build = new UE4Build ( bp ) ;
BuildProducts = UE4Build . UpdateVersionFiles ( ActuallyUpdateVersionFiles : CommandUtils . P4Enabled & & CommandUtils . AllowSubmit ) ;
}
public override bool IsSticky ( )
{
return true ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class HostPlatformNode : GUBPNode
{
protected UnrealTargetPlatform HostPlatform ;
public HostPlatformNode ( UnrealTargetPlatform InHostPlatform )
{
HostPlatform = InHostPlatform ;
}
2015-04-01 13:36:26 -04:00
public override string GetDisplayGroupName ( )
{
string Name = GetFullName ( ) ;
string Suffix = GetHostPlatformSuffix ( ) ;
return Name . EndsWith ( Suffix ) ? Name . Substring ( 0 , Name . Length - Suffix . Length ) : Name ;
}
2014-08-22 13:39:55 -04:00
public static string StaticGetHostPlatformSuffix ( UnrealTargetPlatform InHostPlatform , UnrealTargetPlatform InAgentPlatform = UnrealTargetPlatform . Unknown )
{
if ( InHostPlatform = = UnrealTargetPlatform . Mac )
{
if ( InAgentPlatform = = UnrealTargetPlatform . Win64 )
{
return "_ForMac" ;
}
return "_OnMac" ;
}
2014-09-05 21:50:16 -04:00
else if ( InHostPlatform = = UnrealTargetPlatform . Linux )
{
return "_OnLinux" ;
}
2014-08-22 13:39:55 -04:00
return "" ;
}
public virtual UnrealTargetPlatform GetAgentPlatform ( )
{
return HostPlatform ;
}
public override string ECProcedureInfix ( )
{
if ( GetAgentPlatform ( ) = = UnrealTargetPlatform . Mac )
{
if ( IsSticky ( ) )
{
throw new AutomationException ( "Node {0} is sticky, but Mac hosted. Sticky nodes must be PC hosted." , GetFullName ( ) ) ;
}
return "_Mac" ;
}
2014-09-08 09:45:35 -04:00
if ( GetAgentPlatform ( ) = = UnrealTargetPlatform . Linux )
{
if ( IsSticky ( ) )
{
throw new AutomationException ( "Node {0} is sticky, but Linux hosted. Sticky nodes must be PC hosted." , GetFullName ( ) ) ;
}
return "_Linux" ;
}
2014-08-22 13:39:55 -04:00
return "" ;
}
public virtual string GetHostPlatformSuffix ( )
{
return StaticGetHostPlatformSuffix ( HostPlatform , GetAgentPlatform ( ) ) ;
}
public UnrealTargetPlatform GetAltHostPlatform ( )
{
return GUBP . GetAltHostPlatform ( HostPlatform ) ;
}
public override int TimeoutInMinutes ( )
{
return base . TimeoutInMinutes ( ) + ( ( HostPlatform = = UnrealTargetPlatform . Mac ) ? 30 : 0 ) ; // Mac is slower and more resource constrained
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class CompileNode : HostPlatformNode
{
public CompileNode ( UnrealTargetPlatform InHostPlatform , bool DependentOnCompileTools = true )
: base ( InHostPlatform )
{
if ( DependentOnCompileTools )
{
AddDependency ( ToolsForCompileNode . StaticGetFullName ( HostPlatform ) ) ;
}
else
{
AddDependency ( VersionFilesNode . StaticGetFullName ( ) ) ;
}
}
public virtual UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
return null ;
}
public virtual void PostBuild ( GUBP bp , UE4Build UE4Build )
{
}
public virtual void PostBuildProducts ( GUBP bp )
{
}
public virtual bool DeleteBuildProducts ( )
{
return false ;
}
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
var UE4Build = new UE4Build ( bp ) ;
UE4Build . BuildAgenda Agenda = GetAgenda ( bp ) ;
if ( Agenda ! = null )
{
bool ReallyDeleteBuildProducts = DeleteBuildProducts ( ) & & ! GUBP . bForceIncrementalCompile ;
Agenda . DoRetries = false ; // these would delete build products
UE4Build . Build ( Agenda , InDeleteBuildProducts : ReallyDeleteBuildProducts , InUpdateVersionFiles : false , InForceUnity : true ) ;
2015-05-08 17:45:24 -04:00
var StartPostBuild = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
PostBuild ( bp , UE4Build ) ;
2015-05-08 17:45:24 -04:00
var FinishPostBuild = DateTime . Now . ToString ( ) ;
PrintCSVFile ( String . Format ( "UAT,PostBuild,{0},{1}" , StartPostBuild , FinishPostBuild ) ) ;
2014-08-22 13:39:55 -04:00
UE4Build . CheckBuildProducts ( UE4Build . BuildProductFiles ) ;
foreach ( var Product in UE4Build . BuildProductFiles )
{
AddBuildProduct ( Product ) ;
}
RemoveOveralppingBuildProducts ( ) ;
if ( bp . bSignBuildProducts )
{
// Sign everything we built
2015-05-08 17:45:24 -04:00
var StartSign = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
CodeSign . SignMultipleIfEXEOrDLL ( bp , BuildProducts ) ;
2015-05-08 17:45:24 -04:00
var FinishSign = DateTime . Now . ToString ( ) ;
PrintCSVFile ( String . Format ( "UAT,SignBuildProducts,{0},{1}" , StartSign , FinishSign ) ) ;
2014-08-22 13:39:55 -04:00
}
PostBuildProducts ( bp ) ;
}
if ( Agenda = = null | | ( BuildProducts . Count = = 0 & & GUBP . bForceIncrementalCompile ) )
{
SaveRecordOfSuccessAndAddToBuildProducts ( "Nothing to actually compile" ) ;
}
}
public override int TimeoutInMinutes ( )
{
return base . TimeoutInMinutes ( ) + ( ( HostPlatform = = UnrealTargetPlatform . Mac ) ? 30 : 0 ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class ToolsForCompileNode : CompileNode
{
public ToolsForCompileNode ( UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform , false )
{
2015-05-04 14:42:28 -04:00
if ( InHostPlatform ! = UnrealTargetPlatform . Win64 )
{
AgentSharingGroup = "Editor" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
2014-08-22 13:39:55 -04:00
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "ToolsForCompile" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
2015-05-04 14:42:28 -04:00
public override bool IsSticky ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return true ;
}
return false ;
}
public override string ECProcedure ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return String . Format ( "GUBP_UAT_Node_Parallel_AgentShare_Editor" ) ;
}
return base . ECProcedure ( ) ;
}
2014-08-22 13:39:55 -04:00
public override bool DeleteBuildProducts ( )
{
return true ;
}
public override int AgentMemoryRequirement ( GUBP bp )
{
2014-11-17 12:49:08 -05:00
if ( bp . ParseParam ( "Launcher" ) | | bp . TimeIndex ! = 0 & & HostPlatform ! = UnrealTargetPlatform . Mac )
2014-08-22 13:39:55 -04:00
{
return base . AgentMemoryRequirement ( bp ) ;
}
return 32 ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-09-05 21:50:16 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Win64 & & ! GUBP . bForceIncrementalCompile )
2014-08-22 13:39:55 -04:00
{
Agenda . DotNetProjects . AddRange (
new string [ ]
2014-03-14 14:13:41 -04:00
{
@"Engine\Source\Programs\DotNETCommon\DotNETUtilities\DotNETUtilities.csproj" ,
@"Engine\Source\Programs\RPCUtility\RPCUtility.csproj" ,
}
2014-08-22 13:39:55 -04:00
) ;
}
2015-03-30 15:01:38 -04:00
string AddArgs = "-CopyAppBundleBackToDevice" ;
2014-04-28 14:35:09 -04:00
2014-08-22 13:39:55 -04:00
Agenda . AddTargets ( new string [ ] { "UnrealHeaderTool" } , HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
return Agenda ;
}
public override void PostBuild ( GUBP bp , UE4Build UE4Build )
{
2014-09-05 21:50:16 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
2014-08-22 13:39:55 -04:00
{
UE4Build . AddUATFilesToBuildProducts ( ) ;
UE4Build . AddUBTFilesToBuildProducts ( ) ;
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class RootEditorNode : CompileNode
{
public RootEditorNode ( UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform )
{
2015-05-04 14:42:28 -04:00
if ( InHostPlatform ! = UnrealTargetPlatform . Win64 )
{
AgentSharingGroup = "Editor" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
2014-08-22 13:39:55 -04:00
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "RootEditor" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
}
2015-04-20 13:43:49 -04:00
public override void DoBuild ( GUBP bp )
{
base . DoBuild ( bp ) ;
if ( ! bp . BranchOptions . bNoInstalledEngine )
{
FileFilter Filter = new FileFilter ( ) ;
Filter . Include ( "/Engine/Intermediate/Build/" + HostPlatform . ToString ( ) + "/UE4Editor/Inc/..." ) ;
Filter . Include ( "/Engine/Plugins/.../Intermediate/Build/" + HostPlatform . ToString ( ) + "/UE4Editor/Inc/..." ) ;
string ZipFileName = StaticGetArchivedHeadersPath ( HostPlatform ) ;
CommandUtils . ZipFiles ( ZipFileName , CommandUtils . CmdEnv . LocalRoot , Filter ) ;
BuildProducts . Add ( ZipFileName ) ;
}
}
public static string StaticGetArchivedHeadersPath ( UnrealTargetPlatform HostPlatform )
{
return CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Saved" , "Precompiled" , "Headers-RootEditor" + StaticGetHostPlatformSuffix ( HostPlatform ) + ".zip" ) ;
}
2015-05-04 14:42:28 -04:00
public override bool IsSticky ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return true ;
}
return false ;
}
public override string ECProcedure ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return String . Format ( "GUBP_UAT_Node_Parallel_AgentShare_Editor" ) ;
}
return base . ECProcedure ( ) ;
}
2014-08-22 13:39:55 -04:00
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2015-05-16 17:45:08 -04:00
string AddArgs = "-nobuilduht" ;
if ( ! bp . BranchOptions . bNoInstalledEngine )
{
AddArgs + = " -precompile" ;
}
2014-08-22 13:39:55 -04:00
if ( bp . bOrthogonalizeEditorPlatforms )
{
AddArgs + = " -skipnonhostplatforms" ;
}
Agenda . AddTargets (
new string [ ] { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ,
HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithBaseEditor ( ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
}
}
return Agenda ;
}
void DeleteStaleDLLs ( GUBP bp )
{
if ( GUBP . bForceIncrementalCompile )
{
return ;
}
var Targets = new List < string > { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ;
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithBaseEditor ( ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) )
{
Targets . Add ( ProgramTarget . TargetName ) ;
}
}
2014-04-23 17:28:32 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Target in Targets )
{
var EnginePlatformBinaries = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Binaries" , HostPlatform . ToString ( ) ) ;
var Wildcard = Target + "-*" ;
Log ( "************Deleting stale editor DLLs, path {0} wildcard {1}" , EnginePlatformBinaries , Wildcard ) ;
foreach ( var DiskFile in FindFiles ( Wildcard , true , EnginePlatformBinaries ) )
{
bool IsBuildProduct = false ;
foreach ( var Product in BuildProducts )
{
if ( Product . Equals ( DiskFile , StringComparison . InvariantCultureIgnoreCase ) )
{
IsBuildProduct = true ;
break ;
}
}
if ( ! IsBuildProduct )
{
DeleteFile ( DiskFile ) ;
}
}
var EnginePluginBinaries = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Plugins" ) ;
var HostSubstring = CommandUtils . CombinePaths ( "/" , HostPlatform . ToString ( ) , "/" ) ;
Log ( "************Deleting stale editor DLLs, path {0} wildcard {1} host {2}" , EnginePluginBinaries , Wildcard , HostSubstring ) ;
foreach ( var DiskFile in FindFiles ( Wildcard , true , EnginePluginBinaries ) )
{
if ( DiskFile . IndexOf ( HostSubstring , StringComparison . InvariantCultureIgnoreCase ) < 0 )
{
continue ;
}
bool IsBuildProduct = false ;
foreach ( var Product in BuildProducts )
{
if ( Product . Equals ( DiskFile , StringComparison . InvariantCultureIgnoreCase ) )
{
IsBuildProduct = true ;
break ;
}
}
if ( ! IsBuildProduct )
{
DeleteFile ( DiskFile ) ;
}
}
}
}
public override void PostLoadFromSharedTempStorage ( GUBP bp )
{
DeleteStaleDLLs ( bp ) ;
}
public override void PostBuildProducts ( GUBP bp )
{
DeleteStaleDLLs ( bp ) ;
}
}
2014-10-15 10:22:11 -04:00
public class RootEditorCrossCompileLinuxNode : CompileNode
{
public RootEditorCrossCompileLinuxNode ( UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform )
{
AddDependency ( RootEditorNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
AddDependency ( ToolsForCompileNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
}
2015-04-03 08:25:54 -04:00
public static string StaticGetFullName ( )
2014-10-15 10:22:11 -04:00
{
return "RootEditor_Linux" ;
}
public override string GetFullName ( )
{
2015-04-03 08:25:54 -04:00
return StaticGetFullName ( ) ;
2014-10-15 10:22:11 -04:00
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 3 ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht" ;
2014-10-15 10:22:11 -04:00
Agenda . AddTargets (
new string [ ] { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ,
UnrealTargetPlatform . Linux , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
2015-04-09 14:42:37 -04:00
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithBaseEditor ( ) & & ProgramTarget . Rules . SupportsPlatform ( UnrealTargetPlatform . Linux ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , UnrealTargetPlatform . Linux , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
}
}
2014-10-15 10:22:11 -04:00
return Agenda ;
}
2015-04-09 14:42:37 -04:00
void DeleteStaleDLLs ( GUBP bp )
{
if ( GUBP . bForceIncrementalCompile )
{
return ;
}
var Targets = new List < string > { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ;
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithBaseEditor ( ) & & ProgramTarget . Rules . SupportsPlatform ( UnrealTargetPlatform . Linux ) )
{
Targets . Add ( ProgramTarget . TargetName ) ;
}
}
foreach ( var Target in Targets )
{
var EnginePlatformBinaries = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Binaries" , UnrealTargetPlatform . Linux . ToString ( ) ) ;
var Wildcard = Target + "-*" ;
Log ( "************Deleting stale editor DLLs, path {0} wildcard {1}" , EnginePlatformBinaries , Wildcard ) ;
foreach ( var DiskFile in FindFiles ( Wildcard , true , EnginePlatformBinaries ) )
{
bool IsBuildProduct = false ;
foreach ( var Product in BuildProducts )
{
if ( Product . Equals ( DiskFile , StringComparison . InvariantCultureIgnoreCase ) )
{
IsBuildProduct = true ;
break ;
}
}
if ( ! IsBuildProduct )
{
DeleteFile ( DiskFile ) ;
}
}
var EnginePluginBinaries = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Plugins" ) ;
var HostSubstring = CommandUtils . CombinePaths ( "/" , UnrealTargetPlatform . Linux . ToString ( ) , "/" ) ;
Log ( "************Deleting stale editor DLLs, path {0} wildcard {1} host {2}" , EnginePluginBinaries , Wildcard , HostSubstring ) ;
foreach ( var DiskFile in FindFiles ( Wildcard , true , EnginePluginBinaries ) )
{
if ( DiskFile . IndexOf ( HostSubstring , StringComparison . InvariantCultureIgnoreCase ) < 0 )
{
continue ;
}
bool IsBuildProduct = false ;
foreach ( var Product in BuildProducts )
{
if ( Product . Equals ( DiskFile , StringComparison . InvariantCultureIgnoreCase ) )
{
IsBuildProduct = true ;
break ;
}
}
if ( ! IsBuildProduct )
{
DeleteFile ( DiskFile ) ;
}
}
}
}
public override void PostLoadFromSharedTempStorage ( GUBP bp )
{
DeleteStaleDLLs ( bp ) ;
}
public override void PostBuildProducts ( GUBP bp )
{
DeleteStaleDLLs ( bp ) ;
}
2014-10-15 10:22:11 -04:00
}
2014-08-22 13:39:55 -04:00
public class ToolsNode : CompileNode
{
2015-05-17 09:45:42 -04:00
public ToolsNode ( GUBP bp , UnrealTargetPlatform InHostPlatform )
2014-08-22 13:39:55 -04:00
: base ( InHostPlatform )
{
2015-05-17 09:45:42 -04:00
if ( ! bp . BranchOptions . bNoEditorDependenciesForTools )
{
AddPseudodependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
}
2014-08-22 13:39:55 -04:00
AgentSharingGroup = "ToolsGroup" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "Tools" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
public override float Priority ( )
{
return base . Priority ( ) - 1 ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2014-09-05 21:50:16 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
2014-08-22 13:39:55 -04:00
{
2014-04-25 10:39:39 -04:00
if ( ! GUBP . bForceIncrementalCompile )
{
Agenda . DotNetProjects . AddRange (
new string [ ]
{
CombinePaths ( @"Engine\Source\Programs\UnrealControls\UnrealControls.csproj" ) ,
}
) ;
}
2014-08-22 13:39:55 -04:00
Agenda . DotNetSolutions . AddRange (
2014-04-25 10:39:39 -04:00
new string [ ]
{
CombinePaths ( @"Engine\Source\Programs\NetworkProfiler\NetworkProfiler.sln" ) ,
}
2014-08-22 13:39:55 -04:00
) ;
if ( ! GUBP . bForceIncrementalCompile )
{
2014-04-25 10:39:39 -04:00
Agenda . SwarmProject = CombinePaths ( @"Engine\Source\Programs\UnrealSwarm\UnrealSwarm.sln" ) ;
}
2014-12-15 15:29:48 -05:00
bool WithIOS = ! bp . BranchOptions . PlatformsToRemove . Contains ( UnrealTargetPlatform . IOS ) ;
if ( WithIOS )
{
Agenda . IOSDotNetProjects . AddRange (
2014-08-22 13:39:55 -04:00
new string [ ]
2014-04-25 10:39:39 -04:00
{
CombinePaths ( @"Engine\Source\Programs\IOS\iPhonePackager\iPhonePackager.csproj" ) ,
CombinePaths ( @"Engine\Source\Programs\IOS\DeploymentServer\DeploymentServer.csproj" ) ,
CombinePaths ( @"Engine\Source\Programs\IOS\MobileDeviceInterface\MobileDeviceInterface.csproj" ) ,
CombinePaths ( @"Engine\Source\Programs\IOS\DeploymentInterface\DeploymentInterface.csproj" ) ,
}
2014-08-22 13:39:55 -04:00
) ;
2014-12-15 15:29:48 -05:00
}
2015-05-11 04:28:33 -04:00
bool WithHTML5 = ! bp . BranchOptions . PlatformsToRemove . Contains ( UnrealTargetPlatform . HTML5 ) ;
if ( WithHTML5 )
{
Agenda . HTML5DotNetProjects . AddRange (
new string [ ]
{
CombinePaths ( @"Engine\Source\Programs\HTML5\HTML5LaunchHelper\HTML5LaunchHelper.csproj" ) ,
}
) ;
}
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice" ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
bool bInternalOnly ;
bool SeparateNode ;
2015-01-06 10:24:25 -05:00
bool CrossCompile ;
2015-03-12 08:29:35 -04:00
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithTools ( HostPlatform , out bInternalOnly , out SeparateNode , out CrossCompile ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) & & ! bInternalOnly & & ! SeparateNode )
2014-08-22 13:39:55 -04:00
{
2015-05-04 17:28:40 -04:00
if ( ! bp . BranchOptions . ExcludeNodes . Contains ( ProgramTarget . TargetName ) )
2014-08-22 13:39:55 -04:00
{
2015-05-04 17:28:40 -04:00
foreach ( var Plat in ProgramTarget . Rules . GUBP_ToolPlatforms ( HostPlatform ) )
2014-08-22 13:39:55 -04:00
{
2015-05-04 17:28:40 -04:00
foreach ( var Config in ProgramTarget . Rules . GUBP_ToolConfigs ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , Plat , Config , InAddArgs : AddArgs ) ;
}
2014-08-22 13:39:55 -04:00
}
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
return Agenda ;
}
}
2015-01-06 10:24:25 -05:00
public class ToolsCrossCompileNode : CompileNode
{
public ToolsCrossCompileNode ( UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform )
{
2015-04-03 08:25:54 -04:00
AddPseudodependency ( RootEditorCrossCompileLinuxNode . StaticGetFullName ( ) ) ;
2015-01-06 10:24:25 -05:00
AgentSharingGroup = "ToolsCrossCompileGroup" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "LinuxTools" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
public override float Priority ( )
{
return base . Priority ( ) - 1 ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice" ;
2015-01-06 10:24:25 -05:00
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
bool bInternalOnly ;
bool SeparateNode ;
bool CrossCompile ;
2015-03-12 08:29:35 -04:00
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithTools ( HostPlatform , out bInternalOnly , out SeparateNode , out CrossCompile ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) & & ! bInternalOnly & & ! SeparateNode & & CrossCompile )
2015-01-06 10:24:25 -05:00
{
foreach ( var Config in ProgramTarget . Rules . GUBP_ToolConfigs ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , UnrealTargetPlatform . Linux , Config , InAddArgs : AddArgs ) ;
}
}
}
return Agenda ;
}
}
2014-08-22 13:39:55 -04:00
public class SingleToolsNode : CompileNode
{
SingleTargetProperties ProgramTarget ;
public SingleToolsNode ( UnrealTargetPlatform InHostPlatform , SingleTargetProperties InProgramTarget )
: base ( InHostPlatform )
{
ProgramTarget = InProgramTarget ;
2015-03-30 15:01:38 -04:00
AddPseudodependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
2014-08-22 13:39:55 -04:00
AgentSharingGroup = "ToolsGroup" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , SingleTargetProperties InProgramTarget )
{
return "Tools_" + InProgramTarget . TargetName + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , ProgramTarget ) ;
}
public override float Priority ( )
{
return base . Priority ( ) + 2 ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-04-23 17:51:55 -04:00
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice" ;
2014-04-23 17:51:55 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Plat in ProgramTarget . Rules . GUBP_ToolPlatforms ( HostPlatform ) )
{
foreach ( var Config in ProgramTarget . Rules . GUBP_ToolConfigs ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , Plat , Config , InAddArgs : AddArgs ) ;
}
}
return Agenda ;
}
}
2014-04-23 17:51:55 -04:00
2014-08-22 13:39:55 -04:00
public class InternalToolsNode : CompileNode
{
2015-05-17 09:45:42 -04:00
public InternalToolsNode ( GUBP bp , UnrealTargetPlatform InHostPlatform )
2014-08-22 13:39:55 -04:00
: base ( InHostPlatform )
{
2015-05-17 09:45:42 -04:00
if ( ! bp . BranchOptions . bNoEditorDependenciesForTools )
{
AddPseudodependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
}
2014-08-22 13:39:55 -04:00
AgentSharingGroup = "ToolsGroup" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "InternalTools" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
public override float Priority ( )
{
return base . Priority ( ) - 2 ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
2014-09-03 10:12:50 -04:00
int Result = base . CISFrequencyQuantumShift ( bp ) + 1 ;
2014-08-22 13:39:55 -04:00
return Result ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
bool bAnyAdded = false ;
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2014-09-05 21:50:16 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
2014-08-22 13:39:55 -04:00
{
bAnyAdded = true ;
Agenda . DotNetProjects . AddRange (
new string [ ]
2014-03-14 14:13:41 -04:00
{
2014-04-29 21:51:03 -04:00
CombinePaths ( @"Engine\Source\Programs\NotForLicensees\CrashReportServer\CrashReportCommon\CrashReportCommon.csproj" ) ,
CombinePaths ( @"Engine\Source\Programs\NotForLicensees\CrashReportServer\CrashReportReceiver\CrashReportReceiver.csproj" ) ,
CombinePaths ( @"Engine\Source\Programs\NotForLicensees\CrashReportServer\CrashReportProcess\CrashReportProcess.csproj" ) ,
2014-03-14 14:13:41 -04:00
CombinePaths ( @"Engine\Source\Programs\CrashReporter\RegisterPII\RegisterPII.csproj" ) ,
} ) ;
2014-08-22 13:39:55 -04:00
Agenda . DotNetSolutions . AddRange (
new string [ ]
2014-03-14 14:13:41 -04:00
{
CombinePaths ( @"Engine\Source\Programs\UnrealDocTool\UnrealDocTool\UnrealDocTool.sln" ) ,
}
2014-08-22 13:39:55 -04:00
) ;
Agenda . ExtraDotNetFiles . AddRange (
new string [ ]
2014-03-14 14:13:41 -04:00
{
"Interop.IWshRuntimeLibrary" ,
"UnrealMarkdown" ,
"CommonUnrealMarkdown" ,
}
2014-08-22 13:39:55 -04:00
) ;
}
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice" ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
bool bInternalOnly ;
bool SeparateNode ;
2015-01-06 10:24:25 -05:00
bool CrossCompile ;
2015-03-12 08:29:35 -04:00
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithTools ( HostPlatform , out bInternalOnly , out SeparateNode , out CrossCompile ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) & & bInternalOnly & & ! SeparateNode )
2014-08-22 13:39:55 -04:00
{
foreach ( var Plat in ProgramTarget . Rules . GUBP_ToolPlatforms ( HostPlatform ) )
{
foreach ( var Config in ProgramTarget . Rules . GUBP_ToolConfigs ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , Plat , Config , InAddArgs : AddArgs ) ;
bAnyAdded = true ;
}
}
}
}
if ( bAnyAdded )
{
return Agenda ;
}
return null ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class SingleInternalToolsNode : CompileNode
{
SingleTargetProperties ProgramTarget ;
public SingleInternalToolsNode ( UnrealTargetPlatform InHostPlatform , SingleTargetProperties InProgramTarget )
: base ( InHostPlatform )
{
2015-03-09 23:22:37 -04:00
SetupSingleInternalToolsNode ( InProgramTarget ) ;
2014-08-22 13:39:55 -04:00
}
2015-03-09 23:22:37 -04:00
public SingleInternalToolsNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , SingleTargetProperties InProgramTarget )
: base ( InHostPlatform )
{
// Don't add rooteditor dependency if it isn't in the graph
var bRootEditorNodeDoesExit = bp . HasNode ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
2015-05-17 09:45:42 -04:00
SetupSingleInternalToolsNode ( InProgramTarget , ! bRootEditorNodeDoesExit & & bp . BranchOptions . bNoEditorDependenciesForTools ) ;
2015-03-09 23:22:37 -04:00
}
private void SetupSingleInternalToolsNode ( SingleTargetProperties InProgramTarget , bool bSkipRootEditorPsuedoDependency = true )
{
ProgramTarget = InProgramTarget ;
AgentSharingGroup = "ToolsGroup" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
2015-03-30 15:01:38 -04:00
if ( ! bSkipRootEditorPsuedoDependency )
2015-03-09 23:22:37 -04:00
{
AddPseudodependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
}
}
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , SingleTargetProperties InProgramTarget )
{
return "InternalTools_" + InProgramTarget . TargetName + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , ProgramTarget ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
int Result = base . CISFrequencyQuantumShift ( bp ) + 1 ;
return Result ;
}
public override float Priority ( )
{
return base . Priority ( ) + 3 ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
}
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-04-23 17:51:55 -04:00
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice" ;
2014-04-23 17:51:55 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Plat in ProgramTarget . Rules . GUBP_ToolPlatforms ( HostPlatform ) )
{
foreach ( var Config in ProgramTarget . Rules . GUBP_ToolConfigs ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , Plat , Config , InAddArgs : AddArgs ) ;
}
}
return Agenda ;
}
}
2014-04-23 17:51:55 -04:00
2014-08-22 13:39:55 -04:00
public class EditorPlatformNode : CompileNode
{
UnrealTargetPlatform EditorPlatform ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public EditorPlatformNode ( UnrealTargetPlatform InHostPlatform , UnrealTargetPlatform Plat )
: base ( InHostPlatform )
{
2015-05-04 14:42:28 -04:00
if ( InHostPlatform ! = UnrealTargetPlatform . Win64 )
{
AgentSharingGroup = "Editor" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
2014-08-22 13:39:55 -04:00
EditorPlatform = Plat ;
AddDependency ( RootEditorNode . StaticGetFullName ( InHostPlatform ) ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , UnrealTargetPlatform Plat )
{
return Plat . ToString ( ) + "_EditorPlatform" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , EditorPlatform ) ;
}
public override float Priority ( )
{
return base . Priority ( ) + 1 ;
}
2015-05-04 14:42:28 -04:00
public override bool IsSticky ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return true ;
}
return false ;
}
public override string ECProcedure ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return String . Format ( "GUBP_UAT_Node_Parallel_AgentShare_Editor" ) ;
}
return base . ECProcedure ( ) ;
}
2014-08-22 13:39:55 -04:00
public override int CISFrequencyQuantumShift ( GUBP bp )
{
int Result = base . CISFrequencyQuantumShift ( bp ) ;
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
if ( ! bp . bOrthogonalizeEditorPlatforms )
{
throw new AutomationException ( "EditorPlatformNode node should not be used unless we are orthogonalizing editor platforms." ) ;
}
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Agenda . AddTargets (
new string [ ] { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ,
HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice -onlyplatformspecificfor=" + EditorPlatform . ToString ( ) ) ;
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithBaseEditor ( ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) & & ProgramTarget . Rules . GUBP_NeedsPlatformSpecificDLLs ( ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice -onlyplatformspecificfor=" + EditorPlatform . ToString ( ) ) ;
}
}
return Agenda ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class EditorGameNode : CompileNode
{
2015-04-17 08:15:17 -04:00
List < BranchInfo . BranchUProject > GameProjects = new List < BranchInfo . BranchUProject > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public EditorGameNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj )
: base ( InHostPlatform )
{
2015-05-04 14:42:28 -04:00
if ( InHostPlatform ! = UnrealTargetPlatform . Win64 )
{
AgentSharingGroup = "Editor" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
2015-04-17 08:15:17 -04:00
GameProjects . Add ( InGameProj ) ;
2014-12-17 11:37:40 -05:00
AddDependency ( RootEditorNode . StaticGetFullName ( InHostPlatform ) ) ;
}
2015-04-17 08:15:17 -04:00
public void AddProject ( BranchInfo . BranchUProject InGameProj )
{
if ( InGameProj . Options ( HostPlatform ) . GroupName ! = GameProjects [ 0 ] . Options ( HostPlatform ) . GroupName )
{
throw new AutomationException ( "Attempt to merge projects with different group names" ) ;
}
GameProjects . Add ( InGameProj ) ;
}
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj )
{
2015-04-17 08:15:17 -04:00
return ( InGameProj . Options ( InHostPlatform ) . GroupName ? ? InGameProj . GameName ) + "_EditorGame" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
2014-08-22 13:39:55 -04:00
}
public override string GetFullName ( )
{
2015-04-17 08:15:17 -04:00
return StaticGetFullName ( HostPlatform , GameProjects [ 0 ] ) ;
2014-08-22 13:39:55 -04:00
}
2015-05-04 14:42:28 -04:00
public override bool IsSticky ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return true ;
}
return false ;
}
public override string ECProcedure ( )
{
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
return String . Format ( "GUBP_UAT_Node_Parallel_AgentShare_Editor" ) ;
}
return base . ECProcedure ( ) ;
}
2014-08-22 13:39:55 -04:00
public override string GameNameIfAnyForTempStorage ( )
{
2015-04-17 08:15:17 -04:00
return GameProjects [ 0 ] . Options ( HostPlatform ) . GroupName ? ? GameProjects [ 0 ] . GameName ;
2014-12-17 11:37:40 -05:00
}
2014-08-22 13:39:55 -04:00
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2015-05-16 17:45:08 -04:00
string Args = "-nobuilduht -skipactionhistory -skipnonhostplatforms -CopyAppBundleBackToDevice -forceheadergeneration" ;
if ( ! bp . BranchOptions . bNoInstalledEngine )
{
Args + = " -precompile" ;
}
2014-04-02 18:09:23 -04:00
2015-04-17 08:15:17 -04:00
foreach ( BranchInfo . BranchUProject GameProj in GameProjects )
{
Agenda . AddTargets (
new string [ ] { GameProj . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ,
HostPlatform , UnrealTargetConfiguration . Development , GameProj . FilePath , InAddArgs : Args ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
return Agenda ;
}
}
2014-03-14 14:13:41 -04:00
2015-03-21 10:00:59 -04:00
public class MakeFeaturePacksNode : HostPlatformNode
2015-02-09 19:52:57 -05:00
{
2015-03-21 10:00:59 -04:00
List < BranchInfo . BranchUProject > Projects ;
2015-02-09 19:52:57 -05:00
2015-03-21 10:00:59 -04:00
public MakeFeaturePacksNode ( UnrealTargetPlatform InHostPlatform , IEnumerable < BranchInfo . BranchUProject > InProjects )
2015-02-09 19:52:57 -05:00
: base ( InHostPlatform )
{
2015-03-21 10:00:59 -04:00
Projects = new List < BranchInfo . BranchUProject > ( InProjects ) ;
2015-02-09 19:52:57 -05:00
AddDependency ( ToolsNode . StaticGetFullName ( InHostPlatform ) ) ; // for UnrealPak
2015-04-16 14:08:40 -04:00
AgentSharingGroup = "ToolsGroup" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
2015-02-09 19:52:57 -05:00
}
2015-03-21 10:00:59 -04:00
public static string GetOutputFile ( BranchInfo . BranchUProject Project )
{
return CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "FeaturePacks" , Path . GetFileNameWithoutExtension ( Project . GameName ) + ".upack" ) ;
}
2015-02-16 10:51:24 -05:00
public static bool IsFeaturePack ( BranchInfo . BranchUProject InGameProj )
2015-02-09 19:52:57 -05:00
{
// No obvious way to store this in the project options; it's a property of non-code projects too.
2015-02-16 10:51:24 -05:00
if ( InGameProj . GameName = = "StarterContent" | | InGameProj . GameName = = "MobileStarterContent" | | InGameProj . GameName . StartsWith ( "FP_" ) )
2015-02-09 19:52:57 -05:00
{
2015-02-16 10:51:24 -05:00
return true ;
}
if ( InGameProj . GameName . StartsWith ( "TP_" ) )
{
return CommandUtils . FileExists ( CommandUtils . CombinePaths ( CommandUtils . GetDirectoryName ( InGameProj . FilePath ) , "contents.txt" ) ) ;
2015-02-09 19:52:57 -05:00
}
return false ;
}
2015-02-16 10:51:24 -05:00
public static UnrealTargetPlatform GetDefaultBuildPlatform ( GUBP bp )
{
if ( bp . HostPlatforms . Contains ( UnrealTargetPlatform . Win64 ) )
{
return UnrealTargetPlatform . Win64 ;
}
else if ( bp . HostPlatforms . Contains ( UnrealTargetPlatform . Mac ) )
{
return UnrealTargetPlatform . Mac ;
}
else
{
2015-04-16 12:56:30 -04:00
if ( UnrealBuildTool . BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Linux & & bp . HostPlatforms [ 0 ] ! = UnrealTargetPlatform . Linux )
{
throw new AutomationException ( "Linux is not (yet?) able to cross-compile nodes for platform {0}, did you forget -NoPC / -NoMac?" , bp . HostPlatforms [ 0 ] ) ;
}
2015-02-16 10:51:24 -05:00
return bp . HostPlatforms [ 0 ] ;
}
}
2015-03-21 10:00:59 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
2015-02-09 19:52:57 -05:00
{
2015-03-21 10:00:59 -04:00
return "MakeFeaturePacks" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
2015-02-09 19:52:57 -05:00
}
public override string GetFullName ( )
{
2015-03-21 10:00:59 -04:00
return StaticGetFullName ( HostPlatform ) ;
2015-02-09 19:52:57 -05:00
}
2015-02-16 10:35:26 -05:00
public override int CISFrequencyQuantumShift ( GUBP bp )
{
2015-03-27 08:02:21 -04:00
return base . CISFrequencyQuantumShift ( bp ) + 2 ;
2015-02-16 10:35:26 -05:00
}
2015-02-09 19:52:57 -05:00
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
2015-03-21 10:00:59 -04:00
foreach ( BranchInfo . BranchUProject Project in Projects )
{
string ContentsFileName = CommandUtils . CombinePaths ( CommandUtils . GetDirectoryName ( Project . FilePath ) , "contents.txt" ) ;
// Make sure we delete the output file. It may be read-only.
string OutputFileName = GetOutputFile ( Project ) ;
CommandUtils . DeleteFile ( OutputFileName ) ;
// Get the command line
string CmdLine = CommandUtils . MakePathSafeToUseWithCommandLine ( OutputFileName ) + " " + CommandUtils . MakePathSafeToUseWithCommandLine ( "-create=" + ContentsFileName ) ;
if ( GlobalCommandLine . Installed )
{
CmdLine + = " -installed" ;
}
if ( GlobalCommandLine . UTF8Output )
{
CmdLine + = " -UTF8Output" ;
}
// Run UnrealPak
string UnrealPakExe ;
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
UnrealPakExe = CombinePaths ( CmdEnv . LocalRoot , "Engine/Binaries/Win64/UnrealPak.exe" ) ;
}
else
{
throw new AutomationException ( "Unknown path to UnrealPak for host platform ({0})" , HostPlatform ) ;
}
RunAndLog ( CmdEnv , UnrealPakExe , CmdLine , Options : ERunOptions . Default | ERunOptions . AllowSpew | ERunOptions . UTF8Output ) ;
// Add the build products
BuildProducts . Add ( OutputFileName ) ;
}
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
2015-02-09 19:52:57 -05:00
}
}
2014-08-22 13:39:55 -04:00
public class GamePlatformMonolithicsNode : CompileNode
{
BranchInfo . BranchUProject GameProj ;
UnrealTargetPlatform TargetPlatform ;
2015-01-28 08:26:51 -05:00
bool WithXp ;
2015-03-27 09:13:06 -04:00
bool Precompiled ; // If true, just builds targets which generate static libraries for the -UsePrecompiled option to UBT. If false, just build those that don't.
2015-03-21 12:44:14 -04:00
2015-03-21 15:21:14 -04:00
public GamePlatformMonolithicsNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InTargetPlatform , bool InWithXp = false , bool InPrecompiled = false )
2014-08-22 13:39:55 -04:00
: base ( InHostPlatform )
{
GameProj = InGameProj ;
TargetPlatform = InTargetPlatform ;
2015-01-28 08:26:51 -05:00
WithXp = InWithXp ;
2015-03-21 15:21:14 -04:00
Precompiled = InPrecompiled ;
2015-03-21 12:44:14 -04:00
2015-04-17 15:40:57 -04:00
if ( TargetPlatform = = UnrealTargetPlatform . PS4 | | TargetPlatform = = UnrealTargetPlatform . XboxOne )
2014-08-22 13:39:55 -04:00
{
2015-04-17 15:40:57 -04:00
// Required for PS4MapFileUtil/XboxOnePDBFileUtil
AddDependency ( ToolsNode . StaticGetFullName ( InHostPlatform ) ) ;
2014-08-22 13:39:55 -04:00
}
2015-04-17 15:40:57 -04:00
2014-08-22 13:39:55 -04:00
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
2015-02-24 18:49:02 -05:00
if ( ! bp . BranchOptions . ExcludePlatformsForEditor . Contains ( InHostPlatform ) )
{
AddPseudodependency ( EditorGameNode . StaticGetFullName ( InHostPlatform , GameProj ) ) ;
}
2014-08-22 13:39:55 -04:00
if ( bp . HasNode ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , TargetPlatform ) ) )
{
AddPseudodependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , TargetPlatform ) ) ;
}
}
else
{
2015-04-01 13:36:26 -04:00
if ( TargetPlatform ! = InHostPlatform & & bp . HasNode ( GamePlatformMonolithicsNode . StaticGetFullName ( InHostPlatform , bp . Branch . BaseEngineProject , InHostPlatform , Precompiled : Precompiled ) ) )
2014-08-22 13:39:55 -04:00
{
2015-04-01 13:36:26 -04:00
AddPseudodependency ( GamePlatformMonolithicsNode . StaticGetFullName ( InHostPlatform , bp . Branch . BaseEngineProject , InHostPlatform , Precompiled : Precompiled ) ) ;
2014-08-22 13:39:55 -04:00
}
}
if ( InGameProj . Options ( InHostPlatform ) . bTestWithShared ) /// compiling templates is only for testing purposes, and we will group them to avoid saturating the farm
{
AddPseudodependency ( WaitForTestShared . StaticGetFullName ( ) ) ;
AgentSharingGroup = "TemplateMonolithics" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
}
2014-03-14 14:13:41 -04:00
2015-04-01 13:36:26 -04:00
public override string GetDisplayGroupName ( )
{
return GameProj . GameName + "_Monolithics" + ( Precompiled ? "_Precompiled" : "" ) ;
}
2015-03-21 15:21:14 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InTargetPlatform , bool WithXp = false , bool Precompiled = false )
2014-08-22 13:39:55 -04:00
{
2015-03-21 15:21:14 -04:00
string Name = InGameProj . GameName ;
if ( WithXp )
2015-01-28 08:26:51 -05:00
{
2015-03-21 15:21:14 -04:00
Name + = "_WinXP_Mono" ;
}
2015-01-28 08:26:51 -05:00
else
{
2015-03-21 15:21:14 -04:00
Name + = "_" + InTargetPlatform + "_Mono" ;
2015-01-28 08:26:51 -05:00
}
2015-03-21 15:21:14 -04:00
if ( Precompiled )
{
Name + = "_Precompiled" ;
}
return Name + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
2014-08-22 13:39:55 -04:00
}
public override string GetFullName ( )
{
2015-03-21 15:21:14 -04:00
return StaticGetFullName ( HostPlatform , GameProj , TargetPlatform , WithXp , Precompiled ) ;
2014-08-22 13:39:55 -04:00
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override bool DeleteBuildProducts ( )
{
return true ;
2015-05-12 18:36:53 -04:00
}
public override int AgentMemoryRequirement ( GUBP bp )
{
if ( bp . BranchOptions . EnhanceAgentRequirements . Contains ( StaticGetFullName ( HostPlatform , GameProj , TargetPlatform , WithXp , Precompiled ) ) )
{
return 64 ;
}
return base . AgentMemoryRequirement ( bp ) ;
}
2014-06-23 14:06:45 -04:00
2014-08-22 13:39:55 -04:00
public override int CISFrequencyQuantumShift ( GUBP bp )
{
int Result = base . CISFrequencyQuantumShift ( bp ) ;
2015-04-01 15:08:23 -04:00
if ( GameProj . GameName ! = bp . Branch . BaseEngineProject . GameName | | ! Precompiled )
2014-08-22 13:39:55 -04:00
{
Result + = 3 ; //only every 80m
}
else if ( TargetPlatform ! = HostPlatform )
{
Result + = 2 ; //only every 40m
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2015-03-21 15:21:14 -04:00
public static bool HasPrecompiledTargets ( BranchInfo . BranchUProject Project , UnrealTargetPlatform HostPlatform , UnrealTargetPlatform TargetPlatform )
{
foreach ( TargetRules . TargetType Kind in BranchInfo . MonolithicKinds )
{
if ( Project . Properties . Targets . ContainsKey ( Kind ) )
{
SingleTargetProperties Target = Project . Properties . Targets [ Kind ] ;
if ( Target . Rules . GUBP_GetConfigsForPrecompiledBuilds_MonolithicOnly ( HostPlatform , TargetPlatform ) . Any ( ) )
{
return true ;
}
}
}
return false ;
}
2015-04-24 20:25:23 -04:00
public override float Priority ( )
{
float Result = base . Priority ( ) ;
if ( Precompiled )
{
Result + = 1.0f ;
}
return Result ;
}
2015-04-01 08:35:36 -04:00
public override void DoBuild ( GUBP bp )
{
base . DoBuild ( bp ) ;
if ( Precompiled )
{
// Get a list of all the build dependencies
UE4Build . BuildAgenda Agenda = GetAgenda ( bp ) ;
string FileListPath = new UE4Build ( bp ) . GenerateExternalFileList ( Agenda ) ;
UnrealBuildTool . ExternalFileList FileList = UnrealBuildTool . Utils . ReadClass < UnrealBuildTool . ExternalFileList > ( FileListPath ) ;
// Make all the paths relative to the root
string FilterPrefix = CommandUtils . CombinePaths ( PathSeparator . Slash , CommandUtils . CmdEnv . LocalRoot ) . TrimEnd ( '/' ) + "/" ;
for ( int Idx = 0 ; Idx < FileList . FileNames . Count ; Idx + + )
{
if ( FileList . FileNames [ Idx ] . StartsWith ( FilterPrefix , StringComparison . InvariantCultureIgnoreCase ) )
{
FileList . FileNames [ Idx ] = FileList . FileNames [ Idx ] . Substring ( FilterPrefix . Length ) ;
}
else
{
CommandUtils . LogError ( "Referenced external file is not under local root: {0}" , FileList . FileNames [ Idx ] ) ;
}
}
// Write the resulting file list out to disk
2015-04-20 13:43:49 -04:00
string OutputFileListPath = StaticGetBuildDependenciesPath ( HostPlatform , GameProj , TargetPlatform ) ;
2015-04-01 08:35:36 -04:00
UnrealBuildTool . Utils . WriteClass < UnrealBuildTool . ExternalFileList > ( FileList , OutputFileListPath , "" ) ;
AddBuildProduct ( OutputFileListPath ) ;
2015-04-20 13:43:49 -04:00
// Archive all the headers
FileFilter Filter = new FileFilter ( ) ;
2015-05-02 14:05:46 -04:00
Filter . Include ( "/Engine/Intermediate/Build/" + TargetPlatform . ToString ( ) + "/UE4/Inc/..." ) ;
Filter . Include ( "/Engine/Plugins/.../Intermediate/Build/" + TargetPlatform . ToString ( ) + "/UE4/Inc/..." ) ;
2015-04-20 13:43:49 -04:00
string ZipFileName = StaticGetArchivedHeadersPath ( HostPlatform , GameProj , TargetPlatform ) ;
CommandUtils . ZipFiles ( ZipFileName , CommandUtils . CmdEnv . LocalRoot , Filter ) ;
BuildProducts . Add ( ZipFileName ) ;
2015-04-01 08:35:36 -04:00
}
}
2014-08-22 13:39:55 -04:00
public override UE4Build . BuildAgenda GetAgenda ( GUBP bp )
{
if ( ! bp . ActivePlatforms . Contains ( TargetPlatform ) )
{
throw new AutomationException ( "{0} is not a supported platform for {1}" , TargetPlatform . ToString ( ) , GetFullName ( ) ) ;
}
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-03-14 14:13:41 -04:00
2015-03-30 15:01:38 -04:00
string Args = "-nobuilduht -skipactionhistory -CopyAppBundleBackToDevice" ;
2015-02-16 10:51:24 -05:00
2015-03-21 15:21:14 -04:00
if ( Precompiled )
{
2015-03-27 09:13:06 -04:00
Args + = " -precompile" ;
2015-03-30 09:21:51 -04:00
// MSVC doesn't provide a way to strip symbols from static libraries - you have to use PDBs, but that causes random OOM
// exceptions with the /FS arg because mspdbsrv is 32-bit. Just disable compiler debug info manually for now.
if ( TargetPlatform = = UnrealTargetPlatform . Win32 | | TargetPlatform = = UnrealTargetPlatform . Win64 )
{
Args + = " -nodebuginfo" ;
}
2015-03-21 15:21:14 -04:00
}
if ( WithXp )
{
Args + = " -winxp" ;
}
2014-08-22 13:39:55 -04:00
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( GameProj . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = GameProj . Properties . Targets [ Kind ] ;
2015-01-28 08:26:51 -05:00
var AllowXp = Target . Rules . GUBP_BuildWindowsXPMonolithics ( ) ;
if ( ! WithXp | | ( AllowXp & & WithXp ) )
{
2015-03-21 12:44:14 -04:00
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
var AdditionalPlatforms = Target . Rules . GUBP_GetBuildOnlyPlatforms_MonolithicOnly ( HostPlatform ) ;
var AllPlatforms = Platforms . Union ( AdditionalPlatforms ) ;
if ( AllPlatforms . Contains ( TargetPlatform ) & & Target . Rules . SupportsPlatform ( TargetPlatform ) )
{
2015-03-21 15:21:14 -04:00
List < UnrealTargetConfiguration > Configs ;
if ( Precompiled )
{
Configs = Target . Rules . GUBP_GetConfigsForPrecompiledBuilds_MonolithicOnly ( HostPlatform , TargetPlatform ) ;
}
else
{
2015-04-16 11:55:26 -04:00
Configs = Target . Rules . GUBP_GetConfigs_MonolithicOnly ( HostPlatform , TargetPlatform ) . Except ( Target . Rules . GUBP_GetConfigsForPrecompiledBuilds_MonolithicOnly ( HostPlatform , TargetPlatform ) ) . ToList ( ) ;
2015-03-21 15:21:14 -04:00
}
2015-03-21 12:44:14 -04:00
foreach ( var Config in Configs )
{
2015-03-21 15:21:14 -04:00
if ( GameProj . GameName = = bp . Branch . BaseEngineProject . GameName )
{
Agenda . AddTargets ( new string [ ] { Target . TargetName } , TargetPlatform , Config , InAddArgs : Args ) ;
}
else
{
Agenda . AddTargets ( new string [ ] { Target . TargetName } , TargetPlatform , Config , GameProj . FilePath , InAddArgs : Args ) ;
}
}
}
}
}
2015-02-10 14:58:32 -05:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
return Agenda ;
}
2015-04-01 08:35:36 -04:00
2015-04-20 13:43:49 -04:00
public static string StaticGetArchivedHeadersPath ( UnrealTargetPlatform HostPlatform , BranchInfo . BranchUProject GameProj , UnrealTargetPlatform TargetPlatform )
2015-04-01 08:35:36 -04:00
{
2015-04-20 13:43:49 -04:00
return CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Saved" , "Precompiled" , "Headers-" + StaticGetFullName ( HostPlatform , GameProj , TargetPlatform ) + ".zip" ) ;
}
public static string StaticGetBuildDependenciesPath ( UnrealTargetPlatform HostPlatform , BranchInfo . BranchUProject GameProj , UnrealTargetPlatform TargetPlatform )
{
return CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Saved" , "Precompiled" , "BuildDependencies-" + StaticGetFullName ( HostPlatform , GameProj , TargetPlatform ) + ".xml" ) ;
2015-04-01 08:35:36 -04:00
}
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class SuccessNode : GUBPNode
{
public SuccessNode ( )
{
}
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
public override bool SendSuccessEmail ( )
{
return true ;
}
}
public class GeneralSuccessNode : GUBP . SuccessNode
{
string MyName ;
public GeneralSuccessNode ( string InMyName )
{
MyName = InMyName ;
}
public static string StaticGetFullName ( string InMyName )
{
return InMyName + "_Success" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( MyName ) ;
}
}
public class AggregateNode : GUBPNode
{
public AggregateNode ( )
{
}
public override bool RunInEC ( )
{
return false ;
2014-11-03 11:46:48 -05:00
}
2014-08-22 13:39:55 -04:00
public override bool IsAggregate ( )
{
return true ;
}
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
}
public override void DoFakeBuild ( GUBP bp ) // this is used to more rapidly test a build system, it does nothing but save a record of success as a build product
{
BuildProducts = new List < string > ( ) ;
}
}
public class HostPlatformAggregateNode : AggregateNode
{
protected UnrealTargetPlatform HostPlatform ;
public HostPlatformAggregateNode ( UnrealTargetPlatform InHostPlatform )
{
HostPlatform = InHostPlatform ;
}
public static string StaticGetHostPlatformSuffix ( UnrealTargetPlatform InHostPlatform )
{
return HostPlatformNode . StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public virtual string GetHostPlatformSuffix ( )
{
return StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
public UnrealTargetPlatform GetAltHostPlatform ( )
{
return GUBP . GetAltHostPlatform ( HostPlatform ) ;
}
}
public class EditorAndToolsNode : HostPlatformAggregateNode
{
public EditorAndToolsNode ( GUBP bp , UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform )
{
AddDependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
AddDependency ( ToolsNode . StaticGetFullName ( HostPlatform ) ) ;
AddDependency ( InternalToolsNode . StaticGetFullName ( HostPlatform ) ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "BaseEditorAndTools" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class AggregatePromotableNode : AggregateNode
{
protected List < UnrealTargetPlatform > HostPlatforms ;
2014-11-03 11:46:48 -05:00
string PromotionLabelPrefix ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public AggregatePromotableNode ( List < UnrealTargetPlatform > InHostPlatforms , string InPromotionLabelPrefix )
{
2015-05-05 11:24:13 -04:00
HostPlatforms = InHostPlatforms ;
2014-08-22 13:39:55 -04:00
PromotionLabelPrefix = InPromotionLabelPrefix ;
}
public static string StaticGetFullName ( string InPromotionLabelPrefix )
{
return InPromotionLabelPrefix + "_Promotable_Aggregate" ;
}
2014-11-03 11:46:48 -05:00
public override bool IsPromotableAggregate ( )
{
return true ;
}
2014-08-22 13:39:55 -04:00
public override string GetFullName ( )
{
return StaticGetFullName ( PromotionLabelPrefix ) ;
}
}
2014-03-14 14:13:41 -04:00
2015-02-10 14:58:32 -05:00
public class SharedCookAggregateNode : AggregateNode
{
public SharedCookAggregateNode ( GUBP bp , List < UnrealTargetPlatform > InHostPlatforms , Dictionary < string , List < UnrealTargetPlatform > > NonCodeProjectNames , Dictionary < string , List < TargetRules . GUBPFormalBuild > > NonCodeFormalBuilds )
{
foreach ( var HostPlatform in InHostPlatforms )
{
{
var Options = bp . Branch . BaseEngineProject . Options ( HostPlatform ) ;
if ( Options . bIsPromotable & & ! Options . bSeparateGamePromotion )
{
var Kind = TargetRules . TargetType . Game ;
if ( bp . Branch . BaseEngineProject . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = bp . Branch . BaseEngineProject . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
foreach ( var Plat in Platforms )
{
if ( bNoIOSOnPC & & Plat = = UnrealTargetPlatform . IOS & & HostPlatform = = UnrealTargetPlatform . Win64 )
{
continue ;
}
if ( bp . ActivePlatforms . Contains ( Plat ) )
{
string CookedPlatform = Platform . Platforms [ Plat ] . GetCookPlatform ( Kind = = TargetRules . TargetType . Server , Kind = = TargetRules . TargetType . Client , "" ) ;
foreach ( var NonCodeProject in bp . Branch . NonCodeProjects )
{
if ( ! NonCodeProjectNames . ContainsKey ( NonCodeProject . GameName ) | | ! NonCodeProjectNames [ NonCodeProject . GameName ] . Contains ( Plat ) )
{
continue ;
}
if ( NonCodeFormalBuilds . ContainsKey ( NonCodeProject . GameName ) )
{
var PlatList = NonCodeFormalBuilds [ NonCodeProject . GameName ] ;
foreach ( var PlatPair in PlatList )
{
if ( PlatPair . TargetPlatform = = Plat )
{
AddCompletedDependency ( CookNode . StaticGetFullName ( HostPlatform , NonCodeProject , CookedPlatform ) ) ;
}
}
}
}
}
}
}
}
}
foreach ( var CodeProj in bp . Branch . CodeProjects )
{
var Options = CodeProj . Options ( HostPlatform ) ;
if ( ! Options . bSeparateGamePromotion )
{
if ( Options . bIsPromotable )
{
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( CodeProj . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = CodeProj . Properties . Targets [ Kind ] ;
var Platforms = new List < UnrealTargetPlatform > ( ) ;
var PossPlats = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
var FormalBuilds = Target . Rules . GUBP_GetConfigsForFormalBuilds_MonolithicOnly ( HostPlatform ) ;
foreach ( var FormalBuild in FormalBuilds )
{
var Platform = FormalBuild . TargetPlatform ;
if ( ! Platforms . Contains ( Platform ) & & PossPlats . Contains ( Platform ) )
{
Platforms . Add ( Platform ) ;
}
}
foreach ( var Plat in Platforms )
{
if ( bNoIOSOnPC & & Plat = = UnrealTargetPlatform . IOS & & HostPlatform = = UnrealTargetPlatform . Win64 )
{
continue ;
}
if ( bp . ActivePlatforms . Contains ( Plat ) )
{
string CookedPlatform = Platform . Platforms [ Plat ] . GetCookPlatform ( Kind = = TargetRules . TargetType . Server , Kind = = TargetRules . TargetType . Client , "" ) ;
AddCompletedDependency ( CookNode . StaticGetFullName ( HostPlatform , CodeProj , CookedPlatform ) ) ;
}
}
}
}
}
}
}
}
}
public static string StaticGetFullName ( )
{
return "SharedCookAggregate" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
}
2014-08-22 13:39:55 -04:00
public class GameAggregatePromotableNode : AggregatePromotableNode
{
2014-11-03 11:46:48 -05:00
BranchInfo . BranchUProject GameProj ;
2014-03-14 14:13:41 -04:00
2014-11-03 11:46:48 -05:00
public GameAggregatePromotableNode ( GUBP bp , List < UnrealTargetPlatform > InHostPlatforms , BranchInfo . BranchUProject InGameProj , bool IsSeparate )
2014-08-22 13:39:55 -04:00
: base ( InHostPlatforms , InGameProj . GameName )
{
GameProj = InGameProj ;
2014-11-03 11:46:48 -05:00
2014-08-22 13:39:55 -04:00
foreach ( var HostPlatform in HostPlatforms )
{
2015-05-05 11:24:13 -04:00
AddDependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
if ( ! bp . BranchOptions . PromotablesWithoutTools . Contains ( GameProj . GameName ) )
{
AddDependency ( ToolsNode . StaticGetFullName ( HostPlatform ) ) ;
AddDependency ( InternalToolsNode . StaticGetFullName ( HostPlatform ) ) ;
}
2014-08-22 13:39:55 -04:00
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
AddDependency ( EditorGameNode . StaticGetFullName ( HostPlatform , GameProj ) ) ;
2014-11-03 11:46:48 -05:00
}
2014-08-22 13:39:55 -04:00
// add all of the platforms I use
{
var Platforms = bp . GetMonolithicPlatformsForUProject ( HostPlatform , InGameProj , false ) ;
if ( bp . bOrthogonalizeEditorPlatforms )
{
foreach ( var Plat in Platforms )
{
AddDependency ( EditorPlatformNode . StaticGetFullName ( HostPlatform , Plat ) ) ;
}
}
}
{
2015-04-16 13:30:21 -04:00
if ( ! GameProj . Options ( HostPlatform ) . bPromoteEditorOnly )
2014-08-22 13:39:55 -04:00
{
2015-04-16 13:30:21 -04:00
var Platforms = bp . GetMonolithicPlatformsForUProject ( HostPlatform , InGameProj , true ) ;
foreach ( var Plat in Platforms )
{
AddDependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , GameProj , Plat ) ) ;
if ( Plat = = UnrealTargetPlatform . Win32 & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Game ) )
{
if ( GameProj . Properties . Targets [ TargetRules . TargetType . Game ] . Rules . GUBP_BuildWindowsXPMonolithics ( ) )
{
AddDependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , GameProj , Plat , true ) ) ;
}
}
}
}
2015-03-21 15:21:14 -04:00
}
}
2015-02-10 14:58:32 -05:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( BranchInfo . BranchUProject InGameProj )
{
return AggregatePromotableNode . StaticGetFullName ( InGameProj . GameName ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
2014-11-03 11:46:48 -05:00
public override bool IsSeparatePromotable ( )
{
bool IsSeparate = false ;
foreach ( UnrealTargetPlatform HostPlatform in HostPlatforms )
{
if ( GameProj . Options ( HostPlatform ) . bSeparateGamePromotion )
{
IsSeparate = true ;
}
}
return IsSeparate ;
}
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class SharedAggregatePromotableNode : AggregatePromotableNode
{
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public SharedAggregatePromotableNode ( GUBP bp , List < UnrealTargetPlatform > InHostPlatforms )
: base ( InHostPlatforms , "Shared" )
{
foreach ( var HostPlatform in HostPlatforms )
{
2015-05-05 11:24:13 -04:00
AddDependency ( EditorAndToolsNode . StaticGetFullName ( HostPlatform ) ) ;
2014-08-22 13:39:55 -04:00
{
var Options = bp . Branch . BaseEngineProject . Options ( HostPlatform ) ;
if ( Options . bIsPromotable & & ! Options . bSeparateGamePromotion )
{
AddDependency ( GameAggregatePromotableNode . StaticGetFullName ( bp . Branch . BaseEngineProject ) ) ;
}
}
foreach ( var CodeProj in bp . Branch . CodeProjects )
{
var Options = CodeProj . Options ( HostPlatform ) ;
if ( ! Options . bSeparateGamePromotion )
{
if ( Options . bIsPromotable )
{
AddDependency ( GameAggregatePromotableNode . StaticGetFullName ( CodeProj ) ) ;
}
else if ( Options . bTestWithShared )
{
2015-03-03 08:42:05 -05:00
if ( ! Options . bIsNonCode )
{
2015-03-04 08:31:40 -05:00
AddDependency ( EditorGameNode . StaticGetFullName ( HostPlatform , CodeProj ) ) ; // if we are just testing, we will still include the editor stuff
}
2014-08-22 13:39:55 -04:00
}
}
}
2015-04-03 08:25:54 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Win64 & & bp . ActivePlatforms . Contains ( UnrealTargetPlatform . Linux ) )
{
AddDependency ( RootEditorCrossCompileLinuxNode . StaticGetFullName ( ) ) ;
AddDependency ( ToolsCrossCompileNode . StaticGetFullName ( HostPlatform ) ) ;
}
2014-08-22 13:39:55 -04:00
}
2015-05-16 17:45:08 -04:00
if ( ! bp . BranchOptions . bNoInstalledEngine )
{
AddDependency ( MakeFeaturePacksNode . StaticGetFullName ( MakeFeaturePacksNode . GetDefaultBuildPlatform ( bp ) ) ) ;
}
2014-08-22 13:39:55 -04:00
}
2014-11-03 11:46:48 -05:00
public override bool IsSeparatePromotable ( )
{
return true ;
}
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( )
{
return AggregatePromotableNode . StaticGetFullName ( "Shared" ) ;
}
}
2014-03-14 14:13:41 -04:00
2015-02-10 14:58:32 -05:00
2014-08-22 13:39:55 -04:00
public class WaitForUserInput : GUBPNode
{
protected bool bTriggerWasTriggered ;
public WaitForUserInput ( )
{
bTriggerWasTriggered = false ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
public override bool TriggerNode ( )
{
return true ;
}
public override void SetAsExplicitTrigger ( )
{
bTriggerWasTriggered = true ;
}
public override bool IsSticky ( )
{
return bTriggerWasTriggered ;
}
public virtual string GetTriggerStateName ( )
{
return "GenericTrigger" ;
}
public virtual string GetTriggerDescText ( )
{
return "GenericTrigger no description text available" ;
}
public virtual string GetTriggerActionText ( )
{
return "GenericTrigger no action text available" ;
}
public virtual bool TriggerRequiresRecursiveWorkflow ( )
{
return true ;
}
public override string ECProcedure ( )
{
if ( bTriggerWasTriggered )
{
return base . ECProcedure ( ) ; // after this user hits the trigger, we want to run this as an ordinary node
}
if ( TriggerRequiresRecursiveWorkflow ( ) )
{
return String . Format ( "GUBP_UAT_Trigger" ) ; //here we run a recursive workflow to wait for the trigger
}
return String . Format ( "GUBP_Hardcoded_Trigger" ) ; //here we advance the state in the hardcoded workflow so folks can approve
}
public override string ECProcedureParams ( )
{
var Result = base . ECProcedureParams ( ) ;
if ( ! bTriggerWasTriggered )
{
2014-09-03 10:12:50 -04:00
Result + = String . Format ( ", {{actualParameterName => 'TriggerState', value => '{0}'}}, {{actualParameterName => 'ActionText', value =>\"{1}\"}}, {{actualParameterName => 'DescText', value =>\"{2}\"}}" , GetTriggerStateName ( ) , GetTriggerActionText ( ) , GetTriggerDescText ( ) ) ;
//Result += String.Format(" --actualParameter TriggerState={0} --actualParameter ActionText=\"{1}\" --actualParameter DescText=\"{2}\"", GetTriggerStateName(), GetTriggerActionText(), GetTriggerDescText());
2014-08-22 13:39:55 -04:00
}
return Result ;
}
public override int TimeoutInMinutes ( )
{
return 0 ;
}
}
2014-03-14 14:13:41 -04:00
2015-02-10 14:58:32 -05:00
public class WaitForFormalUserInput : WaitForUserInput
{
public WaitForFormalUserInput ( GUBP bp )
{
AddDependency ( SharedCookAggregateNode . StaticGetFullName ( ) ) ;
AddCompletedDependency ( SharedCookAggregateNode . StaticGetFullName ( ) ) ;
}
public static string StaticGetFullName ( )
{
return "Shared_WaitToMakeBuilds" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
}
2014-08-22 13:39:55 -04:00
public class WaitForPromotionUserInput : WaitForUserInput
{
string PromotionLabelPrefix ;
string PromotionLabelSuffix ;
protected bool bLabelPromoted ; // true if this is the promoted version
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public WaitForPromotionUserInput ( string InPromotionLabelPrefix , string InPromotionLabelSuffix , bool bInLabelPromoted )
{
PromotionLabelPrefix = InPromotionLabelPrefix ;
PromotionLabelSuffix = InPromotionLabelSuffix ;
bLabelPromoted = bInLabelPromoted ;
if ( bLabelPromoted )
{
AddDependency ( LabelPromotableNode . StaticGetFullName ( PromotionLabelPrefix , false ) ) ;
}
else
{
AddDependency ( AggregatePromotableNode . StaticGetFullName ( PromotionLabelPrefix ) ) ;
}
}
public static string StaticGetFullName ( string InPromotionLabelPrefix , string InPromotionLabelSuffix , bool bInLabelPromoted )
{
return InPromotionLabelPrefix + ( bInLabelPromoted ? "_WaitForPromotion" : "_WaitForPromotable" ) + InPromotionLabelSuffix ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( PromotionLabelPrefix , PromotionLabelSuffix , bLabelPromoted ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class WaitForGamePromotionUserInput : WaitForPromotionUserInput
{
BranchInfo . BranchUProject GameProj ;
bool bCustomWorkflow ;
public WaitForGamePromotionUserInput ( GUBP bp , BranchInfo . BranchUProject InGameProj , bool bInLabelPromoted )
: base ( InGameProj . GameName , "" , bInLabelPromoted )
{
GameProj = InGameProj ;
var Options = InGameProj . Options ( UnrealTargetPlatform . Win64 ) ;
bCustomWorkflow = Options . bCustomWorkflowForPromotion ;
}
public static string StaticGetFullName ( BranchInfo . BranchUProject InGameProj , bool bInLabelPromoted )
{
return WaitForPromotionUserInput . StaticGetFullName ( InGameProj . GameName , "" , bInLabelPromoted ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override string GetTriggerDescText ( )
{
if ( bLabelPromoted )
{
return GameProj . GameName + " is ready for promotion." ;
}
return GameProj . GameName + " is ready to make a promotable label and begin testing." ;
}
public override string GetTriggerActionText ( )
{
if ( bLabelPromoted )
{
return "Promote " + GameProj . GameName + "." ;
}
return "Make a promotable label for " + GameProj . GameName + " and begin testing." ;
}
public override string GetTriggerStateName ( )
{
if ( bCustomWorkflow )
{
return GetFullName ( ) ;
}
return base . GetTriggerStateName ( ) ;
}
public override bool TriggerRequiresRecursiveWorkflow ( )
{
if ( bCustomWorkflow )
{
return ! bLabelPromoted ; // the promotable starts the hardcoded chain
}
return base . TriggerRequiresRecursiveWorkflow ( ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class WaitForSharedPromotionUserInput : WaitForPromotionUserInput
{
public WaitForSharedPromotionUserInput ( GUBP bp , bool bInLabelPromoted )
: base ( "Shared" , IsMainBranch ( ) , bInLabelPromoted )
{
}
public override string GetTriggerDescText ( )
{
if ( bLabelPromoted )
{
return "The shared promotable is ready for promotion." ;
}
return "The shared promotable is ready to make a promotable label." ;
}
public override string GetTriggerActionText ( )
{
if ( bLabelPromoted )
{
return "Promote the shared promotable." ;
}
return "Make the shared promotable label." ;
}
public static string StaticGetFullName ( bool bInLabelPromoted )
{
return WaitForPromotionUserInput . StaticGetFullName ( "Shared" , IsMainBranch ( ) , bInLabelPromoted ) ;
}
public static string IsMainBranch ( )
{
string isMain = "" ;
if ( P4Enabled )
{
string CurrentBranch = P4Env . BuildRootP4 ;
if ( CurrentBranch = = "//depot/UE4" )
{
isMain = "_WithNightlys" ;
}
}
return isMain ;
}
public override string GetTriggerStateName ( )
{
return GetFullName ( ) ;
}
public override bool TriggerRequiresRecursiveWorkflow ( )
{
return ! bLabelPromoted ;
}
2014-12-17 11:37:40 -05:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class LabelPromotableNode : GUBPNode
{
string PromotionLabelPrefix ;
protected bool bLabelPromoted ; // true if this is the promoted version
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public LabelPromotableNode ( string InPromotionLabelPrefix , string InPromotionLabelSuffix , bool bInLabelPromoted )
{
PromotionLabelPrefix = InPromotionLabelPrefix ;
bLabelPromoted = bInLabelPromoted ;
AddDependency ( WaitForPromotionUserInput . StaticGetFullName ( PromotionLabelPrefix , InPromotionLabelSuffix , bLabelPromoted ) ) ;
}
string LabelName ( bool bLocalLabelPromoted )
{
string LabelPrefix = PromotionLabelPrefix ;
string CompleteLabelPrefix = ( bLocalLabelPromoted ? "Promoted-" : "Promotable-" ) + LabelPrefix ;
if ( LabelPrefix = = "Shared" & & bLocalLabelPromoted )
{
// shared promotion has a shorter name
CompleteLabelPrefix = "Promoted" ;
}
if ( LabelPrefix = = "Shared" & & ! bLocalLabelPromoted )
{
//shared promotable has a shorter name
CompleteLabelPrefix = "Promotable" ;
}
if ( GUBP . bPreflightBuild )
{
CompleteLabelPrefix = CompleteLabelPrefix + PreflightMangleSuffix ;
}
return CompleteLabelPrefix ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override bool IsSticky ( )
{
return true ;
}
public override bool SendSuccessEmail ( )
{
return true ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( P4Enabled )
{
if ( AllDependencyBuildProducts . Count = = 0 )
{
throw new AutomationException ( "{0} has no build products" , GetFullName ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( bLabelPromoted )
{
2014-04-02 18:09:23 -04:00
P4 . MakeDownstreamLabelFromLabel ( P4Env , LabelName ( true ) , LabelName ( false ) ) ;
2014-08-22 13:39:55 -04:00
}
else
{
2014-04-02 18:09:23 -04:00
int WorkingCL = P4 . CreateChange ( P4Env . Client , String . Format ( "GUBP Node {0} built from changelist {1}" , GetFullName ( ) , bp . CL ) ) ;
2014-08-22 13:39:55 -04:00
Log ( "Build from {0} Working in {1}" , bp . CL , WorkingCL ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var ProductsToSubmit = new List < String > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Product in AllDependencyBuildProducts )
{
// hacks to keep certain things out of P4
if (
! Product . EndsWith ( "version.h" , StringComparison . InvariantCultureIgnoreCase ) & &
! Product . EndsWith ( "version.cpp" , StringComparison . InvariantCultureIgnoreCase ) & &
2014-03-14 14:13:41 -04:00
! Product . Replace ( '\\' , '/' ) . EndsWith ( "DotNetCommon/MetaData.cs" , StringComparison . InvariantCultureIgnoreCase ) & &
2015-03-21 10:43:14 -04:00
! Product . EndsWith ( "_Success.log" , StringComparison . InvariantCultureIgnoreCase ) & &
2015-03-21 15:21:14 -04:00
! Product . Replace ( '\\' , '/' ) . Contains ( "/Intermediate/" ) & &
2015-04-08 15:05:30 -04:00
! Product . Replace ( '\\' , '/' ) . Contains ( "/Engine/Saved/" ) & &
2015-04-10 13:56:50 -04:00
! Product . Replace ( '\\' , '/' ) . Contains ( "/DerivedDataCache/" ) & &
2015-03-21 15:21:14 -04:00
! Product . EndsWith ( ".lib" ) & &
! Product . EndsWith ( ".a" ) & &
! Product . EndsWith ( ".bc" )
2014-08-22 13:39:55 -04:00
)
{
ProductsToSubmit . Add ( Product ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// Open files for add or edit
UE4Build . AddBuildProductsToChangelist ( WorkingCL , ProductsToSubmit ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// Check everything in!
int SubmittedCL ;
2014-04-02 18:09:23 -04:00
P4 . Submit ( WorkingCL , out SubmittedCL , true , true ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// Label it
2014-04-02 18:09:23 -04:00
P4 . MakeDownstreamLabel ( P4Env , LabelName ( false ) , null ) ;
2014-08-22 13:39:55 -04:00
}
}
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
public static string StaticGetFullName ( string InPromotionLabelPrefix , bool bInLabelPromoted )
{
return InPromotionLabelPrefix + ( bInLabelPromoted ? "_LabelPromoted" : "_LabelPromotable" ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( PromotionLabelPrefix , bLabelPromoted ) ;
}
}
2014-05-01 07:33:06 -04:00
2014-08-22 13:39:55 -04:00
public class GameLabelPromotableNode : LabelPromotableNode
{
BranchInfo . BranchUProject GameProj ;
public GameLabelPromotableNode ( GUBP bp , BranchInfo . BranchUProject InGameProj , bool bInLabelPromoted )
: base ( InGameProj . GameName , "" , bInLabelPromoted )
{
GameProj = InGameProj ;
}
2014-05-01 07:33:06 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( BranchInfo . BranchUProject InGameProj , bool bInLabelPromoted )
{
return LabelPromotableNode . StaticGetFullName ( InGameProj . GameName , bInLabelPromoted ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public class SharedLabelPromotableNode : LabelPromotableNode
{
public SharedLabelPromotableNode ( GUBP bp , bool bInLabelPromoted )
: base ( "Shared" , IsMainBranch ( ) , bInLabelPromoted )
{
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( bool bInLabelPromoted )
{
return LabelPromotableNode . StaticGetFullName ( "Shared" , bInLabelPromoted ) ;
}
public static string IsMainBranch ( )
{
string isMain = "" ;
if ( P4Enabled )
{
string CurrentBranch = P4Env . BuildRootP4 ;
if ( CurrentBranch = = "//depot/UE4" )
{
isMain = "_WithNightlys" ;
}
}
return isMain ;
}
}
2014-08-18 13:29:39 -04:00
2015-04-23 13:26:28 -04:00
public class SharedLabelPromotableSuccessNode : AggregateNode
{
public SharedLabelPromotableSuccessNode ( )
{
AddDependency ( SharedLabelPromotableNode . StaticGetFullName ( false ) ) ;
}
public static string StaticGetFullName ( )
{
return SharedLabelPromotableNode . StaticGetFullName ( false ) + "Aggregate" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
}
2014-08-22 13:39:55 -04:00
public class WaitForTestShared : AggregateNode
{
public WaitForTestShared ( GUBP bp )
{
}
public static string StaticGetFullName ( )
{
return "Shared_TestingAggregate" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 5 ;
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public class CookNode : HostPlatformNode
{
BranchInfo . BranchUProject GameProj ;
UnrealTargetPlatform TargetPlatform ;
string CookPlatform ;
bool bIsMassive ;
2014-10-08 10:49:02 -04:00
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public CookNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InTargetPlatform , string InCookPlatform )
: base ( InHostPlatform )
{
GameProj = InGameProj ;
TargetPlatform = InTargetPlatform ;
CookPlatform = InCookPlatform ;
bIsMassive = false ;
AddDependency ( EditorAndToolsNode . StaticGetFullName ( HostPlatform ) ) ;
if ( bp . bOrthogonalizeEditorPlatforms )
{
if ( TargetPlatform ! = HostPlatform & & TargetPlatform ! = GUBP . GetAltHostPlatform ( HostPlatform ) )
{
AddDependency ( EditorPlatformNode . StaticGetFullName ( HostPlatform , TargetPlatform ) ) ;
}
2014-10-08 10:49:02 -04:00
}
2014-08-22 13:39:55 -04:00
bool bIsShared = false ;
// is this the "base game" or a non code project?
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
var Options = InGameProj . Options ( HostPlatform ) ;
2014-10-08 10:49:02 -04:00
bIsMassive = Options . bIsMassive ;
2014-08-22 13:39:55 -04:00
AddDependency ( EditorGameNode . StaticGetFullName ( HostPlatform , GameProj ) ) ;
// add an arc to prevent cooks from running until promotable is labeled
if ( Options . bIsPromotable )
{
if ( ! Options . bSeparateGamePromotion )
{
bIsShared = true ;
}
}
else if ( Options . bTestWithShared )
{
bIsShared = true ;
}
2015-05-16 18:58:05 -04:00
if ( ! bp . BranchOptions . bNoMonolithicDependenciesForCooks )
{
AddPseudodependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , GameProj , TargetPlatform ) ) ;
}
2014-08-22 13:39:55 -04:00
}
else
{
2014-10-08 10:49:02 -04:00
bIsShared = true ;
2014-08-22 13:39:55 -04:00
AddPseudodependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , TargetPlatform ) ) ;
}
if ( bIsShared )
{
// add an arc to prevent cooks from running until promotable is labeled
AddPseudodependency ( WaitForTestShared . StaticGetFullName ( ) ) ;
AgentSharingGroup = "SharedCooks" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// If the cook fails for the base engine, don't bother trying
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & bp . HasNode ( CookNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , CookPlatform ) ) )
{
AddPseudodependency ( CookNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , CookPlatform ) ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// If the base cook platform fails, don't bother trying other ones
string BaseCookedPlatform = Platform . Platforms [ HostPlatform ] . GetCookPlatform ( false , false , "" ) ;
if ( InGameProj . GameName = = bp . Branch . BaseEngineProject . GameName & & CookPlatform ! = BaseCookedPlatform & &
bp . HasNode ( CookNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , BaseCookedPlatform ) ) )
{
AddPseudodependency ( CookNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , BaseCookedPlatform ) ) ;
}
2014-10-08 10:49:02 -04:00
}
2014-08-22 13:39:55 -04:00
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , string InCookPlatform )
{
return InGameProj . GameName + "_" + InCookPlatform + "_Cook" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , GameProj , CookPlatform ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
2015-02-10 16:03:55 -05:00
return base . CISFrequencyQuantumShift ( bp ) + 4 + ( bIsMassive ? 1 : 0 ) ;
2014-08-22 13:39:55 -04:00
}
public override float Priority ( )
{
return 10.0f ;
}
public override int AgentMemoryRequirement ( GUBP bp )
{
return bIsMassive ? 32 : 0 ;
}
public override int TimeoutInMinutes ( )
{
return bIsMassive ? 240 : base . TimeoutInMinutes ( ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public override string RootIfAnyForTempStorage ( )
{
return CombinePaths ( Path . GetDirectoryName ( GameProj . FilePath ) , "Saved" , "Cooked" , CookPlatform ) ;
}
public override void DoBuild ( GUBP bp )
{
if ( HostPlatform = = UnrealTargetPlatform . Mac )
{
// not sure if we need something here or if the cook commandlet will automatically convert the exe name
}
2015-05-08 17:45:24 -04:00
var StartCook = DateTime . Now . ToString ( ) ;
2014-10-27 19:33:51 -04:00
CommandUtils . CookCommandlet ( GameProj . FilePath , "UE4Editor-Cmd.exe" , null , null , null , null , CookPlatform ) ;
2015-05-08 17:45:24 -04:00
var FinishCook = DateTime . Now . ToString ( ) ;
PrintCSVFile ( String . Format ( "UAT,Cook.{0}.{1},{2},{3}" , GameProj . GameName , CookPlatform , StartCook , FinishCook ) ) ;
2014-08-22 13:39:55 -04:00
var CookedPath = RootIfAnyForTempStorage ( ) ;
var CookedFiles = CommandUtils . FindFiles ( "*" , true , CookedPath ) ;
if ( CookedFiles . GetLength ( 0 ) < 1 )
{
throw new AutomationException ( "CookedPath {1} did not produce any files." , CookedPath ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
BuildProducts = new List < string > ( ) ;
foreach ( var CookedFile in CookedFiles )
{
AddBuildProduct ( CookedFile ) ;
}
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public class DDCNode : HostPlatformNode
{
BranchInfo . BranchUProject GameProj ;
UnrealTargetPlatform TargetPlatform ;
string CookPlatform ;
bool bIsMassive ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public DDCNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InTargetPlatform , string InCookPlatform )
: base ( InHostPlatform )
{
GameProj = InGameProj ;
TargetPlatform = InTargetPlatform ;
CookPlatform = InCookPlatform ;
bIsMassive = false ;
AddDependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
if ( bp . bOrthogonalizeEditorPlatforms )
{
if ( TargetPlatform ! = HostPlatform & & TargetPlatform ! = GUBP . GetAltHostPlatform ( HostPlatform ) )
{
AddDependency ( EditorPlatformNode . StaticGetFullName ( HostPlatform , TargetPlatform ) ) ;
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
bool bIsShared = false ;
// is this the "base game" or a non code project?
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
var Options = InGameProj . Options ( HostPlatform ) ;
bIsMassive = Options . bIsMassive ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
AddDependency ( EditorGameNode . StaticGetFullName ( HostPlatform , GameProj ) ) ;
// add an arc to prevent DDCNode from running until promotable is labeled
if ( Options . bIsPromotable )
{
if ( Options . bSeparateGamePromotion )
{
// AddPseudodependency(GameLabelPromotableNode.StaticGetFullName(GameProj, false));
}
else
{
bIsShared = true ;
}
}
else if ( Options . bTestWithShared )
{
bIsShared = true ;
}
//AddPseudodependency(GamePlatformMonolithicsNode.StaticGetFullName(HostPlatform, GameProj, TargetPlatform));
}
else
{
bIsShared = true ;
//AddPseudodependency(GamePlatformMonolithicsNode.StaticGetFullName(HostPlatform, bp.Branch.BaseEngineProject, TargetPlatform));
}
if ( bIsShared )
{
// add an arc to prevent cooks from running until promotable is labeled
//AddPseudodependency(WaitForTestShared.StaticGetFullName());
//AgentSharingGroup = "SharedCooks" + StaticGetHostPlatformSuffix(HostPlatform);
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// If the cook fails for the base engine, don't bother trying
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & bp . HasNode ( DDCNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , CookPlatform ) ) )
{
//AddPseudodependency(DDCNode.StaticGetFullName(HostPlatform, bp.Branch.BaseEngineProject, CookPlatform));
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// If the base cook platform fails, don't bother trying other ones
string BaseCookedPlatform = Platform . Platforms [ HostPlatform ] . GetCookPlatform ( false , false , "" ) ;
if ( InGameProj . GameName = = bp . Branch . BaseEngineProject . GameName & & CookPlatform ! = BaseCookedPlatform & &
bp . HasNode ( DDCNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , BaseCookedPlatform ) ) )
{
//AddPseudodependency(DDCNode.StaticGetFullName(HostPlatform, bp.Branch.BaseEngineProject, BaseCookedPlatform));
}
}
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , string InCookPlatform )
{
return InGameProj . GameName + "_" + InCookPlatform . Replace ( "+" , "_" ) + "_DDC" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , GameProj , CookPlatform ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override float Priority ( )
{
return base . Priority ( ) + 10.0f ;
}
public override int AgentMemoryRequirement ( GUBP bp )
{
return bIsMassive ? 32 : 0 ;
}
public override int TimeoutInMinutes ( )
{
return bIsMassive ? 240 : base . TimeoutInMinutes ( ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public override void DoBuild ( GUBP bp )
{
if ( HostPlatform = = UnrealTargetPlatform . Mac )
{
// not sure if we need something here or if the cook commandlet will automatically convert the exe name
}
CommandUtils . DDCCommandlet ( GameProj . FilePath , "UE4Editor-Cmd.exe" , null , CookPlatform , "-fill" ) ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
BuildProducts = new List < string > ( ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public class GamePlatformCookedAndCompiledNode : HostPlatformAggregateNode
{
BranchInfo . BranchUProject GameProj ;
UnrealTargetPlatform TargetPlatform ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public GamePlatformCookedAndCompiledNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InTargetPlatform , bool bCodeProject )
: base ( InHostPlatform )
{
GameProj = InGameProj ;
TargetPlatform = InTargetPlatform ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( bCodeProject )
{
if ( GameProj . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = GameProj . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
if ( Platforms . Contains ( TargetPlatform ) & & Target . Rules . SupportsPlatform ( TargetPlatform ) )
{
//@todo how do we get the client target platform?
string CookedPlatform = Platform . Platforms [ TargetPlatform ] . GetCookPlatform ( Kind = = TargetRules . TargetType . Server , Kind = = TargetRules . TargetType . Client , "" ) ;
2014-10-08 10:49:02 -04:00
if ( Target . Rules . GUBP_AlternateCookPlatform ( HostPlatform , CookedPlatform ) ! = "" )
{
CookedPlatform = Target . Rules . GUBP_AlternateCookPlatform ( HostPlatform , CookedPlatform ) ;
}
2014-08-22 13:39:55 -04:00
AddDependency ( CookNode . StaticGetFullName ( HostPlatform , GameProj , CookedPlatform ) ) ;
AddDependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , GameProj , TargetPlatform ) ) ;
2015-01-28 08:26:51 -05:00
if ( Target . Rules . GUBP_BuildWindowsXPMonolithics ( ) )
{
AddDependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , GameProj , TargetPlatform , true ) ) ;
2014-08-22 13:39:55 -04:00
}
}
}
2015-01-28 08:26:51 -05:00
}
2014-08-22 13:39:55 -04:00
else
{
if ( Kind = = TargetRules . TargetType . Game ) //for now, non-code projects don't do client or server.
{
if ( bp . Branch . BaseEngineProject . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = bp . Branch . BaseEngineProject . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
if ( Platforms . Contains ( TargetPlatform ) & & Target . Rules . SupportsPlatform ( TargetPlatform ) )
{
//@todo how do we get the client target platform?
string CookedPlatform = Platform . Platforms [ TargetPlatform ] . GetCookPlatform ( Kind = = TargetRules . TargetType . Server , Kind = = TargetRules . TargetType . Client , "" ) ;
AddDependency ( CookNode . StaticGetFullName ( HostPlatform , GameProj , CookedPlatform ) ) ;
AddDependency ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , TargetPlatform ) ) ;
}
}
}
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// put these in the right agent group, even though they aren't exposed to EC to sort right.
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
var Options = InGameProj . Options ( HostPlatform ) ;
if ( ( Options . bIsPromotable | | Options . bTestWithShared ) & & ! Options . bSeparateGamePromotion )
{
AgentSharingGroup = "SharedCooks" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
}
else
{
AgentSharingGroup = "SharedCooks" + StaticGetHostPlatformSuffix ( HostPlatform ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InTargetPlatform )
{
return InGameProj . GameName + "_" + InTargetPlatform + "_CookedAndCompiled" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , GameProj , TargetPlatform ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
} ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public class FormalBuildNode : HostPlatformNode
{
BranchInfo . BranchUProject GameProj ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
//CAUTION, these are lists, but it isn't clear that lists really work on all platforms, so we stick to one node per build
List < UnrealTargetPlatform > ClientTargetPlatforms ;
List < UnrealTargetPlatform > ServerTargetPlatforms ;
List < UnrealTargetConfiguration > ClientConfigs ;
List < UnrealTargetConfiguration > ServerConfigs ;
bool ClientNotGame ;
2014-09-25 20:38:35 -04:00
bool bIsCode ;
2014-09-03 10:12:50 -04:00
UnrealBuildTool . TargetRules . TargetType GameOrClient ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
public FormalBuildNode ( GUBP bp ,
BranchInfo . BranchUProject InGameProj ,
UnrealTargetPlatform InHostPlatform ,
List < UnrealTargetPlatform > InClientTargetPlatforms = null ,
List < UnrealTargetConfiguration > InClientConfigs = null ,
List < UnrealTargetPlatform > InServerTargetPlatforms = null ,
List < UnrealTargetConfiguration > InServerConfigs = null ,
2014-09-03 10:12:50 -04:00
bool InClientNotGame = false
2014-08-22 13:39:55 -04:00
)
: base ( InHostPlatform )
{
GameProj = InGameProj ;
ClientTargetPlatforms = InClientTargetPlatforms ;
ServerTargetPlatforms = InServerTargetPlatforms ;
ClientConfigs = InClientConfigs ;
ServerConfigs = InServerConfigs ;
2014-09-03 10:12:50 -04:00
ClientNotGame = InClientNotGame ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
GameOrClient = TargetRules . TargetType . Game ;
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
if ( ClientNotGame )
{
GameOrClient = TargetRules . TargetType . Client ;
}
2014-09-25 20:38:35 -04:00
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName & & GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
bIsCode = true ;
}
else
{
bIsCode = false ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// verify we actually built these
var WorkingGameProject = InGameProj ;
if ( ! WorkingGameProject . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
// this is a codeless project, use the base project
WorkingGameProject = bp . Branch . BaseEngineProject ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
var AllTargetPlatforms = new List < UnrealTargetPlatform > ( ) ;
2014-08-18 13:29:39 -04:00
var Options = InGameProj . Options ( HostPlatform ) ;
2015-03-04 08:31:40 -05:00
if ( ! Options . bSeparateGamePromotion & & ! bp . BranchOptions . bMakeFormalBuildWithoutLabelPromotable )
2014-08-18 13:29:39 -04:00
{
2015-02-10 14:58:32 -05:00
AddPseudodependency ( WaitForFormalUserInput . StaticGetFullName ( ) ) ;
2014-08-18 13:29:39 -04:00
}
2014-08-22 13:39:55 -04:00
if ( ClientTargetPlatforms ! = null )
{
if ( ! WorkingGameProject . Properties . Targets . ContainsKey ( GameOrClient ) )
{
throw new AutomationException ( "Can't make a game build for {0} because it doesn't have a {1} target." , WorkingGameProject . GameName , GameOrClient . ToString ( ) ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Plat in ClientTargetPlatforms )
{
if ( ! AllTargetPlatforms . Contains ( Plat ) )
{
AllTargetPlatforms . Add ( Plat ) ;
}
}
if ( ClientConfigs = = null )
{
ClientConfigs = new List < UnrealTargetConfiguration > ( ) { UnrealTargetConfiguration . Development } ;
}
foreach ( var Plat in ClientTargetPlatforms )
{
if ( ! WorkingGameProject . Properties . Targets [ GameOrClient ] . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) . Contains ( Plat ) )
{
throw new AutomationException ( "Can't make a game/client build for {0} because we didn't build platform {1}." , WorkingGameProject . GameName , Plat . ToString ( ) ) ;
}
foreach ( var Config in ClientConfigs )
{
if ( ! WorkingGameProject . Properties . Targets [ GameOrClient ] . Rules . GUBP_GetConfigs_MonolithicOnly ( HostPlatform , Plat ) . Contains ( Config ) )
{
throw new AutomationException ( "Can't make a game/client build for {0} because we didn't build platform {1} config {2}." , WorkingGameProject . GameName , Plat . ToString ( ) , Config . ToString ( ) ) ;
2015-03-13 09:50:42 -04:00
}
2014-08-22 13:39:55 -04:00
}
}
}
if ( ServerTargetPlatforms ! = null )
{
if ( ! WorkingGameProject . Properties . Targets . ContainsKey ( TargetRules . TargetType . Server ) & & ServerTargetPlatforms ! = null )
{
throw new AutomationException ( "Can't make a server build for {0} because it doesn't have a server target." , WorkingGameProject . GameName ) ;
}
foreach ( var Plat in ServerTargetPlatforms )
{
if ( ! AllTargetPlatforms . Contains ( Plat ) )
{
AllTargetPlatforms . Add ( Plat ) ;
}
}
if ( ServerConfigs = = null )
{
ServerConfigs = new List < UnrealTargetConfiguration > ( ) { UnrealTargetConfiguration . Development } ;
}
foreach ( var Plat in ServerTargetPlatforms )
{
if ( ! WorkingGameProject . Properties . Targets [ TargetRules . TargetType . Server ] . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) . Contains ( Plat ) )
{
throw new AutomationException ( "Can't make a server build for {0} because we didn't build platform {1}." , WorkingGameProject . GameName , Plat . ToString ( ) ) ;
}
foreach ( var Config in ServerConfigs )
{
if ( ! WorkingGameProject . Properties . Targets [ TargetRules . TargetType . Server ] . Rules . GUBP_GetConfigs_MonolithicOnly ( HostPlatform , Plat ) . Contains ( Config ) )
{
throw new AutomationException ( "Can't make a server build for {0} because we didn't build platform {1} config {2}." , WorkingGameProject . GameName , Plat . ToString ( ) , Config . ToString ( ) ) ;
}
}
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
// add dependencies for cooked and compiled
foreach ( var Plat in AllTargetPlatforms )
{
2014-09-03 10:12:50 -04:00
AddDependency ( GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , GameProj , Plat ) ) ;
}
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InHostPlatform , List < UnrealTargetPlatform > InClientTargetPlatforms = null , List < UnrealTargetConfiguration > InClientConfigs = null , List < UnrealTargetPlatform > InServerTargetPlatforms = null , List < UnrealTargetConfiguration > InServerConfigs = null , bool InClientNotGame = false )
{
string Infix = "" ;
if ( InClientNotGame )
{
if ( InClientTargetPlatforms ! = null & & InClientTargetPlatforms . Count = = 1 )
{
Infix = "_Client_" + InClientTargetPlatforms [ 0 ] . ToString ( ) ;
}
if ( InClientConfigs ! = null & & InClientConfigs . Count = = 1 )
{
Infix + = "_Client_" + InClientConfigs [ 0 ] . ToString ( ) ;
}
}
else
{
if ( InClientTargetPlatforms ! = null & & InClientTargetPlatforms . Count = = 1 )
{
Infix = "_" + InClientTargetPlatforms [ 0 ] . ToString ( ) ;
}
if ( InClientConfigs ! = null & & InClientConfigs . Count = = 1 )
{
Infix + = "_" + InClientConfigs [ 0 ] . ToString ( ) ;
}
}
if ( InServerTargetPlatforms ! = null & & InServerTargetPlatforms . Count = = 1 )
{
Infix = "_Serv_" + InServerTargetPlatforms [ 0 ] . ToString ( ) ;
}
if ( InServerConfigs ! = null & & InServerConfigs . Count = = 1 )
{
Infix + = "_Serv_" + InServerConfigs [ 0 ] . ToString ( ) ;
}
return InGameProj . GameName + Infix + "_MakeBuild" + HostPlatformNode . StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( GameProj , HostPlatform , ClientTargetPlatforms , ClientConfigs , ServerTargetPlatforms , ServerConfigs , ClientNotGame ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override bool SendSuccessEmail ( )
{
return true ;
}
public override string ECAgentString ( )
{
string Result = base . ECAgentString ( ) ;
2014-11-11 08:24:45 -05:00
if ( ClientTargetPlatforms ! = null )
{
if ( ! ClientNotGame )
{
foreach ( UnrealTargetPlatform Plat in ClientTargetPlatforms )
{
if ( Plat = = UnrealTargetPlatform . XboxOne )
{
Result = MergeSpaceStrings ( Result , Plat . ToString ( ) ) ;
}
}
}
}
2014-08-22 13:39:55 -04:00
return Result ;
}
public override float Priority ( )
{
2014-09-03 10:12:50 -04:00
return base . Priority ( ) + 20.0f ;
2014-08-22 13:39:55 -04:00
}
2014-09-09 13:57:48 -04:00
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 3 ;
}
2014-08-22 13:39:55 -04:00
public static string GetArchiveDirectory ( BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InHostPlatform , List < UnrealTargetPlatform > InClientTargetPlatforms = null , List < UnrealTargetConfiguration > InClientConfigs = null , List < UnrealTargetPlatform > InServerTargetPlatforms = null , List < UnrealTargetConfiguration > InServerConfigs = null , bool InClientNotGame = false )
{
string BaseDir = ResolveSharedBuildDirectory ( InGameProj . GameName ) ;
string NodeName = StaticGetFullName ( InGameProj , InHostPlatform , InClientTargetPlatforms , InClientConfigs , InServerTargetPlatforms , InServerConfigs , InClientNotGame ) ;
string Inner = P4Env . BuildRootEscaped + "-CL-" + P4Env . ChangelistString ;
if ( GUBP . bPreflightBuild )
{
Inner = Inner + PreflightMangleSuffix ;
}
string ArchiveDirectory = CombinePaths ( BaseDir , NodeName , Inner ) ;
return ArchiveDirectory ;
}
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
string ProjectArg = "" ;
if ( ! String . IsNullOrEmpty ( GameProj . FilePath ) )
{
ProjectArg = " -project=\"" + GameProj . FilePath + "\"" ;
}
string Args = String . Format ( "BuildCookRun{0} -SkipBuild -SkipCook -Stage -Pak -Package -NoSubmit" , ProjectArg ) ;
2014-03-14 14:13:41 -04:00
2014-08-08 11:08:16 -04:00
bool bXboxOneTarget = false ;
2014-08-22 13:39:55 -04:00
if ( ClientTargetPlatforms ! = null )
{
bool bFirstClient = true ;
foreach ( var Plat in ClientTargetPlatforms )
{
2014-08-08 11:08:16 -04:00
if ( Plat = = UnrealTargetPlatform . XboxOne )
{
bXboxOneTarget = true ;
}
2014-08-22 13:39:55 -04:00
if ( bFirstClient )
{
bFirstClient = false ;
Args + = String . Format ( " -platform={0}" , Plat . ToString ( ) ) ;
}
else
{
Args + = String . Format ( "+{0}" , Plat . ToString ( ) ) ;
}
2014-09-25 20:38:35 -04:00
if ( bIsCode )
2014-09-25 10:11:15 -04:00
{
2014-09-25 13:32:08 -04:00
var Target = GameProj . Properties . Targets [ TargetRules . TargetType . Game ] ;
if ( ClientNotGame )
{
Target = GameProj . Properties . Targets [ TargetRules . TargetType . Client ] ;
}
if ( Target . Rules . GUBP_AdditionalPackageParameters ( HostPlatform , Plat ) ! = "" )
{
Args + = " " + Target . Rules . GUBP_AdditionalPackageParameters ( HostPlatform , Plat ) ;
}
2014-09-25 10:11:15 -04:00
}
2014-08-22 13:39:55 -04:00
}
bool bFirstClientConfig = true ;
foreach ( var Config in ClientConfigs )
{
if ( bFirstClientConfig )
{
bFirstClientConfig = false ;
Args + = String . Format ( " -clientconfig={0}" , Config . ToString ( ) ) ;
}
else
{
Args + = String . Format ( "+{0}" , Config . ToString ( ) ) ;
}
}
if ( ClientNotGame )
{
2014-09-25 10:11:15 -04:00
Args + = " -client" ;
2014-08-22 13:39:55 -04:00
}
}
else
{
Args + = " -noclient" ;
}
if ( ServerTargetPlatforms ! = null )
{
Args + = " -server" ;
bool bFirstServer = true ;
foreach ( var Plat in ServerTargetPlatforms )
{
2014-08-08 11:08:16 -04:00
if ( Plat = = UnrealTargetPlatform . XboxOne )
{
bXboxOneTarget = true ;
}
if ( bFirstServer )
2014-08-22 13:39:55 -04:00
{
bFirstServer = false ;
Args + = String . Format ( " -serverplatform={0}" , Plat . ToString ( ) ) ;
}
else
{
Args + = String . Format ( "+{0}" , Plat . ToString ( ) ) ;
}
2014-09-25 20:38:35 -04:00
if ( bIsCode )
2014-09-25 10:11:15 -04:00
{
2014-09-25 13:32:08 -04:00
var Target = GameProj . Properties . Targets [ TargetRules . TargetType . Server ] ;
if ( Target . Rules . GUBP_AdditionalPackageParameters ( HostPlatform , Plat ) ! = "" )
{
Args + = " " + Target . Rules . GUBP_AdditionalPackageParameters ( HostPlatform , Plat ) ;
}
2014-09-25 10:11:15 -04:00
}
2014-08-22 13:39:55 -04:00
}
bool bFirstServerConfig = true ;
foreach ( var Config in ServerConfigs )
{
if ( bFirstServerConfig )
{
bFirstServerConfig = false ;
Args + = String . Format ( " -serverconfig={0}" , Config . ToString ( ) ) ;
}
else
{
Args + = String . Format ( "+{0}" , Config . ToString ( ) ) ;
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string FinalArchiveDirectory = "" ;
2014-08-08 11:08:16 -04:00
string IntermediateArchiveDirectory = FinalArchiveDirectory ;
2014-08-22 13:39:55 -04:00
if ( P4Enabled )
{
FinalArchiveDirectory = GetArchiveDirectory ( GameProj , HostPlatform , ClientTargetPlatforms , ClientConfigs , ServerTargetPlatforms , ServerConfigs , ClientNotGame ) ;
2014-08-08 11:08:16 -04:00
IntermediateArchiveDirectory = FinalArchiveDirectory ;
// Xbox One packaging does not function with remote file systems. Use a temp local directory to package and then move files into final location.
if ( bXboxOneTarget )
{
IntermediateArchiveDirectory = Path . Combine ( Path . GetTempPath ( ) , "GUBP.XboxOne" ) ;
if ( DirectoryExists_NoExceptions ( IntermediateArchiveDirectory ) )
{
DeleteDirectory_NoExceptions ( IntermediateArchiveDirectory ) ;
}
CreateDirectory_NoExceptions ( IntermediateArchiveDirectory ) ;
}
CleanFormalBuilds ( FinalArchiveDirectory ) ;
if ( DirectoryExists_NoExceptions ( FinalArchiveDirectory ) )
2014-08-22 13:39:55 -04:00
{
if ( IsBuildMachine )
{
2014-08-08 11:08:16 -04:00
throw new AutomationException ( "Archive directory already exists {0}" , FinalArchiveDirectory ) ;
2014-08-22 13:39:55 -04:00
}
2014-08-08 11:08:16 -04:00
DeleteDirectory_NoExceptions ( FinalArchiveDirectory ) ;
2014-08-22 13:39:55 -04:00
}
2014-08-08 11:08:16 -04:00
Args + = String . Format ( " -Archive -archivedirectory={0}" , CommandUtils . MakePathSafeToUseWithCommandLine ( IntermediateArchiveDirectory ) ) ;
2014-08-22 13:39:55 -04:00
}
2014-09-25 10:11:15 -04:00
2014-08-22 13:39:55 -04:00
string LogFile = CommandUtils . RunUAT ( CommandUtils . CmdEnv , Args ) ;
2014-08-08 11:08:16 -04:00
2014-08-22 13:39:55 -04:00
if ( P4Enabled )
{
2014-08-08 11:08:16 -04:00
if ( ! FinalArchiveDirectory . Equals ( IntermediateArchiveDirectory , StringComparison . InvariantCultureIgnoreCase ) )
{
CopyDirectory_NoExceptions ( IntermediateArchiveDirectory , FinalArchiveDirectory ) ;
DeleteDirectory_NoExceptions ( IntermediateArchiveDirectory ) ;
}
}
2014-08-22 13:39:55 -04:00
SaveRecordOfSuccessAndAddToBuildProducts ( CommandUtils . ReadAllText ( LogFile ) ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class TestNode : HostPlatformNode
{
public TestNode ( UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform )
{
}
public override float Priority ( )
{
return 0.0f ;
}
public virtual void DoTest ( GUBP bp )
{
}
public override void DoBuild ( GUBP bp )
{
BuildProducts = new List < string > ( ) ;
DoTest ( bp ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class FormalBuildTestNode : TestNode
{
BranchInfo . BranchUProject GameProj ;
UnrealTargetPlatform ClientTargetPlatform ;
UnrealTargetConfiguration ClientConfig ;
UnrealBuildTool . TargetRules . TargetType GameOrClient ;
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
public FormalBuildTestNode ( GUBP bp ,
BranchInfo . BranchUProject InGameProj ,
UnrealTargetPlatform InHostPlatform ,
UnrealTargetPlatform InClientTargetPlatform ,
UnrealTargetConfiguration InClientConfig
)
: base ( InHostPlatform )
{
GameProj = InGameProj ;
ClientTargetPlatform = InClientTargetPlatform ;
ClientConfig = InClientConfig ;
GameOrClient = TargetRules . TargetType . Game ;
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
// verify we actually built these
var WorkingGameProject = InGameProj ;
if ( ! WorkingGameProject . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
// this is a codeless project, use the base project
WorkingGameProject = bp . Branch . BaseEngineProject ;
}
if ( ! WorkingGameProject . Properties . Targets . ContainsKey ( GameOrClient ) )
{
throw new AutomationException ( "Can't make a game build for {0} because it doesn't have a {1} target." , WorkingGameProject . GameName , GameOrClient . ToString ( ) ) ;
}
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
if ( ! WorkingGameProject . Properties . Targets [ GameOrClient ] . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) . Contains ( ClientTargetPlatform ) )
{
throw new AutomationException ( "Can't make a game/client build for {0} because we didn't build platform {1}." , WorkingGameProject . GameName , ClientTargetPlatform . ToString ( ) ) ;
}
if ( ! WorkingGameProject . Properties . Targets [ GameOrClient ] . Rules . GUBP_GetConfigs_MonolithicOnly ( HostPlatform , ClientTargetPlatform ) . Contains ( ClientConfig ) )
{
throw new AutomationException ( "Can't make a game/client build for {0} because we didn't build platform {1} config {2}." , WorkingGameProject . GameName , ClientTargetPlatform . ToString ( ) , ClientConfig . ToString ( ) ) ;
}
AddDependency ( FormalBuildNode . StaticGetFullName ( GameProj , HostPlatform , new List < UnrealTargetPlatform > ( ) { ClientTargetPlatform } , InClientConfigs : new List < UnrealTargetConfiguration > ( ) { ClientConfig } , InClientNotGame : GameOrClient = = TargetRules . TargetType . Client ) ) ;
}
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( BranchInfo . BranchUProject InGameProj , UnrealTargetPlatform InHostPlatform , UnrealTargetPlatform InClientTargetPlatform , UnrealTargetConfiguration InClientConfig )
{
string Infix = "_" + InClientTargetPlatform . ToString ( ) ;
Infix + = "_" + InClientConfig . ToString ( ) ;
return InGameProj . GameName + Infix + "_TestBuild" + HostPlatformNode . StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( GameProj , HostPlatform , ClientTargetPlatform , ClientConfig ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override float Priority ( )
{
return base . Priority ( ) - 20.0f ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 3 ;
}
public override void DoTest ( GUBP bp )
{
string ProjectArg = "" ;
if ( ! String . IsNullOrEmpty ( GameProj . FilePath ) )
{
ProjectArg = " -project=\"" + GameProj . FilePath + "\"" ;
}
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
string ArchiveDirectory = FormalBuildNode . GetArchiveDirectory ( GameProj , HostPlatform , new List < UnrealTargetPlatform > ( ) { ClientTargetPlatform } , InClientConfigs : new List < UnrealTargetConfiguration > ( ) { ClientConfig } , InClientNotGame : GameOrClient = = TargetRules . TargetType . Client ) ;
if ( ! DirectoryExists_NoExceptions ( ArchiveDirectory ) )
{
throw new AutomationException ( "Archive directory does not exist {0}, so we can't test the build." , ArchiveDirectory ) ;
}
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
string WorkingCommandline = String . Format ( "TestFormalBuild {0} -Archive -alldevices -archivedirectory={1} -platform={2} -clientconfig={3} -runtimeoutseconds=300" ,
ProjectArg , CommandUtils . MakePathSafeToUseWithCommandLine ( ArchiveDirectory ) , ClientTargetPlatform . ToString ( ) , ClientConfig . ToString ( ) ) ;
2014-06-03 10:37:01 -04:00
2014-08-22 13:39:55 -04:00
if ( WorkingCommandline . Contains ( "-project=\"\"" ) )
{
throw new AutomationException ( "Command line {0} contains -project=\"\" which is doomed to fail" , WorkingCommandline ) ;
}
string LogFile = RunUAT ( CommandUtils . CmdEnv , WorkingCommandline ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( CommandUtils . ReadAllText ( LogFile ) ) ;
}
public override string ECAgentString ( )
{
string Result = base . ECAgentString ( ) ;
if ( ClientTargetPlatform ! = HostPlatform )
{
Result = MergeSpaceStrings ( Result , ClientTargetPlatform . ToString ( ) ) ;
}
return Result ;
}
}
2014-06-03 10:37:01 -04:00
2014-09-22 12:13:56 -04:00
public class NonUnityToolNode : TestNode
{
SingleTargetProperties ProgramTarget ;
public NonUnityToolNode ( UnrealTargetPlatform InHostPlatform , SingleTargetProperties InProgramTarget )
: base ( InHostPlatform )
{
ProgramTarget = InProgramTarget ;
AddPseudodependency ( SingleInternalToolsNode . StaticGetFullName ( HostPlatform , ProgramTarget ) ) ;
AddPseudodependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , SingleTargetProperties InGameProj )
{
return InGameProj . TargetName + "_NonUnityTestCompile" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , ProgramTarget ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
int Result = base . CISFrequencyQuantumShift ( bp ) + 2 ;
if ( HostPlatform = = UnrealTargetPlatform . Mac )
{
Result + = 1 ;
}
return Result ;
}
public override int AgentMemoryRequirement ( GUBP bp )
{
int Result = base . AgentMemoryRequirement ( bp ) ;
if ( HostPlatform = = UnrealTargetPlatform . Mac )
{
Result = 32 ;
}
return Result ;
}
public override void DoTest ( GUBP bp )
{
var Build = new UE4Build ( bp ) ;
var Agenda = new UE4Build . BuildAgenda ( ) ;
Agenda . AddTargets ( new string [ ] { "UnrealHeaderTool" } , HostPlatform , UnrealTargetConfiguration . Development ) ;
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : "-skipnonhostplatforms" ) ;
Build . Build ( Agenda , InDeleteBuildProducts : true , InUpdateVersionFiles : false , InForceNonUnity : true ) ;
UE4Build . CheckBuildProducts ( Build . BuildProductFiles ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
}
2014-08-22 13:39:55 -04:00
public class NonUnityTestNode : TestNode
{
public NonUnityTestNode ( UnrealTargetPlatform InHostPlatform )
: base ( InHostPlatform )
{
AddPseudodependency ( RootEditorNode . StaticGetFullName ( HostPlatform ) ) ;
}
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform )
{
return "NonUnityTestCompile" + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
int Result = base . CISFrequencyQuantumShift ( bp ) + 2 ;
if ( HostPlatform = = UnrealTargetPlatform . Mac )
{
Result + = 1 ;
}
return Result ;
}
public override int AgentMemoryRequirement ( GUBP bp )
{
int Result = base . AgentMemoryRequirement ( bp ) ;
if ( HostPlatform = = UnrealTargetPlatform . Mac )
{
Result = 32 ;
}
return Result ;
}
public override void DoTest ( GUBP bp )
{
var Build = new UE4Build ( bp ) ;
var Agenda = new UE4Build . BuildAgenda ( ) ;
Agenda . AddTargets ( new string [ ] { "UnrealHeaderTool" } , HostPlatform , UnrealTargetConfiguration . Development ) ;
Agenda . AddTargets (
new string [ ] { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ,
HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : "-skipnonhostplatforms" ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( bp . Branch . BaseEngineProject . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = bp . Branch . BaseEngineProject . Properties . Targets [ Kind ] ;
Agenda . AddTargets ( new string [ ] { Target . TargetName } , HostPlatform , UnrealTargetConfiguration . Development ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Build . Build ( Agenda , InDeleteBuildProducts : true , InUpdateVersionFiles : false , InForceNonUnity : true ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
UE4Build . CheckBuildProducts ( Build . BuildProductFiles ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class IOSOnPCTestNode : TestNode
{
public IOSOnPCTestNode ( GUBP bp )
: base ( UnrealTargetPlatform . Win64 )
{
AddDependency ( ToolsForCompileNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
AddDependency ( ToolsNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
AddPseudodependency ( GamePlatformMonolithicsNode . StaticGetFullName ( UnrealTargetPlatform . Mac , bp . Branch . BaseEngineProject , UnrealTargetPlatform . IOS ) ) ;
}
public static string StaticGetFullName ( )
{
return "IOSOnPCTestCompile" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 3 ;
}
public override void DoTest ( GUBP bp )
{
var Build = new UE4Build ( bp ) ;
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-05-05 16:21:56 -04:00
2014-08-22 13:39:55 -04:00
Agenda . AddTargets ( new string [ ] { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Game ] . TargetName } , UnrealTargetPlatform . IOS , UnrealTargetConfiguration . Development ) ;
2014-05-05 16:21:56 -04:00
2014-08-22 13:39:55 -04:00
Build . Build ( Agenda , InDeleteBuildProducts : true , InUpdateVersionFiles : false ) ;
2014-05-05 16:21:56 -04:00
2014-08-22 13:39:55 -04:00
UE4Build . CheckBuildProducts ( Build . BuildProductFiles ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
}
2015-01-14 13:17:29 -05:00
public class VSExpressTestNode : TestNode
{
public VSExpressTestNode ( GUBP bp )
: base ( UnrealTargetPlatform . Win64 )
{
AddDependency ( ToolsForCompileNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
AddDependency ( RootEditorNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
}
public static string StaticGetFullName ( )
{
return "VSExpressTestCompile" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 3 ;
}
public override string ECAgentString ( )
{
return "VCTestAgent" ;
}
public override void DoTest ( GUBP bp )
{
var Build = new UE4Build ( bp ) ;
var Agenda = new UE4Build . BuildAgenda ( ) ;
2014-05-05 16:21:56 -04:00
2015-03-30 15:01:38 -04:00
string AddArgs = "-nobuilduht" ;
2015-01-14 13:17:29 -05:00
if ( bp . bOrthogonalizeEditorPlatforms )
{
AddArgs + = " -skipnonhostplatforms" ;
}
Agenda . AddTargets (
new string [ ] { bp . Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . TargetName } ,
HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
foreach ( var ProgramTarget in bp . Branch . BaseEngineProject . Properties . Programs )
{
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithBaseEditor ( ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) )
{
Agenda . AddTargets ( new string [ ] { ProgramTarget . TargetName } , HostPlatform , UnrealTargetConfiguration . Development , InAddArgs : AddArgs ) ;
}
}
Build . Build ( Agenda , InDeleteBuildProducts : true , InUpdateVersionFiles : false ) ;
UE4Build . CheckBuildProducts ( Build . BuildProductFiles ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
}
2014-08-22 13:39:55 -04:00
public class UATTestNode : TestNode
{
string TestName ;
BranchInfo . BranchUProject GameProj ;
string UATCommandLine ;
bool DependsOnEditor ;
List < UnrealTargetPlatform > DependsOnCooked ;
float ECPriority ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public UATTestNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , string InTestName , string InUATCommandLine , string InAgentSharingGroup , bool InDependsOnEditor = true , List < UnrealTargetPlatform > InDependsOnCooked = null , float InECPriority = 0.0f )
: base ( InHostPlatform )
{
AgentSharingGroup = InAgentSharingGroup ;
ECPriority = InECPriority ;
GameProj = InGameProj ;
TestName = InTestName ;
UATCommandLine = InUATCommandLine ;
bool bWillCook = InUATCommandLine . IndexOf ( "-cook" ) > = 0 ;
DependsOnEditor = InDependsOnEditor | | bWillCook ;
if ( InDependsOnCooked ! = null )
{
DependsOnCooked = InDependsOnCooked ;
}
else
{
DependsOnCooked = new List < UnrealTargetPlatform > ( ) ;
}
if ( DependsOnEditor )
{
AddDependency ( EditorAndToolsNode . StaticGetFullName ( HostPlatform ) ) ;
if ( GameProj . GameName ! = bp . Branch . BaseEngineProject . GameName )
{
if ( GameProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
AddDependency ( EditorGameNode . StaticGetFullName ( HostPlatform , GameProj ) ) ;
}
}
}
foreach ( var Plat in DependsOnCooked )
{
AddDependency ( GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , GameProj , Plat ) ) ;
}
AddPseudodependency ( WaitForTestShared . StaticGetFullName ( ) ) ;
// If the same test fails for the base engine, don't bother trying
if ( InGameProj . GameName ! = bp . Branch . BaseEngineProject . GameName )
{
if ( bp . HasNode ( UATTestNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , TestName ) ) )
{
AddPseudodependency ( UATTestNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , InTestName ) ) ;
}
else
{
bool bFoundACook = false ;
foreach ( var Plat in DependsOnCooked )
{
var PlatTestName = "CookedGameTest_" + Plat . ToString ( ) ;
if ( bp . HasNode ( UATTestNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , PlatTestName ) ) )
{
AddPseudodependency ( UATTestNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , PlatTestName ) ) ;
bFoundACook = true ;
}
}
2014-07-22 11:45:18 -04:00
2014-08-22 13:39:55 -04:00
if ( ! bFoundACook & & bp . HasNode ( UATTestNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , "EditorTest" ) ) )
{
AddPseudodependency ( UATTestNode . StaticGetFullName ( HostPlatform , bp . Branch . BaseEngineProject , "EditorTest" ) ) ;
}
2014-07-22 11:45:18 -04:00
2014-08-22 13:39:55 -04:00
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( InGameProj . GameName = = bp . Branch . BaseEngineProject . GameName )
{
ECPriority = ECPriority + 1.0f ;
}
if ( UATCommandLine . IndexOf ( "-RunAutomationTests" , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ECPriority = ECPriority - 4.0f ;
if ( UATCommandLine . IndexOf ( "-EditorTest" , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ECPriority = ECPriority - 4.0f ;
}
}
else if ( UATCommandLine . IndexOf ( "-EditorTest" , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
ECPriority = ECPriority + 2.0f ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
public override float Priority ( )
{
return ECPriority ;
}
2014-10-15 08:26:52 -04:00
public override bool IsTest ( )
{
return true ;
}
2014-08-22 13:39:55 -04:00
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 5 ;
}
public override string ECAgentString ( )
{
string Result = base . ECAgentString ( ) ;
foreach ( UnrealTargetPlatform platform in Enum . GetValues ( typeof ( UnrealTargetPlatform ) ) )
{
if ( platform ! = HostPlatform & & platform ! = GetAltHostPlatform ( ) )
{
if ( UATCommandLine . IndexOf ( "-platform=" + platform . ToString ( ) , StringComparison . InvariantCultureIgnoreCase ) > = 0 )
{
Result = MergeSpaceStrings ( Result , platform . ToString ( ) ) ;
}
}
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , string InTestName )
{
return InGameProj . GameName + "_" + InTestName + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , GameProj , TestName ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
public override void DoTest ( GUBP bp )
{
string ProjectArg = "" ;
if ( ! String . IsNullOrEmpty ( GameProj . FilePath ) & & UATCommandLine . IndexOf ( "-project=" , StringComparison . InvariantCultureIgnoreCase ) < 0 )
{
ProjectArg = " -project=\"" + GameProj . FilePath + "\"" ;
}
string WorkingCommandline = UATCommandLine + ProjectArg + " -NoSubmit -addcmdline=\"-DisablePS4TMAPI\"" ;
if ( WorkingCommandline . Contains ( "-project=\"\"" ) )
{
throw new AutomationException ( "Command line {0} contains -project=\"\" which is doomed to fail" , WorkingCommandline ) ;
}
string LogFile = RunUAT ( CommandUtils . CmdEnv , WorkingCommandline ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( CommandUtils . ReadAllText ( LogFile ) ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class GameAggregateNode : HostPlatformAggregateNode
{
BranchInfo . BranchUProject GameProj ;
string AggregateName ;
float ECPriority ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public GameAggregateNode ( GUBP bp , UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , string InAggregateName , List < string > Dependencies , float InECPriority = 100.0f )
: base ( InHostPlatform )
{
GameProj = InGameProj ;
AggregateName = InAggregateName ;
ECPriority = InECPriority ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Dep in Dependencies )
{
AddDependency ( Dep ) ;
}
}
public override float Priority ( )
{
return ECPriority ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( UnrealTargetPlatform InHostPlatform , BranchInfo . BranchUProject InGameProj , string InAggregateName )
{
return InGameProj . GameName + "_" + InAggregateName + StaticGetHostPlatformSuffix ( InHostPlatform ) ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( HostPlatform , GameProj , AggregateName ) ;
}
public override string GameNameIfAnyForTempStorage ( )
{
return GameProj . GameName ;
}
} ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public class CleanSharedTempStorageNode : GUBPNode
{
public CleanSharedTempStorageNode ( GUBP bp )
{
var ToolsNode = bp . FindNode ( ToolsForCompileNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) ;
AgentSharingGroup = ToolsNode . AgentSharingGroup ;
}
public override float Priority ( )
{
return - 1E15f ;
}
2014-04-29 21:53:42 -04:00
2014-08-22 13:39:55 -04:00
public static string StaticGetFullName ( )
{
return "CleanSharedTempStorage" ;
}
public override string GetFullName ( )
{
return StaticGetFullName ( ) ;
}
public override void DoBuild ( GUBP bp )
{
{
var StartTime = DateTime . UtcNow ;
foreach ( var NodeToDo in bp . GUBPNodes )
{
CleanSharedTempStorageDirectory ( NodeToDo . Value . GameNameIfAnyForTempStorage ( ) ) ;
}
var BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds ;
Log ( "Took {0}s to clear temp storage of old files." , BuildDuration / 1000 ) ;
}
2014-04-29 21:53:42 -04:00
2014-08-22 13:39:55 -04:00
BuildProducts = new List < string > ( ) ;
SaveRecordOfSuccessAndAddToBuildProducts ( ) ;
}
public override int CISFrequencyQuantumShift ( GUBP bp )
{
return base . CISFrequencyQuantumShift ( bp ) + 3 ;
}
} ;
2014-04-29 21:53:42 -04:00
2014-08-22 13:39:55 -04:00
public string AddNode ( GUBPNode Node )
{
string Name = Node . GetFullName ( ) ;
if ( GUBPNodes . ContainsKey ( Name ) )
{
throw new AutomationException ( "Attempt to add a duplicate node {0}" , Node . GetFullName ( ) ) ;
}
GUBPNodes . Add ( Name , Node ) ;
return Name ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public bool HasNode ( string Node )
{
return GUBPNodes . ContainsKey ( Node ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public GUBPNode FindNode ( string Node )
{
return GUBPNodes [ Node ] ;
}
2014-03-14 14:13:41 -04:00
2015-04-17 08:15:17 -04:00
public GUBPNode TryFindNode ( string Node )
{
GUBPNode Result ;
GUBPNodes . TryGetValue ( Node , out Result ) ;
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public void RemovePseudodependencyFromNode ( string Node , string Dep )
{
if ( ! GUBPNodes . ContainsKey ( Node ) )
{
throw new AutomationException ( "Node {0} not found" , Node ) ;
2015-04-26 07:33:29 -04:00
}
2014-08-22 13:39:55 -04:00
GUBPNodes [ Node ] . RemovePseudodependency ( Dep ) ;
}
2014-03-14 14:13:41 -04:00
2015-04-21 18:39:43 -04:00
public void RemoveAllPseudodependenciesFromNode ( string Node )
{
if ( ! GUBPNodes . ContainsKey ( Node ) )
{
throw new AutomationException ( "Node {0} not found" , Node ) ;
}
GUBPNodes [ Node ] . FullNamesOfPseudosependencies . Clear ( ) ;
}
2014-08-22 13:39:55 -04:00
List < string > GetDependencies ( string NodeToDo , bool bFlat = false , bool ECOnly = false )
{
var Result = new List < string > ( ) ;
foreach ( var Node in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
bool Usable = GUBPNodes [ Node ] . RunInEC ( ) | | ! ECOnly ;
if ( Usable )
{
if ( ! Result . Contains ( Node ) )
{
Result . Add ( Node ) ;
}
}
if ( bFlat | | ! Usable )
{
foreach ( var RNode in GetDependencies ( Node , bFlat , ECOnly ) )
{
if ( ! Result . Contains ( RNode ) )
{
Result . Add ( RNode ) ;
}
}
}
}
foreach ( var Node in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
bool Usable = GUBPNodes [ Node ] . RunInEC ( ) | | ! ECOnly ;
if ( Usable )
{
if ( ! Result . Contains ( Node ) )
{
Result . Add ( Node ) ;
}
}
if ( bFlat | | ! Usable )
{
foreach ( var RNode in GetDependencies ( Node , bFlat , ECOnly ) )
{
if ( ! Result . Contains ( RNode ) )
{
Result . Add ( RNode ) ;
}
}
}
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2015-02-10 14:58:32 -05:00
List < string > GetCompletedOnlyDependencies ( string NodeToDo , bool bFlat = false , bool ECOnly = true )
{
var Result = new List < string > ( ) ;
foreach ( var Node in GUBPNodes [ NodeToDo ] . CompletedDependencies )
{
bool Usable = GUBPNodes [ Node ] . RunInEC ( ) | | ! ECOnly ;
if ( Usable )
{
if ( ! Result . Contains ( Node ) )
{
Result . Add ( Node ) ;
}
}
if ( bFlat | | ! Usable )
{
foreach ( var RNode in GetCompletedOnlyDependencies ( Node , bFlat , ECOnly ) )
{
if ( ! Result . Contains ( RNode ) )
{
Result . Add ( RNode ) ;
}
}
}
}
return Result ;
}
2014-08-22 13:39:55 -04:00
List < string > GetECDependencies ( string NodeToDo , bool bFlat = false )
{
return GetDependencies ( NodeToDo , bFlat , true ) ;
}
bool NodeDependsOn ( string Rootward , string Leafward )
{
var Deps = GetDependencies ( Leafward , true ) ;
return Deps . Contains ( Rootward ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string GetControllingTrigger ( string NodeToDo )
{
if ( GUBPNodesControllingTrigger . ContainsKey ( NodeToDo ) )
{
return GUBPNodesControllingTrigger [ NodeToDo ] ;
}
var Result = "" ;
foreach ( var Node in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Node ) )
{
throw new AutomationException ( "Dependency {0} in {1} not found." , Node , NodeToDo ) ;
}
bool IsTrigger = GUBPNodes [ Node ] . TriggerNode ( ) ;
if ( IsTrigger )
{
if ( Node ! = Result & & ! string . IsNullOrEmpty ( Result ) )
{
throw new AutomationException ( "Node {0} has two controlling triggers {1} and {2}." , NodeToDo , Node , Result ) ;
}
Result = Node ;
}
else
{
string NewResult = GetControllingTrigger ( Node ) ;
if ( ! String . IsNullOrEmpty ( NewResult ) )
{
if ( NewResult ! = Result & & ! string . IsNullOrEmpty ( Result ) )
{
throw new AutomationException ( "Node {0} has two controlling triggers {1} and {2}." , NodeToDo , NewResult , Result ) ;
}
Result = NewResult ;
}
}
}
foreach ( var Node in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
if ( ! GUBPNodes . ContainsKey ( Node ) )
{
throw new AutomationException ( "Pseudodependency {0} in {1} not found." , Node , NodeToDo ) ;
}
bool IsTrigger = GUBPNodes [ Node ] . TriggerNode ( ) ;
if ( IsTrigger )
{
if ( Node ! = Result & & ! string . IsNullOrEmpty ( Result ) )
{
throw new AutomationException ( "Node {0} has two controlling triggers {1} and {2}." , NodeToDo , Node , Result ) ;
}
Result = Node ;
}
else
{
string NewResult = GetControllingTrigger ( Node ) ;
if ( ! String . IsNullOrEmpty ( NewResult ) )
{
if ( NewResult ! = Result & & ! string . IsNullOrEmpty ( Result ) )
{
throw new AutomationException ( "Node {0} has two controlling triggers {1} and {2}." , NodeToDo , NewResult , Result ) ;
}
Result = NewResult ;
}
}
}
GUBPNodesControllingTrigger . Add ( NodeToDo , Result ) ;
return Result ;
}
string GetControllingTriggerDotName ( string NodeToDo )
{
if ( GUBPNodesControllingTriggerDotName . ContainsKey ( NodeToDo ) )
{
return GUBPNodesControllingTriggerDotName [ NodeToDo ] ;
}
string Result = "" ;
string WorkingNode = NodeToDo ;
while ( true )
{
string ThisResult = GetControllingTrigger ( WorkingNode ) ;
if ( ThisResult = = "" )
{
break ;
}
if ( Result ! = "" )
{
Result = "." + Result ;
}
Result = ThisResult + Result ;
WorkingNode = ThisResult ;
}
GUBPNodesControllingTriggerDotName . Add ( NodeToDo , Result ) ;
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public string CISFrequencyQuantumShiftString ( string NodeToDo )
{
string FrequencyString = "" ;
int Quantum = GUBPNodes [ NodeToDo ] . DependentCISFrequencyQuantumShift ( ) ;
if ( Quantum > 0 )
{
2015-01-27 14:24:55 -05:00
int TimeQuantum = 20 ;
if ( BranchOptions . QuantumOverride ! = 0 )
{
TimeQuantum = BranchOptions . QuantumOverride ;
}
int Minutes = TimeQuantum * ( 1 < < Quantum ) ;
2014-08-22 13:39:55 -04:00
if ( Minutes < 60 )
{
FrequencyString = string . Format ( " ({0}m)" , Minutes ) ;
}
else
{
FrequencyString = string . Format ( " ({0}h{1}m)" , Minutes / 60 , Minutes % 60 ) ;
}
}
return FrequencyString ;
}
2014-03-14 14:13:41 -04:00
2015-04-24 20:25:23 -04:00
public int ComputeDependentCISFrequencyQuantumShift ( string NodeToDo , Dictionary < string , int > FrequencyOverrides )
2014-08-22 13:39:55 -04:00
{
int Result = GUBPNodes [ NodeToDo ] . ComputedDependentCISFrequencyQuantumShift ;
if ( Result < 0 )
{
Result = GUBPNodes [ NodeToDo ] . CISFrequencyQuantumShift ( this ) ;
Result = GetFrequencyForNode ( this , GUBPNodes [ NodeToDo ] . GetFullName ( ) , Result ) ;
2015-04-24 20:25:23 -04:00
int FrequencyOverride ;
if ( FrequencyOverrides . TryGetValue ( NodeToDo , out FrequencyOverride ) & & Result > FrequencyOverride )
{
Result = FrequencyOverride ;
}
2014-08-22 13:39:55 -04:00
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
2015-04-24 20:25:23 -04:00
Result = Math . Max ( ComputeDependentCISFrequencyQuantumShift ( Dep , FrequencyOverrides ) , Result ) ;
2014-08-22 13:39:55 -04:00
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
2015-04-24 20:25:23 -04:00
Result = Math . Max ( ComputeDependentCISFrequencyQuantumShift ( Dep , FrequencyOverrides ) , Result ) ;
2014-08-22 13:39:55 -04:00
}
2015-02-10 14:58:32 -05:00
foreach ( var Dep in GUBPNodes [ NodeToDo ] . CompletedDependencies )
{
2015-04-24 20:25:23 -04:00
Result = Math . Max ( ComputeDependentCISFrequencyQuantumShift ( Dep , FrequencyOverrides ) , Result ) ;
2015-02-10 14:58:32 -05:00
}
2014-08-22 13:39:55 -04:00
if ( Result < 0 )
{
throw new AutomationException ( "Failed to compute shift." ) ;
}
GUBPNodes [ NodeToDo ] . ComputedDependentCISFrequencyQuantumShift = Result ;
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
bool NodeIsAlreadyComplete ( string NodeToDo , bool LocalOnly )
{
if ( GUBPNodesCompleted . ContainsKey ( NodeToDo ) )
{
return GUBPNodesCompleted [ NodeToDo ] ;
}
string NodeStoreName = StoreName + "-" + GUBPNodes [ NodeToDo ] . GetFullName ( ) ;
string GameNameIfAny = GUBPNodes [ NodeToDo ] . GameNameIfAnyForTempStorage ( ) ;
bool Result ;
if ( LocalOnly )
{
Result = LocalTempStorageExists ( CmdEnv , NodeStoreName , bQuiet : true ) ;
}
else
{
Result = TempStorageExists ( CmdEnv , NodeStoreName , GameNameIfAny , bQuiet : true ) ;
2015-01-15 12:07:10 -05:00
if ( GameNameIfAny ! = "" & & Result = = false )
{
Result = TempStorageExists ( CmdEnv , NodeStoreName , "" , bQuiet : true ) ;
}
2014-08-22 13:39:55 -04:00
}
if ( Result )
{
Log ( "***** GUBP Trigger Node was already triggered {0} -> {1} : {2}" , GUBPNodes [ NodeToDo ] . GetFullName ( ) , GameNameIfAny , NodeStoreName ) ;
}
else
{
Log ( "***** GUBP Trigger Node was NOT yet triggered {0} -> {1} : {2}" , GUBPNodes [ NodeToDo ] . GetFullName ( ) , GameNameIfAny , NodeStoreName ) ;
}
GUBPNodesCompleted . Add ( NodeToDo , Result ) ;
return Result ;
}
string RunECTool ( string Args , bool bQuiet = false )
{
if ( ParseParam ( "FakeEC" ) )
{
Log ( "***** Would have ran ectool {0}" , Args ) ;
return "We didn't actually run ectool" ;
}
else
{
ERunOptions Opts = ERunOptions . Default ;
if ( bQuiet )
{
Opts = ( Opts & ~ ERunOptions . AllowSpew ) | ERunOptions . NoLoggingOfRunCommand ;
}
2015-03-27 10:15:53 -04:00
return RunAndLog ( "ectool" , "--timeout 900 " + Args , Options : Opts ) ;
2014-08-22 13:39:55 -04:00
}
}
2014-09-03 10:12:50 -04:00
void WriteECPerl ( List < string > Args )
{
Args . Add ( "$batch->submit();" ) ;
string ECPerlFile = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LogFolder , "jobsteps.pl" ) ;
WriteAllLines_NoExceptions ( ECPerlFile , Args . ToArray ( ) ) ;
}
2014-08-28 17:05:26 -04:00
string GetEMailListForNode ( GUBP bp , string NodeToDo , string Emails , string Causers )
2014-08-22 13:39:55 -04:00
{
var BranchForEmail = "" ;
if ( P4Enabled )
{
BranchForEmail = P4Env . BuildRootP4 ;
}
2014-08-28 16:40:17 -04:00
return HackEmails ( Emails , Causers , BranchForEmail , NodeToDo ) ;
2014-08-22 13:39:55 -04:00
}
int GetFrequencyForNode ( GUBP bp , string NodeToDo , int BaseFrequency )
{
2015-04-17 13:21:04 -04:00
return HackFrequency ( bp , BranchName , NodeToDo , BaseFrequency ) ;
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
List < P4Connection . ChangeRecord > GetChanges ( int LastOutputForChanges , int TopCL , int LastGreen )
{
var Result = new List < P4Connection . ChangeRecord > ( ) ;
if ( TopCL > LastGreen )
{
if ( LastOutputForChanges > 1990000 )
{
string Cmd = String . Format ( "{0}@{1},{2} {3}@{4},{5}" ,
2015-04-25 09:23:03 -04:00
CombinePaths ( PathSeparator . Slash , P4Env . BuildRootP4 , "..." , "Source" , "..." ) , LastOutputForChanges + 1 , TopCL ,
CombinePaths ( PathSeparator . Slash , P4Env . BuildRootP4 , "..." , "Build" , "..." ) , LastOutputForChanges + 1 , TopCL
2014-08-22 13:39:55 -04:00
) ;
List < P4Connection . ChangeRecord > ChangeRecords ;
2014-04-23 18:27:14 -04:00
if ( P4 . Changes ( out ChangeRecords , Cmd , false , true , LongComment : true ) )
2014-08-22 13:39:55 -04:00
{
foreach ( var Record in ChangeRecords )
{
if ( ! Record . User . Equals ( "buildmachine" , StringComparison . InvariantCultureIgnoreCase ) )
{
Result . Add ( Record ) ;
}
}
}
else
{
throw new AutomationException ( "Could not get changes; cmdline: p4 changes {0}" , Cmd ) ;
}
}
else
{
throw new AutomationException ( "That CL looks pretty far off {0}" , LastOutputForChanges ) ;
}
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
int PrintChanges ( int LastOutputForChanges , int TopCL , int LastGreen )
{
var ChangeRecords = GetChanges ( LastOutputForChanges , TopCL , LastGreen ) ;
foreach ( var Record in ChangeRecords )
{
var Summary = Record . Summary . Replace ( "\r" , "\n" ) ;
if ( Summary . IndexOf ( "\n" ) > 0 )
{
Summary = Summary . Substring ( 0 , Summary . IndexOf ( "\n" ) ) ;
}
Log ( " {0} {1} {2}" , Record . CL , Record . UserEmail , Summary ) ;
}
return TopCL ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
void PrintDetailedChanges ( NodeHistory History , bool bShowAllChanges = false )
{
var StartTime = DateTime . UtcNow ;
2014-04-29 09:35:49 -04:00
2014-08-22 13:39:55 -04:00
string Me = String . Format ( "{0} <<<< local sync" , P4Env . Changelist ) ;
int LastOutputForChanges = 0 ;
int LastGreen = History . LastSucceeded ;
if ( bShowAllChanges )
{
if ( History . AllStarted . Count > 0 )
{
LastGreen = History . AllStarted [ 0 ] ;
}
}
foreach ( var cl in History . AllStarted )
{
if ( cl < LastGreen )
{
continue ;
}
if ( P4Env . Changelist < cl & & Me ! = "" )
{
LastOutputForChanges = PrintChanges ( LastOutputForChanges , P4Env . Changelist , LastGreen ) ;
Log ( " {0}" , Me ) ;
Me = "" ;
}
string Status = "In Process" ;
if ( History . AllSucceeded . Contains ( cl ) )
{
Status = "ok" ;
}
if ( History . AllFailed . Contains ( cl ) )
{
Status = "FAIL" ;
}
LastOutputForChanges = PrintChanges ( LastOutputForChanges , cl , LastGreen ) ;
Log ( " {0} {1}" , cl , Status ) ;
}
if ( Me ! = "" )
{
LastOutputForChanges = PrintChanges ( LastOutputForChanges , P4Env . Changelist , LastGreen ) ;
Log ( " {0}" , Me ) ;
}
var BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds ;
Log ( "Took {0}s to get P4 history" , BuildDuration / 1000 ) ;
2014-04-29 09:35:49 -04:00
2014-08-22 13:39:55 -04:00
}
void PrintNodes ( GUBP bp , List < string > Nodes , bool LocalOnly , List < string > UnfinishedTriggers = null )
{
bool bShowAllChanges = bp . ParseParam ( "AllChanges" ) & & GUBPNodesHistory ! = null ;
bool bShowChanges = ( bp . ParseParam ( "Changes" ) & & GUBPNodesHistory ! = null ) | | bShowAllChanges ;
bool bShowDetailedHistory = ( bp . ParseParam ( "History" ) & & GUBPNodesHistory ! = null ) | | bShowChanges ;
bool bShowDependencies = bp . ParseParam ( "ShowDependencies" ) ;
2014-10-27 07:59:33 -04:00
bool bShowDependednOn = bp . ParseParam ( "ShowDependedOn" ) ;
2014-11-03 11:46:48 -05:00
bool bShowDependentPromotions = bp . ParseParam ( "ShowDependentPromotions" ) ;
2014-08-22 13:39:55 -04:00
bool bShowECDependencies = bp . ParseParam ( "ShowECDependencies" ) ;
bool bShowHistory = ! bp . ParseParam ( "NoHistory" ) & & GUBPNodesHistory ! = null ;
bool AddEmailProps = bp . ParseParam ( "ShowEmails" ) ;
bool ECProc = bp . ParseParam ( "ShowECProc" ) ;
bool ECOnly = bp . ParseParam ( "ShowECOnly" ) ;
bool bShowTriggers = true ;
string LastControllingTrigger = "" ;
string LastAgentGroup = "" ;
foreach ( var NodeToDo in Nodes )
{
if ( ECOnly & & ! GUBPNodes [ NodeToDo ] . RunInEC ( ) )
{
continue ;
}
string EMails = "" ;
if ( AddEmailProps )
{
2014-08-28 16:40:17 -04:00
EMails = GetEMailListForNode ( bp , NodeToDo , "" , "" ) ;
2014-08-22 13:39:55 -04:00
}
if ( bShowTriggers )
{
string MyControllingTrigger = GetControllingTriggerDotName ( NodeToDo ) ;
if ( MyControllingTrigger ! = LastControllingTrigger )
{
LastControllingTrigger = MyControllingTrigger ;
if ( MyControllingTrigger ! = "" )
{
string Finished = "" ;
if ( UnfinishedTriggers ! = null )
{
string MyShortControllingTrigger = GetControllingTrigger ( NodeToDo ) ;
if ( UnfinishedTriggers . Contains ( MyShortControllingTrigger ) )
{
Finished = "(not yet triggered)" ;
}
else
{
Finished = "(already triggered)" ;
}
}
Log ( " Controlling Trigger: {0} {1}" , MyControllingTrigger , Finished ) ;
}
}
}
if ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ! = LastAgentGroup & & GUBPNodes [ NodeToDo ] . AgentSharingGroup ! = "" )
{
Log ( " Agent Group: {0}" , GUBPNodes [ NodeToDo ] . AgentSharingGroup ) ;
}
LastAgentGroup = GUBPNodes [ NodeToDo ] . AgentSharingGroup ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string Agent = GUBPNodes [ NodeToDo ] . ECAgentString ( ) ;
2015-01-26 15:29:36 -05:00
if ( ParseParamValue ( "AgentOverride" ) ! = "" & & ! GUBPNodes [ NodeToDo ] . GetFullName ( ) . Contains ( "Mac" ) )
{
Agent = ParseParamValue ( "AgentOverride" ) ;
}
2014-08-22 13:39:55 -04:00
if ( Agent ! = "" )
{
Agent = "[" + Agent + "]" ;
}
string MemoryReq = "[" + GUBPNodes [ NodeToDo ] . AgentMemoryRequirement ( bp ) . ToString ( ) + "]" ;
if ( MemoryReq = = "[0]" )
{
MemoryReq = "" ;
}
string FrequencyString = CISFrequencyQuantumShiftString ( NodeToDo ) ;
2014-05-02 10:44:27 -04:00
2014-08-22 13:39:55 -04:00
Log ( " {0}{1}{2}{3}{4}{5}{6} {7} {8}" ,
( LastAgentGroup ! = "" ? " " : "" ) ,
NodeToDo ,
FrequencyString ,
NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) ? " - (Completed)" : "" ,
GUBPNodes [ NodeToDo ] . TriggerNode ( ) ? " - (TriggerNode)" : "" ,
2014-10-15 08:26:52 -04:00
GUBPNodes [ NodeToDo ] . IsSticky ( ) ? " - (Sticky)" : "" ,
2014-08-22 13:39:55 -04:00
Agent ,
MemoryReq ,
EMails ,
ECProc ? GUBPNodes [ NodeToDo ] . ECProcedure ( ) : ""
) ;
if ( bShowHistory & & GUBPNodesHistory . ContainsKey ( NodeToDo ) )
{
var History = GUBPNodesHistory [ NodeToDo ] ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( bShowDetailedHistory )
{
PrintDetailedChanges ( History , bShowAllChanges ) ;
}
else
{
Log ( " Last Success: {0}" , History . LastSucceeded ) ;
Log ( " Last Fail : {0}" , History . LastFailed ) ;
Log ( " Fails Since: {0}" , History . FailedString ) ;
2014-12-18 13:47:28 -05:00
Log ( " InProgress Since: {0}" , History . InProgressString ) ;
2014-08-22 13:39:55 -04:00
}
}
if ( bShowDependencies )
{
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
Log ( " dep> {0}" , Dep ) ;
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
Log ( " pdep> {0}" , Dep ) ;
}
2015-02-10 14:58:32 -05:00
foreach ( var Dep in GUBPNodes [ NodeToDo ] . CompletedDependencies )
{
Log ( " cdep>{0}" , Dep ) ;
}
2014-08-22 13:39:55 -04:00
}
if ( bShowECDependencies )
{
foreach ( var Dep in GetECDependencies ( NodeToDo ) )
{
Log ( " {0}" , Dep ) ;
}
2015-02-10 14:58:32 -05:00
foreach ( var Dep in GetCompletedOnlyDependencies ( NodeToDo ) )
{
Log ( " compDep> {0}" , Dep ) ;
}
2014-08-22 13:39:55 -04:00
}
2015-02-10 14:58:32 -05:00
2014-10-27 07:59:33 -04:00
if ( bShowDependednOn )
{
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependedOn )
{
Log ( " depOn> {0}" , Dep ) ;
}
}
2014-11-03 11:46:48 -05:00
if ( bShowDependentPromotions )
{
foreach ( var Dep in GUBPNodes [ NodeToDo ] . DependentPromotions )
{
Log ( " depPro> {0}" , Dep ) ;
}
2014-12-18 13:47:28 -05:00
}
2014-08-22 13:39:55 -04:00
}
}
public void SaveGraphVisualization ( List < string > Nodes )
{
var GraphNodes = new List < GraphNode > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var NodeToGraphNodeMap = new Dictionary < string , GraphNode > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
for ( var NodeIndex = 0 ; NodeIndex < Nodes . Count ; + + NodeIndex )
{
var Node = Nodes [ NodeIndex ] ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var GraphNode = new GraphNode ( )
{
Id = GraphNodes . Count ,
Label = Node
} ;
GraphNodes . Add ( GraphNode ) ;
NodeToGraphNodeMap . Add ( Node , GraphNode ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// Connect everything together
var GraphEdges = new List < GraphEdge > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
for ( var NodeIndex = 0 ; NodeIndex < Nodes . Count ; + + NodeIndex )
{
var Node = Nodes [ NodeIndex ] ;
GraphNode NodeGraphNode = NodeToGraphNodeMap [ Node ] ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Dep in GUBPNodes [ Node ] . FullNamesOfDependencies )
{
GraphNode PrerequisiteFileGraphNode ;
if ( NodeToGraphNodeMap . TryGetValue ( Dep , out PrerequisiteFileGraphNode ) )
{
// Connect a file our action is dependent on, to our action itself
var NewGraphEdge = new GraphEdge ( )
{
Id = GraphEdges . Count ,
Source = PrerequisiteFileGraphNode ,
Target = NodeGraphNode ,
Color = new GraphColor ( ) { R = 0.0f , G = 0.0f , B = 0.0f , A = 0.75f }
} ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
GraphEdges . Add ( NewGraphEdge ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
foreach ( var Dep in GUBPNodes [ Node ] . FullNamesOfPseudosependencies )
{
GraphNode PrerequisiteFileGraphNode ;
if ( NodeToGraphNodeMap . TryGetValue ( Dep , out PrerequisiteFileGraphNode ) )
{
// Connect a file our action is dependent on, to our action itself
var NewGraphEdge = new GraphEdge ( )
{
Id = GraphEdges . Count ,
Source = PrerequisiteFileGraphNode ,
Target = NodeGraphNode ,
Color = new GraphColor ( ) { R = 0.0f , G = 0.0f , B = 0.0f , A = 0.25f }
} ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
GraphEdges . Add ( NewGraphEdge ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string Filename = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LogFolder , "GubpGraph.gexf" ) ;
Log ( "Writing graph to {0}" , Filename ) ;
GraphVisualization . WriteGraphFile ( Filename , "GUBP Nodes" , GraphNodes , GraphEdges ) ;
Log ( "Wrote graph to {0}" , Filename ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// when the host is win64, this is win32 because those are also "host platforms"
static public UnrealTargetPlatform GetAltHostPlatform ( UnrealTargetPlatform HostPlatform )
{
UnrealTargetPlatform AltHostPlatform = UnrealTargetPlatform . Unknown ; // when the host is win64, this is win32 because those are also "host platforms"
if ( HostPlatform = = UnrealTargetPlatform . Win64 )
{
AltHostPlatform = UnrealTargetPlatform . Win32 ;
}
return AltHostPlatform ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public List < UnrealTargetPlatform > GetMonolithicPlatformsForUProject ( UnrealTargetPlatform HostPlatform , BranchInfo . BranchUProject GameProj , bool bIncludeHostPlatform )
{
UnrealTargetPlatform AltHostPlatform = GetAltHostPlatform ( HostPlatform ) ;
var Result = new List < UnrealTargetPlatform > ( ) ;
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( GameProj . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = GameProj . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
2014-08-18 13:29:39 -04:00
var AdditionalPlatforms = Target . Rules . GUBP_GetBuildOnlyPlatforms_MonolithicOnly ( HostPlatform ) ;
var AllPlatforms = Platforms . Union ( AdditionalPlatforms ) ;
foreach ( var Plat in AllPlatforms )
2014-08-22 13:39:55 -04:00
{
if ( GUBP . bNoIOSOnPC & & Plat = = UnrealTargetPlatform . IOS & & HostPlatform = = UnrealTargetPlatform . Win64 )
{
continue ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( ActivePlatforms . Contains ( Plat ) & & Target . Rules . SupportsPlatform ( Plat ) & &
( ( Plat ! = HostPlatform & & Plat ! = AltHostPlatform ) | | bIncludeHostPlatform ) )
{
Result . Add ( Plat ) ;
}
}
}
}
return Result ;
}
List < int > ConvertCLToIntList ( List < string > Strings )
{
var Result = new List < int > ( ) ;
foreach ( var ThisString in Strings )
{
int ThisInt = int . Parse ( ThisString ) ;
if ( ThisInt < 1960000 | | ThisInt > 3000000 )
{
Log ( "CL {0} appears to be out of range" , ThisInt ) ;
}
Result . Add ( ThisInt ) ;
}
Result . Sort ( ) ;
return Result ;
}
void SaveStatus ( string NodeToDo , string Suffix , string NodeStoreName , bool bSaveSharedTempStorage , string GameNameIfAny , string JobStepIDForFailure = null )
{
string Contents = "Just a status record: " + Suffix ;
if ( ! String . IsNullOrEmpty ( JobStepIDForFailure ) & & IsBuildMachine )
{
try
{
Contents = RunECTool ( String . Format ( "getProperties --jobStepId {0} --recurse 1" , JobStepIDForFailure ) , true ) ;
}
catch ( Exception Ex )
{
Log ( System . Diagnostics . TraceEventType . Warning , "Failed to get properties for jobstep to save them." ) ;
Log ( System . Diagnostics . TraceEventType . Warning , LogUtils . FormatException ( Ex ) ) ;
}
}
string RecordOfSuccess = CombinePaths ( CommandUtils . CmdEnv . LocalRoot , "Engine" , "Saved" , "Logs" , NodeToDo + Suffix + ".log" ) ;
CreateDirectory ( Path . GetDirectoryName ( RecordOfSuccess ) ) ;
2015-02-17 16:43:54 -05:00
WriteAllText ( RecordOfSuccess , Contents ) ;
StoreToTempStorage ( CmdEnv , NodeStoreName + Suffix , new List < string > { RecordOfSuccess } , ! bSaveSharedTempStorage , GameNameIfAny ) ;
2014-08-22 13:39:55 -04:00
}
string GetPropertyFromStep ( string PropertyPath )
{
string Property = "" ;
Property = RunECTool ( "getProperty \"" + PropertyPath + "\"" ) ;
Property = Property . TrimEnd ( '\r' , '\n' ) ;
return Property ;
2014-08-18 13:29:39 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
int CountZeros ( int Num )
{
if ( Num < 0 )
{
throw new AutomationException ( "Bad CountZeros" ) ;
}
if ( Num = = 0 )
{
return 31 ;
}
int Result = 0 ;
while ( ( Num & 1 ) = = 0 )
{
Result + + ;
Num > > = 1 ;
}
return Result ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
List < string > TopologicalSort ( HashSet < string > NodesToDo , string ExplicitTrigger = "" , bool LocalOnly = false , bool SubSort = false , bool DoNotConsiderCompletion = false )
{
var StartTime = DateTime . UtcNow ;
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
var OrdereredToDo = new List < string > ( ) ;
2014-04-28 16:25:35 -04:00
2014-08-22 13:39:55 -04:00
var SortedAgentGroupChains = new Dictionary < string , List < string > > ( ) ;
if ( ! SubSort )
{
var AgentGroupChains = new Dictionary < string , List < string > > ( ) ;
foreach ( var NodeToDo in NodesToDo )
{
string MyAgentGroup = GUBPNodes [ NodeToDo ] . AgentSharingGroup ;
if ( MyAgentGroup ! = "" )
{
if ( ! AgentGroupChains . ContainsKey ( MyAgentGroup ) )
{
AgentGroupChains . Add ( MyAgentGroup , new List < string > { NodeToDo } ) ;
}
else
{
AgentGroupChains [ MyAgentGroup ] . Add ( NodeToDo ) ;
}
}
}
foreach ( var Chain in AgentGroupChains )
{
SortedAgentGroupChains . Add ( Chain . Key , TopologicalSort ( new HashSet < string > ( Chain . Value ) , ExplicitTrigger , LocalOnly , true , DoNotConsiderCompletion ) ) ;
}
Log ( "***************Done with recursion" ) ;
}
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
// here we do a topological sort of the nodes, subject to a lexographical and priority sort
while ( NodesToDo . Count > 0 )
{
bool bProgressMade = false ;
float BestPriority = - 1E20f ;
string BestNode = "" ;
bool BestPseudoReady = false ;
var NonReadyAgentGroups = new HashSet < string > ( ) ;
var NonPeudoReadyAgentGroups = new HashSet < string > ( ) ;
var ExaminedAgentGroups = new HashSet < string > ( ) ;
foreach ( var NodeToDo in NodesToDo )
{
bool bReady = true ;
2015-02-10 14:58:32 -05:00
bool bPseudoReady = true ;
bool bCompReady = true ;
2014-08-22 13:39:55 -04:00
if ( ! SubSort & & GUBPNodes [ NodeToDo ] . AgentSharingGroup ! = "" )
{
if ( ExaminedAgentGroups . Contains ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ) )
{
bReady = ! NonReadyAgentGroups . Contains ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ) ;
bPseudoReady = ! NonPeudoReadyAgentGroups . Contains ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ) ; //this might not be accurate if bReady==false
}
else
{
ExaminedAgentGroups . Add ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ) ;
foreach ( var ChainNode in SortedAgentGroupChains [ GUBPNodes [ NodeToDo ] . AgentSharingGroup ] )
{
foreach ( var Dep in GUBPNodes [ ChainNode ] . FullNamesOfDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Dependency {0} node found." , Dep ) ;
}
if ( ! SortedAgentGroupChains [ GUBPNodes [ NodeToDo ] . AgentSharingGroup ] . Contains ( Dep ) & & NodesToDo . Contains ( Dep ) )
{
bReady = false ;
break ;
}
}
if ( ! bReady )
{
NonReadyAgentGroups . Add ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ) ;
break ;
}
foreach ( var Dep in GUBPNodes [ ChainNode ] . FullNamesOfPseudosependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Pseudodependency {0} node found." , Dep ) ;
}
if ( ! SortedAgentGroupChains [ GUBPNodes [ NodeToDo ] . AgentSharingGroup ] . Contains ( Dep ) & & NodesToDo . Contains ( Dep ) )
{
bPseudoReady = false ;
NonPeudoReadyAgentGroups . Add ( GUBPNodes [ NodeToDo ] . AgentSharingGroup ) ;
break ;
}
}
}
}
}
else
{
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Dependency {0} node found." , Dep ) ;
}
if ( NodesToDo . Contains ( Dep ) )
{
bReady = false ;
break ;
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Pseudodependency {0} node found." , Dep ) ;
}
if ( NodesToDo . Contains ( Dep ) )
{
bPseudoReady = false ;
break ;
}
}
2015-02-10 14:58:32 -05:00
foreach ( var Dep in GUBPNodes [ NodeToDo ] . CompletedDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Completed Dependency {0} node found." , Dep ) ;
}
if ( NodesToDo . Contains ( Dep ) )
{
bCompReady = false ;
break ;
}
}
2014-08-22 13:39:55 -04:00
}
var Priority = GUBPNodes [ NodeToDo ] . Priority ( ) ;
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
if ( bReady & & BestNode ! = "" )
{
if ( String . Compare ( GetControllingTriggerDotName ( BestNode ) , GetControllingTriggerDotName ( NodeToDo ) ) < 0 ) //sorted by controlling trigger
{
bReady = false ;
}
else if ( String . Compare ( GetControllingTriggerDotName ( BestNode ) , GetControllingTriggerDotName ( NodeToDo ) ) = = 0 ) //sorted by controlling trigger
{
if ( GUBPNodes [ BestNode ] . IsSticky ( ) & & ! GUBPNodes [ NodeToDo ] . IsSticky ( ) ) //sticky nodes first
{
bReady = false ;
}
else if ( GUBPNodes [ BestNode ] . IsSticky ( ) = = GUBPNodes [ NodeToDo ] . IsSticky ( ) )
{
if ( BestPseudoReady & & ! bPseudoReady )
{
bReady = false ;
}
else if ( BestPseudoReady = = bPseudoReady )
{
bool IamLateTrigger = ! DoNotConsiderCompletion & & GUBPNodes [ NodeToDo ] . TriggerNode ( ) & & NodeToDo ! = ExplicitTrigger & & ! NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) ;
bool BestIsLateTrigger = ! DoNotConsiderCompletion & & GUBPNodes [ BestNode ] . TriggerNode ( ) & & BestNode ! = ExplicitTrigger & & ! NodeIsAlreadyComplete ( BestNode , LocalOnly ) ;
if ( BestIsLateTrigger & & ! IamLateTrigger )
{
bReady = false ;
}
else if ( BestIsLateTrigger = = IamLateTrigger )
{
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
if ( Priority < BestPriority )
{
bReady = false ;
}
else if ( Priority = = BestPriority )
{
if ( BestNode . CompareTo ( NodeToDo ) < 0 )
{
bReady = false ;
}
}
2015-02-10 14:58:32 -05:00
if ( ! bCompReady )
{
bReady = false ;
}
2014-08-22 13:39:55 -04:00
}
}
}
}
}
if ( bReady )
{
BestPriority = Priority ;
BestNode = NodeToDo ;
BestPseudoReady = bPseudoReady ;
bProgressMade = true ;
}
}
if ( bProgressMade )
{
if ( ! SubSort & & GUBPNodes [ BestNode ] . AgentSharingGroup ! = "" )
{
foreach ( var ChainNode in SortedAgentGroupChains [ GUBPNodes [ BestNode ] . AgentSharingGroup ] )
{
OrdereredToDo . Add ( ChainNode ) ;
NodesToDo . Remove ( ChainNode ) ;
}
}
else
{
OrdereredToDo . Add ( BestNode ) ;
NodesToDo . Remove ( BestNode ) ;
}
}
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
if ( ! bProgressMade & & NodesToDo . Count > 0 )
{
Log ( "Cycle in GUBP, could not resolve:" ) ;
foreach ( var NodeToDo in NodesToDo )
{
string Deps = "" ;
if ( ! SubSort & & GUBPNodes [ NodeToDo ] . AgentSharingGroup ! = "" )
{
foreach ( var ChainNode in SortedAgentGroupChains [ GUBPNodes [ NodeToDo ] . AgentSharingGroup ] )
{
foreach ( var Dep in GUBPNodes [ ChainNode ] . FullNamesOfDependencies )
{
if ( ! SortedAgentGroupChains [ GUBPNodes [ NodeToDo ] . AgentSharingGroup ] . Contains ( Dep ) & & NodesToDo . Contains ( Dep ) )
{
Deps = Deps + Dep + "[" + ChainNode + "->" + GUBPNodes [ NodeToDo ] . AgentSharingGroup + "]" + " " ;
}
}
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
if ( NodesToDo . Contains ( Dep ) )
{
Deps = Deps + Dep + " " ;
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
if ( NodesToDo . Contains ( Dep ) )
{
Deps = Deps + Dep + " " ;
}
}
Log ( " {0} deps: {1}" , NodeToDo , Deps ) ;
}
throw new AutomationException ( "Cycle in GUBP" ) ;
}
}
if ( ! SubSort )
{
var BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds ;
Log ( "Took {0}s to sort {1} nodes" , BuildDuration / 1000 , OrdereredToDo . Count ) ;
}
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
return OrdereredToDo ;
}
2014-04-28 16:25:35 -04:00
2014-08-22 13:39:55 -04:00
string GetJobStepPath ( string Dep )
{
if ( Dep ! = "Noop" & & GUBPNodes [ Dep ] . AgentSharingGroup ! = "" )
{
return "jobSteps[" + GUBPNodes [ Dep ] . AgentSharingGroup + "]/jobSteps[" + Dep + "]" ;
}
return "jobSteps[" + Dep + "]" ;
}
string GetJobStep ( string ParentPath , string Dep )
{
return ParentPath + "/" + GetJobStepPath ( Dep ) ;
}
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
void UpdateNodeHistory ( string Node , string CLString )
{
if ( GUBPNodes [ Node ] . RunInEC ( ) & & ! GUBPNodes [ Node ] . TriggerNode ( ) & & CLString ! = "" )
{
string GameNameIfAny = GUBPNodes [ Node ] . GameNameIfAnyForTempStorage ( ) ;
string NodeStoreWildCard = StoreName . Replace ( CLString , "*" ) + "-" + GUBPNodes [ Node ] . GetFullName ( ) ;
var History = new NodeHistory ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
History . AllStarted = ConvertCLToIntList ( FindTempStorageManifests ( CmdEnv , NodeStoreWildCard + StartedTempStorageSuffix , false , true , GameNameIfAny ) ) ;
History . AllSucceeded = ConvertCLToIntList ( FindTempStorageManifests ( CmdEnv , NodeStoreWildCard + SucceededTempStorageSuffix , false , true , GameNameIfAny ) ) ;
History . AllFailed = ConvertCLToIntList ( FindTempStorageManifests ( CmdEnv , NodeStoreWildCard + FailedTempStorageSuffix , false , true , GameNameIfAny ) ) ;
2014-04-23 18:43:04 -04:00
2014-08-22 13:39:55 -04:00
if ( History . AllFailed . Count > 0 )
{
History . LastFailed = History . AllFailed [ History . AllFailed . Count - 1 ] ;
}
if ( History . AllSucceeded . Count > 0 )
{
History . LastSucceeded = History . AllSucceeded [ History . AllSucceeded . Count - 1 ] ;
2014-04-23 18:43:04 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Failed in History . AllFailed )
{
if ( Failed > History . LastSucceeded )
{
History . Failed . Add ( Failed ) ;
History . FailedString = GUBPNode . MergeSpaceStrings ( History . FailedString , String . Format ( "{0}" , Failed ) ) ;
}
}
foreach ( var Started in History . AllStarted )
{
if ( Started > History . LastSucceeded & & ! History . Failed . Contains ( Started ) )
{
History . InProgress . Add ( Started ) ;
History . InProgressString = GUBPNode . MergeSpaceStrings ( History . InProgressString , String . Format ( "{0}" , Started ) ) ;
}
2014-12-18 13:47:28 -05:00
}
2014-08-22 13:39:55 -04:00
}
2014-12-18 13:47:28 -05:00
if ( GUBPNodesHistory . ContainsKey ( Node ) )
{
GUBPNodesHistory . Remove ( Node ) ;
}
GUBPNodesHistory . Add ( Node , History ) ;
2014-08-22 13:39:55 -04:00
}
}
2015-03-03 07:56:18 -05:00
void GetFailureEmails ( string NodeToDo , string CLString , bool OnlyLateUpdates = false )
{
2015-04-16 19:15:28 -04:00
var StartTime = DateTime . UtcNow ;
string EMails ;
2015-03-03 07:56:18 -05:00
string FailCauserEMails = "" ;
string EMailNote = "" ;
bool SendSuccessForGreenAfterRed = false ;
int NumPeople = 0 ;
if ( GUBPNodesHistory . ContainsKey ( NodeToDo ) )
{
var History = GUBPNodesHistory [ NodeToDo ] ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/LastGreen/{0}\" \"{1}\"" , NodeToDo , History . LastSucceeded ) , true ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/LastGreen/{0}\" \"{1}\"" , NodeToDo , History . FailedString ) , true ) ;
if ( History . LastSucceeded > 0 & & History . LastSucceeded < P4Env . Changelist )
{
int LastNonDuplicateFail = P4Env . Changelist ;
try
{
if ( OnlyLateUpdates )
{
LastNonDuplicateFail = FindLastNonDuplicateFail ( NodeToDo , CLString ) ;
if ( LastNonDuplicateFail < P4Env . Changelist )
{
Log ( "*** Red-after-red spam reduction, changed CL {0} to CL {1} because the errors didn't change." , P4Env . Changelist , LastNonDuplicateFail ) ;
}
}
}
catch ( Exception Ex )
{
LastNonDuplicateFail = P4Env . Changelist ;
Log ( System . Diagnostics . TraceEventType . Warning , "Failed to FindLastNonDuplicateFail." ) ;
Log ( System . Diagnostics . TraceEventType . Warning , LogUtils . FormatException ( Ex ) ) ;
}
var ChangeRecords = GetChanges ( History . LastSucceeded , LastNonDuplicateFail , History . LastSucceeded ) ;
foreach ( var Record in ChangeRecords )
{
FailCauserEMails = GUBPNode . MergeSpaceStrings ( FailCauserEMails , Record . UserEmail ) ;
}
if ( ! String . IsNullOrEmpty ( FailCauserEMails ) )
{
NumPeople + + ;
foreach ( var AChar in FailCauserEMails . ToCharArray ( ) )
{
if ( AChar = = ' ' )
{
NumPeople + + ;
}
}
if ( NumPeople > 50 )
{
EMailNote = String . Format ( "This step has been broken for more than 50 changes. It last succeeded at CL {0}. " , History . LastSucceeded ) ;
}
}
}
else if ( History . LastSucceeded < = 0 )
{
EMailNote = String . Format ( "This step has been broken for more than a few days, so there is no record of it ever succeeding. " ) ;
}
if ( EMailNote ! = "" & & ! String . IsNullOrEmpty ( History . FailedString ) )
{
EMailNote + = String . Format ( "It has failed at CLs {0}. " , History . FailedString ) ;
}
if ( EMailNote ! = "" & & ! String . IsNullOrEmpty ( History . InProgressString ) )
{
EMailNote + = String . Format ( "These CLs are being built right now {0}. " , History . InProgressString ) ;
}
if ( History . LastSucceeded > 0 & & History . LastSucceeded < P4Env . Changelist & & History . LastFailed > History . LastSucceeded & & History . LastFailed < P4Env . Changelist )
{
SendSuccessForGreenAfterRed = ParseParam ( "CIS" ) ;
}
}
else
{
RunECTool ( String . Format ( "setProperty \"/myWorkflow/LastGreen/{0}\" \"{1}\"" , NodeToDo , "0" ) ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/RedsSince/{0}\" \"{1}\"" , NodeToDo , "" ) ) ;
}
RunECTool ( String . Format ( "setProperty \"/myWorkflow/FailCausers/{0}\" \"{1}\"" , NodeToDo , FailCauserEMails ) ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/EmailNotes/{0}\" \"{1}\"" , NodeToDo , EMailNote ) ) ;
{
2015-04-16 19:15:28 -04:00
var AdditionalEmails = "" ;
2015-03-03 07:56:18 -05:00
string Causers = "" ;
if ( ParseParam ( "CIS" ) & & ! GUBPNodes [ NodeToDo ] . SendSuccessEmail ( ) & & ! GUBPNodes [ NodeToDo ] . TriggerNode ( ) )
{
Causers = FailCauserEMails ;
}
2015-04-16 19:15:28 -04:00
string AddEmails = ParseParamValue ( "AddEmails" ) ;
if ( ! String . IsNullOrEmpty ( AddEmails ) )
{
AdditionalEmails = GUBPNode . MergeSpaceStrings ( AddEmails , AdditionalEmails ) ;
}
EMails = GetEMailListForNode ( this , NodeToDo , AdditionalEmails , Causers ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/FailEmails/{0}\" \"{1}\"" , NodeToDo , EMails ) ) ;
2015-03-03 07:56:18 -05:00
}
if ( GUBPNodes [ NodeToDo ] . SendSuccessEmail ( ) | | SendSuccessForGreenAfterRed )
{
RunECTool ( String . Format ( "setProperty \"/myWorkflow/SendSuccessEmail/{0}\" \"{1}\"" , NodeToDo , "1" ) ) ;
}
else
{
RunECTool ( String . Format ( "setProperty \"/myWorkflow/SendSuccessEmail/{0}\" \"{1}\"" , NodeToDo , "0" ) ) ;
}
}
2014-04-23 18:43:04 -04:00
2014-08-22 13:39:55 -04:00
bool HashSetEqual ( HashSet < string > A , HashSet < string > B )
{
if ( A . Count ! = B . Count )
{
return false ;
}
foreach ( var Elem in A )
{
if ( ! B . Contains ( Elem ) )
{
return false ;
}
}
foreach ( var Elem in B )
{
if ( ! A . Contains ( Elem ) )
{
return false ;
}
}
return true ;
}
2014-04-23 18:43:04 -04:00
2014-08-22 13:39:55 -04:00
int FindLastNonDuplicateFail ( string NodeToDo , string CLString )
{
var History = GUBPNodesHistory [ NodeToDo ] ;
int Result = P4Env . Changelist ;
2014-06-16 12:05:56 -04:00
2014-08-22 13:39:55 -04:00
string GameNameIfAny = GUBPNodes [ NodeToDo ] . GameNameIfAnyForTempStorage ( ) ;
string NodeStore = StoreName + "-" + GUBPNodes [ NodeToDo ] . GetFullName ( ) + FailedTempStorageSuffix ;
2014-06-16 12:05:56 -04:00
2014-08-22 13:39:55 -04:00
var BackwardsFails = new List < int > ( History . AllFailed ) ;
BackwardsFails . Add ( P4Env . Changelist ) ;
BackwardsFails . Sort ( ) ;
BackwardsFails . Reverse ( ) ;
HashSet < string > CurrentErrors = null ;
foreach ( var CL in BackwardsFails )
{
if ( CL > P4Env . Changelist )
{
continue ;
}
if ( CL < = History . LastSucceeded )
{
break ;
}
var ThisNodeStore = NodeStore . Replace ( CLString , String . Format ( "{0}" , CL ) ) ;
DeleteLocalTempStorage ( CmdEnv , ThisNodeStore , true ) ; // these all clash locally, which is fine we just retrieve them from shared
2014-06-16 12:05:56 -04:00
2014-08-22 13:39:55 -04:00
List < string > Files = null ;
try
{
bool WasLocal ;
Files = RetrieveFromTempStorage ( CmdEnv , ThisNodeStore , out WasLocal , GameNameIfAny ) ; // this will fail on our CL if we didn't fail or we are just setting up the branch
}
catch ( Exception )
{
}
if ( Files = = null )
{
continue ;
}
if ( Files . Count ! = 1 )
{
throw new AutomationException ( "Unexpected number of files for fail record {0}" , Files . Count ) ;
}
string ErrorFile = Files [ 0 ] ;
var ThisErrors = ECJobPropsUtils . ErrorsFromProps ( ErrorFile ) ;
if ( CurrentErrors = = null )
{
CurrentErrors = ThisErrors ;
}
else
{
if ( CurrentErrors . Count = = 0 | | ! HashSetEqual ( CurrentErrors , ThisErrors ) )
{
break ;
}
Result = CL ;
}
}
return Result ;
}
List < string > GetECPropsForNode ( string NodeToDo , string CLString , out string EMails , bool OnlyLateUpdates = false )
{
var StartTime = DateTime . UtcNow ;
2014-06-16 12:46:07 -04:00
2014-08-22 13:39:55 -04:00
var ECProps = new List < string > ( ) ;
2015-03-04 08:31:40 -05:00
EMails = "" ;
var AdditonalEmails = "" ;
string Causers = "" ;
string AddEmails = ParseParamValue ( "AddEmails" ) ;
if ( ! String . IsNullOrEmpty ( AddEmails ) )
{
AdditonalEmails = GUBPNode . MergeSpaceStrings ( AddEmails , AdditonalEmails ) ;
}
EMails = GetEMailListForNode ( this , NodeToDo , AdditonalEmails , Causers ) ;
2015-04-16 19:15:28 -04:00
ECProps . Add ( "FailEmails/" + NodeToDo + "=" + EMails ) ;
2015-03-04 08:31:40 -05:00
if ( ! OnlyLateUpdates )
{
2015-01-26 15:38:03 -05:00
string AgentReq = GUBPNodes [ NodeToDo ] . ECAgentString ( ) ;
2015-03-03 07:56:18 -05:00
if ( ParseParamValue ( "AgentOverride" ) ! = "" & & ! GUBPNodes [ NodeToDo ] . GetFullName ( ) . Contains ( "OnMac" ) )
2015-01-26 15:38:03 -05:00
{
AgentReq = ParseParamValue ( "AgentOverride" ) ;
}
2015-03-04 08:31:40 -05:00
ECProps . Add ( string . Format ( "AgentRequirementString/{0}={1}" , NodeToDo , AgentReq ) ) ;
ECProps . Add ( string . Format ( "RequiredMemory/{0}={1}" , NodeToDo , GUBPNodes [ NodeToDo ] . AgentMemoryRequirement ( this ) ) ) ;
ECProps . Add ( string . Format ( "Timeouts/{0}={1}" , NodeToDo , GUBPNodes [ NodeToDo ] . TimeoutInMinutes ( ) ) ) ;
ECProps . Add ( string . Format ( "JobStepPath/{0}={1}" , NodeToDo , GetJobStepPath ( NodeToDo ) ) ) ;
}
2015-03-02 15:07:21 -05:00
2014-08-22 13:39:55 -04:00
var BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds ;
return ECProps ;
}
2014-04-23 18:43:04 -04:00
2014-08-22 13:39:55 -04:00
void UpdateECProps ( string NodeToDo , string CLString )
{
try
{
Log ( "Updating node props for node {0}" , NodeToDo ) ;
2015-03-02 15:07:21 -05:00
string EMails = "" ;
2014-08-22 13:39:55 -04:00
var Props = GetECPropsForNode ( NodeToDo , CLString , out EMails , true ) ;
foreach ( var Prop in Props )
{
var Parts = Prop . Split ( "=" . ToCharArray ( ) ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/{0}\" \"{1}\"" , Parts [ 0 ] , Parts [ 1 ] ) , true ) ;
2015-02-16 09:24:59 -05:00
}
2014-08-22 13:39:55 -04:00
}
catch ( Exception Ex )
{
Log ( System . Diagnostics . TraceEventType . Warning , "Failed to UpdateECProps." ) ;
Log ( System . Diagnostics . TraceEventType . Warning , LogUtils . FormatException ( Ex ) ) ;
}
}
2015-02-16 09:24:59 -05:00
void UpdateECBuildTime ( string NodeToDo , double BuildDuration )
{
try
{
Log ( "Updating duration prop for node {0}" , NodeToDo ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/NodeDuration/{0}\" \"{1}\"" , NodeToDo , BuildDuration . ToString ( ) ) ) ;
2015-02-16 14:22:20 -05:00
RunECTool ( String . Format ( "setProperty \"/myJobStep/NodeDuration\" \"{0}\"" , BuildDuration . ToString ( ) ) ) ;
2015-02-16 09:24:59 -05:00
}
catch ( Exception Ex )
{
Log ( System . Diagnostics . TraceEventType . Warning , "Failed to UpdateECBuildTime." ) ;
Log ( System . Diagnostics . TraceEventType . Warning , LogUtils . FormatException ( Ex ) ) ;
}
}
2014-04-23 18:43:04 -04:00
2014-08-22 13:39:55 -04:00
[Help("Runs one, several or all of the GUBP nodes")]
[Help(typeof(UE4Build))]
2014-09-06 13:20:05 -04:00
[Help("NoMac", "Toggle to exclude the Mac host platform, default is Win64+Mac+Linux")]
[Help("NoLinux", "Toggle to exclude the Linux (PC, 64-bit) host platform, default is Win64+Mac+Linux")]
[Help("NoPC", "Toggle to exclude the PC host platform, default is Win64+Mac+Linux")]
2014-08-22 13:39:55 -04:00
[Help("CleanLocal", "delete the local temp storage before we start")]
[Help("Store=", "Sets the name of the temp storage block, normally, this is built for you.")]
[Help("StoreSuffix=", "Tacked onto a store name constructed from CL, branch, etc")]
[Help("TimeIndex=", "An integer used to determine subsets to run based on DependentCISFrequencyQuantumShift")]
[Help("UserTimeIndex=", "An integer used to determine subsets to run based on DependentCISFrequencyQuantumShift, this one overrides TimeIndex")]
[Help("PreflightUID=", "A unique integer tag from EC used as part of the tempstorage, builds and label names to distinguish multiple attempts.")]
[Help("Node=", "Nodes to process, -node=Node1+Node2+Node3, if no nodes or games are specified, defaults to all nodes.")]
[Help("SetupNode=", "Like -Node, but only applies with CommanderJobSetupOnly")]
[Help("RelatedToNode=", "Nodes to process, -RelatedToNode=Node1+Node2+Node3, use all nodes that either depend on these nodes or these nodes depend on them.")]
[Help("SetupRelatedToNode=", "Like -RelatedToNode, but only applies with CommanderJobSetupOnly")]
[Help("OnlyNode=", "Nodes to process NO dependencies, -OnlyNode=Node1+Node2+Node3, if no nodes or games are specified, defaults to all nodes.")]
[Help("TriggerNode=", "Trigger Nodes to process, -triggernode=Node.")]
[Help("Game=", "Games to process, -game=Game1+Game2+Game3, if no games or nodes are specified, defaults to all nodes.")]
[Help("ListOnly", "List Nodes in this branch")]
[Help("SaveGraph", "Save graph as an xml file")]
[Help("CommanderJobSetupOnly", "Set up the EC branch info via ectool and quit")]
[Help("FakeEC", "don't run ectool, rather just do it locally, emulating what EC would have done.")]
[Help("Fake", "Don't actually build anything, just store a record of success as the build product for each node.")]
[Help("AllPlatforms", "Regardless of what is installed on this machine, set up the graph for all platforms; true by default on build machines.")]
[Help("SkipTriggers", "ignore all triggers")]
[Help("CL", "force the CL to something, disregarding the P4 value.")]
[Help("History", "Like ListOnly, except gives you a full history. Must have -P4 for this to work.")]
[Help("Changes", "Like history, but also shows the P4 changes. Must have -P4 for this to work.")]
[Help("AllChanges", "Like changes except includes changes before the last green. Must have -P4 for this to work.")]
[Help("EmailOnly", "Only emails the folks given in the argument.")]
[Help("AddEmails", "Add these space delimited emails too all email lists.")]
[Help("ShowDependencies", "Show node dependencies.")]
[Help("ShowECDependencies", "Show EC node dependencies instead.")]
[Help("ShowECProc", "Show EC proc names.")]
[Help("BuildRocket", "Build in rocket mode.")]
[Help("ShowECOnly", "Only show EC nodes.")]
[Help("ECProject", "From EC, the name of the project, used to get a version number.")]
[Help("CIS", "This is a CIS run, assign TimeIndex based on the history.")]
[Help("ForceIncrementalCompile", "make sure all compiles are incremental")]
[Help("AutomatedTesting", "Allow automated testing, currently disabled.")]
[Help("StompCheck", "Look for stomped build products.")]
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
public override void ExecuteBuild ( )
{
Log ( "************************* GUBP" ) ;
string PreflightShelveCLString = GetEnvVar ( "uebp_PreflightShelveCL" ) ;
if ( ( ! String . IsNullOrEmpty ( PreflightShelveCLString ) & & IsBuildMachine ) | | ParseParam ( "PreflightTest" ) )
{
Log ( "**** Preflight shelve {0}" , PreflightShelveCLString ) ;
if ( ! String . IsNullOrEmpty ( PreflightShelveCLString ) )
{
PreflightShelveCL = int . Parse ( PreflightShelveCLString ) ;
if ( PreflightShelveCL < 2000000 )
{
2015-04-13 16:43:36 -04:00
throw new AutomationException ( String . Format ( "{0} does not look like a CL" , PreflightShelveCL ) ) ;
2014-08-22 13:39:55 -04:00
}
}
bPreflightBuild = true ;
}
ECProject = ParseParamValue ( "ECProject" ) ;
if ( ECProject = = null )
{
ECProject = "" ;
2014-12-17 11:37:40 -05:00
}
2014-08-22 13:39:55 -04:00
HostPlatforms = new List < UnrealTargetPlatform > ( ) ;
if ( ! ParseParam ( "NoPC" ) )
{
HostPlatforms . Add ( UnrealTargetPlatform . Win64 ) ;
}
if ( P4Enabled )
{
2015-04-17 13:21:04 -04:00
BranchName = P4Env . BuildRootP4 ;
2014-08-22 13:39:55 -04:00
}
2015-04-17 09:59:43 -04:00
else
{
2015-04-17 13:21:04 -04:00
BranchName = ParseParamValue ( "BranchName" , "" ) ;
2015-04-17 14:13:52 -04:00
}
2015-04-17 13:21:04 -04:00
BranchOptions = GetBranchOptions ( BranchName ) ;
2014-09-05 21:50:16 -04:00
bool WithMac = ! BranchOptions . PlatformsToRemove . Contains ( UnrealTargetPlatform . Mac ) ;
2014-08-22 13:39:55 -04:00
if ( ParseParam ( "NoMac" ) )
{
WithMac = false ;
}
if ( WithMac )
{
HostPlatforms . Add ( UnrealTargetPlatform . Mac ) ;
}
2014-04-23 17:37:20 -04:00
2014-09-05 21:50:16 -04:00
bool WithLinux = ! BranchOptions . PlatformsToRemove . Contains ( UnrealTargetPlatform . Linux ) ;
2015-01-13 12:59:24 -05:00
bool WithoutLinux = ParseParam ( "NoLinux" ) ;
2014-09-06 13:20:05 -04:00
// @TODO: exclude temporarily unless running on a Linux machine to prevent spurious GUBP failures
if ( UnrealBuildTool . BuildHostPlatform . Current . Platform ! = UnrealTargetPlatform . Linux | | ParseParam ( "NoLinux" ) )
2014-09-05 21:50:16 -04:00
{
WithLinux = false ;
}
if ( WithLinux )
{
HostPlatforms . Add ( UnrealTargetPlatform . Linux ) ;
}
2014-08-22 13:39:55 -04:00
bForceIncrementalCompile = ParseParam ( "ForceIncrementalCompile" ) ;
2014-09-10 12:30:17 -04:00
bool bNoAutomatedTesting = ParseParam ( "NoAutomatedTesting" ) | | BranchOptions . bNoAutomatedTesting ;
2014-08-22 13:39:55 -04:00
StoreName = ParseParamValue ( "Store" ) ;
string StoreSuffix = ParseParamValue ( "StoreSuffix" , "" ) ;
2014-12-17 11:37:40 -05:00
2014-08-22 13:39:55 -04:00
if ( bPreflightBuild )
{
int PreflightUID = ParseParamInt ( "PreflightUID" , 0 ) ;
PreflightMangleSuffix = String . Format ( "-PF-{0}-{1}" , PreflightShelveCL , PreflightUID ) ;
StoreSuffix = StoreSuffix + PreflightMangleSuffix ;
}
CL = ParseParamInt ( "CL" , 0 ) ;
bool bCleanLocalTempStorage = ParseParam ( "CleanLocal" ) ;
bool bChanges = ParseParam ( "Changes" ) | | ParseParam ( "AllChanges" ) ;
bool bHistory = ParseParam ( "History" ) | | bChanges ;
bool bListOnly = ParseParam ( "ListOnly" ) | | bHistory ;
2015-02-10 14:58:32 -05:00
bool bSkipTriggers = ParseParam ( "SkipTriggers" ) ;
2014-08-22 13:39:55 -04:00
bFake = ParseParam ( "fake" ) ;
bool bFakeEC = ParseParam ( "FakeEC" ) ;
TimeIndex = ParseParamInt ( "TimeIndex" , 0 ) ;
if ( TimeIndex = = 0 )
{
TimeIndex = ParseParamInt ( "UserTimeIndex" , 0 ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
bNoIOSOnPC = HostPlatforms . Contains ( UnrealTargetPlatform . Mac ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
bool bSaveSharedTempStorage = false ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( bHistory & & ! P4Enabled )
{
throw new AutomationException ( "-Changes and -History require -P4." ) ;
}
bool LocalOnly = true ;
string CLString = "" ;
if ( String . IsNullOrEmpty ( StoreName ) )
{
if ( P4Enabled )
{
if ( CL = = 0 )
{
CL = P4Env . Changelist ;
}
CLString = String . Format ( "{0}" , CL ) ;
StoreName = P4Env . BuildRootEscaped + "-" + CLString ;
bSaveSharedTempStorage = CommandUtils . IsBuildMachine ;
LocalOnly = false ;
}
else
{
StoreName = "TempLocal" ;
bSaveSharedTempStorage = false ;
}
}
StoreName = StoreName + StoreSuffix ;
if ( bFakeEC )
{
LocalOnly = true ;
}
if ( bSaveSharedTempStorage )
{
if ( ! HaveSharedTempStorage ( true ) )
{
throw new AutomationException ( "Request to save to temp storage, but {0} is unavailable." , UE4TempStorageDirectory ( ) ) ;
}
bSignBuildProducts = true ;
}
else if ( ! LocalOnly & & ! HaveSharedTempStorage ( false ) )
{
Log ( "Looks like we want to use shared temp storage, but since we don't have it, we won't use it." ) ;
LocalOnly = true ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
bool CommanderSetup = ParseParam ( "CommanderJobSetupOnly" ) ;
string ExplicitTrigger = "" ;
if ( CommanderSetup )
{
ExplicitTrigger = ParseParamValue ( "TriggerNode" ) ;
if ( ExplicitTrigger = = null )
{
ExplicitTrigger = "" ;
}
}
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
if ( ParseParam ( "CIS" ) & & ExplicitTrigger = = "" & & CommanderSetup ) // explicit triggers will already have a time index assigned
{
if ( ! P4Enabled )
{
throw new AutomationException ( "Can't have -CIS without P4 support" ) ;
}
var P4IndexFileP4 = CombinePaths ( PathSeparator . Slash , CommandUtils . P4Env . BuildRootP4 , "Engine" , "Build" , "CISCounter.txt" ) ;
var P4IndexFileLocal = CombinePaths ( CmdEnv . LocalRoot , "Engine" , "Build" , "CISCounter.txt" ) ;
int Retry = 0 ;
bool bDone = false ;
while ( + + Retry < 20 & & ! bDone )
{
int NowMinutes = ( int ) ( ( DateTime . UtcNow - new DateTime ( 2014 , 1 , 1 ) ) . TotalMinutes ) ;
if ( NowMinutes < 3 * 30 * 24 )
{
throw new AutomationException ( "bad date calc" ) ;
}
if ( ! FileExists_NoExceptions ( P4IndexFileLocal ) )
{
Log ( "{0} doesn't exist, checking in a new one" , P4IndexFileP4 ) ;
WriteAllText ( P4IndexFileLocal , "-1 0" ) ;
int WorkingCL = - 1 ;
try
{
2014-04-02 18:09:23 -04:00
WorkingCL = P4 . CreateChange ( P4Env . Client , "Adding new CIS Counter" ) ;
P4 . Add ( WorkingCL , P4IndexFileP4 ) ;
2014-08-22 13:39:55 -04:00
int SubmittedCL ;
2014-04-02 18:09:23 -04:00
P4 . Submit ( WorkingCL , out SubmittedCL ) ;
2014-08-22 13:39:55 -04:00
}
catch ( Exception )
{
Log ( "Add of CIS counter failed, assuming it now exists." ) ;
if ( WorkingCL > 0 )
{
2014-04-02 18:09:23 -04:00
P4 . DeleteChange ( WorkingCL ) ;
2014-08-22 13:39:55 -04:00
}
}
}
2014-04-02 18:09:23 -04:00
P4 . Sync ( "-f " + P4IndexFileP4 + "#head" ) ;
2014-08-22 13:39:55 -04:00
if ( ! FileExists_NoExceptions ( P4IndexFileLocal ) )
{
Log ( "{0} doesn't exist, checking in a new one" , P4IndexFileP4 ) ;
WriteAllText ( P4IndexFileLocal , "-1 0" ) ;
int WorkingCL = - 1 ;
try
{
WorkingCL = P4 . CreateChange ( P4Env . Client , "Adding new CIS Counter" ) ;
P4 . Add ( WorkingCL , P4IndexFileP4 ) ;
int SubmittedCL ;
P4 . Submit ( WorkingCL , out SubmittedCL ) ;
}
catch ( Exception )
{
Log ( "Add of CIS counter failed, assuming it now exists." ) ;
if ( WorkingCL > 0 )
{
P4 . DeleteChange ( WorkingCL ) ;
}
}
}
var Data = ReadAllText ( P4IndexFileLocal ) ;
var Parts = Data . Split ( " " . ToCharArray ( ) ) ;
int Index = int . Parse ( Parts [ 0 ] ) ;
int Minutes = int . Parse ( Parts [ 1 ] ) ;
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
int DeltaMinutes = NowMinutes - Minutes ;
2015-02-10 14:58:32 -05:00
2015-01-27 14:24:55 -05:00
int TimeQuantum = 20 ;
if ( BranchOptions . QuantumOverride ! = 0 )
{
TimeQuantum = BranchOptions . QuantumOverride ;
}
2014-08-22 13:39:55 -04:00
int NewIndex = Index + 1 ;
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
if ( DeltaMinutes > TimeQuantum * 2 )
{
if ( DeltaMinutes > TimeQuantum * ( 1 < < 8 ) )
{
// it has been forever, lets just start over
NewIndex = 0 ;
}
else
{
int WorkingIndex = NewIndex + 1 ;
for ( int WorkingDelta = DeltaMinutes - TimeQuantum ; WorkingDelta > 0 ; WorkingDelta - = TimeQuantum , WorkingIndex + + )
{
if ( CountZeros ( NewIndex ) < CountZeros ( WorkingIndex ) )
{
NewIndex = WorkingIndex ;
}
}
}
}
{
var Line = String . Format ( "{0} {1}" , NewIndex , NowMinutes ) ;
Log ( "Attempting to write {0} with {1}" , P4IndexFileP4 , Line ) ;
int WorkingCL = - 1 ;
try
{
2014-04-02 18:09:23 -04:00
WorkingCL = P4 . CreateChange ( P4Env . Client , "Updating CIS Counter" ) ;
P4 . Edit ( WorkingCL , P4IndexFileP4 ) ;
2014-08-22 13:39:55 -04:00
WriteAllText ( P4IndexFileLocal , Line ) ;
int SubmittedCL ;
2014-04-02 18:09:23 -04:00
P4 . Submit ( WorkingCL , out SubmittedCL ) ;
2014-08-22 13:39:55 -04:00
bDone = true ;
TimeIndex = NewIndex ;
}
catch ( Exception )
{
Log ( "Edit of CIS counter failed, assuming someone else checked in, retrying." ) ;
if ( WorkingCL > 0 )
{
2014-04-02 18:09:23 -04:00
P4 . DeleteChange ( WorkingCL ) ;
2014-08-22 13:39:55 -04:00
}
System . Threading . Thread . Sleep ( 30000 ) ;
}
}
}
if ( ! bDone )
{
throw new AutomationException ( "Failed to update the CIS counter after 20 tries." ) ;
}
Log ( "Setting TimeIndex to {0}" , TimeIndex ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Log ( "************************* CL: {0}" , CL ) ;
Log ( "************************* P4Enabled: {0}" , P4Enabled ) ;
foreach ( var HostPlatform in HostPlatforms )
{
Log ( "************************* HostPlatform: {0}" , HostPlatform . ToString ( ) ) ;
}
Log ( "************************* StoreName: {0}" , StoreName . ToString ( ) ) ;
Log ( "************************* bCleanLocalTempStorage: {0}" , bCleanLocalTempStorage ) ;
Log ( "************************* bSkipTriggers: {0}" , bSkipTriggers ) ;
Log ( "************************* bSaveSharedTempStorage: {0}" , bSaveSharedTempStorage ) ;
Log ( "************************* bSignBuildProducts: {0}" , bSignBuildProducts ) ;
Log ( "************************* bFake: {0}" , bFake ) ;
Log ( "************************* bFakeEC: {0}" , bFakeEC ) ;
Log ( "************************* bHistory: {0}" , bHistory ) ;
Log ( "************************* TimeIndex: {0}" , TimeIndex ) ;
2014-03-14 14:13:41 -04:00
2015-04-21 15:21:51 -04:00
GUBPNodes = new Dictionary < string , GUBPNode > ( ) ;
Branch = new BranchInfo ( HostPlatforms ) ;
2014-08-22 13:39:55 -04:00
if ( IsBuildMachine | | ParseParam ( "AllPlatforms" ) )
{
ActivePlatforms = new List < UnrealTargetPlatform > ( ) ;
2015-04-27 14:26:12 -04:00
List < BranchInfo . BranchUProject > BranchCodeProjects = new List < BranchInfo . BranchUProject > ( ) ;
BranchCodeProjects . Add ( Branch . BaseEngineProject ) ;
BranchCodeProjects . AddRange ( Branch . CodeProjects ) ;
BranchCodeProjects . RemoveAll ( Project = > BranchOptions . ExcludeNodes . Contains ( Project . GameName ) ) ;
foreach ( var GameProj in BranchCodeProjects )
2014-08-22 13:39:55 -04:00
{
2015-04-27 14:26:12 -04:00
foreach ( var Kind in BranchInfo . MonolithicKinds )
2014-08-22 13:39:55 -04:00
{
2015-04-27 14:26:12 -04:00
if ( GameProj . Properties . Targets . ContainsKey ( Kind ) )
2014-08-22 13:39:55 -04:00
{
2015-04-27 14:26:12 -04:00
var Target = GameProj . Properties . Targets [ Kind ] ;
foreach ( var HostPlatform in HostPlatforms )
2014-08-22 13:39:55 -04:00
{
2015-04-27 14:26:12 -04:00
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
var AdditionalPlatforms = Target . Rules . GUBP_GetBuildOnlyPlatforms_MonolithicOnly ( HostPlatform ) ;
var AllPlatforms = Platforms . Union ( AdditionalPlatforms ) ;
foreach ( var Plat in AllPlatforms )
2014-08-22 13:39:55 -04:00
{
2015-04-27 14:26:12 -04:00
if ( Target . Rules . SupportsPlatform ( Plat ) & & ! ActivePlatforms . Contains ( Plat ) )
2014-08-22 13:39:55 -04:00
{
2015-04-27 14:26:12 -04:00
ActivePlatforms . Add ( Plat ) ;
2014-08-22 13:39:55 -04:00
}
}
}
}
}
2015-04-27 14:26:12 -04:00
}
2014-08-22 13:39:55 -04:00
}
else
{
2014-09-12 15:56:47 -04:00
ActivePlatforms = new List < UnrealTargetPlatform > ( CommandUtils . KnownTargetPlatforms ) ;
2014-08-22 13:39:55 -04:00
}
var SupportedPlatforms = new List < UnrealTargetPlatform > ( ) ;
foreach ( var Plat in ActivePlatforms )
{
if ( ! BranchOptions . PlatformsToRemove . Contains ( Plat ) )
{
SupportedPlatforms . Add ( Plat ) ;
}
}
ActivePlatforms = SupportedPlatforms ;
foreach ( var Plat in ActivePlatforms )
{
Log ( "Active Platform: {0}" , Plat . ToString ( ) ) ;
}
2014-03-14 14:13:41 -04:00
2014-09-05 21:50:16 -04:00
if ( HostPlatforms . Count > = 2 )
2014-08-22 13:39:55 -04:00
{
// make sure each project is set up with the right assumptions on monolithics that prefer a platform.
foreach ( var CodeProj in Branch . CodeProjects )
{
var OptionsMac = CodeProj . Options ( UnrealTargetPlatform . Mac ) ;
var OptionsPC = CodeProj . Options ( UnrealTargetPlatform . Win64 ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var MacMonos = GetMonolithicPlatformsForUProject ( UnrealTargetPlatform . Mac , CodeProj , false ) ;
var PCMonos = GetMonolithicPlatformsForUProject ( UnrealTargetPlatform . Win64 , CodeProj , false ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( ! OptionsMac . bIsPromotable & & OptionsPC . bIsPromotable & &
( MacMonos . Contains ( UnrealTargetPlatform . IOS ) | | PCMonos . Contains ( UnrealTargetPlatform . IOS ) ) )
{
throw new AutomationException ( "Project {0} is promotable for PC, not promotable for Mac and uses IOS monothics. Since Mac is the preferred platform for IOS, please add Mac as a promotable platform." , CodeProj . GameName ) ;
}
if ( OptionsMac . bIsPromotable & & ! OptionsPC . bIsPromotable & &
( MacMonos . Contains ( UnrealTargetPlatform . Android ) | | PCMonos . Contains ( UnrealTargetPlatform . Android ) ) )
{
throw new AutomationException ( "Project {0} is not promotable for PC, promotable for Mac and uses Android monothics. Since PC is the preferred platform for Android, please add PC as a promotable platform." , CodeProj . GameName ) ;
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
AddNode ( new VersionFilesNode ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var HostPlatform in HostPlatforms )
{
2015-02-24 18:49:02 -05:00
AddNode ( new ToolsForCompileNode ( HostPlatform ) ) ;
if ( ! BranchOptions . ExcludePlatformsForEditor . Contains ( HostPlatform ) )
2015-01-06 10:24:25 -05:00
{
2015-02-24 18:49:02 -05:00
AddNode ( new RootEditorNode ( HostPlatform ) ) ;
2015-05-17 09:45:42 -04:00
AddNode ( new ToolsNode ( this , HostPlatform ) ) ;
AddNode ( new InternalToolsNode ( this , HostPlatform ) ) ;
if ( HostPlatform = = UnrealTargetPlatform . Win64 & & ActivePlatforms . Contains ( UnrealTargetPlatform . Linux ) )
2014-09-18 14:24:42 -04:00
{
2015-02-24 18:49:02 -05:00
if ( ! BranchOptions . ExcludePlatformsForEditor . Contains ( UnrealTargetPlatform . Linux ) )
{
AddNode ( new ToolsCrossCompileNode ( HostPlatform ) ) ;
}
}
foreach ( var ProgramTarget in Branch . BaseEngineProject . Properties . Programs )
{
bool bInternalOnly ;
2014-09-18 14:24:42 -04:00
bool SeparateNode ;
2015-01-06 10:24:25 -05:00
bool CrossCompile ;
2014-09-18 14:24:42 -04:00
2015-05-16 18:28:09 -04:00
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithTools ( HostPlatform , out bInternalOnly , out SeparateNode , out CrossCompile ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) & & SeparateNode & & ! BranchOptions . ExcludeNodes . Contains ( ProgramTarget . TargetName ) )
2014-09-18 14:24:42 -04:00
{
2015-02-24 18:49:02 -05:00
if ( bInternalOnly )
2014-09-18 14:24:42 -04:00
{
2015-02-24 18:49:02 -05:00
AddNode ( new SingleInternalToolsNode ( HostPlatform , ProgramTarget ) ) ;
2014-09-18 14:24:42 -04:00
}
else
{
2014-09-22 12:13:56 -04:00
AddNode ( new SingleToolsNode ( HostPlatform , ProgramTarget ) ) ;
2015-02-24 18:49:02 -05:00
}
2014-09-18 14:24:42 -04:00
}
2015-02-24 18:49:02 -05:00
if ( ProgramTarget . Rules . GUBP_IncludeNonUnityToolTest ( ) )
2014-09-22 12:13:56 -04:00
{
AddNode ( new NonUnityToolNode ( HostPlatform , ProgramTarget ) ) ;
}
2014-09-18 14:24:42 -04:00
}
2015-02-24 18:49:02 -05:00
foreach ( var CodeProj in Branch . CodeProjects )
{
foreach ( var ProgramTarget in CodeProj . Properties . Programs )
{
bool bInternalNodeOnly ;
bool SeparateNode ;
bool CrossCompile ;
2015-05-16 18:28:09 -04:00
if ( ProgramTarget . Rules . GUBP_AlwaysBuildWithTools ( HostPlatform , out bInternalNodeOnly , out SeparateNode , out CrossCompile ) & & ProgramTarget . Rules . SupportsPlatform ( HostPlatform ) & & SeparateNode & & ! BranchOptions . ExcludeNodes . Contains ( ProgramTarget . TargetName ) )
2015-02-24 18:49:02 -05:00
{
if ( bInternalNodeOnly )
{
AddNode ( new SingleInternalToolsNode ( HostPlatform , ProgramTarget ) ) ;
}
else
{
AddNode ( new SingleToolsNode ( HostPlatform , ProgramTarget ) ) ;
}
}
if ( ProgramTarget . Rules . GUBP_IncludeNonUnityToolTest ( ) )
{
AddNode ( new NonUnityToolNode ( HostPlatform , ProgramTarget ) ) ;
}
}
}
AddNode ( new EditorAndToolsNode ( this , HostPlatform ) ) ;
if ( bOrthogonalizeEditorPlatforms )
{
foreach ( var Plat in ActivePlatforms )
{
if ( Plat ! = HostPlatform & & Plat ! = GetAltHostPlatform ( HostPlatform ) )
{
if ( Platform . Platforms [ HostPlatform ] . CanHostPlatform ( Plat ) )
{
AddNode ( new EditorPlatformNode ( HostPlatform , Plat ) ) ;
}
}
}
}
2014-09-18 14:24:42 -04:00
}
2014-04-23 17:51:55 -04:00
2014-08-22 13:39:55 -04:00
bool DoASharedPromotable = false ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
int NumSharedCode = 0 ;
foreach ( var CodeProj in Branch . CodeProjects )
{
var Options = CodeProj . Options ( HostPlatform ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( Options . bIsPromotable & & ! Options . bSeparateGamePromotion )
{
NumSharedCode + + ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var NonCodeProjectNames = new Dictionary < string , List < UnrealTargetPlatform > > ( ) ;
var NonCodeFormalBuilds = new Dictionary < string , List < TargetRules . GUBPFormalBuild > > ( ) ;
{
var Target = Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Codeless in Target . Rules . GUBP_NonCodeProjects_BaseEditorTypeOnly ( HostPlatform ) )
{
var Proj = Branch . FindGame ( Codeless . Key ) ;
if ( Proj = = null )
{
Log ( System . Diagnostics . TraceEventType . Information , "{0} was listed as a codeless project by GUBP_NonCodeProjects_BaseEditorTypeOnly, however it does not exist in this branch." , Codeless . Key ) ;
}
else if ( Proj . Properties . bIsCodeBasedProject )
{
2015-04-08 16:16:23 -04:00
if ( ! Branch . NonCodeProjects . Contains ( Proj ) )
{
Branch . NonCodeProjects . Add ( Proj ) ;
NonCodeProjectNames . Add ( Codeless . Key , Codeless . Value ) ;
}
2014-08-22 13:39:55 -04:00
}
else
{
NonCodeProjectNames . Add ( Codeless . Key , Codeless . Value ) ;
}
}
2014-04-23 18:18:41 -04:00
2014-08-22 13:39:55 -04:00
var TempNonCodeFormalBuilds = Target . Rules . GUBP_GetNonCodeFormalBuilds_BaseEditorTypeOnly ( ) ;
var HostMonos = GetMonolithicPlatformsForUProject ( HostPlatform , Branch . BaseEngineProject , true ) ;
2014-04-23 18:18:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Codeless in TempNonCodeFormalBuilds )
{
if ( NonCodeProjectNames . ContainsKey ( Codeless . Key ) )
{
var PlatList = Codeless . Value ;
var NewPlatList = new List < TargetRules . GUBPFormalBuild > ( ) ;
foreach ( var PlatPair in PlatList )
{
if ( HostMonos . Contains ( PlatPair . TargetPlatform ) )
{
NewPlatList . Add ( PlatPair ) ;
}
}
if ( NewPlatList . Count > 0 )
{
NonCodeFormalBuilds . Add ( Codeless . Key , NewPlatList ) ;
}
}
else
{
Log ( System . Diagnostics . TraceEventType . Information , "{0} was listed as a codeless formal build GUBP_GetNonCodeFormalBuilds_BaseEditorTypeOnly, however it does not exist in this branch." , Codeless . Key ) ;
}
}
}
2014-04-29 21:52:22 -04:00
2014-08-22 13:39:55 -04:00
DoASharedPromotable = NumSharedCode > 0 | | NonCodeProjectNames . Count > 0 | | NonCodeFormalBuilds . Count > 0 ;
2014-04-29 21:52:22 -04:00
2015-02-25 09:59:42 -05:00
AddNode ( new NonUnityTestNode ( HostPlatform ) ) ;
2014-08-22 13:39:55 -04:00
if ( DoASharedPromotable )
{
var AgentSharingGroup = "Shared_EditorTests" + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) ;
2014-04-29 21:52:22 -04:00
2014-08-22 13:39:55 -04:00
var Options = Branch . BaseEngineProject . Options ( HostPlatform ) ;
2014-04-29 21:52:22 -04:00
2014-08-22 13:39:55 -04:00
if ( ! Options . bIsPromotable | | Options . bSeparateGamePromotion )
{
throw new AutomationException ( "We assume that if we have shared promotable, the base engine is in it." ) ;
}
2014-04-29 21:52:22 -04:00
2014-09-05 21:50:16 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Win64 ) //temp hack till automated testing works on other platforms than Win64
2014-08-22 13:39:55 -04:00
{
2014-05-02 10:44:27 -04:00
2014-08-22 13:39:55 -04:00
var EditorTests = Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Editor ] . Rules . GUBP_GetEditorTests_EditorTypeOnly ( HostPlatform ) ;
var EditorTestNodes = new List < string > ( ) ;
foreach ( var Test in EditorTests )
{
if ( ! bNoAutomatedTesting )
2014-10-15 08:26:52 -04:00
{
2014-08-22 13:39:55 -04:00
EditorTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , Branch . BaseEngineProject , Test . Key , Test . Value , AgentSharingGroup ) ) ) ;
foreach ( var NonCodeProject in Branch . NonCodeProjects )
{
if ( ! NonCodeProjectNames . ContainsKey ( NonCodeProject . GameName ) )
{
continue ;
}
if ( HostPlatform = = UnrealTargetPlatform . Mac ) continue ; //temp hack till mac automated testing works
EditorTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , NonCodeProject , Test . Key , Test . Value , AgentSharingGroup ) ) ) ;
}
}
}
if ( EditorTestNodes . Count > 0 )
{
AddNode ( new GameAggregateNode ( this , HostPlatform , Branch . BaseEngineProject , "AllEditorTests" , EditorTestNodes , 0.0f ) ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-05-02 10:44:27 -04:00
2014-08-22 13:39:55 -04:00
var ServerPlatforms = new List < UnrealTargetPlatform > ( ) ;
var GamePlatforms = new List < UnrealTargetPlatform > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( Branch . BaseEngineProject . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = Branch . BaseEngineProject . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
if ( Platforms . Contains ( HostPlatform ) )
{
// we want the host platform first since some some pseudodependencies look to see if the shared promotable exists.
Platforms . Remove ( HostPlatform ) ;
Platforms . Insert ( 0 , HostPlatform ) ;
}
foreach ( var Plat in Platforms )
{
if ( ! Platform . Platforms [ HostPlatform ] . CanHostPlatform ( Plat ) )
{
throw new AutomationException ( "Project {0} asked for platform {1} with host {2}, but the host platform cannot build that platform." , Branch . BaseEngineProject . GameName , Plat . ToString ( ) , HostPlatform . ToString ( ) ) ;
}
if ( bNoIOSOnPC & & Plat = = UnrealTargetPlatform . IOS & & HostPlatform = = UnrealTargetPlatform . Win64 )
{
continue ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( ActivePlatforms . Contains ( Plat ) )
{
if ( Kind = = TargetRules . TargetType . Server & & ! ServerPlatforms . Contains ( Plat ) )
{
ServerPlatforms . Add ( Plat ) ;
}
if ( Kind = = TargetRules . TargetType . Game & & ! GamePlatforms . Contains ( Plat ) )
{
GamePlatforms . Add ( Plat ) ;
}
if ( ! GUBPNodes . ContainsKey ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , Branch . BaseEngineProject , Plat ) ) )
{
2015-03-21 15:21:14 -04:00
if ( GamePlatformMonolithicsNode . HasPrecompiledTargets ( Branch . BaseEngineProject , HostPlatform , Plat ) )
{
AddNode ( new GamePlatformMonolithicsNode ( this , HostPlatform , Branch . BaseEngineProject , Plat , InPrecompiled : true ) ) ;
}
2015-03-21 13:41:47 -04:00
AddNode ( new GamePlatformMonolithicsNode ( this , HostPlatform , Branch . BaseEngineProject , Plat ) ) ;
2014-08-22 13:39:55 -04:00
}
2015-01-28 08:26:51 -05:00
if ( Plat = = UnrealTargetPlatform . Win32 & & Target . Rules . GUBP_BuildWindowsXPMonolithics ( ) & & Kind = = TargetRules . TargetType . Game )
{
if ( ! GUBPNodes . ContainsKey ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , Branch . BaseEngineProject , Plat , true ) ) )
{
AddNode ( new GamePlatformMonolithicsNode ( this , HostPlatform , Branch . BaseEngineProject , Plat , true ) ) ;
}
2015-03-21 15:21:14 -04:00
}
2015-02-10 14:58:32 -05:00
}
2014-08-22 13:39:55 -04:00
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var CookedAgentSharingGroup = "Shared_CookedTests" + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var GameTestNodes = new List < string > ( ) ;
var GameCookNodes = new List < string > ( ) ;
2014-10-16 13:58:42 -04:00
//var FormalAgentSharingGroup = "Shared_FormalBuilds" + HostPlatformNode.StaticGetHostPlatformSuffix(HostPlatform);
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
//foreach (var Kind in BranchInfo.MonolithicKinds)//for now, non-code projects don't do client or server.
{
var Kind = TargetRules . TargetType . Game ;
if ( Branch . BaseEngineProject . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = Branch . BaseEngineProject . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
foreach ( var Plat in Platforms )
{
if ( ! Platform . Platforms [ HostPlatform ] . CanHostPlatform ( Plat ) )
{
throw new AutomationException ( "Project {0} asked for platform {1} with host {2}, but the host platform cannot build that platform." , Branch . BaseEngineProject . GameName , Plat . ToString ( ) , HostPlatform . ToString ( ) ) ;
}
if ( bNoIOSOnPC & & Plat = = UnrealTargetPlatform . IOS & & HostPlatform = = UnrealTargetPlatform . Win64 )
{
continue ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( ActivePlatforms . Contains ( Plat ) )
{
2014-10-08 10:49:02 -04:00
string CookedPlatform = Platform . Platforms [ Plat ] . GetCookPlatform ( Kind = = TargetRules . TargetType . Server , Kind = = TargetRules . TargetType . Client , "" ) ;
2014-08-22 13:39:55 -04:00
if ( ! GUBPNodes . ContainsKey ( CookNode . StaticGetFullName ( HostPlatform , Branch . BaseEngineProject , CookedPlatform ) ) )
{
GameCookNodes . Add ( AddNode ( new CookNode ( this , HostPlatform , Branch . BaseEngineProject , Plat , CookedPlatform ) ) ) ;
}
if ( ! GUBPNodes . ContainsKey ( GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , Branch . BaseEngineProject , Plat ) ) )
{
AddNode ( new GamePlatformCookedAndCompiledNode ( this , HostPlatform , Branch . BaseEngineProject , Plat , false ) ) ;
}
var GameTests = Target . Rules . GUBP_GetGameTests_MonolithicOnly ( HostPlatform , GetAltHostPlatform ( HostPlatform ) , Plat ) ;
var RequiredPlatforms = new List < UnrealTargetPlatform > { Plat } ;
if ( ! bNoAutomatedTesting )
{
2014-10-15 08:26:52 -04:00
var ThisMonoGameTestNodes = new List < string > ( ) ;
2014-08-22 13:39:55 -04:00
foreach ( var Test in GameTests )
{
var TestName = Test . Key + "_" + Plat . ToString ( ) ;
ThisMonoGameTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , Branch . BaseEngineProject , TestName , Test . Value , CookedAgentSharingGroup , false , RequiredPlatforms ) ) ) ;
}
if ( ThisMonoGameTestNodes . Count > 0 )
2014-10-15 08:26:52 -04:00
{
2014-08-22 13:39:55 -04:00
GameTestNodes . Add ( AddNode ( new GameAggregateNode ( this , HostPlatform , Branch . BaseEngineProject , "CookedTests_" + Plat . ToString ( ) + "_" + Kind . ToString ( ) + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) , ThisMonoGameTestNodes , 0.0f ) ) ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var NonCodeProject in Branch . NonCodeProjects )
{
if ( ! NonCodeProjectNames . ContainsKey ( NonCodeProject . GameName ) | | ! NonCodeProjectNames [ NonCodeProject . GameName ] . Contains ( Plat ) )
{
continue ;
}
if ( ! GUBPNodes . ContainsKey ( CookNode . StaticGetFullName ( HostPlatform , NonCodeProject , CookedPlatform ) ) )
{
GameCookNodes . Add ( AddNode ( new CookNode ( this , HostPlatform , NonCodeProject , Plat , CookedPlatform ) ) ) ;
}
if ( ! GUBPNodes . ContainsKey ( GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , NonCodeProject , Plat ) ) )
{
AddNode ( new GamePlatformCookedAndCompiledNode ( this , HostPlatform , NonCodeProject , Plat , false ) ) ;
if ( NonCodeFormalBuilds . ContainsKey ( NonCodeProject . GameName ) )
{
var PlatList = NonCodeFormalBuilds [ NonCodeProject . GameName ] ;
foreach ( var PlatPair in PlatList )
{
if ( PlatPair . TargetPlatform = = Plat )
{
2014-09-09 13:57:48 -04:00
var NodeName = AddNode ( new FormalBuildNode ( this , NonCodeProject , HostPlatform , new List < UnrealTargetPlatform > ( ) { Plat } , new List < UnrealTargetConfiguration > ( ) { PlatPair . TargetConfig } ) ) ;
2015-03-13 09:50:42 -04:00
if ( PlatPair . bBeforeTrigger )
{
RemovePseudodependencyFromNode ( FormalBuildNode . StaticGetFullName ( NonCodeProject , HostPlatform , new List < UnrealTargetPlatform > ( ) { Plat } , new List < UnrealTargetConfiguration > ( ) { PlatPair . TargetConfig } ) , WaitForFormalUserInput . StaticGetFullName ( ) ) ;
}
2014-09-09 13:57:48 -04:00
// we don't want this delayed
// this would normally wait for the testing phase, we just want to build it right away
RemovePseudodependencyFromNode (
CookNode . StaticGetFullName ( HostPlatform , NonCodeProject , CookedPlatform ) ,
WaitForTestShared . StaticGetFullName ( ) ) ;
string BuildAgentSharingGroup = "" ;
2014-08-18 12:09:20 -04:00
if ( Options . bSeparateGamePromotion )
{
2014-09-09 13:57:48 -04:00
BuildAgentSharingGroup = NonCodeProject . GameName + "_MakeFormalBuild_" + Plat . ToString ( ) + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) ;
if ( Plat = = UnrealTargetPlatform . IOS | | Plat = = UnrealTargetPlatform . Android ) // These trash build products, so we need to use different agents
2014-09-09 12:18:17 -04:00
{
2014-09-09 13:57:48 -04:00
BuildAgentSharingGroup = "" ;
2014-09-09 12:18:17 -04:00
}
2014-09-09 13:57:48 -04:00
GUBPNodes [ CookNode . StaticGetFullName ( HostPlatform , NonCodeProject , CookedPlatform ) ] . AgentSharingGroup = BuildAgentSharingGroup ;
GUBPNodes [ GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , NonCodeProject , Plat ) ] . AgentSharingGroup = BuildAgentSharingGroup ;
GUBPNodes [ NodeName ] . AgentSharingGroup = BuildAgentSharingGroup ;
2014-09-09 12:18:17 -04:00
}
2014-10-09 13:40:13 -04:00
else
{
2014-10-16 13:58:42 -04:00
//GUBPNodes[NodeName].AgentSharingGroup = FormalAgentSharingGroup;
2014-10-09 13:40:13 -04:00
if ( Plat = = UnrealTargetPlatform . XboxOne )
{
GUBPNodes [ NodeName ] . AgentSharingGroup = "" ;
}
}
2014-09-09 13:57:48 -04:00
if ( PlatPair . bTest )
{
AddNode ( new FormalBuildTestNode ( this , NonCodeProject , HostPlatform , Plat , PlatPair . TargetConfig ) ) ;
2015-03-13 09:50:42 -04:00
}
2014-09-09 12:18:17 -04:00
}
}
}
2014-09-09 13:57:48 -04:00
}
2014-08-22 13:39:55 -04:00
if ( ! bNoAutomatedTesting )
{
2015-04-08 16:16:23 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Mac | | HostPlatform = = UnrealTargetPlatform . Linux ) continue ; //temp hack till Linux and Mac automated testing works
2014-09-09 13:57:48 -04:00
var ThisMonoGameTestNodes = new List < string > ( ) ;
foreach ( var Test in GameTests )
{
var TestName = Test . Key + "_" + Plat . ToString ( ) ;
ThisMonoGameTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , NonCodeProject , TestName , Test . Value , CookedAgentSharingGroup , false , RequiredPlatforms ) ) ) ;
}
if ( ThisMonoGameTestNodes . Count > 0 )
2014-10-15 08:26:52 -04:00
{
2014-09-09 13:57:48 -04:00
GameTestNodes . Add ( AddNode ( new GameAggregateNode ( this , HostPlatform , NonCodeProject , "CookedTests_" + Plat . ToString ( ) + "_" + Kind . ToString ( ) + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) , ThisMonoGameTestNodes , 0.0f ) ) ) ;
}
}
}
}
}
}
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
#if false
//for now, non-code projects don't do client or server.
foreach ( var ServerPlatform in ServerPlatforms )
{
var ServerTarget = Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Server ] ;
foreach ( var GamePlatform in GamePlatforms )
{
var Target = Branch . BaseEngineProject . Properties . Targets [ TargetRules . TargetType . Game ] ;
foreach ( var NonCodeProject in Branch . NonCodeProjects )
{
if ( ! NonCodeProjectNames . ContainsKey ( NonCodeProject . GameName ) | | ! NonCodeProjectNames . ContainsKey ( NonCodeProject . GameName ) | |
! NonCodeProjectNames [ NonCodeProject . GameName ] . Contains ( ServerPlatform ) | | ! NonCodeProjectNames [ NonCodeProject . GameName ] . Contains ( GamePlatform ) )
{
continue ;
}
var ClientServerTests = Target . Rules . GUBP_GetClientServerTests_MonolithicOnly ( HostPlatform , GetAltHostPlatform ( HostPlatform ) , ServerPlatform , GamePlatform ) ;
var RequiredPlatforms = new List < UnrealTargetPlatform > { ServerPlatform } ;
if ( ServerPlatform ! = GamePlatform )
{
RequiredPlatforms . Add ( GamePlatform ) ;
}
foreach ( var Test in ClientServerTests )
{
GameTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , NonCodeProject , Test . Key + "_" + GamePlatform . ToString ( ) + "_" + ServerPlatform . ToString ( ) , Test . Value , false , RequiredPlatforms , true ) ) ) ;
}
}
}
}
#endif
2014-08-22 13:39:55 -04:00
if ( GameTestNodes . Count > 0 )
{
AddNode ( new GameAggregateNode ( this , HostPlatform , Branch . BaseEngineProject , "AllCookedTests" , GameTestNodes ) ) ;
}
}
2015-02-10 14:58:32 -05:00
if ( ! GUBPNodes . ContainsKey ( SharedCookAggregateNode . StaticGetFullName ( ) ) )
{
AddNode ( new SharedCookAggregateNode ( this , HostPlatforms , NonCodeProjectNames , NonCodeFormalBuilds ) ) ;
}
2014-10-09 13:40:13 -04:00
2015-05-16 17:45:08 -04:00
if ( HostPlatform = = MakeFeaturePacksNode . GetDefaultBuildPlatform ( this ) & & ! BranchOptions . bNoInstalledEngine )
2015-02-09 19:52:57 -05:00
{
2015-03-21 10:00:59 -04:00
AddNode ( new MakeFeaturePacksNode ( HostPlatform , Branch . AllProjects . Where ( x = > MakeFeaturePacksNode . IsFeaturePack ( x ) ) ) ) ;
2015-02-09 19:52:57 -05:00
}
2014-08-22 13:39:55 -04:00
foreach ( var CodeProj in Branch . CodeProjects )
{
var Options = CodeProj . Options ( HostPlatform ) ;
2014-03-14 14:13:41 -04:00
2015-03-18 11:20:05 -04:00
if ( ! Options . bIsPromotable & & ! Options . bTestWithShared & & ! Options . bIsNonCode )
2014-08-22 13:39:55 -04:00
{
2015-03-18 11:20:05 -04:00
continue ; // we skip things that aren't promotable and aren't tested - except noncode as code situations
2014-08-22 13:39:55 -04:00
}
var AgentShareName = CodeProj . GameName ;
if ( ! Options . bSeparateGamePromotion )
{
AgentShareName = "Shared" ;
}
2014-03-14 14:13:41 -04:00
2015-03-03 08:42:05 -05:00
if ( ! BranchOptions . ExcludePlatformsForEditor . Contains ( HostPlatform ) & & ! Options . bIsNonCode )
2015-02-24 18:49:02 -05:00
{
2015-04-17 08:15:17 -04:00
EditorGameNode Node = ( EditorGameNode ) TryFindNode ( EditorGameNode . StaticGetFullName ( HostPlatform , CodeProj ) ) ;
if ( Node = = null )
{
AddNode ( new EditorGameNode ( this , HostPlatform , CodeProj ) ) ;
}
else
{
Node . AddProject ( CodeProj ) ;
}
2015-02-24 18:49:02 -05:00
}
2014-09-05 21:50:16 -04:00
if ( ! bNoAutomatedTesting & & HostPlatform = = UnrealTargetPlatform . Win64 ) //temp hack till automated testing works on other platforms than Win64
2014-08-22 13:39:55 -04:00
{
2015-03-02 15:07:21 -05:00
if ( CodeProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
2015-03-04 08:31:40 -05:00
var EditorTests = CodeProj . Properties . Targets [ TargetRules . TargetType . Editor ] . Rules . GUBP_GetEditorTests_EditorTypeOnly ( HostPlatform ) ;
var EditorTestNodes = new List < string > ( ) ;
string AgentSharingGroup = "" ;
if ( EditorTests . Count > 1 )
2015-02-09 10:53:40 -05:00
{
2015-03-04 08:31:40 -05:00
AgentSharingGroup = AgentShareName + "_EditorTests" + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) ;
2015-02-09 10:53:40 -05:00
}
2015-03-04 08:31:40 -05:00
foreach ( var Test in EditorTests )
{
EditorTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , CodeProj , Test . Key , Test . Value , AgentSharingGroup ) ) ) ;
2015-03-18 13:46:36 -04:00
if ( ! Options . bTestWithShared | | ! HasNode ( WaitForTestShared . StaticGetFullName ( ) ) )
2015-03-04 08:31:40 -05:00
{
RemovePseudodependencyFromNode ( ( UATTestNode . StaticGetFullName ( HostPlatform , CodeProj , Test . Key ) ) , WaitForTestShared . StaticGetFullName ( ) ) ;
}
}
if ( EditorTestNodes . Count > 0 )
{
AddNode ( new GameAggregateNode ( this , HostPlatform , CodeProj , "AllEditorTests" , EditorTestNodes , 0.0f ) ) ;
}
}
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var CookedAgentSharingGroup = AgentShareName + "_CookedTests" + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) ;
2014-10-16 13:58:42 -04:00
//var FormalAgentSharingGroup = "Shared_FormalBuilds" + HostPlatformNode.StaticGetHostPlatformSuffix(HostPlatform);
2014-08-22 13:39:55 -04:00
var ServerPlatforms = new List < UnrealTargetPlatform > ( ) ;
var GamePlatforms = new List < UnrealTargetPlatform > ( ) ;
var GameTestNodes = new List < string > ( ) ;
foreach ( var Kind in BranchInfo . MonolithicKinds )
{
if ( CodeProj . Properties . Targets . ContainsKey ( Kind ) )
{
var Target = CodeProj . Properties . Targets [ Kind ] ;
var Platforms = Target . Rules . GUBP_GetPlatforms_MonolithicOnly ( HostPlatform ) ;
2014-08-18 13:29:39 -04:00
var AdditionalPlatforms = Target . Rules . GUBP_GetBuildOnlyPlatforms_MonolithicOnly ( HostPlatform ) ;
var AllPlatforms = Platforms . Union ( AdditionalPlatforms ) ;
foreach ( var Plat in AllPlatforms )
2014-08-22 13:39:55 -04:00
{
if ( ! Platform . Platforms [ HostPlatform ] . CanHostPlatform ( Plat ) )
{
throw new AutomationException ( "Project {0} asked for platform {1} with host {2}, but the host platform cannot build that platform." , CodeProj . GameName , Plat . ToString ( ) , HostPlatform . ToString ( ) ) ;
}
if ( bNoIOSOnPC & & Plat = = UnrealTargetPlatform . IOS & & HostPlatform = = UnrealTargetPlatform . Win64 )
{
continue ;
}
2015-01-28 08:26:51 -05:00
if ( Plat = = UnrealTargetPlatform . Win32 & & Target . Rules . GUBP_BuildWindowsXPMonolithics ( ) )
{
if ( ! GUBPNodes . ContainsKey ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , CodeProj , Plat , true ) ) )
{
AddNode ( new GamePlatformMonolithicsNode ( this , HostPlatform , CodeProj , Plat , true ) ) ;
}
}
2014-08-22 13:39:55 -04:00
if ( ActivePlatforms . Contains ( Plat ) )
{
if ( Kind = = TargetRules . TargetType . Server & & ! ServerPlatforms . Contains ( Plat ) )
{
ServerPlatforms . Add ( Plat ) ;
}
if ( Kind = = TargetRules . TargetType . Game & & ! GamePlatforms . Contains ( Plat ) )
{
GamePlatforms . Add ( Plat ) ;
}
if ( ! GUBPNodes . ContainsKey ( GamePlatformMonolithicsNode . StaticGetFullName ( HostPlatform , CodeProj , Plat ) ) )
{
2015-03-21 15:21:14 -04:00
if ( GamePlatformMonolithicsNode . HasPrecompiledTargets ( CodeProj , HostPlatform , Plat ) )
{
AddNode ( new GamePlatformMonolithicsNode ( this , HostPlatform , CodeProj , Plat , InPrecompiled : true ) ) ;
}
2014-08-22 13:39:55 -04:00
AddNode ( new GamePlatformMonolithicsNode ( this , HostPlatform , CodeProj , Plat ) ) ;
}
2014-08-18 13:29:39 -04:00
if ( ! AdditionalPlatforms . Contains ( Plat ) )
{
2014-09-09 13:57:48 -04:00
string CookedPlatform = Platform . Platforms [ Plat ] . GetCookPlatform ( Kind = = TargetRules . TargetType . Server , Kind = = TargetRules . TargetType . Client , "" ) ;
2014-10-08 10:49:02 -04:00
if ( Target . Rules . GUBP_AlternateCookPlatform ( HostPlatform , CookedPlatform ) ! = "" )
{
CookedPlatform = Target . Rules . GUBP_AlternateCookPlatform ( HostPlatform , CookedPlatform ) ;
}
2014-09-09 13:57:48 -04:00
if ( ! GUBPNodes . ContainsKey ( CookNode . StaticGetFullName ( HostPlatform , CodeProj , CookedPlatform ) ) )
{
AddNode ( new CookNode ( this , HostPlatform , CodeProj , Plat , CookedPlatform ) ) ;
}
if ( ! GUBPNodes . ContainsKey ( GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , CodeProj , Plat ) ) )
{
AddNode ( new GamePlatformCookedAndCompiledNode ( this , HostPlatform , CodeProj , Plat , true ) ) ;
}
var FormalBuildConfigs = Target . Rules . GUBP_GetConfigsForFormalBuilds_MonolithicOnly ( HostPlatform ) ;
2014-05-01 07:33:06 -04:00
2014-09-09 13:57:48 -04:00
foreach ( var Config in FormalBuildConfigs )
{
string FormalNodeName = null ;
if ( Kind = = TargetRules . TargetType . Client )
{
if ( Plat = = Config . TargetPlatform )
{
FormalNodeName = AddNode ( new FormalBuildNode ( this , CodeProj , HostPlatform , InClientTargetPlatforms : new List < UnrealTargetPlatform > ( ) { Config . TargetPlatform } , InClientConfigs : new List < UnrealTargetConfiguration > ( ) { Config . TargetConfig } , InClientNotGame : true ) ) ;
}
}
else if ( Kind = = TargetRules . TargetType . Server )
{
if ( Plat = = Config . TargetPlatform )
{
FormalNodeName = AddNode ( new FormalBuildNode ( this , CodeProj , HostPlatform , InServerTargetPlatforms : new List < UnrealTargetPlatform > ( ) { Config . TargetPlatform } , InServerConfigs : new List < UnrealTargetConfiguration > ( ) { Config . TargetConfig } ) ) ;
}
}
else if ( Kind = = TargetRules . TargetType . Game )
{
if ( Plat = = Config . TargetPlatform )
{
FormalNodeName = AddNode ( new FormalBuildNode ( this , CodeProj , HostPlatform , InClientTargetPlatforms : new List < UnrealTargetPlatform > ( ) { Config . TargetPlatform } , InClientConfigs : new List < UnrealTargetConfiguration > ( ) { Config . TargetConfig } ) ) ;
}
}
if ( FormalNodeName ! = null )
{
2015-03-13 09:50:42 -04:00
if ( Config . bBeforeTrigger )
{
RemovePseudodependencyFromNode ( FormalBuildNode . StaticGetFullName ( CodeProj , HostPlatform , new List < UnrealTargetPlatform > ( ) { Config . TargetPlatform } , new List < UnrealTargetConfiguration > ( ) { Config . TargetConfig } ) , WaitForFormalUserInput . StaticGetFullName ( ) ) ;
}
2014-09-09 13:57:48 -04:00
// we don't want this delayed
// this would normally wait for the testing phase, we just want to build it right away
RemovePseudodependencyFromNode (
CookNode . StaticGetFullName ( HostPlatform , CodeProj , CookedPlatform ) ,
WaitForTestShared . StaticGetFullName ( ) ) ;
string BuildAgentSharingGroup = "" ;
2014-10-09 13:40:13 -04:00
2014-09-09 13:57:48 -04:00
if ( Options . bSeparateGamePromotion )
{
BuildAgentSharingGroup = CodeProj . GameName + "_MakeFormalBuild_" + Plat . ToString ( ) + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) ;
if ( Plat = = UnrealTargetPlatform . IOS | | Plat = = UnrealTargetPlatform . Android | | Plat = = UnrealTargetPlatform . XboxOne ) // These trash build products, so we need to use different agents
{
BuildAgentSharingGroup = "" ;
}
GUBPNodes [ CookNode . StaticGetFullName ( HostPlatform , CodeProj , CookedPlatform ) ] . AgentSharingGroup = BuildAgentSharingGroup ;
GUBPNodes [ GamePlatformCookedAndCompiledNode . StaticGetFullName ( HostPlatform , CodeProj , Plat ) ] . AgentSharingGroup = BuildAgentSharingGroup ;
GUBPNodes [ FormalNodeName ] . AgentSharingGroup = BuildAgentSharingGroup ;
}
2014-10-09 13:40:13 -04:00
else
{
2014-10-16 13:58:42 -04:00
//GUBPNodes[FormalNodeName].AgentSharingGroup = FormalAgentSharingGroup;
2014-10-09 13:40:13 -04:00
if ( Plat = = UnrealTargetPlatform . XboxOne )
{
GUBPNodes [ FormalNodeName ] . AgentSharingGroup = "" ;
}
}
2014-09-09 13:57:48 -04:00
if ( Config . bTest )
{
AddNode ( new FormalBuildTestNode ( this , CodeProj , HostPlatform , Plat , Config . TargetConfig ) ) ;
}
}
}
if ( ! bNoAutomatedTesting )
{
2015-04-08 16:16:23 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Mac | | HostPlatform = = UnrealTargetPlatform . Linux ) continue ; //temp hack till Linux and Mac automated testing works
2014-09-09 13:57:48 -04:00
var GameTests = Target . Rules . GUBP_GetGameTests_MonolithicOnly ( HostPlatform , GetAltHostPlatform ( HostPlatform ) , Plat ) ;
var RequiredPlatforms = new List < UnrealTargetPlatform > { Plat } ;
var ThisMonoGameTestNodes = new List < string > ( ) ;
2014-07-31 09:28:43 -04:00
2014-09-09 13:57:48 -04:00
foreach ( var Test in GameTests )
{
var TestNodeName = Test . Key + "_" + Plat . ToString ( ) ;
ThisMonoGameTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , CodeProj , TestNodeName , Test . Value , CookedAgentSharingGroup , false , RequiredPlatforms ) ) ) ;
2015-03-18 13:46:36 -04:00
if ( ! Options . bTestWithShared | | ! HasNode ( WaitForTestShared . StaticGetFullName ( ) ) )
2015-02-09 10:53:40 -05:00
{
RemovePseudodependencyFromNode ( ( UATTestNode . StaticGetFullName ( HostPlatform , CodeProj , TestNodeName ) ) , WaitForTestShared . StaticGetFullName ( ) ) ;
}
2014-09-09 13:57:48 -04:00
}
if ( ThisMonoGameTestNodes . Count > 0 )
{
GameTestNodes . Add ( AddNode ( new GameAggregateNode ( this , HostPlatform , CodeProj , "CookedTests_" + Plat . ToString ( ) + "_" + Kind . ToString ( ) + HostPlatformNode . StaticGetHostPlatformSuffix ( HostPlatform ) , ThisMonoGameTestNodes , 0.0f ) ) ) ;
}
}
}
}
}
}
2014-08-18 13:29:39 -04:00
}
2014-09-09 13:57:48 -04:00
if ( ! bNoAutomatedTesting )
{
foreach ( var ServerPlatform in ServerPlatforms )
{
foreach ( var GamePlatform in GamePlatforms )
{
2015-04-08 16:16:23 -04:00
if ( HostPlatform = = UnrealTargetPlatform . Mac | | HostPlatform = = UnrealTargetPlatform . Linux ) continue ; //temp hack till Linux and Mac automated testing works
2014-09-09 13:57:48 -04:00
var Target = CodeProj . Properties . Targets [ TargetRules . TargetType . Game ] ;
var ClientServerTests = Target . Rules . GUBP_GetClientServerTests_MonolithicOnly ( HostPlatform , GetAltHostPlatform ( HostPlatform ) , ServerPlatform , GamePlatform ) ;
var RequiredPlatforms = new List < UnrealTargetPlatform > { ServerPlatform } ;
if ( ServerPlatform ! = GamePlatform )
{
RequiredPlatforms . Add ( GamePlatform ) ;
}
foreach ( var Test in ClientServerTests )
{
var TestNodeName = Test . Key + "_" + GamePlatform . ToString ( ) + "_" + ServerPlatform . ToString ( ) ;
GameTestNodes . Add ( AddNode ( new UATTestNode ( this , HostPlatform , CodeProj , TestNodeName , Test . Value , CookedAgentSharingGroup , false , RequiredPlatforms ) ) ) ;
}
}
}
if ( GameTestNodes . Count > 0 )
{
AddNode ( new GameAggregateNode ( this , HostPlatform , CodeProj , "AllCookedTests" , GameTestNodes ) ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
int NumSharedAllHosts = 0 ;
foreach ( var CodeProj in Branch . CodeProjects )
{
if ( CodeProj . Properties . Targets . ContainsKey ( TargetRules . TargetType . Editor ) )
{
bool AnySeparate = false ;
var PromotedHosts = new List < UnrealTargetPlatform > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
foreach ( var HostPlatform in HostPlatforms )
{
2015-04-21 15:21:51 -04:00
if ( ! BranchOptions . ExcludePlatformsForEditor . Contains ( HostPlatform ) & & ! BranchOptions . RemovePlatformFromPromotable . Contains ( HostPlatform ) )
2015-02-24 18:49:02 -05:00
{
var Options = CodeProj . Options ( HostPlatform ) ;
AnySeparate = AnySeparate | | Options . bSeparateGamePromotion ;
if ( Options . bIsPromotable )
{
if ( ! Options . bSeparateGamePromotion )
{
NumSharedAllHosts + + ;
}
PromotedHosts . Add ( HostPlatform ) ;
}
}
2014-08-22 13:39:55 -04:00
}
if ( PromotedHosts . Count > 0 )
{
2014-11-03 11:46:48 -05:00
AddNode ( new GameAggregatePromotableNode ( this , PromotedHosts , CodeProj , true ) ) ;
2014-08-22 13:39:55 -04:00
if ( AnySeparate )
{
AddNode ( new WaitForGamePromotionUserInput ( this , CodeProj , false ) ) ;
AddNode ( new GameLabelPromotableNode ( this , CodeProj , false ) ) ;
AddNode ( new WaitForGamePromotionUserInput ( this , CodeProj , true ) ) ;
AddNode ( new GameLabelPromotableNode ( this , CodeProj , true ) ) ;
}
}
}
}
if ( NumSharedAllHosts > 0 )
{
2014-11-03 11:46:48 -05:00
AddNode ( new GameAggregatePromotableNode ( this , HostPlatforms , Branch . BaseEngineProject , false ) ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
AddNode ( new SharedAggregatePromotableNode ( this , HostPlatforms ) ) ;
AddNode ( new WaitForSharedPromotionUserInput ( this , false ) ) ;
AddNode ( new SharedLabelPromotableNode ( this , false ) ) ;
2015-04-23 13:26:28 -04:00
AddNode ( new SharedLabelPromotableSuccessNode ( ) ) ;
2014-08-22 13:39:55 -04:00
AddNode ( new WaitForTestShared ( this ) ) ;
AddNode ( new WaitForSharedPromotionUserInput ( this , true ) ) ;
AddNode ( new SharedLabelPromotableNode ( this , true ) ) ;
2015-02-10 14:58:32 -05:00
AddNode ( new WaitForFormalUserInput ( this ) ) ;
2014-08-22 13:39:55 -04:00
}
foreach ( var HostPlatform in HostPlatforms )
{
AddCustomNodes ( HostPlatform ) ;
}
if ( HasNode ( ToolsForCompileNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) )
{
2014-10-15 10:22:11 -04:00
if ( HasNode ( GamePlatformMonolithicsNode . StaticGetFullName ( UnrealTargetPlatform . Mac , Branch . BaseEngineProject , UnrealTargetPlatform . IOS ) ) & & HasNode ( ToolsNode . StaticGetFullName ( UnrealTargetPlatform . Win64 ) ) )
{
//AddNode(new IOSOnPCTestNode(this)); - Disable IOSOnPCTest until a1011 crash is fixed
}
2015-05-13 15:11:52 -04:00
//AddNode(new VSExpressTestNode(this));
2015-03-04 08:31:40 -05:00
if ( ActivePlatforms . Contains ( UnrealTargetPlatform . Linux ) & & ! BranchOptions . ExcludePlatformsForEditor . Contains ( UnrealTargetPlatform . Linux ) )
2015-02-24 18:49:02 -05:00
{
AddNode ( new RootEditorCrossCompileLinuxNode ( UnrealTargetPlatform . Win64 ) ) ;
}
2014-08-22 13:39:55 -04:00
if ( ! bPreflightBuild )
{
AddNode ( new CleanSharedTempStorageNode ( this ) ) ;
}
}
2014-06-30 16:04:59 -04:00
#if false
// this doesn't work for lots of reasons...we can't figure out what the dependencies are until far later
2014-06-13 06:48:43 -04:00
if ( bPreflightBuild )
{
GeneralSuccessNode PreflightSuccessNode = new GeneralSuccessNode ( "Preflight" ) ;
foreach ( var NodeToDo in GUBPNodes )
{
if ( NodeToDo . Value . RunInEC ( ) )
{
PreflightSuccessNode . AddPseudodependency ( NodeToDo . Key ) ;
}
}
AddNode ( PreflightSuccessNode ) ;
2014-04-29 21:53:42 -04:00
}
2014-06-30 16:04:59 -04:00
#endif
2014-08-22 13:39:55 -04:00
foreach ( var NodeToDo in GUBPNodes )
{
foreach ( var Dep in GUBPNodes [ NodeToDo . Key ] . FullNamesOfDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the full graph. It is a dependency of {1}." , Dep , NodeToDo . Key ) ;
}
if ( Dep = = NodeToDo . Key )
{
throw new AutomationException ( "Node {0} has a self arc." , NodeToDo . Key ) ;
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo . Key ] . FullNamesOfPseudosependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the full graph. It is a pseudodependency of {1}." , Dep , NodeToDo . Key ) ;
}
if ( Dep = = NodeToDo . Key )
{
throw new AutomationException ( "Node {0} has a self pseudoarc." , NodeToDo . Key ) ;
}
}
}
2015-04-17 14:13:52 -04:00
2014-08-22 13:39:55 -04:00
if ( bCleanLocalTempStorage ) // shared temp storage can never be wiped
{
DeleteLocalTempStorageManifests ( CmdEnv ) ;
}
2014-05-02 10:44:27 -04:00
2014-08-22 13:39:55 -04:00
GUBPNodesControllingTrigger = new Dictionary < string , string > ( ) ;
GUBPNodesControllingTriggerDotName = new Dictionary < string , string > ( ) ;
2014-05-02 10:44:27 -04:00
2014-08-22 13:39:55 -04:00
var FullNodeList = new Dictionary < string , string > ( ) ;
var FullNodeDirectDependencies = new Dictionary < string , string > ( ) ;
2014-10-27 07:59:33 -04:00
var FullNodeDependedOnBy = new Dictionary < string , string > ( ) ;
2015-01-08 11:56:04 -05:00
var FullNodeDependentPromotions = new Dictionary < string , string > ( ) ;
2014-11-03 16:17:30 -05:00
var SeparatePromotables = new List < string > ( ) ;
2015-04-21 15:21:51 -04:00
{
foreach ( var NodeToDo in GUBPNodes )
{
if ( GUBPNodes [ NodeToDo . Key ] . IsSeparatePromotable ( ) )
{
SeparatePromotables . Add ( GUBPNodes [ NodeToDo . Key ] . GetFullName ( ) ) ;
List < string > Dependencies = new List < string > ( ) ;
Dependencies = GetECDependencies ( NodeToDo . Key ) ;
foreach ( var Dep in Dependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the graph. It is a dependency of {1}." , Dep , NodeToDo ) ;
}
if ( ! GUBPNodes [ Dep ] . IsPromotableAggregate ( ) )
{
if ( ! GUBPNodes [ Dep ] . DependentPromotions . Contains ( NodeToDo . Key ) )
{
GUBPNodes [ Dep ] . DependentPromotions . Add ( NodeToDo . Key ) ;
}
}
}
}
}
2015-04-23 08:57:18 -04:00
// Make sure that everything that's listed as a frequency barrier is completed with the given interval
2015-04-24 20:25:23 -04:00
Dictionary < string , int > FrequencyOverrides = new Dictionary < string , int > ( ) ;
2015-04-23 08:57:18 -04:00
foreach ( KeyValuePair < string , sbyte > Barrier in BranchOptions . FrequencyBarriers )
{
// All the nodes which are dependencies of the barrier node
HashSet < string > IncludedNodes = new HashSet < string > { Barrier . Key } ;
// Find all the nodes which are indirect dependencies of this node
List < string > SearchNodes = new List < string > { Barrier . Key } ;
for ( int Idx = 0 ; Idx < SearchNodes . Count ; Idx + + )
{
GUBPNode Node = GUBPNodes [ SearchNodes [ Idx ] ] ;
2015-04-24 20:25:23 -04:00
foreach ( string DependencyName in Node . FullNamesOfDependencies . Union ( Node . FullNamesOfPseudosependencies ) )
2015-04-23 08:57:18 -04:00
{
if ( ! IncludedNodes . Contains ( DependencyName ) )
{
IncludedNodes . Add ( DependencyName ) ;
SearchNodes . Add ( DependencyName ) ;
}
}
}
// Make sure that everything included in this list is before the cap, and everything not in the list is after it
foreach ( KeyValuePair < string , GUBPNode > NodePair in GUBPNodes )
{
if ( IncludedNodes . Contains ( NodePair . Key ) )
{
2015-04-24 20:25:23 -04:00
int Frequency ;
if ( FrequencyOverrides . TryGetValue ( NodePair . Key , out Frequency ) )
{
Frequency = Math . Min ( Frequency , Barrier . Value ) ;
}
else
{
Frequency = Barrier . Value ;
}
FrequencyOverrides [ NodePair . Key ] = Frequency ;
2015-04-23 08:57:18 -04:00
}
}
}
2015-04-24 20:25:23 -04:00
// Compute all the frequencies
foreach ( var NodeToDo in GUBPNodes )
{
ComputeDependentCISFrequencyQuantumShift ( NodeToDo . Key , FrequencyOverrides ) ;
}
2015-04-21 15:21:51 -04:00
foreach ( var NodeToDo in GUBPNodes )
{
var Deps = GUBPNodes [ NodeToDo . Key ] . DependentPromotions ;
string All = "" ;
foreach ( var Dep in Deps )
{
if ( All ! = "" )
{
All + = " " ;
}
All + = Dep ;
}
FullNodeDependentPromotions . Add ( NodeToDo . Key , All ) ;
}
}
2014-08-22 13:39:55 -04:00
{
Log ( "******* {0} GUBP Nodes" , GUBPNodes . Count ) ;
var SortedNodes = TopologicalSort ( new HashSet < string > ( GUBPNodes . Keys ) , LocalOnly : true , DoNotConsiderCompletion : true ) ;
2015-05-06 18:08:37 -04:00
var DependencyStart = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
foreach ( var Node in SortedNodes )
{
string Note = GetControllingTriggerDotName ( Node ) ;
if ( Note = = "" )
{
Note = CISFrequencyQuantumShiftString ( Node ) ;
}
if ( Note = = "" )
{
Note = "always" ;
}
if ( GUBPNodes [ Node ] . RunInEC ( ) )
{
var Deps = GetECDependencies ( Node ) ;
string All = "" ;
foreach ( var Dep in Deps )
{
if ( All ! = "" )
{
All + = " " ;
}
All + = Dep ;
}
Log ( " {0}: {1} {2}" , Node , Note , All ) ;
FullNodeList . Add ( Node , Note ) ;
FullNodeDirectDependencies . Add ( Node , All ) ;
}
else
{
Log ( " {0}: {1} [Aggregate]" , Node , Note ) ;
}
}
2015-05-06 18:08:37 -04:00
var DependencyFinish = DateTime . Now . ToString ( ) ;
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,GetDependencies,{0},{1}" , DependencyStart , DependencyFinish ) ) ;
2014-08-22 13:39:55 -04:00
}
2015-04-01 13:36:26 -04:00
Dictionary < string , int > FullNodeListSortKey = GetDisplayOrder ( FullNodeList . Keys . ToList ( ) , FullNodeDirectDependencies , GUBPNodes ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
bool bOnlyNode = false ;
bool bRelatedToNode = false ;
bool bGraphSubset = false ;
var NodesToDo = new HashSet < string > ( ) ;
2014-09-03 10:12:50 -04:00
2014-08-22 13:39:55 -04:00
{
2014-09-03 10:12:50 -04:00
string NodeSpec = ParseParamValue ( "Node" ) ;
2014-08-22 13:39:55 -04:00
if ( String . IsNullOrEmpty ( NodeSpec ) )
2014-09-03 10:12:50 -04:00
{
2014-08-22 13:39:55 -04:00
NodeSpec = ParseParamValue ( "RelatedToNode" ) ;
if ( ! String . IsNullOrEmpty ( NodeSpec ) )
{
bRelatedToNode = true ;
}
}
if ( String . IsNullOrEmpty ( NodeSpec ) & & CommanderSetup )
{
NodeSpec = ParseParamValue ( "SetupNode" ) ;
if ( String . IsNullOrEmpty ( NodeSpec ) )
{
NodeSpec = ParseParamValue ( "SetupRelatedToNode" ) ;
if ( ! String . IsNullOrEmpty ( NodeSpec ) )
{
bRelatedToNode = true ;
}
}
}
if ( String . IsNullOrEmpty ( NodeSpec ) )
{
NodeSpec = ParseParamValue ( "OnlyNode" ) ;
if ( ! String . IsNullOrEmpty ( NodeSpec ) )
{
bOnlyNode = true ;
}
}
if ( ! String . IsNullOrEmpty ( NodeSpec ) )
{
bGraphSubset = true ;
if ( NodeSpec . Equals ( "Noop" , StringComparison . InvariantCultureIgnoreCase ) )
{
Log ( "Request for Noop node, done." ) ;
PrintRunTime ( ) ;
return ;
}
List < string > Nodes = new List < string > ( NodeSpec . Split ( '+' ) ) ;
foreach ( var NodeArg in Nodes )
{
var NodeName = NodeArg . Trim ( ) ;
bool bFoundAnything = false ;
if ( ! String . IsNullOrEmpty ( NodeName ) )
{
foreach ( var Node in GUBPNodes )
{
if ( Node . Value . GetFullName ( ) . Equals ( NodeArg , StringComparison . InvariantCultureIgnoreCase ) | |
Node . Value . AgentSharingGroup . Equals ( NodeArg , StringComparison . InvariantCultureIgnoreCase )
)
{
if ( ! NodesToDo . Contains ( Node . Key ) )
{
NodesToDo . Add ( Node . Key ) ;
}
bFoundAnything = true ;
}
}
if ( ! bFoundAnything )
{
throw new AutomationException ( "Could not find node named {0}" , NodeName ) ;
}
}
}
}
}
string GameSpec = ParseParamValue ( "Game" ) ;
if ( ! String . IsNullOrEmpty ( GameSpec ) )
{
bGraphSubset = true ;
List < string > Games = new List < string > ( GameSpec . Split ( '+' ) ) ;
foreach ( var GameArg in Games )
{
var GameName = GameArg . Trim ( ) ;
if ( ! String . IsNullOrEmpty ( GameName ) )
{
foreach ( var GameProj in Branch . CodeProjects )
{
if ( GameProj . GameName . Equals ( GameName , StringComparison . InvariantCultureIgnoreCase ) )
{
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
NodesToDo . Add ( GameAggregatePromotableNode . StaticGetFullName ( GameProj ) ) ;
foreach ( var Node in GUBPNodes )
{
if ( Node . Value . GameNameIfAnyForTempStorage ( ) = = GameProj . GameName )
{
NodesToDo . Add ( Node . Key ) ;
}
}
GameName = null ;
}
}
if ( GameName ! = null )
{
foreach ( var GameProj in Branch . NonCodeProjects )
{
if ( GameProj . GameName . Equals ( GameName , StringComparison . InvariantCultureIgnoreCase ) )
{
foreach ( var Node in GUBPNodes )
{
if ( Node . Value . GameNameIfAnyForTempStorage ( ) = = GameProj . GameName )
{
NodesToDo . Add ( Node . Key ) ;
}
}
GameName = null ;
}
}
}
if ( GameName ! = null )
{
throw new AutomationException ( "Could not find game named {0}" , GameName ) ;
}
}
}
}
if ( NodesToDo . Count = = 0 )
{
Log ( "No nodes specified, adding all nodes" ) ;
foreach ( var Node in GUBPNodes )
{
NodesToDo . Add ( Node . Key ) ;
}
}
else if ( TimeIndex ! = 0 )
{
Log ( "Check to make sure we didn't ask for nodes that will be culled by time index" ) ;
foreach ( var NodeToDo in NodesToDo )
{
if ( TimeIndex % ( 1 < < GUBPNodes [ NodeToDo ] . DependentCISFrequencyQuantumShift ( ) ) ! = 0 )
{
throw new AutomationException ( "You asked specifically for node {0}, but it is culled by the time quantum: TimeIndex = {1}, DependentCISFrequencyQuantumShift = {2}." , NodeToDo , TimeIndex , GUBPNodes [ NodeToDo ] . DependentCISFrequencyQuantumShift ( ) ) ;
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Log ( "Desired Nodes" ) ;
foreach ( var NodeToDo in NodesToDo )
{
2014-10-15 08:26:52 -04:00
Log ( " {0}" , NodeToDo ) ;
2014-08-22 13:39:55 -04:00
}
// if we are doing related to, then find things that depend on the selected nodes
if ( bRelatedToNode )
{
bool bDoneWithDependencies = false ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
while ( ! bDoneWithDependencies )
{
bDoneWithDependencies = true ;
var Fringe = new HashSet < string > ( ) ;
foreach ( var NodeToDo in GUBPNodes )
{
if ( ! NodesToDo . Contains ( NodeToDo . Key ) )
{
foreach ( var Dep in GUBPNodes [ NodeToDo . Key ] . FullNamesOfDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the graph. It is a dependency of {1}." , Dep , NodeToDo . Key ) ;
}
if ( NodesToDo . Contains ( Dep ) )
{
Fringe . Add ( NodeToDo . Key ) ;
bDoneWithDependencies = false ;
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo . Key ] . FullNamesOfPseudosependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the graph. It is a pseudodependency of {1}." , Dep , NodeToDo . Key ) ;
}
}
}
}
NodesToDo . UnionWith ( Fringe ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// find things that our nodes depend on
if ( ! bOnlyNode )
{
bool bDoneWithDependencies = false ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
while ( ! bDoneWithDependencies )
{
bDoneWithDependencies = true ;
var Fringe = new HashSet < string > ( ) ;
foreach ( var NodeToDo in NodesToDo )
{
2015-05-08 15:02:46 -04:00
if ( BranchOptions . NodesToRemovePseudoDependencies . Count > 0 )
2015-05-06 18:54:54 -04:00
{
2015-05-08 15:02:46 -04:00
var ListOfRetainedNodesToRemovePseudoDependencies = BranchOptions . NodesToRemovePseudoDependencies ;
foreach ( var NodeToRemovePseudoDependencies in BranchOptions . NodesToRemovePseudoDependencies )
{
if ( NodeToDo = = NodeToRemovePseudoDependencies )
{
RemoveAllPseudodependenciesFromNode ( NodeToDo ) ;
ListOfRetainedNodesToRemovePseudoDependencies . Remove ( NodeToDo ) ;
break ;
}
}
BranchOptions . NodesToRemovePseudoDependencies = ListOfRetainedNodesToRemovePseudoDependencies ;
2015-05-06 18:54:54 -04:00
}
2014-08-22 13:39:55 -04:00
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the graph. It is a dependency of {1}." , Dep , NodeToDo ) ;
}
if ( ! NodesToDo . Contains ( Dep ) )
{
Fringe . Add ( Dep ) ;
bDoneWithDependencies = false ;
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the graph. It is a pseudodependency of {1}." , Dep , NodeToDo ) ;
}
}
}
NodesToDo . UnionWith ( Fringe ) ;
}
2015-04-21 15:21:51 -04:00
}
2014-10-27 07:59:33 -04:00
if ( TimeIndex ! = 0 )
{
Log ( "Culling based on time index" ) ;
var NewNodesToDo = new HashSet < string > ( ) ;
foreach ( var NodeToDo in NodesToDo )
{
if ( TimeIndex % ( 1 < < GUBPNodes [ NodeToDo ] . DependentCISFrequencyQuantumShift ( ) ) = = 0 )
{
Log ( " Keeping {0}" , NodeToDo ) ;
NewNodesToDo . Add ( NodeToDo ) ;
}
else
{
Log ( " Rejecting {0}" , NodeToDo ) ;
}
}
NodesToDo = NewNodesToDo ;
}
2015-01-13 12:59:24 -05:00
//Remove Plat if specified
if ( WithoutLinux )
{
var NewNodesToDo = new HashSet < string > ( ) ;
foreach ( var NodeToDo in NodesToDo )
{
if ( ! GUBPNodes [ NodeToDo ] . GetFullName ( ) . Contains ( "Linux" ) )
{
NewNodesToDo . Add ( NodeToDo ) ;
}
else
{
Log ( " Rejecting {0} because -NoLinux was requested" , NodeToDo ) ;
}
}
NodesToDo = NewNodesToDo ;
}
2014-10-27 07:59:33 -04:00
//find things that depend on our nodes and setup commander dictionary
if ( ! bOnlyNode )
{
foreach ( var NodeToDo in NodesToDo )
{
if ( ! GUBPNodes [ NodeToDo ] . IsAggregate ( ) & & ! GUBPNodes [ NodeToDo ] . IsTest ( ) )
{
List < string > ECDependencies = new List < string > ( ) ;
ECDependencies = GetECDependencies ( NodeToDo ) ;
foreach ( var Dep in ECDependencies )
{
if ( ! GUBPNodes . ContainsKey ( Dep ) )
{
throw new AutomationException ( "Node {0} is not in the graph. It is a dependency of {1}." , Dep , NodeToDo ) ;
}
if ( ! GUBPNodes [ Dep ] . FullNamesOfDependedOn . Contains ( NodeToDo ) )
{
GUBPNodes [ Dep ] . FullNamesOfDependedOn . Add ( NodeToDo ) ;
}
}
}
}
foreach ( var NodeToDo in NodesToDo )
{
var Deps = GUBPNodes [ NodeToDo ] . FullNamesOfDependedOn ;
string All = "" ;
foreach ( var Dep in Deps )
{
if ( All ! = "" )
{
All + = " " ;
}
All + = Dep ;
}
FullNodeDependedOnBy . Add ( NodeToDo , All ) ;
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( CommanderSetup )
{
if ( ! String . IsNullOrEmpty ( ExplicitTrigger ) )
{
bool bFoundIt = false ;
foreach ( var Node in GUBPNodes )
{
if ( Node . Value . GetFullName ( ) . Equals ( ExplicitTrigger , StringComparison . InvariantCultureIgnoreCase ) )
{
if ( Node . Value . TriggerNode ( ) & & Node . Value . RunInEC ( ) )
{
Node . Value . SetAsExplicitTrigger ( ) ;
bFoundIt = true ;
break ;
}
}
}
if ( ! bFoundIt )
{
throw new AutomationException ( "Could not find trigger node named {0}" , ExplicitTrigger ) ;
}
}
else
{
if ( bSkipTriggers )
{
foreach ( var Node in GUBPNodes )
{
if ( Node . Value . TriggerNode ( ) & & Node . Value . RunInEC ( ) )
{
Node . Value . SetAsExplicitTrigger ( ) ;
}
}
}
}
}
2014-08-18 13:29:39 -04:00
if ( bPreflightBuild )
{
Log ( "Culling triggers and downstream for preflight builds " ) ;
var NewNodesToDo = new HashSet < string > ( ) ;
foreach ( var NodeToDo in NodesToDo )
{
var TriggerDot = GetControllingTriggerDotName ( NodeToDo ) ;
if ( TriggerDot = = "" & & ! GUBPNodes [ NodeToDo ] . TriggerNode ( ) )
{
Log ( " Keeping {0}" , NodeToDo ) ;
NewNodesToDo . Add ( NodeToDo ) ;
}
else
{
Log ( " Rejecting {0}" , NodeToDo ) ;
}
}
NodesToDo = NewNodesToDo ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
GUBPNodesCompleted = new Dictionary < string , bool > ( ) ;
GUBPNodesHistory = new Dictionary < string , NodeHistory > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Log ( "******* Caching completion" ) ;
{
var StartTime = DateTime . UtcNow ;
foreach ( var Node in NodesToDo )
{
Log ( "** {0}" , Node ) ;
NodeIsAlreadyComplete ( Node , LocalOnly ) ; // cache these now to avoid spam later
GetControllingTriggerDotName ( Node ) ;
}
var BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds ;
Log ( "Took {0}s to cache completion for {1} nodes" , BuildDuration / 1000 , NodesToDo . Count ) ;
}
2015-03-03 07:56:18 -05:00
/ * if ( CLString ! = "" & & StoreName . Contains ( CLString ) & & ! ParseParam ( "NoHistory" ) )
2014-08-22 13:39:55 -04:00
{
Log ( "******* Updating history" ) ;
var StartTime = DateTime . UtcNow ;
foreach ( var Node in NodesToDo )
{
if ( ! NodeIsAlreadyComplete ( Node , LocalOnly ) )
{
UpdateNodeHistory ( Node , CLString ) ;
2015-01-08 11:56:04 -05:00
}
2014-08-22 13:39:55 -04:00
}
var BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds ;
Log ( "Took {0}s to get history for {1} nodes" , BuildDuration / 1000 , NodesToDo . Count ) ;
2015-03-03 07:56:18 -05:00
} * /
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var OrdereredToDo = TopologicalSort ( NodesToDo , ExplicitTrigger , LocalOnly ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// find all unfinished triggers, excepting the one we are triggering right now
var UnfinishedTriggers = new List < string > ( ) ;
if ( ! bSkipTriggers )
{
foreach ( var NodeToDo in OrdereredToDo )
{
if ( GUBPNodes [ NodeToDo ] . TriggerNode ( ) & & ! NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) )
{
if ( String . IsNullOrEmpty ( ExplicitTrigger ) | | ExplicitTrigger ! = NodeToDo )
{
UnfinishedTriggers . Add ( NodeToDo ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Log ( "*********** Desired And Dependent Nodes, in order." ) ;
2014-12-18 13:47:28 -05:00
PrintNodes ( this , OrdereredToDo , LocalOnly , UnfinishedTriggers ) ;
2014-08-22 13:39:55 -04:00
//check sorting
{
foreach ( var NodeToDo in OrdereredToDo )
{
if ( GUBPNodes [ NodeToDo ] . TriggerNode ( ) & & ( GUBPNodes [ NodeToDo ] . IsSticky ( ) | | NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) ) ) // these sticky triggers are ok, everything is already completed anyway
{
continue ;
}
2014-10-15 08:26:52 -04:00
if ( GUBPNodes [ NodeToDo ] . IsTest ( ) )
{
bHasTests = true ;
}
2014-08-22 13:39:55 -04:00
int MyIndex = OrdereredToDo . IndexOf ( NodeToDo ) ;
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
int DepIndex = OrdereredToDo . IndexOf ( Dep ) ;
if ( DepIndex > = MyIndex )
{
throw new AutomationException ( "Topological sort error, node {0} has a dependency of {1} which sorted after it." , NodeToDo , Dep ) ;
}
}
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies )
{
int DepIndex = OrdereredToDo . IndexOf ( Dep ) ;
if ( DepIndex > = MyIndex )
{
throw new AutomationException ( "Topological sort error, node {0} has a pseduodependency of {1} which sorted after it." , NodeToDo , Dep ) ;
}
}
}
}
2014-06-30 16:04:59 -04:00
2014-08-22 13:39:55 -04:00
string FakeFail = ParseParamValue ( "FakeFail" ) ;
if ( CommanderSetup )
{
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( OrdereredToDo . Count = = 0 )
{
throw new AutomationException ( "No nodes to do!" ) ;
}
var ECProps = new List < string > ( ) ;
ECProps . Add ( String . Format ( "TimeIndex={0}" , TimeIndex ) ) ;
foreach ( var NodePair in FullNodeList )
{
ECProps . Add ( string . Format ( "AllNodes/{0}={1}" , NodePair . Key , NodePair . Value ) ) ;
}
2015-04-16 18:02:46 -04:00
foreach ( var NodePair in FullNodeDirectDependencies )
{
ECProps . Add ( string . Format ( "DirectDependencies/{0}={1}" , NodePair . Key , NodePair . Value ) ) ;
}
2014-08-22 13:39:55 -04:00
foreach ( var NodePair in FullNodeListSortKey )
{
ECProps . Add ( string . Format ( "SortKey/{0}={1}" , NodePair . Key , NodePair . Value ) ) ;
2014-10-27 07:59:33 -04:00
}
2015-01-27 13:15:02 -05:00
foreach ( var NodePair in FullNodeDependedOnBy )
2015-02-10 14:58:32 -05:00
{
2015-01-27 13:15:02 -05:00
ECProps . Add ( string . Format ( "DependedOnBy/{0}={1}" , NodePair . Key , NodePair . Value ) ) ;
2015-02-10 14:58:32 -05:00
}
2015-01-27 13:15:02 -05:00
foreach ( var NodePair in FullNodeDependentPromotions )
{
ECProps . Add ( string . Format ( "DependentPromotions/{0}={1}" , NodePair . Key , NodePair . Value ) ) ;
}
2014-11-03 16:17:30 -05:00
foreach ( var Node in SeparatePromotables )
{
ECProps . Add ( string . Format ( "PossiblePromotables/{0}={1}" , Node , "" ) ) ;
2015-01-08 11:56:04 -05:00
}
2014-08-22 13:39:55 -04:00
var ECJobProps = new List < string > ( ) ;
if ( ExplicitTrigger ! = "" )
{
ECJobProps . Add ( "IsRoot=0" ) ;
}
else
{
ECJobProps . Add ( "IsRoot=1" ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var FilteredOrdereredToDo = new List < string > ( ) ;
2015-05-01 20:39:36 -04:00
var StartFilterTime = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
// remove nodes that have unfinished triggers
foreach ( var NodeToDo in OrdereredToDo )
{
string ControllingTrigger = GetControllingTrigger ( NodeToDo ) ;
bool bNoUnfinishedTriggers = ! UnfinishedTriggers . Contains ( ControllingTrigger ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( bNoUnfinishedTriggers )
{
// if we are triggering, then remove nodes that are not controlled by the trigger or are dependencies of this trigger
if ( ! String . IsNullOrEmpty ( ExplicitTrigger ) )
{
if ( ExplicitTrigger ! = NodeToDo & & ! NodeDependsOn ( NodeToDo , ExplicitTrigger ) & & ! NodeDependsOn ( ExplicitTrigger , NodeToDo ) )
{
continue ; // this wasn't on the chain related to the trigger we are triggering, so it is not relevant
}
}
2014-08-18 13:29:39 -04:00
if ( bPreflightBuild & & ! bSkipTriggers & & GUBPNodes [ NodeToDo ] . TriggerNode ( ) )
{
// in preflight builds, we are either skipping triggers (and running things downstream) or we just stop at triggers and don't make them available for triggering.
continue ;
}
2014-08-22 13:39:55 -04:00
FilteredOrdereredToDo . Add ( NodeToDo ) ;
}
}
2015-05-01 20:39:36 -04:00
2014-08-22 13:39:55 -04:00
OrdereredToDo = FilteredOrdereredToDo ;
2015-05-01 20:39:36 -04:00
var FinishFilterTime = DateTime . Now . ToString ( ) ;
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,FilterNodes,{0},{1}" , StartFilterTime , FinishFilterTime ) ) ;
2014-08-22 13:39:55 -04:00
Log ( "*********** EC Nodes, in order." ) ;
PrintNodes ( this , OrdereredToDo , LocalOnly , UnfinishedTriggers ) ;
2015-05-01 20:39:36 -04:00
var FinishNodePrint = DateTime . Now . ToString ( ) ;
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,SetupCommanderPrint,{0},{1}" , FinishFilterTime , FinishNodePrint ) ) ;
2014-08-22 13:39:55 -04:00
// here we are just making sure everything before the explicit trigger is completed.
if ( ! String . IsNullOrEmpty ( ExplicitTrigger ) )
{
foreach ( var NodeToDo in FilteredOrdereredToDo )
{
if ( GUBPNodes [ NodeToDo ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) & & NodeToDo ! = ExplicitTrigger & & ! NodeDependsOn ( ExplicitTrigger , NodeToDo ) ) // if something is already finished, we don't put it into EC
{
throw new AutomationException ( "We are being asked to process node {0}, however, this is an explicit trigger {1}, so everything before it should already be handled. It seems likely that you waited too long to run the trigger. You will have to do a new build from scratch." , NodeToDo , ExplicitTrigger ) ;
}
}
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
string LastSticky = "" ;
bool HitNonSticky = false ;
bool bHaveECNodes = false ;
2014-09-03 10:12:50 -04:00
List < string > StepList = new List < string > ( ) ;
StepList . Add ( "use strict;" ) ;
StepList . Add ( "use diagnostics;" ) ;
StepList . Add ( "use ElectricCommander();" ) ;
StepList . Add ( "my $ec = new ElectricCommander;" ) ;
StepList . Add ( "$ec->setTimeout(600);" ) ;
StepList . Add ( "my $batch = $ec->newBatch(\"serial\");" ) ;
2014-08-22 13:39:55 -04:00
// sticky nodes are ones that we run on the main agent. We run then first and they must not be intermixed with parallel jobs
2014-09-03 10:12:50 -04:00
foreach ( var NodeToDo in OrdereredToDo )
{
if ( GUBPNodes [ NodeToDo ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) ) // if something is already finished, we don't put it into EC
{
bHaveECNodes = true ;
if ( GUBPNodes [ NodeToDo ] . IsSticky ( ) )
{
LastSticky = NodeToDo ;
if ( HitNonSticky & & ! bSkipTriggers )
{
throw new AutomationException ( "Sticky and non-sticky jobs did not sort right." ) ;
}
}
else
{
HitNonSticky = true ;
}
}
}
2014-08-22 13:39:55 -04:00
string ParentPath = ParseParamValue ( "ParentPath" ) ;
2015-05-01 20:39:36 -04:00
var StartPerlOutput = DateTime . Now . ToString ( ) ;
2014-09-03 10:12:50 -04:00
string BaseArgs = String . Format ( "$batch->createJobStep({{parentPath => '{0}'" , ParentPath ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
bool bHasNoop = false ;
if ( LastSticky = = "" & & bHaveECNodes )
{
// if we don't have any sticky nodes and we have other nodes, we run a fake noop just to release the resource
2015-02-13 13:37:22 -05:00
string Args = String . Format ( "{0}, subprocedure => 'GUBP_UAT_Node', parallel => '0', jobStepName => 'Noop', actualParameter => [{{actualParameterName => 'NodeName', value => 'Noop'}}, {{actualParameterName => 'Sticky', value =>'1' }}], releaseMode => 'release'}});" , BaseArgs ) ;
2014-09-03 10:12:50 -04:00
StepList . Add ( Args ) ;
2014-08-22 13:39:55 -04:00
bHasNoop = true ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var FakeECArgs = new List < string > ( ) ;
var AgentGroupChains = new Dictionary < string , List < string > > ( ) ;
2015-05-08 14:02:32 -04:00
var StickyChain = new List < string > ( ) ;
2014-08-22 13:39:55 -04:00
foreach ( var NodeToDo in OrdereredToDo )
{
if ( GUBPNodes [ NodeToDo ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) ) // if something is already finished, we don't put it into EC
{
string MyAgentGroup = GUBPNodes [ NodeToDo ] . AgentSharingGroup ;
if ( MyAgentGroup ! = "" )
{
if ( ! AgentGroupChains . ContainsKey ( MyAgentGroup ) )
{
AgentGroupChains . Add ( MyAgentGroup , new List < string > { NodeToDo } ) ;
}
else
{
AgentGroupChains [ MyAgentGroup ] . Add ( NodeToDo ) ;
}
}
}
2015-05-08 14:02:32 -04:00
if ( GUBPNodes [ NodeToDo ] . IsSticky ( ) )
{
if ( ! StickyChain . Contains ( NodeToDo ) )
{
StickyChain . Add ( NodeToDo ) ;
}
}
2014-08-22 13:39:55 -04:00
}
foreach ( var NodeToDo in OrdereredToDo )
{
if ( GUBPNodes [ NodeToDo ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) ) // if something is already finished, we don't put it into EC
2014-10-15 08:26:52 -04:00
{
2014-08-22 13:39:55 -04:00
string EMails ;
var NodeProps = GetECPropsForNode ( NodeToDo , CLString , out EMails ) ;
ECProps . AddRange ( NodeProps ) ;
bool Sticky = GUBPNodes [ NodeToDo ] . IsSticky ( ) ;
bool DoParallel = ! Sticky ;
2015-05-07 13:19:06 -04:00
if ( GUBPNodes [ NodeToDo ] . ECProcedure ( ) = = "GUBP_UAT_Node_Parallel_AgentShare_Editor" )
{
DoParallel = true ;
}
2014-08-22 13:39:55 -04:00
if ( Sticky & & GUBPNodes [ NodeToDo ] . ECAgentString ( ) ! = "" )
{
throw new AutomationException ( "Node {1} is sticky but has agent requirements." , NodeToDo ) ;
}
string Procedure = GUBPNodes [ NodeToDo ] . ECProcedure ( ) ;
2015-04-03 07:56:40 -04:00
if ( GUBPNodes [ NodeToDo ] . IsSticky ( ) & & NodeToDo = = LastSticky )
{
Procedure = Procedure + "_Release" ;
}
2014-09-03 10:12:50 -04:00
string Args = String . Format ( "{0}, subprocedure => '{1}', parallel => '{2}', jobStepName => '{3}', actualParameter => [{{actualParameterName => 'NodeName', value =>'{4}'}}" ,
2014-08-22 13:39:55 -04:00
BaseArgs , Procedure , DoParallel ? 1 : 0 , NodeToDo , NodeToDo ) ;
string ProcedureParams = GUBPNodes [ NodeToDo ] . ECProcedureParams ( ) ;
if ( ! String . IsNullOrEmpty ( ProcedureParams ) )
{
2014-09-03 10:12:50 -04:00
Args = Args + ProcedureParams ;
2014-08-22 13:39:55 -04:00
}
if ( ( Procedure = = "GUBP_UAT_Trigger" | | Procedure = = "GUBP_Hardcoded_Trigger" ) & & ! String . IsNullOrEmpty ( EMails ) )
{
2014-09-03 10:12:50 -04:00
Args = Args + ", {actualParameterName => 'EmailsForTrigger', value => \'" + EMails + "\'}" ;
2014-08-22 13:39:55 -04:00
}
2014-09-03 10:12:50 -04:00
Args = Args + "]" ;
2014-08-22 13:39:55 -04:00
string PreCondition = "" ;
string RunCondition = "" ;
2014-09-03 10:12:50 -04:00
var UncompletedEcDeps = new List < string > ( ) ;
2015-02-10 14:58:32 -05:00
var UncompletedCompletedDeps = new List < string > ( ) ;
2014-08-22 13:39:55 -04:00
string MyAgentGroup = GUBPNodes [ NodeToDo ] . AgentSharingGroup ;
bool bDoNestedJobstep = false ;
bool bDoFirstNestedJobstep = false ;
string NodeParentPath = ParentPath ;
string PreconditionParentPath ;
2015-02-17 16:43:54 -05:00
if ( GUBPNodes [ NodeToDo ] . GetFullName ( ) . Contains ( "MakeBuild" ) & & GUBPNodes [ NodeToDo ] . FullNamesOfPseudosependencies . Contains ( WaitForFormalUserInput . StaticGetFullName ( ) ) & & ! bGraphSubset )
2014-09-03 10:12:50 -04:00
{
2015-02-17 16:43:54 -05:00
RemovePseudodependencyFromNode ( NodeToDo , WaitForFormalUserInput . StaticGetFullName ( ) ) ;
2014-08-22 13:39:55 -04:00
PreconditionParentPath = GetPropertyFromStep ( "/myWorkflow/ParentJob" ) ;
UncompletedEcDeps = GetECDependencies ( NodeToDo ) ;
2014-08-18 13:29:39 -04:00
}
2014-08-22 13:39:55 -04:00
else
2014-08-18 13:29:39 -04:00
{
2014-08-22 13:39:55 -04:00
PreconditionParentPath = ParentPath ;
2014-09-03 10:12:50 -04:00
var EcDeps = GetECDependencies ( NodeToDo ) ;
foreach ( var Dep in EcDeps )
{
if ( GUBPNodes [ Dep ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( Dep , LocalOnly ) & & OrdereredToDo . Contains ( Dep ) ) // if something is already finished, we don't put it into EC
{
if ( OrdereredToDo . IndexOf ( Dep ) > OrdereredToDo . IndexOf ( NodeToDo ) )
{
throw new AutomationException ( "Topological sort error, node {0} has a dependency of {1} which sorted after it." , NodeToDo , Dep ) ;
}
UncompletedEcDeps . Add ( Dep ) ;
}
}
}
var PreConditionUncompletedEcDeps = UncompletedEcDeps ;
2015-02-10 14:58:32 -05:00
var CompletedDeps = GetCompletedOnlyDependencies ( NodeToDo ) ;
foreach ( var Dep in CompletedDeps )
{
if ( GUBPNodes [ Dep ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( Dep , LocalOnly ) & & OrdereredToDo . Contains ( Dep ) ) // if something is already finished, we don't put it into EC
{
if ( OrdereredToDo . IndexOf ( Dep ) > OrdereredToDo . IndexOf ( NodeToDo ) )
{
throw new AutomationException ( "Topological sort error, node {0} has a dependency of {1} which sorted after it." , NodeToDo , Dep ) ;
}
UncompletedCompletedDeps . Add ( Dep ) ;
}
}
2014-08-22 13:39:55 -04:00
if ( MyAgentGroup ! = "" )
{
bDoNestedJobstep = true ;
NodeParentPath = ParentPath + "/jobSteps[" + MyAgentGroup + "]" ;
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
PreConditionUncompletedEcDeps = new List < string > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
var MyChain = AgentGroupChains [ MyAgentGroup ] ;
int MyIndex = MyChain . IndexOf ( NodeToDo ) ;
if ( MyIndex > 0 )
{
PreConditionUncompletedEcDeps . Add ( MyChain [ MyIndex - 1 ] ) ;
}
else
{
bDoFirstNestedJobstep = bDoNestedJobstep ;
// to avoid idle agents (and also EC doesn't actually reserve our agent!), we promote all dependencies to the first one
foreach ( var Chain in MyChain )
{
var EcDeps = GetECDependencies ( Chain ) ;
foreach ( var Dep in EcDeps )
{
if ( GUBPNodes [ Dep ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( Dep , LocalOnly ) & & OrdereredToDo . Contains ( Dep ) ) // if something is already finished, we don't put it into EC
{
if ( OrdereredToDo . IndexOf ( Dep ) > OrdereredToDo . IndexOf ( Chain ) )
{
throw new AutomationException ( "Topological sort error, node {0} has a dependency of {1} which sorted after it." , Chain , Dep ) ;
}
if ( ! MyChain . Contains ( Dep ) & & ! PreConditionUncompletedEcDeps . Contains ( Dep ) )
{
PreConditionUncompletedEcDeps . Add ( Dep ) ;
}
}
}
}
}
}
2015-05-08 14:02:32 -04:00
if ( GUBPNodes [ NodeToDo ] . IsSticky ( ) )
{
var MyChain = StickyChain ;
int MyIndex = MyChain . IndexOf ( NodeToDo ) ;
if ( MyIndex > 0 )
{
2015-05-11 14:24:31 -04:00
if ( ! PreConditionUncompletedEcDeps . Contains ( MyChain [ MyIndex - 1 ] ) & & ! NodeIsAlreadyComplete ( MyChain [ MyIndex - 1 ] , LocalOnly ) )
{
PreConditionUncompletedEcDeps . Add ( MyChain [ MyIndex - 1 ] ) ;
}
2015-05-08 14:02:32 -04:00
}
else
{
var EcDeps = GetECDependencies ( NodeToDo ) ;
foreach ( var Dep in EcDeps )
{
if ( GUBPNodes [ Dep ] . RunInEC ( ) & & ! NodeIsAlreadyComplete ( Dep , LocalOnly ) & & OrdereredToDo . Contains ( Dep ) ) // if something is already finished, we don't put it into EC
{
if ( OrdereredToDo . IndexOf ( Dep ) > OrdereredToDo . IndexOf ( NodeToDo ) )
{
throw new AutomationException ( "Topological sort error, node {0} has a dependency of {1} which sorted after it." , NodeToDo , Dep ) ;
}
if ( ! MyChain . Contains ( Dep ) & & ! PreConditionUncompletedEcDeps . Contains ( Dep ) )
{
PreConditionUncompletedEcDeps . Add ( Dep ) ;
}
}
}
}
}
2014-08-22 13:39:55 -04:00
if ( bHasNoop & & PreConditionUncompletedEcDeps . Count = = 0 )
{
PreConditionUncompletedEcDeps . Add ( "Noop" ) ;
}
if ( PreConditionUncompletedEcDeps . Count > 0 )
{
2014-09-03 10:12:50 -04:00
PreCondition = "\"\\$\" . \"[/javascript if(" ;
2014-08-22 13:39:55 -04:00
// these run "parallel", but we add preconditions to serialize them
int Index = 0 ;
foreach ( var Dep in PreConditionUncompletedEcDeps )
2014-09-03 10:12:50 -04:00
{
PreCondition = PreCondition + "getProperty('" + GetJobStep ( PreconditionParentPath , Dep ) + "/status\') == \'completed\'" ;
2014-08-22 13:39:55 -04:00
Index + + ;
if ( Index ! = PreConditionUncompletedEcDeps . Count )
{
PreCondition = PreCondition + " && " ;
}
}
PreCondition = PreCondition + ") true;]\"" ;
}
2015-02-10 14:58:32 -05:00
if ( UncompletedCompletedDeps . Count > 0 )
{
PreCondition = "\"\\$\" . \"[/javascript if(" ;
// these run "parallel", but we add preconditions to serialize them
int Index = 0 ;
foreach ( var Dep in CompletedDeps )
{
if ( GUBPNodes [ Dep ] . RunInEC ( ) )
{
PreCondition = PreCondition + "getProperty('" + GetJobStep ( PreconditionParentPath , Dep ) + "/status\') == \'completed\'" ;
Index + + ;
if ( Index ! = CompletedDeps . Count )
{
PreCondition = PreCondition + " && " ;
}
}
}
PreCondition = PreCondition + ") true;]\"" ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( UncompletedEcDeps . Count > 0 )
{
2014-09-03 10:12:50 -04:00
RunCondition = "\"\\$\" . \"[/javascript if(" ;
2014-08-22 13:39:55 -04:00
int Index = 0 ;
foreach ( var Dep in UncompletedEcDeps )
{
2014-09-03 10:12:50 -04:00
RunCondition = RunCondition + "((\'\\$\" . \"[" + GetJobStep ( PreconditionParentPath , Dep ) + "/outcome]\' == \'success\') || " ;
RunCondition = RunCondition + "(\'\\$\" . \"[" + GetJobStep ( PreconditionParentPath , Dep ) + "/outcome]\' == \'warning\'))" ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Index + + ;
if ( Index ! = UncompletedEcDeps . Count )
{
RunCondition = RunCondition + " && " ;
}
}
2014-09-03 10:12:50 -04:00
RunCondition = RunCondition + ")true; else false;]\"" ;
2014-08-22 13:39:55 -04:00
}
2014-04-02 18:09:23 -04:00
2014-08-22 13:39:55 -04:00
if ( bDoNestedJobstep )
{
if ( bDoFirstNestedJobstep )
{
{
2014-09-03 10:12:50 -04:00
string NestArgs = String . Format ( "$batch->createJobStep({{parentPath => '{0}', jobStepName => '{1}', parallel => '1'" ,
2014-08-22 13:39:55 -04:00
ParentPath , MyAgentGroup ) ;
if ( ! String . IsNullOrEmpty ( PreCondition ) )
{
2014-09-03 10:12:50 -04:00
NestArgs = NestArgs + ", precondition => " + PreCondition ;
2014-08-22 13:39:55 -04:00
}
2014-09-03 10:12:50 -04:00
NestArgs = NestArgs + "});" ;
StepList . Add ( NestArgs ) ;
2014-08-22 13:39:55 -04:00
}
{
2014-09-03 10:12:50 -04:00
string NestArgs = String . Format ( "$batch->createJobStep({{parentPath => '{0}/jobSteps[{1}]', jobStepName => '{2}_GetPool', subprocedure => 'GUBP{3}_AgentShare_GetPool', parallel => '1', actualParameter => [{{actualParameterName => 'AgentSharingGroup', value => '{4}'}}, {{actualParameterName => 'NodeName', value => '{5}'}}]" ,
2014-08-22 13:39:55 -04:00
ParentPath , MyAgentGroup , MyAgentGroup , GUBPNodes [ NodeToDo ] . ECProcedureInfix ( ) , MyAgentGroup , NodeToDo ) ;
if ( ! String . IsNullOrEmpty ( PreCondition ) )
{
2014-09-03 10:12:50 -04:00
NestArgs = NestArgs + ", precondition => " + PreCondition ;
2014-08-22 13:39:55 -04:00
}
2014-09-03 10:12:50 -04:00
NestArgs = NestArgs + "});" ;
StepList . Add ( NestArgs ) ;
2014-08-22 13:39:55 -04:00
}
{
2014-09-03 10:12:50 -04:00
string NestArgs = String . Format ( "$batch->createJobStep({{parentPath => '{0}/jobSteps[{1}]', jobStepName => '{2}_GetAgent', subprocedure => 'GUBP{3}_AgentShare_GetAgent', parallel => '1', exclusiveMode => 'call', resourceName => '{4}', actualParameter => [{{actualParameterName => 'AgentSharingGroup', value => '{5}'}}, {{actualParameterName => 'NodeName', value=> '{6}'}}]" ,
2014-08-22 13:39:55 -04:00
ParentPath , MyAgentGroup , MyAgentGroup , GUBPNodes [ NodeToDo ] . ECProcedureInfix ( ) ,
String . Format ( "$[/myJob/jobSteps[{0}]/ResourcePool]" , MyAgentGroup ) ,
MyAgentGroup , NodeToDo ) ;
{
2014-09-03 10:12:50 -04:00
NestArgs = NestArgs + ", precondition => " ;
NestArgs = NestArgs + "\"\\$\" . \"[/javascript if(" ;
2014-08-22 13:39:55 -04:00
NestArgs = NestArgs + "getProperty('" + PreconditionParentPath + "/jobSteps[" + MyAgentGroup + "]/jobSteps[" + MyAgentGroup + "_GetPool]/status') == 'completed'" ;
NestArgs = NestArgs + ") true;]\"" ;
}
2014-09-03 10:12:50 -04:00
NestArgs = NestArgs + "});" ;
StepList . Add ( NestArgs ) ;
2014-08-22 13:39:55 -04:00
}
{
2014-09-03 10:12:50 -04:00
PreCondition = "\"\\$\" . \"[/javascript if(" ;
2014-08-22 13:39:55 -04:00
PreCondition = PreCondition + "getProperty('" + PreconditionParentPath + "/jobSteps[" + MyAgentGroup + "]/jobSteps[" + MyAgentGroup + "_GetAgent]/status') == 'completed'" ;
PreCondition = PreCondition + ") true;]\"" ;
}
}
2014-09-03 10:12:50 -04:00
Args = Args . Replace ( String . Format ( "parentPath => '{0}'" , ParentPath ) , String . Format ( "parentPath => '{0}'" , NodeParentPath ) ) ;
2014-08-22 13:39:55 -04:00
Args = Args . Replace ( "UAT_Node_Parallel_AgentShare" , "UAT_Node_Parallel_AgentShare3" ) ;
}
2014-08-18 13:29:39 -04:00
2014-08-22 13:39:55 -04:00
if ( ! String . IsNullOrEmpty ( PreCondition ) )
{
2014-09-03 10:12:50 -04:00
Args = Args + ", precondition => " + PreCondition ;
2014-08-22 13:39:55 -04:00
}
if ( ! String . IsNullOrEmpty ( RunCondition ) )
{
2014-09-03 10:12:50 -04:00
Args = Args + ", condition => " + RunCondition ;
2014-08-22 13:39:55 -04:00
}
2014-04-23 17:54:46 -04:00
#if false
// this doesn't work because it includes precondition time
2014-04-23 17:51:55 -04:00
if ( GUBPNodes [ NodeToDo ] . TimeoutInMinutes ( ) > 0 )
{
Args = Args + String . Format ( " --timeLimitUnits minutes --timeLimit {0}" , GUBPNodes [ NodeToDo ] . TimeoutInMinutes ( ) ) ;
}
2014-04-23 17:54:46 -04:00
#endif
2014-08-22 13:39:55 -04:00
if ( Sticky & & NodeToDo = = LastSticky )
{
2015-02-13 13:37:22 -05:00
Args = Args + ", releaseMode => 'release'" ;
2014-08-22 13:39:55 -04:00
}
2014-09-03 10:12:50 -04:00
Args = Args + "});" ;
StepList . Add ( Args ) ;
2014-08-22 13:39:55 -04:00
if ( bFakeEC & &
! UnfinishedTriggers . Contains ( NodeToDo ) & &
( GUBPNodes [ NodeToDo ] . ECProcedure ( ) . StartsWith ( "GUBP_UAT_Node" ) | | GUBPNodes [ NodeToDo ] . ECProcedure ( ) . StartsWith ( "GUBP_Mac_UAT_Node" ) ) // other things we really can't test
) // unfinished triggers are never run directly by EC, rather it does another job setup
{
string Arg = String . Format ( "gubp -Node={0} -FakeEC {1} {2} {3} {4} {5}" ,
NodeToDo ,
bFake ? "-Fake" : "" ,
ParseParam ( "AllPlatforms" ) ? "-AllPlatforms" : "" ,
ParseParam ( "UnfinishedTriggersFirst" ) ? "-UnfinishedTriggersFirst" : "" ,
ParseParam ( "UnfinishedTriggersParallel" ) ? "-UnfinishedTriggersParallel" : "" ,
ParseParam ( "WithMac" ) ? "-WithMac" : ""
) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string Node = ParseParamValue ( "-Node" ) ;
if ( ! String . IsNullOrEmpty ( Node ) )
{
Arg = Arg + " -Node=" + Node ;
}
if ( ! String . IsNullOrEmpty ( FakeFail ) )
{
Arg = Arg + " -FakeFail=" + FakeFail ;
}
FakeECArgs . Add ( Arg ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( MyAgentGroup ! = "" & & ! bDoNestedJobstep )
{
var MyChain = AgentGroupChains [ MyAgentGroup ] ;
int MyIndex = MyChain . IndexOf ( NodeToDo ) ;
if ( MyIndex = = MyChain . Count - 1 )
{
2014-09-03 10:12:50 -04:00
var RelPreCondition = "\"\\$\" . \"[/javascript if(" ;
2014-08-22 13:39:55 -04:00
// this runs "parallel", but we a precondition to serialize it
RelPreCondition = RelPreCondition + "getProperty('" + PreconditionParentPath + "/jobSteps[" + NodeToDo + "]/status') == 'completed'" ;
RelPreCondition = RelPreCondition + ") true;]\"" ;
// we need to release the resource
2015-02-13 13:37:22 -05:00
string RelArgs = String . Format ( "{0}, subprocedure => 'GUBP_Release_AgentShare', parallel => '1', jobStepName => 'Release_{1}', actualParameter => [{{actualParameterName => 'AgentSharingGroup', valued => '{2}'}}], releaseMode => 'release', precondition => '{3}'" ,
2014-08-22 13:39:55 -04:00
BaseArgs , MyAgentGroup , MyAgentGroup , RelPreCondition ) ;
2014-09-03 10:12:50 -04:00
StepList . Add ( RelArgs ) ;
2014-08-22 13:39:55 -04:00
}
}
}
}
2014-09-03 10:12:50 -04:00
WriteECPerl ( StepList ) ;
2015-05-01 20:39:36 -04:00
var FinishPerlOutput = DateTime . Now . ToString ( ) ;
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,PerlOutput,{0},{1}" , StartPerlOutput , FinishPerlOutput ) ) ;
2015-03-12 14:54:03 -04:00
RunECTool ( String . Format ( "setProperty \"/myWorkflow/HasTests\" \"{0}\"" , bHasTests ) ) ;
2014-08-22 13:39:55 -04:00
{
ECProps . Add ( "GUBP_LoadedProps=1" ) ;
string BranchDefFile = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LogFolder , "BranchDef.properties" ) ;
CommandUtils . WriteAllLines ( BranchDefFile , ECProps . ToArray ( ) ) ;
RunECTool ( String . Format ( "setProperty \"/myWorkflow/BranchDefFile\" \"{0}\"" , BranchDefFile . Replace ( "\\" , "\\\\" ) ) ) ;
}
{
ECProps . Add ( "GUBP_LoadedJobProps=1" ) ;
string BranchJobDefFile = CommandUtils . CombinePaths ( CommandUtils . CmdEnv . LogFolder , "BranchJobDef.properties" ) ;
CommandUtils . WriteAllLines ( BranchJobDefFile , ECProps . ToArray ( ) ) ;
RunECTool ( String . Format ( "setProperty \"/myJob/BranchJobDefFile\" \"{0}\"" , BranchJobDefFile . Replace ( "\\" , "\\\\" ) ) ) ;
}
if ( bFakeEC )
{
foreach ( var Args in FakeECArgs )
{
RunUAT ( CmdEnv , Args ) ;
}
}
2015-05-07 15:35:40 -04:00
Log ( "Commander setup only, done." ) ;
2014-08-22 13:39:55 -04:00
PrintRunTime ( ) ;
return ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
if ( ParseParam ( "SaveGraph" ) )
{
SaveGraphVisualization ( OrdereredToDo ) ;
}
if ( bListOnly )
{
Log ( "List only, done." ) ;
return ;
2015-04-21 15:21:51 -04:00
}
2014-08-22 13:39:55 -04:00
var BuildProductToNodeMap = new Dictionary < string , string > ( ) ;
2014-12-17 11:37:40 -05:00
foreach ( var NodeToDo in OrdereredToDo )
2014-08-22 13:39:55 -04:00
{
if ( GUBPNodes [ NodeToDo ] . BuildProducts ! = null | | GUBPNodes [ NodeToDo ] . AllDependencyBuildProducts ! = null )
{
throw new AutomationException ( "topological sort error" ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
GUBPNodes [ NodeToDo ] . AllDependencyBuildProducts = new List < string > ( ) ;
GUBPNodes [ NodeToDo ] . AllDependencies = new List < string > ( ) ;
foreach ( var Dep in GUBPNodes [ NodeToDo ] . FullNamesOfDependencies )
{
GUBPNodes [ NodeToDo ] . AddAllDependent ( Dep ) ;
if ( GUBPNodes [ Dep ] . AllDependencies = = null )
{
if ( ! bOnlyNode )
{
throw new AutomationException ( "Node {0} was not processed yet3? Processing {1}" , Dep , NodeToDo ) ;
}
}
2014-12-15 15:29:48 -05:00
else
{
foreach ( var DepDep in GUBPNodes [ Dep ] . AllDependencies )
{
GUBPNodes [ NodeToDo ] . AddAllDependent ( DepDep ) ;
}
}
2014-08-22 13:39:55 -04:00
if ( GUBPNodes [ Dep ] . BuildProducts = = null )
{
if ( ! bOnlyNode )
{
throw new AutomationException ( "Node {0} was not processed yet? Processing {1}" , Dep , NodeToDo ) ;
}
}
else
{
foreach ( var Prod in GUBPNodes [ Dep ] . BuildProducts )
{
GUBPNodes [ NodeToDo ] . AddDependentBuildProduct ( Prod ) ;
}
if ( GUBPNodes [ Dep ] . AllDependencyBuildProducts = = null )
{
throw new AutomationException ( "Node {0} was not processed yet2? Processing {1}" , Dep , NodeToDo ) ;
}
foreach ( var Prod in GUBPNodes [ Dep ] . AllDependencyBuildProducts )
{
GUBPNodes [ NodeToDo ] . AddDependentBuildProduct ( Prod ) ;
}
}
}
2014-04-25 12:35:08 -04:00
2014-08-22 13:39:55 -04:00
string NodeStoreName = StoreName + "-" + GUBPNodes [ NodeToDo ] . GetFullName ( ) ;
string GameNameIfAny = GUBPNodes [ NodeToDo ] . GameNameIfAnyForTempStorage ( ) ;
string StorageRootIfAny = GUBPNodes [ NodeToDo ] . RootIfAnyForTempStorage ( ) ;
2014-12-17 11:37:40 -05:00
2014-08-22 13:39:55 -04:00
if ( bFake )
{
StorageRootIfAny = "" ; // we don't rebase fake runs since those are entirely "records of success", which are always in the logs folder
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
// this is kinda complicated
bool SaveSuccessRecords = ( IsBuildMachine | | bFakeEC ) & & // no real reason to make these locally except for fakeEC tests
( ! GUBPNodes [ NodeToDo ] . TriggerNode ( ) | | GUBPNodes [ NodeToDo ] . IsSticky ( ) ) // trigger nodes are run twice, one to start the new workflow and once when it is actually triggered, we will save reconds for the latter
& & ( GUBPNodes [ NodeToDo ] . RunInEC ( ) | | ! GUBPNodes [ NodeToDo ] . IsAggregate ( ) ) ; //aggregates not in EC can be "run" multiple times, so we can't track those
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Log ( "***** Running GUBP Node {0} -> {1} : {2}" , GUBPNodes [ NodeToDo ] . GetFullName ( ) , GameNameIfAny , NodeStoreName ) ;
if ( NodeIsAlreadyComplete ( NodeToDo , LocalOnly ) )
{
if ( NodeToDo = = VersionFilesNode . StaticGetFullName ( ) & & ! IsBuildMachine )
{
Log ( "***** NOT ****** Retrieving GUBP Node {0} from {1}; it is the version files." , GUBPNodes [ NodeToDo ] . GetFullName ( ) , NodeStoreName ) ;
GUBPNodes [ NodeToDo ] . BuildProducts = new List < string > ( ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
}
else
{
Log ( "***** Retrieving GUBP Node {0} from {1}" , GUBPNodes [ NodeToDo ] . GetFullName ( ) , NodeStoreName ) ;
bool WasLocal ;
2015-01-15 12:07:10 -05:00
try
{
2015-02-10 14:58:32 -05:00
GUBPNodes [ NodeToDo ] . BuildProducts = RetrieveFromTempStorage ( CmdEnv , NodeStoreName , out WasLocal , GameNameIfAny , StorageRootIfAny ) ;
2015-01-15 12:07:10 -05:00
}
catch
{
if ( GameNameIfAny ! = "" )
{
GUBPNodes [ NodeToDo ] . BuildProducts = RetrieveFromTempStorage ( CmdEnv , NodeStoreName , out WasLocal , "" , StorageRootIfAny ) ;
}
else
{
throw new AutomationException ( "Build Products cannot be found for node {0}" , NodeToDo ) ;
}
}
2014-08-22 13:39:55 -04:00
if ( ! WasLocal )
{
GUBPNodes [ NodeToDo ] . PostLoadFromSharedTempStorage ( this ) ;
}
}
}
else
{
if ( SaveSuccessRecords )
{
SaveStatus ( NodeToDo , StartedTempStorageSuffix , NodeStoreName , bSaveSharedTempStorage , GameNameIfAny ) ;
}
2015-02-16 09:24:59 -05:00
var BuildDuration = 0.0 ;
2014-08-22 13:39:55 -04:00
try
{
if ( ! String . IsNullOrEmpty ( FakeFail ) & & FakeFail . Equals ( NodeToDo , StringComparison . InvariantCultureIgnoreCase ) )
{
throw new AutomationException ( "Failing node {0} by request." , NodeToDo ) ;
}
if ( bFake )
{
Log ( "***** FAKE!! Building GUBP Node {0} for {1}" , NodeToDo , NodeStoreName ) ;
GUBPNodes [ NodeToDo ] . DoFakeBuild ( this ) ;
}
else
2014-12-17 11:37:40 -05:00
{
Log ( "***** Building GUBP Node {0} for {1}" , NodeToDo , NodeStoreName ) ;
2015-02-16 09:24:59 -05:00
var StartTime = DateTime . UtcNow ;
2015-05-07 15:35:40 -04:00
var StartBuild = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
GUBPNodes [ NodeToDo ] . DoBuild ( this ) ;
2015-05-06 18:08:37 -04:00
var FinishBuild = DateTime . Now . ToString ( ) ;
if ( IsBuildMachine )
{
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,DoBuild,{0},{1}" , StartBuild , FinishBuild ) ) ;
2015-05-06 18:08:37 -04:00
}
2015-02-16 09:24:59 -05:00
BuildDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds / 1000 ;
2014-08-22 13:39:55 -04:00
}
if ( ! GUBPNodes [ NodeToDo ] . IsAggregate ( ) )
{
2015-02-17 16:43:54 -05:00
var StoreDuration = 0.0 ;
var StartTime = DateTime . UtcNow ;
2015-05-07 15:35:40 -04:00
var StartStore = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
StoreToTempStorage ( CmdEnv , NodeStoreName , GUBPNodes [ NodeToDo ] . BuildProducts , ! bSaveSharedTempStorage , GameNameIfAny , StorageRootIfAny ) ;
2015-02-17 16:43:54 -05:00
StoreDuration = ( DateTime . UtcNow - StartTime ) . TotalMilliseconds / 1000 ;
2015-05-07 15:35:40 -04:00
var FinishStore = DateTime . Now . ToString ( ) ;
2015-02-17 16:43:54 -05:00
Log ( "Took {0} seconds to store build products" , StoreDuration ) ;
if ( IsBuildMachine )
{
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,StoreBuildProducts,{0},{1}" , StartStore , FinishStore ) ) ;
2015-02-17 16:43:54 -05:00
RunECTool ( String . Format ( "setProperty \"/myJobStep/StoreDuration\" \"{0}\"" , StoreDuration . ToString ( ) ) ) ;
}
2014-08-22 13:39:55 -04:00
if ( ParseParam ( "StompCheck" ) )
{
foreach ( var Dep in GUBPNodes [ NodeToDo ] . AllDependencies )
{
try
{
bool WasLocal ;
2015-05-06 18:08:37 -04:00
var StartRetrieve = DateTime . Now . ToString ( ) ;
2014-12-17 11:37:40 -05:00
RetrieveFromTempStorage ( CmdEnv , NodeStoreName , out WasLocal , GameNameIfAny , StorageRootIfAny ) ;
2015-05-06 18:08:37 -04:00
var FinishRetrieve = DateTime . Now . ToString ( ) ;
if ( IsBuildMachine )
{
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,RetrieveBuildProducts,{0},{1}" , StartRetrieve , FinishRetrieve ) ) ;
2015-05-06 18:08:37 -04:00
}
2014-12-17 11:37:40 -05:00
if ( ! WasLocal )
{
throw new AutomationException ( "Retrieve was not local?" ) ;
}
2014-08-22 13:39:55 -04:00
}
catch ( Exception Ex )
{
throw new AutomationException ( "Node {0} stomped Node {1} Ex: {2}" , NodeToDo , Dep , LogUtils . FormatException ( Ex ) ) ;
}
}
}
2014-04-25 12:35:08 -04:00
2014-08-22 13:39:55 -04:00
}
}
catch ( Exception Ex )
{
if ( SaveSuccessRecords )
{
2015-05-01 20:39:36 -04:00
var StartNodeHistory = DateTime . Now . ToString ( ) ;
UpdateNodeHistory ( NodeToDo , CLString ) ;
2015-05-06 18:08:37 -04:00
var FinishNodeHistory = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
SaveStatus ( NodeToDo , FailedTempStorageSuffix , NodeStoreName , bSaveSharedTempStorage , GameNameIfAny , ParseParamValue ( "MyJobStepId" ) ) ;
2015-05-06 18:08:37 -04:00
var FinishSaveStatus = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
UpdateECProps ( NodeToDo , CLString ) ;
2015-05-01 20:39:36 -04:00
var FinishECPropUpdate = DateTime . Now . ToString ( ) ;
2015-05-06 18:08:37 -04:00
2015-03-03 07:56:18 -05:00
if ( IsBuildMachine )
{
GetFailureEmails ( NodeToDo , CLString ) ;
2015-05-01 20:39:36 -04:00
var FinishFailEmails = DateTime . Now . ToString ( ) ;
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,UpdateNodeHistory,{0},{1}" , StartNodeHistory , FinishNodeHistory ) ) ;
PrintCSVFile ( String . Format ( "UAT,SaveNodeStatus,{0},{1}" , FinishNodeHistory , FinishSaveStatus ) ) ;
PrintCSVFile ( String . Format ( "UAT,UpdateECProps,{0},{1}" , FinishSaveStatus , FinishECPropUpdate ) ) ;
PrintCSVFile ( String . Format ( "UAT,GetFailEmails,{0},{1}" , FinishECPropUpdate , FinishFailEmails ) ) ;
2015-03-03 07:56:18 -05:00
}
2015-02-16 09:24:59 -05:00
UpdateECBuildTime ( NodeToDo , BuildDuration ) ;
2014-08-22 13:39:55 -04:00
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
Log ( "{0}" , ExceptionToString ( Ex ) ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
if ( GUBPNodesHistory . ContainsKey ( NodeToDo ) )
{
var History = GUBPNodesHistory [ NodeToDo ] ;
Log ( "Changes since last green *********************************" ) ;
Log ( "" ) ;
Log ( "" ) ;
Log ( "" ) ;
PrintDetailedChanges ( History ) ;
Log ( "End changes since last green" ) ;
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string FailInfo = "" ;
FailInfo + = "********************************* Main log file" ;
FailInfo + = Environment . NewLine + Environment . NewLine ;
FailInfo + = LogUtils . GetLogTail ( ) ;
FailInfo + = Environment . NewLine + Environment . NewLine + Environment . NewLine ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string OtherLog = "See logfile for details: '" ;
if ( FailInfo . Contains ( OtherLog ) )
{
string LogFile = FailInfo . Substring ( FailInfo . IndexOf ( OtherLog ) + OtherLog . Length ) ;
if ( LogFile . Contains ( "'" ) )
{
LogFile = CombinePaths ( CmdEnv . LogFolder , LogFile . Substring ( 0 , LogFile . IndexOf ( "'" ) ) ) ;
if ( FileExists_NoExceptions ( LogFile ) )
{
FailInfo + = "********************************* Sub log file " + LogFile ;
FailInfo + = Environment . NewLine + Environment . NewLine ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
FailInfo + = LogUtils . GetLogTail ( LogFile ) ;
FailInfo + = Environment . NewLine + Environment . NewLine + Environment . NewLine ;
}
}
}
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
string Filename = CombinePaths ( CmdEnv . LogFolder , "LogTailsAndChanges.log" ) ;
WriteAllText ( Filename , FailInfo ) ;
2014-03-14 14:13:41 -04:00
2014-08-22 13:39:55 -04:00
throw ( Ex ) ;
}
if ( SaveSuccessRecords )
{
2015-05-01 20:39:36 -04:00
var StartNodeHistory = DateTime . Now . ToString ( ) ;
UpdateNodeHistory ( NodeToDo , CLString ) ;
2015-05-01 20:51:47 -04:00
var FinishNodeHistory = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
SaveStatus ( NodeToDo , SucceededTempStorageSuffix , NodeStoreName , bSaveSharedTempStorage , GameNameIfAny ) ;
2015-05-06 18:08:37 -04:00
var FinishSaveStatus = DateTime . Now . ToString ( ) ;
2014-08-22 13:39:55 -04:00
UpdateECProps ( NodeToDo , CLString ) ;
2015-05-01 20:39:36 -04:00
var FinishECPropUpdate = DateTime . Now . ToString ( ) ;
2015-05-06 18:08:37 -04:00
2015-03-03 07:56:18 -05:00
if ( IsBuildMachine )
{
GetFailureEmails ( NodeToDo , CLString ) ;
2015-05-01 20:39:36 -04:00
var FinishFailEmails = DateTime . Now . ToString ( ) ;
2015-05-07 15:35:40 -04:00
PrintCSVFile ( String . Format ( "UAT,UpdateNodeHistory,{0},{1}" , StartNodeHistory , FinishNodeHistory ) ) ;
PrintCSVFile ( String . Format ( "UAT,SaveNodeStatus,{0},{1}" , FinishNodeHistory , FinishSaveStatus ) ) ;
PrintCSVFile ( String . Format ( "UAT,UpdateECProps,{0},{1}" , FinishSaveStatus , FinishECPropUpdate ) ) ;
PrintCSVFile ( String . Format ( "UAT,GetFailEmails,{0},{1}" , FinishECPropUpdate , FinishFailEmails ) ) ;
2015-03-03 07:56:18 -05:00
}
2015-02-16 09:24:59 -05:00
UpdateECBuildTime ( NodeToDo , BuildDuration ) ;
2014-08-22 13:39:55 -04:00
}
}
foreach ( var Product in GUBPNodes [ NodeToDo ] . BuildProducts )
{
if ( BuildProductToNodeMap . ContainsKey ( Product ) )
{
throw new AutomationException ( "Overlapping build product: {0} and {1} both produce {2}" , BuildProductToNodeMap [ Product ] , NodeToDo , Product ) ;
}
BuildProductToNodeMap . Add ( Product , NodeToDo ) ;
}
2015-05-07 15:35:40 -04:00
}
2014-08-22 13:39:55 -04:00
PrintRunTime ( ) ;
}
2015-05-07 15:35:40 -04:00
2015-04-01 13:36:26 -04:00
/// <summary>
/// Sorts a list of nodes to display in EC. The default order is based on execution order and agent groups, whereas this function arranges nodes by
/// frequency then execution order, while trying to group nodes on parallel paths (eg. Mac/Windows editor nodes) together.
/// </summary>
static Dictionary < string , int > GetDisplayOrder ( List < string > NodeNames , Dictionary < string , string > InitialNodeDependencyNames , Dictionary < string , GUBPNode > GUBPNodes )
{
// Split the nodes into separate lists for each frequency
SortedDictionary < int , List < string > > NodesByFrequency = new SortedDictionary < int , List < string > > ( ) ;
foreach ( string NodeName in NodeNames )
{
List < string > NodesByThisFrequency ;
if ( ! NodesByFrequency . TryGetValue ( GUBPNodes [ NodeName ] . DependentCISFrequencyQuantumShift ( ) , out NodesByThisFrequency ) )
{
NodesByThisFrequency = new List < string > ( ) ;
NodesByFrequency . Add ( GUBPNodes [ NodeName ] . DependentCISFrequencyQuantumShift ( ) , NodesByThisFrequency ) ;
}
NodesByThisFrequency . Add ( NodeName ) ;
}
2015-04-01 16:26:41 -04:00
// Build the output list by scanning each frequency in order
2015-04-01 13:36:26 -04:00
HashSet < string > VisitedNodes = new HashSet < string > ( ) ;
Dictionary < string , int > SortedNodes = new Dictionary < string , int > ( ) ;
foreach ( List < string > NodesByThisFrequency in NodesByFrequency . Values )
{
2015-04-01 16:26:41 -04:00
// Find a list of nodes in each display group. If the group name matches the node name, put that node at the front of the list.
Dictionary < string , string > DisplayGroups = new Dictionary < string , string > ( ) ;
foreach ( string NodeName in NodesByThisFrequency )
{
string GroupName = GUBPNodes [ NodeName ] . GetDisplayGroupName ( ) ;
if ( ! DisplayGroups . ContainsKey ( GroupName ) )
{
DisplayGroups . Add ( GroupName , NodeName ) ;
}
else if ( GroupName = = NodeName )
{
DisplayGroups [ GroupName ] = NodeName + " " + DisplayGroups [ GroupName ] ;
}
else
{
DisplayGroups [ GroupName ] = DisplayGroups [ GroupName ] + " " + NodeName ;
}
}
// Build a list of ordering dependencies, putting all Mac nodes after Windows nodes with the same names.
Dictionary < string , string > NodeDependencyNames = new Dictionary < string , string > ( InitialNodeDependencyNames ) ;
foreach ( KeyValuePair < string , string > DisplayGroup in DisplayGroups )
{
string [ ] GroupNodes = DisplayGroup . Value . Split ( ' ' ) ;
for ( int Idx = 1 ; Idx < GroupNodes . Length ; Idx + + )
{
NodeDependencyNames [ GroupNodes [ Idx ] ] + = " " + GroupNodes [ 0 ] ;
}
}
// Add nodes for each frequency into the master list, trying to match up different groups along the way
2015-04-01 13:36:26 -04:00
foreach ( string FirstNodeName in NodesByThisFrequency )
{
string [ ] GroupNodeNames = DisplayGroups [ GUBPNodes [ FirstNodeName ] . GetDisplayGroupName ( ) ] . Split ( ' ' ) ;
foreach ( string GroupNodeName in GroupNodeNames )
{
AddNodeAndDependencies ( GroupNodeName , NodeDependencyNames , VisitedNodes , SortedNodes ) ;
}
}
}
return SortedNodes ;
}
static void AddNodeAndDependencies ( string NodeName , Dictionary < string , string > NodeDependencyNames , HashSet < string > VisitedNodes , Dictionary < string , int > SortedNodes )
{
if ( ! VisitedNodes . Contains ( NodeName ) )
{
VisitedNodes . Add ( NodeName ) ;
foreach ( string NodeDependencyName in NodeDependencyNames [ NodeName ] . Split ( new char [ ] { ' ' } , StringSplitOptions . RemoveEmptyEntries ) )
{
AddNodeAndDependencies ( NodeDependencyName , NodeDependencyNames , VisitedNodes , SortedNodes ) ;
}
SortedNodes . Add ( NodeName , SortedNodes . Count ) ;
}
}
2014-08-22 13:39:55 -04:00
string StartedTempStorageSuffix = "_Started" ;
string FailedTempStorageSuffix = "_Failed" ;
string SucceededTempStorageSuffix = "_Succeeded" ;
2014-03-14 14:13:41 -04:00
}