Maruko
Maruko

Reputation: 99

Yocto / OE : recipe with CMake install a shared library .so

I need to figure out how to manage a recipe for a package based on CMake creating a very simple shared library. The goal is to provide the .so library into the Yocto build system in an atomic way, so can be used by other recipes managing application level.

This is the simple cpp code

#include <iostream>
#include "Student.h"
using namespace std;

Student::Student(string name):name(name){}

void Student::display(){
    cout << "A student with name " << this->name << endl;
}

This is kind of CMakeList.txt

cmake_minimum_required(VERSION 2.8.9)
project(directory_test)
set(CMAKE_BUILD_TYPE Release)

#Bring the headers, such as Student.h into the project
include_directories(include)

#However, the file(GLOB...) allows for wildcard additions:
file(GLOB SOURCES "*.cpp")

#Generate the shared library from the sources
add_library(testStudent SHARED ${SOURCES})

#Set the location for library installation
install(TARGETS testStudent DESTINATION lib)
install(FILES student.h DESTINATION include)

This is the recipe studentlib_0.1.bb

SUMMARY = "Cmake application - creates a library"

SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "\
            file://CMakeLists.txt \
            file://student.cpp \
            file://student.h \
        "

S = "${WORKDIR}"

inherit cmake

EXTRA_OECMAKE = ""

The problem is when I build the specific recipe studentlib

$ bitbake studentlib
...
Build Configuration:
BB_VERSION           = "1.38.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "universal"
TARGET_SYS           = "arm-poky-linux-gnueabi"
MACHINE              = "qemuarm"
DISTRO               = "poky"
DISTRO_VERSION       = "2.5.2"
TUNE_FEATURES        = "arm armv5 thumb dsp"
TARGET_FPU           = "soft"
    ...
NOTE: Executing RunQueue Tasks
ERROR: studentlib-0.1-r0 do_package_qa: QA Issue: -dev package contains non-symlink .so: studentlib-dev path '/work/armv5e-poky-linux-gnueabi/studentlib/0.1-r0/packages-split/studentlib-dev/usr/lib/libtestStudent.so' [dev-elf]
ERROR: studentlib-0.1-r0 do_package_qa: QA run found fatal errors. Please consider fixing them.
ERROR: studentlib-0.1-r0 do_package_qa: Function failed: do_package_qa
ERROR: Logfile of failure stored in: /home/me/yocto-qemuarm-sumo/poky/build/tmp/work/armv5e-poky-linux-gnueabi/studentlib/0.1-r0/temp/log.do_package_qa.21681
ERROR: Task (/home/me/yocto-qemuarm-sumo/poky/meta-me/recipes-cmake/studentlib/studentlib_0.1.bb:do_package_qa) failed with exit code '1'

How can I solve this Issue? I can't find any example for explanation.

Thanks

Upvotes: 4

Views: 6101

Answers (2)

Mo_
Mo_

Reputation: 875

You should read the answer from qschulz to understand what's happening and why.

Still, here are my practical recommendations:

  • When you include inherit cmake, Bitbake works out of the box, if you follow the conventions, e.g.:
  • Your recipe has exactly the same file name as the TARGETS you install() in cmake. The filename sets the PN (package name) variable, which sets PROVIDES, see qschulz
  • Your Project has a version, e.g. in cmake project() statement
  • Your CMakeLists.txt sets the target's .so-version:
set_target_properties(some_target PROPERTIES 
                              VERSION ${PROJECT_VERSION}
                            SOVERSION ${PROJECT_VERSION_MAJOR})
  • You do NOT override do_install() etc. in bitbake

Upvotes: 0

qschulz
qschulz

Reputation: 1763

In Yocto, files (which are installed in ${D} either manually in do_install or by the make, cmake, autotools, etc... in e.g. do_compile) are put in a package when they match one of the regular expression (or glob, not entirely sure about that) contained in FILES_foo.

One recipe can (and usually does) provide multiple packages. So you'd have multiple FILES_foo1 with their own paths to match.

In Yocto, the file is put in the first package where one of the paths in its FILE_foo matches the file. Even if the file matches the paths of other packages, it'll ever be in only one package, the first one.

FWIW, packages are created from leftmost to rightmost in PACKAGES variable in the recipe. By default, the PACKAGES variable is ${PN}-src ${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN} (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n292).

The default FILES_* variables are defined in bitbake.conf as well, c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf. Look for everything starting with FILES_.

In there, you can see that by default, FILES_${PN} has ${libdir}/lib*${SOLIBS} (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n296) packaged. SOLIBS is, by default, .so.* (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n280), which means only dot versions of libraries are packaged in the ${PN} package (if they are not matched by another package before). FILES_${PN}-dev on the other hand packages ${FILES_SOLIBSDEV} which defaults to ${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}, with SOLIBSDEV in turns defaults to .so (c.f. http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n313, http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n314 and http://git.yoctoproject.org/cgit.cgi/poky/tree/meta/conf/bitbake.conf#n283). Please note that library filenames should all start with lib to be able to be matched by the default FILES_*.

TL;DR: By default, lib*.so.* in FILES_${PN} and lib*.so in FILES_${PN}-dev.

That's the background needed to understand what is expected in which package. The issue is that -dev package should only contain lib*.so symlinks to versioned libraries (i.e. lib*.so.*). People usually expect versioned libraries so it's easy to know which version is installed and against which version a particular software should be linked against. If the version does not matter or if the major version only matters, those will then link to the unversioned or major versioned symlinks to the versioned library. Best practice dictates that behavior.

Two possible cases, either you only provide the unversioned library in which case the solution is to version your library in your cmake or in your recipe. Then everything works out of the box. Or you have a copy of your versioned library named as an unversioned library, in which case you should delete your copy and just make a symlink to the versioned library.

If that is not an option (but please really consider it), you can try to find a way so that ${PN}-dev does not have this library. There are multiple options: add lib*.so to FILES_${PN} and either remove the ${PN}-dev from the PACKAGES, remove lib*.so from FILES_${PN}-dev, unset FILES_${PN}-dev, ...

Upvotes: 5

Related Questions