UE如何确定不同平台使用的Launch源文件

发布时间 2023-10-30 20:15:49作者: tsecer

问题

众所周知,UE的启动模块位于Engine\Source\Runtime\Launch文件夹,这个文件夹下包含了所有UE支持的平台类型,但是Launch.Build.cs文件并没有特殊的说明来确定使用哪个子文件夹的内容。

尽管从源代码组织结构上看可以想当然的知道只会选择当前构建平台,但是UE是如何知道具体使用哪个子文件夹中的源文件呢?

tsecer@harry: MINGW64 UnrealEngine/Engine/Source/Runtime/Launch/Private (release)
$ ll
total 216
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 Android/
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 HoloLens/
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 IOS/
-rw-r--r-- 1 tsecer 1049089   5256  6月  1  2022 Launch.cpp
-rw-r--r-- 1 tsecer 1049089 208485  6月  1  2022 LaunchEngineLoop.cpp
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 Linux/
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 Mac/
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 Unix/
drwxr-xr-x 1 tsecer 1049089      0  6月  1  2022 Windows/

Launch

这个模块在Unreal Built Tool的源代码中也有体现,但它只是默认作为一个必须包含的root模块(而不会影响平台文件夹的选取),对于一些对链接顺序由要求的平台(例如linux),或者模块之间加载顺序有依赖的场景,需要把这个模块放在最开始。

///@file: e:\tsecer\Engine\Source\Programs\UnrealBuildTool\Configuration\TargetRules.cs
	/// <summary>
	/// Specifies the name of the launch module. For modular builds, this is the module that is compiled into the target's executable.
	/// </summary>
	public string? LaunchModuleName
	{
		get
		{
			return (LaunchModuleNamePrivate == null && Type != global::UnrealBuildTool.TargetType.Program)? "Launch" : LaunchModuleNamePrivate;
		}
		set
		{
			LaunchModuleNamePrivate = value;
		}
	}

exclude

对于平台文件,并不是通过(最直观的、想当然的)包含指定文件夹,而是通过排除特定文件夹实现的。例如,在Windows下构建的时候,将会排除除了Windows文件夹之外的所有平台(Linux、IOS、Android、HoloLens)文件夹。

///@file: Engine\Source\Programs\UnrealBuildTool\Configuration\UEBuildModuleCPP.cs
	/// <summary>
	/// Finds all the source files that should be built for this module
	/// </summary>
	/// <param name="Platform">The platform the module is being built for</param>
	/// <param name="DirectoryToSourceFiles">Map of directory to source files inside it</param>
	/// <returns>Set of source files that should be built</returns>
	public InputFileCollection FindInputFiles(UnrealTargetPlatform Platform, Dictionary<DirectoryItem, FileItem[]> DirectoryToSourceFiles)
	{
		ReadOnlyHashSet<string> ExcludedNames = UEBuildPlatform.GetBuildPlatform(Platform).GetExcludedFolderNames();

		InputFileCollection InputFiles = new InputFileCollection();

		SourceDirectories = new HashSet<DirectoryReference>();
		foreach (DirectoryReference Dir in ModuleDirectories)
		{
			DirectoryItem ModuleDirectoryItem = DirectoryItem.GetItemByDirectoryReference(Dir);
			FindInputFilesFromDirectoryRecursive(ModuleDirectoryItem, ExcludedNames, SourceDirectories, DirectoryToSourceFiles, InputFiles);
		}

		return InputFiles;
	}

platform

在Engine\Source\Programs\UnrealBuildTool\Platform文件夹下,包含了当前支持的所有平台,每个平台一个文件夹。在UBT启动的时候,会通过csharp的反射机制找到所有平台名称(UEBuildPlatform类的派生类)。例如,在linux平台下,对应的派生类为

	class LinuxPlatform : UEBuildPlatform
	{
		/// <summary>
		/// Linux host architecture (compiler target triplet)
		/// </summary>
		public const string DefaultHostArchitecture = "x86_64-unknown-linux-gnu";

		/// <summary>
		/// SDK in use by the platform
		/// </summary>
		protected LinuxPlatformSDK SDK;
	}

在Engine\Source\Runtime\Sockets\Private文件夹,同样存在不同平台的子文件夹,这是一个通用机制。

tsecer@harry MINGW64 UnrealEngine/Engine/Source/Runtime/Sockets/Private (release)
$ ll
total 50
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 Android/
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 BSDSockets/
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 HoloLens/
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 IOS/
-rw-r--r-- 1 tsecer 1049089  1875  6月  1  2022 IPAddress.cpp
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 Mac/
-rw-r--r-- 1 tsecer 1049089   135  6月  1  2022 MultichannelTcpGlobals.cpp
-rw-r--r-- 1 tsecer 1049089  3971  6月  1  2022 NetworkMessage.cpp
-rw-r--r-- 1 tsecer 1049089  2283  6月  1  2022 ServerTOC.cpp
-rw-r--r-- 1 tsecer 1049089  2322  6月  1  2022 Sockets.cpp
-rw-r--r-- 1 tsecer 1049089   170  6月  1  2022 SocketsPrivate.h
-rw-r--r-- 1 tsecer 1049089 26373  6月  1  2022 SocketSubsystem.cpp
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 Unix/
drwxr-xr-x 1 tsecer 1049089     0  6月  1  2022 Windows/

调用链

当然,我不是通过阅读代码分析的,而是通过调试器分析的,下面是调用链(做个备忘):

