You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Filter out numerous source files that match */Source/ThirdParty/* that should have already been filtered, this does not include Module.Build.cs or .tps files, or if bGatherThirdPartySource is enabled * Filter out source files that match */third_party/* by default * Add option bIncludeDotNetPrograms to remove all ..NET projects, doing so saved me around 400MB. Note if you disable the .NET projects UnrealBuildTool won't build before compiling (but GenerateProjectFiles.bat will still build it) Attempted changes that did not reduce memory usage by a significant amount: * Filtering out project configurations * Filtering out Engine/Shaders or Engine/Content/Editor/Templates * Increasing the shared include size, even making it large enough to contain every include path didn't really make a difference. Also it can't really be increased anyway because that entire property is added to the process environment when starting a build and there's a max environment size of around 32k Other Fixes: * Fix vs2019 ToolVersionString 15.0 -> 16.0 * Add VCProjectVersion to Project globals * Update UniqueIdentifier GUIDs in projects to be stable by hashing the directory path and using that hash as the GUID * Don't write ProjectConfiguration if filtered out (Didn't affect memory usage) * Add optional configuration filter for Debug, DebugGame, & Development #jira UE-111822 #rb none [CL 16319735 by Joe Kirchoff in ue5-main branch]
1012 lines
41 KiB
C#
1012 lines
41 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using System.Xml.Linq;
|
|
using EpicGames.Core;
|
|
|
|
#nullable disable
|
|
|
|
namespace UnrealBuildTool
|
|
{
|
|
/// <summary>
|
|
/// Represents a folder within the master project (e.g. Visual Studio solution)
|
|
/// </summary>
|
|
class VisualStudioSolutionFolder : MasterProjectFolder
|
|
{
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public VisualStudioSolutionFolder(ProjectFileGenerator InitOwnerProjectFileGenerator, string InitFolderName)
|
|
: base(InitOwnerProjectFileGenerator, InitFolderName)
|
|
{
|
|
}
|
|
}
|
|
|
|
enum VCProjectFileFormat
|
|
{
|
|
Default, // Default to the best installed version, but allow SDKs to override
|
|
VisualStudio2012, // Unsupported
|
|
VisualStudio2013, // Unsupported
|
|
VisualStudio2015,
|
|
VisualStudio2017,
|
|
VisualStudio2019,
|
|
}
|
|
|
|
class VCProjectFileSettings
|
|
{
|
|
/// <summary>
|
|
/// The version of Visual Studio to generate project files for.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "VCProjectFileGenerator", Name = "Version")]
|
|
public VCProjectFileFormat ProjectFileFormat = VCProjectFileFormat.Default;
|
|
|
|
/// <summary>
|
|
/// Puts the most common include paths in the IncludePath property in the MSBuild project. This significantly reduces Visual Studio
|
|
/// memory usage (measured 1.1GB -> 500mb), but seems to be causing issues with Visual Assist. Value here specifies maximum length
|
|
/// of the include path list in KB.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "VCProjectFileGenerator")]
|
|
public int MaxSharedIncludePaths = 24 * 1024;
|
|
|
|
/// <summary>
|
|
/// Semi-colon separated list of paths that should not be added to the projects include paths. Useful for omitting third-party headers
|
|
/// (e.g ThirdParty/WebRTC) from intellisense suggestions and reducing memory footprints.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "VCProjectFileGenerator")]
|
|
public string ExcludedIncludePaths = "";
|
|
|
|
/// <summary>
|
|
/// Whether to write a solution option (suo) file for the sln.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "BuildConfiguration")]
|
|
public bool bWriteSolutionOptionFile = true;
|
|
|
|
/// <summary>
|
|
/// Forces UBT to be built in debug configuration, regardless of the solution configuration
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "VCProjectFileGenerator")]
|
|
public bool bBuildUBTInDebug = false;
|
|
|
|
/// <summary>
|
|
/// Whether to add the -FastPDB option to build command lines by default.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "BuildConfiguration")]
|
|
public bool bAddFastPDBToProjects = false;
|
|
|
|
/// <summary>
|
|
/// Whether to generate per-file intellisense data.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "BuildConfiguration")]
|
|
public bool bUsePerFileIntellisense = true;
|
|
|
|
/// <summary>
|
|
/// Whether to include a dependency on ShaderCompileWorker when generating project files for the editor.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "BuildConfiguration")]
|
|
public bool bEditorDependsOnShaderCompileWorker = true;
|
|
|
|
/// <summary>
|
|
/// Whether to include a dependency on LiveCodingConsole when building targets that support live coding.
|
|
/// </summary>
|
|
[XmlConfigFile(Category = "VCProjectFileGenerator")]
|
|
public bool bBuildLiveCodingConsole = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Visual C++ project file generator implementation
|
|
/// </summary>
|
|
class VCProjectFileGenerator : ProjectFileGenerator
|
|
{
|
|
/// <summary>
|
|
/// The settings object
|
|
/// </summary>
|
|
protected VCProjectFileSettings Settings = new VCProjectFileSettings();
|
|
|
|
/// <summary>
|
|
/// Override for the build tool to use in generated projects. If the compiler version is specified on the command line, we use the same argument on the
|
|
/// command line for generated projects.
|
|
/// </summary>
|
|
string BuildToolOverride;
|
|
|
|
/// <summary>
|
|
/// Default constructor
|
|
/// </summary>
|
|
/// <param name="InOnlyGameProject">The single project to generate project files for, or null</param>
|
|
/// <param name="InProjectFileFormat">Override the project file format to use</param>
|
|
/// <param name="InArguments">Additional command line arguments</param>
|
|
public VCProjectFileGenerator(FileReference InOnlyGameProject, VCProjectFileFormat InProjectFileFormat, CommandLineArguments InArguments)
|
|
: base(InOnlyGameProject)
|
|
{
|
|
XmlConfig.ApplyTo(Settings);
|
|
|
|
if (InProjectFileFormat != VCProjectFileFormat.Default)
|
|
{
|
|
Settings.ProjectFileFormat = InProjectFileFormat;
|
|
}
|
|
|
|
if (InArguments.HasOption("-2015"))
|
|
{
|
|
BuildToolOverride = "-2015";
|
|
}
|
|
else if (InArguments.HasOption("-2017"))
|
|
{
|
|
BuildToolOverride = "-2017";
|
|
}
|
|
else if (InArguments.HasOption("-2019"))
|
|
{
|
|
BuildToolOverride = "-2019";
|
|
}
|
|
}
|
|
|
|
public override string[] GetTargetArguments(string[] Arguments)
|
|
{
|
|
return Arguments.Where(s => string.Equals(s, BuildToolOverride, StringComparison.InvariantCultureIgnoreCase)).ToArray();
|
|
}
|
|
|
|
/// File extension for project files we'll be generating (e.g. ".vcxproj")
|
|
override public string ProjectFileExtension
|
|
{
|
|
get
|
|
{
|
|
return ".vcxproj";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// </summary>
|
|
public override void CleanProjectFiles(DirectoryReference InMasterProjectDirectory, string InMasterProjectName, DirectoryReference InIntermediateProjectFilesDirectory)
|
|
{
|
|
FileReference MasterProjectFile = FileReference.Combine(InMasterProjectDirectory, InMasterProjectName);
|
|
FileReference MasterProjDeleteFilename = MasterProjectFile + ".sln";
|
|
if (FileReference.Exists(MasterProjDeleteFilename))
|
|
{
|
|
FileReference.Delete(MasterProjDeleteFilename);
|
|
}
|
|
MasterProjDeleteFilename = MasterProjectFile + ".sdf";
|
|
if (FileReference.Exists(MasterProjDeleteFilename))
|
|
{
|
|
FileReference.Delete(MasterProjDeleteFilename);
|
|
}
|
|
MasterProjDeleteFilename = MasterProjectFile + ".suo";
|
|
if (FileReference.Exists(MasterProjDeleteFilename))
|
|
{
|
|
FileReference.Delete(MasterProjDeleteFilename);
|
|
}
|
|
MasterProjDeleteFilename = MasterProjectFile + ".v11.suo";
|
|
if (FileReference.Exists(MasterProjDeleteFilename))
|
|
{
|
|
FileReference.Delete(MasterProjDeleteFilename);
|
|
}
|
|
MasterProjDeleteFilename = MasterProjectFile + ".v12.suo";
|
|
if (FileReference.Exists(MasterProjDeleteFilename))
|
|
{
|
|
FileReference.Delete(MasterProjDeleteFilename);
|
|
}
|
|
|
|
// Delete the project files folder
|
|
if (DirectoryReference.Exists(InIntermediateProjectFilesDirectory))
|
|
{
|
|
try
|
|
{
|
|
DirectoryReference.Delete(InIntermediateProjectFilesDirectory, true);
|
|
}
|
|
catch (Exception Ex)
|
|
{
|
|
Log.TraceInformation("Error while trying to clean project files path {0}. Ignored.", InIntermediateProjectFilesDirectory);
|
|
Log.TraceInformation("\t" + Ex.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allocates a generator-specific project file object
|
|
/// </summary>
|
|
/// <param name="InitFilePath">Path to the project file</param>
|
|
/// <returns>The newly allocated project file object</returns>
|
|
protected override ProjectFile AllocateProjectFile(FileReference InitFilePath)
|
|
{
|
|
return new VCProjectFile(InitFilePath, Settings.ProjectFileFormat, bUsePrecompiled, BuildToolOverride, Settings);
|
|
}
|
|
|
|
|
|
/// ProjectFileGenerator interface
|
|
public override MasterProjectFolder AllocateMasterProjectFolder(ProjectFileGenerator InitOwnerProjectFileGenerator, string InitFolderName)
|
|
{
|
|
return new VisualStudioSolutionFolder(InitOwnerProjectFileGenerator, InitFolderName);
|
|
}
|
|
|
|
/// "4.0", "12.0", or "14.0", etc...
|
|
static public string GetProjectFileToolVersionString(VCProjectFileFormat ProjectFileFormat)
|
|
{
|
|
switch (ProjectFileFormat)
|
|
{
|
|
case VCProjectFileFormat.VisualStudio2012:
|
|
return "4.0";
|
|
case VCProjectFileFormat.VisualStudio2013:
|
|
return "12.0";
|
|
case VCProjectFileFormat.VisualStudio2015:
|
|
return "14.0";
|
|
case VCProjectFileFormat.VisualStudio2017:
|
|
return "15.0";
|
|
case VCProjectFileFormat.VisualStudio2019:
|
|
return "16.0";
|
|
}
|
|
return string.Empty;
|
|
}
|
|
|
|
/// for instance: <PlatformToolset>v110</PlatformToolset>
|
|
static public string GetProjectFilePlatformToolsetVersionString(VCProjectFileFormat ProjectFileFormat)
|
|
{
|
|
switch (ProjectFileFormat)
|
|
{
|
|
case VCProjectFileFormat.VisualStudio2012:
|
|
return "v110";
|
|
case VCProjectFileFormat.VisualStudio2013:
|
|
return "v120";
|
|
case VCProjectFileFormat.VisualStudio2015:
|
|
return "v140";
|
|
case VCProjectFileFormat.VisualStudio2017:
|
|
return "v141";
|
|
case VCProjectFileFormat.VisualStudio2019:
|
|
return "v142";
|
|
|
|
}
|
|
return string.Empty;
|
|
}
|
|
|
|
static public void AppendPlatformToolsetProperty(StringBuilder VCProjectFileContent, VCProjectFileFormat ProjectFileFormat)
|
|
{
|
|
string ToolVersionString = GetProjectFileToolVersionString(ProjectFileFormat);
|
|
string PlatformToolsetVersionString = GetProjectFilePlatformToolsetVersionString(ProjectFileFormat);
|
|
VCProjectFileContent.AppendLine(" <PlatformToolset>{0}</PlatformToolset>", PlatformToolsetVersionString);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Configures project generator based on command-line options
|
|
/// </summary>
|
|
/// <param name="Arguments">Arguments passed into the program</param>
|
|
/// <param name="IncludeAllPlatforms">True if all platforms should be included</param>
|
|
protected override void ConfigureProjectFileGeneration(String[] Arguments, ref bool IncludeAllPlatforms)
|
|
{
|
|
// Call parent implementation first
|
|
base.ConfigureProjectFileGeneration(Arguments, ref IncludeAllPlatforms);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Selects which platforms and build configurations we want in the project file
|
|
/// </summary>
|
|
/// <param name="IncludeAllPlatforms">True if we should include ALL platforms that are supported on this machine. Otherwise, only desktop platforms will be included.</param>
|
|
/// <param name="SupportedPlatformNames">Output string for supported platforms, returned as comma-separated values.</param>
|
|
protected override void SetupSupportedPlatformsAndConfigurations(bool IncludeAllPlatforms, out string SupportedPlatformNames)
|
|
{
|
|
// Call parent implementation to figure out the actual platforms
|
|
base.SetupSupportedPlatformsAndConfigurations(IncludeAllPlatforms, out SupportedPlatformNames);
|
|
|
|
// If we have a non-default setting for visual studio, check the compiler exists. If not, revert to the default.
|
|
if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2015)
|
|
{
|
|
if (!WindowsPlatform.HasCompiler(WindowsCompiler.VisualStudio2015_DEPRECATED))
|
|
{
|
|
Log.TraceWarning("Visual Studio C++ 2015 installation not found - ignoring preferred project file format.");
|
|
Settings.ProjectFileFormat = VCProjectFileFormat.Default;
|
|
}
|
|
}
|
|
else if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2017)
|
|
{
|
|
if (!WindowsPlatform.HasCompiler(WindowsCompiler.VisualStudio2017))
|
|
{
|
|
Log.TraceWarning("Visual Studio C++ 2017 installation not found - ignoring preferred project file format.");
|
|
Settings.ProjectFileFormat = VCProjectFileFormat.Default;
|
|
}
|
|
}
|
|
else if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2019)
|
|
{
|
|
if (!WindowsPlatform.HasCompiler(WindowsCompiler.VisualStudio2019))
|
|
{
|
|
Log.TraceWarning("Visual Studio C++ 2019 installation not found - ignoring preferred project file format.");
|
|
Settings.ProjectFileFormat = VCProjectFileFormat.Default;
|
|
}
|
|
}
|
|
|
|
// Certain platforms override the project file format because their debugger add-ins may not yet support the latest
|
|
// version of Visual Studio. This is their chance to override that.
|
|
// ...but only if the user didn't override this via the command-line.
|
|
if (Settings.ProjectFileFormat == VCProjectFileFormat.Default)
|
|
{
|
|
// Pick the best platform installed by default
|
|
if (WindowsPlatform.HasCompiler(WindowsCompiler.VisualStudio2019) && WindowsPlatform.HasIDE(WindowsCompiler.VisualStudio2019))
|
|
{
|
|
Settings.ProjectFileFormat = VCProjectFileFormat.VisualStudio2019;
|
|
}
|
|
else if (WindowsPlatform.HasCompiler(WindowsCompiler.VisualStudio2017) && WindowsPlatform.HasIDE(WindowsCompiler.VisualStudio2017))
|
|
{
|
|
Settings.ProjectFileFormat = VCProjectFileFormat.VisualStudio2017;
|
|
}
|
|
else if (WindowsPlatform.HasCompiler(WindowsCompiler.VisualStudio2015_DEPRECATED) && WindowsPlatform.HasIDE(WindowsCompiler.VisualStudio2015_DEPRECATED))
|
|
{
|
|
Settings.ProjectFileFormat = VCProjectFileFormat.VisualStudio2015;
|
|
}
|
|
|
|
// Allow the SDKs to override
|
|
foreach (UnrealTargetPlatform SupportedPlatform in SupportedPlatforms)
|
|
{
|
|
UEBuildPlatform BuildPlatform;
|
|
if (UEBuildPlatform.TryGetBuildPlatform(SupportedPlatform, out BuildPlatform))
|
|
{
|
|
// Don't worry about platforms that we're missing SDKs for
|
|
if (BuildPlatform.HasRequiredSDKsInstalled() == SDKStatus.Valid)
|
|
{
|
|
VCProjectFileFormat ProposedFormat = BuildPlatform.GetRequiredVisualStudioVersion();
|
|
|
|
if (ProposedFormat != VCProjectFileFormat.Default)
|
|
{
|
|
// Reduce the Visual Studio version to the max supported by each platform we plan to include.
|
|
if (Settings.ProjectFileFormat == VCProjectFileFormat.Default || ProposedFormat < Settings.ProjectFileFormat)
|
|
{
|
|
Settings.ProjectFileFormat = ProposedFormat;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Used to sort VC solution config names along with the config and platform values
|
|
/// </summary>
|
|
class VCSolutionConfigCombination
|
|
{
|
|
/// <summary>
|
|
/// Visual Studio solution configuration name for this config+platform
|
|
/// </summary>
|
|
public string VCSolutionConfigAndPlatformName;
|
|
|
|
/// <summary>
|
|
/// Configuration name
|
|
/// </summary>
|
|
public UnrealTargetConfiguration Configuration;
|
|
|
|
/// <summary>
|
|
/// Platform name
|
|
/// </summary>
|
|
public UnrealTargetPlatform Platform;
|
|
|
|
/// <summary>
|
|
/// The target type
|
|
/// </summary>
|
|
public TargetType TargetConfigurationName;
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("{0}={1} {2} {3}", VCSolutionConfigAndPlatformName, Configuration, Platform, TargetConfigurationName);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Composes a string to use for the Visual Studio solution configuration, given a build configuration and target rules configuration name
|
|
/// </summary>
|
|
/// <param name="Configuration">The build configuration</param>
|
|
/// <param name="TargetType">The type of target being built</param>
|
|
/// <returns>The generated solution configuration name</returns>
|
|
string MakeSolutionConfigurationName(UnrealTargetConfiguration Configuration, TargetType TargetType)
|
|
{
|
|
string SolutionConfigName = Configuration.ToString();
|
|
|
|
// Don't bother postfixing "Game" or "Program" -- that will be the default when using "Debug", "Development", etc.
|
|
// Also don't postfix "RocketGame" when we're building Rocket game projects. That's the only type of game there is in that case!
|
|
if (TargetType != TargetType.Game && TargetType != TargetType.Program)
|
|
{
|
|
SolutionConfigName += " " + TargetType.ToString();
|
|
}
|
|
|
|
return SolutionConfigName;
|
|
}
|
|
|
|
static IDictionary<MasterProjectFolder, Guid> GenerateProjectFolderGuids(MasterProjectFolder RootFolder)
|
|
{
|
|
IDictionary<MasterProjectFolder, Guid> Guids = new Dictionary<MasterProjectFolder, Guid>();
|
|
foreach (MasterProjectFolder Folder in RootFolder.SubFolders)
|
|
{
|
|
GenerateProjectFolderGuids("UE5", Folder, Guids);
|
|
}
|
|
return Guids;
|
|
}
|
|
|
|
static void GenerateProjectFolderGuids(string ParentPath, MasterProjectFolder Folder, IDictionary<MasterProjectFolder, Guid> Guids)
|
|
{
|
|
string Path = String.Format("{0}/{1}", ParentPath, Folder.FolderName);
|
|
Guids[Folder] = MakeMd5Guid(Encoding.UTF8.GetBytes(Path));
|
|
|
|
foreach (MasterProjectFolder SubFolder in Folder.SubFolders)
|
|
{
|
|
GenerateProjectFolderGuids(Path, SubFolder, Guids);
|
|
}
|
|
}
|
|
|
|
static Guid MakeMd5Guid(byte[] Input)
|
|
{
|
|
byte[] Hash = MD5.Create().ComputeHash(Input);
|
|
Hash[6] = (byte)(0x30 | (Hash[6] & 0x0f)); // 0b0011'xxxx Version 3 UUID (MD5)
|
|
Hash[8] = (byte)(0x80 | (Hash[8] & 0x3f)); // 0b10xx'xxxx RFC 4122 UUID
|
|
Array.Reverse(Hash, 0, 4);
|
|
Array.Reverse(Hash, 4, 2);
|
|
Array.Reverse(Hash, 6, 2);
|
|
return new Guid(Hash);
|
|
}
|
|
|
|
public static Guid MakeMd5Guid(Guid Namespace, string Text)
|
|
{
|
|
byte[] Input = new byte[16 + Encoding.UTF8.GetByteCount(Text)];
|
|
|
|
Namespace.TryWriteBytes(Input.AsSpan(0, 16));
|
|
Array.Reverse(Input, 0, 4);
|
|
Array.Reverse(Input, 4, 2);
|
|
Array.Reverse(Input, 6, 2);
|
|
|
|
Encoding.UTF8.GetBytes(Text, 0, Text.Length, Input, 16);
|
|
return MakeMd5Guid(Input);
|
|
}
|
|
|
|
public static Guid MakeMd5Guid(string Text)
|
|
{
|
|
byte[] Input = Encoding.UTF8.GetBytes(Text);
|
|
|
|
return MakeMd5Guid(Input);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Writes the project files to disk
|
|
/// </summary>
|
|
/// <returns>True if successful</returns>
|
|
protected override bool WriteProjectFiles(PlatformProjectGeneratorCollection PlatformProjectGenerators)
|
|
{
|
|
if (!base.WriteProjectFiles(PlatformProjectGenerators))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Write AutomationReferences file
|
|
// Write in in net core expected format
|
|
if (AutomationProjectFiles.Any())
|
|
{
|
|
XNamespace NS = XNamespace.Get("http://schemas.microsoft.com/developer/msbuild/2003");
|
|
|
|
DirectoryReference AutomationToolDir = DirectoryReference.Combine(UnrealBuildTool.EngineSourceDirectory, "Programs", "AutomationTool");
|
|
new XDocument(
|
|
new XElement(NS + "Project",
|
|
new XAttribute("ToolsVersion", VCProjectFileGenerator.GetProjectFileToolVersionString(Settings.ProjectFileFormat)),
|
|
new XAttribute("DefaultTargets", "Build"),
|
|
new XElement(NS + "ItemGroup",
|
|
from AutomationProject in AutomationProjectFiles
|
|
select new XElement(NS + "ProjectReference",
|
|
new XAttribute("Include", AutomationProject.ProjectFilePath.MakeRelativeTo(AutomationToolDir))
|
|
)
|
|
)
|
|
)
|
|
).Save(FileReference.Combine(AutomationToolDir, "AutomationTool.csproj.References").FullName);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
protected override bool WriteMasterProjectFile(ProjectFile UBTProject, PlatformProjectGeneratorCollection PlatformProjectGenerators)
|
|
{
|
|
bool bSuccess = true;
|
|
|
|
string SolutionFileName = MasterProjectName + ".sln";
|
|
|
|
// Setup solution file content
|
|
StringBuilder VCSolutionFileContent = new StringBuilder();
|
|
|
|
// Solution file header. Note that a leading newline is required for file type detection to work correclty in the shell.
|
|
if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2019)
|
|
{
|
|
VCSolutionFileContent.AppendLine();
|
|
VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
|
|
VCSolutionFileContent.AppendLine("# Visual Studio Version 16");
|
|
VCSolutionFileContent.AppendLine("VisualStudioVersion = 16.0.28315.86");
|
|
VCSolutionFileContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
|
|
}
|
|
else if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2017)
|
|
{
|
|
VCSolutionFileContent.AppendLine();
|
|
VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
|
|
VCSolutionFileContent.AppendLine("# Visual Studio 15");
|
|
VCSolutionFileContent.AppendLine("VisualStudioVersion = 15.0.25807.0");
|
|
VCSolutionFileContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
|
|
}
|
|
else if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2015)
|
|
{
|
|
VCSolutionFileContent.AppendLine();
|
|
VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
|
|
VCSolutionFileContent.AppendLine("# Visual Studio 14");
|
|
VCSolutionFileContent.AppendLine("VisualStudioVersion = 14.0.22310.1");
|
|
VCSolutionFileContent.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1");
|
|
}
|
|
else if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2013)
|
|
{
|
|
VCSolutionFileContent.AppendLine();
|
|
VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
|
|
VCSolutionFileContent.AppendLine("# Visual Studio 2013");
|
|
}
|
|
else if (Settings.ProjectFileFormat == VCProjectFileFormat.VisualStudio2012)
|
|
{
|
|
VCSolutionFileContent.AppendLine();
|
|
VCSolutionFileContent.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00");
|
|
VCSolutionFileContent.AppendLine("# Visual Studio 2012");
|
|
}
|
|
else
|
|
{
|
|
throw new BuildException("Unexpected ProjectFileFormat");
|
|
}
|
|
|
|
IDictionary<MasterProjectFolder, Guid> ProjectFolderGuids = GenerateProjectFolderGuids(RootFolder);
|
|
|
|
// Solution folders, files and project entries
|
|
{
|
|
// This the GUID that Visual Studio uses to identify a solution folder
|
|
string SolutionFolderEntryGUID = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}";
|
|
|
|
// Solution folders
|
|
{
|
|
IEnumerable<MasterProjectFolder> AllSolutionFolders = ProjectFolderGuids.Keys.OrderBy(Folder => Folder.FolderName).ThenBy(Folder => ProjectFolderGuids[Folder]);
|
|
foreach (MasterProjectFolder CurFolder in AllSolutionFolders)
|
|
{
|
|
string FolderGUIDString = ProjectFolderGuids[CurFolder].ToString("B").ToUpperInvariant();
|
|
VCSolutionFileContent.AppendLine("Project(\"" + SolutionFolderEntryGUID + "\") = \"" + CurFolder.FolderName + "\", \"" + CurFolder.FolderName + "\", \"" + FolderGUIDString + "\"");
|
|
|
|
// Add any files that are inlined right inside the solution folder
|
|
if (CurFolder.Files.Count > 0)
|
|
{
|
|
VCSolutionFileContent.AppendLine(" ProjectSection(SolutionItems) = preProject");
|
|
foreach (string CurFile in CurFolder.Files)
|
|
{
|
|
// Syntax is: <relative file path> = <relative file path>
|
|
VCSolutionFileContent.AppendLine(" " + CurFile + " = " + CurFile);
|
|
}
|
|
VCSolutionFileContent.AppendLine(" EndProjectSection");
|
|
}
|
|
|
|
VCSolutionFileContent.AppendLine("EndProject");
|
|
}
|
|
}
|
|
|
|
|
|
// Project files
|
|
//List<MSBuildProjectFile> AllProjectFilesSorted = AllProjectFiles.OrderBy((ProjFile) => ProjFile.ProjectFilePath.GetFileNameWithoutExtension()).Cast<MSBuildProjectFile>().ToList();
|
|
foreach (MSBuildProjectFile CurProject in AllProjectFiles)
|
|
{
|
|
// Visual Studio uses different GUID types depending on the project type
|
|
string ProjectTypeGUID = CurProject.ProjectTypeGUID;
|
|
|
|
// NOTE: The project name in the solution doesn't actually *have* to match the project file name on disk. However,
|
|
// we prefer it when it does match so we use the actual file name here.
|
|
string ProjectNameInSolution = CurProject.ProjectFilePath.GetFileNameWithoutExtension();
|
|
|
|
// Use the existing project's GUID that's already known to us
|
|
string ProjectGUID = CurProject.ProjectGUID.ToString("B").ToUpperInvariant();
|
|
|
|
VCSolutionFileContent.AppendLine("Project(\"" + ProjectTypeGUID + "\") = \"" + ProjectNameInSolution + "\", \"" + CurProject.ProjectFilePath.MakeRelativeTo(ProjectFileGenerator.MasterProjectPath) + "\", \"" + ProjectGUID + "\"");
|
|
|
|
// Setup dependency on UnrealBuildTool, if we need that. This makes sure that UnrealBuildTool is
|
|
// freshly compiled before kicking off any build operations on this target project
|
|
if (!CurProject.IsStubProject)
|
|
{
|
|
List<ProjectFile> Dependencies = new List<ProjectFile>();
|
|
if (CurProject.IsGeneratedProject && UBTProject != null && CurProject != UBTProject)
|
|
{
|
|
Dependencies.Add(UBTProject);
|
|
Dependencies.AddRange(UBTProject.DependsOnProjects);
|
|
}
|
|
Dependencies.AddRange(CurProject.DependsOnProjects);
|
|
|
|
if (Dependencies.Count > 0)
|
|
{
|
|
VCSolutionFileContent.AppendLine("\tProjectSection(ProjectDependencies) = postProject");
|
|
|
|
// Setup any addition dependencies this project has...
|
|
foreach (ProjectFile DependsOnProject in Dependencies)
|
|
{
|
|
string DependsOnProjectGUID = ((MSBuildProjectFile)DependsOnProject).ProjectGUID.ToString("B").ToUpperInvariant();
|
|
VCSolutionFileContent.AppendLine("\t\t" + DependsOnProjectGUID + " = " + DependsOnProjectGUID);
|
|
}
|
|
|
|
VCSolutionFileContent.AppendLine("\tEndProjectSection");
|
|
}
|
|
}
|
|
|
|
VCSolutionFileContent.AppendLine("EndProject");
|
|
}
|
|
|
|
// Get the path to the visualizers file. Try to make it relative to the solution directory, but fall back to a full path if it's a foreign project.
|
|
FileReference VisualizersFile = FileReference.Combine(UnrealBuildTool.EngineDirectory, "Extras", "VisualStudioDebugging", "Unreal.natvis");
|
|
|
|
// Add the visualizers at the solution level. Doesn't seem to be picked up from a makefile project in VS2017 15.8.5.
|
|
VCSolutionFileContent.AppendLine(String.Format("Project(\"{0}\") = \"Visualizers\", \"Visualizers\", \"{{1CCEC849-CC72-4C59-8C36-2F7C38706D4C}}\"", SolutionFolderEntryGUID));
|
|
VCSolutionFileContent.AppendLine("\tProjectSection(SolutionItems) = preProject");
|
|
VCSolutionFileContent.AppendLine("\t\t{0} = {0}", VisualizersFile.MakeRelativeTo(MasterProjectPath));
|
|
VCSolutionFileContent.AppendLine("\tEndProjectSection");
|
|
VCSolutionFileContent.AppendLine("EndProject");
|
|
}
|
|
|
|
// Solution configuration platforms. This is just a list of all of the platforms and configurations that
|
|
// appear in Visual Studio's build configuration selector.
|
|
List<VCSolutionConfigCombination> SolutionConfigCombinations = new List<VCSolutionConfigCombination>();
|
|
|
|
// The "Global" section has source control, solution configurations, project configurations,
|
|
// preferences, and project hierarchy data
|
|
{
|
|
VCSolutionFileContent.AppendLine("Global");
|
|
{
|
|
HashSet<UnrealTargetPlatform> PlatformsValidForProjects = new HashSet<UnrealTargetPlatform>();
|
|
{
|
|
VCSolutionFileContent.AppendLine(" GlobalSection(SolutionConfigurationPlatforms) = preSolution");
|
|
|
|
Dictionary<string, Tuple<UnrealTargetConfiguration, TargetType>> SolutionConfigurationsValidForProjects = new Dictionary<string, Tuple<UnrealTargetConfiguration, TargetType>>();
|
|
|
|
foreach (UnrealTargetConfiguration CurConfiguration in SupportedConfigurations)
|
|
{
|
|
if (InstalledPlatformInfo.IsValidConfiguration(CurConfiguration, EProjectType.Code))
|
|
{
|
|
foreach (UnrealTargetPlatform CurPlatform in SupportedPlatforms)
|
|
{
|
|
if (InstalledPlatformInfo.IsValidPlatform(CurPlatform, EProjectType.Code))
|
|
{
|
|
foreach (ProjectFile CurProject in AllProjectFiles)
|
|
{
|
|
if (!CurProject.IsStubProject)
|
|
{
|
|
if (CurProject.ProjectTargets.Count == 0)
|
|
{
|
|
throw new BuildException("Expecting project '" + CurProject.ProjectFilePath + "' to have at least one ProjectTarget associated with it!");
|
|
}
|
|
|
|
// Figure out the set of valid target configuration names
|
|
foreach (ProjectTarget ProjectTarget in CurProject.ProjectTargets)
|
|
{
|
|
if (VCProjectFile.IsValidProjectPlatformAndConfiguration(ProjectTarget, CurPlatform, CurConfiguration, PlatformProjectGenerators))
|
|
{
|
|
PlatformsValidForProjects.Add(CurPlatform);
|
|
|
|
// Default to a target configuration name of "Game", since that will collapse down to an empty string
|
|
TargetType TargetType = TargetType.Game;
|
|
if (ProjectTarget.TargetRules != null)
|
|
{
|
|
TargetType = ProjectTarget.TargetRules.Type;
|
|
}
|
|
|
|
string SolutionConfigName = MakeSolutionConfigurationName(CurConfiguration, TargetType);
|
|
SolutionConfigurationsValidForProjects[SolutionConfigName] = new Tuple<UnrealTargetConfiguration, TargetType>(CurConfiguration, TargetType);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (UnrealTargetPlatform CurPlatform in PlatformsValidForProjects)
|
|
{
|
|
foreach (KeyValuePair<string, Tuple<UnrealTargetConfiguration, TargetType>> SolutionConfigKeyValue in SolutionConfigurationsValidForProjects)
|
|
{
|
|
// e.g. "Development|Win64 = Development|Win64"
|
|
string SolutionConfigName = SolutionConfigKeyValue.Key;
|
|
UnrealTargetConfiguration Configuration = SolutionConfigKeyValue.Value.Item1;
|
|
TargetType TargetType = SolutionConfigKeyValue.Value.Item2;
|
|
|
|
string SolutionPlatformName = CurPlatform.ToString();
|
|
|
|
string SolutionConfigAndPlatformPair = SolutionConfigName + "|" + SolutionPlatformName;
|
|
SolutionConfigCombinations.Add(
|
|
new VCSolutionConfigCombination
|
|
{
|
|
VCSolutionConfigAndPlatformName = SolutionConfigAndPlatformPair,
|
|
Configuration = Configuration,
|
|
Platform = CurPlatform,
|
|
TargetConfigurationName = TargetType
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
// Sort the list of solution platform strings alphabetically (Visual Studio prefers it)
|
|
SolutionConfigCombinations.Sort(
|
|
new Comparison<VCSolutionConfigCombination>(
|
|
(x, y) => { return String.Compare(x.VCSolutionConfigAndPlatformName, y.VCSolutionConfigAndPlatformName, StringComparison.InvariantCultureIgnoreCase); }
|
|
)
|
|
);
|
|
|
|
HashSet<string> AppendedSolutionConfigAndPlatformNames = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
|
|
foreach (VCSolutionConfigCombination SolutionConfigCombination in SolutionConfigCombinations)
|
|
{
|
|
// We alias "Game" and "Program" to both have the same solution configuration, so we're careful not to add the same combination twice.
|
|
if (!AppendedSolutionConfigAndPlatformNames.Contains(SolutionConfigCombination.VCSolutionConfigAndPlatformName))
|
|
{
|
|
VCSolutionFileContent.AppendLine(" " + SolutionConfigCombination.VCSolutionConfigAndPlatformName + " = " + SolutionConfigCombination.VCSolutionConfigAndPlatformName);
|
|
AppendedSolutionConfigAndPlatformNames.Add(SolutionConfigCombination.VCSolutionConfigAndPlatformName);
|
|
}
|
|
}
|
|
|
|
VCSolutionFileContent.AppendLine(" EndGlobalSection");
|
|
}
|
|
|
|
// Embed UnrealVS section, which is parsed by that VSPackage (Extension) to know how to handle this solution
|
|
{
|
|
string UnrealVSGuid = "ddbf523f-7eb6-4887-bd51-85a714ff87eb";
|
|
VCSolutionFileContent.AppendLine("\t# UnrealVS Section");
|
|
VCSolutionFileContent.AppendLine("\tGlobalSection({0}) = preSolution", UnrealVSGuid);
|
|
VCSolutionFileContent.AppendLine("\t\tAvailablePlatforms={0}", string.Join(";", PlatformsValidForProjects.Select(platform => platform.ToString())));
|
|
VCSolutionFileContent.AppendLine("\tEndGlobalSection");
|
|
}
|
|
|
|
// Assign each project's "project configuration" to our "solution platform + configuration" pairs. This
|
|
// also sets up which projects are actually built when building the solution.
|
|
{
|
|
VCSolutionFileContent.AppendLine(" GlobalSection(ProjectConfigurationPlatforms) = postSolution");
|
|
|
|
foreach (MSBuildProjectFile CurProject in AllProjectFiles)
|
|
{
|
|
foreach (VCSolutionConfigCombination SolutionConfigCombination in SolutionConfigCombinations)
|
|
{
|
|
// Get the context for the current solution context
|
|
MSBuildProjectContext ProjectContext = CurProject.GetMatchingProjectContext(SolutionConfigCombination.TargetConfigurationName, SolutionConfigCombination.Configuration, SolutionConfigCombination.Platform, PlatformProjectGenerators);
|
|
|
|
// Override the configuration to build for UBT
|
|
if (Settings.bBuildUBTInDebug && CurProject == UBTProject)
|
|
{
|
|
ProjectContext.ConfigurationName = "Debug";
|
|
}
|
|
|
|
// Write the solution mapping (e.g. "{4232C52C-680F-4850-8855-DC39419B5E9B}.Debug|iOS.ActiveCfg = iOS_Debug|Win32")
|
|
string CurProjectGUID = CurProject.ProjectGUID.ToString("B").ToUpperInvariant();
|
|
VCSolutionFileContent.AppendLine(" {0}.{1}.ActiveCfg = {2}", CurProjectGUID, SolutionConfigCombination.VCSolutionConfigAndPlatformName, ProjectContext.Name);
|
|
if (ProjectContext.bBuildByDefault)
|
|
{
|
|
VCSolutionFileContent.AppendLine(" {0}.{1}.Build.0 = {2}", CurProjectGUID, SolutionConfigCombination.VCSolutionConfigAndPlatformName, ProjectContext.Name);
|
|
if (ProjectContext.bDeployByDefault)
|
|
{
|
|
VCSolutionFileContent.AppendLine(" {0}.{1}.Deploy.0 = {2}", CurProjectGUID, SolutionConfigCombination.VCSolutionConfigAndPlatformName, ProjectContext.Name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VCSolutionFileContent.AppendLine(" EndGlobalSection");
|
|
}
|
|
|
|
|
|
// Setup other solution properties
|
|
{
|
|
// HideSolutionNode sets whether or not the top-level solution entry is completely hidden in the UI.
|
|
// We don't want that, as we need users to be able to right click on the solution tree item.
|
|
VCSolutionFileContent.AppendLine(" GlobalSection(SolutionProperties) = preSolution");
|
|
VCSolutionFileContent.AppendLine(" HideSolutionNode = FALSE");
|
|
VCSolutionFileContent.AppendLine(" EndGlobalSection");
|
|
}
|
|
|
|
|
|
|
|
// Solution directory hierarchy
|
|
{
|
|
VCSolutionFileContent.AppendLine(" GlobalSection(NestedProjects) = preSolution");
|
|
|
|
// Every entry in this section is in the format "Guid1 = Guid2". Guid1 is the child project (or solution
|
|
// filter)'s GUID, and Guid2 is the solution filter directory to parent the child project (or solution
|
|
// filter) to. This sets up the hierarchical solution explorer tree for all solution folders and projects.
|
|
|
|
System.Action<StringBuilder /* VCSolutionFileContent */, List<MasterProjectFolder> /* Folders */ > FolderProcessorFunction = null;
|
|
FolderProcessorFunction = (LocalVCSolutionFileContent, LocalMasterProjectFolders) =>
|
|
{
|
|
foreach (MasterProjectFolder CurFolder in LocalMasterProjectFolders)
|
|
{
|
|
string CurFolderGUIDString = ProjectFolderGuids[CurFolder].ToString("B").ToUpperInvariant();
|
|
|
|
foreach (MSBuildProjectFile ChildProject in CurFolder.ChildProjects)
|
|
{
|
|
// e.g. "{BF6FB09F-A2A6-468F-BE6F-DEBE07EAD3EA} = {C43B6BB5-3EF0-4784-B896-4099753BCDA9}"
|
|
LocalVCSolutionFileContent.AppendLine(" " + ChildProject.ProjectGUID.ToString("B").ToUpperInvariant() + " = " + CurFolderGUIDString);
|
|
}
|
|
|
|
foreach (MasterProjectFolder SubFolder in CurFolder.SubFolders)
|
|
{
|
|
// e.g. "{BF6FB09F-A2A6-468F-BE6F-DEBE07EAD3EA} = {C43B6BB5-3EF0-4784-B896-4099753BCDA9}"
|
|
LocalVCSolutionFileContent.AppendLine(" " + ProjectFolderGuids[SubFolder].ToString("B").ToUpperInvariant() + " = " + CurFolderGUIDString);
|
|
}
|
|
|
|
// Recurse into subfolders
|
|
FolderProcessorFunction(LocalVCSolutionFileContent, CurFolder.SubFolders);
|
|
}
|
|
};
|
|
FolderProcessorFunction(VCSolutionFileContent, RootFolder.SubFolders);
|
|
|
|
VCSolutionFileContent.AppendLine(" EndGlobalSection");
|
|
}
|
|
}
|
|
|
|
VCSolutionFileContent.AppendLine("EndGlobal");
|
|
}
|
|
|
|
|
|
// Save the solution file
|
|
if (bSuccess)
|
|
{
|
|
string SolutionFilePath = FileReference.Combine(MasterProjectPath, SolutionFileName).FullName;
|
|
bSuccess = WriteFileIfChanged(SolutionFilePath, VCSolutionFileContent.ToString());
|
|
}
|
|
|
|
|
|
// Save a solution config file which selects the development editor configuration by default.
|
|
if (bSuccess && Settings.bWriteSolutionOptionFile)
|
|
{
|
|
// Figure out the filename for the SUO file. VS will automatically import the options from earlier versions if necessary.
|
|
FileReference SolutionOptionsFileName;
|
|
switch (Settings.ProjectFileFormat)
|
|
{
|
|
case VCProjectFileFormat.VisualStudio2012:
|
|
SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, Path.ChangeExtension(SolutionFileName, "v11.suo"));
|
|
break;
|
|
case VCProjectFileFormat.VisualStudio2013:
|
|
SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, Path.ChangeExtension(SolutionFileName, "v12.suo"));
|
|
break;
|
|
case VCProjectFileFormat.VisualStudio2015:
|
|
SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, ".vs", Path.GetFileNameWithoutExtension(SolutionFileName), "v14", ".suo");
|
|
break;
|
|
case VCProjectFileFormat.VisualStudio2017:
|
|
SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, ".vs", Path.GetFileNameWithoutExtension(SolutionFileName), "v15", ".suo");
|
|
break;
|
|
case VCProjectFileFormat.VisualStudio2019:
|
|
SolutionOptionsFileName = FileReference.Combine(MasterProjectPath, ".vs", Path.GetFileNameWithoutExtension(SolutionFileName), "v16", ".suo");
|
|
break;
|
|
default:
|
|
throw new BuildException("Unsupported Visual Studio version");
|
|
}
|
|
|
|
// Check it doesn't exist before overwriting it. Since these files store the user's preferences, it'd be bad form to overwrite them.
|
|
if (!FileReference.Exists(SolutionOptionsFileName))
|
|
{
|
|
DirectoryReference.CreateDirectory(SolutionOptionsFileName.Directory);
|
|
|
|
VCSolutionOptions Options = new VCSolutionOptions(Settings.ProjectFileFormat);
|
|
|
|
// Set the default configuration and startup project
|
|
VCSolutionConfigCombination DefaultConfig = SolutionConfigCombinations.Find(x => x.Configuration == UnrealTargetConfiguration.Development && x.Platform == UnrealTargetPlatform.Win64 && x.TargetConfigurationName == TargetType.Editor);
|
|
if (DefaultConfig != null)
|
|
{
|
|
List<VCBinarySetting> Settings = new List<VCBinarySetting>();
|
|
Settings.Add(new VCBinarySetting("ActiveCfg", DefaultConfig.VCSolutionConfigAndPlatformName));
|
|
if (DefaultProject != null)
|
|
{
|
|
Settings.Add(new VCBinarySetting("StartupProject", ((MSBuildProjectFile)DefaultProject).ProjectGUID.ToString("B")));
|
|
}
|
|
Options.SetConfiguration(Settings);
|
|
}
|
|
|
|
// Mark all the projects as closed by default, apart from the startup project
|
|
VCSolutionExplorerState ExplorerState = new VCSolutionExplorerState();
|
|
if (Settings.ProjectFileFormat >= VCProjectFileFormat.VisualStudio2017)
|
|
{
|
|
BuildSolutionExplorerState_VS2017(RootFolder, "", ExplorerState, DefaultProject);
|
|
}
|
|
else
|
|
{
|
|
BuildSolutionExplorerState_VS2015(AllProjectFiles, ExplorerState, DefaultProject, IncludeEnginePrograms);
|
|
}
|
|
Options.SetExplorerState(ExplorerState);
|
|
|
|
// Write the file
|
|
if (Options.Sections.Count > 0)
|
|
{
|
|
Options.Write(SolutionOptionsFileName.FullName);
|
|
}
|
|
}
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
protected override void WriteDebugSolutionFiles(PlatformProjectGeneratorCollection PlatformProjectGenerators, DirectoryReference IntermediateProjectFilesPath)
|
|
{
|
|
//build and collect UnrealVS configuration
|
|
StringBuilder UnrealVSContent = new StringBuilder();
|
|
foreach (UnrealTargetPlatform SupportedPlatform in SupportedPlatforms)
|
|
{
|
|
PlatformProjectGenerator ProjGenerator = PlatformProjectGenerators.GetPlatformProjectGenerator(SupportedPlatform, true);
|
|
if (ProjGenerator != null)
|
|
{
|
|
ProjGenerator.GetUnrealVSConfigurationEntries(UnrealVSContent);
|
|
}
|
|
}
|
|
if (UnrealVSContent.Length > 0)
|
|
{
|
|
UnrealVSContent.Insert(0, "<UnrealVS>" + ProjectFileGenerator.NewLine);
|
|
UnrealVSContent.Append("</UnrealVS>" + ProjectFileGenerator.NewLine);
|
|
|
|
string ConfigFilePath = FileReference.Combine(IntermediateProjectFilesPath, "UnrealVS.xml").FullName;
|
|
/* bool bSuccess = */
|
|
ProjectFileGenerator.WriteFileIfChanged(ConfigFilePath, UnrealVSContent.ToString());
|
|
}
|
|
}
|
|
|
|
static void BuildSolutionExplorerState_VS2017(MasterProjectFolder Folder, string Suffix, VCSolutionExplorerState ExplorerState, ProjectFile DefaultProject)
|
|
{
|
|
foreach (ProjectFile Project in Folder.ChildProjects)
|
|
{
|
|
string ProjectIdentifier = String.Format("{0}{1}", Project.ProjectFilePath.GetFileNameWithoutExtension(), Suffix);
|
|
if (Project == DefaultProject)
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>(ProjectIdentifier, new string[] { ProjectIdentifier }));
|
|
}
|
|
else
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>(ProjectIdentifier, new string[] { }));
|
|
}
|
|
}
|
|
|
|
foreach (MasterProjectFolder SubFolder in Folder.SubFolders)
|
|
{
|
|
string SubFolderName = SubFolder.FolderName + Suffix;
|
|
if (SubFolderName == "Automation;Programs")
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>(SubFolderName, new string[] { }));
|
|
}
|
|
else
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>(SubFolderName, new string[] { SubFolderName }));
|
|
}
|
|
BuildSolutionExplorerState_VS2017(SubFolder, ";" + SubFolderName, ExplorerState, DefaultProject);
|
|
}
|
|
}
|
|
|
|
static void BuildSolutionExplorerState_VS2015(List<ProjectFile> AllProjectFiles, VCSolutionExplorerState ExplorerState, ProjectFile DefaultProject, bool IncludeEnginePrograms)
|
|
{
|
|
foreach (ProjectFile ProjectFile in AllProjectFiles)
|
|
{
|
|
string ProjectName = ProjectFile.ProjectFilePath.GetFileNameWithoutExtension();
|
|
if (ProjectFile == DefaultProject)
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>(ProjectName, new string[] { ProjectName }));
|
|
}
|
|
else
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>(ProjectName, new string[] { }));
|
|
}
|
|
}
|
|
if (IncludeEnginePrograms)
|
|
{
|
|
ExplorerState.OpenProjects.Add(new Tuple<string, string[]>("Automation", new string[0]));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Takes a string and "cleans it up" to make it parsable by the Visual Studio source control provider's file format
|
|
/// </summary>
|
|
/// <param name="Str">String to clean up</param>
|
|
/// <returns>The cleaned up string</returns>
|
|
public string CleanupStringForSCC(string Str)
|
|
{
|
|
string Cleaned = Str;
|
|
|
|
// SCC is expecting paths to contain only double-backslashes for path separators. It's a bit weird but we need to do it.
|
|
Cleaned = Cleaned.Replace(Path.DirectorySeparatorChar.ToString(), Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString());
|
|
Cleaned = Cleaned.Replace(Path.AltDirectorySeparatorChar.ToString(), Path.DirectorySeparatorChar.ToString() + Path.DirectorySeparatorChar.ToString());
|
|
|
|
// SCC is expecting not to see spaces in these strings, so we'll replace spaces with "\u0020"
|
|
Cleaned = Cleaned.Replace(" ", "\\u0020");
|
|
|
|
return Cleaned;
|
|
}
|
|
|
|
}
|
|
|
|
}
|