Nuke.Unreal
Build Unreal apps in Style.
Loading...
Searching...
No Matches
XRepoLibrary.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text.RegularExpressions;
5using System.Threading.Tasks;
6using Nuke.Cola;
7using Nuke.Cola.Tooling;
8using Nuke.Cola.Tooling.XMake;
9using Nuke.Common;
10using Nuke.Common.IO;
11using Nuke.Common.Utilities;
12using Nuke.Common.Utilities.Collections;
14using Serilog;
15using UPlugin = Nuke.Unreal.Plugins.UnrealPlugin;
16
18
19/// <summary>
20/// Utility classes for working with XRepo (or XMake) packages
21/// </summary>
22public static partial class XRepoLibrary
23{
24 [GeneratedRegex(
25 """
26 ^
27 (?<SPEC>
28 (?:(?<PROVIDER>\w+)\:\:)?
29 (?<NAME>[\w\-\.]+)
30 (?:\[
31 (?<FEATURES>[\w\-,]+)
32 \])?
33 (?:[\s\/-]
34 (?<VERSION>[\w\-\.#]+)
35 )?
36 )
37 (?:\s(?<OPTIONS>[\w=,']+))?
38 $
39 """,
40 RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace
41 )]
42 private static partial Regex SpecRegex();
43
44 /// <summary>
45 /// Parses an input library spec string as a record
46 /// </summary>
47 public static LibrarySpec ParseSpec(string spec)
48 {
49 var matches = spec.Parse(SpecRegex(), forceNullOnWhitespce: true);
50 return new(
51 matches("SPEC")!,
52 matches("NAME")!,
53 matches("VERSION"),
54 matches("PROVIDER"),
55 matches("OPTIONS"),
56 matches("FEATURES")
57 );
58 }
59
60 internal static IEnumerable<XRepoLibraryRecord> InstallXRepoLibrary(IUnrealBuild build, UnrealPlatform platform, LibrarySpec spec, string options, AbsolutePath targetPath, bool debug, string runtime = "MD")
61 {
62 var libraryFiles = targetPath / "LibraryFiles";
63 if (platform == UnrealPlatform.Win64)
64 {
65 options = options.AppendNonEmpty(",") + $"runtimes='{runtime}'";
66 }
67 var xrepoPlatArch = platform.GetXRepoPlatformArch();
68
69 var sdk = platform.GetSdk();
70 if (sdk != null)
71 {
72 Assert.True(sdk.IsValid(build), $"Attempting to use a platform which is not set up for cross compiling ({Unreal.GetHostPlatform()} -> {platform})");
73 sdk.Setup(build).Wait();
74 }
75
76 var sdkXMakeData = sdk?.GetXMakeData(build);
77
78 var extraArgs = ArgumentStringHandlerEx.Render(
79 $"""
80 -p {sdkXMakeData?.Platform ?? xrepoPlatArch.Platform.ToString()}
81 -a {xrepoPlatArch.Arch.ToCorrectString()}
82 -m {(debug ? "debug" : "release")}
83 {sdkXMakeData?.Arguments ?? ""}
84 """
85 );
86 XRepoTasks.Install(spec.Spec, options, extraArgs)
87 .When(sdkXMakeData?.ToolSetup != null, sdkXMakeData?.ToolSetup)
88 ();
89
90 string[] HandlePaths(IEnumerable<AbsolutePath>? paths, AbsolutePath dstDir)
91 {
92 if (paths == null) return [];
93 return paths
94 .Select(i =>
95 {
96 var dstPath = dstDir / i.Name;
97 if (i.FileExists() || i.DirectoryExists())
98 i.Copy(dstPath, ExistsPolicy.MergeAndOverwrite);
99 else
100 {
101 Log.Warning("A library is referring to a non-existing file or folder: {0}", i);
102 return "";
103 }
104 return dstPath.Name;
105 })
106 .Where(p => !string.IsNullOrWhiteSpace(p))
107 .ToArray()
108 ;
109 }
110
111 return XRepoTasks.Fetch(spec.Spec, options, extraArgs)
112 .When(sdkXMakeData?.ToolSetup != null, sdkXMakeData?.ToolSetup)
113 ()!
114 .ParseXRepoFetch().NotNull("Couldn't parse XRepo package from fetch output")!
115 .Where(i => i.IsLibrary)
116 .Select(i =>
117 {
118 Log.Information("Handling library (dependency) {0} version {1}", i.InferredName!, i.Version);
119 var manifest = i.GetManifest().NotNull("Libraries must have a manifest.txt file")!;
120 return new XRepoLibraryRecord(
121 Spec: new LibrarySpec(
122 i.InferredName! + " " + i.Version!,
123 i.InferredName!,
124 i.Version
125 ),
126 Options: manifest["configs"]?.ToString() ?? "",
127 Description: manifest["description"]?.ToString(),
128 IncludePaths: HandlePaths(i.IncludeDirs, libraryFiles / i.InferredName / "Includes"),
129 SysIncludePaths: HandlePaths(i.SysIncludeDirs, libraryFiles / i.InferredName / "SysIncludes"),
130 LibFiles: HandlePaths(i.LibFiles,
131 libraryFiles / i.InferredName / "Libs" / platform / (debug ? "Debug" : "Release")),
132 Libs: i.Links
133 ?.Select(l => platform.IsWindows && !l.EndsWith(".lib") ? l + ".lib" : l)
134 ?? [],
135 SysLibs: i.SysLinks
136 ?.Select(l => platform.IsWindows && !l.EndsWith(".lib") ? l + ".lib" : l)
137 ?? [],
138 Defines: i.Defines ?? []
139 );
140 })
141 .ToArray();
142 }
143
144 /// <summary>
145 /// Prepare a third-party library from an XRepo library spec for Unreal engine's consumption. Each platforms
146 /// will be considered which is listed under SupportedTargetPlatforms of the owning UPlugin. If it's empty
147 /// only consider the host platform.
148 /// </summary>
149 /// <param name="build">The build context</param>
150 /// <param name="specIn">
151 /// The library spec specified here (without the options) https://mcro.de/Nuke.Unreal/d2/d84/CppLibraries.html
152 /// </param>
153 /// <param name="options">Comma separated '=' delimited key-value pairs. Space is not allowed around commas</param>
154 /// <param name="targetPath">Where library files should be organized</param>
155 /// <param name="supportedPlatforms">
156 /// Optionally limit the platforms considered for this library, if it shouldn't be compiled with all what's
157 /// listed in its UPlugin.
158 /// </param>
159 /// <param name="suffix">Optional addition to the name of library name exposed to Unreal</param>
160 /// <param name="releaseRuntime">Windows CRT linkage for release versions (default is MD)</param>
161 /// <param name="debugRuntime">Windows CRT linkage for debug versions (default is MD)</param>
162 public static void InstallXRepoLibrary(this IUnrealBuild build, string specIn, string options, AbsolutePath targetPath, List<UnrealPlatform>? supportedPlatforms = null, string? suffix = null, string releaseRuntime = "MD", string debugRuntime = "MD")
163 {
164 Log.Information("Installing library {0} via xrepo", specIn);
165 var spec = ParseSpec(specIn) with { Options = options };
166 Log.Information(" Name: {0}", spec.Name);
167 Log.Information(" Version: {0}", spec.Version);
168 Log.Information(" Provider: {0}", spec.Provider ?? "xrepo");
169 Log.Information(" Options: {0}", spec.Options);
170 Log.Information(" Features: {0}", spec.Features);
171
172 var platforms = UPlugin.Get(targetPath).Descriptor.SupportedTargetPlatforms;
173 if (platforms == null || platforms.IsEmpty())
174 {
175 platforms = [Unreal.GetHostPlatform()];
176 }
177
178 foreach (var platform in platforms)
179 {
180 if (!supportedPlatforms.IsNullOrEmpty() && supportedPlatforms!.All(p => p != platform))
181 {
182 Log.Information("{0} platform has been skipped", platform);
183 continue;
184 }
185
186 Log.Information("Installing debug build for {0}", platform);
187 var debugLibs = InstallXRepoLibrary(build, platform, spec, options, targetPath, true, debugRuntime);
188
189 Log.Information("Installing release build for {0}", platform);
190 Log.Information(" (metadata will be used from release build)");
191 var releaseLibs = InstallXRepoLibrary(build, platform, spec, options, targetPath, false, releaseRuntime);
192
193 Log.Information("Generating partial module rule class for {0}", platform);
194 new XRepoLibraryModuleGenerator().Generate(
195 ((UnrealBuild) build).TemplatesPath,
196 targetPath,
197 spec,
198 platform,
199 releaseLibs,
200 suffix
201 );
202 }
203 }
204}
Utility classes for working with XRepo (or XMake) packages.
static void InstallXRepoLibrary(this IUnrealBuild build, string specIn, string options, AbsolutePath targetPath, List< UnrealPlatform >? supportedPlatforms=null, string? suffix=null, string releaseRuntime="MD", string debugRuntime="MD")
Prepare a third-party library from an XRepo library spec for Unreal engine's consumption....
static LibrarySpec ParseSpec(string spec)
Parses an input library spec string as a record.
A class encapsulating information and tasks around one Unreal plugin.
The main build class Unreal projects using Nuke.Unreal should inherit from. This class contains all b...
High level representation of common platforms supported by Unreal Engine (NDA ones excluded) and extr...
static readonly UnrealPlatform Win64
Any platform name containing 'Windows' is also mapped to this platform.
A collection of utilities around basic functions regarding the environment of the Engine we're workin...
Definition Unreal.cs:24
static UnrealPlatform GetHostPlatform()
Get the current development platform Nuke.Unreal is ran on.
Base interface for build components which require an UnrealBuild main class.