Nuke.Unreal
Build Unreal apps in Style.
Loading...
Searching...
No Matches
BuildCommon.cs
1using System;
2using Nuke.Common.IO;
3using System.Runtime.CompilerServices;
4using Nuke.Common;
5using System.Collections;
6using System.Collections.Generic;
7using Nuke.Common.Utilities.Collections;
8using System.Linq;
9using Nuke.Common.Utilities;
10using System.IO;
11using System.Reflection;
12using Serilog;
13using System.Text.RegularExpressions;
14using Nuke.Cola;
15using System.Runtime.InteropServices;
16
17namespace Nuke.Unreal;
18
19/// <summary>
20/// Extra build related utilities not necessarily associated with Unreal tasks
21/// </summary>
22public static class BuildCommon
23{
24 static BuildCommon()
25 {
26 HttpTasks.DefaultTimeout = TimeSpan.FromMinutes(60);
27 }
28
29 /// <summary>
30 /// Get the contents folder Nuke.Unreal is shipped with. This is usually contained in the local
31 /// nuget installation of Nuke.Unreal, but may vary depending on the circumstances.
32 /// </summary>
33 public static AbsolutePath GetContentsFolder()
34 {
35 var executingAssemblyFolder = (AbsolutePath) Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
36
37 if (Directory.Exists(executingAssemblyFolder / "Templates"))
38 {
39 return executingAssemblyFolder;
40 }
41
42 var nukeUnrealAssemblyFolder = (AbsolutePath) Path.GetDirectoryName(typeof(BuildCommon).Assembly.Location);
43 if (Directory.Exists(nukeUnrealAssemblyFolder / "Templates"))
44 {
45 return nukeUnrealAssemblyFolder;
46 }
47
48 var contentFolder = nukeUnrealAssemblyFolder
49 .DescendantsAndSelf(p => p.Parent, d => Path.GetPathRoot(d) != d)
50 .FirstOrDefault(p => Directory.Exists(p / "content"));
51
52 Assert.NotNullOrEmpty(contentFolder, "Couldn't find contents folder of Nuke.Unreal.");
53 return contentFolder!;
54 }
55
56 /// <summary>
57 /// Returns false on known folders which are intermediate results of Engine operations,
58 /// therefore its contents must not be modified by the user.
59 /// </summary>
60 /// <param name="path"></param>
61 /// <returns></returns>
62 public static bool IsProjectFolder(this AbsolutePath path)
63 => !path.Name.StartsWith('.')
64 && !path.Name.StartsWith("Nuke.")
65 && path.Name != "Intermediate"
66 && path.Name != "Binaries"
67 && path.Name != "ThirdParty"
68 && path.Name != "Saved";
69
70 /// <summary>
71 /// Gives a recursive folder tree filtering out known intermediate folders
72 /// </summary>
73 /// <param name="origin"></param>
74 /// <param name="filter">Extra filtering function</param>
75 public static IEnumerable<AbsolutePath> SubTreeProject(this AbsolutePath origin, Func<AbsolutePath, bool>? filter = null) =>
76 origin.SubTree(sd => filter?.Invoke(sd) ?? true && sd.IsProjectFolder());
77
78 /// <summary>
79 /// Look for something in subtree of a folder or in parent folders based on a predicate.
80 /// </summary>
81 public static bool LookAroundFor(Func<string, bool> predicate, out AbsolutePath? result) =>
82 PathExtensions.LookAroundFor(predicate, out result, IsProjectFolder);
83
84 /// <summary>
85 /// Get the owning parent folder of an arbitrarily deep subfolder based on wildcard filtering of
86 /// files in parent folder. The closest match will be returned.
87 /// </summary>
88 /// <param name="path"></param>
89 /// <param name="ownerPattern"></param>
90 /// <returns>Owning parent folder or null if there's no match.</returns>
91 public static AbsolutePath? GetOwner(this AbsolutePath path, string ownerPattern)
92 => path
93 .DescendantsAndSelf(d => d.Parent, d => Path.GetPathRoot(d) != d)
94 .SelectMany(p => p.GlobFiles(ownerPattern))
95 .FirstOrDefault();
96
97 /// <summary>
98 /// Get the Unreal plugin owning the given subfolder.
99 /// </summary>
100 public static AbsolutePath? GetOwningPlugin(this AbsolutePath path)
101 => path
102 .DescendantsAndSelf(d => d.Parent, d => Path.GetPathRoot(d) != d)
103 .SelectMany(p => p.GlobFiles("*.uplugin"))
104 .FirstOrDefault();
105
106 /// <summary>
107 /// Get the Unreal project owning the given subfolder.
108 /// </summary>
109 public static AbsolutePath? GetOwningProject(this AbsolutePath path)
110 => path
111 .DescendantsAndSelf(d => d.Parent, d => Path.GetPathRoot(d) != d)
112 .SelectMany(p => p.GlobFiles("*.uproject"))
113 .FirstOrDefault();
114
115 /// <summary>
116 /// Get the Unreal module owning the given subfolder.
117 /// </summary>
118 public static AbsolutePath? GetOwningModule(this AbsolutePath path)
119 => path
120 .DescendantsAndSelf(d => d.Parent, d => Path.GetPathRoot(d) != d)
121 .SelectMany(p => p.GlobFiles("*.Build.cs"))
122 .FirstOrDefault();
123
124 /// <summary>
125 /// Create a short path symlink for input path to work around the 260 character path length
126 /// limitation cursing Windows from the 80's to present day.
127 /// </summary>
128 public static AbsolutePath Shorten(this AbsolutePath longPath, bool allPlatforms = false)
129 {
130 var result = longPath;
131 if (allPlatforms || RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
132 {
133 Log.Information("Creating short symlink on {0} for {1}", longPath.GetRoot(), longPath);
134 result = longPath.GetRoot() / Guid.NewGuid().ToString("N")[..16];
135 result.Links(longPath);
136 }
137 return result;
138 }
139}
Extra build related utilities not necessarily associated with Unreal tasks.
static ? AbsolutePath GetOwningPlugin(this AbsolutePath path)
Get the Unreal plugin owning the given subfolder.
static bool LookAroundFor(Func< string, bool > predicate, out AbsolutePath? result)
Look for something in subtree of a folder or in parent folders based on a predicate.
static IEnumerable< AbsolutePath > SubTreeProject(this AbsolutePath origin, Func< AbsolutePath, bool >? filter=null)
Gives a recursive folder tree filtering out known intermediate folders.
static bool IsProjectFolder(this AbsolutePath path)
Returns false on known folders which are intermediate results of Engine operations,...
static ? AbsolutePath GetOwningModule(this AbsolutePath path)
Get the Unreal module owning the given subfolder.
static ? AbsolutePath GetOwner(this AbsolutePath path, string ownerPattern)
Get the owning parent folder of an arbitrarily deep subfolder based on wildcard filtering of files in...
static ? AbsolutePath GetOwningProject(this AbsolutePath path)
Get the Unreal project owning the given subfolder.
static AbsolutePath GetContentsFolder()
Get the contents folder Nuke.Unreal is shipped with. This is usually contained in the local nuget ins...
static AbsolutePath Shorten(this AbsolutePath longPath, bool allPlatforms=false)
Create a short path symlink for input path to work around the 260 character path length limitation cu...