@@ -13,56 +13,19 @@ componentize-dotnet serves as a one-stop shop for .NET developers, wrapping seve
1313- [ wit-bindgen] ( https://github.com/bytecodealliance/wit-bindgen ) (WIT imports and exports)
1414- [ wasm-tools] ( https://github.com/bytecodealliance/wasm-tools ) (component conversion)
1515- [ WASI SDK] ( https://github.com/WebAssembly/wasi-sdk ) (SDK used by NativeAOT-LLVM)
16+ - [ Wac] ( https://github.com/bytecodealliance/wac ) (used to compose components)
1617
17- First, install the .NET SDK. For this walkthrough, we’ll use the [ .NET 9 SDK RC
18- 1] ( https://dotnet.microsoft.com/en-us/download/dotnet/9.0 ) . You should also have
19- [ wasmtime] ( https://wasmtime.dev/ ) installed so you can run the binary that you produce.
18+ First, install the .NET SDK. For this walkthrough, we’ll use the [ .NET 10 SDK preview] ( https://dotnet.microsoft.com/en-us/download/dotnet/10.0 ) .
19+ You should also have [ wasmtime] ( https://wasmtime.dev/ ) installed so you can run the binary that you produce.
2020
2121Once you have the .NET SDK installed, create a new project:
2222
2323``` sh
24- dotnet new classlib -o adder
24+ dotnet new install BytecodeAlliance.Componentize.DotNet.Templates
25+ dotnet new componentize.wasi.cli -o adder
2526cd adder
2627```
2728
28- The ` componentize-dotnet ` package depends on the ` NativeAOT-LLVM ` package, which resides at the
29- dotnet-experimental package source, so you will need to make sure that NuGet is configured to refer
30- to experimental packages. You can create a project-scoped NuGet configuration by running:
31-
32- ``` sh
33- dotnet new nugetconfig
34- ```
35-
36- Edit your nuget.config file to look like this:
37-
38- ``` xml
39- <?xml version =" 1.0" encoding =" utf-8" ?>
40- <configuration >
41- <packageSources >
42- <!-- To inherit the global NuGet package sources remove the <clear/> line below -->
43- <clear />
44- <add key =" dotnet-experimental" value =" https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
45- <add key =" nuget" value =" https://api.nuget.org/v3/index.json" />
46- </packageSources >
47- </configuration >
48- ```
49-
50- Now back in the console we’ll add the ` BytecodeAlliance.Componentize.DotNet.Wasm.SDK ` package:
51-
52- ``` sh
53- dotnet add package BytecodeAlliance.Componentize.DotNet.Wasm.SDK --prerelease
54- ```
55-
56- In the .csproj project file, add the following to the ` <PropertyGroup> ` :
57-
58- ``` xml
59- <RuntimeIdentifier >wasi-wasm</RuntimeIdentifier >
60- <UseAppHost >false</UseAppHost >
61- <PublishTrimmed >true</PublishTrimmed >
62- <InvariantGlobalization >true</InvariantGlobalization >
63- <SelfContained >true</SelfContained >
64- ```
65-
6629Next, create or download the WIT world you would like to target. For this example we will use an
6730[ ` example `
6831world] ( https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit )
@@ -76,23 +39,36 @@ world example {
7639}
7740```
7841
79- In the .csproj project file, add a new ` <ItemGroup> ` :
42+ In the ` adder .csproj` project file, add a new ` <ItemGroup> ` :
8043
8144``` xml
8245<ItemGroup >
8346 <Wit Update =" add.wit" World =" example" />
8447</ItemGroup >
8548```
8649
87- If you try to build the project with ` dotnet build ` , you'll get an error like "The name
50+ Since this component will only export a function dotnet considers this a library project. Let's update
51+ the ` <OutputType> ` to be a library in the ` adder.csproj ` :
52+
53+ ``` xml
54+ <OutputType >Library</OutputType >
55+ ```
56+
57+ And remove the ` Program.cs ` file:
58+
59+ ``` bash
60+ rm Program.cs
61+ ```
62+
63+ At this point, if you try to build the project with ` dotnet build ` , you'll get an error like "The name
8864'ExampleWorldImpl' does not exist in the current context". This is because you've said you'll
8965provide an implementation, but haven't yet done so. To fix this, add the following code to your
90- project:
66+ project in a file called ` adder.cs ` :
9167
9268``` csharp
9369namespace ExampleWorld ;
9470
95- public class ExampleWorldImpl : IOperations
71+ public class ExampleWorldImpl : IExampleWorld
9672{
9773 public static uint Add (uint x , uint y )
9874 {
@@ -107,7 +83,7 @@ If we build it:
10783dotnet build
10884```
10985
110- The component will be available at ` bin/Debug/net9 .0/wasi-wasm/native/adder.wasm ` .
86+ The component will be available at ` bin/Debug/net10 .0/wasi-wasm/native/adder.wasm ` .
11187
11288## Building a component that exports an interface
11389
@@ -137,7 +113,7 @@ world hostapp {
137113
138114If you peek at the bindings, you'll notice that we now implement a class for the ` add ` interface
139115rather than for the ` example ` world. This is a consistent pattern. As you export more interfaces
140- from your world, you implement more classes. Our add example gets the slight update of:
116+ from your world, you implement more classes. Our ` adder.cs ` example gets the slight update of:
141117
142118``` csharp
143119namespace ExampleWorld .wit .exports .example .component ;
@@ -157,12 +133,12 @@ Once again, compile an application to a Wasm component using `dotnet build`:
157133$ dotnet build
158134Restore complete (0.4s)
159135You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy
160- adder succeeded (1.1s) → bin/Debug/net9 .0/wasi-wasm/adder.dll
136+ adder succeeded (1.1s) → bin/Debug/net10 .0/wasi-wasm/adder.dll
161137
162138Build succeeded in 2.5s
163139```
164140
165- The component will be available at ` bin/Debug/net9 .0/wasi-wasm/native/adder.wasm ` .
141+ The component will be available at ` bin/Debug/net10 .0/wasi-wasm/native/adder.wasm ` .
166142
167143## Building a component that imports an interface
168144
@@ -172,51 +148,15 @@ our `adder` component and call the `add` function. We will later compose this co
172148the ` adder ` library component we just built.
173149
174150Now we will be taking the ` adder ` component and executing it from another WebAssembly component.
175- ` dotnet new console ` creates a new project that creates an executable.
151+ ` dotnet new componentize.wasi.cli ` creates a new project that creates an executable.
152+ Back out of the current project and create a new one:
176153
177154``` sh
178- dotnet new console -o host-app
155+ cd ..
156+ dotnet new componentize.wasi.cli -o host-app
179157cd host-app
180158```
181159
182- The ` componentize-dotnet ` package depends on the ` NativeAOT-LLVM ` package, which resides at the
183- dotnet-experimental package source, so you will need to make sure that NuGet is configured to refer
184- to experimental packages. You can create a project-scoped NuGet configuration by running:
185-
186- ``` sh
187- dotnet new nugetconfig
188- ```
189-
190- Edit your nuget.config file to look like this:
191-
192- ``` xml
193- <?xml version =" 1.0" encoding =" utf-8" ?>
194- <configuration >
195- <packageSources >
196- <!-- To inherit the global NuGet package sources remove the <clear/> line below -->
197- <clear />
198- <add key =" dotnet-experimental" value =" https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json" />
199- <add key =" nuget" value =" https://api.nuget.org/v3/index.json" />
200- </packageSources >
201- </configuration >
202- ```
203-
204- Now back in the console we’ll add the ` BytecodeAlliance.Componentize.DotNet.Wasm.SDK ` package:
205-
206- ``` sh
207- dotnet add package BytecodeAlliance.Componentize.DotNet.Wasm.SDK --prerelease
208- ```
209-
210- In the .csproj project file, add the following to the ` <PropertyGroup> ` :
211-
212- ``` xml
213- <RuntimeIdentifier >wasi-wasm</RuntimeIdentifier >
214- <UseAppHost >false</UseAppHost >
215- <PublishTrimmed >true</PublishTrimmed >
216- <InvariantGlobalization >true</InvariantGlobalization >
217- <SelfContained >true</SelfContained >
218- ```
219-
220160Copy the same WIT file as before into your project:
221161
222162``` wit
@@ -236,7 +176,7 @@ world hostapp {
236176}
237177```
238178
239- Add it to your .csproj project file as a new ` ItemGroup ` :
179+ Add it to your ` host-app .csproj` project file as a new ` ItemGroup ` :
240180
241181``` xml
242182<ItemGroup >
@@ -255,8 +195,8 @@ Modify `Program.cs` to look like this:
255195// example.component refers to the package name defined in the WIT file.
256196using HostappWorld .wit .imports .example .component ;
257197
258- var left = 1 ;
259- var right = 2 ;
198+ uint left = 1 ;
199+ uint right = 2 ;
260200var result = AddInterop .Add (left , right );
261201Console .WriteLine ($" {left } + {right } = {result }" );
262202```
@@ -282,12 +222,30 @@ world, it needs to be composed the first component. You can compose your `host-a
282222your ` adder ` component by running [ ` wac plug ` ] ( https://github.com/bytecodealliance/wac ) :
283223
284224``` sh
285- wac plug bin/Debug/net9 .0/wasi-wasm/native/host-app.wasm --plug ../adder/bin/Debug/net9 .0/wasi-wasm/native/adder.wasm -o main.wasm
225+ wac plug bin/Debug/net10 .0/wasi-wasm/native/host-app.wasm --plug ../adder/bin/Debug/net10 .0/wasi-wasm/native/adder.wasm -o main.wasm
286226```
287227
228+ You can also automate the process by adding the following to your ` host-app.csproj ` :
229+
230+ ``` xml
231+ <Target Name =" ComposeWasmComponent" AfterTargets =" Publish" >
232+ <PropertyGroup >
233+ <EntrypointComponent >bin/$(Configuration)/$(TargetFramework)/wasi-wasm/native/host-app.wasm</EntrypointComponent >
234+ <DependencyComponent >../adder/bin/$(Configuration)/$(TargetFramework)/wasi-wasm/native/adder.wasm</DependencyComponent >
235+ </PropertyGroup >
236+
237+ <MakeDir Directories =" dist" />
238+ <Exec Command =" $(WacExe) plug $(EntrypointComponent) --plug $(DependencyComponent) -o dist/main.wasm" />
239+ </Target >
240+ ```
241+
242+ Run ` dotnet build ` again you will have a composed component in ` ./dist/main.wasm `
243+
288244Then you can run the composed component:
289245
290246``` sh
291- wasmtime run main.wasm
247+ wasmtime run ./dist/ main.wasm
2922481 + 2 = 3
293249```
250+
251+ Checkout the [ componentize-dotnet docs] ( https://github.com/bytecodealliance/componentize-dotnet ) for more configurations options.
0 commit comments