The compiled code has no functions
hello, I'm learning Rust from Java, I'm interested in Rust, and recently I had a difficulty compiling to wasm using Rust+ffmpeg hybrid, bindgen couldn't generate the ffi function I needed. ffmpeg code location: The "tripartite/ffmpeg" folder in the project project directory. Versions of bindgen I have tried :0.69.5, 0.70.1.
Compile command: cargo build --release --target wasm32-unknown-unknown
System environment:
bindgen version: 0.69.5 - 0.70.1
OS: MacOs Sonoma Version 14.5
Rust edition : "2021"
Rustc Version: rustc 1.82.0 (f6e511eec 2024-10-15)
Cargo Version: cargo 1.82.0 (8f40fc59f 2024-08-21)
CPU: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
emsdk: The *recommended* precompiled SDK download is 3.1.72 (7a360458327cd24c2a7aab428bdbcb5bca8810e4).
To install/activate it use:
latest
This is equivalent to installing/activating:
3.1.72 INSTALLED
emcc Version: emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.72 (437140d149d9c977ffc8b09dbaf9b0f5a02db190)
clang Version:
Apple clang version 16.0.0 (clang-1600.0.26.4)
Target: x86_64-apple-darwin23.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
This is an error message
error[E0425]: cannot find function `avformat_alloc_context` in this scope
--> src/lib.rs:26:56
|
26 | let mut format_context: *mut AVFormatContext = avformat_alloc_context();
| ^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `av_malloc` in this scope
--> src/lib.rs:33:22
|
33 | let buffer = av_malloc(buffer_size) as *mut u8;
| ^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `avformat_free_context` in this scope
--> src/lib.rs:35:13
|
35 | avformat_free_context(format_context);
| ^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `format_context`
error[E0425]: cannot find function `avio_alloc_context` in this scope
--> src/lib.rs:56:26
|
56 | let io_context = avio_alloc_context(
| ^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `av_free` in this scope
--> src/lib.rs:67:13
|
67 | av_free(buffer as *mut std::os::raw::c_void);
| ^^^^^^^ not found in this scope
error[E0425]: cannot find function `avformat_free_context` in this scope
--> src/lib.rs:68:13
|
68 | avformat_free_context(format_context);
| ^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `format_context`
error[E0425]: cannot find function `avformat_open_input` in this scope
--> src/lib.rs:75:12
|
75 | if avformat_open_input(&mut format_context, ptr::null_mut(), ptr::null_mut(), ptr::null_mut()) < 0 {
| ^^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `avformat_free_context` in this scope
--> src/lib.rs:77:13
|
77 | avformat_free_context(format_context);
| ^^^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `format_context`
error[E0425]: cannot find function `avformat_find_stream_info` in this scope
--> src/lib.rs:82:12
|
82 | if avformat_find_stream_info(format_context, ptr::null_mut()) < 0 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `avformat_close_input` in this scope
--> src/lib.rs:84:13
|
84 | avformat_close_input(&mut format_context);
| ^^^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `avformat_close_input` in this scope
--> src/lib.rs:101:13
|
101 | avformat_close_input(&mut format_context);
| ^^^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `avformat_close_input` in this scope
--> src/lib.rs:114:9
|
114 | avformat_close_input(&mut format_context);
| ^^^^^^^^^^^^^^^^^^^^ not found in this scope
error[E0425]: cannot find function `av_free` in this scope
--> src/lib.rs:153:5
|
153 | av_free((*io_context).buffer as *mut c_void);
| ^^^^^^^ not found in this scope
error[E0425]: cannot find function `av_free` in this scope
--> src/lib.rs:154:5
|
154 | av_free(io_context as *mut c_void);
| ^^^^^^^ not found in this scope
This is the project code:video_metadata_wasm.zip
help me,Please!
Thanks for reaching out! To help you effectively, I need more specific details. Could you provide a minimal reproducible example? Reviewing code in a zip files isn't feasible for me to debug efficiently.
This is likely to be wasm function visibility defaulting to hidden. You need to build with -fvisibility=default
Thanks for reaching out! To help you effectively, I need more specific details. Could you provide a minimal reproducible example? Reviewing code in a zip files isn't feasible for me to debug efficiently.
OK,what do I need to do?
I compiled ffmpeg as a static library by following the command, I copied the header file, and lib into my project directory still without exporting functions
./configure --prefix=/usr/local/ffmpeg \
--enable-gpl \
--enable-version3 \
--enable-nonfree \
--enable-postproc \
--enable-libass \
--enable-libfdk-aac \
--enable-libfreetype \
--enable-libmp3lame \
--enable-libopencore-amrnb \
--enable-libopencore-amrwb \
--enable-libopenjpeg \
--enable-openssl \
--enable-libopus \
--enable-libspeex \
--enable-libtheora \
--enable-libvorbis \
--enable-libvpx \
--enable-libx264 \
--enable-libxvid \
--enable-static \
--enable-shared
This is likely to be wasm function visibility defaulting to hidden. You need to build with -fvisibility=default
I used the following command to compile and there was an error
./configure --prefix=/usr/local/wasm32/ffmpeg \
--cc=emcc --cxx=em++ --ar=emar --ranlib=emranlib \
--cpu=generic --enable-static --target-os=none --arch=wasm32 \
--disable-doc --disable-debug --disable-ffmpeg --disable-ffplay --disable-ffprobe \
--disable-symver --disable-everything --disable-asm --disable-inline-asm --disable-stripping \
--enable-gpl --enable-version3 --enable-nonfree --enable-cross-compile --enable-small \
--enable-parser=aac --enable-parser=h264 --enable-demuxer=h264 --enable-demuxer=mov \
--enable-demuxer=aac --enable-decoder=h264 --enable-decoder=aac --enable-avformat \
--enable-avcodec --enable-avutil --enable-swscale --enable-swresample \
--extra-cflags="-fvisibility=default" --extra-cflags="-std=c11"
Compiler lacks C11 support
If you think configure made a mistake, make sure you are using the latest version from Git. If the latest version fails, report the problem to the [email protected] mailing list or IRC #ffmpeg on irc.libera.chat. Include the log file "ffbuild/config.log" produced by configure as this will help solve the problem.
This is likely to be wasm function visibility defaulting to hidden. You need to build with -fvisibility=default
I successfully built a static library through commands, but I still did not generate functions through bindings
emconfigure ./configure \
--prefix=/usr/local/test/ffmpeg/wasm \
--cc="emcc" --cxx="em++" --ar="emar" --ranlib=emranlib \
--enable-cross-compile --target-os=none --arch=wasm32 --cpu=generic \
--disable-ffplay --disable-ffprobe --disable-asm --disable-doc --disable-devices --disable-avdevice \
--disable-indevs --disable-outdevs --disable-network --disable-w32threads --disable-pthreads \
--enable-ffmpeg --enable-static --disable-shared --enable-decoder=pcm_mulaw --enable-decoder=pcm_alaw \
--enable-decoder=adpcm_ima_smjpeg --enable-decoder=aac --enable-decoder=hevc --enable-decoder=h264 \
--enable-protocol=file --disable-stripping \
--extra-cflags="-I/Users/mac/Software/codes/emsdk/upstream/emscripten/cache/sysroot/include -fvisibility=default -std=c11" \
--extra-cxxflags="-I/Users/mac/Software/codes/emsdk/upstream/emscripten/cache/sysroot/include -fvisibility=default -std=c11" \
--extra-ldflags="-L/Users/mac/Software/codes/emsdk/upstream/emscripten/cache/sysroot/lib"
build.rs
use std::env;
fn main() {
let out_dir = env::var("OUT_DIR").expect("OUT_DIR not set");
let ffmpeg_dir_root = "tripartite/ffmpeg";
let ffmpeg_lib = format!("{ffmpeg_dir_root}/lib");
let ffmpeg_include = format!("{ffmpeg_dir_root}/include");
// Link the ffmpeg library
println!("cargo:rustc-link-search=native={ffmpeg_lib}");
println!("cargo:rustc-link-lib=static=avutil");
println!("cargo:rustc-link-lib=static=avcodec");
// println!("cargo:rustc-link-lib=static=avdevice");
println!("cargo:rustc-link-lib=static=avfilter");
println!("cargo:rustc-link-lib=static=avformat");
println!("cargo:rustc-link-lib=static=swscale");
println!("cargo:rustc-link-lib=static=swresample");
// generate file: bindings.rs
let em_sdk_sysroot = env::var("EMSDK")
.map(|home| format!("{home}/upstream/emscripten/cache/sysroot"))
.unwrap_or_else(|_| "/usr/local/emscripten".to_string());
let static_wrapper_path = format!("{out_dir}/static_fns_wrapper.c");
let wrapper_header_path = format!("{}/wrapper.h", env!("CARGO_MANIFEST_DIR"));
println!("Generating bindings...");
// println!("EMSDK_SYSROOT: {}", em_sdk_sysroot);
println!("Static wrapper path: {}", static_wrapper_path);
println!("Wrapper header path: {}", wrapper_header_path);
let bindings = bindgen::Builder::default()
.header(wrapper_header_path)
.wrap_static_fns_path(&static_wrapper_path)
.wrap_static_fns(true)
.clang_arg(format!("-I{em_sdk_sysroot}/include"))
.clang_arg(format!("-I{ffmpeg_include}"))
.clang_arg(format!("-L{ffmpeg_lib}"))
.generate_comments(true)
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(format!("{}/src/bindings.rs", env!("CARGO_MANIFEST_DIR")))
.expect("Couldn't write bindings!");
println!("Bindings and static wrapper successfully generated.");
}
I have the same issue when compiling to target wasm32-unknown-emscripten on macOS m1.
I can see that the bindings.rs that generated has a little functions compared to when compiling to other platforms.
cargo build --release --target wasm32-unknown-emscripten
Error:
error[E0425]: cannot find function `speex_preprocess_state_destroy` in crate `aec_rs_sys`
--> src/lib.rs:85:29
|
85 | aec_rs_sys::speex_preprocess_state_destroy(preprocess_state);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not found in `aec_rs_sys`
Repro:
git clone https://github.com/thewh1teagle/aec-rs -b feat/wasm
cd aec-rs
brew install emscripten cmake
rustup target add wasm32-unknown-emscripten
cargo build --release --target wasm32-unknown-emscripten -p libaec
https://github.com/thewh1teagle/aec-rs/issues/7
Update: adding the following fixed the issue:
let mut bindings = bindgen::Builder::default().header("wrapper.h");
if target.contains("wasm") {
bindings = bindings.clang_arg("-fvisibility=default");
}
It took me quite long to find this issue and quite simple fix. Is there a reason this isn't documented better or this flag added by default?