Where should the contents of /sys/kernel/kheaders.tar.xz be installed? - linux

Recent Linux kernels can be built with a copy of the kernel headers included -- these are available in a pseudo file at /sys/kernel/kheaders.tar.xz. This unpacks to a tree with arch and include. include has about 30 subdirectories, including linux, and arch leads to a tree of what looks like related architecture files.
Is there a single place that the contents can be unpacked so that the C compiler can access the headers at the expected places? (Including intra-header inclusion, e.g., <linux/gpio/consumer.h> includes <linux/bug.h>, which includes <asm/bug.h>.)
I tried just unpacking everything into /usr/include, which sort-of kind-of works, but the arch stuff is not at all in the right place. Plus, unpacking over an existing /usr/include feels sloppy -- stuff might get clobbered, and you'll have a mess the next time you upgrade the kernel.
Is there a Best Practices that kernel developers use for this?

Related

Yocto layer for ADIS16475

Context
Lately I've had trouble including an adis driver in my Yocto build. I've asked the question on the adis forum but found the solution before anyone answered it. The adis forum not being very user friendly and the answer being quiet long, I've decided to answer my question here and link it in the forum.
The question
I'm building my OS with yocto and I'd like to add a driver for IMU ADIS1607 (anything but the ease of use is a plus) as part of this build.
I'm building a prototype on a raspberryPi4. My application uses an ADIS IMU (ADIS16507). Since the board for the final product is not fixed I'm building my OS with Yocto.
I'm currently trying to add a driver for ADIS16507. Ideally I'd like to add ADIS16475, but I could do with something else provided it works nicely.
First off I have checked that I'm able to build the whole ADIS linux kernel for RaspberryPi as specified in the doc. With that kernel the driver works nicely.
However the ADIS linux kernel is too heavy for what I intend to do. Hence I'm trying to build a lighter OS with yocto (also, as aforementioned, I'll likely need to port my work on different platforms).
I have a few ideas on how to do it, however none of them worked easily and I'm not sure which one to pursue.
I assumed the simplest way would be to compile the ADIS16475 on its own and add it to the Yocto build. However I'm struggling a little with Yocto and haven't been able to compile sucessfully
Alternatively I did find the libiio layer for yocto but it seems to require quiet a lot of code to on top of it to be able to read the IMU values.
I am aware of the python bindings of libiio layer and of Pyadi-iio and it seems easy to use (although I did not try adding it with yocto) but computational speed is an issue for me and I'd rather use C/C++ instead of python.
Finally I also found the meta-adi layer. I think that in my case it is not relevant but the documentation I found is rather sparse and I'm not certain what this layer is supposed to do.
Any pointer on which method I should use (maybe I've missed an obvious easy one) is welcome.
So here is the solution I found. We will use the ADIS16475 which is a part of the standard libc since version 5.10. Then we'll get the corresponding device tree overlay from ADIS and add the relevant variables to have it compiled with the other device tree overlays.
Getting the correct versions
For this to work we need libc 5.10 or later since earlier version do not include the adis16475.c source file. However only the latest yocto release, Hardknott, uses the 5.10 version. So simplest thing to do is to switch to the Hardknott branch of Yocto. Keep in mind that if you use other layers, you might also have to change release for compatibility reasons.
Configuring the kernel to compile ADIS16475 drivers as built in
Here we're gonna dab into kernel compilation so there are a few things to know
Short and approximate theory
If you don't know much about kernel compilation don't worry, neither do I. But here is an approximate quick explanation in order for you to understand what we're doing: Kernel makefiles hold list of files the have to compile. For drivers there are 2 important lists. obj-y that holds the files that will be compiled and built in the kernel and obj-m that holds the files that will be compiled as loadable modules. In order to make these list configurable, they are defined in makefiles with statements such as:
obj-${CONFIG_MYDRIVER} += my_driver.o
The idea is that you can set CONFIG_MYDRIVER in an external file to 'm' or 'y'. If you set it to anything else the line in the makefile will be ignored and your file won't be compiled. So basically all we have to do is to set the right variables to the right values in order for yocto to compile our drivers.
Custom kernel configuration
Basically what we want to do is to create our own configuration fragment file. To do this you will need to set your yocto layer (I'll assume if you're reading this post you know how to do it). In your layer you should add the following folders:
meta-my-layer
|
- recipe-kernel
|
- linux
|
- linux-raspberrypi_5.10.bbappend
|
-linux-raspberrypi
|
-adis16475.cfg
(Note that we are appending linux-raspberrypi_5.10 because it's the one in meta-raspberrypi that is responsible for libc compilation. If you're compiling for another machine look what files are in recipe-kernel/linux. Your BSP might even actually use the ones in poky/meta/recipe-kernel/linux)
Now all that is left to do is to add adis16475.cfg to our sources by adding the following lines in linux-raspberrypi_5.10.bbappend:
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://adis16475.cfg"
And to actually setup your configuration in adis16475.cfg by adding to the file:
CONFIG_SPI_MASTER=y
CONFIG_IIO=y
CONFIG_ADIS16475=y
CONFIG_IIO_KFIFO_BUF=y
CONFIG_SPI_BCM2835=y
To the best of my knowledge and experience, this is the minimal amount of drivers you have to build for it to work.
Once this is done you will have your drivers built in but you won't see any effect on the Pi. That's because we're lacking the correct overlay.
Building adis16475-overlay.dts
To solve this problem I've been widely inspired by this post, so if you're having trouble you might want to check it out.
The issue here is that to my knowledge, the overlay corresponding to the driver is not provided by libc, at least not the 5.10 version. So we will have to be a little crafty. First off get the overlay from adis and copy it into recipe-kernel/linux/linux-raspberrypi.
Once this is done we will source it for yocto to find by modifying recipe-kernel/linux/linux-raspberrypi_5.10.bbappend to look like this:
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://adis16475.cfg \
file://adis16475-overlay.dts;subdir=git/arch/${ARCH}/boot/dts/overlays"
The last line we added tells yocto where to get our .dts file and where to put it (with the others overlays).
Finally what we have to do is to add our overlay to the list of overlays and device trees to be compiled. To do so we will use the machine configuration file raspberrypi4-64.conf. More details about it here.
First in your layer conf folder, create machine/raspberrypi4-64-extra.conf. This file will hold all the additional configuration we want to make for this driver. In it first add:
# Create the device trees and overlay list with necessary drivers
KERNEL_DEVICETREE = " \
${RPI_KERNEL_DEVICETREE} \
${RPI_KERNEL_DEVICETREE_OVERLAYS} \
overlays/adis16475.dtbo \
"
This sets the list of device trees to compile. It add the RPI device trees and overlays necessary for the pi (two first variables) and our adis16475 overlay.
Then we'll take advantage of this file to enable a few necessary raspberrypi specific configuration options. Add:
# Enable RPI specific options in config.txt
ENABLE_SPI_BUS = "1"
RPI_EXTRA_CONFIG = '\ndtoverlay=adis16475\n'
Finally you need to tell yocto to use this extra config. The most verstile way is to add the following line in your local/local.conf:
# Enables the DIP hardware support
require conf/machine/${MACHINE}-dip-extra.conf
Once this is done, provided you did add your layer to your bblayers.conf file, and your machine is set to raspberrypi4-64 in your local.con file, then everything else should work nicely.
Notes on the machine type
Here I worked with the machine set as raspberrypi4-64 for it was the one I had. There is no reasons for this procedure not to work with any other machine from the meta-raspberrypi layer. Just remember to replace the name of your machine everywhere I put raspberrypi4-64 and you should be fine.
Hope this will help some other people lost in the Yoctoverse
Cheers

configuring linux kernel with (hard-loaded, built in) currently loaded modules

I want to build from source a recent Linux kernel (e.g. 4.13.4 in end of september 2017) on my Debian/Sid/x86-64 with all (or most) currently loaded modules configured as hard-built in the new kernel.
(I believe that I have read something like this somewhere, but can't remember where and can't find it)
It would be some make configfromloadedmodules (but of course it is not exactly configfromloadedmodules makefile target, but some other target that I did not easily find).
That is, for most (ideally all) currently loaded modules (as given by lsmod) it would answer Y (not m) for each of them at make config time and give me some good enough .config; but I don't want a bloated kernel with all drivers -even those that I don't use and which are not currently loaded- built in.
Does that exist, or was what I have probably read some wish or some non standard feature of experimental kernels?
This would avoid any initrd thing and give me a kernel suited for my hardware and habits.
The current kernel is a standard Debian one 4.12.0-2-amd64, so I have its /boot/config-4.12.0-2-amd64 (so I want to automatize the replacement of CONFIGxxx=m with CONFIGxxx=y there, according to the currently loaded modules, e.g. as given by lsmod).
See also this answer; I still believe that device trees are not essential to Linux, but they are a useful convenience.
A near variant of my question is how to easily configure a kernel, suited to my computer and hardware and set-up, without ìnitrd, without any modules (e.g. with CONFIG_MODULES=n) and without (or with very few) useless drivers, which would work as nicely as my current Debian kernel.
I believe, you should read about "make localmodconfig" and "make localyesconfig" and use one as per your requirement.
This, This and This are helpful links.

Unable to understand why one should not use /usr/src/linux for kernel development

I was reading "Linux Kernel Development" by Robert Love. I came across a line which I am unable to understand fully:-
The kernel source is installed in /usr/src/linux. You should not use this source tree for development because the kernel version against which your C library is compiled is often linked to this tree.
It looks like I am unable to relate it with some very basic concept.
The /usr/src/linux area has a (usually incomplete) set of kernel headers that are used by the library header files. They should match the library, and not get messed up. Headers in /usr/include/linux are "private" but these should be those headers which were used in a compilation of your libraries (notably glibc) and hacking around the with a link in /usr/src is a mistake as Linus tried to explain many times - sometimes quite forcibly. Headers used in a kernel compilation are NOT searched for in subdirectories of /usr/src/linux but are specific to a kernel version and can be drastically different between different versions, or at least you do not have any guarantees that they are not.

Loading Linux libraries at runtime

I think a major design flaw in Linux is the shared object hell when it comes to distributing programs in binary instead of source code form.
Here is my specific problem: I want to publish a Linux program in ELF binary form that should run on as many distributions as possible so my mandatory dependencies are as low as it gets: The only libraries required under any circumstances are libpthread, libX11, librt and libm (and glibc of course). I'm linking dynamically against these libraries when I build my program using gcc.
Optionally, however, my program should also support ALSA (sound interface), the Xcursor, Xfixes, and Xxf86vm extensions as well as GTK. But these should only be used if they are available on the user's system, otherwise my program should still run but with limited functionality. For example, if GTK isn't there, my program will fall back to terminal mode. Because my program should still be able to run without ALSA, Xcursor, Xfixes, etc. I cannot link dynamically against these libraries because then the program won't start at all if one of the libraries isn't there.
So I need to manually check if the libraries are present and then open them one by one using dlopen() and import the necessary function symbols using dlsym(). This, however, leads to all kinds of problems:
1) Library naming conventions:
Shared objects often aren't simply called "libXcursor.so" but have some kind of version extension like "libXcursor.so.1" or even really funny things like "libXcursor.so.0.2000". These extensions seem to differ from system to system. So which one should I choose when calling dlopen()? Using a hardcoded name here seems like a very bad idea because the names differ from system to system. So the only workaround that comes to my mind is to scan the whole library path and look for filenames starting with a "libXcursor.so" prefix and then do some custom version matching. But how do I know that they are really compatible?
2) Library search paths: Where should I look for the *.so files after all? This is also different from system to system. There are some default paths like /usr/lib and /lib but *.so files could also be in lots of other paths. So I'd have to open /etc/ld.so.conf and parse this to find out all library search paths. That's not a trivial thing to do because /etc/ld.so.conf files can also use some kind of include directive which means that I have to parse even more .conf files, do some checks against possible infinite loops caused by circular include directives etc. Is there really no easier way to find out the search paths for *.so?
So, my actual question is this: Isn't there a more convenient, less hackish way of achieving what I want to do? Is it really so complicated to create a Linux program that has some optional dependencies like ALSA, GTK, libXcursor... but should also work without it! Is there some kind of standard for doing what I want to do? Or am I doomed to do it the hackish way?
Thanks for your comments/solutions!
I think a major design flaw in Linux is the shared object hell when it comes to distributing programs in binary instead of source code form.
This isn't a design flaw as far as creators of the system are concerned; it's an advantage -- it encourages you to distribute programs in source form. Oh, you wanted to sell your software? Sorry, that's not the use case Linux is optimized for.
Library naming conventions: Shared objects often aren't simply called "libXcursor.so" but have some kind of version extension like "libXcursor.so.1" or even really funny things like "libXcursor.so.0.2000".
Yes, this is called external library versioning. Read about it here. As should be clear from that description, if you compiled your binaries using headers on a system that would normally give you libXcursor.so.1 as a runtime reference, then the only shared library you are compatible with is libXcursor.so.1, and trying to dlopen libXcursor.so.0.2000 will lead to unpredictable crashes.
Any system that provides libXcursor.so but not libXcursor.so.1 is either a broken installation, or is also incompatible with your binaries.
Library search paths: Where should I look for the *.so files after all?
You shouldn't be trying to dlopen any of these libraries using their full path. Just call dlopen("libXcursor.so.1", RTLD_GLOBAL);, and the runtime loader will search for the library in system-appropriate locations.

