Downstream kernel specific package
Unless a device has been mainlined, we need to package the downstream kernel (also called "vendor kernel"). This is the reference for the APKBUILD files of vendor kernels.
Generate a template
Usually you would generate both a new device specific package and a new vendor kernel package by running pmbootstrap init
and typing in a new device name. In case you should only have a device package, but not a kernel package, you can regenerate the latter with pmbootstrap aportgen linux-changeme-changeme
(you guessed it, changeme needs to be adjusted).
The template gets improved every now and then to make porting easier, so don't be surprised when you are looking at older ports and their APKBUILDs look a bit more complicated than what gets generated from the latest pmbootstrap
version. Essentially they are doing the same thing.
Modernize your aport
To recreate your vendor kernel aport on top of the latest (and therefore most readable) template, do the following steps:
$ mv aports/device/testing/linux-wiki-example /tmp/linux-wiki-example-old
$ pmbootstrap aportgen linux-wiki-example
$ # (now adjust the new aport to use the sources and patches from the "-old" dir, rename $pkgname from linux-wiki-example to linux-wiki-example-old)
$ pmbootstrap checksum linux-wiki-example
$ pmbootstrap build --force linux-wiki-example
$ # (now test it on your device and make sure it boots, e.g. with 'pmbootstrap zap', 'pmbootstrap install', 'pmbootstrap flasher boot')
$ pmbootstrap pkgrel_bump linux-wiki-example
$ git add -A
$ git commit -m "device/linux-wiki-example: modernize aport"
downstreamkernel_prepare
Newly generated downstream kernel packages use the downstreamkernel_prepare
script. That way we can share code between the APKBUILDs, so it is less redundant. To see what the function does, read the source over here.
It is supposed to be sourced, so the content of the script gets executed in the current shell. This is done with the dot in-front of the script name:
prepare() {
default_prepare
. downstreamkernel_prepare
}
Note that this behavior had changed in pmaports!1084. Out of tree device ports may not have been adjusted yet and still pass arguments to the script. This is not supported anymore, adjust them like written above or consider modernizing the whole pmaport as explained earlier in this article.
GCC version
The kernel gets compiled with GCC. Alpine Linux has been shipping version GCC 6 for a long time, but changed the default GCC version to GCC 8 in September 2018. It was discovered that at least one vendor kernel does not boot when compiled with GCC 8 (pmaports#103), so we ended up packaging GCC 6 side by side with GCC 8. All existing 3.x vendor kernels that were packaged have been adjusted to use GCC 6 at this point in time, just to make sure we don't introduce any breakage there. The default for new packages is using the current GCC version that is packaged in Alpine (at time of writing: GCC 8).
Use GCC 4
Follow the GCC 6 instructions below, but replace 6 with 4 everywhere.
Use GCC 6
If your new kernel port does not boot at all, or it doesn't even compile, please try to compile it with GCC 6 and see if it works then.
To do that, open aports/device/linux-[your-device]/APKBUILD
and add these lines:
# Compiler: GCC 6 (doesn't boot when compiled with newer versions)
if [ "${CC:0:5}" != "gcc6-" ]; then
CC="gcc6-$CC"
HOSTCC="gcc6-gcc"
CROSS_COMPILE="gcc6-$CROSS_COMPILE"
fi
between makedepends=
and # Source
lines.
Then add gcc6
to the kernel's makedepends
line.
Technical detail: the if...
guard around setting the variables is necessary, because the CC
and CROSS_COMPILE
variables extend themselves. abuild
will parse the APKBUILD
a second time while running the package()
step (inside fakeroot). So without the if
statement, we will end up with CC="gcc6-gcc6-gcc"
instead of CC="gcc6-gcc"
which gets problematic if you are calling make
to install kernel modules in the package section (as done in linux-asus-tf101
for example). Interestingly, only CC
and CROSS_COMPILE
gets passed through, hence we can't simply check the HOSTCC
variable.
Use the newest GCC from Alpine
Let's say you are using a device that has already been packaged, and you want to figure out if it also boots when compiled with a newer compiler. Just removing HOSTCC vars and references to them should be enough:
Remove these lines:
# Compiler: this kernel was only tested with GCC6. Feel free to make a merge
# request if you find out that it is booting working with newer GCCs as
# well. See <https://postmarketos.org/vendorkernel> for instructions.
if [ "${CC:0:5}" != "gcc6-" ]; then
CC="gcc6-$CC"
HOSTCC="gcc6-gcc"
CROSS_COMPILE="gcc6-$CROSS_COMPILE"
fi
And remove the mention of HOSTCC
in invocation of downstreamkernel_prepare
.
Then remove the gcc6
package from the makedepends
line.
Afterwards, remove the compiler-gcc6.h
file from the aport dir, and from the source
line. Instead you will probably need other patches as linked here. First try compiling without patches, then add one patch at a time to fix a specific problem. As usually, with pmbootstrap checksum
, you can regenerate the checksums at the bottom of the file, this needs to be done whenever you change source
.
When you made it boot successfully, please increase the pkgrel
and make a merge request.
Using GNU Make 3.x
GNU Make sometimes introduce backward-incompatible changes. While recent versions of Linux kernel requires GNU Make 4.x, building older kernels fails with GNU Make 4.x but succeeds with GNU Make 3.x.
To use GNU Make 3.81, open aports/device/linux-[your-device]/APKBUILD
and add these lines:
# GNU Make 3.81
PATH="/usr/make3.81/bin:$PATH"
between makedepends=
and # Source
lines.
Then add make3.81
to the kernel's makedepends
line.
Using a specific kernel image
By default downstreamkernel_package.sh looks for a few kernel image files such as Image.gz-dtb
and *zImage
, but for various reasons you may want/need to look for something else; in these situations set KERNEL_IMAGE_NAME
similar to the following:
package() {
KERNEL_IMAGE_NAME="Image.gz" downstreamkernel_package \
"$builddir" "$pkgdir" "$_carch" "$_flavor" "$_outdir"
}
heimdall-isorec
If you have a device that only boots with heimdall-isorec, you will need to adjust your linux APKBUILD as follows:
- add
busybox-static-armhf
to makedepends - copy the "init" file from
linux-samsung-i9100
and customize the partition - add "init" to
source=
in the APKBUILD - adjust your
prepare()
like it's done inlinux-samsung-i9100
and adjust the paths in there
You can search for more examples of heimdall-isorec deviecs with grep:
$ grep -r 'deviceinfo_flash_method="heimdall-isorec"' aports
aports/device/device-samsung-i9070/deviceinfo:deviceinfo_flash_method="heimdall-isorec"
aports/device/device-samsung-i9100/deviceinfo:deviceinfo_flash_method="heimdall-isorec"
See also
- How to properly backup downstream kernels
- Troubleshooting:kernel
- device specific package
- pmaports#103 Adjust to GCC8 upgrade in Alpine edge
- pmaports!30 device/linux-*: use GCC-6 for all 3.x kernels