using System.IO;
using System.Linq;
using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
using System.Reflection;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
SortedDictionary<string, Assembly>? _assemblies;
Resolver? _resolver;
+ private class WasmAppConfig
+ {
+ [JsonPropertyName("assembly_root")]
+ public string AssemblyRoot { get; set; } = "managed";
+ [JsonPropertyName("enable_debugging")]
+ public int EnableDebugging { get; set; } = 0;
+ [JsonPropertyName("assets")]
+ public List<object> Assets { get; } = new List<object>();
+ [JsonPropertyName("remote_sources")]
+ public List<string> RemoteSources { get; set; } = new List<string>();
+ }
+
+ private class AssetEntry {
+ protected AssetEntry (string name, string behavior)
+ {
+ Name = name;
+ Behavior = behavior;
+ }
+ [JsonPropertyName("behavior")]
+ public string Behavior { get; init; }
+ [JsonPropertyName("name")]
+ public string Name { get; init; }
+ }
+
+ private class AssemblyEntry : AssetEntry
+ {
+ public AssemblyEntry(string name) : base(name, "assembly") {}
+ }
+
+ private class VfsEntry : AssetEntry {
+ public VfsEntry(string name) : base(name, "vfs") {}
+ [JsonPropertyName("virtual_path")]
+ public string? VirtualPath { get; set; }
+ }
+
+ private class IcuData : AssetEntry {
+ public IcuData(string name = "icudt.dat") : base(name, "icu") {}
+ [JsonPropertyName("load_remote")]
+ public bool LoadRemote { get; set; }
+ }
+
public override bool Execute ()
{
if (!File.Exists(MainAssembly))
_resolver = new Resolver(paths);
var mlc = new MetadataLoadContext(_resolver, "System.Private.CoreLib");
- var mainAssembly = mlc.LoadFromAssemblyPath (MainAssembly);
+ var mainAssembly = mlc.LoadFromAssemblyPath(MainAssembly);
Add(mlc, mainAssembly);
if (ExtraAssemblies != null)
}
}
+ var config = new WasmAppConfig ();
+
// Create app
Directory.CreateDirectory(AppDir!);
- Directory.CreateDirectory(Path.Join(AppDir, "managed"));
+ Directory.CreateDirectory(Path.Join(AppDir, config.AssemblyRoot));
foreach (var assembly in _assemblies!.Values)
- File.Copy(assembly.Location, Path.Join(AppDir, "managed", Path.GetFileName(assembly.Location)), true);
+ File.Copy(assembly.Location, Path.Join(AppDir, config.AssemblyRoot, Path.GetFileName(assembly.Location)), true);
foreach (var f in new string[] { "dotnet.wasm", "dotnet.js", "dotnet.timezones.blat", "icudt.dat" })
File.Copy(Path.Join (MicrosoftNetCoreAppRuntimePackDir, "native", f), Path.Join(AppDir, f), true);
File.Copy(MainJS!, Path.Join(AppDir, "runtime.js"), true);
- using (var sw = File.CreateText(Path.Join(AppDir, "mono-config.js")))
- {
- sw.WriteLine("config = {");
- sw.WriteLine("\tassembly_root: \"managed\",");
- sw.WriteLine("\tenable_debugging: 0,");
- sw.WriteLine("\tassets: [");
+ foreach (var assembly in _assemblies.Values)
+ config.Assets.Add(new AssemblyEntry (Path.GetFileName(assembly.Location)));
- foreach (var assembly in _assemblies.Values)
- sw.WriteLine($"\t\t{{ behavior: \"assembly\", name: \"{Path.GetFileName(assembly.Location)}\" }},");
+ if (FilesToIncludeInFileSystem != null)
+ {
+ string supportFilesDir = Path.Join(AppDir, "supportFiles");
+ Directory.CreateDirectory(supportFilesDir);
- if (FilesToIncludeInFileSystem != null)
+ var i = 0;
+ foreach (var item in FilesToIncludeInFileSystem)
{
- string supportFilesDir = Path.Join(AppDir, "supportFiles");
- Directory.CreateDirectory(supportFilesDir);
-
- var i = 0;
- foreach (var item in FilesToIncludeInFileSystem)
+ string? targetPath = item.GetMetadata("TargetPath");
+ if (string.IsNullOrEmpty(targetPath))
{
- string? targetPath = item.GetMetadata("TargetPath");
- if (string.IsNullOrEmpty(targetPath))
- {
- targetPath = Path.GetFileName(item.ItemSpec);
- }
-
- // We normalize paths from `\` to `/` as MSBuild items could use `\`.
- targetPath = targetPath.Replace('\\', '/');
+ targetPath = Path.GetFileName(item.ItemSpec);
+ }
- var generatedFileName = $"{i++}_{Path.GetFileName(item.ItemSpec)}";
+ // We normalize paths from `\` to `/` as MSBuild items could use `\`.
+ targetPath = targetPath.Replace('\\', '/');
- File.Copy(item.ItemSpec, Path.Join(supportFilesDir, generatedFileName), true);
+ var generatedFileName = $"{i++}_{Path.GetFileName(item.ItemSpec)}";
- var actualItemName = "supportFiles/" + generatedFileName;
+ File.Copy(item.ItemSpec, Path.Join(supportFilesDir, generatedFileName), true);
- sw.WriteLine("\t\t{");
- sw.WriteLine("\t\t\tbehavior: \"vfs\",");
- sw.WriteLine($"\t\t\tname: \"{actualItemName}\",");
- sw.WriteLine($"\t\t\tvirtual_path: \"{targetPath}\",");
- sw.WriteLine("\t\t},");
- }
+ var asset = new VfsEntry ($"supportFiles/{generatedFileName}") {
+ VirtualPath = targetPath
+ };
+ config.Assets.Add(asset);
}
+ }
- var enableRemote = (RemoteSources != null) && (RemoteSources!.Length > 0);
- var sEnableRemote = enableRemote ? "true" : "false";
-
- sw.WriteLine($"\t\t{{ behavior: \"icu\", name: \"icudt.dat\", load_remote: {sEnableRemote} }},");
- sw.WriteLine($"\t\t{{ behavior: \"vfs\", name: \"dotnet.timezones.blat\", virtual_path: \"/usr/share/zoneinfo/\" }}");
- sw.WriteLine ("\t],");
+ config.Assets.Add(new IcuData { LoadRemote = RemoteSources?.Length > 0 });
+ config.Assets.Add(new VfsEntry ("dotnet.timezones.blat") { VirtualPath = "/usr/share/zoneinfo/"});
- if (enableRemote) {
- sw.WriteLine("\tremote_sources: [");
- foreach (var source in RemoteSources!)
- sw.WriteLine("\t\t\"" + source.ItemSpec + "\", ");
- sw.WriteLine ("\t],");
- }
+ if (RemoteSources?.Length > 0) {
+ foreach (var source in RemoteSources)
+ if (source != null && source.ItemSpec != null)
+ config.RemoteSources.Add(source.ItemSpec);
+ }
- sw.WriteLine ("};");
+ using (var sw = File.CreateText(Path.Join(AppDir, "mono-config.js")))
+ {
+ var json = JsonSerializer.Serialize (config, new JsonSerializerOptions { WriteIndented = true });
+ sw.Write($"config = {json};");
}
using (var sw = File.CreateText(Path.Join(AppDir, "run-v8.sh")))