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;
12using Serilog;
13
14// Maximum line length of long parameter description:
15// ------------------------------------------------------------
16
17/// <summary>
18/// Indicating the INI config hierarchy importance, from least important to most important
19/// (in terms of what overrides the other)
20/// </summary>
21public enum IniHierarchyLevel
22{
23 Base,
24 Default,
25 Saved
26}
27
28namespace Nuke.Unreal
29{
30 /// <summary>
31 /// The main build class Unreal projects using Nuke.Unreal should inherit from. This class
32 /// contains all base targets for use-cases which are relevant for 99% of Unreal project
33 /// development tasks.
34 /// </summary>
35 public abstract partial class UnrealBuild : NukeBuild
36 {
37 /// <summary>
38 /// Shortcut to casting `this` to another class
39 /// </summary>
40 protected T Self<T>() where T : INukeBuild => (T)(object)this;
41
42 /// <summary>
43 /// Shortcut to casting `this` to another class
44 /// </summary>
45 protected T? SelfAs<T>() where T : class, INukeBuild => (object)this as T;
46
47 protected override void OnBuildInitialized()
48 {
49 base.OnBuildInitialized();
50 if (IsPerforce && IsLocalBuild)
51 {
52 Log.Warning("This project is part of a perforce workspace.");
53 Log.Warning("Some files may be locked by P4 which this build may modify. This may result in file-system errors.");
54 }
55 }
56
57 /// <summary>
58 /// Most targets read the desired Unreal version from the project file.
59 /// </summary>
60 [Parameter(
61 """
62
63 Specify the target Unreal Engine version. It's used only
64 for the Switch target. Everything else should infer engine
65 version from the project file. Can be simple version name
66 like `5.5`, a GUID associated with engine location or an
67 absolute path to engine root.
68
69 """,
70 Name = "unreal"
71 )]
72 public virtual string? UnrealVersion { get; set; }
73
74 [Parameter("Specify the output working directory for artifacts")]
75 public AbsolutePath? Output;
76
77 /// <summary>
78 /// Get an output folder where the targets should store their artifacts. Override this
79 /// function in your main build class to enforce your own.
80 /// </summary>
81 public virtual AbsolutePath GetOutput() => Output ??= ProjectFolder / "Intermediate" / "Output";
82
83 [Parameter("Set platform for running targets")]
84 public virtual UnrealPlatform Platform { get; set; } = UnrealPlatform.FromFlag(Unreal.GetDefaultPlatform());
85
86 [Parameter("The target configuration for building or packaging the project")]
87 public virtual UnrealConfig[] Config { get; set; } = [UnrealConfig.Development];
88
89 [Parameter("The editor configuration to be used while building or packaging the project")]
90 public virtual UnrealConfig[] EditorConfig { get; set; } = [UnrealConfig.Development];
91
92 [Parameter("The Unreal target type for building the project")]
93 public virtual UnrealTargetType[] TargetType { get; set; } = [UnrealTargetType.Game];
94
95 /// <summary>
96 /// UBT arguments to be applied globally for all UBT invocations. Override this function
97 /// in your main build class if your project needs extra intricacies for everything what
98 /// UBT may do through Nuke.Unreal.
99 ///
100 /// These arguments are also propagated to all UAT invocations through its `-UbtArgs`
101 /// </summary>
102 public virtual UbtConfig UbtGlobal(UbtConfig _) => _
103 .WaitMutex();
104
105 /// <summary>
106 /// UAT arguments to be applied globally for all UAT invocations. Override this function
107 /// in your main build class if your project needs extra intricacies for everything what
108 /// UAT may do through Nuke.Unreal.
109 /// </summary>
110 public virtual UatConfig UatGlobal(UatConfig _)
111 {
112 var ubtArgs = GetArgumentBlock("ubt").ToList();
113 return _
114 .UTF8Output()
115 .WaitForUATMutex()
116 .If(!IsPerforce, _ => _.NoP4())
117 .If(!ubtArgs.IsEmpty(), _ => _.UbtArgs(ubtArgs.JoinSpace()));
118 }
119
120 private EngineVersion? _engineVersionCache = null;
121
122 /// <summary>
123 /// Utility function to get the proper Engine version associated with current project.
124 /// Rather use `Unreal.Version` static function, that looks nicer.
125 /// </summary>
127 {
128 if (_engineVersionCache == null)
129 {
130 var versionString = UnrealVersion ?? ProjectDescriptor.EngineAssociation;
131 Assert.NotNull(versionString, "Unreal Engine version couldn't be determined");
132 _engineVersionCache = new(versionString!);
133 }
134 return _engineVersionCache!;
135 }
136
137 /// <summary>
138 /// Path to the root of the associated Unreal Engine installation/source
139 /// </summary>
140 public AbsolutePath UnrealEnginePath => Unreal.GetEnginePath(this);
141
142 /// <summary>
143 /// Print some rudimentary information onto console about this project and it's environment.
144 /// Override this function in your main build class if your project may have its own
145 /// important info like this useful for debugging.
146 /// </summary>
147 public virtual void PrintInfo()
148 {
149 var unrealVersion = GetEngineVersionFromProject();
150 Log.Information("Project name: {0}", ProjectPath.NameWithoutExtension);
151 Log.Information("Unreal version: {0}", unrealVersion.VersionName);
152 Log.Information("Unreal full version: {0}", unrealVersion.VersionPatch);
153 Log.Information("Unreal root: {0}", UnrealEnginePath);
154 Log.Information("Output folder: {0}", GetOutput());
155 }
156
157 /// <summary>
158 /// Get optionally named argument block (section after `-->`) with contextual data
159 /// substituted.
160 /// <list type="bullet">
161 /// <item>`~p` Project file path</item>
162 /// <item>`~pdir` Project folder</item>
163 /// <item>`~ue` Unreal Engine folder</item>
164 /// </list>
165 /// </summary>
166 public virtual IEnumerable<string> GetArgumentBlock(string name = "")
167 => Arguments.GetBlock(name)
168 .Select(a => a
169 .Replace("~p", ProjectPath)
170 .Replace("~pdir", ProjectFolder)
171 .Replace("~ue", UnrealEnginePath)
172 .DoubleQuoteIfNeeded()
173 );
174
175 /// <summary>
176 /// Read INI configuration emulating the same hierarchy of importance as Unreal Engine
177 /// also does.
178 /// </summary>
179 /// <param name="shortName">The name of the configuration like `Game` or `Engine`</param>
180 /// <param name="lowestLevel">
181 /// The least important level of hierarchy for reading this config.
182 /// Default is `Base`
183 /// </param>
184 /// <param name="highestLevel">
185 /// The maximum important level of hierarchy for reading this config
186 /// Default is `Saved`
187 /// </param>
188 /// <param name="considerPlugins">
189 /// If true also consider config files found in plugins.
190 /// Default if true.
191 /// </param>
192 /// <param name="extraConfigSubfolder">
193 /// Manually add extra configuration subfolders which may be outside of the normal
194 /// sources of config files.
195 /// </param>
196 /// <returns>The parsed contents of the indicated config name</returns>
198 string shortName,
199 IniHierarchyLevel lowestLevel = IniHierarchyLevel.Base,
200 IniHierarchyLevel highestLevel = IniHierarchyLevel.Saved,
201 bool considerPlugins = true,
202 IEnumerable<string>? extraConfigSubfolder = null
203 ) {
204 var resultIni = new ConfigIni();
205 extraConfigSubfolder = (extraConfigSubfolder ?? Enumerable.Empty<string>())
206 .Append(Platform.ToString());
207
208 IReadOnlyCollection<AbsolutePath> GlobIni(AbsolutePath folder)
209 {
210 return folder.GlobFiles($"{shortName}.ini", $"*{shortName}.ini");
211 }
212
213 void MergeInis(AbsolutePath folder, ConfigIni result)
214 {
215 if (folder.DirectoryExists())
216 foreach (var iniFile in GlobIni(folder))
217 {
218 var currIni = ConfigIni.Parse(File.ReadAllText(iniFile));
219 if (currIni != null)
220 result.Merge(currIni);
221 }
222 }
223
224 void GatherInis(AbsolutePath configFolder, ConfigIni result)
225 {
226 MergeInis(configFolder, resultIni);
227 foreach (var folder in extraConfigSubfolder.Select(s => configFolder / s))
228 {
229 if (folder.DirectoryExists())
230 MergeInis(folder, resultIni);
231 }
232 }
233
234 if (lowestLevel <= IniHierarchyLevel.Base && highestLevel >= IniHierarchyLevel.Base)
235 {
236 var configFolder = UnrealEnginePath / "Engine" / "Config";
237 var baseIni = ConfigIni.Parse(File.ReadAllText(configFolder / "Base.ini"));
238 if (baseIni != null)
239 resultIni.Merge(baseIni);
240
241 GatherInis(configFolder, resultIni);
242 }
243
244 if (lowestLevel <= IniHierarchyLevel.Default && highestLevel >= IniHierarchyLevel.Default)
245 {
246 var configFolder = ProjectFolder / "Config";
247 GatherInis(configFolder, resultIni);
248 }
249 if (lowestLevel <= IniHierarchyLevel.Default && highestLevel >= IniHierarchyLevel.Default && considerPlugins)
250 {
251 foreach (var pluginConfigFolder in (ProjectFolder / "Plugins").GlobDirectories("**/Config"))
252 {
253 GatherInis(pluginConfigFolder, resultIni);
254 }
255 }
256 if (lowestLevel <= IniHierarchyLevel.Saved && highestLevel >= IniHierarchyLevel.Saved)
257 {
258 var configFolder = ProjectFolder / "Saved" / "Config";
259 GatherInis(configFolder, resultIni);
260 }
261
262 return resultIni;
263 }
264 }
265}
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
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 bool IsPerforce
Does this project reside in a Perforce workspace?
virtual AbsolutePath GetOutput()
Get an output folder where the targets should store their artifacts. Override this function in your m...
EngineVersion GetEngineVersionFromProject()
Utility function to get the proper Engine version associated with current project....
virtual ? string UnrealVersion
Most targets read the desired Unreal version from the project file.
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...
T Self< T >()
Shortcut to casting this to another class.
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 GetDefaultPlatform()
Get the current development platform 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
TargetType
The type of target.