Normally to cross compile a LineageOS kernel requires a massive amount of storage as it requires downloading the entirety of the android source, including building LineageOS itself, which you may not care to do if you just want to fiddle with kernel configuration or patching.
Here's a way around that! (In the form of a script with comments.)
Special thanks to this blog post in particular, which does a decent job of explaining what to do-- hopefully my comments offer some additional clarification.
#!/bin/sh -e
# First we need to download the correct kernel for the device; in my case I have a Galaxy Tab S5e,
# so this is the correct repo ("sdm670" refers to the snapdragon 670 chipset used in it).
#
# As an aside, the "|| true" on the "git clone" line is just a lazy way of allowing the script to be
# re-run without failing if the directory already exists.
KERNEL_NAME=android_kernel_samsung_sdm670
KERNEL_URL=https://github.com/LineageOS/$KERNEL_NAME
git clone $KERNEL_URL -b lineage-21 || true
# Annoyingly, instead of using the usual "aarch64-linux-gnu" cross compilation toolchain which you may already
# have installed, Android (and by extension LineageOS) requires that we use their own custom toolchain. We
# need one repo for the clang compiler, one for x86-to-ARM64 GCC cross compilation tools, and one for
# x86-to-ARM32 GCC cross compilation tools. If you have a phone or tablet with an x86 processor instead
# you'll want to download the X86 GCC toolchain for that instead of the ARM ones.
#
# The correct branch for these (as indicated by the "-b" flag on each of these lines) can be found by going to
# https://github.com/LineageOS/android then setting the branch to the version of LineageOS we want to build
# the kernel for, then looking at "snippets/lineage.xml", pressing ctrl+f, and searching for lines with
# "prebuilts/" in them; it should be listed in the "revision" field of the same line.
git clone https://github.com/LineageOS/android_prebuilts_clang_kernel_linux-x86_clang-r416183b \
-b lineage-20.0 || true
git clone https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_aarch64_aarch64-linux-android-4.9 \
-b lineage-19.1 || true
git clone https://github.com/LineageOS/android_prebuilts_gcc_linux-x86_arm_arm-linux-androideabi-4.9 \
-b lineage-19.1 || true
# Let's take note of the directory everything is sitting in, just so I can avoid using relative paths later.
# Then we can go ahead and step into the kernel directory.
BASEDIR=$PWD
cd $KERNEL_NAME
# This line just ensures that everything is cleaned up, including deleting any old kernel config files.
# Many tutorials do "make clean" before this, but the "make mrproper" target actually invokes that one,
# so it's pointless to do so.
#
# (If you're confused like I was: "Mr. Proper" is apparently what some countries call "Mr. Clean".)
make mrproper
# Having an explicit output directory isn't necessary, but it's nice, so why not?
# When we build our kernel later the result should be in $KERNEL_NAME/out.
mkdir -p out
# Next we need to set up the correct kernel config for the device.
# We can find the available configs by navigating to $KERNEL_NAME/arch/arm64/configs.
# Note that "arm64" in that path may need to be changed depending what kind of device you have.
# In my case, the codename for the Galaxy Tab S5e is "gts4lv", so I've picked "gts4lv_defconfig".
#
# I initially wasted a bunch of time trying to get "sdm670-perf_defconfig" and "sdm670_defconfig" to work,
# but they repeatedly gave me compile errors-- look for your device's name first and foremost in case a config
# is offered for it, not just the chipset's name!
make \
O=out \
ARCH=arm64 \
gts4lv_defconfig
# Next, I'll note down the locations of each of the toolchain directories we care about,
# since they're each quite a mouthful and "GCCDIR" happens to be referred to twice.
GCCDIR=$BASEDIR/android_prebuilts_gcc_linux-x86_aarch64_aarch64-linux-android-4.9
GCCDIR32=$BASEDIR/android_prebuilts_gcc_linux-x86_arm_arm-linux-androideabi-4.9
CLANGDIR=$BASEDIR/android_prebuilts_clang_kernel_linux-x86_clang-r416183b
# Finally, we get to build the kernel. While normally I'd just export environment variables
# (and indeed that would save some duplication, for instance having to re-state "ARCH" from earlier)
# it seems like linux's makefile likes to ignore some environment variables so I've opted against it
# even when it may not always be necessary, just for consistency.
#
# Specifying "CLANG_TRIPLE" is usually unnecessary as it would be inferred from "CROSS_COMPILE", but
# in the case of Android this breaks the stack protector for whatever reason, or so I've read.
# So we need to specify it to be "aarch64-linux-gnu-".
#
# Specifying "LLVM=1" will automatically specify things like "CC=clang" and such for you, so
# specifying CC or NM or LD or AR etc. is generally unnecessary.
#
# When targeting an x86 device, or one which is ARM32 in the first place, the "CROSS_COMPILE_ARM32"
# flag should be removed.
#
# Finally, "-j$(nproc)" should automatically expand out to e.g. "-j4" if you have 4 cores,
# letting the build run multithreaded so it will complete faster.
make \
O=out \
ARCH=arm64 \
PATH=$CLANGDIR/bin:$GCCDIR/bin:$PATH \
LD_LIBRARY_PATH=$CLANGDIR/lib \
LLVM=1 \
CROSS_COMPILE=$GCCDIR/bin/aarch64-linux-android- \
CROSS_COMPILE_ARM32=$GCCDIR32/bin/arm-linux-androideabi- \
CLANG_TRIPLE=aarch64-linux-gnu- \
-j$(nproc)
Additional side note that may be of use: adb shell zcat /proc/config.gz
can be used to grab the kernel config from your device.
Also worth noting that using a separate output directory means the kernel config is at out/.config
, so make menuconfig
won't work how you expect unless you do make O=out menuconfig
.