diff --git a/.vsts-ci-macos.yml b/.vsts-ci-macos.yml index 66010f3b4..b3a485cf4 100644 --- a/.vsts-ci-macos.yml +++ b/.vsts-ci-macos.yml @@ -23,11 +23,7 @@ jobs: version: 8.0.100 includePreviewVersions: true - - bash: | - cd $(Agent.WorkFolder) - wget https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-mac.zip - unzip ninja-mac.zip -d ninja-mac - + - bash: brew install ninja displayName: 'Install Ninja' # - bash: | @@ -56,6 +52,21 @@ jobs: dotnet build -m:1 /bl:$(build.artifactstagingdirectory)/SampleNet6-mac.binlog displayName: Build NetCore-Wasm Sample + # Static linking test (net5) without the linker + - pwsh: | + cd $(build.sourcesdirectory)/src/Uno.Wasm.StaticLinking.Interpreter + dotnet clean -c Release /p:DISABLE_CLIHOST_NET6=true + dotnet publish -c Release /m:1 /p:DISABLE_CLIHOST_NET6=true /p:WasmShellEmccLinkOptimization=false /p:WasmShellILLinkerEnabled=false /bl:$(build.artifactstagingdirectory)/SampleNet5-nolinker-macos.binlog + displayName: Build StaticLinking.Interpreter Sample (net5 without linker) + + - bash: | + $(build.sourcesdirectory)/build/scripts/run-tests.sh \ + "$(build.sourcesdirectory)/src/Uno.Wasm.StaticLinking.Interpreter/bin/Release/net5.0/dist" \ + "$(build.sourcesdirectory)/src/Uno.Wasm.StaticLinking.Aot.UITests" "http://localhost:8000/" + displayName: StaticLinking Interpreter Test + env: + BUILD_SOURCESDIRECTORY: "$(build.sourcesdirectory)" + - task: PublishBuildArtifacts@1 condition: always() inputs: diff --git a/src/Uno.Wasm.Bootstrap/ShellTask.cs b/src/Uno.Wasm.Bootstrap/ShellTask.cs index d8a87b27e..b7807b2a3 100644 --- a/src/Uno.Wasm.Bootstrap/ShellTask.cs +++ b/src/Uno.Wasm.Bootstrap/ShellTask.cs @@ -810,7 +810,15 @@ private void RunPackager() + (EnableSimd ? "-simd" : "") + " " + (EnableJiterpreter ? "-jiterpreter" : "") + " " + (PrintAOTSkippedMethods ? "-print-skipped-aot-methods" : "") + " " - + (string.IsNullOrWhiteSpace(RuntimeOptions) ? "" : $"--runtime-options \"{RuntimeOptions}\" "); + + (string.IsNullOrWhiteSpace(RuntimeOptions) ? "" : $"--runtime-options \"{RuntimeOptions}\" ") + + // Disable icalls generation on macOS, as it's using the cross-compiler that is not available + + (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "--no-link-icalls" : ""); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && IsRuntimeAOT()) + { + throw new Exception("Building with AOT is not supported on macOS"); + } var pthreadPoolSizeParam = $"--pthread-pool-size={PThreadsPoolSize}"; diff --git a/src/Uno.Wasm.Packager/packager.cs b/src/Uno.Wasm.Packager/packager.cs index cd1229a1c..26a61ffb8 100644 --- a/src/Uno.Wasm.Packager/packager.cs +++ b/src/Uno.Wasm.Packager/packager.cs @@ -6,6 +6,7 @@ using Mono.Options; using Mono.Cecil.Cil; using System.Diagnostics; +using System.Runtime.InteropServices; // // Google V8 style options: @@ -1845,9 +1846,13 @@ int Run (string[] args) { ofiles += $" {a.o_path}"; } - ninja.WriteLine ("build $builddir/icall-table.json: gen-runtime-icall-table"); + if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + ninja.WriteLine("build $builddir/icall-table.json: gen-runtime-icall-table"); + } if (link_icalls) { + string icall_assemblies = ""; foreach (var a in assemblies.Where(a => a.culture is null)) { if (a.name == "mscorlib" || a.name == "System") @@ -1856,13 +1861,20 @@ int Run (string[] args) { ninja.WriteLine ($"build $builddir/icall-table.h: gen-icall-table {icall_assemblies}"); ninja.WriteLine ($" runtime_table=$builddir/icall-table.json"); } + else + { + // Fake a command so that __static_icalls__ gets to the tuner + ninja.WriteLine ("build __static_icalls__: mkdir"); + } if (gen_pinvoke) { string pinvoke_assemblies = ""; foreach (var a in assemblies.Where(a => a.culture is null)) pinvoke_assemblies += $"{a.linkout_path} "; ninja.WriteLine ($"build $builddir/pinvoke-table.h: cpifdiff $builddir/pinvoke-table.h.tmp"); - ninja.WriteLine ($"build $builddir/pinvoke-table.h.tmp: gen-pinvoke-table $builddir/icall-table.json {pinvoke_assemblies}"); + + var icallTable = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "__static_icalls__" : "$builddir/icall-table.json"; + ninja.WriteLine ($"build $builddir/pinvoke-table.h.tmp: gen-pinvoke-table {icallTable} {pinvoke_assemblies}"); if (is_netcore) { diff --git a/src/Uno.Wasm.StaticLinking.Aot.UITests/app.js b/src/Uno.Wasm.StaticLinking.Aot.UITests/app.js index 91fcb72f0..ee3b5f300 100644 --- a/src/Uno.Wasm.StaticLinking.Aot.UITests/app.js +++ b/src/Uno.Wasm.StaticLinking.Aot.UITests/app.js @@ -43,7 +43,8 @@ const path = require("path"); else { console.log(`Results: ${value}`); } - const expected = "InterpreterAndAOT;42;42.30;42.7;e42;True;true;True;1.2;1.4;3.1;0;42;requireJs:true;jsInterop:Invoked;gl:true;functionsExportsAvailable:true;sat:True;"; + let expected = process.platform === 'darwin' ? "Interpreter;" : "InterpreterAndAOT;"; + expected += "42;42.30;42.7;e42;True;true;True;1.2;1.4;3.1;0;42;requireJs:true;jsInterop:Invoked;gl:true;functionsExportsAvailable:true;sat:True;"; if (value !== expected) { console.log(`Invalid results got ${value}, expected ${expected}`); process.exit(1); diff --git a/src/Uno.Wasm.StaticLinking.Aot.UITests/app.ts b/src/Uno.Wasm.StaticLinking.Aot.UITests/app.ts index 3c4a49e8b..9ed9f5180 100644 --- a/src/Uno.Wasm.StaticLinking.Aot.UITests/app.ts +++ b/src/Uno.Wasm.StaticLinking.Aot.UITests/app.ts @@ -42,7 +42,8 @@ const path = require("path"); console.log(`Results: ${value}`); } - const expected = "InterpreterAndAOT;42;42.30;42.7;e42;True;true;True;1.2;1.4;3.1;0;42;requireJs:true;jsInterop:Invoked;gl:true;functionsExportsAvailable:true;sat:True;"; + let expected = process.platform === 'darwin' ? "Interpreter;" : "InterpreterAndAOT;"; + expected += "42;42.30;42.7;e42;True;true;True;1.2;1.4;3.1;0;42;requireJs:true;jsInterop:Invoked;gl:true;functionsExportsAvailable:true;sat:True;"; if (value !== expected) { console.log(`Invalid results got ${value}, expected ${expected}`); diff --git a/src/Uno.Wasm.Tuner/IcallTableGenerator.net5.cs b/src/Uno.Wasm.Tuner/IcallTableGenerator.net5.cs index 785a33863..072a1b9c1 100644 --- a/src/Uno.Wasm.Tuner/IcallTableGenerator.net5.cs +++ b/src/Uno.Wasm.Tuner/IcallTableGenerator.net5.cs @@ -33,6 +33,39 @@ internal sealed class IcallTableGenerator private TaskLoggingHelper Log { get; set; } private readonly Func _fixupSymbolName; + /// + /// This table is an extract of net8's icalls table, in order to avoid + /// having to compute it on macOS, which cannot run mono-aot-cross on that platform. + /// + string[] _staticSignatures = new[] { + "III", + "IIIIIIIII", + "IIIIIIIIII", + "IIIIIII", + "IIIIII", + "IIII", + "VIIIIIII", + "VIIIIIIII", + "VIIIII", + "II", + "VIII", + "VII", + "VIIII", + "IIIII", + "I", + "VIIL", + "L", + "VI", + "VIIIIII", + "DD", + "DDD", + "DDI", + "LILL", + "LIL", + "VL", + "V" + }; + // // Given the runtime generated icall table, and a set of assemblies, generate // a smaller linked icall table mapping tokens to C function names @@ -43,8 +76,28 @@ public IcallTableGenerator(string? runtimeIcallTableFile, Func f { Log = log; _fixupSymbolName = fixupSymbolName; - if (runtimeIcallTableFile != null) + if (runtimeIcallTableFile != null && !runtimeIcallTableFile.Equals("__static_icalls__")) + { ReadTable(runtimeIcallTableFile); + + // validate that the _signatures are in the _staticSignatures table + foreach (var sig in _signatures) + { + if (!_staticSignatures.Contains(sig)) + { + throw new Exception($"Icall signature '{sig}' is not in the static icall signatures table"); + } + } + } + else + { + Log.LogMessage(MessageImportance.Low, $"Using static signatures"); + + foreach (var sig in _staticSignatures) + { + _signatures.Add(sig); + } + } } public void ScanAssembly(Assembly asm) @@ -74,6 +127,8 @@ public IEnumerable Generate(string? outputPath) } } + Log.LogMessage(MessageImportance.Low, $"Icalls signatures: " + string.Join(",", _signatures)); + return _signatures; }