Nuke.Cola
Loading...
Searching...
No Matches
XRepoPackage.cs
1using System.Dynamic;
2using System.Text.RegularExpressions;
3using Newtonsoft.Json;
4using Newtonsoft.Json.Linq;
5using Nuke.Common;
6using Nuke.Common.IO;
7using Nuke.Common.Tooling;
8using Nuke.Common.Utilities;
9using Nuke.Common.Utilities.Collections;
10
12
13public partial record class XRepoPackagePath(
14 AbsolutePath ParentFolder,
15 string Name,
16 string Version,
17 string Hash
18) {
19
20 [GeneratedRegex(
21 """
22 ^
23 (?<PARENT>.*?[\/\\]packages[\/\\]\w)[\/\\]
24 (?<NAME>.+?)[\/\\]
25 (?<VERSION>.+?)[\/\\]
26 (?<HASH>.+?)(?:[\/\\]|$)
27 """,
28 RegexOptions.CultureInvariant
29 | RegexOptions.IgnoreCase
30 | RegexOptions.IgnorePatternWhitespace
31 )]
32 private static partial Regex PathParserPattern();
33
34 /// <summary>
35 /// Parse an input path to XRepoPackagePath
36 /// </summary>
37 /// <param name="from"></param>
38 /// <returns>An XRepoPackagePath if that could be inferred</returns>
39 public static XRepoPackagePath? Make(AbsolutePath from)
40 {
41 var parsed = from.ToString().Parse(PathParserPattern(), forceNullOnWhitespce: true);
42 var parentFolder = parsed("PARENT");
43 var name = parsed("NAME");
44 var version = parsed("VERSION");
45 var hash = parsed("HASH");
46 if (parentFolder == null || name == null || version == null || hash == null)
47 {
48 return null;
49 }
50
51 return new(parentFolder, name, version, hash);
52 }
53
54 /// <summary>
55 /// Get the root folder of all packages.
56 /// </summary>
57 public AbsolutePath PackagesRoot => ParentFolder.Parent!;
58
59 /// <summary>
60 /// Get the folder of this package
61 /// </summary>
62 public AbsolutePath PackageFolder => ParentFolder / Name / Version / Hash;
63}
64
65/// <summary>
66/// Mirror of package-repo object which may be returned by xrepo fetch.
67/// </summary>
68[JsonObject(MemberSerialization.OptIn)]
69public record class XRepoPackageRepo(
70
71 [JsonProperty(PropertyName = "commit")]
72 string Commit,
73
74 [JsonProperty(PropertyName = "url")]
75 string Url,
76
77 [JsonProperty(PropertyName = "branch")]
78 string Branch,
79
80 [JsonProperty(PropertyName = "name")]
81 string Name
82);
83
84/// <summary>
85/// Mirror of package-artifact object which may be returned by xrepo fetch.
86/// </summary>
87[JsonObject(MemberSerialization.OptIn)]
88public record class XRepoPackageArtifact(
89
90 [JsonProperty(PropertyName = "installdir")]
91 string InstallDir
92);
93
94/// <summary>
95/// Mirror of package object which is returned by xrepo fetch.
96/// </summary>
97[JsonObject(MemberSerialization.OptIn)]
98public record class XRepoPackage(
99
100 [JsonProperty(PropertyName = "version")]
101 string Version,
102
103 [JsonProperty(PropertyName = "license")]
104 string? License = null,
105
106 [JsonProperty(PropertyName = "links")]
107 [JsonConverter(typeof(OneOrManyConverter<string>))]
108 List<string>? Links = null,
109
110 [JsonProperty(PropertyName = "syslinks")]
111 [JsonConverter(typeof(OneOrManyConverter<string>))]
112 List<string>? SysLinks = null,
113
114 [JsonProperty(PropertyName = "static")]
115 bool? Static = false,
116
117 [JsonProperty(PropertyName = "shared")]
118 bool? Shared = false,
119
120 [JsonProperty(PropertyName = "linkdirs")]
121 AbsolutePath[]? LinkDirs = null,
122
123 [JsonProperty(PropertyName = "libfiles")]
124 AbsolutePath[]? LibFiles = null,
125
126 [JsonProperty(PropertyName = "includedirs")]
127 AbsolutePath[]? IncludeDirs = null,
128
129 [JsonProperty(PropertyName = "sysincludedirs")]
130 AbsolutePath[]? SysIncludeDirs = null,
131
132 [JsonProperty(PropertyName = "cxxflags")]
133 string? CxxFlags = null,
134
135 [JsonProperty(PropertyName = "defines")]
136 [JsonConverter(typeof(OneOrManyConverter<string>))]
137 List<string>? Defines = null,
138
139 // These only appear in system program dependencies
140 [JsonProperty(PropertyName = "name")]
141 string? Name = null,
142
143 [JsonProperty(PropertyName = "program")]
144 AbsolutePath? Program = null,
145
146 // These only appear in auto-environment program dependencies
147 [JsonProperty(PropertyName = "arch")]
148 string? Arch = null,
149
150 [JsonProperty(PropertyName = "configs")]
151 Dictionary<string, string>? Configs = null,
152
153 [JsonProperty(PropertyName = "description")]
154 string? Description = null,
155
156 [JsonProperty(PropertyName = "plat")]
157 string? Plat = null,
158
159 [JsonProperty(PropertyName = "envs")]
160 Dictionary<string, object>? Envs = null,
161
162 [JsonProperty(PropertyName = "repo")]
163 XRepoPackageRepo? Repo = null,
164
165 // TODO deps and librarydeps
166
167 [JsonProperty(PropertyName = "pathenvs")]
168 string[]? PathEnvs = null,
169
170 [JsonProperty(PropertyName = "kind")]
171 string? Kind = null,
172
173 [JsonProperty(PropertyName = "artifacts")]
174 XRepoPackageArtifact? Artifacts = null,
175
176 [JsonProperty(PropertyName = "mode")]
177 string? Mode = null
178)
179{
180 /// <summary>
181 /// Get the parsed path of this package. This is only available for libraries
182 /// </summary>
183 /// <returns></returns>
184 public XRepoPackagePath? GetPath()
185 {
186 foreach (var includeDir in IncludeDirs ?? [])
187 {
188 var result = includeDir.InferXRepoPackage();
189 if (result != null)
190 {
191 return result;
192 }
193 }
194
195 return null;
196 }
197
198 /// <summary>
199 /// Since XMake doesn't append the library name directly to package information using `fetch` we will need to
200 /// do some guess-work
201 /// </summary>
202 public string? InferredName => Name ?? GetPath()?.Name;
203
204 public bool IsSystemProgram => Program != null;
205 public bool IsEnvironmentProgram => !IsSystemProgram && (Kind?.EqualsOrdinalIgnoreCase("binary") ?? false);
206 public bool IsProgram => IsSystemProgram || IsEnvironmentProgram;
207 public bool IsLibrary => !IsProgram;
208
209 /// <summary>
210 /// Is this package a header only library
211 /// </summary>
212 public bool IsHeaderOnly => (!IncludeDirs.IsNullOrEmpty() || !SysIncludeDirs.IsNullOrEmpty())
213 && IsLibrary
214 && LinkDirs.IsNullOrEmpty()
215 && LibFiles.IsNullOrEmpty()
216 ;
217
218 public JObject? GetManifest()
219 {
220 var path = GetPath();
221 if (path == null) return null;
222 var manifestJsonPath = path.PackageFolder / "manifest.json";
223 manifestJsonPath.ExistingFile()?.Delete();
224 var tempLuaPath = path.PackageFolder / "convert_manifest.lua";
225 tempLuaPath.WriteAllText(
226 """
227 import("core.base.json")
228 local manifest = io.load("manifest.txt")
229 json.savefile("manifest.json", manifest)
230 """
231 );
232 XMakeTasks.XMake("lua ./convert_manifest.lua", workingDirectory: path.PackageFolder);
233 Assert.FileExists(manifestJsonPath, "XMake didn't generate a json version of the manifest file. It may have logged why.");
234 return manifestJsonPath.ReadJson();
235 }
236}
237
238public static class XRepoPackageExtensions
239{
240 public static XRepoPackagePath? InferXRepoPackage(this AbsolutePath path) => XRepoPackagePath.Make(path);
241
242 /// <summary>
243 /// Get a specific library from a collection of XRepo packages
244 /// </summary>
245 /// <param name="packages"></param>
246 /// <param name="name"></param>
247 /// <returns></returns>
248 public static XRepoPackage? GetLibrary(this IEnumerable<XRepoPackage> packages, string name)
249 => packages.Where(p => p.IsLibrary)
250 .FirstOrDefault(p => p.InferredName.EqualsOrdinalIgnoreCase(name));
251
252 /// <summary>
253 /// Get a specific program from a collection of XRepo packages
254 /// </summary>
255 /// <param name="packages"></param>
256 /// <param name="name"></param>
257 /// <returns></returns>
258 public static XRepoPackage? GetProgram(this IEnumerable<XRepoPackage> packages, string name)
259 => packages.Where(p => p.IsProgram)
260 .FirstOrDefault(p => p.InferredName.EqualsOrdinalIgnoreCase(name));
261
262 /// <summary>
263 /// Parse the Tool output of XRepoTasks.Info into structured data.
264 /// </summary>
265 public static List<XRepoPackage>? ParseXRepoFetch(this IEnumerable<Output> output)
266 {
267 foreach (var line in output)
268 {
269 if (line.Text.StartsWith("[{") && line.Text.EndsWith("]"))
270 {
271 return line.Text.GetJson<List<XRepoPackage>>();
272 }
273 }
274
275 return null;
276 }
277}
A JSON converter for property which may have a single value or an array of values when de-serializing...
XMake is a versatile build tool for many languages https://xmake.io/#/?id=supported-languages scripta...
Definition XMakeTasks.cs:15
static ToolEx XMake
Get XMake. It throws an exception if setup has failed.
Definition XMakeTasks.cs:85
static ? XRepoPackage GetProgram(this IEnumerable< XRepoPackage > packages, string name)
Get a specific program from a collection of XRepo packages.
static ? XRepoPackage GetLibrary(this IEnumerable< XRepoPackage > packages, string name)
Get a specific library from a collection of XRepo packages.
static ? List< XRepoPackage > ParseXRepoFetch(this IEnumerable< Output > output)
Parse the Tool output of XRepoTasks.Info into structured data.
record class XRepoPackage([JsonProperty(PropertyName="version")] string Version, [JsonProperty(PropertyName="license")] string? License=null, [JsonProperty(PropertyName="links")][JsonConverter(typeof(OneOrManyConverter< string >))] List< string >? Links=null, [JsonProperty(PropertyName="syslinks")][JsonConverter(typeof(OneOrManyConverter< string >))] List< string >? SysLinks=null, [JsonProperty(PropertyName="static")] bool? Static=false, [JsonProperty(PropertyName="shared")] bool? Shared=false, [JsonProperty(PropertyName="linkdirs")] AbsolutePath[]? LinkDirs=null, [JsonProperty(PropertyName="libfiles")] AbsolutePath[]? LibFiles=null, [JsonProperty(PropertyName="includedirs")] AbsolutePath[]? IncludeDirs=null, [JsonProperty(PropertyName="sysincludedirs")] AbsolutePath[]? SysIncludeDirs=null, [JsonProperty(PropertyName="cxxflags")] string? CxxFlags=null, [JsonProperty(PropertyName="defines")][JsonConverter(typeof(OneOrManyConverter< string >))] List< string >? Defines=null, [JsonProperty(PropertyName="name")] string? Name=null, [JsonProperty(PropertyName="program")] AbsolutePath? Program=null, [JsonProperty(PropertyName="arch")] string? Arch=null, [JsonProperty(PropertyName="configs")] Dictionary< string, string >? Configs=null, [JsonProperty(PropertyName="description")] string? Description=null, [JsonProperty(PropertyName="plat")] string? Plat=null, [JsonProperty(PropertyName="envs")] Dictionary< string, object >? Envs=null, [JsonProperty(PropertyName="repo")] XRepoPackageRepo? Repo=null, [JsonProperty(PropertyName="pathenvs")] string[]? PathEnvs=null, [JsonProperty(PropertyName="kind")] string? Kind=null, [JsonProperty(PropertyName="artifacts")] XRepoPackageArtifact? Artifacts=null, [JsonProperty(PropertyName="mode")] string? Mode=null)
Mirror of package object which is returned by xrepo fetch.
record class XRepoPackageArtifact([JsonProperty(PropertyName="installdir")] string InstallDir)
Mirror of package-artifact object which may be returned by xrepo fetch.
record class XRepoPackageRepo([JsonProperty(PropertyName="commit")] string Commit, [JsonProperty(PropertyName="url")] string Url, [JsonProperty(PropertyName="branch")] string Branch, [JsonProperty(PropertyName="name")] string Name)
Mirror of package-repo object which may be returned by xrepo fetch.