This repository has been archived by the owner on Oct 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathWasi.Sdk.targets
264 lines (235 loc) · 15.7 KB
/
Wasi.Sdk.targets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WasiSdkTaskDir Condition="'$(MSBuildRuntimeType)' == 'Core'">net7.0</WasiSdkTaskDir>
<WasiSdkTaskDir Condition="'$(MSBuildRuntimeType)' != 'Core'">netstandard2.0</WasiSdkTaskDir>
<WasiSdkTaskAssembly>$(MSBuildThisFileDirectory)..\tools\$(WasiSdkTaskDir)\Wasi.Sdk.dll</WasiSdkTaskAssembly>
</PropertyGroup>
<UsingTask TaskName="Wasi.Sdk.Tasks.EmitWasmBundleObjectFile" AssemblyFile="$(WasiSdkTaskAssembly)" />
<UsingTask TaskName="Wasi.Sdk.Tasks.WasmResolveAssemblyDependencies" AssemblyFile="$(WasiSdkTaskAssembly)" />
<PropertyGroup>
<!-- Keep this block all in sync manually, since URLs can be arbitrary -->
<WasiSdkVersion>16.0</WasiSdkVersion>
<WasiSdkUrl Condition="$([MSBuild]::IsOSPlatform('Windows'))">https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-mingw.tar.gz</WasiSdkUrl>
<WasiSdkUrl Condition="$([MSBuild]::IsOSPlatform('Linux'))">https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz</WasiSdkUrl>
<WasiSdkUrl Condition="$([MSBuild]::IsOSPlatform('OSX'))">https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz</WasiSdkUrl>
<WasiSdkRoot>$([System.IO.Path]::Combine("$([System.Environment]::GetFolderPath(SpecialFolder.UserProfile))", ".wasi-sdk", "wasi-sdk-$(WasiSdkVersion)"))</WasiSdkRoot>
<WasiClang>$(WasiSdkRoot)\bin\clang</WasiClang>
<WasiClang Condition="$([MSBuild]::IsOSPlatform('Windows'))">$(WasiClang).exe</WasiClang>
<WasiRuntimePackRoot>$(MSBuildThisFileDirectory)..\packs\wasi-wasm\</WasiRuntimePackRoot>
<WasiBundleAssemblies Condition="'$(WasiBundleAssemblies)' == ''">true</WasiBundleAssemblies>
<!-- This assumes that wasmtime is available on path. Developers can set an environment variable referencing any other runner or location. -->
<WasiRunner Condition="'$(WasiRunner)' == ''">wasmtime</WasiRunner>
<CopyWasmToOutputDependsOn>
$(CopyWasmToOutputDependsOn);
ObtainWasiSdk;
PrepareBuildWasmInputs;
BuildWasm;
</CopyWasmToOutputDependsOn>
</PropertyGroup>
<PropertyGroup Condition="'$(RunCommand)' == '' AND '$(WasiRunner)' != ''">
<RunCommand>$(WasiRunner)</RunCommand>
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
<!-- For some reason neither $(OutDir) nor $(OutputPath) seem to be set-->
<RunArguments>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).wasm</RunArguments>
<!-- If you enable debugging, it will claim FD 3, so anything else that uses sock_accept needs to look for the DEBUGGER_FD env var and use FD>=4 if found -->
<RunArguments Condition="'$(WaitForDebugger)' == 'true' AND '$(WasiDebugPort)' != ''">$(RunArguments) --tcplisten 127.0.0.1:$(WasiDebugPort) --env DEBUGGER_FD=3</RunArguments>
<RunArguments Condition="'$(WasiRunnerArgs)' != ''">$(RunArguments) $(WasiRunnerArgs)</RunArguments>
</PropertyGroup>
<ItemGroup>
<WasiNativeFileReference Include="$(MSBuildThisFileDirectory)..\native\*.c" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmono-ee-interp.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmono-ilgen.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmono-wasi-driver.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmonosgen-2.0.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmono-component-hot_reload-stub-static.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmono-component-marshal-ilgen-stub-static.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libmono-component-diagnostics_tracing-stub-static.a" />
<WasiNativeFileReference Condition="'$(WaitForDebugger)' == 'true'" Include="$(WasiRuntimePackRoot)native\libmono-component-debugger-static.a" />
<WasiNativeFileReference Condition="'$(WaitForDebugger)' != 'true'" Include="$(WasiRuntimePackRoot)native\libmono-component-debugger-stub-static.a" />
<WasiNativeFileReference Include="$(WasiRuntimePackRoot)native\libSystem.Native.a" />
<UpToDateCheckInput Include="@(WasiNativeFileReference)" />
</ItemGroup>
<Target Name="ResolveWasiFrameworkReferenceAssemblies">
<!-- For any framework references, e.g., to Microsoft.AspNetCore.App, the @(ReferencePath) collection will only include
an item for its reference assembly, not its implementation assembly. We need the implementation assemblies at runtime
and even at dependency-walking time since the deps might include more than just what the implementation assemblies say.
The logic here attempts to guess the disk path to the implementation assemblies based on SDK conventions.
This is definitely NOT how things should work, and may be fragile as it relies on assumptions about the SDK layout on disk.
For a real implementation, we should create a proper wasi-wasm RID and have real runtime packs for it. Then we'd use the
same technique the Blazor SDK does to set the project RID to wasi-wasm, and then the normal build process would resolve
all the framework references to RID-specific implementations for us. -->
<PropertyGroup>
<_PathSep>/</_PathSep>
<_PathSep Condition="$([MSBuild]::IsOSPlatform('Windows'))">\</_PathSep>
</PropertyGroup>
<ItemGroup>
<_WasiResolvedFrameworkReference Include="@(ResolvedFrameworkReference)" Condition="'%(ResolvedFrameworkReference.Identity)' != 'Microsoft.NETCore.App'" />
<_WasiResolvedFrameworkReference Update="@(_WasiResolvedFrameworkReference)">
<!-- e.g., From: C:\Program Files\dotnet\packs\Microsoft.AspNetCore.App.Ref\7.0.0-preview.3.22152.6
To: C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\7.0.0-preview.3.22152.6 -->
<ImplementationPath>$([System.String]::Copy('%(TargetingPackPath)').Replace('packs$(_PathSep)%(OriginalItemSpec).Ref', 'shared$(_PathSep)%(OriginalItemSpec)'))</ImplementationPath>
</_WasiResolvedFrameworkReference>
</ItemGroup>
<PropertyGroup>
<_WasiResolvedFrameworkReferenceAssembliesPattern>@(_WasiResolvedFrameworkReference->'%(ImplementationPath)\*.dll', ';')</_WasiResolvedFrameworkReferenceAssembliesPattern>
</PropertyGroup>
<ItemGroup>
<_WasiResolvedFrameworkReferenceAssemblies Include="$(_WasiResolvedFrameworkReferenceAssembliesPattern)" />
</ItemGroup>
</Target>
<Target Name="PrepareBuildWasmInputs" DependsOnTargets="ResolveWasiFrameworkReferenceAssemblies">
<!-- First, walk the dependency chain of .NET assemblies so we get the minimal set needed to bundle -->
<ItemGroup>
<_WasiRuntimePackAssemblies Include="$(WasiRuntimePackRoot)lib\net7.0\*.dll" />
<_WasiRuntimePackAssemblies Include="@(_WasiResolvedFrameworkReferenceAssemblies)" />
<_WasmApplicationAssemblies Include="@(ReferencePath)" Condition="'%(ReferencePath.FrameworkReferenceName)' == ''" />
</ItemGroup>
<WasmResolveAssemblyDependencies EntryPoint="$(OutDir)$(TargetFileName)" ApplicationAssemblies="@(_WasmApplicationAssemblies)" WasiRuntimePackAssemblies="@(_WasiRuntimePackAssemblies)">
<Output TaskParameter="Dependencies" ItemName="_WasmTransitivelyReferencedAssemblies" />
</WasmResolveAssemblyDependencies>
<!-- Optionally, trim during the build -->
<!-- This produces a lot of messy warnings, and has no incrementalism, so should be considered extra-experimental -->
<PropertyGroup Condition="'$(WasiTrim)' == 'true' AND '$(DOTNET_HOST_PATH)' == ''">
<_DotNetHostDirectory>$(NetCoreRoot)</_DotNetHostDirectory>
<_DotNetHostFileName>dotnet</_DotNetHostFileName>
<_DotNetHostFileName Condition="'$(OS)' == 'Windows_NT'">dotnet.exe</_DotNetHostFileName>
</PropertyGroup>
<ILLink
Condition="'$(WasiTrim)' == 'true'"
AssemblyPaths="@(_WasmTransitivelyReferencedAssemblies)"
OutputDirectory="$(IntermediateOutputPath)dotnet-wasi-sdk\linked\"
RootAssemblyNames="$(OutDir)$(TargetFileName)"
TrimMode="link"
DefaultAction="copy"
SingleWarn="true"
Warn="5"
TreatWarningsAsErrors="false"
NoWarn="1701;1702;1701;1702"
RemoveSymbols="true"
ToolExe="$(_DotNetHostFileName)"
ToolPath="$(_DotNetHostDirectory)" />
<ItemGroup Condition="'$(WasiTrim)' == 'true'">
<_WasmTransitivelyReferencedAssemblies Remove="@(_WasmTransitivelyReferencedAssemblies)" />
<_WasmTransitivelyReferencedAssemblies Include="$(IntermediateOutputPath)dotnet-wasi-sdk\linked\*.dll" />
</ItemGroup>
<!-- Make a list of any corresponding .pdb files we can find -->
<ItemGroup>
<_WasmTransitivelyReferencedPdbs
Include="@(_WasmTransitivelyReferencedAssemblies -> '%(RelativeDir)%(Filename).pdb')"
Condition="Exists('%(RelativeDir)%(Filename).pdb')" />
</ItemGroup>
<!-- Now we can populate the list of files to bundle and any other WASM build inputs -->
<PropertyGroup>
<WasmOutputIntermediateDir>$(IntermediateOutputPath)dotnet-wasi-sdk\</WasmOutputIntermediateDir>
<WasmOutputIntermediateFile>$(WasmOutputIntermediateDir)$(AssemblyName).wasm</WasmOutputIntermediateFile>
</PropertyGroup>
<ItemGroup>
<WasmBundleFiles Condition="'$(WasiBundleAssemblies)' == 'true'" Include="@(_WasmTransitivelyReferencedAssemblies)" WasmRole="assembly" />
<WasmBundleFiles Condition="'$(WasiBundleAssemblies)' == 'true' AND '$(WaitForDebugger)' == 'true'" Include="@(_WasmTransitivelyReferencedPdbs)" WasmRole="assembly" />
<BuildWasmInputs Include="@(WasiNativeFileReference)" />
<BuildWasmInputs Include="@(WasmBundleFiles)" />
<BuildWasmInputs Include="@(IntermediateAssembly)" />
<UpToDateCheckOutput Include="$(WasmOutputIntermediateFile)" />
</ItemGroup>
</Target>
<Target Name="GenerateWasmBundleSources">
<PropertyGroup>
<_WasmBundleObjectsIntermediateDir>$(WasmOutputIntermediateDir)bundle-objects\</_WasmBundleObjectsIntermediateDir>
<_GetBundledFileSourcePath>$(_WasmBundleObjectsIntermediateDir)dotnet_wasi_getbundledfile.c</_GetBundledFileSourcePath>
</PropertyGroup>
<!-- Get the file hashes of everything in @(WasmBundleFiles), then pass it all to EmitWasmBundleObjectFile. This
will emit corresponding .o files for anything we don't already have on disk. -->
<GetFileHash Files="@(WasmBundleFiles)">
<Output TaskParameter="Items" ItemName="WasmBundleFilesWithHashes" />
</GetFileHash>
<ItemGroup>
<WasmBundleFilesWithHashes Update="@(WasmBundleFilesWithHashes)">
<ObjectFile>$(_WasmBundleObjectsIntermediateDir)%(WasmBundleFilesWithHashes.Filename)%(WasmBundleFilesWithHashes.Extension).$([System.String]::Copy(%(WasmBundleFilesWithHashes.FileHash)).Substring(0, 8)).o</ObjectFile>
</WasmBundleFilesWithHashes>
</ItemGroup>
<EmitWasmBundleObjectFile FilesToBundle="@(WasmBundleFilesWithHashes)" ClangExecutable="$(WasiClang)">
<Output TaskParameter="BundleApiSourceCode" ItemName="_WasiBundleApiSourceCode" />
</EmitWasmBundleObjectFile>
<!-- Write out the .c source code of a file that knows about all the bundled files and can supply them at runtime.
Also include this, and the bundle object files, in the set of files to compile. -->
<WriteLinesToFile File="$(_GetBundledFileSourcePath)"
Overwrite="true"
Lines="@(_WasiBundleApiSourceCode)"
WriteOnlyWhenDifferent="true" />
<ItemGroup>
<WasiNativeFileReference Include="$(_GetBundledFileSourcePath)" />
<WasiNativeFileReference Include="%(WasmBundleFilesWithHashes.ObjectFile)" />
</ItemGroup>
<!-- Clean up the bundle-objects dir - remove anything we no longer need -->
<ItemGroup>
<WasmBundleFileToDelete Include="$(_WasmBundleObjectsIntermediateDir)*.o" />
<WasmBundleFileToDelete Remove="%(WasmBundleFilesWithHashes.ObjectFile)" />
</ItemGroup>
<Delete Files="@(WasmBundleFileToDelete)" />
</Target>
<Target Name="BuildWasm" Inputs="@(BuildWasmInputs)" Outputs="$(WasmOutputIntermediateFile)" DependsOnTargets="GenerateWasmBundleSources">
<!-- Generate a file entrypoint_YourAssemblyName.c containing the dotnet_wasi_getentrypointassemblyname symbol.
This means we don't have to hardcode the assembly name in main.c -->
<PropertyGroup>
<WasiGetEntrypointCFile>$(WasmOutputIntermediateDir)entrypoint_$(AssemblyName).c</WasiGetEntrypointCFile>
</PropertyGroup>
<WriteLinesToFile File="$(WasiGetEntrypointCFile)"
Overwrite="true"
Lines="const char* dotnet_wasi_getentrypointassemblyname() { return "$(TargetFileName)"%3B }"
WriteOnlyWhenDifferent="true" />
<ItemGroup>
<WasiNativeFileReference Include="$(WasiGetEntrypointCFile)" />
<FileWrites Include="$(WasiGetEntrypointCFile)" />
<WasiAfterRuntimeLoadedDeclarations Include="@(WasiAfterRuntimeLoaded->'void %(Identity)();')" />
<WasiAfterRuntimeLoadedCalls Include="@(WasiAfterRuntimeLoaded->'%(Identity)();')" />
</ItemGroup>
<!-- Invoke the WASI SDK clang binary to build the .wasm file -->
<PropertyGroup>
<WasiSdkClangArgs>@(WasiNativeFileReference, ' ')</WasiSdkClangArgs>
<WasiSdkClangArgs>$(WasiSdkClangArgs) --sysroot="$(WasiSdkRoot)\share\wasi-sysroot"</WasiSdkClangArgs>
<WasiSdkClangArgs>$(WasiSdkClangArgs) -I"$(WasiRuntimePackRoot)\native\include"</WasiSdkClangArgs>
<WasiSdkClangArgs>$(WasiSdkClangArgs) -Wl,--export=malloc,--export=free,--export=__heap_base,--export=__data_end</WasiSdkClangArgs>
<WasiSdkClangArgs>$(WasiSdkClangArgs) -Wl,-z,stack-size=1048576,--initial-memory=52428800,--max-memory=524288000,-lwasi-emulated-mman</WasiSdkClangArgs>
<WasiSdkClangArgs>$(WasiSdkClangArgs) -Wl,-s</WasiSdkClangArgs> <!-- Strip debug symbols -->
<WasiSdkClangArgs Condition="'@(WasiAfterRuntimeLoadedDeclarations)' != ''">$(WasiSdkClangArgs) -D WASI_AFTER_RUNTIME_LOADED_DECLARATIONS="@(WasiAfterRuntimeLoadedDeclarations, ' ')"</WasiSdkClangArgs>
<WasiSdkClangArgs Condition="'@(WasiAfterRuntimeLoadedCalls)' != ''">$(WasiSdkClangArgs) -D WASI_AFTER_RUNTIME_LOADED_CALLS="@(WasiAfterRuntimeLoadedCalls, ' ')"</WasiSdkClangArgs>
<WasiSdkClangArgs>$(WasiSdkClangArgs) -o "$(WasmOutputIntermediateFile)"</WasiSdkClangArgs>
</PropertyGroup>
<MakeDir Directories="$(WasmOutputIntermediateDir)" />
<Message Importance="normal" Text="Performing WASI SDK build: "$(WasiClang)" $(WasiSdkClangArgs)" />
<Exec Command=""$(WasiClang)" $(WasiSdkClangArgs)" />
<ItemGroup>
<FileWrites Include="$(WasmOutputIntermediateFile)" />
</ItemGroup>
</Target>
<Target Name="CopyWasmToOutput" AfterTargets="Build" DependsOnTargets="$(CopyWasmToOutputDependsOn)">
<Copy SourceFiles="$(WasmOutputIntermediateFile)"
SkipUnchangedFiles="true"
DestinationFolder="$(OutDir)">
<Output TaskParameter="CopiedFiles" ItemName="WasiSdkBinOutputFiles" />
</Copy>
<Copy Condition="'$(WasiBundleAssemblies)' != 'true'"
SourceFiles="@(_WasmTransitivelyReferencedAssemblies)"
DestinationFolder="$(OutDir)" />
<Message Importance="high" Text="$(AssemblyName) -> @(WasiSdkBinOutputFiles->'$([System.IO.Path]::GetFullPath('%(WasiSdkBinOutputFiles.Identity)'))')" />
<ItemGroup>
<FileWrites Include="@(WasiSdkBinOutputFiles)" />
</ItemGroup>
</Target>
<Target Name="ObtainWasiSdk" Condition="!(Exists($(WasiClang)))">
<PropertyGroup>
<WasiSdkDownloadTempDir>$(IntermediateOutputPath)\wasi-sdk-temp</WasiSdkDownloadTempDir>
</PropertyGroup>
<MakeDir Directories="$(WasiSdkDownloadTempDir)" />
<DownloadFile
SourceUrl="$(WasiSdkUrl)"
DestinationFolder="$(WasiSdkDownloadTempDir)">
<Output TaskParameter="DownloadedFile" ItemName="WasiSdkDownloadTempFile" />
</DownloadFile>
<!-- Windows 10+ has tar built in, so this should work cross-platform -->
<Message Importance="high" Text="Extracting @(WasiSdkDownloadTempFile) to $(WasiSdkRoot)..." />
<MakeDir Directories="$(WasiSdkRoot)" />
<Exec Command="tar -xf "@(WasiSdkDownloadTempFile)" -C . --strip-components=1" WorkingDirectory="$(WasiSdkRoot)" />
<RemoveDir Directories="$(WasiSdkDownloadTempDir)" />
</Target>
</Project>