Skip to content

Commit b0c2e73

Browse files
committed
[wasm] Add support for using custom native libraries (dotnet#55797)
(cherry picked from commit d574b03)
1 parent d17b813 commit b0c2e73

File tree

14 files changed

+234
-45
lines changed

14 files changed

+234
-45
lines changed

src/mono/wasm/build/WasmApp.Native.targets

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
</_WasmBuildNativeCoreDependsOn>
1919

2020
<WasmBuildNativeOnlyDependsOn>
21+
_InitializeCommonProperties;
2122
_PrepareForWasmBuildNativeOnly;
2223
_WasmBuildNativeCore;
2324
</WasmBuildNativeOnlyDependsOn>
@@ -38,13 +39,14 @@
3839
<Target Name="WasmBuildNativeOnly" DependsOnTargets="$(WasmBuildNativeOnlyDependsOn)" Condition="'$(WasmBuildNative)' == 'true'" />
3940

4041
<Target Name="_PrepareForWasmBuildNativeOnly">
42+
<MakeDir Directories="$(_WasmIntermediateOutputPath)" />
43+
4144
<ItemGroup>
4245
<_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" />
4346
<_WasmAssembliesInternal Include="@(WasmAssembliesToBundle->Distinct())" />
4447
</ItemGroup>
4548
</Target>
4649

47-
4850
<Target Name="_SetupEmscripten">
4951
<PropertyGroup>
5052
<_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmscriptenSdkToolsPath)' == '' or !Exists('$(EmscriptenSdkToolsPath)'))">%24(EmscriptenSdkToolsPath)=$(EmscriptenSdkToolsPath) </_EMSDKMissingPaths>
@@ -115,8 +117,9 @@
115117

116118
<PropertyGroup>
117119
<WasmBuildNative Condition="'$(RunAOTCompilation)' == 'true'">true</WasmBuildNative>
118-
<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and '$(PublishTrimmed)' != 'true'">false</WasmBuildNative>
119-
<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and '$(Configuration)' == 'Release'">true</WasmBuildNative>
120+
<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and @(NativeFileReference->Count()) > 0" >true</WasmBuildNative>
121+
<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and '$(PublishTrimmed)' != 'true'" >false</WasmBuildNative>
122+
<WasmBuildNative Condition="'$(WasmBuildNative)' == '' and '$(Configuration)' == 'Release'" >true</WasmBuildNative>
120123
<WasmBuildNative Condition="'$(WasmBuildNative)' == ''">false</WasmBuildNative>
121124
</PropertyGroup>
122125

@@ -153,6 +156,8 @@
153156

154157
<EmccCompileOptimizationFlag Condition="'$(EmccCompileOptimizationFlag)' == ''">$(_EmccOptimizationFlagDefault)</EmccCompileOptimizationFlag>
155158
<EmccLinkOptimizationFlag Condition="'$(EmccLinkOptimizationFlag)' == ''" >-O0 -s ASSERTIONS=$(_EmccAssertionLevelDefault)</EmccLinkOptimizationFlag>
159+
160+
<_EmccCompileRsp>$(_WasmIntermediateOutputPath)emcc-compile.rsp</_EmccCompileRsp>
156161
</PropertyGroup>
157162

