Repository navigation
Referencing a project that exposes WIT bindings gives linker error #92
Description
Activity
After some digging around, it seems like the error is because this flag is not being set for the linker:
componentize-dotnet/src/WitBindgen/build/BytecodeAlliance.Componentize.DotNet.WitBindgen.targets
Line 70 in 15a30cd
<CustomLinkerArg Include="@(WitComponentImports->Replace('\', '/')->'-Wl,--component-type,"%(Identity)"')" /> Reacted by James SturtevantIs there some combination of configurations that could make this setup work? If there is, it would be nice for this to be documented somewhere since I could not find any relevant information.
There aren't any docs or tests currently. We could probably add a test in https://github.com/bytecodealliance/componentize-dotnet/tree/main/test that demonstrates this pattern.
OK I think I've managed to find a somewhat hacky solution.
Basically create two C# projects. The first project is kept empty and the second project references the first project. In the second project, we can then use componentize-dotnet to generate the wit bindings, but we set the generated files root to be in the first project. So something like this:
<PropertyGroup> ... <WitGeneratedFilesRoot>../Library/generated/wit</WitGeneratedFilesRoot> </PropertyGroup> <ItemGroup> <PackageReference Include="BytecodeAlliance.Componentize.DotNet.Wasm.SDK" Version="0.7.0-preview*" /> <PackageReference Include="runtime.linux-x64.microsoft.dotnet.ilcompiler.llvm" Version="10.0.0-alpha.1.25162.1" /> <ProjectReference Include="../Library/Library.csproj" /> </ItemGroup>
This way, the bindings are in the first project, but since we are building the second project, the proper linker arguments are set.
This works with two C# projects but if we want to create a WASM component with F#, this doesn't work because the F# project refuses to call
wit-bindgen. So to get F# working, what we can do is create 3 projects:Libraryis a C# project that is empty except for the automatically generated WIT bindings.Componentis a F# project that has a project reference toLibraryand can import the WIT bindings.Driveris a C# project that has a project reference toComponent, and generates the bindings inLibraryso that they are available to F# inComponent, and also so that the proper linker arguments are set. The only code inDriveris to call some "start" entry-point function in the F# project.
This approach seems to work pretty well if all we want to do is import WIT bindings, but I don't think it's possible to use this to export bindings directly from F#.
Background: I am interested in compiling F# to a WASM component. So far, I've managed to get a simple WASI "Hello, world!" program compiling and running using componentize-dotnet. For the next step, I wanted to access host bindings exposed via a WIT file. Since
wit-bindgengenerates C#, and not F# source files, it does not seem like I can do this directly from F#.What I have experimented so far is creating a new C# Project which imports the wit file, and then reference this C# project from F#. With this setup, the auto-generated host bindings seem to be accessible to F#. However, I get some kind of link error when trying to build the project:
Here,
foobaris a function that I am exposing from my wit file:This error only occurs when actually calling
HostWorld.exports.HostWorld.Foobar ()somewhere from the F# project or from the C# project.Is there some combination of configurations that could make this setup work? If there is, it would be nice for this to be documented somewhere since I could not find any relevant information.
Environment:
BytecodeAlliance.Componentize.DotNet.Wasm.SDK: 0.7.0-preview00010runtime.linux-x64.microsoft.dotnet.ilcompiler.llvm: 10.0.0-alpha.1.25162.1