Skip to content

Commit 24d7eb9

Browse files
Merge pull request #221 from jsturtevant/update-csharp-docs
Update docs to use latest componentize-dotnet
2 parents 7fa0d98 + f729880 commit 24d7eb9

File tree

1 file changed

+53
-95
lines changed
  • component-model/src/language-support

1 file changed

+53
-95
lines changed

component-model/src/language-support/csharp.md

Lines changed: 53 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2121
Once 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
2526
cd 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-
6629
Next, create or download the WIT world you would like to target. For this example we will use an
6730
[`example`
6831
world](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
8965
provide 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
9369
namespace 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:
10783
dotnet 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

138114
If you peek at the bindings, you'll notice that we now implement a class for the `add` interface
139115
rather 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
143119
namespace ExampleWorld.wit.exports.example.component;
@@ -157,12 +133,12 @@ Once again, compile an application to a Wasm component using `dotnet build`:
157133
$ dotnet build
158134
Restore complete (0.4s)
159135
You 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

162138
Build 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
172148
the `adder` library component we just built.
173149

174150
Now 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
179157
cd 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-
220160
Copy 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.
256196
using HostappWorld.wit.imports.example.component;
257197

258-
var left = 1;
259-
var right = 2;
198+
uint left = 1;
199+
uint right = 2;
260200
var result = AddInterop.Add(left, right);
261201
Console.WriteLine($"{left} + {right} = {result}");
262202
```
@@ -282,12 +222,30 @@ world, it needs to be composed the first component. You can compose your `host-a
282222
your `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+
288244
Then you can run the composed component:
289245

290246
```sh
291-
wasmtime run main.wasm
247+
wasmtime run ./dist/main.wasm
292248
1 + 2 = 3
293249
```
250+
251+
Checkout the [componentize-dotnet docs](https://github.com/bytecodealliance/componentize-dotnet) for more configurations options.

0 commit comments

Comments
 (0)