158163
<ItemGroup>
@@ -161,15 +166,41 @@
161166
<_EmccCommonFlags Include="-s DISABLE_EXCEPTION_CATCHING=0" />
162167
<_EmccCommonFlags Include="-g" Condition="'$(WasmNativeStrip)' == 'false'" />
163168
<_EmccCommonFlags Include="-v" Condition="'$(EmccVerbose)' != 'false'" />
169+
170+
<_EmccIncludePaths Include="$(_WasmIntermediateOutputPath.TrimEnd('\/'))" />
171+
<_EmccIncludePaths Include="$(_WasmRuntimePackIncludeDir)mono-2.0" />
172+
<_EmccIncludePaths Include="$(_WasmRuntimePackIncludeDir)wasm" />
173+
174+
<!-- Adding optimization flag at the top, so it gets precedence -->
175+
<_EmccCFlags Include="$(EmccCompileOptimizationFlag)" />
176+
<_EmccCFlags Include="@(_EmccCommonFlags)" />
177+
178+
<_EmccCFlags Include="-DENABLE_AOT=1" Condition="'$(RunAOTCompilation)' == 'true'" />
179+
<_EmccCFlags Include="-DDRIVER_GEN=1" Condition="'$(RunAOTCompilation)' == 'true'" />
180+
<_EmccCFlags Include="-DINVARIANT_GLOBALIZATION=1" Condition="'$(InvariantGlobalization)' == 'true'" />
181+
<_EmccCFlags Include="-DLINK_ICALLS=1" Condition="'$(WasmLinkIcalls)' == 'true'" />
182+
<_EmccCFlags Include="-DCORE_BINDINGS" />
183+
<_EmccCFlags Include="-DGEN_PINVOKE=1" />
184+
185+
<_EmccCFlags Include="&quot;-I%(_EmccIncludePaths.Identity)&quot;" />
186+
<_EmccCFlags Include="-g" Condition="'$(WasmNativeDebugSymbols)' == 'true'" />
187+
188+
<_EmccCFlags Include="$(EmccExtraCFlags)" />
189+
190+
<_WasmRuntimePackSrcFile Include="$(_WasmRuntimePackSrcDir)*.c" />
191+
<_WasmRuntimePackSrcFile ObjectFile="$(_WasmIntermediateOutputPath)%(FileName).o" />
192+
193+
<_DotnetJSSrcFile Include="$(_WasmRuntimePackSrcDir)\*.js" />
194+
<_WasmNativeFileForLinking Include="@(NativeFileReference)" />
164195
</ItemGroup>
165196

166-
<ItemGroup>
167-
<_DotnetJSSrcFile Include="$(_WasmRuntimePackSrcDir)\*.js" />
168-
</ItemGroup>
197+
<Error Text="Could not find NativeFileReference %(NativeFileReference.Identity)" Condition="'%(NativeFileReference.Identity)' != '' and !Exists(%(NativeFileReference.Identity))" />
169198
</Target>
170199

171200
<Target Name="_GeneratePInvokeTable">
172201
<ItemGroup>
202+
<_WasmPInvokeModules Include="%(_WasmNativeFileForLinking.FileName)" Condition="'%(_WasmNativeFileForLinking.ScanForPInvokes)' != 'false'" />
203+
173204
<_WasmPInvokeModules Include="libSystem.Native" />
174205
<_WasmPInvokeModules Include="libSystem.IO.Compression.Native" />
175206
<_WasmPInvokeModules Include="libSystem.Globalization.Native" />
@@ -194,38 +225,13 @@
194225

