# Building a WASM shared library that does not import memory from the environment

**URL:** <https://ziggit.dev/t/building-a-wasm-shared-library-that-does-not-import-memory-from-the-environment/2240>\
**Category:** Help\
**Tags:** wasm, build-system\
**Created:** [November 21, 2023, 1:24pm UTC](https://ziggit.dev/t/building-a-wasm-shared-library-that-does-not-import-memory-from-the-environment/2240 "2023-11-21T13:24:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Corendos](https://ziggit.dev/user_avatar/ziggit.dev/corendos/32/433_2.png) [@Corendos](https://ziggit.dev/u/Corendos)\
**Post date:** [November 21, 2023, 1:24pm UTC](https://ziggit.dev/t/building-a-wasm-shared-library-that-does-not-import-memory-from-the-environment/2240/1 "2023-11-21T13:24:46Z")

</div>

Hey there 👋

I’m currently working on a project with dynamic loading of WASM code and native bindings. I used to use [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) but due to its lack of support for iOS, I decided to give [wasm3](https://github.com/wasm3/wasm3/tree/main) a go.

Unfortunately, it’s not really working as expected. My current workflow to build a loadable wasm module is to declare a shared library with `Build.addSharedLibrary(...)` and I have a very simple zig file with various `export` and `extern` functions declared.

The issue now is that the resulting wasm module, when I look at it with `wasm2wat`, contains an import from “env” of the memory. If I understand correctly, wasm3 [is not compatible to such a thing](https://github.com/wasm3/wasm3/issues/137#issuecomment-636069563).

Would anyone know if there is a workaround for that ?

I don’t really have a strong knowledge of these concepts yet and thus randomly tried to use the `export_memory` flag but that seems to be incompatible with shared libraries.

Many thanks 😄

---

<div class="post-metadata">

**Author:** ![Corendos](https://ziggit.dev/user_avatar/ziggit.dev/corendos/32/433_2.png) [@Corendos](https://ziggit.dev/u/Corendos)\
**Post date:** [November 21, 2023, 6:48pm UTC](https://ziggit.dev/t/building-a-wasm-shared-library-that-does-not-import-memory-from-the-environment/2240/2 "2023-11-21T18:48:03Z")

</div>

Finally found a way !

For potential readers, you can declare your wasm binary as such in a `build.zig` file:

```zig
const wasm_module = b.addExecutable(std.Build.ExecutableOptions{
    .name = "module",
    .optimize = optimize,
    .target = target,
    .root_source_file = .{ .path = "src/main.zig" },
});

// Allow exported symbols to actually be exported.
wasm_module.rdynamic = true;
// Avoid issue with the linker trying to find an entry point for the executable.
wasm_module.entry = .disabled;

```

---

<div class="post-metadata">

**Author:** ![kinder](https://ziggit.dev/letter_avatar_proxy/v4/letter/k/b4bc9f/32.png) [@kinder](https://ziggit.dev/u/kinder)\
**Post date:** [November 24, 2023, 2:08am UTC](https://ziggit.dev/t/building-a-wasm-shared-library-that-does-not-import-memory-from-the-environment/2240/3 "2023-11-24T02:08:31Z")

</div>

As a alternate method that I used, I have a project layout with a shared lib file which I import in multiple component files. So the exports are defined in the lib file, then exposed from the different components. Where each component must be build output as WASM (and implement the required interface). I think it demonstrates that the Zig builder gives us enough control to deal with custom situations.

My `build.zig` contains the list of names:

```zig
const export_names = [_][]const u8{
    "canonical_abi_free",
    "canonical_abi_realloc",
    "handle-http-request",
};

```

Also within the `build.zig`, each component assigns the property for symbols:

```zig
// save component
    {
        const saexe = b.addExecutable(.{
            .name = "save",
            .root_source_file = .{ .path = "src/save.zig" },
            .target = target,
            .optimize = optimize,
        });
        saexe.single_threaded = true;
        saexe.export_symbol_names = &export_names;
        saexe.addOptions("build_options", project_level);
        b.installArtifact(saexe);
    }

```

The `shared-module/lib.zig` logic that is imported by the component:

```zig
// begin exports required by C/host
comptime {
    @export(guestHttpInit, .{ .name = "handle-http-request" });
    @export(canAbiRealloc, .{ .name = "canonical_abi_realloc" });
    @export(canAbiFree, .{ .name = "canonical_abi_free" });
}

```

Finally, one of the components ‘save.zig’ that imports lib:

```zig
const sharedModuleNamespace = @import("shared-module/lib.zig");

```
