2022-01-19 15:00:37 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2022-06-07 12:37:53 -04:00
using System ;
2022-01-19 15:00:37 -05:00
using System.IO ;
2022-06-07 12:37:53 -04:00
using System.Reflection ;
using System.Runtime.Serialization ;
2023-05-30 18:38:07 -04:00
using EpicGames.Core ;
2022-03-24 13:28:25 -04:00
using UnrealBuildBase ;
2022-01-19 15:00:37 -05:00
namespace UnrealBuildTool
{
/// <summary>
/// TargetRules extension for low level tests.
/// </summary>
public class TestTargetRules : TargetRules
{
2023-06-29 15:18:42 -04:00
/// <summary>
/// Configuration mapping to control build graph test metadata generation during project files generation.
/// </summary>
[ConfigFile(ConfigHierarchyType.Engine, "LowLevelTestsSettings")]
public bool bUpdateBuildGraphPropertiesFile = false ;
2022-04-20 14:24:59 -04:00
/// <summary>
/// Keeps track if low level tests executable must build with the Editor.
/// </summary>
2023-03-29 20:09:34 -04:00
internal bool bTestsRequireEditor = false ;
2022-04-20 14:24:59 -04:00
/// <summary>
/// Keeps track if low level tests executable must build with the Engine.
/// </summary>
2023-03-29 20:09:34 -04:00
internal bool bTestsRequireEngine = false ;
2022-04-20 14:24:59 -04:00
/// <summary>
/// Keeps track if low level tests executable must build with the ApplicationCore.
/// </summary>
2023-03-29 20:09:34 -04:00
internal bool bTestsRequireApplicationCore = false ;
2022-04-20 14:24:59 -04:00
/// <summary>
/// Keeps track if low level tests executable must build with the CoreUObject.
/// </summary>
2023-03-29 20:09:34 -04:00
internal bool bTestsRequireCoreUObject = false ;
2022-04-20 14:24:59 -04:00
/// <summary>
/// Keep track of low level test runner module instance.
/// </summary>
2023-03-29 20:09:34 -04:00
internal ModuleRules ? LowLevelTestsRunnerModule ;
2022-04-20 14:24:59 -04:00
2022-01-19 15:00:37 -05:00
/// <summary>
2022-04-27 12:36:35 -04:00
/// Associated tested target of this test target, if defined.
2022-01-19 15:00:37 -05:00
/// </summary>
2022-04-27 12:36:35 -04:00
protected TargetRules ? TestedTarget { get ; private set ; }
2022-01-19 15:00:37 -05:00
/// <summary>
2022-04-27 12:36:35 -04:00
/// Test target override for bCompileAgainstApplicationCore.
2023-02-06 14:27:24 -05:00
/// It is set to true if there is any reference to ApplicationCore in the dependency graph.
2022-04-27 12:36:35 -04:00
/// </summary>
public override bool bCompileAgainstApplicationCore
{
2023-05-30 18:01:50 -04:00
get = > bTestsRequireApplicationCore ;
set = > bTestsRequireApplicationCore = value ;
2022-04-27 12:36:35 -04:00
}
2023-02-06 14:27:24 -05:00
/// <summary>
/// If set to true, it will not compile against ApplicationCore even if "ApplicationCore" is in the dependency graph.
/// </summary>
2023-06-29 15:18:42 -04:00
public bool bNeverCompileAgainstApplicationCore = false ;
2023-02-06 14:27:24 -05:00
2022-04-27 12:36:35 -04:00
/// <summary>
/// Test target override for bCompileAgainstCoreUObject.
2023-02-06 14:27:24 -05:00
/// It is set to true if there is any reference to CoreUObject in the dependency graph.
2022-04-27 12:36:35 -04:00
/// </summary>
public override bool bCompileAgainstCoreUObject
{
2023-05-30 18:01:50 -04:00
get = > bTestsRequireCoreUObject ;
set = > bTestsRequireCoreUObject = value ;
2022-04-27 12:36:35 -04:00
}
2023-02-06 14:27:24 -05:00
/// <summary>
/// If set to true, it will not compile against CoreUObject even if "CoreUObject" is in the dependency graph.
/// </summary>
2023-06-29 15:18:42 -04:00
public bool bNeverCompileAgainstCoreUObject = false ;
2023-02-06 14:27:24 -05:00
2022-04-27 12:36:35 -04:00
/// <summary>
/// Test target override for bCompileAgainstEngine.
2023-02-06 14:27:24 -05:00
/// It is set to true if there is any reference to Engine in the dependency graph.
2022-04-27 12:36:35 -04:00
/// </summary>
public override bool bCompileAgainstEngine
{
2023-05-30 18:01:50 -04:00
get = > bTestsRequireEngine ;
set = > bTestsRequireEngine = value ;
2022-04-27 12:36:35 -04:00
}
2023-02-06 14:27:24 -05:00
/// <summary>
/// If set to true, it will not compile against engine even if "Engine" is in the dependency graph.
/// </summary>
2023-06-29 15:18:42 -04:00
public bool bNeverCompileAgainstEngine = false ;
2023-02-06 14:27:24 -05:00
2022-04-27 12:36:35 -04:00
/// <summary>
/// Test target override for bCompileAgainstEditor.
2023-02-06 14:27:24 -05:00
/// It is set to true if there is any reference to UnrealEd in the dependency graph.
2022-04-27 12:36:35 -04:00
/// </summary>
public override bool bCompileAgainstEditor
{
2023-05-30 18:01:50 -04:00
get = > bTestsRequireEditor ;
set = > bTestsRequireEditor = value ;
2022-04-27 12:36:35 -04:00
}
2023-02-06 14:27:24 -05:00
/// <summary>
/// If set to true, it will not compile against editor even if "UnrealEd" is in the dependency graph.
/// </summary>
2023-06-29 15:18:42 -04:00
public bool bNeverCompileAgainstEditor = false ;
2023-02-06 14:27:24 -05:00
2022-04-27 12:36:35 -04:00
/// <summary>
2023-02-24 15:27:37 -05:00
/// Whether to stub the platform file.
/// </summary>
public bool bUsePlatformFileStub
2023-05-30 18:01:50 -04:00
{
get = > bUsePlatformFileStubPrivate ;
2023-02-24 15:27:37 -05:00
set
{
bUsePlatformFileStubPrivate = value ;
GlobalDefinitions . Remove ( "UE_LLT_USE_PLATFORM_FILE_STUB=0" ) ;
GlobalDefinitions . Remove ( "UE_LLT_USE_PLATFORM_FILE_STUB=1" ) ;
GlobalDefinitions . Add ( $"UE_LLT_USE_PLATFORM_FILE_STUB={Convert.ToInt32(bUsePlatformFileStubPrivate)}" ) ;
}
}
private bool bUsePlatformFileStubPrivate = false ;
/// <summary>
/// Whether to mock engine default instances for materials, AI controller etc.
/// </summary>
public bool bMockEngineDefaults
{
2023-05-30 18:01:50 -04:00
get = > bMockEngineDefaultsPrivate ;
2023-02-24 15:27:37 -05:00
set
{
bMockEngineDefaultsPrivate = value ;
GlobalDefinitions . Remove ( "UE_LLT_WITH_MOCK_ENGINE_DEFAULTS=0" ) ;
GlobalDefinitions . Remove ( "UE_LLT_WITH_MOCK_ENGINE_DEFAULTS=1" ) ;
GlobalDefinitions . Add ( $"UE_LLT_WITH_MOCK_ENGINE_DEFAULTS={Convert.ToInt32(bMockEngineDefaultsPrivate)}" ) ;
}
}
private bool bMockEngineDefaultsPrivate = false ;
/// <summary>
/// Constructor that explicit targets can inherit from.
2022-04-27 12:36:35 -04:00
/// </summary>
/// <param name="Target"></param>
public TestTargetRules ( TargetInfo Target ) : base ( Target )
{
SetupCommonProperties ( Target ) ;
2023-05-30 18:59:32 -04:00
ExeBinariesSubFolder = LaunchModuleName = Name + ( ExplicitTestsTarget ? String . Empty : "Tests" ) ;
2022-04-27 12:36:35 -04:00
2023-02-06 14:27:24 -05:00
if ( ExplicitTestsTarget )
2022-04-27 12:36:35 -04:00
{
2022-05-19 16:29:25 -04:00
bBuildInSolutionByDefault = true ;
2023-05-25 16:08:34 -04:00
if ( ProjectFile ! = null )
{
DirectoryReference SamplesDirectory = DirectoryReference . Combine ( Unreal . RootDirectory , "Samples" ) ;
if ( ! ProjectFile . IsUnderDirectory ( Unreal . EngineDirectory ) )
{
if ( ProjectFile . IsUnderDirectory ( SamplesDirectory ) )
{
SolutionDirectory = Path . Combine ( "Samples" , ProjectFile . Directory . GetDirectoryName ( ) , "LowLevelTests" ) ;
}
else
{
SolutionDirectory = Path . Combine ( "Games" , ProjectFile . Directory . GetDirectoryName ( ) , "LowLevelTests" ) ;
}
}
2023-05-26 16:23:08 -04:00
else
{
SolutionDirectory = "Programs/LowLevelTests" ;
}
2023-05-25 16:08:34 -04:00
}
else
{
SolutionDirectory = "Programs/LowLevelTests" ;
}
2023-02-24 15:27:37 -05:00
// Default to true for explicit targets to reduce compilation times.
// Selective module compilation will automatically detect if Engine is required based on Engine include files in tests.
bNeverCompileAgainstEngine = true ;
2022-04-27 12:36:35 -04:00
}
2022-10-21 18:00:09 -04:00
if ( Target . Platform = = UnrealTargetPlatform . Win64 )
{
string OutputName = "$(TargetName)" ;
2023-05-30 18:38:07 -04:00
if ( Target . Configuration ! = UndecoratedConfiguration )
2022-10-21 18:00:09 -04:00
{
OutputName = OutputName + "-" + Target . Platform + "-" + Target . Configuration ;
}
2022-11-02 14:43:21 -04:00
if ( File ! = null )
{
2023-06-12 15:00:47 -04:00
DirectoryReference OutputDirectory ;
if ( ProjectFile ! = null & & File . IsUnderDirectory ( ProjectFile . Directory ) )
{
OutputDirectory = UEBuildTarget . GetOutputDirectoryForExecutable ( ProjectFile . Directory , File ) ;
}
else
{
OutputDirectory = UEBuildTarget . GetOutputDirectoryForExecutable ( Unreal . EngineDirectory , File ) ;
}
FileReference OutputTestFile = FileReference . Combine ( OutputDirectory , "Binaries" , Target . Platform . ToString ( ) , ExeBinariesSubFolder , $"{OutputName}.exe.is_unreal_test" ) ;
PostBuildSteps . Add ( "echo > " + OutputTestFile . FullName ) ;
2022-11-02 14:43:21 -04:00
}
2022-10-21 18:00:09 -04:00
}
2022-04-27 12:36:35 -04:00
}
2022-06-07 12:37:53 -04:00
/// <summary>
/// Constructs a valid TestTargetRules instance from an existent TargetRules instance.
/// </summary>
public static TestTargetRules Create ( TargetRules Rules , TargetInfo TargetInfo )
{
Type TestTargetRulesType = typeof ( TestTargetRules ) ;
TestTargetRules TestRules = ( TestTargetRules ) FormatterServices . GetUninitializedObject ( TestTargetRulesType ) ;
// Initialize the logger before calling the constructor
TestRules . Logger = Rules . Logger ;
ConstructorInfo ? Constructor = TestTargetRulesType . GetConstructor ( new Type [ ] { typeof ( TargetRules ) , typeof ( TargetInfo ) } ) ;
if ( Constructor = = null )
{
throw new BuildException ( "No constructor found on {0} which takes first argument of type TargetRules and second of type TargetInfo." , TestTargetRulesType . Name ) ;
}
try
{
Constructor . Invoke ( TestRules , new object [ ] { Rules , TargetInfo } ) ;
}
catch ( Exception Ex )
{
throw new BuildException ( Ex , "Unable to instantiate instance of '{0}' object type from compiled assembly '{1}'. Unreal Build Tool creates an instance of your module's 'Rules' object in order to find out about your module's requirements. The CLR exception details may provide more information: {2}" , TestTargetRulesType . Name , Path . GetFileNameWithoutExtension ( TestTargetRulesType . Assembly ? . Location ) , Ex . ToString ( ) ) ;
}
return TestRules ;
}
2022-04-27 12:36:35 -04:00
/// <summary>
/// Constructor for TestTargetRules based on existing target.
/// TestTargetRules is setup as a program and is linked monolithically.
2022-01-19 15:00:37 -05:00
/// It removes a lot of default compilation behavior in order to produce a minimal test environment.
/// </summary>
public TestTargetRules ( TargetRules TestedTarget , TargetInfo Target ) : base ( Target )
{
if ( TestedTarget is TestTargetRules )
{
throw new BuildException ( "TestedTarget can't be of type TestTargetRules." ) ;
}
this . TestedTarget = TestedTarget ;
2023-02-06 14:27:24 -05:00
TargetFiles = TestedTarget . TargetFiles ;
2022-01-19 15:00:37 -05:00
ExeBinariesSubFolder = Name = TestedTarget . Name + "Tests" ;
2022-04-20 14:24:59 -04:00
TargetSourceFile = File = TestedTarget . File ;
2022-04-27 12:36:35 -04:00
if ( TestedTarget . LaunchModuleName ! = null )
{
LaunchModuleName = TestedTarget . LaunchModuleName + "Tests" ;
}
2022-01-19 15:00:37 -05:00
2022-03-24 13:28:25 -04:00
ManifestFileNames = TestedTarget . ManifestFileNames ;
2022-01-19 15:00:37 -05:00
WindowsPlatform = TestedTarget . WindowsPlatform ;
2022-04-27 12:36:35 -04:00
SetupCommonProperties ( Target ) ;
}
private void SetupCommonProperties ( TargetInfo Target )
{
2023-02-06 14:27:24 -05:00
IncludeOrderVersion = EngineIncludeOrderVersion . Latest ;
2022-04-27 12:36:35 -04:00
bIsTestTargetOverride = true ;
VSTestRunSettingsFile = FileReference . Combine ( Unreal . EngineDirectory , "Source" , "Programs" , "LowLevelTests" , "vstest.runsettings" ) ;
2022-10-31 20:57:12 -04:00
DefaultBuildSettings = BuildSettingsVersion . Latest ;
2022-04-27 12:36:35 -04:00
2022-01-19 15:00:37 -05:00
Type = TargetType . Program ;
LinkType = TargetLinkType . Monolithic ;
bBuildInSolutionByDefault = false ;
2022-03-24 13:28:25 -04:00
bDeployAfterCompile = Target . Platform ! = UnrealTargetPlatform . Android ;
2022-01-19 15:00:37 -05:00
bIsBuildingConsoleApplication = true ;
// Disabling default true flags that aren't necessary for tests
// Lean and Mean mode
bBuildDeveloperTools = false ;
// No localization
bCompileICU = false ;
// No need for shaders by default
bForceBuildShaderFormats = false ;
2023-02-06 14:27:24 -05:00
// Do not compile against the engine, editor etc
2022-01-19 15:00:37 -05:00
bCompileAgainstEngine = false ;
2023-02-06 14:27:24 -05:00
bCompileAgainstEditor = false ;
2022-01-19 15:00:37 -05:00
bCompileAgainstCoreUObject = false ;
bCompileAgainstApplicationCore = false ;
2023-02-06 14:27:24 -05:00
bCompileCEF3 = false ;
// No mixing with Functional Test framework
bForceDisableAutomationTests = true ;
bDebugBuildsActuallyUseDebugCRT = true ;
// Allow logging in shipping
2022-01-19 15:00:37 -05:00
bUseLoggingInShipping = true ;
2022-03-24 13:28:25 -04:00
// Allow exception handling
bForceEnableExceptions = true ;
2023-02-06 14:27:24 -05:00
bBuildWithEditorOnlyData = false ;
bBuildRequiresCookedData = true ;
bBuildDeveloperTools = false ;
2022-01-19 15:00:37 -05:00
// Useful for debugging test failures
if ( Target . Configuration = = UnrealTargetConfiguration . Debug )
{
bDebugBuildsActuallyUseDebugCRT = true ;
}
2023-02-06 14:27:24 -05:00
if ( ! ExplicitTestsTarget & & TestedTarget ! = null )
{
GlobalDefinitions . AddRange ( TestedTarget . GlobalDefinitions ) ;
}
2022-01-19 15:00:37 -05:00
GlobalDefinitions . Add ( "STATS=0" ) ;
2022-03-24 13:28:25 -04:00
GlobalDefinitions . Add ( "TEST_FOR_VALID_FILE_SYSTEM_MEMORY=0" ) ;
2023-05-30 18:38:07 -04:00
2023-02-24 15:27:37 -05:00
// LLT Globals
GlobalDefinitions . Add ( "UE_LLT_USE_PLATFORM_FILE_STUB=0" ) ;
GlobalDefinitions . Add ( "UE_LLT_WITH_MOCK_ENGINE_DEFAULTS=0" ) ;
2022-01-19 15:00:37 -05:00
// Platform specific setup
if ( Target . Platform = = UnrealTargetPlatform . Android )
{
UndecoratedConfiguration = Target . Configuration ;
GlobalDefinitions . Add ( "USE_ANDROID_INPUT=0" ) ;
GlobalDefinitions . Add ( "USE_ANDROID_OPENGL=0" ) ;
GlobalDefinitions . Add ( "USE_ANDROID_LAUNCH=0" ) ;
GlobalDefinitions . Add ( "USE_ANDROID_JNI=0" ) ;
}
2023-06-15 04:50:22 -04:00
else if ( Target . Platform = = UnrealTargetPlatform . IOS )
2022-01-19 15:00:37 -05:00
{
2022-04-27 12:36:35 -04:00
bIsBuildingConsoleApplication = false ;
2022-01-19 15:00:37 -05:00
}
}
}
}