195226
<Target Name="_WasmCompileNativeFiles">
196227
<ItemGroup>
197-
<_EmccIncludePaths Include="$(_WasmIntermediateOutputPath.TrimEnd('\/'))" />
198-
<_EmccIncludePaths Include="$(_WasmRuntimePackIncludeDir)mono-2.0" />
199-
<_EmccIncludePaths Include="$(_WasmRuntimePackIncludeDir)wasm" />
200-
201-
<!-- Adding optimization flag at the top, so it gets precedence -->
202-
<_EmccCFlags Include="$(EmccCompileOptimizationFlag)" />
203-
<_EmccCFlags Include="@(_EmccCommonFlags)" />
204-
205-
<_EmccCFlags Include="-DENABLE_AOT=1" Condition="'$(RunAOTCompilation)' == 'true'" />
206-
<_EmccCFlags Include="-DDRIVER_GEN=1" Condition="'$(RunAOTCompilation)' == 'true'" />
207-
<_EmccCFlags Include="-DINVARIANT_GLOBALIZATION=1" Condition="'$(InvariantGlobalization)' == 'true'" />
208-
<_EmccCFlags Include="-DLINK_ICALLS=1" Condition="'$(WasmLinkIcalls)' == 'true'" />
209-
<_EmccCFlags Include="-DCORE_BINDINGS" />
210-
<_EmccCFlags Include="-DGEN_PINVOKE=1" />
211-
<_EmccCFlags Include="-emit-llvm" />
212-
213-
<_EmccCFlags Include="&quot;-I%(_EmccIncludePaths.Identity)&quot;" />
214-
<_EmccCFlags Include="-g" Condition="'$(WasmNativeDebugSymbols)' == 'true'" />
215-
<_EmccCFlags Include="-s EXPORTED_FUNCTIONS='[@(_ExportedFunctions->'&quot;%(Identity)&quot;', ',')]'" Condition="@(_ExportedFunctions->Count()) > 0" />
216-
217-
<_EmccCFlags Include="$(EmccExtraCFlags)" />
218-
219-
<_WasmRuntimePackSrcFile Remove="@(_WasmRuntimePackSrcFile)" />
220-
<_WasmRuntimePackSrcFile Include="$(_WasmRuntimePackSrcDir)\*.c" />
221-
<_WasmRuntimePackSrcFile ObjectFile="$(_WasmIntermediateOutputPath)%(FileName).o" />
228+
<_WasmSourceFileToCompile Remove="@(_WasmSourceFileToCompile)" />
222229
<_WasmSourceFileToCompile Include="@(_WasmRuntimePackSrcFile)" />
223230
</ItemGroup>
224231

225232
<PropertyGroup>
226233
<_EmBuilder Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">embuilder.bat</_EmBuilder>
227234
<_EmBuilder Condition="!$([MSBuild]::IsOSPlatform('WINDOWS'))">embuilder.py</_EmBuilder>
228-
<_EmccCompileRsp>$(_WasmIntermediateOutputPath)emcc-compile.rsp</_EmccCompileRsp>
229235
</PropertyGroup>
230236

231237
<WriteLinesToFile Lines="@(_EmccCFlags)" File="$(_EmccCompileRsp)" Overwrite="true" WriteOnlyWhenDifferent="true" />
@@ -235,6 +241,10 @@
235241

236242
<Message Text="Compiling native assets with emcc. This may take a while ..." Importance="High" />
237243
<EmccCompile SourceFiles="@(_WasmSourceFileToCompile)" Arguments='"@$(_EmccDefaultFlagsRsp)" "@$(_EmccCompileRsp)"' EnvironmentVariables="@(EmscriptenEnvVars)" />
244+
245+
<ItemGroup>
246+
<WasmNativeAsset Include="%(_WasmSourceFileToCompile.ObjectFile)" />
247+
</ItemGroup>
238248
</Target>
239249

240250
<ItemGroup Condition="'$(Configuration)' == 'Debug' and '@(_MonoComponent->Count())' == 0">
@@ -271,6 +281,8 @@
271281
Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\*.a"
272282
Exclude="@(_MonoRuntimeComponentDontLink->'$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\%(Identity)')" />
273283

284+
<_WasmExtraJSFile Include="@(Content)" Condition="'%(Content.Extension)' == '.js'" />
285+
274286
<_EmccLinkStepArgs Include="@(_EmccLDFlags)" />
275287
<_EmccLinkStepArgs Include="--js-library &quot;%(_DotnetJSSrcFile.Identity)&quot;" />
276288
<_EmccLinkStepArgs Include="--js-library &quot;%(_WasmExtraJSFile.Identity)&quot;" Condition="'%(_WasmExtraJSFile.Kind)' == 'js-library'" />
@@ -483,6 +495,5 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_
483495
<ParameterGroup>
484496
<EmccProperties ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="false" Output="true" />
485497
</ParameterGroup>
486-
</UsingTask>
487-
498+
</UsingTask>
488499
</Project>

src/mono/wasm/build/WasmApp.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
<WasmBuildAppAfterThisTarget Condition="'$(WasmBuildAppAfterThisTarget)' == ''">Publish</WasmBuildAppAfterThisTarget>
99
<WasmBuildAppDependsOn>
10+
_InitializeCommonProperties;
1011
_BeforeWasmBuildApp;
1112
_WasmResolveReferences;
1213
_WasmAotCompileApp;

