rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

The compiled code has no functions

Open axzsd opened this issue 1 year ago • 9 comments

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

axzsd avatar Nov 23 '24 03:11 axzsd

This is the project code:video_metadata_wasm.zip

axzsd avatar Nov 23 '24 03:11 axzsd

help me,Please!

axzsd avatar Nov 25 '24 01:11 axzsd

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.

pvdrz avatar Nov 25 '24 02:11 pvdrz

This is likely to be wasm function visibility defaulting to hidden. You need to build with -fvisibility=default

emilio avatar Nov 25 '24 18:11 emilio

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 

axzsd avatar Nov 26 '24 06:11 axzsd

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.

axzsd avatar Nov 26 '24 07:11 axzsd

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.");
}

axzsd avatar Nov 27 '24 04:11 axzsd

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");
    }

thewh1teagle avatar Dec 08 '24 17:12 thewh1teagle

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?

ginnyTheCat avatar Mar 02 '25 02:03 ginnyTheCat