Closed
Description
Version of emscripten/emsdk:
I'm on macOS 14.5.
❯ emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.65-git
clang version 20.0.0git
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/emscripten/3.1.65/libexec/llvm/bin
Failing command line in full:
Consider the following project:
CMakeLists.txt
# ------------------------------------------------------------------------------
# CMAKE SETUP
# ------------------------------------------------------------------------------
cmake_minimum_required(VERSION 3.25)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE BOOL "Enable/Disable output of compile commands during generation.")
project("Wasm Side Module")
# ------------------------------------------------------------------------------
# OPTIONS
# ------------------------------------------------------------------------------
option(USE_EXCEPTIONS "Use Exceptions" ON)
option(USE_WASM_EXCEPTIONS "Use WASM Exceptions" OFF)
set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard version to compile with")
set(CMAKE_CXX_STANDARD_REQUIRED ON CACHE BOOL "Whether the C++ standard version is a requirement")
set(CMAKE_CXX_EXTENSIONS OFF CACHE BOOL "Whether compiler specific extensions are requested")
# ------------------------------------------------------------------------------
# DEPENDENCIES
# ------------------------------------------------------------------------------
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build" FORCE)
endif()
include(FetchContent)
# Need dependencies to get them
add_compile_options(
-fPIC
-flto
-fsanitize=undefined
-Werror=bad-function-cast
-Werror=cast-function-type
-fno-omit-frame-pointer
)
add_link_options(
-fPIC
-flto
-fsanitize=undefined
)
if(EMSCRIPTEN)
add_link_options(
--profiling-funcs
-sSTACK_OVERFLOW_CHECK=2
-sDYNCALLS=1
-sEXCEPTION_STACK_TRACES=1
-sSAFE_HEAP
-sASSERTIONS=2
)
endif()
if(USE_EXCEPTIONS)
add_compile_options(-fexceptions)
add_link_options(-fexceptions)
elseif(USE_WASM_EXCEPTIONS)
add_compile_options(-fwasm-exceptions)
add_link_options(-fwasm-exceptions)
endif()
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG ed8f8be70d82b0a081286e262867956e565c1bf6
)
FetchContent_MakeAvailable(
fmt
)
if(EMSCRIPTEN)
# Side module
add_executable(side_module side_module.cpp)
target_link_options(side_module PRIVATE -sSIDE_MODULE=2)
target_link_libraries(side_module PRIVATE fmt::fmt)
set_target_properties(side_module PROPERTIES
PREFIX ""
SUFFIX ".wasm"
ENABLE_EXPORTS ON
)
# Main module
add_executable(main_module main_module.cpp)
target_link_options(main_module PRIVATE
-sMAIN_MODULE=2
-sNO_AUTOLOAD_DYLIBS
$<TARGET_FILE:side_module>
)
target_link_libraries(main_module PRIVATE side_module)
set_target_properties(main_module PROPERTIES SUFFIX ".cjs")
endif()
main_module.cpp
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
{
void* handle = dlopen("side_module.wasm", RTLD_NOW);
if (!handle) {
std::cout << "failed to dlopen" << std::endl;
return 1;
}
typedef void (*func)();
func test_func = (func)dlsym(handle, "my_function");
{
const char* error = dlerror();
if (error || !test_func) {
std::cout << "Failed to load symbol err = " << error << "\n";
return 1;
}
}
std::cout << "calling test_func" << std::endl;
test_func();
return 0;
}
side_module.cpp
#include <emscripten.h>
#include <fmt/format.h>
#include <iostream>
#include <map>
#include <string_view>
class MyObject
{
struct AttributeManager
{
int create(std::string_view name)
{
std::string key(name);
auto [it, insertion_successful] = m_name_to_id.emplace(key, m_name_to_id.size());
return it->second;
}
int get_id(std::string_view name) const
{
std::string key(name);
auto it = m_name_to_id.find(key);
if (it != m_name_to_id.end()) {
return it->second;
} else {
return -1;
}
}
protected:
std::map<std::string, int> m_name_to_id;
};
AttributeManager m_manager;
public:
int get_attribute_id(std::string_view name) const
{
auto ret = m_manager.get_id(name);
if (ret == -1) {
throw std::runtime_error(fmt::format("Attribute '{}' does not exist.", name));
}
return ret;
}
int create_attribute(std::string_view name) { return m_manager.create(name); }
};
extern "C" {
EMSCRIPTEN_KEEPALIVE
void my_function()
{
MyObject foo;
int x = foo.create_attribute("foo");
int y = foo.create_attribute("bar");
std::cout << foo.get_attribute_id("foo") << std::endl;
std::cout << foo.get_attribute_id("bar") << std::endl;
}
}
Steps to reproduce:
Compile with the following:
emcmake cmake ..
cmake --build . -j 12
node main_module.cjs
Failing output:
❯ node main_module.cjs
calling test_func
Aborted(Assertion failed: bad function pointer type - dynCall function not found for sig 'iij')
/Users/jedumas/sandbox/wasm/build/main_module.cjs:638
/** @suppress {checkTypes} */ var e = new WebAssembly.RuntimeError(what);
^
RuntimeError: Aborted(Assertion failed: bad function pointer type - dynCall function not found for sig 'iij')
at abort (/Users/jedumas/sandbox/wasm/build/main_module.cjs:638:41)
at assert (/Users/jedumas/sandbox/wasm/build/main_module.cjs:370:5)
at dynCallLegacy (/Users/jedumas/sandbox/wasm/build/main_module.cjs:1268:3)
at dynCall (/Users/jedumas/sandbox/wasm/build/main_module.cjs:1297:13)
at /Users/jedumas/sandbox/wasm/build/main_module.cjs:1805:12
at stubs.<computed> (/Users/jedumas/sandbox/wasm/build/main_module.cjs:1955:20)
at side_module.wasm.legalfunc$invoke_iij (wasm://wasm/side_module.wasm-002f3df6:wasm-function[213]:0x21ab1)
at side_module.wasm.my_function (wasm://wasm/side_module.wasm-002f3df6:wasm-function[72]:0x7691)
at main_module.wasm.main (wasm://wasm/main_module.wasm-00f4246e:wasm-function[398]:0x23b11)
at callMain (/Users/jedumas/sandbox/wasm/build/main_module.cjs:6651:15)
Node.js v22.7.0
Metadata
Metadata
Assignees
Labels
No labels