src/mono/wasm/build/WasmApp.targets

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@
8080
<!--<WasmStripAOTAssemblies Condition="'$(AOTMode)' == 'LLVMOnlyInterp'">false</WasmStripAOTAssemblies>-->
8181
<!--<WasmStripAOTAssemblies Condition="'$(WasmStripAOTAssemblies)' == ''">$(RunAOTCompilation)</WasmStripAOTAssemblies>-->
8282
<WasmStripAOTAssemblies>false</WasmStripAOTAssemblies>
83+
84+
<!-- emcc, and mono-aot-cross don't like relative paths for output files -->
85+
<_WasmIntermediateOutputPath>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'wasm'))</_WasmIntermediateOutputPath>
8386
<_BeforeWasmBuildAppDependsOn />
8487
</PropertyGroup>
8588

@@ -90,7 +93,7 @@
9093

9194
<Target Name="_WasmCoreBuild" BeforeTargets="WasmBuildApp" DependsOnTargets="$(WasmBuildAppDependsOn)" />
9295

93-
<Target Name="_BeforeWasmBuildApp" DependsOnTargets="$(_BeforeWasmBuildAppDependsOn)">
96+
<Target Name="_InitializeCommonProperties">
9497
<Error Condition="'$(MicrosoftNetCoreAppRuntimePackDir)' == '' and ('%(ResolvedRuntimePack.PackageDirectory)' == '' or !Exists(%(ResolvedRuntimePack.PackageDirectory)))"
9598
Text="Could not find %25(ResolvedRuntimePack.PackageDirectory)=%(ResolvedRuntimePack.PackageDirectory)" />
9699

@@ -100,11 +103,12 @@
100103
<MicrosoftNetCoreAppRuntimePackRidDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidDir)))</MicrosoftNetCoreAppRuntimePackRidDir>
101104
<MicrosoftNetCoreAppRuntimePackRidNativeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidDir), 'native'))</MicrosoftNetCoreAppRuntimePackRidNativeDir>
102105

103-
<!-- FIXME: confirm that this won't get used before this -->
104106
<_WasmRuntimePackIncludeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include'))</_WasmRuntimePackIncludeDir>
105107
<_WasmRuntimePackSrcDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'src'))</_WasmRuntimePackSrcDir>
106108
</PropertyGroup>
109+
</Target>
107110

111+
<Target Name="_BeforeWasmBuildApp" DependsOnTargets="$(_BeforeWasmBuildAppDependsOn)">
108112
<Error Condition="'$(IntermediateOutputPath)' == ''" Text="%24(IntermediateOutputPath) property needs to be set" />
109113
<Error Condition="!Exists('$(MicrosoftNetCoreAppRuntimePackRidDir)')" Text="MicrosoftNetCoreAppRuntimePackRidDir=$(MicrosoftNetCoreAppRuntimePackRidDir) doesn't exist" />
110114
<Error Condition="@(WasmAssembliesToBundle->Count()) == 0" Text="WasmAssembliesToBundle item is empty. No assemblies to process" />
@@ -115,8 +119,6 @@
115119
<WasmMainAssemblyFileName Condition="'$(WasmMainAssemblyFileName)' == ''">$(TargetFileName)</WasmMainAssemblyFileName>
116120

117121
<WasmAppDir>$([MSBuild]::NormalizeDirectory($(WasmAppDir)))</WasmAppDir>
118-
<!-- emcc, and mono-aot-cross don't like relative paths for output files -->
119-
<_WasmIntermediateOutputPath>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'wasm'))</_WasmIntermediateOutputPath>
120122
</PropertyGroup>
121123

122124
<MakeDir Directories="$(_WasmIntermediateOutputPath)" />

src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public class PInvokeTableGenerator : Task
2222
[Required]
2323
public string? OutputPath { get; set; }
2424

