Where's the location of the app/binary defined in a yocto recipe? - embedded-linux

I have a following recipe which runs a said service which in turns runs an app on boot-up, but I am trying to understand where the location of the app defined which ends up in sysfs image.
Currently, the appSource binary (defined in Makefile) gets stored in /usr/bin but I'm not sure where the destination location (/usr/bin) is defined.
The following command results in
$ bitbake -e appSource | grep ^FILES_${PN}
FILES_appSource="/usr/bin/* /usr/sbin/* /usr/libexec/* /usr/lib/lib*.so.* /etc /com /var /bin/* /sbin/* /lib/*.so.* /lib/udev /usr/lib/udev /lib/udev /usr/lib/udev
Here's the recipe
inherit autotools-brokensep pkgconfig
DESCRIPTION = "A sample recipe"
LICENSE = "CLOSED"
DEPENDS = "glib-2.0"
FILESPATH =+ "${THISDIR}:"
SRC_URI = "file://appSource"
S = "${WORKDIR}/appSource""
FILES_${PN} += "${systemd_unitdir}/*"
INIT_MANAGER = "systemd"
do_install_append() {
if ${#bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then
install -d ${D}/etc/initscripts
install -d ${D}${systemd_unitdir}/system
install -m 0644 ${WORKDIR}/appService/appService.service ${D}${systemd_unitdir}/system/appService.service
install -d ${D}${systemd_unitdir}/system/multi-user.target.wants/
ln -sf ${systemd_unitdir}/system/appService.service ${D}${systemd_unitdir}/system/multi-user.target.wants/appService.service
fi
}

Here is what I find out:
You are inheriting autotools-brokensep which has the following content:
# Autotools class for recipes where separate build dir doesn't work
# Ideally we should fix software so it does work. Standard autotools supports
# this.
inherit autotools
B = "${S}"
So, it inherit autotools which has do_install with the content of:
autotools_do_install() {
oe_runmake 'DESTDIR=${D}' install
# Info dir listing isn't interesting at this point so remove it if it exists.
if [ -e "${D}${infodir}/dir" ]; then
rm -f ${D}${infodir}/dir
fi
}
So, it runs the install target of your Makefile into ${D} which is ${WORKDIR}/image.
So, I assume that your Makefile has an install target that copies the binary into /usr/bin.
For the FILES variable content, this is defined in bitbake.conf:
FILES_${PN} = "${bindir}/* ${sbindir}/* ${libexecdir}/* ${libdir}/lib*${SOLIBS} \ ...
Provide your Makefile to confirm my assumption, or I do a further research on the topic.

Related

Is there a Buildroot setting for making kernel source available to compile against?

I've been given a .zip file containing source for a proprietary kernel module. Once unzip'd, there is an install script that needs to be run. The install script untar's the actual source and builds the kernel module. It requires kernel headers to compile against.
Here is my Buildroot .mk file:
FOOCO_VERSION = 1.0
FOOCO_SOURCE = cust_kernel_drvr.zip
FOOCO_SITE = /mnt/third-party/fooco
FOOCO_SITE_METHOD = local
define FOOCO_CONFIGURE_CMDS
unzip $(#D)/$(FOOCO_SOURCE) -d $(#D)
endef
define FOOCO_BUILD_CMDS
chmod +x $(#D)/TOOLS/Linux_x64/DRIVER/install
cd $(#D)/TOOLS/Linux_x64/DRIVER; $(SHELL) ./install
rm -rf $(#D)
endef
$(eval $(generic-package))
This results in the following log output and error:
(Note: I enabled debugging that shows the start and end of each step.)
DEBUG: start | rsync | fooco
>>> fooco 1.0 Syncing from source dir /mnt/third-party/fooco
rsync -au --chmod=u=rwX,go=rX --exclude .svn --exclude .git --exclude .hg --exclude .bzr --exclude CVS /mnt/third-party/fooco/ /root/buildroot-2022.02.1/output/build/fooco-1.0
DEBUG: end | rsync | fooco
DEBUG: start | configure | fooco
>>> fooco 1.0 Configuring
unzip /root/buildroot-2022.02.1/output/build/fooco-1.0/cust_kernel_drvr.zip -d /root/buildroot-2022.02.1/output/build/fooco-1.0
Archive: /root/buildroot-2022.02.1/output/build/foofo-1.0/cust_kernel_drvr.zip
[snip]
creating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/
creating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/
inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/install
inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/cust_kernel_drvr-1.2.0.15-0.noarch.rpm
inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/cust_kernel_drvr.tar.gz
inflating: /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/license_gpl.txt
[snip]
DEBUG: end | configure | fooco
DEBUG: start | build | fooco
>>> fooco 1.0 Building
chmod +x /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/install
cd /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER; /bin/bash ./install
Extracting archive..OK!
Compiling the driver...Error: make[1]: Entering directory '/root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver'
common.mk:82: *** Kernel header files not in any of the expected locations.
common.mk:83: *** Install the appropriate kernel development package, e.g.
common.mk:84: *** kernel-devel, for building kernel modules and try again. Stop.
make[1]: Leaving directory '/root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver'
Error: unable to find driver file (fooco_cust.ko) in /root/buildroot-2022.02.1/output/build/fooco-1.0/TOOLS/Linux_x64/DRIVER/fooco_cust/src/linux/driver
rm -rf /root/buildroot-2022.02.1/output/build/fooco-1.0
DEBUG: end | build | fooco
touch: cannot touch '/root/buildroot-2022.02.1/output/build/fooco-1.0/.stamp_built': No such file or directory
make: *** [/root/buildroot-2022.02.1/output/build/fooco-1.0/.stamp_built] Error 1
package/pkg-generic.mk:289: recipe for target
'/root/buildroot-2022.02.1/output/build/fooco-1.0/.stamp_built' failed
I found that the make files that came with the kernel module are looking in several places for the kernel headers:
/lib/modules/${BUILD_KERNEL}/source \
/lib/modules/${BUILD_KERNEL}/build \
/usr/src/linux-${BUILD_KERNEL} \
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \
/usr/src/kernel-headers-${BUILD_KERNEL} \
/usr/src/kernel-source-${BUILD_KERNEL} \
/usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
/usr/src/linux \
/usr/src/kernels/${BUILD_KERNEL} \
/usr/src/kernels
Why is the kernel source not visible to this build? I thought that, since Buildroot is building the kernel as part of the overall process, the header files would be available for subsequent kernel module compiles. Am I missing a setting? I feel that I'm not understanding the Buildroot process in a basic way, even after referring to the manual many times.
I'm using Buildroot 2022.02.1 and kernel 5.15.33.
Your download/extract logic is very convoluted. You should really use something like this:
FOO_SITE = /mnt/third-party/fooco
FOO_SOURCE = cust_kernel_drvr.zip
FOO_SITE_METHOD = file
define FOO_EXTRACT_CMDS
unzip $(FOO_DLDIR)/$(FOOCO_SOURCE) -d $(#D)
endef
Regarding the build issue: it is impossible to help without studying the specific build system of this kernel module. Very likely you will need to pass some environment variables to tell the build system where your kernel source code is located, and possibly other things. But without looking at the specific details, it's impossible to help you.
You can have a look at how standard out of tree kernel modules are handled by looking at the package/pkg-kernel-module.mk code. However, that will not be directly useful to a package like yours that uses a custom installation script.
The magic was the LINUX_DIR variable which, according to Buildroot user manual:
contains the path to where the Linux kernel has been extracted and built.
I was able to patch the install script to send this variable to the make file that was looking for the kernel.

Unable to add a simple kernel-module to Yocto image

Goal
I want to add a touchscreen driver available in the linux kernel source tree to my Yocto image (The link takes you to goodix.c). I basically need to add it as a kernel module.
Solution
I follow the Incorporating Out-of-Tree Modules section of the Yocto Mega Manual. I base mine off their example kernel-module recipe, called hello-mod.
In recipe goodix-9271_0.1.bb: RPROVIDES_${PN} = "kernel-module-goodix"
In layer.conf: MACHINE_EXTRA_RDEPENDS += "kernel-module-goodix"
Problem
My build simply consistently fails in do_rootfs with:
Error:
Problem: package packagegroup-base-1.0-r83.imx6ul_var_dart requires packagegroup-machine-base, but none of the providers can be installed
- package packagegroup-base-extended-1.0-r83.imx6ul_var_dart requires packagegroup-base, but none of the providers can be installed
- package packagegroup-machine-base-1.0-r83.imx6ul_var_dart requires kernel-module-goodix, but none of the providers can be installed
- conflicting requests
- nothing provides kernel-module-goodix-5.4.3-imx6ul+gb40ccfdb73ea needed by goodix-9271-0.1-r0.imx6ul_var_dart
(try to add '--skip-broken' to skip uninstallable packages or '--nobest' to use not only best candidate packages)
What I cannot understand after reading the documentation on this section is why this error is happening. I tried adjusting the recipe names (removing the kernel-module prefix, etc) but nothing seems to work. What is going wrong?
Source
inherit module logging
# Driver for Goodix touchscreens
SUMMARY = "Generic driver for Goodix touchscreens"
DESCRIPTION = "Support for Goodix 1151, 5663, 5688, 917S, 9286, 911, 9271, 9110, 927, 928, 912, 9147, and 967 touchscreens"
# License
LICENSE = "GPL-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6"
# Compatibility
COMPATIBLE_MACHINE = "(imx)"
# Package name
RPROVIDES_${PN} = "kernel-module-goodix"
# Source
S = "${WORKDIR}"
SRC_URI = "file://Makefile \
file://goodix.c"
# Functions
do_install() {
bbwarn "Installing Goodix kernel module ..."
bbwarn "KERNEL_SRC = ${KERNEL_SRC}"
bbwarn "KERNEL_VERSION = ${KERNEL_VERSION}"
bbwarn "WORKDIR = ${WORKDIR}"
cd ${S}
xz goodix.ko
install --verbose -d ${D}/lib/modules/${KERNEL_VERSION}/kernel/drivers/input/touchscreen
install --verbose -m 0644 goodix.ko.xz ${D}/lib/modules/${KERNEL_VERSION}/kernel/drivers/input/touchscreen
}
# Reference included files
FILES_${PN} = "/lib/modules/${KERNEL_VERSION}/kernel/drivers/input/touchscreen/*"
Edits
The error basically says that kernel-module-goodix-5.3.4-imx6ul+gb40ccfdb73ea isn't provided. I didn't name my package that way though. So why is it looking for something with the suffix 5.3.4-imx6ul+gb40ccfdb73ea there?
Edit (Solution)
For anyone reading this who isn't satisfied by the accepted answer. Just know that what was wrong with my original recipe was that I wasn't naming my actual recipe "kernel-module-<name>.bb". That was actually what was required.
I have created a recipe for an UART Bluetooth driver before and it works fine for me, here is the recipe:
#
# FNLINK BLUETOOTH 8822 KERNEL DRIVER
#
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
SRC_URI = "file://uart_bt.zip"
S = "${WORKDIR}/bluetooth_uart_driver"
inherit module
EXTRA_OEMAKE_append_task-install = " -C ${STAGING_KERNEL_DIR} M=${S}"
EXTRA_OEMAKE += "KDIR=${STAGING_KERNEL_DIR}"
Change S to "bluetooth_uart_driver" because the zip file contains that directory with the content:
ifneq ($(KERNELRELEASE),)
obj-m := hci_uart.o
hci_uart-y := hci_ldisc.o hci_h4.o hci_rtk_h5.o rtk_coex.o
#EXTRA_CFLAGS += -DDEBUG
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a
endif
This works well for me, and the .ko file is generated and shipped into /lib/modules/${KVER}/extra , so you can override the do_install function and install it where you want.
Simple Test:
I downloaded the goodix.c driver and created a custom recipe for it with this Makefile (I modified my old BT Makefile):
ifneq ($(KERNELRELEASE),)
obj-m := goodix.o
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a
endif
My recipe:
|meta-test/
|--> recipes-driver/
|--> files/
|--> goodix.c
|--> Makefile
|--> goodix-driver_0.1.bb
goodix-driver_0.1.bb:
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
SRC_URI = "file://goodix.c file://Makefile"
S = "${WORKDIR}"
inherit module
EXTRA_OEMAKE_append_task-install = " -C ${STAGING_KERNEL_DIR} M=${S}"
EXTRA_OEMAKE += "KDIR=${STAGING_KERNEL_DIR}"
With this in a simple poky build I was able to generate the .ko file.
Note:
If goodix.c is present in your upstream Linux kernel, which means you can find it in:
tmp/work/.../linux-../../git/drivers/input/touchscreen/goodix.c
which means you can just patch it without creating a whole recipe for it, you just edit it directly and then go back to git folder and :
git add drivers/input/touchscreen/goodix.c
git commit -m "My-updates"
git format-patch -1 -o /path/to/meta-custom/recipes-kernel/linux/files
Now, in /path/to/meta-custom/recipes-kernel/linux/linux-xx_%.bbappend add:
SRC_URI_append = " file://My-updates.patch"
Now, do not forget to activate it via menuconfig and add its flag to the kernel defconfig file so it gets compiled and shipped within the rootfs.
I am updating my question with an answer which also describes how to create a simple kernel module bitbake file.
File name and placement
Name of my kernel module: foo
Name of my bitbake file: kernel-module-foo (kernel-module- prefix required)
Topology (see below):
├── conf
│ └── layer.conf
├── COPYING.MIT
├── README
├── recipes-kernel
│ └── linux
│ ├── kernel-module-foo.bb
Bitbake file
# Bitbake class(es)
inherit module
# Dependencies
DEPENDS = "virtual/kernel"
# Metadata
SUMMARY = "Sample kernel module"
# Licensing
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5= 0835ade698e0bcf8506ecda2f7b4f302"
# Source
GIT_BRANCH = "my-branch"
SRC_URI = "git://<path-to-git-repo>;branch=${GIT_BRANCH}"
SRCREV = "<my-git-branch-src-revision>"
# OE build directives
EXTRA_OEMAKE_append_task-install = "-C ${STAGING_KERNEL_DIR} M=${S}"
EXTRA_OEMAKE += "KDIR=${STAGING_KERNEL_DIR}"
# Autoinstall (optionally disable)
KERNEL_MODULE_AUTOLOAD += "pwr_ctl_onoff"

How to build Go + C code in Yocto, fetching the source code from files in the recipe

I'm having issues building Go + C code inside of Yocto.
I'm using Yocto gatesgarth, and the only way I can get it to work is by following the examples where they use git.
I do not want to use git for the fetching, just copy the files and build them. This is to allow me to try out changes, and also avoid dealing with source control revision.
How would you go about doing that?
Thanks!
Edit: I posted a solution bellow, I hope this will be useful.
I could not get it to work without overloading do_compile() and do_install(), but here it is.
DESCRIPTION = "The application code"
LICENSE = "CLOSED"
LIC_FILES_CHKSUM=""
SRC_URI = "file://build/streamerapp.go file://build/gstreamer_pipelines.c file://build/gstreamer_pipelines.h"
GO_IMPORT = "streamerapp"
GO_LINKSHARED = ""
PTEST_ENABLED="0"
export GO111MODULE="auto"
CGO_ENABLED = "1"
inherit go
do_compile() {
cd ${WORKDIR}/build
export TMPDIR="${GOTMPDIR}"
${GO} build ${GO_LINKSHARED} ${GOBUILDFLAGS} -o streamerapp
cd ${OLDPWD}
}
do_install() {
cd ${WORKDIR}/build
#install -m <permisions> SRC DEST
mkdir -p ${D}${bindir}
install -m 0755 ./streamerapp ${D}${bindir}
cd ${OLDPWD}
}

How can I add a folder or file to the root in a recipe with bitbake?

I am trying to put a folder into the root of the filesystem. In the documentation (e.g. here) they use mostly variables and so the files and folders from SRC_URI result in being stored under /usr/bin or something but never in /.
So here is my recipe:
DESCRIPTION = "Example for adding files and folders to rootfs"
SRC_URI += "file://example_folder"
SRC_URI += "file://example_file"
LICENSE = [...]
do_install() {
install -d ${D}/rootfolder
cp -r ${WORKDIR}/example_folder ${D]/rootfolder/
install -m 0755 ${WORKDIR}/example_file ${D}/rootfolder
}
This is just one of very many do_install variants that I tried.Every of them resulted in either Error: example not found in the base feeds [...] or that the files and folders haven't been placed in the root but in /usr/bin as explained above.
In the cases were you get the error "Error: example not found in the base feeds [...]" it's quite likely that you actually have succeeded in building your recipe example.bb. Assuming of course, that you get that error when building your image, which has IMAGE_INSTALL += "example" in it.
If you install your files into /rootfolder, there's nothing in OE itself that knows how to package those files into an rpm, ipk, or deb package. You need to add that yourself to your recipe by adding a line like:
FILES_${PN} += "/rootfolder"
Doing that, your example above should work.
Depending on what files you install, you might want to add some of them to other packages like ${PN}-dbg, ${PN}-dev, etc.

Yocto recipe : how to install in specific folder

I have created a Yocto recipe for my program.
What are the default folders that are building image from recipe ?
At the time of building image, I want to move my files to another folder like "/opt/xyz".
Should I simply do "mv" or is there any other options?
I guess you want to copy your compiled program to a folder such as ${bindir}:
Quote from Yocto ref-manual 1.1:
When specifying paths as part of the CONFFILES variable, it is good practice to use appropriate path variables. For example, ${sysconfdir} rather than /etc or ${bindir} rather than /usr/bin. You can find a list of these variables at the top of the meta/conf/bitbake.conf file in the Source Directory.
You can copy files from your working directory to any directory in the target filesystem. See the hello-world example for instance (note that the example is taken from the 1.1 reference manual, but I haven't found it yet in the newer version):
DESCRIPTION = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
PR = "r0"
SRC_URI = "file://helloworld.c"
S = "${WORKDIR}"
do_compile() {
${CC} helloworld.c -o helloworld
}
do_install() {
install -d ${D}${bindir}
install -m 0755 helloworld ${D}${bindir}
}
FILES_${PN} = "${bindir}"
In this example, the helloworld binary would be copied to /usr/bin on your image (could be /opt too, see Source Directory for the variable definition).
Adjust FILES_${PN} var for ${sysconfdir} ${bindir} ${datadir} ${libdir} directories.
do_install(){
install -d ${D}{base_prefix}/opt/xyz/
install -m ${WORKDIR}/yourbinary ${D}${base_prefix}/opt/xyz/
}
FILES_${PN} = "${base_prefix}/opt/*"
above
1st line creates the dir in imagedir in that opt/xvz/
2nd line copy your binary to opt/xyz/dir
3rd line use to copy of your opt/xyz/binary to yocto rootfs.

Resources