Skip to content

Build kernels

Build kernels #68

Workflow file for this run

name: Build kernels
on:
push:
paths:
- ".github/workflows/kernel.yml"
workflow_dispatch:
schedule:
- cron: "14 13 * * 5"
jobs:
Read-configuration:
name: 🐂 Parse *.config.json
runs-on: ubuntu-latest
outputs:
CONFIGS: ${{ steps.generate-matrix.outputs.CONFIGS }}
BUILD_DATE: ${{ steps.generate-builddate.outputs.BUILDDATE }}
steps:
# This action checks-out your CONFIGSitory under $GITHUB_WORKSPACE, so your workflow can access it.
- name: 😄 Checkout
uses: actions/checkout@v4
# Match the configuration files in the CONFIGS directory, read the contents and merge them into an array.
- name: 😆 Generate Matrix
id: generate-matrix
run: |
echo "CONFIGS<<EOF" >> $GITHUB_OUTPUT
jq -s '[.[][]]' Kernel/configs/*.config.json >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Set compile time.
- name: ⏰ Set builddate
id: generate-builddate
run: echo "BUILDDATE=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
Build-Kernel:
name: "🐎 Build kernel"
runs-on: ubuntu-latest
needs:
- Read-configuration
strategy:
max-parallel: 4
fail-fast: false
matrix:
CONFIG: ${{ fromJSON(needs.Read-configuration.outputs.CONFIGS) }}
env:
# Basic configuration
WORKSPACE: ${{ github.workspace }}
BUILD_DATE: "${{ needs.Read-configuration.outputs.BUILD_DATE }}"
# Kernel source configuration
KERNEL_NAME: ${{ matrix.CONFIG.kernelSource.name }}
KERNEL_REPO: ${{ matrix.CONFIG.kernelSource.repo }}
KERNEL_BRANCH: ${{ matrix.CONFIG.kernelSource.branch }}
KERNEL_DEVICE: ${{ matrix.CONFIG.kernelSource.device }}
KERNEL_DEFCONFIG_PATH: ${{ matrix.CONFIG.kernelSource.defconfig }}
# Whether to use ccache to speed up compilation
ENABLE_CCACHE: ${{ matrix.CONFIG.enableCcache }}
# Whether to use ANYKERNEL3 packaged flash package
USE_ANYKERNEL3: ${{ matrix.CONFIG.AnyKernel3.use }}
# Whether to publish
CONFIRM_RELEASE: ${{ matrix.CONFIG.AnyKernel3.release }}
# Whether to enable KernelSU
ENABLE_KERNELSU: ${{ matrix.CONFIG.enableKernelSU }}
# Whether to enable LXC docker
ENABLE_LXC: ${{ matrix.CONFIG.enableLXC }}
# Set output & ccache directory
OUT_DIR: "${{ github.workspace }}/out"
CCACHE_DIR: "${{ github.workspace }}/ccache"
steps:
# Set swap space
- name: 📐 Set swap to 10G
uses: pierotofy/set-swap-space@master
with:
swap-size-gb: 10
# This action checks-out your CONFIGSitory under $GITHUB_WORKSPACE, so your workflow can access it.
- name: 😄 Checkout
uses: actions/checkout@v4
# Install prerequisites for Ubuntu
- name: ⭐ Install prerequisites
run: |
sudo apt-get update
sudo apt-get install -y curl git ftp lftp wget libarchive-tools ccache python2 python2-dev python3
sudo apt-get install -y pngcrush schedtool dpkg-dev liblz4-tool make optipng maven device-tree-compiler
sudo apt-get install -y libc6-dev-i386 lib32ncurses5-dev libx11-dev lib32z-dev libgl1-mesa-dev xsltproc
sudo apt-get install -y libxml2-utils libbz2-dev libbz2-1.0 libghc-bzlib-dev squashfs-tools lzop flex tree
sudo apt-get install -y build-essential bc gcc-aarch64-linux-gnu gcc-arm-linux-gnueabi libssl-dev libfl-dev
sudo apt-get install -y pwgen libswitch-perl policycoreutils minicom libxml-sax-base-perl libxml-simple-perl
sudo apt-get install -y zip unzip tar gzip bzip2 rar unrar llvm g++-multilib bison gperf zlib1g-dev automake
# Initialize ccache
- name: 🚄 Setup ccache
if: ${{ env.ENABLE_CCACHE == 'true' }}
id: hash
run: |
# Create output directory
mkdir -p ${{ env.OUT_DIR }}
# Initialize ccache
ccache -o compression=false -o cache_dir=${{ env.CCACHE_DIR }}
# Generate configuration's hash
echo $(echo -n '${{ toJSON(matrix.config) }}' | openssl dgst -sha1 | awk '{print $2}')
echo "HASH=$(echo -n '${{ toJSON(matrix.config) }}' | openssl dgst -sha1 | awk '{print $2}')" >> $GITHUB_OUTPUT
- name: 🚅 Cache ccache & output
env:
HASH: ${{ steps.hash.outputs.HASH }}
if: ${{ env.ENABLE_CCACHE == 'true' }}
uses: actions/cache@v3
with:
path: |
${{ env.OUT_DIR }}
${{ env.CCACHE_DIR }}
key: cache-${{ env.KERNEL_NAME }}-${{env.HASH}}-${{ env.BUILD_DATE }}
restore-keys: |
cache-${{ env.KERNEL_NAME }}-${{env.HASH}}-${{ env.BUILD_DATE }}
cache-${{ env.KERNEL_NAME }}-${{env.HASH}}-
cache-${{ env.KERNEL_NAME }}-
- name: 🌟 Clone kernel source => (${{ env.KERNEL_REPO }})
run: |
git clone --recursive --depth=1 -j $(nproc) --branch ${{ env.KERNEL_BRANCH }} ${{ env.KERNEL_REPO }} ${{ env.KERNEL_NAME }}
# tree ${{ env.KERNEL_NAME }}
- name: 💫 Get toolchains
env:
toolchains: "${{ toJSON(matrix.CONFIG.toolchains) }}"
run: |
toolchains_num="$(echo $toolchains | jq 'length')"
echo "🤔 There is $toolchains_num defined toolchains."
for ((i=0;i<toolchains_num;i++)); do
toolchain=$(echo $toolchains | jq -r ".[$i]")
toolchain_name=$(echo $toolchain | jq -r ".name")
# From archive
if echo $toolchain | jq -e 'has("url")' > /dev/null; then
# If from archive
toolchain_url=$(echo $toolchain | jq -r ".url")
mkdir -p $toolchain_name
# Download archive
wget "$toolchain_url"
# Get filename
filename="${toolchain_url##*/}"
case "$filename" in
*.zip)
unzip -d $toolchain_name "$filename"
;;
*.tar)
tar xvf "$filename" -C $toolchain_name
;;
*.tar.gz)
tar zxvf "$filename" -C $toolchain_name
;;
*.rar)
unrar x "$filename" $toolchain_name
;;
*)
echo "unknown file type: $filename"
;;
esac
# Delete file to avoid duplicate name conflicts
rm $filename
echo "🤔 Download $toolchain_name => ($toolchain_url)"
else
# If from git
toolchain_repo=$(echo $toolchain | jq -r ".repo")
toolchain_branch=$(echo $toolchain | jq -r ".branch")
git clone --recursive --depth=1 -j $(nproc) --branch $toolchain_branch $toolchain_repo $toolchain_name
echo "🤔 Clone $toolchain_name => ($toolchain_repo)"
fi
jq -r ".binaryEnv[] | tostring" <<< "$toolchain" | while read -r subPath; do
echo "${{ env.WORKSPACE }}/$toolchain_name/$subPath" >> $GITHUB_PATH
done
done
- name: 😎 Set build args
id: generate-args
env:
PARAMS: "${{ toJSON(matrix.CONFIG.params) }}"
THREAD: $(nproc --all)
run: |
echo "🤔 PATH Variable: $PATH"
ARCH=$(echo $PARAMS | jq -r ".ARCH")
CC=$(echo $PARAMS | jq -r ".CC")
args="-j${{ env.THREAD }} O=${{ env.OUT_DIR }} ARCH=$ARCH"
if [ -n "$CC" ]; then
if [[ "$CC" == *"/"* ]]; then
CC=${{ env.WORKSPACE }}/$CC
fi
if [ ${{ env.ENABLE_CCACHE }} = true ]; then
args="$args CC=\"ccache $CC\""
else
args="$args CC=$CC"
fi
fi
while read -r externalCommand; do
key=$(echo "$externalCommand" | cut -d= -f1)
value=$(echo "$externalCommand" | cut -d= -f2)
if [[ "$value" == *"/"* ]]; then
value="${{ env.WORKSPACE }}/$value"
fi
args="$args $key=$value"
done < <(jq -r '.externalCommands | to_entries[] | "\(.key)=\(.value)"' <<< "$PARAMS")
echo "ARCH=$ARCH" >> $GITHUB_OUTPUT
echo "ARGS=$args" >> $GITHUB_OUTPUT
echo "🤔 $args"
- name: 😋 Setup KernelSU
working-directory: ${{ env.KERNEL_NAME }}
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
if: ${{ env.ENABLE_KERNELSU == 'true' }}
run: |
# Delete old KernelSU
if [ -d "./KernelSU" ]; then
rm -rf "./KernelSU"
fi
if [ -d "./drivers/kernelsu" ]; then
rm -rf "./drivers/kernelsu"
fi
# Apply new KernelSU patches
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
cat arch/${{ env.ARCH }}/configs/${{ env.KERNEL_DEFCONFIG_PATH }}
- name: 😋 Setup LXC docker
working-directory: ${{ env.KERNEL_NAME }}
env:
DEFCONFIG: ${{ env.WORKSPACE }}/${{ env.KERNEL_NAME }}/arch/${{ steps.generate-args.outputs.ARCH }}/configs/${{env.KERNEL_DEFCONFIG_PATH}}
ADD_DEFCONFIG: ${{ env.WORKSPACE }}/LXC/LXC_defconfig
if: ${{ env.ENABLE_LXC == 'true' }}
run: |
# Add configuration
for config in $(cat ${{ env.ADD_DEFCONFIG }})
do
echo $i >> ${{ env.DEFCONFIG }}
done
# Apply patch
if [ -f kernel/cgroup.c ]; then
row=$(sed -n -e '/^static int cgroup_add_file/=' kernel/cgroup.c)
touch /tmp/tmp.txt
sed -n -e '/static int cgroup_add_file/,/return 0/p' kernel/cgroup.c >> /tmp/tmp.txt
row2=$(sed -n -e '/return 0/=' /tmp/tmp.txt)
row3=$(echo `expr $row + $row2 - 1`)
sed -i "$row3 i\ }" kernel/cgroup.c
sed -i "$row3 i\ kernfs_create_link(cgrp->kn, name, kn);" kernel/cgroup.c
sed -i "$row3 i\ snprintf(name, CGROUP_FILE_NAME_MAX, \"%s.%s\", cft->ss->name, cft->name);" kernel/cgroup.c
sed -i "$row3 i\ if (cft->ss && (cgrp->root->flags & CGRP_ROOT_NOPREFIX) && !(cft->flags & CFTYPE_NO_PREFIX)) {" kernel/cgroup.c
echo "🎖️ Modify kernel/cgroup.c"
fi
if [ -f kernel/cgroup/cgroup.c ]; then
row=$(sed -n -e '/^static int cgroup_add_file/=' kernel/cgroup/cgroup.c)
touch /tmp/tmp.txt
sed -n -e '/static int cgroup_add_file/,/return 0/p' kernel/cgroup/cgroup.c >> /tmp/tmp.txt
row2=$(sed -n -e '/return 0/=' /tmp/tmp.txt)
row3=$(echo `expr $row + $row2 - 1`)
sed -i "$row3 i\ }" kernel/cgroup/cgroup.c
sed -i "$row3 i\ kernfs_create_link(cgrp->kn, name, kn);" kernel/cgroup/cgroup.c
sed -i "$row3 i\ snprintf(name, CGROUP_FILE_NAME_MAX, \"%s.%s\", cft->ss->name, cft->name);" kernel/cgroup/cgroup.c
sed -i "$row3 i\ if (cft->ss && (cgrp->root->flags & CGRP_ROOT_NOPREFIX) && !(cft->flags & CFTYPE_NO_PREFIX)) {" kernel/cgroup/cgroup.c
echo "🎖️ Modify kernel/cgroup/cgroup.c"
fi
if [ -f android-kernel/net/netfilter/xt_qtaguid.c ]; then
git am -s < ${{ env.WORKSPACE }}/LXC/Patches/xt_qtaguid.patch
echo "🎖️ Apply xt_qtaguid.patch"
fi
- name: 👍 Start building the kernel
working-directory: ${{ env.KERNEL_NAME }}
env:
ARGS: ${{ steps.generate-args.outputs.ARGS }}
run: |
echo "🤔 PATH Variable: $PATH"
export KBUILD_BUILD_HOST=Github-Action
export KBUILD_BUILD_USER=$(echo ${{ github.actor }} | tr A-Z a-z)
make ${{ env.ARGS }} ${{ env.KERNEL_DEFCONFIG_PATH }}
make ${{ env.ARGS }}
# tree ${{ env.OUT_DIR }}
- name: 💛 Upload Image
uses: actions/upload-artifact@v4
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
with:
name: ${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}-Image
path: ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image
if-no-files-found: ignore
retention-days: 7
- name: 💙 Upload Image.gz
uses: actions/upload-artifact@v4
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
with:
name: ${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}-Image.gz
path: ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image.gz
if-no-files-found: ignore
retention-days: 7
- name: 💙 Upload Image.gz-dtb
uses: actions/upload-artifact@v4
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
with:
name: ${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}-Image.gz-dtb
path: ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image.gz-dtb
if-no-files-found: ignore
retention-days: 7
- name: 💜 Upload dtb
uses: actions/upload-artifact@v4
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
with:
name: ${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}-dtb
path: ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/dtb
if-no-files-found: ignore
retention-days: 7
- name: ❤️ Upload dtbo.img
uses: actions/upload-artifact@v4
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
with:
name: ${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}-dtbo.img
path: ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/dtbo.img
if-no-files-found: ignore
retention-days: 7
- name: ☢️ Upload output directory
uses: actions/upload-artifact@v4
env:
ARCH: ${{ steps.generate-args.outputs.ARCH }}
with:
name: ${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}-Output
path: ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/
retention-days: 7
- name: ⏰ Pack Anykernel3
if: ${{ env.USE_ANYKERNEL3 == 'true' }}
env:
PARAMS: "${{ toJSON(matrix.CONFIG.AnyKernel3) }}"
ARCH: ${{ steps.generate-args.outputs.ARCH }}
ANYKERNEL3_FILE: "${{ env.WORKSPACE }}/AnyKernel3-${{ env.KERNEL_NAME }}-${{ env.BUILD_DATE }}"
run: |
if echo -n '${{ env.PARAMS }}' | jq -e 'has("custom")' > /dev/null; then
CUSTOM_ANYKERNEL3=$(echo -n '${{ env.PARAMS }}' | jq -r ".custom")
ANYKERNEL_REPO=$(echo $CUSTOM_ANYKERNEL3 | jq -r ".repo")
ANYKERNEL_BRANCH=$(echo $CUSTOM_ANYKERNEL3 | jq -r ".branch")
git clone --recursive --depth=1 -j $(nproc) --branch $ANYKERNEL_BRANCH $ANYKERNEL_REPO AnyKernel3
echo "🤔 Use custom AnyKernel3 => ($ANYKERNEL_REPO)"
else
git clone --recursive --depth=1 -j $(nproc) https://github.com/osm0sis/AnyKernel3 AnyKernel3
sed -i 's/do.devicecheck=1/do.devicecheck=0/g' AnyKernel3/anykernel.sh
sed -i 's!block=/dev/block/platform/omap/omap_hsmmc.0/by-name/boot;!block=auto;!g' AnyKernel3/anykernel.sh
sed -i 's/is_slot_device=0;/is_slot_device=auto;/g' AnyKernel3/anykernel.sh
echo "🤔 Use origin Anykernel3 => (https://github.com/osm0sis/AnyKernel3)"
fi
mkdir -p ./AnyKernel3/kernels/hos
if [ -e "${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image.gz-dtb" ]; then
cp -f ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image.gz-dtb ./AnyKernel3/kernels/hos/
else
if [ -e "${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image" ]; then
cp -f ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image ./AnyKernel3//kernels/hos/
fi
if [ -e "${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image.gz" ]; then
cp -f ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/Image.gz ./AnyKernel3//kernels/hos/
fi
if [ -e "${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/dtbo" ]; then
cp -f ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/dtbo ./AnyKernel3//kernels/hos/
fi
if [ -e "${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/dtbo.img" ]; then
cp -f ${{ env.OUT_DIR }}/arch/${{ env.ARCH }}/boot/dtbo.img ./AnyKernel3//kernels/hos/
fi
fi
cd AnyKernel3/
zip -q -r "${{ env.ANYKERNEL3_FILE }}.zip" *
- name: "💾 Upload AnyKernel3 image => (${{ env.BUILD_DATE }})"
env:
ANYKERNEL3_FILE: "${{ env.KERNEL_NAME }}-${{ env.KERNEL_DEVICE }}-hyperos-${{ env.BUILD_DATE }}"
uses: actions/upload-artifact@v3
if: ${{ env.USE_ANYKERNEL3 == 'true' }}
with:
name: "${{ env.ANYKERNEL3_FILE }}"
path: AnyKernel3/*
- name: 🧧 Create GitHub Release => (${{ env.BUILD_DATE }})
env:
ANYKERNEL3_FILE: "${{ env.WORKSPACE }}/${{ env.KERNEL_NAME }}-${{ env.KERNEL_DEVICE }}-hyperos-${{ env.BUILD_DATE }}"
continue-on-error: true
uses: softprops/action-gh-release@v1
if: ${{ env.USE_ANYKERNEL3 == 'true' && env.CONFIRM_RELEASE == 'true' }}
with:
tag_name: v${{ env.BUILD_DATE }}.${{ github.run_number }}
files: "${{ env.ANYKERNEL3_FILE }}.zip"
generate_release_notes: true