>	UnrealBuildTool.dll!UnrealBuildTool.UEBuildModuleCPP.FindInputFilesFromDirectory(UnrealBuildBase.DirectoryItem BaseDirectory, UnrealBuildTool.UEBuildModuleCPP.InputFileCollection InputFiles) 行 1543	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildModuleCPP.FindInputFilesFromDirectoryRecursive(UnrealBuildBase.DirectoryItem BaseDirectory, EpicGames.Core.ReadOnlyHashSet<string> ExcludedNames, System.Collections.Generic.HashSet<EpicGames.Core.DirectoryReference> SourceDirectories, System.Collections.Generic.Dictionary<UnrealBuildBase.DirectoryItem, UnrealBuildBase.FileItem[]> DirectoryToSourceFiles, UnrealBuildTool.UEBuildModuleCPP.InputFileCollection InputFiles) 行 1528	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildModuleCPP.FindInputFilesFromDirectoryRecursive(UnrealBuildBase.DirectoryItem BaseDirectory, EpicGames.Core.ReadOnlyHashSet<string> ExcludedNames, System.Collections.Generic.HashSet<EpicGames.Core.DirectoryReference> SourceDirectories, System.Collections.Generic.Dictionary<UnrealBuildBase.DirectoryItem, UnrealBuildBase.FileItem[]> DirectoryToSourceFiles, UnrealBuildTool.UEBuildModuleCPP.InputFileCollection InputFiles) 行 1524	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildModuleCPP.FindInputFilesFromDirectoryRecursive(UnrealBuildBase.DirectoryItem BaseDirectory, EpicGames.Core.ReadOnlyHashSet<string> ExcludedNames, System.Collections.Generic.HashSet<EpicGames.Core.DirectoryReference> SourceDirectories, System.Collections.Generic.Dictionary<UnrealBuildBase.DirectoryItem, UnrealBuildBase.FileItem[]> DirectoryToSourceFiles, UnrealBuildTool.UEBuildModuleCPP.InputFileCollection InputFiles) 行 1524	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildModuleCPP.FindInputFiles(UnrealBuildTool.UnrealTargetPlatform Platform, System.Collections.Generic.Dictionary<UnrealBuildBase.DirectoryItem, UnrealBuildBase.FileItem[]> DirectoryToSourceFiles) 行 1504	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildModuleCPP.Compile(UnrealBuildTool.ReadOnlyTargetRules Target, UnrealBuildTool.UEToolChain ToolChain, UnrealBuildTool.CppCompileEnvironment BinaryCompileEnvironment, System.Collections.Generic.List<EpicGames.Core.FileReference> SpecificFilesToCompile, UnrealBuildTool.ISourceFileWorkingSet WorkingSet, UnrealBuildTool.IActionGraphBuilder Graph) 行 395	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildBinary.SetupBinaryLinkEnvironment(UnrealBuildTool.ReadOnlyTargetRules Target, UnrealBuildTool.UEToolChain ToolChain, UnrealBuildTool.LinkEnvironment LinkEnvironment, UnrealBuildTool.CppCompileEnvironment CompileEnvironment, System.Collections.Generic.List<EpicGames.Core.FileReference> SpecificFilesToCompile, UnrealBuildTool.ISourceFileWorkingSet WorkingSet, EpicGames.Core.DirectoryReference ExeDir, UnrealBuildTool.IActionGraphBuilder Graph) 行 721	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildBinary.Build(UnrealBuildTool.ReadOnlyTargetRules Target, UnrealBuildTool.UEToolChain ToolChain, UnrealBuildTool.CppCompileEnvironment CompileEnvironment, UnrealBuildTool.LinkEnvironment LinkEnvironment, System.Collections.Generic.List<EpicGames.Core.FileReference> SpecificFilesToCompile, UnrealBuildTool.ISourceFileWorkingSet WorkingSet, EpicGames.Core.DirectoryReference ExeDir, UnrealBuildTool.IActionGraphBuilder Graph) 行 187	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UEBuildTarget.Build(UnrealBuildTool.BuildConfiguration BuildConfiguration, UnrealBuildTool.ISourceFileWorkingSet WorkingSet, UnrealBuildTool.TargetDescriptor TargetDescriptor) 行 1844	C#
 	UnrealBuildTool.dll!UnrealBuildTool.BuildMode.CreateMakefile(UnrealBuildTool.BuildConfiguration BuildConfiguration, UnrealBuildTool.TargetDescriptor TargetDescriptor, UnrealBuildTool.ISourceFileWorkingSet WorkingSet) 行 742	C#
 	UnrealBuildTool.dll!UnrealBuildTool.BuildMode.Build(System.Collections.Generic.List<UnrealBuildTool.TargetDescriptor> TargetDescriptors, UnrealBuildTool.BuildConfiguration BuildConfiguration, UnrealBuildTool.ISourceFileWorkingSet WorkingSet, UnrealBuildTool.BuildOptions Options, EpicGames.Core.FileReference WriteOutdatedActionsFile, bool bSkipPreBuildTargets) 行 267	C#
 	UnrealBuildTool.dll!UnrealBuildTool.BuildMode.Execute(EpicGames.Core.CommandLineArguments Arguments) 行 237	C#
 	UnrealBuildTool.dll!UnrealBuildTool.UnrealBuildTool.Main(string[] ArgumentsArray) 行 612	C#