Reputation: 91
I'm trying to learn how to build custom linux images with Yocto and I'm struggling to create an image with both a shared library and a program that uses it.
I started by following this tutorial and everything went ok. Then I tried to separate the program from the library in two different layers, without success.
I started with the library code:
greetings.c
#include <stdio.h>
#include <string.h>
#include "greetings.h"
void get_greeting(char * buffer) {
if(buffer == NULL) {
return;
}
char greeting[] = "Hello world from the greetings lib\n";
strcpy(buffer, greeting);
return;
}
greetings.h
void get_greeting(char * buffer);
Makefile.am
AUTOMAKE_OPTIONS = foreign
lib_LTLIBRARIES = libgreetings.la
libgreetings_la_SOURCES = greetings.c
include_HEADERS = greetings.h
libgreetings_la_CFLAGS = -Wall -Werror -fPIC
libgreetings_la_LDFLAGS = -shared
ACLOCAL_AMFLAGS = -I m4
configure.ac
AC_INIT([Greetings lib], 1.0)
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_MACRO_DIR([m4])
LT_INIT()
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
I added this code to a git repository and created a "meta-greetings" layer with the layer.conf and recipe files:
layer.conf
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-greetings"
BBFILE_PATTERN_meta-greetings = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-greetings = "6"
LAYERDEPENDS_meta-greetings = "core"
LAYERSERIES_COMPAT_meta-greetings = "thud"
IMAGE_INSTALL_append = " greetings"
recipes-greetings/greetings/greetings_0.1.bb
SUMMARY = "bitbake-layers recipe"
DESCRIPTION = "Simple helloworld lib"
DEPENDS = ""
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=96af5705d6f64a88e035781ef00e98a8"
KBRANCH = "master"
SRCREV = "1a908a8f8616af704ce71d693e88c6d4498f24c4"
SRC_URI = "git://bitbucket.org/Grifo/greetings_lib.git;branch=${KBRANCH};protocol=ssh"
S = "${WORKDIR}/git"
inherit autotools
So far so good, I added this layer to my bblayers file and proceeded to compile the final image. I run it in qemu and even got to see the files in /usr/lib:
However, there's no "libgreetings.so". I don't know if that may be the cause of the problem (still to explain) but the previously mentioned tutorial got similar results so I proceeded.
After that I did the program:
helloworld.c
#include <stdio.h>
#include "greetings.h"
int main(void) {
char greeting[40];
get_greeting(greeting);
printf("Hello world!\n");
printf("%s", greeting);
return 0;
}
Makefile.am
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = hello_world
hello_world_SOURCES = helloworld.c
hello_world_LDADD = $(libdir)/libgreetings.so
ACLOCAL_AMFLAGS = -I m4
configure.ac
AC_INIT([Hello world], 1.0)
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
Added this code to git and created a "meta-helloworld" layer with the files:
layer.conf
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-helloworld"
BBFILE_PATTERN_meta-helloworld = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-helloworld = "7"
LAYERDEPENDS_meta-helloworld = "core meta-greetings"
LAYERSERIES_COMPAT_meta-helloworld = "thud"
IMAGE_INSTALL_append = " helloworld"
recipes-helloworld/helloworld/helloworld_0.1.bb
SUMMARY = "bitbake-layers helloworld"
DESCRIPTION = "Simple helloworld program"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE;md5=96af5705d6f64a88e035781ef00e98a8"
KBRANCH = "master"
SRCREV = "6a29425473286028e85e74003f2f57ecaf766354"
SRC_URI = "git://bitbucket.org/Grifo/hello_world.git;branch=${KBRANCH};protocol=ssh"
DEPENDS = "greetings"
S = "${WORKDIR}/git"
inherit autotools
After all this I bitbaked the final image again but got the following error:
(...)
Sstate summary: Wanted 7 Found 0 Missed 7 Current 737 (0% match, 99% complete)
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
ERROR: helloworld-0.1-r0 do_compile: oe_runmake failed
ERROR: helloworld-0.1-r0 do_compile: Function failed: do_compile (log file is located at /var/tmp/workspaces/grifo/poky/build/tmp/work/armv5e-poky-linux-gnueabi/helloworld/0.1-r0/temp/log.do_compile.12040)
ERROR: Logfile of failure stored in: /var/tmp/workspaces/grifo/poky/build/tmp/work/armv5e-poky-linux-gnueabi/helloworld/0.1-r0/temp/log.do_compile.12040
Log data follows:
| DEBUG: SITE files ['endian-little', 'bit-32', 'arm-common', 'arm-32', 'common-linux', 'common-glibc', 'arm-linux', 'arm-linux-gnueabi', 'common']
| DEBUG: Executing shell function do_compile
| NOTE: make -j 8
| make: *** No rule to make target `/usr/lib/libgreetings.so', needed by `hello_world'. Stop.
| ERROR: oe_runmake failed
| WARNING: /var/tmp/workspaces/grifo/poky/build/tmp/work/armv5e-poky-linux-gnueabi/helloworld/0.1-r0/temp/run.do_compile.12040:1 exit 1 from 'exit 1'
| ERROR: Function failed: do_compile (log file is located at /var/tmp/workspaces/grifo/poky/build/tmp/work/armv5e-poky-linux-gnueabi/helloworld/0.1-r0/temp/log.do_compile.12040)
ERROR: Task (/var/tmp/workspaces/grifo/poky/meta-helloworld/recipes-helloworld/helloworld/helloworld_0.1.bb:do_compile) failed with exit code '1'
NOTE: Tasks Summary: Attempted 1966 tasks of which 1965 didn't need to be rerun and 1 failed.
Summary: 1 task failed:
/var/tmp/workspaces/grifo/poky/meta-helloworld/recipes-helloworld/helloworld/helloworld_0.1.bb:do_compile
Summary: There was 1 WARNING message shown.
Summary: There were 2 ERROR messages shown, returning a non-zero exit code.
I am sorry for the really long question but I felt like I need to give all the details since I don't know if the problem comes from my recipe or my autotools files.
Before I built the recipes and compile it using yocto, I first compiled and run it in my host computer using the shell and everything run fine. I compiled and make install
the greetings library (/usr/local/lib) and after that compiled the helloworld program which run without any problem.
I know that I could probably do this easily all within the same layer, however I'm trying to do it in separate layers to simulate different projects. Another requirement of mine is to use autotools instead of cmake.
Thank you in advance,
Grifo
EDIT:
I got it to work! Thank you Alexander Kanavin for pointing me in the right direction. I just had to change hello_world_LDADD = $(libdir)/libgreetings.so
to hello_world_LDADD = -lgreetings
in my helloworld's Makefile.am.
Upvotes: 5
Views: 9258
Reputation: 643
libgreetings.so is a file needed only for development and so it does not get installed to the image (unless you also install libgreetings-dev package - that's where it went).
During cross-compile, you typically specify libraries to link with like this: -lgreetings
So change hello_world_LDADD = $(libdir)/libgreetings.so
to hello_world_LDADD = -lgreetings
.
I would start with that. Typically you shouldn't hardcode them like that in the makefile, but rather 'discover' and check the library in configure.ac (e.g. using pkg-config, assuming your library installs the corresponding .pc file), and set the appropriate compiler and linker flags:
PKG_CHECK_MODULES(GREETINGS, [greetings])
Then, in Makefile.am:
hello_world_LDADD = $(GREETINGS_LIBS)
Upvotes: 5