eosio::wasm_entry not creating an export
Hi, I'm trying to export another symbol besides the apply function for WASM which seems to be possible using the eosio::wasm_entry attribute.
But it doesn't work for me. The exported function is just not part of the WASM at all. Here's my example contract:
#include <eosio/eosio.hpp>
extern "C" __attribute__((eosio_wasm_entry)) void initialize() {}
extern "C" {
[[eosio::wasm_entry]] void foobarbaz() {
eosio::print("do you see me in wasm?");
}
[[eosio::wasm_entry]] void apply(uint64_t receiver, uint64_t code, uint64_t action) {
eosio::print("hello!");
}
}
When i compile it and check the WAT, it's missing:
(module
(type (;0;) (func (param i32 i32)))
(type (;1;) (func (param i32 i32 i32) (result i32)))
(type (;2;) (func (param i32)))
(type (;3;) (func))
(type (;4;) (func (param i64 i64 i64)))
(import "env" "eosio_assert" (func (;0;) (type 0)))
(import "env" "memset" (func (;1;) (type 1)))
(import "env" "prints" (func (;2;) (type 2)))
(func (;3;) (type 3)
(call 4))
(func (;4;) (type 3)
(local i32)
(i32.store offset=12
(local.tee 0
(i32.sub
(global.get 0)
(i32.const 16)))
(i32.const 0))
(i32.store offset=8196
(i32.const 0)
(local.tee 0
(i32.and
(i32.add
(i32.load
(i32.load offset=12
(local.get 0)))
(i32.const 7))
(i32.const -8))))
(i32.store offset=8192
(i32.const 0)
(local.get 0))
(i32.store offset=8204
(i32.const 0)
(memory.size)))
(func (;5;) (type 2) (param i32))
(func (;6;) (type 4) (param i64 i64 i64)
(call 3)
(call 2
(i32.const 8208))
(call 5
(i32.const 0)))
(table (;0;) 1 1 funcref)
(memory (;0;) 1)
(global (;0;) (mut i32) (i32.const 8192))
(global (;1;) i32 (i32.const 8215))
(global (;2;) i32 (i32.const 8215))
(export "apply" (func 6))
(data (;0;) (i32.const 8208) "hello!\00")
(data (;1;) (i32.const 0) "\18 \00\00"))
IIRC, you can work around this by adding __attribute__((visibility("default")))
That helped with including the function in the WASM 👍 But it's still not marked as an export.
#include <eosio/eosio.hpp>
extern "C" __attribute__((visibility("default"), eosio_wasm_entry)) void
initialize() {
eosio::print("in init!");
}
extern "C" {
[[eosio::wasm_entry]] void apply(uint64_t receiver, uint64_t code,
uint64_t action) {
eosio::print("hello!");
}
[[eosio::wasm_entry]] __attribute__((visibility("default"))) void
foobarbaz(const std::vector<char> &payload) {
eosio::print("do you see me?");
}
}
(module
(type $t0 (func (param i32)))
(type $t1 (func (param i32 i32)))
(type $t2 (func (param i32 i32 i32) (result i32)))
(type $t3 (func))
(type $t4 (func (param i64 i64 i64)))
(import "env" "prints" (func $env.prints (type $t0)))
(import "env" "eosio_assert" (func $env.eosio_assert (type $t1)))
(import "env" "memset" (func $env.memset (type $t2)))
(func $f3 (type $t3)
(call $f4))
(func $f4 (type $t3)
(local $l0 i32)
(i32.store offset=12
(local.tee $l0
(i32.sub
(global.get $g0)
(i32.const 16)))
(i32.const 0))
(i32.store offset=8196
(i32.const 0)
(local.tee $l0
(i32.and
(i32.add
(i32.load
(i32.load offset=12
(local.get $l0)))
(i32.const 7))
(i32.const -8))))
(i32.store offset=8192
(i32.const 0)
(local.get $l0))
(i32.store offset=8204
(i32.const 0)
(memory.size)))
(func $f5 (type $t0) (param $p0 i32))
(func $f6 (type $t3)
(call $f3)
(call $env.prints
(i32.const 8208))
(call $f5
(i32.const 0)))
(func $apply (type $t4) (param $p0 i64) (param $p1 i64) (param $p2 i64)
(call $f3)
(call $env.prints
(i32.const 8217))
(call $f5
(i32.const 0)))
(func $f8 (type $t0) (param $p0 i32)
(call $f3)
(call $env.prints
(i32.const 8224))
(call $f5
(i32.const 0)))
(table $T0 1 1 funcref)
(memory $M0 1)
(global $g0 (mut i32) (i32.const 8192))
(global $g1 i32 (i32.const 8239))
(global $g2 i32 (i32.const 8239))
(export "apply" (func $apply))
(data $d0 (i32.const 8208) "in init!\00")
(data $d1 (i32.const 8217) "hello!\00")
(data $d2 (i32.const 8224) "do you see me?\00")
(data $d3 (i32.const 0) "0 \00\00"))
Any other attribute I can add so it's marked as an export?
What you need isn't an attribute. It's an undocumented linker option:
eosio-ld -only-export=foobarbaz:function foobarbaz.o -o foobarbaz.wasm
This PR seems to expose it, but it was not included in the recent v1.7 release :(
I'm still getting this error on 1.7:
eosio-ld: Unknown command line argument '-only-export'. Try: 'eosio-ld -help'
eosio-ld: Did you mean '-eosio-imports'?