Reputation: 202
I am trying to compile a C++ library to wasm32 wasi for use inside my rust application. However I am running into this issue.
Error: failed to run main module `target/wasm32-wasi/release/so.wasm`
Caused by:
0: failed to instantiate "target/wasm32-wasi/release/so.wasm"
1: unknown import: `env::_ZdlPv` has not been defined
This error relates to line 5 in my mylib.cpp. Which just declares a variable
#include "OpenXLSX/OpenXLSX.hpp"
extern "C" int test() {
std::string i = "";
OpenXLSX::XLXmlData s;
return 0;
}
my main.rs
#[link(name = "mylib")]
extern "C" {
pub fn test() -> i32;
}
pub fn main() {
let res = unsafe { test() };
println!("test code: {}", res);
}
and my build.rs, where I assume the error is
use std::env;
fn main() {
cc::Build::new()
.cpp_link_stdlib(None)
.cpp(true)
.flag("-std=c++17")
.archiver("llvm-ar")
.include("OpenXLSX/external/pugixml")
.include("OpenXLSX/external/nowide")
.include("OpenXLSX/external/zippy")
.include("OpenXLSX/headers")
.include("OpenXLSX")
.flag("--sysroot=/opt/wasi-sysroot")
.flag("-fvisibility=default")
.file("OpenXLSX/sources/XLCell.cpp")
.file("OpenXLSX/sources/XLCellIterator.cpp")
.file("OpenXLSX/sources/XLCellRange.cpp")
.file("OpenXLSX/sources/XLCellReference.cpp")
.file("OpenXLSX/sources/XLCellValue.cpp")
.file("OpenXLSX/sources/XLColor.cpp")
.file("OpenXLSX/sources/XLColumn.cpp")
.file("OpenXLSX/sources/XLContentTypes.cpp")
.file("OpenXLSX/sources/XLDateTime.cpp")
.file("OpenXLSX/sources/XLDocument.cpp")
.file("OpenXLSX/sources/XLFormula.cpp")
.file("OpenXLSX/sources/XLProperties.cpp")
.file("OpenXLSX/sources/XLRelationships.cpp")
.file("OpenXLSX/sources/XLRow.cpp")
.file("OpenXLSX/sources/XLRowData.cpp")
.file("OpenXLSX/sources/XLSharedStrings.cpp")
.file("OpenXLSX/sources/XLSheet.cpp")
.file("OpenXLSX/sources/XLWorkbook.cpp")
.file("OpenXLSX/sources/XLXmlData.cpp")
.file("OpenXLSX/sources/XLXmlFile.cpp")
.file("OpenXLSX/sources/XLZipArchive.cpp")
.file("OpenXLSX/external/pugixml/pugixml.cpp")
.compile("OpenXLSX");
cc::Build::new()
.archiver("llvm-ar")
.cpp_link_stdlib(None)
.cpp(true)
.flag("-fvisibility=default")
.flag("-std=c++17")
.include("OpenXLSX/external/pugixml")
.include("OpenXLSX/headers")
.include("OpenXLSX")
.flag("--sysroot=/opt/wasi-sysroot")
.file("mylib.cpp")
.compile("libmylib.a");
}
In a separate attempt, Instead of step 1 in my build.rs where I try to link the OpenXLSX files, I have also used cmake to generate a single.a file compiled for wasm32-wasi with wasi sysroot, that I tried loading.
let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
println!("cargo:rustc-link-lib=static=OpenXLSX");
println!("cargo:rustc-link-search=native={}/wasm-libs", src_dir);
And I tried to generate the bindings with Bindgen, it gave me duplicate definition errors. Which is the main reason I am writing my code in a c++ function and trying to call that from rust. I assume there would still be a linking issue,even if I get bindgen to work.
Upvotes: 1
Views: 825
Reputation: 276
In short, your c++ code is using operator delete(void*)
but you are not linking the c++ standard library that usually provides the implementation for it.
In a bit more detail:
_ZdlPv
is the mangled name of operator delete(void*)
. That's the standard C++ delete
operator that's used to free objects allocated on the heap with new
. Check this SO answer. You can also check the name on Demangler.com.OpenXLSX::XLXmlData s;
you are creating an XLXmlData instance. XLXmlData has a std::unique_ptr as a member. So, when a XLXmlData
object goes out of scope (at the end of test()
) its destructor ~XLXmlData()
is called and in it, the compiler generates code to clean-up all members, including the unique_ptr. This code, contains a call to the delete
operator.XLXmlData
to see what code gets generated. The call to delete
is on line 38.delete
is a C++ keyword, under the hood, the compiler emits just a regular function call (under the mangled _ZdlPv
name, as we already saw), so something needs to provide the implementation for that symbol. This "something" typically is the C++ standard library.build.rs
passes None
to .cpp_link_stdlib()
. According to the docs this disables automatic linking, so the linker will not look for the implementation of delete
in the standard library. As nothing else implements delete
, this ultimately leads to the unknown import
error you are seeing.To recap, you should link with the standard library. A lot of C++ stuff simply will not work without it.
Upvotes: 1