Nuke.Unreal
Build Unreal apps in Style.
Loading...
Searching...
No Matches
UnrealBuild.cs
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq;
5using Nuke.Cola;
6using Nuke.Common;
7using Nuke.Common.IO;
8using Nuke.Common.Utilities;
9using Nuke.Common.Utilities.Collections;
10using Nuke.Unreal.Ini;
14using Serilog;
15
16namespace Nuke.Unreal;
17
18/// <summary>
19/// Indicating the INI config hierarchy importance, from least important to most important
20/// (in terms of what overrides the other)
21/// </summary>
23{
24 Base,
25 Default,
26 Saved
27}
28
29/// <summary>
30/// The main build class Unreal projects using Nuke.Unreal should inherit from. This class
31/// contains all base targets for use-cases which are relevant for 99% of Unreal project
32/// development tasks.
33/// </summary>
34[DisableDefaultOutput(DefaultOutput.ErrorsAndWarnings)]
35public abstract partial class UnrealBuild : NukeBuild, IUnrealBuild
36{
37 protected override void OnBuildCreated()
38 {
39 base.OnBuildCreated();
40 PlatformSdkManager.RegisterSdks();
41 }
42
43 /// <summary>
44 /// <para>
45 /// **NUKE PARAMETER**
46 /// </para>
47 /// Specify the target Unreal Engine version. It's used only for the Switch target. Everything else should infer
48 /// engine version from the project file. Can be simple version name like `5.5`, a GUID associated with engine
49 /// location or an absolute path to engine root.
50 /// </summary>
51 /// <remarks>
52 /// Most targets read the desired Unreal version from the project file.
53 /// </remarks>
54 [Parameter(Name = "unreal")]
55 public virtual string? UnrealVersion { get; set; }
56
57 /// <summary>
58 /// <para>
59 /// **NUKE PARAMETER**
60 /// </para>
61 /// Specify the output working directory for artifacts
62 /// </summary>
63 [Parameter]
64 public AbsolutePath? Output;
65
66 /// <summary>
67 /// Get an output folder where the targets should store their artifacts. Override this
68 /// function in your main build class to enforce your own.
69 /// </summary>
70 public virtual AbsolutePath GetOutput() => Output ??= ProjectFolder / "Intermediate" / "Output";
71
72 /// <summary>
73 /// <para>
74 /// **NUKE PARAMETER**
75 /// </para>
76 /// Set platform for running targets
77 /// </summary>
78 [Parameter]
80
81 /// <summary>
82 /// <para>
83 /// **NUKE PARAMETER**
84 /// </para>
85 /// The target configuration for building or packaging the project
86 /// </summary>
87 [Parameter]
88 public virtual UnrealConfig[] Config { get; set; } = [UnrealConfig.Development];
89
90 /// <summary>
91 /// <para>
92 /// **NUKE PARAMETER**
93 /// </para>
94 /// The editor configuration to be used while building or packaging the project
95 /// </summary>
96 [Parameter]
97 public virtual UnrealConfig[] EditorConfig { get; set; } = [UnrealConfig.Development];
98
99 /// <summary>
100 /// <para>
101 /// **NUKE PARAMETER**
102 /// </para>
103 /// The Unreal target type for building the project
104 /// </summary>
105 [Parameter]
106 public virtual UnrealTargetType[] TargetType { get; set; } = [UnrealTargetType.Game];
107
108 /// <summary>
109 /// <para>
110 /// **NUKE PARAMETER**
111 /// </para>
112 /// Select texture compression mode for Android
113 /// </summary>
114 [Parameter]
115 public virtual AndroidCookFlavor[] AndroidTextureMode { get; set; } = [ AndroidCookFlavor.Multi ];
116
117 /// <summary>
118 /// UBT arguments to be applied globally for all UBT invocations. Override this function
119 /// in your main build class if your project needs extra intricacies for everything what
120 /// UBT may do through Nuke.Unreal.
121 ///
122 /// These arguments are also propagated to all UAT invocations through its `-UbtArgs`
123 /// </summary>
124 public virtual UbtConfig UbtGlobal(UbtConfig _) => _
125 .WaitMutex();
126
127 /// <summary>
128 /// UAT arguments to be applied globally for all UAT invocations. Override this function
129 /// in your main build class if your project needs extra intricacies for everything what
130 /// UAT may do through Nuke.Unreal.
131 /// </summary>
132 public virtual UatConfig UatGlobal(UatConfig _)
133 {
134 var ubtArgs = GetArgumentBlock("ubt").ToList();
135 return _
136 .UTF8Output()
137 .WaitForUATMutex()
138 .NoP4()
139 .If(!ubtArgs.IsEmpty(), _ => _.UbtArgs(ubtArgs.JoinSpace()));
140 }
141
142 private EngineVersion? _engineVersionCache = null;
143
144 /// <summary>
145 /// Utility function to get the proper Engine version associated with current project.
146 /// Rather use `Unreal.Version` static function, that looks nicer.
147 /// </summary>
149 {
150 if (_engineVersionCache == null)
151 {
152 var versionString = UnrealVersion ?? ProjectDescriptor.EngineAssociation;
153 Assert.NotNull(versionString, "Unreal Engine version couldn't be determined");
154 _engineVersionCache = new(versionString!);
155 }
156 return _engineVersionCache!;
157 }
158
159 /// <summary>
160 /// Path to the root of the associated Unreal Engine installation/source
161 /// </summary>
162 public AbsolutePath UnrealEnginePath => Unreal.GetEnginePath(this);
163
164 /// <summary>
165 /// Print some rudimentary information onto console about this project and it's environment.
166 /// Override this function in your main build class if your project may have its own
167 /// important info like this useful for debugging.
168 /// </summary>
169 public virtual void PrintInfo()
170 {
171 var unrealVersion = GetEngineVersionFromProject();
172 Log.Information("Project name: {0}", ProjectPath.NameWithoutExtension);
173 Log.Information("Unreal version: {0}", unrealVersion.VersionName);
174 Log.Information("Unreal full version: {0}", unrealVersion.VersionPatch);
175 Log.Information("Unreal root: {0}", UnrealEnginePath);
176 Log.Information("Output folder: {0}", GetOutput());
177 }
178
179 /// <summary>
180 /// Get optionally named argument block (section after `-->`) with contextual data
181 /// substituted.
182 /// <list type="bullet">
183 /// <item>`~p` Project file path</item>
184 /// <item>`~pdir` Project folder</item>
185 /// <item>`~ue` Unreal Engine folder</item>
186 /// </list>
187 /// </summary>
188 public virtual IEnumerable<string> GetArgumentBlock(string name = "")
189 => Arguments.GetBlock(name)
190 .Select(a => a
191 .Replace("~p", ProjectPath)
192 .Replace("~pdir", ProjectFolder)
193 .Replace("~ue", UnrealEnginePath)
194 .DoubleQuoteIfNeeded()
195 );
196
197 /// <summary>
198 /// Read INI configuration emulating the same hierarchy of importance as Unreal Engine
199 /// also does.
200 /// </summary>
201 /// <param name="shortName">The name of the configuration like `Game` or `Engine`</param>
202 /// <param name="lowestLevel">
203 /// The least important level of hierarchy for reading this config.
204 /// Default is `Base`
205 /// </param>
206 /// <param name="highestLevel">
207 /// The maximum important level of hierarchy for reading this config
208 /// Default is `Saved`
209 /// </param>
210 /// <param name="considerPlugins">
211 /// If true also consider config files found in plugins.
212 /// Default if true.
213 /// </param>
214 /// <param name="extraConfigSubfolder">
215 /// Manually add extra configuration subfolders which may be outside of the normal
216 /// sources of config files.
217 /// </param>
218 /// <returns>The parsed contents of the indicated config name</returns>
220 string shortName,
221 IniHierarchyLevel lowestLevel = IniHierarchyLevel.Base,
222 IniHierarchyLevel highestLevel = IniHierarchyLevel.Saved,
223 bool considerPlugins = true,
224 IEnumerable<string>? extraConfigSubfolder = null
225 ) {
226 var resultIni = new ConfigIni();
227 extraConfigSubfolder = (extraConfigSubfolder ?? Enumerable.Empty<string>())
228 .Append(Platform.ToString());
229
230 IReadOnlyCollection<AbsolutePath> GlobIni(AbsolutePath folder)
231 {
232 return folder.GlobFiles($"{shortName}.ini", $"*{shortName}.ini");
233 }
234
235 void MergeInis(AbsolutePath folder, ConfigIni result)
236 {
237 if (folder.DirectoryExists())
238 foreach (var iniFile in GlobIni(folder))
239 {
240 var currIni = ConfigIni.Parse(File.ReadAllText(iniFile));
241 if (currIni != null)
242 result.Merge(currIni);
243 }
244 }
245
246 void GatherInis(AbsolutePath configFolder, ConfigIni result)
247 {
248 MergeInis(configFolder, resultIni);
249 foreach (var folder in extraConfigSubfolder.Select(s => configFolder / s))
250 {
251 if (folder.DirectoryExists())
252 MergeInis(folder, resultIni);
253 }
254 }
255
256 if (lowestLevel <= IniHierarchyLevel.Base && highestLevel >= IniHierarchyLevel.Base)
257 {
258 var configFolder = UnrealEnginePath / "Engine" / "Config";
259 var baseIni = ConfigIni.Parse(File.ReadAllText(configFolder / "Base.ini"));
260 if (baseIni != null)
261 resultIni.Merge(baseIni);
262
263 GatherInis(configFolder, resultIni);
264 }
265
266 if (lowestLevel <= IniHierarchyLevel.Default && highestLevel >= IniHierarchyLevel.Default)
267 {
268 var configFolder = ProjectFolder / "Config";
269 GatherInis(configFolder, resultIni);
270 }
271 if (lowestLevel <= IniHierarchyLevel.Default && highestLevel >= IniHierarchyLevel.Default && considerPlugins)
272 {
273 foreach (var pluginConfigFolder in (ProjectFolder / "Plugins").GlobDirectories("**/Config"))
274 {
275 GatherInis(pluginConfigFolder, resultIni);
276 }
277 }
278 if (lowestLevel <= IniHierarchyLevel.Saved && highestLevel >= IniHierarchyLevel.Saved)
279 {
280 var configFolder = ProjectFolder / "Saved" / "Config";
281 GatherInis(configFolder, resultIni);
282 }
283
284 return resultIni;
285 }
286}
High level representation of an Unreal Engine version.
The root class representing Unreal INI configuration.
Definition ConfigIni.cs:50
void Merge(ConfigIni from)
Compose another ConfigIni instance into this one, overriding existing values and adding new ones.
Definition ConfigIni.cs:120
static ? ConfigIni Parse(string? input)
Parse an Unreal configuration text into a ConfigIni.
Definition ConfigIni.cs:82
Static class managing IPlatformSdk implementations.
virtual UatConfig NoP4(params object[] values)
Disables Perforce functionality (default if not run on a build machine) Disables Perforce functionali...
virtual UatConfig UbtArgs(params object[] values)
extra options to pass to ubt
Unreal Automation Tool is a vast collection of scripts solving all aspects of deploying a program mad...
Definition UatConfig.cs:13
virtual UbtConfig WaitMutex(bool? val=null)
Whether to wait for the mutex rather than aborting immediately Wait for another instance to finish an...
Unreal Build Tool defines the Unreal project structure and provides unified source building utilities...
Definition UbtConfig.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
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 AbsolutePath GetOutput()
Get an output folder where the targets should store their artifacts. Override this function in your m...
virtual UnrealConfig[] Config
virtual UnrealConfig[] EditorConfig
EngineVersion GetEngineVersionFromProject()
Utility function to get the proper Engine version associated with current project....
virtual ? string UnrealVersion
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 AndroidCookFlavor[] AndroidTextureMode
virtual UnrealPlatform Platform
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 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 UnrealPlatformFlag GetHostPlatformFlag()
Get the current development platform flag Nuke.Unreal is ran on.
Definition Unreal.cs:197
static AbsolutePath GetEnginePath(string engineAssociation, bool ignoreCache=false)
Get the Unreal Engine path based on an input association text. (version, GUID or absolute path)
Definition Unreal.cs:116
Base interface for build components which require an UnrealBuild main class.
TargetType
The type of target.
IniHierarchyLevel
Indicating the INI config hierarchy importance, from least important to most important (in terms of w...