代码编译时执行脚本

在插件的 uplugin 文件中可以写入 PreBuildSteps/PostBuildSteps 以下两个元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"PostBuildSteps":
{
"Win64":
[
"\"$(PluginDir)\\Source\\AkAudio\\WwisePostBuildSteps.bat\" \"$(EngineDir)\\Binaries\\Win64\\UE4Editor-cmd.exe\" \"$(ProjectFile)\" $(TargetType) -run=AkPluginActivator -platform=$(TargetPlatform) -configuration=Profile -targetconfig=$(TargetConfiguration)"
],
"PS4":
[
"\"$(PluginDir)\\Source\\AkAudio\\WwisePostBuildSteps.bat\" \"$(EngineDir)\\Binaries\\Win64\\UE4Editor-cmd.exe\" \"$(ProjectFile)\" -run=AkPluginActivator -platform=$(TargetPlatform) -configuration=Profile -targetconfig=$(TargetConfiguration)"
]
}
}

可以在构建时指定自动执行一个脚本,用来处理一些特殊的功能。

ProjectDescriptor的声明:Source\Programs\UnrealBuildTool\System\ProjectDescriptor.cs

在 UBT 的 Source\Programs\UnrealBuildTool\Configuration\UEBuildTarget.cs 中被解析:

Source\Programs\UnrealBuildTool\Configuration\UEBuildTarget.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/// <summary>
/// Creates scripts for executing the pre-build scripts
/// </summary>
public FileReference[] CreatePreBuildScripts() {
// Find all the pre-build steps
List < Tuple < string[],
UEBuildPlugin >> PreBuildCommandBatches = new List < Tuple < string[],
UEBuildPlugin >> ();
if (ProjectDescriptor != null && ProjectDescriptor.PreBuildSteps != null) {
AddCustomBuildSteps(ProjectDescriptor.PreBuildSteps, null, PreBuildCommandBatches);
}
if (Rules.PreBuildSteps.Count > 0) {
PreBuildCommandBatches.Add(new Tuple < string[], UEBuildPlugin > (Rules.PreBuildSteps.ToArray(), null));
}
foreach(UEBuildPlugin BuildPlugin in BuildPlugins.Where(x =>x.Descriptor.PreBuildSteps != null)) {
AddCustomBuildSteps(BuildPlugin.Descriptor.PreBuildSteps, BuildPlugin, PreBuildCommandBatches);
}
return WriteCustomBuildStepScripts(BuildHostPlatform.Current.Platform, ProjectIntermediateDirectory, "PreBuild", PreBuildCommandBatches);
}

/// <summary>
/// Creates scripts for executing post-build steps
/// </summary>
/// <returns>Array of post-build scripts</returns>
private FileReference[] CreatePostBuildScripts() {
// Find all the post-build steps
List < Tuple < string[],
UEBuildPlugin >> PostBuildCommandBatches = new List < Tuple < string[],
UEBuildPlugin >> ();
if (!Rules.bDisableLinking) {
if (ProjectDescriptor != null && ProjectDescriptor.PostBuildSteps != null) {
AddCustomBuildSteps(ProjectDescriptor.PostBuildSteps, null, PostBuildCommandBatches);
}
if (Rules.PostBuildSteps.Count > 0) {
PostBuildCommandBatches.Add(new Tuple < string[], UEBuildPlugin > (Rules.PostBuildSteps.ToArray(), null));
}
foreach(UEBuildPlugin BuildPlugin in BuildPlugins.Where(x =>x.Descriptor.PostBuildSteps != null)) {
AddCustomBuildSteps(BuildPlugin.Descriptor.PostBuildSteps, BuildPlugin, PostBuildCommandBatches);
}
}
return WriteCustomBuildStepScripts(BuildHostPlatform.Current.Platform, ProjectIntermediateDirectory, "PostBuild", PostBuildCommandBatches);
}

/// <summary>
/// Adds custom build steps from the given JSON object to the list of command batches
/// </summary>
/// <param name="BuildSteps">The custom build steps</param>
/// <param name="Plugin">The plugin to associate with these commands</param>
/// <param name="CommandBatches">List to receive the command batches</param>
private void AddCustomBuildSteps(CustomBuildSteps BuildSteps, UEBuildPlugin Plugin, List < Tuple < string[], UEBuildPlugin >> CommandBatches) {
string[] Commands;
if (BuildSteps.TryGetCommands(BuildHostPlatform.Current.Platform, out Commands)) {
CommandBatches.Add(Tuple.Create(Commands, Plugin));
}
}

/// <summary>
/// Write scripts containing the custom build steps for the given host platform
/// </summary>
/// <param name="HostPlatform">The current host platform</param>
/// <param name="Directory">The output directory for the scripts</param>
/// <param name="FilePrefix">Bare prefix for all the created script files</param>
/// <param name="CommandBatches">List of custom build steps, and their matching PluginInfo (if appropriate)</param>
/// <returns>List of created script files</returns>
private FileReference[] WriteCustomBuildStepScripts(UnrealTargetPlatform HostPlatform, DirectoryReference Directory, string FilePrefix, List < Tuple < string[], UEBuildPlugin >> CommandBatches) {
List < FileReference > ScriptFiles = new List < FileReference > ();
foreach(Tuple < string[], UEBuildPlugin > CommandBatch in CommandBatches) {
// Find all the standard variables
Dictionary < string,
string > Variables = GetTargetVariables(CommandBatch.Item2);

// Get the output path to the script
string ScriptExtension = (HostPlatform == UnrealTargetPlatform.Win64) ? ".bat": ".sh";
FileReference ScriptFile = FileReference.Combine(Directory, String.Format("{0}-{1}{2}", FilePrefix, ScriptFiles.Count + 1, ScriptExtension));

// Write it to disk
List < string > Contents = new List < string > ();
if (HostPlatform == UnrealTargetPlatform.Win64) {
Contents.Insert(0, "@echo off");
}
foreach(string Command in CommandBatch.Item1) {
Contents.Add(Utils.ExpandVariables(Command, Variables));
}
if (!DirectoryReference.Exists(ScriptFile.Directory)) {
DirectoryReference.CreateDirectory(ScriptFile.Directory);
}
File.WriteAllLines(ScriptFile.FullName, Contents);

// Add the output file to the list of generated scripts
ScriptFiles.Add(ScriptFile);
}
return ScriptFiles.ToArray();
}

在编译代码之后会执行指定的脚本,会有以下 Log:

1
2>8> Exec: PostBuild-1.bat.ran

注意:测试中发现如果插件的代码没有变动,它不会执行。