25+
private static char[] s_charsToReplace = new[] { '.', '-', };
26+
2527
public override bool Execute()
2628
{
2729
Log.LogMessage(MessageImportance.Normal, $"Generating pinvoke table to '{OutputPath}'.");
@@ -101,7 +103,7 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary<string, string> modules
101103

102104
foreach (var module in modules.Keys)
103105
{
104-
string symbol = module.Replace(".", "_") + "_imports";
106+
string symbol = ModuleNameToId(module) + "_imports";
105107
w.WriteLine("static PinvokeImport " + symbol + " [] = {");
106108

107109
var assemblies_pinvokes = pinvokes.
@@ -120,7 +122,7 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary<string, string> modules
120122
w.Write("static void *pinvoke_tables[] = { ");
121123
foreach (var module in modules.Keys)
122124
{
123-
string symbol = module.Replace(".", "_") + "_imports";
125+
string symbol = ModuleNameToId(module) + "_imports";
124126
w.Write(symbol + ",");
125127
}
126128
w.WriteLine("};");
@@ -130,6 +132,18 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary<string, string> modules
130132
w.Write("\"" + module + "\"" + ",");
131133
}
132134
w.WriteLine("};");
135+
136+
static string ModuleNameToId(string name)
137+
{
138+
if (name.IndexOfAny(s_charsToReplace) < 0)
139+
return name;
140+
141+
string fixedName = name;
142+
foreach (char c in s_charsToReplace)
143+
fixedName = fixedName.Replace(c, '_');
144+
145+
return fixedName;
146+
}
133147
}
134148

135149
private string MapType (Type t)

src/tests/BuildWasmApps/Wasm.Build.Tests/BuildTestBase.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ static BuildTestBase()
6969

