You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects - UnrealArch is a single architecture, expandable enum-like struct - There is no more concept of "no/default architecture", there is always a valid active architecture when building - Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not - UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc) - UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm) - TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once) - Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc) #preflight 63c81fb5b065224750a1759e #rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts] #p4v-preflight-copy 23562471 [CL 23829977 by josh adams in ue5-main branch]
264 lines
10 KiB
C#
264 lines
10 KiB
C#
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using System.Collections.Generic;
|
|
using System.Text.RegularExpressions;
|
|
using EpicGames.Core;
|
|
using Microsoft.Extensions.Logging;
|
|
using UnrealBuildBase;
|
|
|
|
namespace UnrealBuildTool
|
|
{
|
|
abstract class UEToolChain
|
|
{
|
|
protected readonly ILogger Logger;
|
|
|
|
public UEToolChain(ILogger InLogger)
|
|
{
|
|
Logger = InLogger;
|
|
}
|
|
|
|
public virtual void SetEnvironmentVariables()
|
|
{
|
|
}
|
|
|
|
public virtual void GetVersionInfo(List<string> Lines)
|
|
{
|
|
}
|
|
|
|
public virtual void GetExternalDependencies(HashSet<FileItem> ExternalDependencies)
|
|
{
|
|
}
|
|
|
|
public static DirectoryReference GetModuleInterfaceDir(DirectoryReference OutputDir)
|
|
{
|
|
return DirectoryReference.Combine(OutputDir, "Ifc");
|
|
}
|
|
|
|
// Return the path to the cpp compiler that will be used by this toolchain.
|
|
public virtual FileReference? GetCppCompilerPath()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
protected abstract CPPOutput CompileCPPFiles(CppCompileEnvironment CompileEnvironment, List<FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, IActionGraphBuilder Graph);
|
|
|
|
public CPPOutput CompileAllCPPFiles(CppCompileEnvironment CompileEnvironment, List<FileItem> InputFiles, DirectoryReference OutputDir, string ModuleName, IActionGraphBuilder Graph)
|
|
{
|
|
CPPOutput Result;
|
|
|
|
UnrealArchitectureConfig ArchConfig = UnrealArchitectureConfig.ForPlatform(CompileEnvironment.Platform);
|
|
// compile architectures separately if needed
|
|
if (ArchConfig.Mode == UnrealArchitectureMode.SingleTargetCompileSeparately || ArchConfig.Mode == UnrealArchitectureMode.SingleTargetLinkSeparately)
|
|
{
|
|
Result = new CPPOutput();
|
|
foreach (UnrealArch Arch in CompileEnvironment.Architectures.Architectures)
|
|
{
|
|
// determine the output location of intermediates (so, if OutputDir had the arch name in it, like Intermediate/x86+arm64, we would replace it with either emptry string
|
|
// or a single arch name depending on if the platform uses architecture directories for the architecture)
|
|
// @todo Add ArchitectureConfig.RequiresArchitectureFilenames but for directory -- or can we just use GetFolderNameForArch?!?!?
|
|
// string ArchReplacement = (Arch == ArchitectureWithoutMarkup()) ? "" : ArchConfig.GetFolderNameForArchitecture(Arch);
|
|
|
|
string PlatformArchitecturesString = ArchConfig.GetFolderNameForArchitectures(CompileEnvironment.Architectures);
|
|
DirectoryReference ArchOutputDir = new(OutputDir.FullName.Replace(PlatformArchitecturesString, ArchConfig.GetFolderNameForArchitecture(Arch)));
|
|
|
|
CppCompileEnvironment ArchEnvironment = new(CompileEnvironment, Arch);
|
|
CPPOutput ArchResult = CompileCPPFiles(ArchEnvironment, InputFiles, ArchOutputDir, ModuleName, Graph);
|
|
Result.Merge(ArchResult, Arch);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Result = CompileCPPFiles(CompileEnvironment, InputFiles, OutputDir, ModuleName, Graph);
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
public virtual CPPOutput CompileRCFiles(CppCompileEnvironment Environment, List<FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
|
|
{
|
|
CPPOutput Result = new CPPOutput();
|
|
return Result;
|
|
}
|
|
|
|
public virtual CPPOutput CompileISPCFiles(CppCompileEnvironment Environment, List<FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
|
|
{
|
|
CPPOutput Result = new CPPOutput();
|
|
return Result;
|
|
}
|
|
|
|
public virtual CPPOutput GenerateISPCHeaders(CppCompileEnvironment Environment, List<FileItem> InputFiles, DirectoryReference OutputDir, IActionGraphBuilder Graph)
|
|
{
|
|
CPPOutput Result = new CPPOutput();
|
|
return Result;
|
|
}
|
|
|
|
public virtual void GenerateTypeLibraryHeader(CppCompileEnvironment CompileEnvironment, ModuleRules.TypeLibrary TypeLibrary, FileReference OutputFile, IActionGraphBuilder Graph)
|
|
{
|
|
throw new NotSupportedException("This platform does not support type libraries.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows a toolchain to decide to create an import library if needed for this Environment
|
|
/// </summary>
|
|
/// <param name="LinkEnvironment"></param>
|
|
/// <param name="Graph"></param>
|
|
/// <returns></returns>
|
|
public virtual FileItem[] LinkImportLibrary(LinkEnvironment LinkEnvironment, IActionGraphBuilder Graph)
|
|
{
|
|
// by default doing nothing
|
|
return new FileItem[] { };
|
|
}
|
|
|
|
public abstract FileItem? LinkFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly, IActionGraphBuilder Graph);
|
|
public virtual FileItem[] LinkAllFiles(LinkEnvironment LinkEnvironment, bool bBuildImportLibraryOnly, IActionGraphBuilder Graph)
|
|
{
|
|
List<FileItem> Result = new();
|
|
|
|
// compile architectures separately if needed
|
|
UnrealArchitectureConfig ArchConfig = UnrealArchitectureConfig.ForPlatform(LinkEnvironment.Platform);
|
|
if (ArchConfig.Mode == UnrealArchitectureMode.SingleTargetLinkSeparately)
|
|
{
|
|
foreach (UnrealArch Arch in LinkEnvironment.Architectures.Architectures)
|
|
{
|
|
LinkEnvironment ArchEnvironment = new LinkEnvironment(LinkEnvironment, Arch);
|
|
|
|
// determine the output location of intermediates (so, if OutputDir had the arch name in it, like Intermediate/x86+arm64, we would replace it with either emptry string
|
|
// or a single arch name
|
|
//string ArchReplacement = Arch == ArchitectureWithoutMarkup() ? "" : ArchConfig.GetFolderNameForArchitecture(Arch);
|
|
string PlatformArchitecturesString = ArchConfig.GetFolderNameForArchitectures(LinkEnvironment.Architectures);
|
|
|
|
ArchEnvironment.OutputFilePaths = LinkEnvironment.OutputFilePaths.Select(x => new FileReference(x.FullName.Replace(PlatformArchitecturesString, ArchConfig.GetFolderNameForArchitecture(Arch)))).ToList();
|
|
|
|
FileItem? LinkFile = LinkFiles(ArchEnvironment, bBuildImportLibraryOnly, Graph);
|
|
if (LinkFile != null)
|
|
{
|
|
Result.Add(LinkFile);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FileItem? LinkFile = LinkFiles(LinkEnvironment, bBuildImportLibraryOnly, Graph);
|
|
if (LinkFile != null)
|
|
{
|
|
Result.Add(LinkFile);
|
|
}
|
|
}
|
|
return Result.ToArray();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the name of the response file for the current linker environment and output file
|
|
/// </summary>
|
|
/// <param name="LinkEnvironment"></param>
|
|
/// <param name="OutputFile"></param>
|
|
/// <returns></returns>
|
|
public static FileReference GetResponseFileName(LinkEnvironment LinkEnvironment, FileItem OutputFile)
|
|
{
|
|
// Construct a relative path for the intermediate response file
|
|
return FileReference.Combine(LinkEnvironment.IntermediateDirectory!, OutputFile.Location.GetFileName() + ".response");
|
|
}
|
|
|
|
public virtual ICollection<FileItem> PostBuild(FileItem Executable, LinkEnvironment ExecutableLinkEnvironment, IActionGraphBuilder Graph)
|
|
{
|
|
return new List<FileItem>();
|
|
}
|
|
|
|
public virtual ICollection<FileItem> PostBuild(FileItem[] Executables, LinkEnvironment ExecutableLinkEnvironment, IActionGraphBuilder Graph)
|
|
{
|
|
// by default, run PostBuild for exe Exe and merge results
|
|
return Executables.SelectMany(x => PostBuild(x, ExecutableLinkEnvironment, Graph)).ToList();
|
|
}
|
|
|
|
public virtual void SetUpGlobalEnvironment(ReadOnlyTargetRules Target)
|
|
{
|
|
}
|
|
|
|
public virtual void ModifyBuildProducts(ReadOnlyTargetRules Target, UEBuildBinary Binary, List<string> Libraries, List<UEBuildBundleResource> BundleResources, Dictionary<FileReference, BuildProductType> BuildProducts)
|
|
{
|
|
}
|
|
|
|
public virtual void ModifyTargetReceipt(TargetReceipt Receipt)
|
|
{
|
|
}
|
|
|
|
public virtual void FinalizeOutput(ReadOnlyTargetRules Target, TargetMakefileBuilder MakefileBuilder)
|
|
{
|
|
}
|
|
|
|
public virtual void PrepareRuntimeDependencies(List<RuntimeDependency> RuntimeDependencies, Dictionary<FileReference, FileReference> TargetFileToSourceFile, DirectoryReference ExeDir)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a build product and its associated debug file to a receipt.
|
|
/// </summary>
|
|
/// <param name="OutputFile">Build product to add</param>
|
|
/// <param name="OutputType">The type of build product</param>
|
|
public virtual bool ShouldAddDebugFileToReceipt(FileReference OutputFile, BuildProductType OutputType)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public virtual FileReference GetDebugFile(FileReference OutputFile, string DebugExtension)
|
|
{
|
|
// by default, just change the extension to the debug extension
|
|
return OutputFile.ChangeExtension(DebugExtension);
|
|
}
|
|
|
|
public virtual void SetupBundleDependencies(List<UEBuildBinary> Binaries, string GameName)
|
|
{
|
|
}
|
|
|
|
public virtual string GetSDKVersion()
|
|
{
|
|
return "Not Applicable";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs the provided tool and argument. Returns the output, using a rexex capture if one is provided
|
|
/// </summary>
|
|
/// <param name="Command">Full path to the tool to run</param>
|
|
/// <param name="ToolArg">Argument that will be passed to the tool</param>
|
|
/// <param name="Expression">null, or a Regular expression to capture in the output</param>
|
|
/// <returns></returns>
|
|
protected string? RunToolAndCaptureOutput(FileReference Command, string ToolArg, string? Expression = null)
|
|
{
|
|
string ProcessOutput = Utils.RunLocalProcessAndReturnStdOut(Command.FullName, ToolArg, Logger);
|
|
|
|
if (string.IsNullOrEmpty(Expression))
|
|
{
|
|
return ProcessOutput;
|
|
}
|
|
|
|
Match M = Regex.Match(ProcessOutput, Expression);
|
|
return M.Success ? M.Groups[1].ToString() : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs the provided tool and argument and parses the output to retrieve the version
|
|
/// </summary>
|
|
/// <param name="Command">Full path to the tool to run</param>
|
|
/// <param name="VersionArg">Argument that will result in the version string being shown (it's ok this is a byproduct of a command that returns an error)</param>
|
|
/// <param name="VersionExpression">Regular expression to capture the version. By default we look for four integers separated by periods, with the last two optional</param>
|
|
/// <returns></returns>
|
|
public Version RunToolAndCaptureVersion(FileReference Command, string VersionArg, string VersionExpression = @"(\d+\.\d+(\.\d+)?(\.\d+)?)")
|
|
{
|
|
string? ProcessOutput = RunToolAndCaptureOutput(Command, VersionArg, VersionExpression);
|
|
|
|
Version? ToolVersion;
|
|
|
|
if (Version.TryParse(ProcessOutput, out ToolVersion))
|
|
{
|
|
return ToolVersion;
|
|
}
|
|
|
|
Logger.LogWarning("Unable to retrieve version from {Command} {Arg}", Command, VersionArg);
|
|
|
|
return new Version(0, 0);
|
|
}
|
|
};
|
|
}
|