I'm attempting to create an image with yocto using a custom source (linux kernel 3.16). When I attempt to run 'bitbake myCustomRecipe', I get a warning and error like the following:
WARNING: Unable to get checksum for myCustomRecipe SRC_URI entry defconfig: file could not be found
I have several other warnings/errors, but I believe that these follow naturally due to the above warning. My layer structure is like this:
meta-mytestLayer
|
+--conf/
| |
| +--layer.conf
|
+--recipes-kernel/
|
+--linux/
|
+--myCustomRecipe_3.16/
| |
| +--defconfig
|
+--myCustomRecipe_3.16.bb
As you can see, there is a defconfig file within the myCustomRecipe_3.16/ directory. Why is this not being found? This file structure is very similar to the ones I have seen in several tutorials (like lab three of this document). My layer.config looks like this:
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "myTestLayer"
BBFILE_PATTERN_myTestLayer = "^${LAYERDIR}/"
BBFILE_PRIORITY_myTestLayer = "6"
and my recipe looks like this:
inherit kernel
require recipes-kernel/linux/linux-yocto.inc
SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git;protocol=git;nocheckout=1;name=machine"
SRC_URI += "file://defconfig"
LINUX_VERSION ?= "3.16"
LINUX_VERSION_EXTENSION ?= ""
SRCREV_machine="f14680f1692a9ec2a5b1b716a7a0c03dd391106f"
PR = "r1"
PV = "${LINUX_VERSION}+git${SRCPV}"
COMPATIBLE_MACHINE = "qemux86"
I'm a total yocto newbie and am looking at a number of labs/reference manuals/tutorials but haven't found anything related to this specific problem. I'm mostly working with the link I provided earlier and using this section of the Yocto Project Linux Kernel Development Manual.
You have your defconfig file in a directory called myCustomRecipe_3.16/, while OpenEmbedded will look for the file in directories(1) named either of:
myCustomRecipe-3.16/
myCustomRecipe/
files/
Note the '-' instead of '_'.
If you look at the log.do_unpack for your failed recipe, you'll see which directories has been searched for your defconfig.
(1) Well, that's only part of the story. Those three directories will be appended with directories for all your OVERRIDES as well.
Related
I am new, yocto build at imx6q embedded system.
I want to overwrite linux system files after do_rootfs. For example, target system files are below.
/etc/network/interface
/etc/issue
/etc/init.d/rcS
/home/root/mytest.sh
so, i made custom layer and custom recipe.
helloworld binary is copy ok.
but, do_mytask function is not called.
what's wrong with my code?
or any other method for my purpose.
#
# This file was derived from the 'Hello World!' example recipe in the
# Yocto Project Development Manual.
#
SUMMARY = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
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}
}
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
SRC_URI += " \
file://interfaces \
file://issue \
file://mytest.sh \
"
addtask mytask after do_rootfs before do_image
do_mytask() {
install -d ${D}/etc/network
cp -af ${WORKDIR}/interfaces ${D}/etc/network/interfaces
cp -af ${WORKDIR}/issue ${D}/etc/issue
}
You'll need to extend the recipes that provide the files you want to replace.
Using /etc/network/interfaces as an example, the first step is to figure out which recipe installs that file.
From the bitbake prompt:
$ oe-pkgdata-util find-path /etc/network/interfaces
init-ifupdown: /etc/network/interfaces
So this tells us that /etc/network/interfaces is installed by the init-ifupdown receipe.
A file search shows that init-ifupdown is part of poky:
$ find . -name init-ifupdown*.bb
./poky/meta/recipes-core/init-ifupdown/init-ifupdown_1.0.bb
Now, since you need to modify the output of init-ifupdown, you'll need to extend init-ifupdown by creating a similarly named .bbappend in your own layer.
You might create the new .bbappend at
my-layer/receipes-core/init-ifupdown/init-ifupdown_%.bbappend
The % is a wildcard that ensures the .bbappend will apply to all future versions of the init-ifupdown recipe, which is probably what you want.
Place your custom interfaces file in a folder below the .bbappend:
my-layer/receipes-core/init-ifupdown/files/interfaces
The .bbappend then only needs to contain a single line to enable bitbake to pick up the new interfaces file:
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
Finally, repeat the above with each system file you'd like to replace.
It depends on the file to modify. For example, if you search 'interfaces' in poky directories, you'll find it in 'meta/recipes-core/init-ifupdown/init-ifupdown-${PV}/'. You just need to create a recipe named init-ifupdown-${PV}.bbappend in your meta, recreating the path seen in poky (recipes-core/init-ifupdown/). This recipe can contain a single line :
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
Then you create a 'files' folder with the 'interfaces' file you want to have.
For 'issue', like others found in the /etc directory (profile, fstab, ...), it's the same procedure, with the sources in poky/meta/recipes-core/base-files/.
For init.d scripts, use the 'update-rc' class.
You recipe is not "image recipe" (and it shouldn't be for hello world) thus you cannot use tasks do_rootfs and do_image in this case. A bit of clarification: image recipe is .bb file that you use to build image with bitbake or devtool (in your case some containing imx6q, you can find them with bitbake-layers show-recipes "*-image-*").
It looks like you are looking really is a way to override do_install of some recipe that installs that mentioned files. Then find what recipe installs those files and create bbappend file in your top layer. This bbappend file may contain do_install_append task where you can place your install <file> <dir> lines (note, using cp as not recommended, everything should be done with install tool).
Adding an extra comment based on Carsten Hansen original answer for folks working with Xilinx/Petalinux.
Under Petalinux environment we don't really have the command: oe-pkgdata-util, so the strategy is to do a search in the Xilinx SDK folder. You might have it installed on Linux under /opt according to the documentation. If you do a:
grep -r syslog-startup.conf .
you will see busybox recipe being the one that does the installation of the syslog-startup.conf.
You can create the override recipe called busybox_%.bbappend under:
../project-spec/meta-user/recipes-core/busybox/
Put the modified syslog-startup.conf file under:
../project-spec/meta-user/recipes-core/busybox/files/syslog-startup.conf
Rebuild via petalinux-build. You can also force the creation of the rootfs via petalinux-build -c rootfs and the system should populate your new file.
Summary
I am trying to understand a complicated chain of Makefiles, in order to get a build to succeed. I narrowed down my problem to this bit in our build script:
INF_RL=`make -f $BUILD_ROOT/Makefile BUILD_ROOT_MAKEFILE= show__BUILD_INF_RL`
$INF_RL/$BUILD_UTILS_RELDIR/BuildAll.sh
$INF_RL is being set to an empty string (or not being set). If I replace the first line with
INF_RL=/foo_rel_linx86/infrastructure_release/v8.0.14
in order to hardcode what I know $INF_RL is supposed to be, then the build goes smoothly. But I want to know how to fix this the proper way.
What I've Tried / Thought
My first thought was that make -f is failing. So I tried it in my shell:
% make -f $BUILD_ROOT/Makefile BUILD_ROOT_MAKEFILE= show__BUILD_INF_RL
% setenv | grep BUILD_ROOT
BUILD_ROOT=/userhome/andrew.cheong/TPS
Indeed, it returned an empty string. But what conclusion could I draw from this? I wasn't sure if the shell was the same thing as the environment / scope in which Make was chaining together its Makefiles. I abandoned this investigation.
Next, I looked into show__BUILD_INF_RL, which seemed to be defined in $BUILD_ROOT/Makefile:
BUILD_ROOT_MAKEFILE = 1
MAKE_DIRS = src
CASE_KITS = tpsIn tpsOut
REQUIRED_VERSIONS = "case.v$(INF_VS)"
all:
## These next 3 rules allows any variable set in this makefile (and therefore
## the included makefile.include to have it's value echoed from the command
## "make show_<variableName>"
## NOTE: the "disp" target is vital as it allows the show_% implicit rule to be
## recognised as such - implicit rules *must* have a target.
show_% := DISPLAY_MACRO = $(#:show_%=%)
show_% : disp
# echo $($(DISPLAY_MACRO))
disp:
include $(BUILD_ROOT)/makefile.include
Here, I faced more questions:
What is BUILD_ROOT_MAKEFILE for? Why is it set to 1, then seemingly something else in the make -f command?
In the make -f command, is BUILD_ROOT_MAKEFILE= its own argument? If so, what kind of target or rule is that? Otherwise, why is it being set to the macro?
In $BUILD_ROOT, there is another file, makefile.LINUX_X86.include:
BUILD_INF_RL = /foo_rel_linx86/infrastructure_release/v$(INF_VS)
$(warning $(BUILD_INF_RL))
BUILD_UTILS = $(BUILD_INF_RL)/build-utils_LINUX_X86
Though a completely ignorant guess, I think BUILD_INF_RL is being set here, and intended to be extracted into the build script's variable INF_RL when the macro show__BUILD_INF_RL is invoked. I added the middle line to see if it was indeed being set, and indeed, I get this output when running the build script:
/userhome/andrew.cheong/TPS/makefile.LINUX_X86.include:3: /foo_rel_linx86/infrastructure_release/v8.0.14
i.e. Looks like what I've hardcoded way above! But why doesn't it make it into INF_RL? There is yet another file, makefile.include, also in $BUILD_ROOT:
#
# INCLUDE THIS FILE AS THE LAST LINE IN THE LOCAL MAKEFILE
#
# makefile.include - use this file to define global build settings
# e.g. infrastructure version and location, or third-party
#
# supported macros in addition to build-utils-makefile.include
#
# BUILD_INF_RL : optional, specification of infrastructure release location
# defaults to vdev_build area
#
include $(BUILD_ROOT)/../../makefile.include.$(BUILD_ARCH).Versions
#include $(BUILD_UTILS)/makefile.archdef.include
include $(BUILD_ROOT)/makefile.$(BUILD_ARCH).include
$(warning $(BUILD_INF_RL))
_BUILD_INF_RL = $(BUILD_INF_RL)
# place the results at the root of the infdemo tree
BUILD_DEST = $(BUILD_ROOT)
INCLUDE_DIRS += $(BUILD_INF_RL)/core/$(BUILD_TARGET)/include
LINK_DIRS += $(BUILD_INF_RL)/core/$(BUILD_TARGET)/lib
# libraries required for a typical fidessa app, including OA and DB access
FIDEVMAPP_LIBS = FidApp FidInf FidCore Fidevm
include $(BUILD_UTILS)/makefile.include
That $(warning ...) is again mine, and when running the build script, I get:
/userhome/andrew.cheong/TPS/makefile.include:18: /foo_rel_linx86/infrastructure_release/v8.0.14
The Question
The fact that both $(warning ...)s show up when I run the build script that's calling the make -f ... show__BUILD_INF_RL, tells me that those Makefiles are being included. Then what is causing the macro to fail and return an empty string instead of the correct INF_RL path?
Historical Notes
These build scripts were written at a time when we were only compiling for Solaris. (The scripts were based on templates written by an infrastructure team that loosely accounted for both Solaris and Linux, but we never ran the Linux branch, as it was unnecessary.) We are now fully migrating to Linux, and hitting this issue. The reason I'm skeptical of it being a Linux versus Solaris issue is that we have at least four other products that use a similar Makefile chain and have been migrated with no issues. Not sure why this one in particular is behaving different.
Your question got very long and complex so I didn't read it all... for SO it's often better if you just ask a specific targeted question that you want to know the answer to, with a simple repro case.
I can't say why different makefiles behave differently, but this line:
show_% := DISPLAY_MACRO = $(#:show_%=%)
seems really wrong to me. This is (a) setting the variable show_%, which don't actually use anywhere, (b) to the simply expanded string DISPLAY_MACRO = because at this point in the makefile the variable $# is not set to any value.
Maybe you wanted this line to be this instead:
show_% : DISPLAY_MACRO = $(#:show_%=%)
(note : not :=) so that it's a pattern-specific variable assignment, not a simple variable assignment?
I'm new to Scons and I'm trying to figure out if I could use it for my use-case. I have a script whose main actoin is to take a single input and produces multiple output files in a given directory. However, it also needs one additional input and one additional output, as in
script --special-in some.foo --special-in some.bar input.foo output.dir/
The names of some.* files can be computed from the input file name (here input.foo). And the some.* files produced by one rule are consumed by other rules.
In the documentation I found that one can create custom builders as in
bld = Builder(action = 'foobuild $TARGETS - $SOURCES',
suffix = '.foo',
src_suffix = '.input',
emitter = modify_targets)
where the emitter adds the additional target and source. However, I couldn't find how should I distinguish the main source/target from the special ones, which need to be passed using specific options - I can't use $TARGETS and $SOURCES as in the above example. I could probably use a generator and index into source and target, but this seems a bit hacky. I there a better way?
From what you describe, you should be using both an emitter and a generator, just as you state at the end of your question. The "main" source/target will be the first element in the source/target lists. This doesn't seem hacky to me, but I may just be used to it...
Answers are always better with a working example...
Here is the SConstruct to do what you describe. I'm not exactly sure how you plan to compute some.foo and some.bar from input.foo, so in this example I compute input.bar and input.baz from input.foo, and just append output.dir to the list of targets.
import os
def my_generator(source, target, env, for_signature):
command = './script '
command += ' '.join(['--special-in %s' % str(i) for i in source[1:]])
command += ' '
command += ' '.join([str(t) for t in target])
return command
def my_emitter(target, source, env):
source += ['%s%s' % (os.path.splitext(
str(source[0]))[0], ext) for ext in ['.bar', '.baz']]
target += ['output.dir']
return target, source
bld = Builder(generator=my_generator,
emitter=my_emitter)
env = Environment(BUILDERS={'Foo':bld})
env.Foo('output.foo', 'input.foo')
When run on linux...
>> touch input.bar input.baz input.foo
>> echo "#\!/bin/sh" > script && chmod +x script
>> tree
.
├── input.bar
├── input.baz
├── input.foo
├── SConstruct
└── script
0 directories, 5 files
>> scons --version
SCons by Steven Knight et al.:
script: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001 - 2014 The SCons Foundation
>> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
./script --special-in input.bar --special-in input.baz output.foo output.dir
scons: done building targets.
All dependencies/targets will be maintained, if you need to feed the outputs from one builder like this into another.
If this doesn't answer your question, please clarify what more you are trying to do.
I have a linux makefile that needs to compile on 2 different kernel versions. The makefile is not generated from automake/autoconf.
The C code are already conditioned using macros to generate different code for different kernel version, but certain features in the makefile needs to be also conditioned.
Is there a way in a makefile to do:
if (kernel_version > 2.6.30)
newer_kernel = 1
else
newer_kernel = 0
endif
Well, I can think of one quick way to do it with bash:
KERNEL_VERSION=`uname -r`
HIGHER_VERSION=`echo -e "$KERNEL_VERSION\n2.6.30" | sort -g -t '.' | tail --lines=1`
if [ "$HIGHER_VERSION" == "2.6.30" ]
# its an older kernel
else
# its a newer kernel
fi
Basically, you use uname to obtain the version of the current kernel, then compare it to 2.6.30 using sort (the -g flag enables numeric sorting, -t '.' means use dot as a field separator), then use tail to determine which of the two version was higher in the list. Not exactly a beautiful solution, but it will work.
You can put it into a separate script or directly into the makefile recipe
According to g++ -print-search-dirs my C++ compiler is searching for libraries in many directories, including ...
/lib/../lib/:
/usr/lib/../lib/:
/lib/:
/usr/lib/
Naively, /lib/../lib/ would appear to be the same directory as /lib/ — lib's parent will have a child named lib, "that man's father's son is my father's son's son" and all that. The same holds for /usr/lib/../lib/ and /usr/lib/
Is there some reason, perhaps having to do with symbolic links, that g++ ought to be configured to search both /lib/../lib/ and /lib/?
If this is unnecessary redundancy, how would one go about fixing it?
If it matters, this was observed on an unmodified install of Ubuntu 9.04.
Edit: More information.
The results are from executing g++ -print-search-dirs with no other switches, from a bash shell.
Neither LIBRARY_PATH nor LPATH are output from printenv, and both echo $LPATH and echo LIBRARY_PATH return blank lines.
An attempt at an answer (which I gathered from a few minutes of looking at the gcc.c driver source and the Makefile environment).
These paths are constructed in runtime from:
GCC exec prefix (see GCC documentation on GCC_EXEC_PREFIX)
The $LIBRARY_PATH environment variable
The $LPATH environment variable (which is treated like $LIBRARY_PATH)
Any values passed to -B command-line switch
Standard executable prefixes (as specified during compilation time)
Tooldir prefix
The last one (tooldir prefix) is usually defined to be a relative path:
From gcc's Makefile.in
# Directory in which the compiler finds libraries etc.
libsubdir = $(libdir)/gcc/$(target_noncanonical)/$(version)
# Directory in which the compiler finds executables
libexecsubdir = $(libexecdir)/gcc/$(target_noncanonical)/$(version)
# Used to produce a relative $(gcc_tooldir) in gcc.o
unlibsubdir = ../../..
....
# These go as compilation flags, so they define the tooldir base prefix
# as ../../../../, and the one of the library search prefixes as ../../../
# These get PREFIX appended, and then machine for which gcc is built
# i.e i484-linux-gnu, to get something like:
# /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../i486-linux-gnu/lib/../lib/
DRIVER_DEFINES = \
-DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
-DTOOLDIR_BASE_PREFIX=\"$(unlibsubdir)/../\" \
However, these are for compiler-version specific paths. Your examples are likely affected by the environment variables that I've listed above (LIBRARY_PATH, LPATH)
Well, theoretically, if /lib was a symlink to /drive2/foo, then /lib/../lib would point to /drive2/lib if I'm not mistaken. Theoretically...
Edit: I just tested and it's not the case - it comes back to /lib. Hrm :(