Search code examples
linkeryoctobitbake

How to link with a shared library installed in a custom directory by another yocto bitbake recipe


I have two bitbake recipes a.bb and b.bb

The recipe a.bb installs a shared library libABC.so in a custom path /opt/app/lib.

The recipe b.bb generates a binary that needs to link with the libABC.so. I am not able to achieve this.

  • a.bb:
do_install(){
  install -d ${D}/opt/app/lib
  install -m 0644 {WORKDIR}/dir/libABC.so ${D}/opt/app/lib
}
  • b.bb:
DEPENDS += "a"
RDEPENDS_${PN} += "a"

However, the compiler always complains about the missing library:

arm-oe-linux-gnueabi/9.3.0/ld: cannot find -lABC

If I install the libABC.so in the standard path ${libdir}, the same binary links successfully.

I have tried to use the SYSROOT_DIRS in a.bb which at least shows ./recipe-sysroot/opt/app/lib/libABC.so in the logs of b.bb but it still doesn't work.

SYSROOT_DIRS += "/opt/app/lib"

Please help to resolve this issue.


Solution

  • At first, you need to fix your a:do_install:

    do_install(){
      install -d ${D}/opt/app/lib
      install -m 0644 {WORKDIR} ${D}/opt/app/lib
               ^
               |
               (What is this ? Did you mean libABC.so ?)
    }
    

    Now, let me explain something about recipes dependencies in Yocto:

    Have in mind that DEPENDS += "a" in bitbake means, exactly, the following:

    Hey bitbake:

    1. Go build a first until you reach do_populate_sysroot which prepares /path/to/tmp/work/../a/0.1-r0/sysroot-destdir
    2. Go prepare recipe-sysroot of b with what is inside sysroot-destdir of a using b:do_prepare_sysroot task that is executed before do_configure.

    [IMPORTANT NOTE]

    If you are installing something under /opt that is itself a compile-time dependency of another recipe, in your case a, then you need to do not forget that /opt by default is not in SYSROOT_DIRS which is the variable that contains what to copy from recipe a to recipe b's recipe-sysroot folder, so make sure to add this to a.bb:

    SYSROOT_DIRS:prepend = "/opt "
    

    You already did this, so good.

    Now, recipe-sysroot is the root file system of the recipe b, so the linker ld will check libraries under recipe-sysroot, you can check this with:

    bitbake -e b | grep "^export LD="
    

    You will find something like:

    export LD="x86_64-poky-linux-ld --sysroot=/path/to/tmp/work/core2-64-poky-linux/b/0.1-r0/recipe-sysroot  "
    

    You can notice under the recipe-sysroot that there is no etc/ld.conf.d and other ld-configuration-related stuff, so we expect that the linker ld has some information to look under recipe-sysroot/{usr/lib,lib}. Don't worry, the linker knows everything based on LDFLAGS.

    Now, you need to understand that there are multiple LDFLAGS:

    • BUILD_LDFLAGS: This is used for native building for the HOST
    • TARGET_LDFLAGS: This is used for target builds for your machine
    • BUILDSDK_LDFLAGS: When building for an SDK

    So, you need to change TARGET_LDFLAGS in your b.bb recipe.

    Now, you also need to know what variable points to /path/to/b/recipe-sysroot, that is RECIPE_SYSROOT variable, so add:

    TARGET_LDFLAGS:prepend = "-L${RECIPE_SYSROOT}/opt/app/lib "