Automake and files with the same name

I've a C++ autoconf managed project that I'm adapting to compile on FreeBSD hosts.
The original system was Linux so I made one AM_CONDITIONAL to distinguish the host I'm building and separate the code into system specific files.
configure.ac
AC_CANONICAL_HOST
AM_CONDITIONAL([IS_FREEBSD],false)
case $host in
*free*)
AC_DEFINE([IS_FREEBSD],[1],[FreeBSD Host])
AM_CONDITIONAL([IS_FREEBSD],true)
BP_ADD_LDFLAG([-L/usr/local/lib])
;;
esac
Makefile.am
lib_LTLIBRARIES=mylib.la
mylib_la_SOURCES=a.cpp \
b.cpp
if IS_FREEBSD
mylib_la_SOURCES+=freebsd/c.cpp
else
mylib_la_SOURCES+=linux/c.cpp
endif
When I run automake it fails with this kind of message:
Makefile.am: object `c.lo' created by `linux/c.cpp' and `freebsd/c.cpp'
Any ideas on how to configure automake to respect this conditional even in the Makefile.in build proccess?
I this works if the files have diferent names, but it's c++ code and I'm trying to keep the filenames the same as the class name.
Thanks in advance!
You could request for the objects to be built in their respective subdirectories with
AUTOMAKE_OPTIONS = subdir-objects
Another option, besides subdir-objects, is to give each sub-project some custom per-project build flags. When you do this, automake changes its *.o naming rules to prepend the target name onto the module name. For example, this:
mylib_la_CXXFLAGS=$(AM_CXXFLAGS)
mylib_la_SOURCES=a.cpp b.cpp
will result in the output files mylib_la-a.o and mylib_la-b.o, rather than a.o and b.o. Thus you can have two different projects with the same output directory that each have, say, a b.cpp file, and not have their outputs conflict.
Notice that I did this by setting the project-specific CXXFLAGS to the values automake was already going to use, AM_CXXFLAGS. Automake isn't smart enough to detect this trick and use the shorter *.o names. If it happens that you do need per-project build options, you can of course do that instead of this hack.
There's a whole list of automake variables that, when set on a per-executable basis, give this same effect. So for instance, maybe one sub-project needs special link flags already, so you give it something like:
mylib_la_LDFLAGS=-lfoo
This will give you the prefixed *.o files just as the AM_CXXFLAGS trick did, only now you are "legitimately" using this feature, instead of tricking automake into doing it.
By the way, it's bad autoconf style to change how your program builds based solely on the OS it's being built for. Good autoconf style is to check only for specific platform features, not whole platforms, because platforms change. FreeBSD might be a certain way today, but maybe in the next release it will copy a feature from Linux that would erase the need for you to build your program two different ways. Or, maybe the feature you're using today is deprecated, and will be dropped in the next version.
There's forty years of portable Unix programming wisdom in the autotools, grasshopper. The "maybes" I've given above have happened in the past, and will certainly do so again. Testing individual features is the nimblest way to cope with constantly changing platforms.
You can get unexpected bonuses from this approach, too. For instance, maybe your program needs two nonportable features to do its work. Say that on FreeBSD, these are the A and B features, and on Linux, they're the X and Y features; A and X are similar mechanisms but with different interfaces, and the same for B and Y. It could be that feature A comes from the original BSDs, and is in Solaris because it has BSD roots from SunOS in the 80's, and Solaris also has feature Y from it's System V based redesign in the early 90's. By testing for these features, your program could run on Solaris, too, because it has the features your program needs, just not in the same combination as on FreeBSD and Linux.

Resources