UnrealBuildTool(二)——UnrealBuildTool生成工程文件
UnrealBuildTool生成工程文件的整个流程
本文主要介绍UE4如何通过UnrealBuildTool.exe去生成工程文件“visual studio 中就是生成UE4.sln”文件
关于UnrealBuildTool.exe是如何生成的请查看上一篇文章UnrealBuildTool.exe的生成
一、UnrealBuildTool.exe 生成工程文件的全流程
为什么点一下 “GenerateProjectFiles.bat” (UnrealEngine/GenerateProjectFiles.bat)就能生成工程文件?初入Unreal4的坑根据教程一步步操作然后 “UE4.sln” 就生成出来了!!!!太神奇了吧!!
我要搞懂他!!我不要不明不白!
搭配下面这张图一起食用可以有一个更清晰的思路!
二、下面将把主流程抓出来梳理一遍整个生成过程
1、主入口 UnrealBuildTool中的Main()——一切的开端
当我们运行 GenerateProjectFiles.bat 的时候,默认会传入 “-ProjectFiles” 该参数,如下如所示(下图为GenerateProjectFiles.bat中的截屏)
/// <summary>
/// UnrealBuildTool.cs
/// </summary>
class GlobalOptions
{
...
[CommandLine]
[CommandLine("-Clean", Value="Clean")]
[CommandLine("-ProjectFiles", Value="GenerateProjectFiles")]
[CommandLine("-ProjectFileFormat=", Value="GenerateProjectFiles")]
[CommandLine("-Makefile", Value="GenerateProjectFiles")]
[CommandLine("-CMakefile", Value="GenerateProjectFiles")]
[CommandLine("-QMakefile", Value="GenerateProjectFiles")]
[CommandLine("-KDevelopfile", Value="GenerateProjectFiles")]
[CommandLine("-CodeliteFiles", Value="GenerateProjectFiles")]
[CommandLine("-XCodeProjectFiles", Value="GenerateProjectFiles")]
[CommandLine("-EdditProjectFiles", Value="GenerateProjectFiles")]
[CommandLine("-VSCode", Value="GenerateProjectFiles")]
[CommandLine("-VSMac", Value="GenerateProjectFiles")]
[CommandLine("-CLion", Value="GenerateProjectFiles")]
[CommandLine("-Rider", Value="GenerateProjectFiles")]
public string Mode = null;
...
}
private static int Main(string[] ArgumentsArray)
{
...
// 传入的数据进行数据类型的转化
CommandLineArguments Arguments = new CommandLineArguments(ArgumentsArray);
// 将上述数据转化成我们需要的对应参数 由于传入的是 -ProjectFiles 因此得到的Mode就是GenerateProjectFiles
GlobalOptions Options = new GlobalOptions(Arguments);
...
// 创建一个Mode
Type ModeType = typeof(BuildMode);
...
// 找到 GenerateProjectFiles 对应的Mode 此处得到的是 GenerateProjectFilesMode
if(!ModeNameToType.TryGetValue(Options.Mode, out ModeType))
{
Log.TraceError("No mode named '{0}'. Available modes are:\n {1}", Options.Mode, String.Join("\n ", ModeNameToType.Keys));
return 1;
}
...
// 创建对应的实例
ToolMode Mode = (ToolMode)Activator.CreateInstance(ModeType);
...
// 运行上述得到的Mode 即 GenerateProjectFilesMode
int Result = Mode.Execute(Arguments);
...
}
1、可以看到在Main中,将传入的参数进行编译,并创建了一个对应的Mode,最后运行该Mode,即Mode.Execute(Arguments)
2、由于传入的参数是“-ProjectFiles”,因此Options.Mode的值是GenerateProjectFiles,对应的ModeType便是GenerateProjectFilesMode
2、ToolMode不同的运行模式——Mode.Execute的运行
/// <summary>
/// GenerateProjectFilesMode.cs
/// </summary>
class GenerateProjectFilesMode : ToolMode
{
[CommandLine("-ProjectFileFormat")]
[CommandLine("-2012unsupported", Value = nameof(ProjectFileFormat.VisualStudio2012))]
[CommandLine("-2013unsupported", Value = nameof(ProjectFileFormat.VisualStudio2013))]
[CommandLine("-2015", Value = nameof(ProjectFileFormat.VisualStudio2015))]
[CommandLine("-2017", Value = nameof(ProjectFileFormat.VisualStudio2017))]
[CommandLine("-2019", Value = nameof(ProjectFileFormat.VisualStudio2019))]
[CommandLine("-Makefile", Value = nameof(ProjectFileFormat.Make))]
[CommandLine("-CMakefile", Value = nameof(ProjectFileFormat.CMake))]
[CommandLine("-QMakefile", Value = nameof(ProjectFileFormat.QMake))]
[CommandLine("-KDevelopfile", Value = nameof(ProjectFileFormat.KDevelop))]
[CommandLine("-CodeLiteFiles", Value = nameof(ProjectFileFormat.CodeLite))]
[CommandLine("-XCodeProjectFiles", Value = nameof(ProjectFileFormat.XCode))]
[CommandLine("-EddieProjectFiles", Value = nameof(ProjectFileFormat.Eddie))]
[CommandLine("-VSCode", Value = nameof(ProjectFileFormat.VisualStudioCode))]
[CommandLine("-VSMac", Value = nameof(ProjectFileFormat.VisualStudioMac))]
[CommandLine("-CLion", Value = nameof(ProjectFileFormat.CLion))]
[CommandLine("-Rider", Value = nameof(ProjectFileFormat.Rider))]
HashSet<ProjectFileFormat> ProjectFileFormats = new HashSet<ProjectFileFormat>();
public override int Execute(CommandLineArguments Arguments)
{
...
// 我们是没有设置任何参数的 所以Count是0
if (ProjectFileFormats.Count == 0)
{
...
// 我们是没有设置任何参数的 所以Count是0
if (ProjectFileFormats.Count == 0)
{
// 获取默认的ProjectFileFormats 也就是WindowsBuildHostPlatform
ProjectFileFormats.UnionWith(BuildHostPlatform.Current.GetDefaultProjectFileFormats());
}
}
...
switch (ProjectFileFormat)
{
...
case ProjectFileFormat.VisualStudio:
Generator = new VCProjectFileGenerator(ProjectFile, VCProjectFileFormat.Default, Arguments);
break;
...
}
Generators.Add(Generator);
}
...
foreach(ProjectFileGenerator Generator in Generators)
{
if (!Generator.GenerateProjectFiles(PlatformProjectGenerators, Arguments.GetRawArray()))
{
return (int)CompilationResult.OtherCompilationError;
}
}
...
}
}
1、我们是没有设置任何参数的 所以ProjectFileFormats.Count是0,我们获取默认的平台
2、如下面代码所示,获取默认平台的时候,查看当前的系统,发现是Win64,因此最后我们得到的平台就是WindowsBuildHostPlatform
3、我们根据当前的平台,在这里就是WindowsBuildHostPlatform,得到对应的"Generator",此处我们得到的是"VCProjectFileGenerator",并执行对应的"GenerateProjectFiles"方法
/// <summary>
/// BuildHostPlatform.cs
/// </summary>
public abstract class BuildHostPlatform
{
...
private static UnrealTargetPlatform GetRuntimePlatform()
{
PlatformID Platform = Environment.OSVersion.Platform;
switch (Platform)
{
case PlatformID.Win32NT:
return UnrealTargetPlatform.Win64;
...
}
}
static public BuildHostPlatform Current
{
get
{
if (CurrentPlatform == null)
{
UnrealTargetPlatform RuntimePlatform = GetRuntimePlatform();
if (RuntimePlatform == UnrealTargetPlatform.Win64)
{
CurrentPlatform = new WindowsBuildHostPlatform();
}
...
}
return CurrentPlatform;
}
}
}
class WindowsBuildHostPlatform : BuildHostPlatform
{
...
internal override IEnumerable<ProjectFileFormat> GetDefaultProjectFileFormats()
{
yield return ProjectFileFormat.VisualStudio;
}
}
4、继承自“ToolMode”的模式有如下这些,在调用UnrealBuildTool.exe的时候会根据不同的参数选择不同的Mode并执行"Execute"方法
3、ProjectFileGenerator生成器——生成对应的解决方案
/// <summary>
/// ProjectFileGenerator.cs
/// </summary>
abstract class ProjectFileGenerator
{
// 为所有已知引擎和游戏目标生成VisualStudio解决方案文件和VisualC++项目文件
public virtual bool GenerateProjectFiles( PlatformProjectGeneratorCollection PlatformProjectGenerators, String[] Arguments )
{
...
// 根据命令行选项配置项目生成器
ConfigureProjectFileGeneration( Arguments, ref IncludeAllPlatforms);
...
WriteProjectFiles(PlatformProjectGenerators);
...
}
protected virtual bool WriteProjectFiles(PlatformProjectGeneratorCollection PlatformProjectGenerators)
{
...
WriteMasterProjectFile( UBTProject, PlatformProjectGenerators );
...
return true;
}
protected abstract bool WriteMasterProjectFile( ProjectFile UBTProject, PlatformProjectGeneratorCollection PlatformProjectGenerators );
}
1、前面最后说到,调用Generator的"GenerateProjectFiles"方法,如上面代码所示
2、生成解决方案的时候首先会 进行生成方案的配置,即"ConfigureProjectFileGeneration"
3、接着开始将解决方案写入文件中,即"WriteProjectFiles(PlatformProjectGenerators)",该方法在子类中是有重写的,看下面的子类
/// <summary>
/// VCProjectFileGenerator.cs
/// </summary>
class VCProjectFileGenerator : ProjectFileGenerator
{
protected override bool WriteProjectFiles(PlatformProjectGeneratorCollection PlatformProjectGenerators)
{
if(!base.WriteProjectFiles(PlatformProjectGenerators))
{
return false;
}
// 写入自动引用文件
if (AutomationProjectFiles.Any())
{
...
}
...
}
protected override bool WriteMasterProjectFile(ProjectFile UBTProject, PlatformProjectGeneratorCollection PlatformProjectGenerators)
{
...
// 保存的文件名 UE4.sln
string SolutionFileName = MasterProjectName + ".sln";
...
// 保存解决方案文件
if (bSuccess)
{
string SolutionFilePath = FileReference.Combine(MasterProjectPath, SolutionFileName).FullName;
bSuccess = WriteFileIfChanged(SolutionFilePath, VCSolutionFileContent.ToString());
}
// 保存默认情况下选择开发编辑器配置的解决方案配置文件
if (bSuccess && Settings.bWriteSolutionOptionFile)
{
...
}
}
}
4、子类中"WriteProjectFiles"方法会先调用父类的"WriteProjectFiles",然后再写入自动引用文件并且保存
5、父类的"WriteProjectFiles"方法会调用"WriteMasterProjectFile",也就是我们此次的终点,生成"UE4.sln!!!"
7、继承自“ProjectFileGenerator”的生成器有如下这些,在对应Mode的Execute方法中会根据不同的平台选择不同的生成器,并进行解决方案的生成
三、这绝对是全网写的最最详细的UE4项目生成解释了!希望读者们能给我点个赞,多多增加阅读量!!
四、后面还会写第三篇,关于运行时调用UnrealBuildTool.exe的一些东西,多多支持!
更多推荐
所有评论(0)