You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Referencing a project that exposes WIT bindings gives linker error #92
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-bindgen generates 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:
error: failed to encode component
Caused by:0: failed to decode world from module
1: module was not valid
2: no top-level imported function `foobar` specified
clang: error: linker command failed with exit code 1(use -v to see invocation)
Here, foobar is 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.
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.
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:
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:
Library is a C# project that is empty except for the automatically generated WIT bindings.
Component is a F# project that has a project reference to Library and can import the WIT bindings.
Driver is a C# project that has a project reference to Component, and generates the bindings in Library so that they are available to F# in Component, and also so that the proper linker arguments are set. The only code in Driver is 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#.
Activity
lukechu10 commentedon Aug 19, 2025
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
jsturtevant commentedon Aug 20, 2025
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.
lukechu10 commentedon Aug 20, 2025
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:
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#.