From f179b7634370fc9181610624cc095370ec53e072 Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Sat, 4 Dec 2021 06:48:02 +0000 Subject: [PATCH] [wasm] Build improvements, and fixes (#61581) Includes: - Better error logging, and handling - Add @(NativeFileReference) to up-to-date check items for VS - Add `WasmBuild.sln` - Better fix up of symbol names for pinvokes, and callbacks, based on @lambdageek's suggestion in https://github.com/dotnet/runtime/pull/60814#discussion_r736903990 Fixes dotnet#60862 --- eng/testing/tests.wasm.targets | 1 + src/libraries/tests.proj | 14 ++++- src/mono/wasm/build/WasmApp.Native.targets | 4 ++ src/mono/wasm/build/WasmApp.targets | 2 +- src/mono/wasm/sln/WasmBuild.sln | 73 ++++++++++++++++++++++ src/mono/wasm/wasm.proj | 1 + src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 6 +- src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs | 64 +++++++++++++++++-- .../Wasm.Build.Tests/BuildPublishTests.cs | 57 +++++++++-------- .../Wasm.Build.Tests/BuildTestBase.cs | 56 ++++++++++------- .../InvariantGlobalizationTests.cs | 9 +-- .../Wasm.Build.Tests/LocalEMSDKTests.cs | 10 +-- .../Wasm.Build.Tests/MainWithArgsTests.cs | 7 ++- .../Wasm.Build.Tests/NativeBuildTests.cs | 21 ++++--- .../Wasm.Build.Tests/NativeLibraryTests.cs | 11 ++-- .../NativeRebuildTests/NativeRebuildTestsBase.cs | 22 ++++--- .../Wasm.Build.Tests/PInvokeTableGeneratorTests.cs | 17 ++--- .../BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs | 16 ++--- .../Wasm.Build.Tests/SatelliteAssembliesTests.cs | 45 ++++++------- .../Wasm.Build.Tests/WasmBuildAppTest.cs | 35 ++++++----- .../Wasm.Build.Tests/WasmNativeDefaultsTests.cs | 12 ++-- 21 files changed, 332 insertions(+), 151 deletions(-) create mode 100755 src/mono/wasm/sln/WasmBuild.sln diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index ca2d51a..9f8b2ea 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -13,6 +13,7 @@ <_ShellCommandSeparator Condition="'$(OS)' == 'Windows_NT'">&& <_ShellCommandSeparator Condition="'$(OS)' != 'Windows_NT'">&& + false diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 592a83a..1dfa559 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -13,12 +13,24 @@ false - + + + + + + + + + + + + + diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index 9fdf3c3..ea282f9 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -26,6 +26,10 @@ true + + + + <_MonoComponent Include="hot_reload;debugger" /> diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 4bcaac9..ad4896e 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -159,7 +159,7 @@ + Text="%24(MicrosoftNetCoreAppRuntimePackDir)='', and cannot find %25(ResolvedRuntimePack.PackageDirectory)=%(ResolvedRuntimePack.PackageDirectory). One of these need to be set to a valid path" /> diff --git a/src/mono/wasm/sln/WasmBuild.sln b/src/mono/wasm/sln/WasmBuild.sln new file mode 100755 index 0000000..10256d2 --- /dev/null +++ b/src/mono/wasm/sln/WasmBuild.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31722.452 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WasmBuildTasks", "..\..\..\tasks\WasmBuildTasks\WasmBuildTasks.csproj", "{D5BD9C0C-8A05-493E-BE45-13AF8286CD92}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WasmAppBuilder", "..\..\..\tasks\WasmAppBuilder\WasmAppBuilder.csproj", "{8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoAOTCompiler", "..\..\..\tasks\AotCompilerTask\MonoAOTCompiler.csproj", "{A9C02284-0387-42E7-BF78-47DF13656D5E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Build.Tests", "..\..\..\tests\BuildWasmApps\Wasm.Build.Tests\Wasm.Build.Tests.csproj", "{94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DebuggerTestSuite", "..\debugger\DebuggerTestSuite\DebuggerTestSuite.csproj", "{4C0EE027-FC30-4167-B2CF-A6D18F00E08F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugHost", "..\debugger\BrowserDebugHost\BrowserDebugHost.csproj", "{292A88FD-795F-467A-8801-B5B791CEF96E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugProxy", "..\debugger\BrowserDebugProxy\BrowserDebugProxy.csproj", "{F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WasmAppHost", "..\host\WasmAppHost.csproj", "{C7099764-EC2E-4FAF-9057-0321893DE4F8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplyUpdateReferencedAssembly", "..\debugger\tests\ApplyUpdateReferencedAssembly\ApplyUpdateReferencedAssembly.csproj", "{75477B6F-DC8E-4002-88B8-017C992C568E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Release|Any CPU.Build.0 = Release|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Release|Any CPU.Build.0 = Release|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Release|Any CPU.Build.0 = Release|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Release|Any CPU.Build.0 = Release|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Release|Any CPU.Build.0 = Release|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Release|Any CPU.Build.0 = Release|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Release|Any CPU.Build.0 = Release|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Release|Any CPU.Build.0 = Release|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2BDE8FDE-4261-4B4D-8B54-ACC88B06C8D1} + EndGlobalSection +EndGlobal diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 0a8e59d..5340cef 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -12,6 +12,7 @@ emcc $(ArtifactsObjDir)wasm <_EmccDefaultsRspPath>$(NativeBinDir)src\emcc-default.rsp + false diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index dee6b53..701edb6 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -744,13 +744,13 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task Log.LogMessage(importance, $"{msgPrefix}Exec (with response file contents expanded) in {args.WorkingDir}: {envStr}{CompilerBinaryPath} {File.ReadAllText(args.ResponseFilePath)}"); } - Log.LogMessage(importance, output); - if (exitCode != 0) { - Log.LogError($"Precompiling failed for {assembly}"); + Log.LogError($"Precompiling failed for {assembly}.{Environment.NewLine}{output}"); return false; } + + Log.LogMessage(importance, output); } catch (Exception ex) { diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 8170c0f..9526a60 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -24,7 +24,7 @@ public class PInvokeTableGenerator : Task [Output] public string FileWrites { get; private set; } = string.Empty; - private static char[] s_charsToReplace = new[] { '.', '-', }; + private static char[] s_charsToReplace = new[] { '.', '-', '+' }; public override bool Execute() { @@ -88,7 +88,21 @@ public class PInvokeTableGenerator : Task private void CollectPInvokes(List pinvokes, List callbacks, Type type) { - foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance)) { + foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance)) + { + try + { + CollectPInvokesForMethod(method); + } + catch (Exception ex) + { + Log.LogMessage(MessageImportance.Low, $"Could not get pinvoke, or callbacks for method {method.Name}: {ex}"); + continue; + } + } + + void CollectPInvokesForMethod(MethodInfo method) + { if ((method.Attributes & MethodAttributes.PinvokeImpl) != 0) { var dllimport = method.CustomAttributes.First(attr => attr.AttributeType.Name == "DllImportAttribute"); @@ -164,7 +178,8 @@ public class PInvokeTableGenerator : Task Where(l => l.Module == module && !l.Skip). OrderBy(l => l.EntryPoint). GroupBy(d => d.EntryPoint). - Select (l => "{\"" + l.Key + "\", " + l.Key + "}, // " + string.Join (", ", l.Select(c => c.Method.DeclaringType!.Module!.Assembly!.GetName ()!.Name!).Distinct().OrderBy(n => n))); + Select (l => "{\"" + FixupSymbolName(l.Key) + "\", " + FixupSymbolName(l.Key) + "}, " + + "// " + string.Join (", ", l.Select(c => c.Method.DeclaringType!.Module!.Assembly!.GetName ()!.Name!).Distinct().OrderBy(n => n))); foreach (var pinvoke in assemblies_pinvokes) { w.WriteLine (pinvoke); @@ -216,6 +231,45 @@ public class PInvokeTableGenerator : Task } } + private static string FixupSymbolName(string name) + { + UTF8Encoding utf8 = new(); + byte[] bytes = utf8.GetBytes(name); + StringBuilder sb = new(); + + foreach (byte b in bytes) + { + if ((b >= (byte)'0' && b <= (byte)'9') || + (b >= (byte)'a' && b <= (byte)'z') || + (b >= (byte)'A' && b <= (byte)'Z') || + (b == (byte)'_')) + { + sb.Append((char) b); + } + else if (s_charsToReplace.Contains((char) b)) + { + sb.Append('_'); + } + else + { + sb.Append($"_{b:X}_"); + } + } + + return sb.ToString(); + } + + private static string SymbolNameForMethod(MethodInfo method) + { + StringBuilder sb = new(); + Type? type = method.DeclaringType; + sb.Append($"{type!.Module!.Assembly!.GetName()!.Name!}_"); + sb.Append($"{(type!.IsNested ? type!.FullName : type!.Name)}_"); + sb.Append(method.Name); + + return FixupSymbolName(sb.ToString()); + } + private string MapType (Type t) { string name = t.Name; @@ -262,7 +316,7 @@ public class PInvokeTableGenerator : Task if (method.Name == "EnumCalendarInfo") { // FIXME: System.Reflection.MetadataLoadContext can't decode function pointer types // https://github.com/dotnet/runtime/issues/43791 - sb.Append($"int {pinvoke.EntryPoint} (int, int, int, int, int);"); + sb.Append($"int {FixupSymbolName(pinvoke.EntryPoint)} (int, int, int, int, int);"); return sb.ToString(); } @@ -274,7 +328,7 @@ public class PInvokeTableGenerator : Task } sb.Append(MapType(method.ReturnType)); - sb.Append($" {pinvoke.EntryPoint} ("); + sb.Append($" {FixupSymbolName(pinvoke.EntryPoint)} ("); int pindex = 0; var pars = method.GetParameters(); foreach (var p in pars) { diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs index 42eb966..1e25eb0 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildPublishTests.cs @@ -33,11 +33,14 @@ namespace Wasm.Build.Tests // no relinking for build bool relinked = false; BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: !relinked, id: id, - createProject: true, - publish: false); + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: !relinked, + CreateProject: true, + Publish: false + )); + Run(); @@ -53,10 +56,11 @@ namespace Wasm.Build.Tests relinked = buildArgs.Config == "Release"; BuildProject(buildArgs, id: id, - dotnetWasmFromRuntimePack: !relinked, - createProject: false, - publish: true, - useCache: false); + new BuildProjectOptions( + DotnetWasmFromRuntimePack: !relinked, + CreateProject: false, + Publish: true, + UseCache: false)); Run(); @@ -79,12 +83,13 @@ namespace Wasm.Build.Tests // no relinking for build bool relinked = false; (_, string output) = BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: !relinked, - id: id, - createProject: true, - publish: false, - label: "first_build"); + id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: !relinked, + CreateProject: true, + Publish: false, + Label: "first_build")); BuildPaths paths = GetBuildPaths(buildArgs); var pathsDict = GetFilesTable(buildArgs, paths, unchanged: false); @@ -109,11 +114,12 @@ namespace Wasm.Build.Tests // relink by default for Release+publish (_, output) = BuildProject(buildArgs, id: id, - dotnetWasmFromRuntimePack: false, - createProject: false, - publish: true, - useCache: false, - label: "first_publish"); + new BuildProjectOptions( + DotnetWasmFromRuntimePack: false, + CreateProject: false, + Publish: true, + UseCache: false, + Label: "first_publish")); var publishStat = StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath)); Assert.True(publishStat["pinvoke.o"].Exists); @@ -125,12 +131,13 @@ namespace Wasm.Build.Tests // second build (_, output) = BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: !relinked, - id: id, - createProject: true, - publish: false, - label: "second_build"); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: !relinked, + CreateProject: true, + Publish: false, + Label: "second_build")); var secondBuildStat = StatFiles(pathsDict.Select(kvp => kvp.Value.fullPath)); // no relinking, or AOT diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs index cc4aa85..210ea11 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs @@ -280,18 +280,10 @@ namespace Wasm.Build.Tests public (string projectDir, string buildOutput) BuildProject(BuildArgs buildArgs, string id, - Action? initProject = null, - bool? dotnetWasmFromRuntimePack = null, - bool hasIcudt = true, - bool useCache = true, - bool expectSuccess = true, - bool createProject = true, - bool publish = true, - string? verbosity=null, - string? label=null) - { - string msgPrefix = label != null ? $"[{label}] " : string.Empty; - if (useCache && _buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product)) + BuildProjectOptions options) + { + string msgPrefix = options.Label != null ? $"[{options.Label}] " : string.Empty; + if (options.UseCache && _buildContext.TryGetBuildFor(buildArgs, out BuildProduct? product)) { Console.WriteLine ($"Using existing build found at {product.ProjectDir}, with build log at {product.LogFile}"); @@ -303,33 +295,35 @@ namespace Wasm.Build.Tests return (_projectDir, "FIXME"); } - if (createProject) + if (options.CreateProject) { InitPaths(id); InitProjectDir(_projectDir); - initProject?.Invoke(); + options.InitProject?.Invoke(); File.WriteAllText(Path.Combine(_projectDir, $"{buildArgs.ProjectName}.csproj"), buildArgs.ProjectFileContents); File.Copy(Path.Combine(AppContext.BaseDirectory, "test-main.js"), Path.Combine(_projectDir, "test-main.js")); } else if (_projectDir is null) { - throw new Exception("_projectDir should be set, to use createProject=false"); + throw new Exception("_projectDir should be set, to use options.createProject=false"); } StringBuilder sb = new(); - sb.Append(publish ? "publish" : "build"); + sb.Append(options.Publish ? "publish" : "build"); + if (options.Publish && options.BuildOnlyAfterPublish) + sb.Append(" -p:WasmBuildOnlyAfterPublish=true"); sb.Append($" {s_buildEnv.DefaultBuildArgs}"); sb.Append($" /p:Configuration={buildArgs.Config}"); - string logFileSuffix = label == null ? string.Empty : label.Replace(' ', '_'); + string logFileSuffix = options.Label == null ? string.Empty : options.Label.Replace(' ', '_'); string logFilePath = Path.Combine(_logPath, $"{buildArgs.ProjectName}{logFileSuffix}.binlog"); _testOutput.WriteLine($"-------- Building ---------"); _testOutput.WriteLine($"Binlog path: {logFilePath}"); Console.WriteLine($"Binlog path: {logFilePath}"); sb.Append($" /bl:\"{logFilePath}\" /nologo"); - sb.Append($" /fl /flp:\"v:diag,LogFile={logFilePath}.log\" /v:{verbosity ?? "minimal"}"); + sb.Append($" /fl /flp:\"v:diag,LogFile={logFilePath}.log\" /v:{options.Verbosity ?? "minimal"}"); if (buildArgs.ExtraBuildArgs != null) sb.Append($" {buildArgs.ExtraBuildArgs} "); @@ -338,26 +332,26 @@ namespace Wasm.Build.Tests (int exitCode, string buildOutput) result; try { - result = AssertBuild(sb.ToString(), id, expectSuccess: expectSuccess, envVars: s_buildEnv.EnvVars); + result = AssertBuild(sb.ToString(), id, expectSuccess: options.ExpectSuccess, envVars: s_buildEnv.EnvVars); //AssertRuntimePackPath(result.buildOutput); // check that we are using the correct runtime pack! - if (expectSuccess) + if (options.ExpectSuccess) { string bundleDir = Path.Combine(GetBinDir(config: buildArgs.Config), "AppBundle"); - AssertBasicAppBundle(bundleDir, buildArgs.ProjectName, buildArgs.Config, hasIcudt, dotnetWasmFromRuntimePack ?? !buildArgs.AOT); + AssertBasicAppBundle(bundleDir, buildArgs.ProjectName, buildArgs.Config, options.HasIcudt, options.DotnetWasmFromRuntimePack ?? !buildArgs.AOT); } - if (useCache) + if (options.UseCache) _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir, logFilePath, true)); return (_projectDir, result.buildOutput); } catch { - if (useCache) + if (options.UseCache) _buildContext.CacheBuild(buildArgs, new BuildProduct(_projectDir, logFilePath, false)); throw; } @@ -860,4 +854,18 @@ namespace Wasm.Build.Tests public record BuildProduct(string ProjectDir, string LogFile, bool Result); internal record FileStat (bool Exists, DateTime LastWriteTimeUtc, long Length, string FullPath); internal record BuildPaths(string ObjWasmDir, string ObjDir, string BinDir, string BundleDir); - } + + public record BuildProjectOptions + ( + Action? InitProject = null, + bool? DotnetWasmFromRuntimePack = null, + bool HasIcudt = true, + bool UseCache = true, + bool ExpectSuccess = true, + bool CreateProject = true, + bool Publish = true, + bool BuildOnlyAfterPublish = true, + string? Verbosity = null, + string? Label = null + ); +} diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs index 7d66bc3..f34cb9c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/InvariantGlobalizationTests.cs @@ -74,10 +74,11 @@ namespace Wasm.Build.Tests "; BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), - id: id, - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, - hasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + HasIcudt: invariantGlobalization == null || invariantGlobalization.Value == false)); if (invariantGlobalization == true) { diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/LocalEMSDKTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/LocalEMSDKTests.cs index 30ed330..5a85ae9 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/LocalEMSDKTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/LocalEMSDKTests.cs @@ -30,9 +30,10 @@ namespace Wasm.Build.Tests buildArgs = ExpandBuildArgs(buildArgs); (_, string buildOutput) = BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), id: id, - expectSuccess: false); + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + ExpectSuccess: false)); Assert.Matches(errorPattern, buildOutput); } @@ -52,9 +53,10 @@ namespace Wasm.Build.Tests buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "true"); (_, string buildOutput) = BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), id: id, - expectSuccess: false); + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + ExpectSuccess: false)); Assert.Matches(errorPattern, buildOutput); } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs index 73598d8..2e453ee 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/MainWithArgsTests.cs @@ -86,9 +86,10 @@ namespace Wasm.Build.Tests Console.WriteLine ($"-- args: {buildArgs}, name: {projectName}"); BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), - id: id, - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42 + args.Length, args: string.Join(' ', args), test: output => diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs index 3453f99..304161e 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs @@ -32,9 +32,10 @@ namespace Wasm.Build.Tests buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "true"); BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: false, - id: id); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: false)); RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, test: output => {}, @@ -57,10 +58,11 @@ namespace Wasm.Build.Tests (_, string output) = BuildProject( buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: false, id: id, - expectSuccess: false); + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: false, + ExpectSuccess: false)); Assert.Contains("Stopping after AOT", output); } @@ -89,9 +91,10 @@ namespace Wasm.Build.Tests buildArgs = ExpandBuildArgs(buildArgs, insertAtEnd: printFileTypeTarget); (_, string output) = BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: false, - id: id); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: false)); if (!output.Contains("** wasm-dis exit code: 0")) throw new XunitException($"Expected to successfully run wasm-dis on System.Private.CoreLib.dll.o ." diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs index eb30628..e8892a9 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeLibraryTests.cs @@ -37,8 +37,8 @@ namespace Wasm.Build.Tests } BuildProject(buildArgs, - dotnetWasmFromRuntimePack: false, - id: id); + id: id, + new BuildProjectOptions(DotnetWasmFromRuntimePack: false)); string output = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 0, test: output => {}, @@ -81,9 +81,10 @@ public class Test }"; BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), - dotnetWasmFromRuntimePack: false, - id: id); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: false)); string output = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 0, test: output => {}, diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs index cd0d3ac..da32a9f 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/NativeRebuildTests/NativeRebuildTestsBase.cs @@ -48,11 +48,12 @@ namespace Wasm.Build.NativeRebuild.Tests { buildArgs = GenerateProjectContents(buildArgs, nativeRelink, invariant, extraProperties); BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), - dotnetWasmFromRuntimePack: false, - hasIcudt: !invariant, - id: id, - createProject: true); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: false, + HasIcudt: !invariant, + CreateProject: true)); RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 42, host: RunHost.V8, id: id); return (buildArgs, GetBuildPaths(buildArgs)); @@ -80,11 +81,12 @@ namespace Wasm.Build.NativeRebuild.Tests Console.WriteLine($"{Environment.NewLine}Rebuilding with no changes ..{Environment.NewLine}"); (_, string output) = BuildProject(buildArgs, id: id, - dotnetWasmFromRuntimePack: false, - hasIcudt: !invariant, - createProject: false, - useCache: false, - verbosity: verbosity); + new BuildProjectOptions( + DotnetWasmFromRuntimePack: false, + HasIcudt: !invariant, + CreateProject: false, + UseCache: false, + Verbosity: verbosity)); return output; } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs index 27783ae..feada6b 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/PInvokeTableGeneratorTests.cs @@ -123,15 +123,16 @@ namespace Wasm.Build.Tests extraProperties: "true<_WasmDevel>true"); (_, string output) = BuildProject(buildArgs, - initProject: () => - { - File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); - File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", filename), - Path.Combine(_projectDir!, filename)); - }, - publish: buildArgs.AOT, id: id, - dotnetWasmFromRuntimePack: false); + new BuildProjectOptions( + InitProject: () => + { + File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); + File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", filename), + Path.Combine(_projectDir!, filename)); + }, + Publish: buildArgs.AOT, + DotnetWasmFromRuntimePack: false)); return (buildArgs, output); } diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs index 961c141..ba65b24 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/RebuildTests.cs @@ -35,10 +35,11 @@ namespace Wasm.Build.Tests buildArgs = ExpandBuildArgs(buildArgs); BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: true, - id: id, - createProject: true); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: true, + CreateProject: true)); Run(); @@ -52,9 +53,10 @@ namespace Wasm.Build.Tests // no-op Rebuild BuildProject(buildArgs, id: id, - dotnetWasmFromRuntimePack: true, - createProject: false, - useCache: false); + new BuildProjectOptions( + DotnetWasmFromRuntimePack: true, + CreateProject: false, + UseCache: false)); Run(); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs index b65c274..7b6c4c7 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/SatelliteAssembliesTests.cs @@ -50,13 +50,14 @@ namespace Wasm.Build.Tests extraProperties: nativeRelink ? $"true" : string.Empty); BuildProject(buildArgs, - initProject: () => - { - Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "resx"), Path.Combine(_projectDir!, "resx")); - CreateProgramForCultureTest(_projectDir!, $"{projectName}.resx.words", "TestClass"); - }, - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, - id: id); + id: id, + new BuildProjectOptions( + InitProject: () => + { + Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "resx"), Path.Combine(_projectDir!, "resx")); + CreateProgramForCultureTest(_projectDir!, $"{projectName}.resx.words", "TestClass"); + }, + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); string output = RunAndTestWasmApp( buildArgs, expectedExitCode: 42, @@ -88,17 +89,18 @@ namespace Wasm.Build.Tests extraItems: $""); BuildProject(buildArgs, - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, - id: id, - initProject: () => - { - string rootDir = _projectDir!; - _projectDir = Path.Combine(rootDir, projectName); - - Directory.CreateDirectory(_projectDir); - Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "SatelliteAssemblyFromProjectRef"), rootDir); - CreateProgramForCultureTest(_projectDir, "LibraryWithResources.resx.words", "LibraryWithResources.Class1"); - }); + id: id, + new BuildProjectOptions( + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + InitProject: () => + { + string rootDir = _projectDir!; + _projectDir = Path.Combine(rootDir, projectName); + + Directory.CreateDirectory(_projectDir); + Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "SatelliteAssemblyFromProjectRef"), rootDir); + CreateProgramForCultureTest(_projectDir, "LibraryWithResources.resx.words", "LibraryWithResources.Class1"); + })); string output = RunAndTestWasmApp(buildArgs, expectedExitCode: 42, @@ -123,9 +125,10 @@ namespace Wasm.Build.Tests extraItems: $""); BuildProject(buildArgs, - initProject: () => CreateProgramForCultureTest(_projectDir!, $"{projectName}.words", "TestClass"), - dotnetWasmFromRuntimePack: false, - id: id); + id: id, + new BuildProjectOptions( + InitProject: () => CreateProgramForCultureTest(_projectDir!, $"{projectName}.words", "TestClass"), + DotnetWasmFromRuntimePack: false)); var bitCodeFileNames = Directory.GetFileSystemEntries(Path.Combine(_projectDir!, "obj"), "*.dll.bc", SearchOption.AllDirectories) .Select(path => Path.GetFileName(path)) diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 68bc578..d6ae5ed 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -112,13 +112,14 @@ namespace Wasm.Build.Tests }"; BuildProject(buildArgs, - initProject: () => - { - File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); - File.WriteAllText(Path.Combine(_projectDir!, "runtimeconfig.template.json"), runtimeConfigTemplateJson); - }, - id: id, - dotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release")); + id: id, + new BuildProjectOptions( + InitProject: () => + { + File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); + File.WriteAllText(Path.Combine(_projectDir!, "runtimeconfig.template.json"), runtimeConfigTemplateJson); + }, + DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("test_runtimeconfig_json: 25", output), host: host, id: id); @@ -141,12 +142,13 @@ namespace Wasm.Build.Tests "; BuildProject(buildArgs, - initProject: () => - { - File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); - }, - id: id, - dotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release")); + id: id, + new BuildProjectOptions( + InitProject: () => + { + File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); + }, + DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("System.Threading.ThreadPool.MaxThreads: 20", output), host: host, id: id); @@ -167,9 +169,10 @@ namespace Wasm.Build.Tests dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), - id: id, - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("Hello, World!", output), host: host, id: id); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs index 64d0085..00674bf 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs @@ -89,11 +89,13 @@ namespace Wasm.Build.Tests insertAtEnd: printValueTarget); (_, string output) = BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, - id: Path.GetRandomFileName(), - expectSuccess: false, - useCache: false); + id: Path.GetRandomFileName(), + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + ExpectSuccess: false, + UseCache: false, + BuildOnlyAfterPublish: false)); return output; } -- 2.7.4