7070
public BuildTestBase(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
7171
{
72+
Console.WriteLine($"{Environment.NewLine}-------- New test --------{Environment.NewLine}");
7273
_buildContext = buildContext;
7374
_testOutput = output;
7475
_logPath = s_buildEnv.LogRootPath; // FIXME:
@@ -216,7 +217,8 @@ protected static string RunWithXHarness(string testCommand, string testLogPath,
216217
[MemberNotNull(nameof(_projectDir), nameof(_logPath))]
217218
protected void InitPaths(string id)
218219
{
219-
_projectDir = Path.Combine(AppContext.BaseDirectory, id);
220+
if (_projectDir == null)
221+
_projectDir = Path.Combine(AppContext.BaseDirectory, id);
220222
_logPath = Path.Combine(s_buildEnv.LogRootPath, id);
221223

222224
Directory.CreateDirectory(_logPath);
@@ -539,7 +541,6 @@ public static (int exitCode, string buildOutput) RunProcess(string path,
539541
var lastLines = outputBuilder.ToString().Split('\r', '\n').TakeLast(20);
540542
throw new XunitException($"Process timed out, output: {string.Join(Environment.NewLine, lastLines)}");
541543
}
542-
543544
}
544545

545546
lock (syncObj)

src/tests/BuildWasmApps/Wasm.Build.Tests/NativeBuildTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ private void NativeBuild(string projectNamePrefix, string projectContents, Build
3131
{
3232
string projectName = $"{projectNamePrefix}_{buildArgs.Config}_{buildArgs.AOT}";
3333

34-
buildArgs = buildArgs with { ProjectName = projectName, ProjectFileContents = projectContents };
34+
buildArgs = buildArgs with { ProjectName = projectName };
3535
buildArgs = ExpandBuildArgs(buildArgs, extraProperties: "<WasmBuildNative>true</WasmBuildNative>");
36-
Console.WriteLine ($"-- args: {buildArgs}, name: {projectName}");
3736

3837
BuildProject(buildArgs,
3938
initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), projectContents),
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.IO;
6+
using Xunit;
7+
using Xunit.Abstractions;
8+
9+
#nullable enable
10+
11+
namespace Wasm.Build.Tests
12+
{
13+
public class NativeLibraryTests : BuildTestBase
14+
{
15+
public NativeLibraryTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext)
16+
: base(output, buildContext)
17+
{
18+
}
19+
20+
[Theory]
21+
[BuildAndRun(aot: false)]
22+
[BuildAndRun(aot: true)]
23+
public void ProjectWithNativeReference(BuildArgs buildArgs, RunHost host, string id)
24+
{
25+
string projectName = $"AppUsingNativeLib-a";
26+
buildArgs = buildArgs with { ProjectName = projectName };
27+
buildArgs = ExpandBuildArgs(buildArgs, extraItems: "<NativeFileReference Include=\"native-lib.o\" />");
28+
29+
if (!_buildContext.TryGetBuildFor(buildArgs, out BuildProduct? _))
30+
{
31+
InitPaths(id);
32+
if (Directory.Exists(_projectDir))
33+
Directory.Delete(_projectDir, recursive: true);
34+
35+
Utils.DirectoryCopy(Path.Combine(BuildEnvironment.TestAssetsPath, "AppUsingNativeLib"), _projectDir);
36+
File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "native-lib.o"), Path.Combine(_projectDir, "native-lib.o"));
37+
}
38+
39+
BuildProject(buildArgs,
40+
dotnetWasmFromRuntimePack: false,
41+
id: id);
42+
43+
string output = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 0,
44+
test: output => {},
45+
host: host, id: id);
46+
47+
Assert.Contains("print_line: 100", output);
48+
Assert.Contains("from pinvoke: 142", output);
49+
}
50+
51+
[Theory]
52+
[BuildAndRun(aot: false)]
53+
[BuildAndRun(aot: true)]
54+
public void ProjectUsingSkiaSharp(BuildArgs buildArgs, RunHost host, string id)
55+
{
56+
string projectName = $"AppUsingSkiaSharp";
57+
buildArgs = buildArgs with { ProjectName = projectName };
58+
buildArgs = ExpandBuildArgs(buildArgs,
59+
extraItems: @$"
60+
<PackageReference Include=""SkiaSharp"" Version=""2.80.3"" />
61+
<PackageReference Include=""SkiaSharp.NativeAssets.WebAssembly"" Version=""2.80.3"" />
62+
63+
<NativeFileReference Include=""$(SkiaSharpStaticLibraryPath)\2.0.9\*.a"" />
64+
<WasmFilesToIncludeInFileSystem Include=""{Path.Combine(BuildEnvironment.TestAssetsPath, "mono.png")}"" />
65+
");
66+
67+
string programText = @"
68+
using System;
69+
using SkiaSharp;
70+
71+
public class Test
72+
{
73+
public static int Main()
74+
{
75+
using SKFileStream skfs = new SKFileStream(""mono.png"");
76+
using SKImage img = SKImage.FromEncodedData(skfs);
77+
78+
Console.WriteLine ($""Size: {skfs.Length} Height: {img.Height}, Width: {img.Width}"");
79+
return 0;
80+
}
81+
}";
82+
83+
BuildProject(buildArgs,
84+
initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText),
85+
dotnetWasmFromRuntimePack: false,
86+
id: id);
87+
88+
string output = RunAndTestWasmApp(buildArgs, buildDir: _projectDir, expectedExitCode: 0,
89+
test: output => {},
90+
host: host, id: id,
91+
args: "mono.png");
92+
93+
Assert.Contains("Size: 26462 Height: 599, Width: 499", output);
94+
}
95+
}
96+
}

src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
<PropertyGroup>
33
<WasmBuildAppDependsOn>PrepareForWasmBuild;$(WasmBuildAppDependsOn)</WasmBuildAppDependsOn>
44
<_MicrosoftNetCoreAppRefDir>$(AppRefDir)\</_MicrosoftNetCoreAppRefDir>
5-
<LocalFrameworkOverrideName>Microsoft.NETCore.App</LocalFrameworkOverrideName>
65
</PropertyGroup>
76

87
<Target Name="PrepareForWasmBuild">

0 commit comments

Comments
 (0)