2019-12-26 23:01:54 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-08-20 09:26:18 -04:00
2019-08-16 13:41:27 -04:00
using System ;
using System.Collections.Generic ;
2019-11-04 08:41:55 -05:00
using System.IO ;
2019-08-16 13:41:27 -04:00
using System.Linq ;
2020-12-21 23:07:37 -04:00
using EpicGames.Core ;
2021-06-09 12:55:13 -04:00
using UnrealBuildBase ;
2019-08-16 13:41:27 -04:00
namespace UnrealBuildTool
{
class RiderProjectFileGenerator : ProjectFileGenerator
{
public override string ProjectFileExtension = > ".json" ;
private readonly DirectoryReference EngineSourceProgramsDirectory =
DirectoryReference . Combine ( UnrealBuildTool . EngineSourceDirectory , "Programs" ) ;
private readonly CommandLineArguments Arguments ;
2020-09-24 00:43:27 -04:00
/// <summary>
/// List of deprecated platforms.
/// Don't generate project model for these platforms unless they are specified in "Platforms" console arguments.
/// </summary>
/// <returns></returns>
2021-01-31 15:09:58 -04:00
private readonly HashSet < UnrealTargetPlatform > DeprecatedPlatforms = new HashSet < UnrealTargetPlatform > { } ;
2019-08-16 13:41:27 -04:00
/// <summary>
/// Platforms to generate project files for
/// </summary>
[CommandLine("-Platforms=", ListSeparator = '+')]
HashSet < UnrealTargetPlatform > Platforms = new HashSet < UnrealTargetPlatform > ( ) ;
/// <summary>
/// Target types to generate project files for
/// </summary>
[CommandLine("-TargetTypes=", ListSeparator = '+')]
HashSet < TargetType > TargetTypes = new HashSet < TargetType > ( ) ;
/// <summary>
/// Target configurations to generate project files for
/// </summary>
[CommandLine("-TargetConfigurations=", ListSeparator = '+')]
HashSet < UnrealTargetConfiguration > TargetConfigurations = new HashSet < UnrealTargetConfiguration > ( ) ;
/// <summary>
2020-09-24 00:43:27 -04:00
/// Projects to generate project files for
2019-08-16 13:41:27 -04:00
/// </summary>
[CommandLine("-ProjectNames=", ListSeparator = '+')]
HashSet < string > ProjectNames = new HashSet < string > ( ) ;
2020-09-24 00:43:27 -04:00
/// <summary>
/// Should format JSON files in human readable form, or use packed one without indents
/// </summary>
2020-10-29 13:38:15 -04:00
[CommandLine("-Minimize", Value = "Compact")]
2020-09-24 00:43:27 -04:00
private JsonWriterStyle Minimize = JsonWriterStyle . Readable ;
2021-11-18 14:37:34 -05:00
public RiderProjectFileGenerator ( FileReference ? InOnlyGameProject ,
2019-08-16 13:41:27 -04:00
CommandLineArguments InArguments )
: base ( InOnlyGameProject )
{
Arguments = InArguments ;
Arguments . ApplyTo ( this ) ;
}
public override bool ShouldGenerateIntelliSenseData ( ) = > true ;
2022-01-07 15:40:01 -05:00
public override void CleanProjectFiles ( DirectoryReference InPrimaryProjectDirectory , string InPrimaryProjectName ,
2019-08-16 13:41:27 -04:00
DirectoryReference InIntermediateProjectFilesDirectory )
{
2022-01-07 15:40:01 -05:00
DirectoryReference . Delete ( InPrimaryProjectDirectory ) ;
2019-08-16 13:41:27 -04:00
}
private void ConfigureProjectFileGeneration ( )
{
bIncludeConfigFiles = true ;
bIncludeEngineSource = true ;
bIncludeDocumentation = false ;
bIncludeShaderSource = true ;
bGenerateProjectFiles = true ;
bIncludeTemplateFiles = false ;
bIncludeTestAndShippingConfigs = true ;
2022-03-17 17:05:06 -04:00
bIncludeEnginePrograms = true ; // It's true by default, but I like to have things explicit
2019-08-16 13:41:27 -04:00
}
2021-11-18 14:37:34 -05:00
protected override ProjectFile AllocateProjectFile ( FileReference InitFilePath , DirectoryReference BaseDir )
2019-08-16 13:41:27 -04:00
{
2021-11-18 14:37:34 -05:00
RiderProjectFile projectFile = new RiderProjectFile ( InitFilePath , BaseDir ,
RootPath : InitFilePath . Directory , Arguments : Arguments , TargetTypes : TargetTypes ) ;
2019-08-16 13:41:27 -04:00
return projectFile ;
}
protected override bool WriteProjectFiles ( PlatformProjectGeneratorCollection PlatformProjectGenerators )
{
using ( ProgressWriter Progress = new ProgressWriter ( "Writing project files..." , true ) )
{
2020-04-14 09:30:15 -04:00
List < ProjectFile > ProjectsToGenerate = new List < ProjectFile > ( GeneratedProjectFiles ) ;
2019-08-16 13:41:27 -04:00
if ( ProjectNames . Any ( ) )
{
2020-04-14 09:30:15 -04:00
ProjectsToGenerate = ProjectsToGenerate . Where ( it = >
2019-08-16 13:41:27 -04:00
ProjectNames . Contains ( it . ProjectFilePath . GetFileNameWithoutAnyExtensions ( ) ) ) . ToList ( ) ;
}
2020-04-14 09:30:15 -04:00
int TotalProjectFileCount = ProjectsToGenerate . Count ;
2019-08-16 13:41:27 -04:00
2020-04-14 09:30:15 -04:00
HashSet < UnrealTargetPlatform > PlatformsToGenerate = new HashSet < UnrealTargetPlatform > ( SupportedPlatforms ) ;
2019-08-16 13:41:27 -04:00
if ( Platforms . Any ( ) )
{
2020-04-14 09:30:15 -04:00
PlatformsToGenerate . IntersectWith ( Platforms ) ;
2019-08-16 13:41:27 -04:00
}
2020-04-14 09:30:15 -04:00
List < UnrealTargetPlatform > FilteredPlatforms = PlatformsToGenerate . Where ( it = >
{
2020-09-24 00:43:27 -04:00
// Skip deprecated platforms if they are not specified in commandline arguments directly
if ( DeprecatedPlatforms . Contains ( it ) & & ! Platforms . Contains ( it ) ) return false ;
2020-04-14 09:30:15 -04:00
if ( UEBuildPlatform . IsPlatformAvailable ( it ) )
return true ;
Log . TraceWarning (
"Platform {0} is not a valid platform to build. Check that the SDK is installed properly" ,
it ) ;
Log . TraceWarning ( "Platform will be ignored in project file generation" ) ;
return false ;
} ) . ToList ( ) ;
HashSet < UnrealTargetConfiguration > ConfigurationsToGenerate = new HashSet < UnrealTargetConfiguration > ( SupportedConfigurations ) ;
2019-08-16 13:41:27 -04:00
if ( TargetConfigurations . Any ( ) )
{
2020-04-14 09:30:15 -04:00
ConfigurationsToGenerate . IntersectWith ( TargetConfigurations ) ;
2019-08-16 13:41:27 -04:00
}
2020-04-14 09:30:15 -04:00
for ( int ProjectFileIndex = 0 ; ProjectFileIndex < ProjectsToGenerate . Count ; + + ProjectFileIndex )
2019-08-16 13:41:27 -04:00
{
2021-11-18 14:37:34 -05:00
RiderProjectFile ? CurProject = ProjectsToGenerate [ ProjectFileIndex ] as RiderProjectFile ;
2020-09-24 00:43:27 -04:00
if ( CurProject ! = null )
2019-08-16 13:41:27 -04:00
{
2020-09-24 00:43:27 -04:00
if ( ! CurProject . WriteProjectFile ( FilteredPlatforms , ConfigurationsToGenerate . ToList ( ) ,
PlatformProjectGenerators , Minimize ) )
{
return false ;
}
2019-08-16 13:41:27 -04:00
}
Progress . Write ( ProjectFileIndex + 1 , TotalProjectFileCount ) ;
}
Progress . Write ( TotalProjectFileCount , TotalProjectFileCount ) ;
}
return true ;
}
2020-09-24 00:43:27 -04:00
private FileReference GetRiderProjectLocation ( string GeneratedProjectName )
2020-02-23 20:02:48 -05:00
{
2020-09-24 00:43:27 -04:00
if ( OnlyGameProject ! = null & & FileReference . Exists ( OnlyGameProject ) )
2020-02-23 20:02:48 -05:00
{
2020-09-24 00:43:27 -04:00
return FileReference . Combine ( OnlyGameProject . Directory , "Intermediate" , "ProjectFiles" , ".Rider" , GeneratedProjectName ) ;
2020-02-23 20:02:48 -05:00
}
else
{
2021-06-11 18:21:35 -04:00
return FileReference . Combine ( Unreal . EngineDirectory , "Intermediate" , "ProjectFiles" , ".Rider" , GeneratedProjectName ) ;
2020-02-23 20:02:48 -05:00
}
}
2019-08-16 13:41:27 -04:00
private void AddProjectsForAllTargets (
PlatformProjectGeneratorCollection PlatformProjectGenerators ,
List < FileReference > AllGames ,
2021-11-18 14:37:34 -05:00
out ProjectFile ? EngineProject ,
2019-11-04 08:41:55 -05:00
out List < ProjectFile > GameProjects ,
out Dictionary < FileReference , ProjectFile > ProgramProjects )
2019-08-16 13:41:27 -04:00
{
// As we're creating project files, we'll also keep track of whether we created an "engine" project and return that if we have one
EngineProject = null ;
GameProjects = new List < ProjectFile > ( ) ;
2019-11-04 08:41:55 -05:00
ProgramProjects = new Dictionary < FileReference , ProjectFile > ( ) ;
2019-08-16 13:41:27 -04:00
// Find all of the target files. This will filter out any modules or targets that don't
// belong to platforms we're generating project files for.
List < FileReference > AllTargetFiles = DiscoverTargets ( AllGames ) ;
// Sort the targets by name. When we have multiple targets of a given type for a project, we'll use the order to determine which goes in the primary project file (so that client names with a suffix will go into their own project).
AllTargetFiles = AllTargetFiles . OrderBy ( x = > x . FullName , StringComparer . OrdinalIgnoreCase ) . ToList ( ) ;
foreach ( FileReference TargetFilePath in AllTargetFiles )
{
string TargetName = TargetFilePath . GetFileNameWithoutAnyExtensions ( ) ;
// Check to see if this is an Engine target. That is, the target is located under the "Engine" folder
bool IsEngineTarget = false ;
bool WantProjectFileForTarget = true ;
2021-06-11 18:21:35 -04:00
if ( TargetFilePath . IsUnderDirectory ( Unreal . EngineDirectory ) )
2019-08-16 13:41:27 -04:00
{
// This is an engine target
IsEngineTarget = true ;
if ( TargetFilePath . IsUnderDirectory ( EngineSourceProgramsDirectory ) )
{
2022-03-17 17:05:06 -04:00
WantProjectFileForTarget = bIncludeEnginePrograms ;
2019-08-16 13:41:27 -04:00
}
else if ( TargetFilePath . IsUnderDirectory ( UnrealBuildTool . EngineSourceDirectory ) )
{
WantProjectFileForTarget = bIncludeEngineSource ;
}
}
if ( WantProjectFileForTarget )
{
RulesAssembly RulesAssembly ;
2022-03-28 20:50:06 -04:00
FileReference ? CheckProjectFile =
2019-08-16 13:41:27 -04:00
AllGames . FirstOrDefault ( x = > TargetFilePath . IsUnderDirectory ( x . Directory ) ) ;
if ( CheckProjectFile = = null )
{
2021-09-03 19:27:06 -04:00
RulesAssembly = RulesCompiler . CreateEngineRulesAssembly ( false , false , false ) ;
2019-08-16 13:41:27 -04:00
}
else
{
2021-09-03 19:27:06 -04:00
RulesAssembly = RulesCompiler . CreateProjectRulesAssembly ( CheckProjectFile , false , false , false ) ;
2019-08-16 13:41:27 -04:00
}
// Create target rules for all of the platforms and configuration combinations that we want to enable support for.
// Just use the current platform as we only need to recover the target type and both should be supported for all targets...
TargetRules TargetRulesObject = RulesAssembly . CreateTargetRules ( TargetName ,
BuildHostPlatform . Current . Platform , UnrealTargetConfiguration . Development , "" , CheckProjectFile ,
null ) ;
bool IsProgramTarget = false ;
2021-11-18 14:37:34 -05:00
DirectoryReference ? GameFolder = null ;
2019-08-16 13:41:27 -04:00
string ProjectFileNameBase ;
if ( TargetRulesObject . Type = = TargetType . Program )
{
IsProgramTarget = true ;
ProjectFileNameBase = TargetName ;
}
else if ( IsEngineTarget )
{
ProjectFileNameBase = EngineProjectFileNameBase ;
}
else
{
// Figure out which game project this target belongs to
2021-11-18 14:37:34 -05:00
FileReference ? ProjectInfo = FindGameContainingFile ( AllGames , TargetFilePath ) ;
2019-08-16 13:41:27 -04:00
if ( ProjectInfo = = null )
{
throw new BuildException ( "Found a non-engine target file (" + TargetFilePath +
") that did not exist within any of the known game folders" ) ;
}
GameFolder = ProjectInfo . Directory ;
ProjectFileNameBase = ProjectInfo . GetFileNameWithoutExtension ( ) ;
}
// Get the suffix to use for this project file. If we have multiple targets of the same type, we'll have to split them out into separate IDE project files.
2021-11-18 14:37:34 -05:00
string? GeneratedProjectName = TargetRulesObject . GeneratedProjectName ;
2019-08-16 13:41:27 -04:00
if ( GeneratedProjectName = = null )
{
2021-11-18 14:37:34 -05:00
ProjectFile ? ExistingProjectFile ;
2020-09-24 00:43:27 -04:00
if ( ProjectFileMap . TryGetValue ( GetRiderProjectLocation ( ProjectFileNameBase ) , out ExistingProjectFile ) & &
2021-11-18 14:37:34 -05:00
ExistingProjectFile . ProjectTargets . Any ( x = > x . TargetRules ! . Type = = TargetRulesObject . Type ) )
2019-08-16 13:41:27 -04:00
{
GeneratedProjectName = TargetRulesObject . Name ;
}
else
{
GeneratedProjectName = ProjectFileNameBase ;
}
}
2020-09-24 00:43:27 -04:00
FileReference ProjectFilePath = GetRiderProjectLocation ( GeneratedProjectName ) ;
2019-08-16 13:41:27 -04:00
if ( TargetRulesObject . Type = = TargetType . Game | | TargetRulesObject . Type = = TargetType . Client | |
TargetRulesObject . Type = = TargetType . Server )
{
// Allow platforms to generate stub projects here...
PlatformProjectGenerators . GenerateGameProjectStubs (
InGenerator : this ,
InTargetName : TargetName ,
InTargetFilepath : TargetFilePath . FullName ,
InTargetRules : TargetRulesObject ,
InPlatforms : SupportedPlatforms ,
InConfigurations : SupportedConfigurations ) ;
}
DirectoryReference BaseFolder ;
if ( IsProgramTarget )
{
BaseFolder = TargetFilePath . Directory ;
}
else if ( IsEngineTarget )
{
2021-06-11 18:21:35 -04:00
BaseFolder = Unreal . EngineDirectory ;
2019-08-16 13:41:27 -04:00
}
else
{
2021-11-18 14:37:34 -05:00
BaseFolder = GameFolder ! ;
2019-08-16 13:41:27 -04:00
}
bool bProjectAlreadyExisted ;
ProjectFile ProjectFile = FindOrAddProject ( ProjectFilePath , BaseFolder ,
true , out bProjectAlreadyExisted ) ;
ProjectFile . IsForeignProject =
CheckProjectFile ! = null & & ! NativeProjects . IsNativeProject ( CheckProjectFile ) ;
ProjectFile . IsGeneratedProject = true ;
ProjectFile . IsStubProject = UnrealBuildTool . IsProjectInstalled ( ) ;
if ( TargetRulesObject . bBuildInSolutionByDefault . HasValue )
{
ProjectFile . ShouldBuildByDefaultForSolutionTargets =
TargetRulesObject . bBuildInSolutionByDefault . Value ;
}
// Add the project to the right output list
2019-11-04 08:41:55 -05:00
if ( IsProgramTarget )
{
ProgramProjects [ TargetFilePath ] = ProjectFile ;
}
else if ( IsEngineTarget )
2019-08-16 13:41:27 -04:00
{
EngineProject = ProjectFile ;
2021-06-11 18:21:35 -04:00
if ( Unreal . IsEngineInstalled ( ) )
2019-08-16 13:41:27 -04:00
{
// Allow engine projects to be created but not built for Installed Engine builds
EngineProject . IsForeignProject = false ;
EngineProject . IsGeneratedProject = true ;
EngineProject . IsStubProject = true ;
}
}
else
{
if ( ! bProjectAlreadyExisted )
{
GameProjects . Add ( ProjectFile ) ;
// Add the .uproject file for this game/template
FileReference UProjectFilePath =
FileReference . Combine ( BaseFolder , ProjectFileNameBase + ".uproject" ) ;
if ( FileReference . Exists ( UProjectFilePath ) )
{
ProjectFile . AddFileToProject ( UProjectFilePath , BaseFolder ) ;
}
else
{
throw new BuildException (
"Not expecting to find a game with no .uproject file. File '{0}' doesn't exist" ,
UProjectFilePath ) ;
}
}
}
2021-11-18 14:37:34 -05:00
foreach ( Project ExistingProjectTarget in ProjectFile . ProjectTargets )
2019-08-16 13:41:27 -04:00
{
2021-11-18 14:37:34 -05:00
if ( ExistingProjectTarget . TargetRules ! . Type = = TargetRulesObject . Type )
2019-08-16 13:41:27 -04:00
{
throw new BuildException (
"Not expecting project {0} to already have a target rules of with configuration name {1} ({2}) while trying to add: {3}" ,
ProjectFilePath , TargetRulesObject . Type . ToString ( ) ,
ExistingProjectTarget . TargetRules . ToString ( ) , TargetRulesObject . ToString ( ) ) ;
}
// Not expecting to have both a game and a program in the same project. These would alias because we share the project and solution configuration names (just because it makes sense to)
if ( ( ExistingProjectTarget . TargetRules . Type = = TargetType . Game & &
TargetRulesObject . Type = = TargetType . Program ) | |
( ExistingProjectTarget . TargetRules . Type = = TargetType . Program & &
TargetRulesObject . Type = = TargetType . Game ) )
{
throw new BuildException (
"Not expecting project {0} to already have a Game/Program target ({1}) associated with it while trying to add: {2}" ,
ProjectFilePath , ExistingProjectTarget . TargetRules . ToString ( ) ,
TargetRulesObject . ToString ( ) ) ;
}
}
2021-11-18 14:37:34 -05:00
ProjectTarget ProjectTarget = new ProjectTarget
(
TargetRules : TargetRulesObject ,
TargetFilePath : TargetFilePath ,
ProjectFilePath : ProjectFilePath ,
UnrealProjectFilePath : CheckProjectFile ,
SupportedPlatforms : TargetRulesObject . GetSupportedPlatforms ( )
2020-12-20 17:32:59 -04:00
. Where ( x = > UEBuildPlatform . TryGetBuildPlatform ( x , out _ ) ) . ToArray ( ) ,
2021-11-18 14:37:34 -05:00
CreateRulesDelegate : ( Platform , Configuration ) = >
2019-08-16 13:41:27 -04:00
RulesAssembly . CreateTargetRules ( TargetName , Platform , Configuration , "" , CheckProjectFile ,
null )
2021-11-18 14:37:34 -05:00
) ;
2019-08-16 13:41:27 -04:00
ProjectFile . ProjectTargets . Add ( ProjectTarget ) ;
// Make sure the *.Target.cs file is in the project.
ProjectFile . AddFileToProject ( TargetFilePath , BaseFolder ) ;
Log . TraceVerbose ( "Generating target {0} for {1}" , TargetRulesObject . Type . ToString ( ) ,
ProjectFilePath ) ;
}
}
}
private void SetupSupportedPlatformsAndConfigurations ( )
{
2019-08-16 13:49:52 -04:00
string SupportedPlatformNames ;
SetupSupportedPlatformsAndConfigurations ( true , out SupportedPlatformNames ) ;
2019-08-16 13:41:27 -04:00
}
public override bool GenerateProjectFiles ( PlatformProjectGeneratorCollection PlatformProjectGenerators ,
String [ ] arguments )
{
ConfigureProjectFileGeneration ( ) ;
2020-09-24 00:43:27 -04:00
if ( bGeneratingGameProjectFiles )
2019-08-16 13:41:27 -04:00
{
2022-01-07 15:40:01 -05:00
PrimaryProjectPath = OnlyGameProject ! . Directory ;
PrimaryProjectName = OnlyGameProject . GetFileNameWithoutExtension ( ) ;
2019-08-16 13:41:27 -04:00
2022-01-07 15:40:01 -05:00
if ( ! DirectoryReference . Exists ( DirectoryReference . Combine ( PrimaryProjectPath , "Source" ) ) )
2019-08-16 13:41:27 -04:00
{
2022-01-07 15:40:01 -05:00
if ( ! DirectoryReference . Exists ( DirectoryReference . Combine ( PrimaryProjectPath , "Intermediate" ,
2019-08-16 13:41:27 -04:00
"Source" ) ) )
{
if ( BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Mac )
{
2022-01-07 15:40:01 -05:00
PrimaryProjectPath = Unreal . EngineDirectory ;
2020-09-11 15:54:42 -04:00
GameProjectName = "UnrealGame" ;
2019-08-16 13:41:27 -04:00
}
2022-01-07 15:40:01 -05:00
if ( ! DirectoryReference . Exists ( DirectoryReference . Combine ( PrimaryProjectPath , "Source" ) ) )
2019-08-16 13:41:27 -04:00
{
2022-01-07 15:40:01 -05:00
throw new BuildException ( "Directory '{0}' is missing 'Source' folder." , PrimaryProjectPath ) ;
2019-08-16 13:41:27 -04:00
}
}
}
IntermediateProjectFilesPath =
2022-01-07 15:40:01 -05:00
DirectoryReference . Combine ( PrimaryProjectPath , "Intermediate" , "ProjectFiles" ) ;
2019-08-16 13:41:27 -04:00
}
SetupSupportedPlatformsAndConfigurations ( ) ;
Log . TraceVerbose ( "Detected supported platforms: " + SupportedPlatforms ) ;
List < FileReference > AllGameProjects = FindGameProjects ( ) ;
GatherProjects ( PlatformProjectGenerators , AllGameProjects ) ;
WriteProjectFiles ( PlatformProjectGenerators ) ;
Log . TraceVerbose ( "Project generation complete ({0} generated, {1} imported)" , GeneratedProjectFiles . Count ,
OtherProjectFiles . Count ) ;
return true ;
}
private void GatherProjects ( PlatformProjectGeneratorCollection PlatformProjectGenerators ,
List < FileReference > AllGameProjects )
{
2021-11-18 14:37:34 -05:00
ProjectFile ? EngineProject = null ;
List < ProjectFile > ? GameProjects = null ;
2021-12-19 16:09:38 -05:00
List < ProjectFile > ? ModProjects = new List < ProjectFile > ( ) ;
2021-11-18 14:37:34 -05:00
Dictionary < FileReference , ProjectFile > ? ProgramProjects = null ;
2019-11-04 08:41:55 -05:00
2019-08-16 13:41:27 -04:00
// Setup buildable projects for all targets
AddProjectsForAllTargets ( PlatformProjectGenerators , AllGameProjects , out EngineProject ,
2019-11-04 08:41:55 -05:00
out GameProjects , out ProgramProjects ) ;
2019-08-16 13:41:27 -04:00
2021-12-19 16:09:38 -05:00
AddProjectsForMods ( GameProjects , ModProjects ) ;
2021-11-18 14:37:34 -05:00
AddAllGameProjects ( GameProjects ) ;
2019-08-16 13:41:27 -04:00
// If we're still missing an engine project because we don't have any targets for it, make one up.
if ( EngineProject = = null )
{
FileReference ProjectFilePath = FileReference . Combine ( IntermediateProjectFilesPath ,
EngineProjectFileNameBase + ProjectFileExtension ) ;
2019-08-16 13:49:52 -04:00
bool bAlreadyExisted ;
2021-06-11 18:21:35 -04:00
EngineProject = FindOrAddProject ( ProjectFilePath , Unreal . EngineDirectory , true , out bAlreadyExisted ) ;
2019-08-16 13:41:27 -04:00
EngineProject . IsForeignProject = false ;
EngineProject . IsGeneratedProject = true ;
EngineProject . IsStubProject = true ;
}
}
2022-01-07 15:40:01 -05:00
protected override bool WritePrimaryProjectFile ( ProjectFile ? ProjectFile ,
2019-08-16 13:41:27 -04:00
PlatformProjectGeneratorCollection PlatformProjectGenerators )
{
return true ;
}
}
2020-10-29 13:38:15 -04:00
}