Files
UnrealEngine/Engine/Source/ThirdParty/EOSSDK/EOSSDK.Build.cs
2025-05-18 13:04:45 +08:00

326 lines
11 KiB
C#

// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnrealBuildTool;
using EpicGames.Core;
using Microsoft.Extensions.Logging;
public class EOSSDK : ModuleRules
{
public virtual bool bHasPlatformBaseFile => false;
public virtual bool bHasMultiplePlatformSDKBuilds => false;
public string KittTargetConfiguration => "shipping";
public virtual string EOSSDKPlatformName
{
get
{
if (Target.IsInPlatformGroup(UnrealPlatformGroup.Windows))
{
return "Win64";
}
else
{
return Target.Platform.ToString();
}
}
}
public virtual string EOSSDKIdealPlatformSDKVersion => UEBuildPlatformSDK.GetSDKForPlatform(Target.Platform.ToString()).GetInstalledVersion();
public virtual string SDKBaseDir
{
get
{
// Prefer to use the SDK dir from the platform extension.
// Will fail if this is not a platform extension, or there is no SDK in the platform extension.
string PlatformExtensionBaseDir = GetModuleDirectoryForSubClass(this.GetType())?.FullName;
if(PlatformExtensionBaseDir != null)
{
PlatformExtensionBaseDir = Path.Combine(PlatformExtensionBaseDir, "SDK");
if(Directory.Exists(PlatformExtensionBaseDir))
{
return PlatformExtensionBaseDir;
}
}
// Fallback on the base module SDK.
return Path.Combine(ModuleDirectory, "SDK");
}
}
private string SDKIncludesDir
{
get
{
if (Target.Platform == UnrealTargetPlatform.IOS)
{
return Path.Combine(SDKBinariesDir, "EOSSDK.framework", "Headers");
}
return Path.Combine(SDKBaseDir, "Include");
}
}
private string FindPlatformSubDir(string ParentDir)
{
string PlatformDir = Path.Combine(ParentDir, EOSSDKPlatformName);
if (bHasMultiplePlatformSDKBuilds)
{
List<string> AvailableBuilds = Directory.GetDirectories(PlatformDir).ToList();
AvailableBuilds = AvailableBuilds.Where(x => Directory.EnumerateFiles(x, "*").Any()).ToList(); // ignore empty folders
string IdealBuildDir = AvailableBuilds.FirstOrDefault(Elem => Elem.Split("\\").Last().StartsWith(EOSSDKIdealPlatformSDKVersion));
if (Directory.Exists(IdealBuildDir))
{
Log.TraceVerboseOnce("Found EOSSDK for platform SDK \"{0}\" at \"{1}\".", EOSSDKIdealPlatformSDKVersion, IdealBuildDir);
return IdealBuildDir;
}
else
{
// Sort versions in ascendent order as the array returned by Directory.GetDirectories is not properly sorted
Comparison<string> AscendingOrder = (x, y) => int.Parse(x.Split("\\").Last().Split(".").First()).CompareTo(int.Parse(y.Split("\\").Last().Split(".").First()));
AvailableBuilds.Sort(AscendingOrder);
// Fall back to latest one available.
string LatestBuildDir = AvailableBuilds.Last();
string LatestBuildSDKVersion = LatestBuildDir.Split("\\").Last();
Log.TraceWarningOnce("Unable to find EOSSDK for platform SDK \"{0}\" in directory \"{1}\" (available builds: [{2}]), falling back on EOSSDK for platform SDK \"{3}\".",
EOSSDKIdealPlatformSDKVersion,
ParentDir,
string.Join(", ", AvailableBuilds.Select(elem => elem.Split("\\").Last())),
LatestBuildSDKVersion);
return LatestBuildDir;
}
}
else if (Directory.Exists(PlatformDir))
{
return PlatformDir;
}
return ParentDir;
}
public string SDKLibsDir => FindPlatformSubDir(Path.Combine(SDKBaseDir, "Lib"));
public string SDKBinariesDir => FindPlatformSubDir(Path.Combine(SDKBaseDir, "Bin"));
public virtual string EngineBinariesDir => Path.Combine(EngineDirectory, "Binaries", Target.Platform.ToString());
public virtual string LibraryLinkNameBase
{
get
{
if (Target.Platform == UnrealTargetPlatform.Android)
{
return "EOSSDK";
}
string ArchSuffix = (Target.Platform == UnrealTargetPlatform.Win64 && Target.Architecture == UnrealArch.Arm64) ? "arm64" : "";
return String.Format("EOSSDK-{0}-Shipping{1}", EOSSDKPlatformName, ArchSuffix);
}
}
public virtual string LibraryLinkName
{
get
{
if (Target.Platform == UnrealTargetPlatform.Mac)
{
return Path.Combine(SDKBinariesDir, "lib" + LibraryLinkNameBase + ".dylib");
}
else if(Target.Platform == UnrealTargetPlatform.Linux ||
Target.Platform == UnrealTargetPlatform.LinuxArm64)
{
return Path.Combine(SDKBinariesDir, "lib" + LibraryLinkNameBase + ".so");
}
else if (Target.Platform.IsInGroup(UnrealPlatformGroup.Microsoft))
{
return Path.Combine(SDKLibsDir, LibraryLinkNameBase + ".lib");
}
// Android has one .so per architecture, so just deal with that below.
// Other platforms will override this property.
throw new BuildException("Unsupported platform (LibraryLinkName)");
}
}
public virtual string RuntimeLibraryFileName
{
get
{
if (Target.Platform == UnrealTargetPlatform.Mac)
{
return "lib" + LibraryLinkNameBase + ".dylib";
}
else if (Target.Platform == UnrealTargetPlatform.IOS)
{
return LibraryLinkNameBase + ".framework";
}
else if (Target.Platform == UnrealTargetPlatform.Android ||
Target.Platform == UnrealTargetPlatform.Linux ||
Target.Platform == UnrealTargetPlatform.LinuxArm64)
{
return "lib" + LibraryLinkNameBase + ".so";
}
else if (Target.Platform.IsInGroup(UnrealPlatformGroup.Microsoft))
{
return LibraryLinkNameBase + ".dll";
}
// Other platforms will override this property.
throw new BuildException("Unsupported platform (RuntimeLibraryFileName)");
}
}
public virtual bool bRequiresRuntimeLoad
{
get
{
return Target.Platform.IsInGroup(UnrealPlatformGroup.Windows) || Target.Platform == UnrealTargetPlatform.Mac;
// Other platforms may override this property.
}
}
/**
* Allow projects to provide their own EOSSDK binaries.
* In monolithic targets, prevents this module adding EOSSDK binaries to the linker args. The project is expected to add EOSSDK binaries to the linker args instead.
* In unique build environments, prevents this module staging EOSSDK binaries. The project is expected to stage EOSSDK binaries instead.
*/
[ConfigFile(ConfigHierarchyType.Engine, "EOSSDK")]
bool bHasProjectBinary = false;
bool HasProjectBinary
{
get
{
// Keep supporting old GlobalDef mechanism in case licensees are using it
if (Target.GlobalDefinitions.Contains("EOSSDK_USE_PROJECT_BINARY=1"))
{
Logger.LogWarning("EOSSDK_USE_PROJECT_BINARY is deprecated, please use Engine.ini [EOSSDK] bHasProjectBinary=true config mechanism instead");
return true;
}
ConfigCache.ReadSettings(DirectoryReference.FromFile(Target.ProjectFile), Target.Platform, this);
return bHasProjectBinary;
}
}
public virtual bool bIncludeKITT => false;
public virtual string KittModuleName(string BaseName, string ConfigName)
{
return String.Format("{0}-{1}-{2}", BaseName, EOSSDKPlatformName, KittTargetConfiguration);
}
public virtual string KittModuleExtension()
{
throw new Exception("KITT is not supported on this platform: " + Target.Platform.ToString());
}
public virtual void AddKITTRuntimeDependency(string BaseName, string ConfigName)
{
// TODO: Pending further testing in other platforms. Not used by Switch
string KittModule = KittModuleName(BaseName, ConfigName) + KittModuleExtension();
string KittModuleSource = Path.Combine(SDKBinariesDir, KittModule);
string KittModuleTarget = Path.Combine(EngineBinariesDir, KittModule);
RuntimeDependencies.Add(KittModuleTarget, KittModuleSource, StagedFileType.NonUFS);
}
public EOSSDK(ReadOnlyTargetRules Target) : base(Target)
{
Type = ModuleType.External;
bool bIsMonolithic = Target.LinkType == TargetLinkType.Monolithic;
bool bIsUniqueBuildEnv = Target.BuildEnvironment == TargetBuildEnvironment.Unique;
bool bMergeModules = Target.bMergeModules;
// Don't link against the SDK if this is a monolithic or merged build and a project binary is being provided.
bool bEnableLink = !((bIsMonolithic || bMergeModules) && HasProjectBinary);
// Don't stage SDK binaries if we're not linking against the SDK, or if this is a unique build environment and a project binary is being provided
bool bEnableStage = bEnableLink && !(bIsUniqueBuildEnv && HasProjectBinary);
PublicDefinitions.Add("WITH_EOS_SDK=1");
PublicSystemIncludePaths.Add(SDKIncludesDir);
PublicDefinitions.Add(String.Format("EOSSDK_RUNTIME_LOAD_REQUIRED={0}", bRequiresRuntimeLoad ? 1 : 0));
PublicDefinitions.Add(String.Format("EOSSDK_RUNTIME_LIBRARY_NAME=\"{0}\"", RuntimeLibraryFileName));
if (bHasPlatformBaseFile)
{
PublicSystemIncludePaths.Add(Path.Combine(SDKIncludesDir, EOSSDKPlatformName));
PublicDefinitions.Add(string.Format("EOS_PLATFORM_BASE_FILE_NAME=\"eos_{0}_base.h\"", EOSSDKPlatformName));
}
if (Target.Platform == UnrealTargetPlatform.Android)
{
PublicSystemIncludePaths.Add(Path.Combine(SDKIncludesDir, "Android"));
if (bEnableLink)
{
PublicAdditionalLibraries.Add(Path.Combine(SDKBinariesDir, "static-stdc++", "libs", "armeabi-v7a", RuntimeLibraryFileName));
PublicAdditionalLibraries.Add(Path.Combine(SDKBinariesDir, "static-stdc++", "libs", "arm64-v8a", RuntimeLibraryFileName));
PublicAdditionalLibraries.Add(Path.Combine(SDKBinariesDir, "static-stdc++", "libs", "x86_64", RuntimeLibraryFileName));
string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(PluginPath, "EOSSDK_UPL.xml"));
}
}
else if (Target.Platform == UnrealTargetPlatform.IOS)
{
if (bEnableLink)
{
PublicAdditionalFrameworks.Add(new Framework("EOSSDK", SDKBinariesDir, "", true));
}
}
else if (Target.Platform == UnrealTargetPlatform.Mac)
{
if (bEnableLink)
{
string DylibPath = Path.Combine(Target.UEThirdPartyBinariesDirectory, "EOSSDK", "Mac", RuntimeLibraryFileName);
PublicDelayLoadDLLs.Add(DylibPath);
RuntimeDependencies.Add(DylibPath);
}
}
else
{
if(bEnableLink)
{
PublicAdditionalLibraries.Add(Path.Combine(SDKBinariesDir, LibraryLinkName));
if (Target.Platform == UnrealTargetPlatform.Linux && bIsMonolithic)
{
// Monolithic Linux will not look in Engine/Binaries/Linux at runtime, so copy it to target output dir instead.
// Note: other libs do get found in Engine/Binaries/ThirdParty, via relative paths from the TargetOutputDir, We _could_
// do the same thing as this _is_ essentially a third party binary...
RuntimeDependencies.Add(Path.Combine("$(TargetOutputDir)", RuntimeLibraryFileName), Path.Combine(SDKBinariesDir, RuntimeLibraryFileName));
}
else
{
RuntimeDependencies.Add(Path.Combine(EngineBinariesDir, RuntimeLibraryFileName), Path.Combine(SDKBinariesDir, RuntimeLibraryFileName));
// needed for linux to find the .so
PublicRuntimeLibraryPaths.Add(EngineBinariesDir);
}
if (bRequiresRuntimeLoad)
{
PublicDelayLoadDLLs.Add(RuntimeLibraryFileName);
}
}
}
if (bIncludeKITT && bEnableStage)
{
AddKITTRuntimeDependency("kitt", KittTargetConfiguration);
AddKITTRuntimeDependency("kitt_support", KittTargetConfiguration);
AddKITTRuntimeDependency("kitt_webkit", KittTargetConfiguration);
AddKITTRuntimeDependency("kitt_data_eos", KittTargetConfiguration);
}
}
}