Yocto: Cannot build Rust target, missing

I have a Rust application that generates a number of bindings to a custom Linux kernel device driver via bindgen. The application builds and runs correctly under Ubuntu.

The application needs to run on custom embedded hardware which uses a Linux kernel built using Yocto.

I have used cargo bitbake to generate a recipe for my application and I have added it to a custom **Yocto **layer. When I try and build my application the compilation fails because bitbake fails to locate libclang

The error is as follows:

|   --- stderr
|   thread 'main' panicked at 'Unable to find libclang: "couldn't find any valid shared libraries matching: ['libclang.so', 'libclang-*.so', 'libclang.so.*', 'libclang-*.so.*'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/corei7-64-poky-linux/demo-driver/0.1.0.AUTOINC+a8bbb460f8-r0/cargo_home/bitbake/bindgen-0.59.2/src/lib.rs:2144:31
|   stack backtrace:
|      0: rust_begin_unwind
|      1: core::panicking::panic_fmt
|      2: core::result::unwrap_failed
|      3: core::result::Result<T,E>::expect
|      4: core::ops::function::FnOnce::call_once
|      5: lazy_static::lazy::Lazy<T>::get::{{closure}}
|      6: std::sync::once::Once::call_once::{{closure}}
|      7: std::sync::once::Once::call_inner
|      8: std::sync::once::Once::call_once
|      9: <bindgen::ensure_libclang_is_loaded::LIBCLANG as core::ops::deref::Deref>::deref
|     10: bindgen::ensure_libclang_is_loaded
|     11: bindgen::Bindings::generate
|     12: bindgen::Builder::generate
|     13: build_script_build::main
|     14: core::ops::function::FnOnce::call_once
|   note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
| warning: build failed, waiting for other jobs to finish...
|     Building [========================>  ] 90/95: clap
| warning: `clap` (lib) generated 2 warnings (2 duplicates)
| error: build failed
| WARNING: exit code 101 from a shell command.

Can anyone advise on how I should update my bitbake recipe so that libclang.so is build and available?

I think you need to install libclang to actually have that shared object file. I think it'd be apt install libclang-dev.

This is a Yocto build - there is no "apt".

Yocto builds the complete OS including any toolchains via the "bitbake" command. In the case of Rust it will invoke cargo after pulling & building the required components.

Welp, sorry. Should have paid more attention.
I have no clue about Yocto, sorry. Someone else might be able to help though.

@RedDocMD - No worries - it is a bit of a specialised question - and could be more of a Yocto issue -

Look into how people add clang to their recipes as a C compiler. That should install libclang and friends.

I added the meta-clang layer to my bblayers.conf file and modified the recipe to include:

DEPENDS += " clang"

when I re-ran bitbake it downloaded and built clang but eventually still failed with etc same error.

Searing in the build directory I can now see that libclang.so has been build:

[build, develop+3]: find . -name "libclang*.so"
./tmp/sysroots-components/x86_64/clang-native/usr/lib/libclang-cpp.so
./tmp/sysroots-components/x86_64/clang-native/usr/lib/libclang.so
./tmp/sysroots-components/corei7-64/clang/usr/lib/libclang-cpp.so
./tmp/sysroots-components/corei7-64/clang/usr/lib/libclang.so
./tmp/work-shared/llvm-project-source-14.0.3-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-fuchsia/libclang_rt.scudo.so
./tmp/work-shared/llvm-project-source-14.0.3-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-fuchsia/libclang_rt.asan.so
./tmp/work-shared/llvm-project-source-14.0.3-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-fuchsia/libclang_rt.scudo.so
./tmp/work-shared/llvm-project-source-14.0.3-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-fuchsia/libclang_rt.asan.so
./tmp/work-shared/llvm-project-source-14.0.3-r0/git/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.so
./tmp/work-shared/llvm-project-source-14.0.3-r0/git/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.so
./tmp/work/corei7-64-poky-linux/demo-driver/0.1.0.AUTOINC+a8bbb460f8-r0/recipe-sysroot/usr/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/demo-driver/0.1.0.AUTOINC+a8bbb460f8-r0/recipe-sysroot/usr/lib/libclang.so
./tmp/work/corei7-64-poky-linux/llvm/13.0.1-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-fuchsia/libclang_rt.scudo.so
./tmp/work/corei7-64-poky-linux/llvm/13.0.1-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-fuchsia/libclang_rt.asan.so
./tmp/work/corei7-64-poky-linux/llvm/13.0.1-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-fuchsia/libclang_rt.scudo.so
./tmp/work/corei7-64-poky-linux/llvm/13.0.1-r0/git/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/x86_64-unknown-fuchsia/libclang_rt.asan.so
./tmp/work/corei7-64-poky-linux/llvm/13.0.1-r0/git/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mips-r2-hard-musl/lib/linux/libclang_rt.builtins-mips.so
./tmp/work/corei7-64-poky-linux/llvm/13.0.1-r0/git/clang/test/Driver/Inputs/mips_mti_linux/lib/clang/3.8.0/mipsel-r2-hard-musl/lib/linux/libclang_rt.builtins-mipsel.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/sysroot-destdir/usr/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/sysroot-destdir/usr/lib/libclang.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/packages-split/clang-dev/usr/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/packages-split/clang-dev/usr/lib/libclang.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/build/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/build/lib/libclang.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/image/usr/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/image/usr/lib/libclang.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/package/usr/lib/libclang-cpp.so
./tmp/work/corei7-64-poky-linux/clang/14.0.3-r0/package/usr/lib/libclang.so
./tmp/work/x86_64-linux/clang-native/14.0.3-r0/sysroot-destdir/mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/x86_64-linux/clang-native/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang-cpp.so
./tmp/work/x86_64-linux/clang-native/14.0.3-r0/sysroot-destdir/mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/x86_64-linux/clang-native/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang.so
./tmp/work/x86_64-linux/clang-native/14.0.3-r0/build/lib/libclang-cpp.so
./tmp/work/x86_64-linux/clang-native/14.0.3-r0/build/lib/libclang.so
./tmp/work/x86_64-linux/clang-native/14.0.3-r0/image/mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/x86_64-linux/clang-native/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang-cpp.so
./tmp/work/x86_64-linux/clang-native/14.0.3-r0/image/mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/x86_64-linux/clang-native/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang.so
./tmp/work/x86_64-linux/clang-cross-x86_64/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang-cpp.so
./tmp/work/x86_64-linux/clang-cross-x86_64/14.0.3-r0/recipe-sysroot-native/usr/lib/libclang.so

So it now looks like cargo is not finding it when it tries to build my Rust application:

 Caused by:
|   process didn't exit successfully: `/mnt/data-001/ahk-dev/Views/View01/
   ngh-yocto-nuc/build/tmp/work/corei7-64-poky-linux/
  demo-driver/0.1.0.AUTOINC+a8bbb460f8-r0/build/target/
  release/build/ngh_dummy_driver_if-ca354be690695b41/build-script-build`
   (exit status: 101)
|   --- stderr
|   thread 'main' panicked at 'Unable to find libclang: 
   "couldn't find any valid shared libraries matching: ['libclang.so', 'libclang-*.so',
    'libclang.so.*', 'libclang-*.so.*'], set the `LIBCLANG_PATH` environment variable to a 
    path where one of these files can be found (invalid: [])"',
    /mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/
    corei7-64-poky-linux/demo-driver/0.1.0.AUTOINC+a8bbb460f8-r0/
   cargo_home/bitbake/bindgen-0.59.2/src/lib.rs:2144:31
|   stack backtrace:

Does anyone know how to configure my recipe such that LIBCLANG_PATH is set correctly to one of the versions of libclang.so which have been built by bitbake?

I have added the following to the recipe:

export LIBCLANG_PATH = "${WORKDIR}/recipe-sysroot/${libdir}"

Although that is a directory which contains libclang.so the build still fails with the following:

thread 'main' panicked at 'Unable to find libclang: "the `libclang` shared library at 
    /mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/corei7-64-poky-linux/
    demo-driver/0.1.0.AUTOINC+a8bbb460f8-r0/recipe-sysroot//usr/lib/libclang.so.14.0.3
    could not be opened: 
    libncurses.so.5: cannot open shared object file: No such file or directory"', 
    /mnt/data-001/ahk-dev/Views/View01/ngh-yocto-nuc/build/tmp/work/corei7-64-poky-linux/
    demo-  driver/0.1.0.AUTOINC+a8bbb460f8-r0/cargo_home/bitbake/bindgen-0.59.2/src/lib.rs:2144:31

This means that libclang.so is coming from
${WORKDIR}/recipe-sysroot/usr/lib

I have found libncurses.so.5 is available in ${WORKDIR}/recipe-sysroot/lib, if I manually create a link for the missing library in ${WORKDIR}/recipe-sysroot/lib to ${WORKDIR}/recipe-sysroot/usr/lib the build continues completes successfully.

I thought I could simply modify LIBCLANG_PATH to include the second location , i.e.:

export LIBCLANG_PATH = "${WORKDIR}/recipe-sysroot/${libdir};${WORKDIR}/recipe-sysroot/lib"

But this results in the the original error.

Is there a way to either:

Set `LIBCLANG_PATH` so that both directories are searched

or

Configure the build so that all dependencies are written to the same directory