// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using EpicGames.Core;
using Microsoft.Extensions.Logging;
namespace UnrealBuildTool
{
///
/// Base class for platform-specific project generators
///
abstract class PlatformProjectGenerator
{
public static readonly string DefaultPlatformConfigurationType = "Makefile";
protected readonly ILogger Logger;
///
/// Constructor
///
/// Command line arguments passed to the project generator
/// Logger for output
public PlatformProjectGenerator(CommandLineArguments Arguments, ILogger Logger)
{
this.Logger = Logger;
}
///
/// Register the platform with the UEPlatformProjectGenerator class
///
public abstract IEnumerable GetPlatforms();
public virtual void GenerateGameProjectStub(ProjectFileGenerator InGenerator, string InTargetName, string InTargetFilepath, TargetRules InTargetRules,
List InPlatforms, List InConfigurations)
{
// Do nothing
}
public virtual void GenerateGameProperties(UnrealTargetConfiguration Configuration, StringBuilder VCProjectFileContent, TargetType TargetType, DirectoryReference RootDirectory, FileReference TargetFilePath)
{
// Do nothing
}
public virtual bool RequiresVSUserFileGeneration()
{
return false;
}
ConcurrentDictionary FoundVSISupportDict = new();
public struct VSSettings
{
public UnrealTargetPlatform Platform;
public UnrealTargetConfiguration Configuration = UnrealTargetConfiguration.Development;
public VCProjectFileFormat ProjectFileFormat = VCProjectFileFormat.Default;
public UnrealArch? Architecture = null;
public VSSettings(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, VCProjectFileFormat InProjectFileFormat, UnrealArch? InArchitecture)
{
Platform = InPlatform;
Configuration = InConfiguration;
ProjectFileFormat = InProjectFileFormat;
Architecture = InArchitecture;
}
};
///
/// Checks the local VS install directories to see if the platform is supported.
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// bool true if native VisualStudio support (or custom VSI) is available
public virtual bool HasVisualStudioSupport(VSSettings InVSSettings)
{
int HashResult = 691;
HashResult *= InVSSettings.Platform.ToString().GetHashCode();
HashResult *= InVSSettings.Configuration.ToString().GetHashCode();
HashResult *= InVSSettings.ProjectFileFormat.ToString().GetHashCode();
HashResult *= InVSSettings.Architecture != null ? InVSSettings.Architecture.ToString()!.GetHashCode() : 1;
return FoundVSISupportDict.GetOrAdd(HashResult, _ =>
{
WindowsCompiler VSCompiler;
string VCVersion;
switch (InVSSettings.ProjectFileFormat)
{
case VCProjectFileFormat.VisualStudio2022:
VSCompiler = WindowsCompiler.VisualStudio2022;
VCVersion = "v170";
break;
default:
// Unknown VS Version
return false;
}
IEnumerable? InstallDirs = WindowsPlatform.TryGetVSInstallDirs(VSCompiler, Logger);
if (InstallDirs != null)
{
foreach (DirectoryReference VSInstallDir in InstallDirs)
{
DirectoryReference PlatformsPath = new DirectoryReference(System.IO.Path.Combine(VSInstallDir.FullName, "MSBuild\\Microsoft\\VC\\", VCVersion, "Platforms", GetVisualStudioPlatformName(InVSSettings)));
if (DirectoryReference.Exists(PlatformsPath))
{
return true;
}
}
}
return false;
});
}
///
/// Return the VisualStudio platform name for this build platform
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// string The name of the platform that VisualStudio recognizes
public virtual string GetVisualStudioPlatformName(VSSettings InVSSettings)
{
// By default, return the platform string
return InVSSettings.Platform.ToString();
}
///
/// Return whether we need a distinct platform name - for cases where there are two targets of the same VS solution platform
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// bool
public virtual bool RequiresDistinctVisualStudioConfigurationName(VSSettings InVSSettings)
{
return false;
}
///
/// Return project configuration settings that must be included before the default props file for all configurations
///
/// The UnrealTargetPlatform being built
/// String builder for the project file
/// string The custom configuration section for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioPreDefaultString(UnrealTargetPlatform InPlatform, StringBuilder ProjectFileBuilder)
{
}
///
/// Return project configuration settings that must be included before the default props file
///
/// The UnrealTargetPlatform being built
/// The UnrealTargetConfiguration being built
/// String builder for the project file
/// string The custom configuration section for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioPreDefaultString(UnrealTargetPlatform InPlatform, UnrealTargetConfiguration InConfiguration, StringBuilder ProjectFileBuilder)
{
}
///
/// Return the platform toolset string to write into the project configuration
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// String builder for the project file
/// string The custom configuration section for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioPlatformToolsetString(VSSettings InVSSettings, StringBuilder ProjectFileBuilder)
{
}
///
/// Return any custom property group lines
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// String builder for the project file
/// string The custom property import lines for the project file; Empty string if it doesn't require one
public virtual void GetAdditionalVisualStudioPropertyGroups(VSSettings InVSSettings, StringBuilder ProjectFileBuilder)
{
}
///
/// Return any custom property group lines
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// string The platform configuration type. Defaults to "Makefile" unless overridden
public virtual string GetVisualStudioPlatformConfigurationType(VSSettings InVSSettings)
{
return DefaultPlatformConfigurationType;
}
///
/// Return any custom paths for VisualStudio this platform requires
/// This include ReferencePath, LibraryPath, LibraryWPath, IncludePath and ExecutablePath.
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// The type of target (game or program)
/// Path to the .target.cs file
///
///
/// String builder for the project file
/// The custom path lines for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioPathsEntries(VSSettings InVSSettings, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath, StringBuilder ProjectFileBuilder)
{
}
///
/// Return any custom property settings. These will be included in the ImportGroup section
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// String builder for the project file
/// string The custom property import lines for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioImportGroupProperties(VSSettings InVSSettings, StringBuilder ProjectFileBuilder)
{
}
///
/// Return any custom property settings. These will be included right after Global properties to make values available to all other imports.
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// String builder for the project file
/// string The custom property import lines for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioGlobalProperties(VSSettings InVSSettings, StringBuilder ProjectFileBuilder)
{
}
///
/// Return any custom target overrides. These will be included last in the project file so they have the opportunity to override any existing settings.
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// String builder for the project file
/// string The custom property import lines for the project file; Empty string if it doesn't require one
public virtual void GetVisualStudioTargetOverrides(VSSettings InVSSettings, StringBuilder ProjectFileBuilder)
{
}
///
/// Return any custom layout directory sections
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
///
/// The type of target (game or program)
///
///
///
/// string The custom property import lines for the project file; Empty string if it doesn't require one
public virtual string GetVisualStudioLayoutDirSection(VSSettings InVSSettings, string InConditionString, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference NMakeOutputPath)
{
return "";
}
///
/// Get the output manifest section, if required
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// The type of the target being built
/// Path to the .target.cs file
/// Path to the project file
/// The output manifest section for the project file; Empty string if it doesn't require one
public virtual string GetVisualStudioOutputManifestSection(VSSettings InVSSettings, TargetType TargetType, FileReference TargetRulesPath, FileReference ProjectFilePath)
{
return "";
}
///
/// Get whether this platform deploys
///
/// bool true if the 'Deploy' option should be enabled
public virtual bool GetVisualStudioDeploymentEnabled(VSSettings InVSSettings)
{
return false;
}
///
/// Additional configuration related to Visual Studio user file (.vcxproj.user).
///
public class VisualStudioUserFileSettings
{
public IReadOnlySet PropertiesToPatch => PropertiesToPatchContainer;
public IReadOnlySet PropertiesToPatchOrderButPreserveValue => PropertiesToPatchOrderButPreserveValueContainer;
///
/// Patch existing .vcxproj.user file based on the new file content and corresponding patching settings, by doing the following:
/// - Go over every <PropertyGroup> in the new document.
/// - Finds <PropertyGroup> in the current document with matching "Condition" attribute.
/// - If no property group is found, appends property group from new document to the end of current document.
/// - Otherwise, saves values of properties configured with bPreserveExistingValue == true.
/// - Removes all properties flagged for patching from current document property group.
/// - Adds all properties required for patching from new document property group as declared in new document order.
///
/// This makes possible to override some properties crucial for UE features while keeping rest of user configuration intact.
///
/// Otherwise, if .vcxproj.user doesn't exist, patching do nothing and instead creates a new file based on new file content.
///
/// Name of the property to patch.
/// If true, the value of the property will be taken from existing user file, but relative order will be taken from newly generated file.
public void PatchProperty(string PropertyName, bool bPreserveExistingValue = false)
{
if (!PropertiesToPatchContainer.Contains(PropertyName))
{
PropertiesToPatchContainer.Add(PropertyName);
}
if (bPreserveExistingValue && !PropertiesToPatchOrderButPreserveValueContainer.Contains(PropertyName))
{
PropertiesToPatchOrderButPreserveValueContainer.Add(PropertyName);
}
}
private HashSet PropertiesToPatchContainer = new();
private HashSet PropertiesToPatchOrderButPreserveValueContainer = new();
}
///
/// Get the text to insert into the user file for the given platform/configuration/target
///
/// Configuration for user file creation/patching/etc.
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
/// The condition string
/// The target rules
/// The target rules path
/// The project file path
/// Output path for NMake
/// The name of the project
/// Path to foreign .uproject file, if any
/// The string to append to the user file
public virtual string GetVisualStudioUserFileStrings(VisualStudioUserFileSettings VCUserFileSettings, VSSettings InVSSettings, string InConditionString, TargetRules InTargetRules, FileReference TargetRulesPath, FileReference ProjectFilePath, FileReference? NMakeOutputPath, string ProjectName, string? ForeignUProjectPath)
{
return String.Empty;
}
///
/// For Additional Project Property files that need to be written out. This is currently used only on Android.
///
public virtual void WriteAdditionalPropFile()
{
}
///
/// For additional Project files (ex. *PROJECTNAME*-AndroidRun.androidproj.user) that needs to be written out. This is currently used only on Android.
///
/// Project file this will be related to
public virtual void WriteAdditionalProjUserFile(ProjectFile ProjectFile)
{
}
///
/// For additional Project files (ex. *PROJECTNAME*-AndroidRun.androidproj) that needs to be written out. This is currently used only on Android.
///
/// Project file this will be related to
/// Project file written out, Solution folder it should be put in
public virtual Tuple? WriteAdditionalProjFile(ProjectFile ProjectFile)
{
return null;
}
///
/// Gets the text to insert into the UnrealVS configuration file
///
public virtual void GetUnrealVSConfigurationEntries(StringBuilder UnrealVSContent)
{
}
///
/// Gets the text to insert into the Project files as additional build arguments for given platform/configuration
///
/// The ProjectFileSettings that contains the project platform/configuration/etc info being built
public virtual string GetExtraBuildArguments(VSSettings InVSSettings)
{
return "";
}
///
/// Indicates whether this generator will be emitting additional build targets.
/// Functionally, it's fine to return true and not return any additional text in GetVisualStudioTargetsString, but doing
/// so may incur additional cost of preparing data for generation.
///
/// The platform being added
/// True if Targets will be generate, false otherwise. If true is returned, GetVisualStudioTargetsString will be called next.
///
public virtual bool HasVisualStudioTargets(UnrealTargetPlatform InPlatform)
{
return false;
}
///
/// Get the text to insert into the Project files as additional build targets for the given platform.
///
/// The platform being added
/// List of build configurations for the platform
/// String builder for the project file
public virtual void GetVisualStudioTargetsString(UnrealTargetPlatform InPlatform, List InPlatformConfigurations, StringBuilder ProjectFileBuilder)
{
}
///
/// Get include paths to system headers (STL, SDK, ...) needed for coding assistance features in IDE
///
/// Target for which include paths shall be returned
/// The list of include paths
public virtual IList GetSystemIncludePaths(UEBuildTarget InTarget)
{
return new List(0);
}
}
}