Nuke.Unreal
Build Unreal apps in Style.
Loading...
Searching...
No Matches
UnrealBuild.Targets.cs
1using System;
2using System.IO;
3using System.Linq;
4using Nuke.Common;
5using Nuke.Common.IO;
6using Nuke.Common.Utilities.Collections;
7using GlobExpressions;
8using Nuke.Common.Tools.Git;
10using Nuke.Cola;
11using Nuke.Common.Utilities;
12using Nuke.Common.ProjectModel;
13using Serilog;
14using System.Runtime.InteropServices;
15using Nuke.Cola.Tooling;
16
17// Maximum line length of long parameter description:
18// ------------------------------------------------------------
19
20namespace Nuke.Unreal
21{
22 public abstract partial class UnrealBuild : NukeBuild
23 {
24 public virtual Target Info => _ => _
25 .Description("Prints curated information about project")
26 .Executes(PrintInfo);
27
28 public virtual Target CleanDeployment => _ => _
29 .Description("Removes previous deployment folder")
30 .Executes(() => GetOutput().DeleteDirectory());
31
32 public virtual Target CleanProject => _ => _
33 .Description("Removes auto generated folders of Unreal Engine from the project")
34 .Executes(() => Unreal.ClearFolder(ProjectFolder));
35
36 public virtual Target CleanPlugins => _ => _
37 .Description("Removes auto generated folders of Unreal Engine from the plugins")
38 .OnlyWhenDynamic(() => PluginsFolder.DirectoryExists())
39 .Executes(() =>
40 {
41 void recurseBody(AbsolutePath path)
42 {
43 if (Glob.Files(path, "*.uplugin", GlobOptions.CaseInsensitive).Any())
44 {
45 Log.Debug("Cleaning plugin {0}", path);
46 Unreal.ClearFolder(path);
47 }
48 else
49 {
50 foreach (var dir in Directory.EnumerateDirectories(path))
51 {
52 recurseBody((AbsolutePath)dir);
53 }
54 }
55 }
56
57 foreach (var pluginDir in Directory.EnumerateDirectories(PluginsFolder))
58 {
59 recurseBody((AbsolutePath)pluginDir);
60 }
61 });
62
63 public virtual Target Clean => _ => _
64 .Description("Removes auto generated folders of Unreal Engine")
65 .DependsOn(CleanProject)
66 .DependsOn(CleanPlugins);
67
68 public virtual Target Switch => _ => _
69 .Description("Switch to an explicit Engine version")
70 .DependsOn(Clean)
71 .Before(Prepare, Generate, BuildEditor, Build, Cook)
72 .Requires(() => UnrealVersion)
73 .Executes(() =>
74 {
75 Log.Information($"Targeting Unreal Engine {UnrealVersion} on platform {Platform}");
77 ProjectDescriptor = ProjectDescriptor with { EngineAssociation = UnrealVersion };
79 _projectDescriptor = null;
80 _engineVersionCache = null;
81 });
82
83 public virtual Target Prepare => _ => _
84 .Description(
85 """
86
87 Run necessary preparations which needs to be done before Unreal tools can handle
88 the project. By default it is empty and the main build project may override it or
89 other Targets can depend on it / hook into it.
90
91 """
92 );
93
94 public virtual Target Generate => _ => _
95 .Description(
96 """
97
98 Generate project files for the default IDE of the current platform
99 (Visual Studio or XCode)
100
101 """
102 )
103 .DependsOn(Prepare)
104 .Executes(() =>
105 {
106 Unreal.BuildTool(this, _ => _
107 .ProjectFiles()
109 .Game()
110 .If(Unreal.IsSource(this), _ => _
111 .Engine()
112 )
113 .Progress()
114 .AppendRaw(GetArgumentBlock("ubt"))
115 )("");
116 });
117
118 public virtual Target BuildEditor => _ => _
119 .Description(
120 """
121
122 Build the editor binaries so this project can be opened properly in the
123 Unreal editor
124
125 """
126 )
127 .After(Prepare)
128 .Executes(() =>
129 {
130 Unreal.BuildTool(this, _ => _
131 .Target(
134 EditorConfig
135 )
136 .Project(ProjectPath, true)
137 .If(Unreal.IsSource(this), _ => _
138 .Target(
139 "ShaderCompileWorker",
141 [UnrealConfig.Development]
142 )
143 .Quiet()
144 )
145 .FromMsBuild()
146 .Apply(UbtGlobal)
147 .AppendRaw(GetArgumentBlock("ubt"))
148 )("");
149 });
150
151 public virtual Target Build => _ => _
152 .Description("Build this project for execution")
153 .After(Cook) // Android needs Cook to happen before building the APK, so OBB files can be included in the APK
154 .After(Prepare)
155 .Executes(() =>
156 {
157 var targets = TargetType.Select(tt => tt == UnrealTargetType.Game
159 : ProjectName + tt
160 );
161 Unreal.BuildTool(this, _ => _
162 .For(targets, (t, _) => _
163 .Target(t, Platform, Config)
164 )
166 .Apply(UbtGlobal)
167 .AppendRaw(GetArgumentBlock("ubt"))
168 )("");
169 });
170
171
172 /// <summary>
173 /// UAT arguments to be applied every time UAT is called for Cooking. Override this function
174 /// in your main build class if your project needs extra intricacies for Cooking.
175 /// For example specifying maps explicitly.
176 /// </summary>
177 public virtual UatConfig UatCook(UatConfig _) => _;
178
179 /// <summary>
180 /// Enforce packaging for distribution when that is set from `Game` ini files.
181 /// Override this function in your main build class if you want a different logic set for
182 /// flagging packages for distribution.
183 /// </summary>
184 public virtual bool ForDistribution()
185 {
186 var section = ReadIniHierarchy("Game")["/Script/UnrealEd.ProjectPackagingSettings"];
187 return section != null && section
188 .GetFirst("ForDistribution", new() { Value = "" }).Value
189 .EqualsAnyOrdinalIgnoreCase("true", "1");
190 }
191
192 public virtual Target Cook => _ => _
193 .Description("Cook Unreal assets for standalone game execution")
194 .DependsOn(BuildEditor)
195 .Executes(() =>
196 {
197 var isAndroidPlatform = Platform == UnrealPlatform.Android;
198
199 var androidTextureMode = SelfAs<IAndroidTargets>()?.TextureMode
200 ?? [AndroidCookFlavor.Multi];
201
202 Config.ForEach(config =>
203 {
204 Unreal.AutomationTool(this, _ => _
205 .BuildCookRun(_ => _
207 .Clientconfig(config)
208 .Skipstage()
209 .Manifests()
210 .If(ForDistribution(), _ => _
211 .Distribution()
212 )
213 )
214 .ScriptsForProject(ProjectPath)
215 .Targetplatform(Platform)
216 .Cook()
217 .If(InvokedTargets.Contains(BuildEditor), _ => _
218 .NoCompileEditor()
219 )
220 .If(isAndroidPlatform, _ => _
221 .Cookflavor(androidTextureMode)
222 )
223 .Apply(UatGlobal)
224 .Apply(UatCook)
225 .AppendRaw(GetArgumentBlock("uat"))
226 )("", workingDirectory: UnrealEnginePath);
227 });
228 });
229
230 public virtual Target EnsureBuildPluginSupport => _ => _
231 .Description(
232 """
233
234 Ensure support for plain C# build plugins without the need for CSX or dotnet
235 projects. This only needs to be done once, you can check the results into
236 source control.
237
238 """
239 )
240 .Executes(() =>
241 {
242 var project = ProjectModelTasks.ParseProject(BuildProjectFile);
243 project.SkipEvaluation = true;
244 var compileItems = project.GetItems("Compile");
245 var pattern = "../**/*.nuke.cs";
246
247 if (BuildProjectFile.ReadAllText().Contains(pattern))
248 Log.Debug("Build project already supports standalone C# build plugins.");
249 else
250 {
251 Log.Information("Preparing build project to accept standalone C# files. {0}, in {1}", pattern, BuildProjectFile);
252 project.AddItem("Compile", pattern);
253 project.Save();
254 Log.Information("This only needs to be done once, you can check the results into source control.");
255 }
256 });
257
258 [Parameter("Do not use globally applicable UBT/UAT arguments with run-uat/run-ubt")]
259 public bool IgnoreGlobalArgs = false;
260
261 public virtual Target RunUat => _ => _
262 .Description("Simply run UAT with arguments passed after `-->`")
263 .Executes(() =>
264 {
265 Unreal.AutomationTool(this, _ => _
266 .AppendRaw(GetArgumentBlock())
267 .If(!IgnoreGlobalArgs, _ => _.Apply(UatGlobal))
268 )("", workingDirectory: ProjectFolder);
269 });
270
271 public virtual Target RunUbt => _ => _
272 .Description("Simply run UBT with arguments passed after `-->`")
273 .Executes(() =>
274 {
275 Unreal.BuildTool(this, _ => _
276 .AppendRaw(GetArgumentBlock())
277 .If(!IgnoreGlobalArgs, _ => _.Apply(UbtGlobal))
278 )("", workingDirectory: ProjectFolder);
279 });
280
281 public virtual Target RunShell => _ => _
282 .Description(
283 """
284
285 Start a UShell session. This opens a new console window, and nuke will exit
286 immadiately. Working directory is the project folder, regardless of actual
287 working directory.
288
289 """
290 )
291 .Executes(() =>
292 {
293 var ushellDir = UnrealEnginePath / "Engine" / "Extras" / "ushell";
294 var scriptExt = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "bat" : "sh";
295 var ushellScript = ushellDir / ("ushell." + scriptExt);
296 Common.Tooling.ProcessTasks.StartShell(
297 ushellScript,
299 );
300 });
301
302 [Parameter(
303 """
304
305 Name the Unreal tool to be run, You can omit the `Unreal` prefix and the extension.
306 For example:
307 nuke run --tool pak --> ./Path/To/MyProject.pak -Extract "D:/temp"
308 nuke run --tool editor-cmd --> ~p -run=MyCommandlet
309
310 """
311 )]
312 public string? Tool;
313
314 public virtual Target Run => _ => _
315 .Description(
316 """
317
318 Run an Unreal tool from the engine binaries folder. You can omit the `Unreal`
319 prefix and the extension. For example:
320
321 nuke run --tool pak --> ./Path/To/MyProject.pak -Extract "D:/temp"
322 nuke run --tool editor-cmd --> ~p -run=MyCommandlet
323
324 Working directory is the project folder, regardless of actual working
325 directory.
326
327 """
328 )
329 .Requires(() => Tool)
330 .Executes(() =>
331 {
332 Unreal.GetTool(this, Tool!).WithSemanticLogging()(
333 GetArgumentBlock().JoinSpace(), ProjectFolder
334 );
335 });
336
337 [Parameter("Name of the editor commandlet to run")]
338 public string? Cmd;
339
340 public virtual Target RunEditorCmd => _ => _
341 .Description("Run an editor commandlet with arguments passed in after -->")
342 .Requires(() => Cmd)
343 .Executes(() =>
344 {
345 Unreal.GetTool(this, "Editor-Cmd").WithSemanticLogging()(
347 .Prepend($"{ProjectPath} -run={Cmd}")
348 .JoinSpace()
349 ,
351 );
352 });
353 }
354}
Unreal Automation Tool is a vast collection of scripts solving all aspects of deploying a program mad...
Definition UatConfig.cs:13
The main build class Unreal projects using Nuke.Unreal should inherit from. This class contains all b...
AbsolutePath ProjectFolder
Path to folder containing the .project file.
virtual IEnumerable< string > GetArgumentBlock(string name="")
Get optionally named argument block (section after -->) with contextual data substituted....
virtual AbsolutePath ProjectPath
string ProjectName
Short name of the project.
ProjectDescriptor ProjectDescriptor
"Immutable" C# representation of the .uproject contents
AbsolutePath UnrealEnginePath
Path to the root of the associated Unreal Engine installation/source.
virtual UbtConfig UbtGlobal(UbtConfig _)
UBT arguments to be applied globally for all UBT invocations. Override this function in your main bui...
virtual UatConfig UatCook(UatConfig _)
UAT arguments to be applied every time UAT is called for Cooking. Override this function in your main...
virtual AbsolutePath GetOutput()
Get an output folder where the targets should store their artifacts. Override this function in your m...
virtual ? string UnrealVersion
Most targets read the desired Unreal version from the project file.
virtual bool ForDistribution()
Enforce packaging for distribution when that is set from Game ini files. Override this function in yo...
ConfigIni ReadIniHierarchy(string shortName, IniHierarchyLevel lowestLevel=IniHierarchyLevel.Base, IniHierarchyLevel highestLevel=IniHierarchyLevel.Saved, bool considerPlugins=true, IEnumerable< string >? extraConfigSubfolder=null)
Read INI configuration emulating the same hierarchy of importance as Unreal Engine also does.
virtual void PrintInfo()
Print some rudimentary information onto console about this project and it's environment....
virtual UatConfig UatGlobal(UatConfig _)
UAT arguments to be applied globally for all UAT invocations. Override this function in your main bui...
Build configurations UBT supports.
High level representation of common platforms supported by Unreal Engine (NDA ones excluded) and extr...
static UnrealPlatform FromFlag(UnrealPlatformFlag flag)
Get the high-level platform from a bit-field platform flag.
The regular target types UBT supports.
static readonly UnrealTargetType Editor
Editor builds for the project.
static readonly UnrealTargetType Game
Can act as both client and server.
A collection of utilities around basic functions regarding the environment of the Engine we're workin...
Definition Unreal.cs:24
static void WriteJson(object input, AbsolutePath path)
Write data in JSON with Unreal conventions of JSON format.
Definition Unreal.cs:82
static Tool AutomationTool(EngineVersion ofVersion)
Prepare invocation for UAT.
Definition Unreal.cs:266
static Tool GetTool(UnrealBuild build, string name)
Get a native binary tool from Engine/Binaries folder. Unreal tools written in C# or stored in other f...
Definition Unreal.cs:345
static void InvalidateEnginePathCache()
In the rare and unlikely case that the Engine location may have changed during one session.
static bool IsSource(AbsolutePath enginePath)
Is given path an engine built from source?
static Tool BuildTool(EngineVersion ofVersion)
Prepare invocation for UBT.
Definition Unreal.cs:219
static UnrealPlatformFlag GetDefaultPlatform()
Get the current development platform Nuke.Unreal is ran on.
Definition Unreal.cs:197
static void ClearFolder(AbsolutePath folder)
Clear intermediate folders of Unreal from a given folder.
Definition Unreal.cs:311
@ Project
Enable debug info for project modules.
TargetType
The type of target.
@ Game
Cooked monolithic game executable (GameName.exe). Also used for a game-agnostic engine executable (UE...