Update build-kernel.yml #76
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ################################################################################ | ||
| # Advanced / “Complex” Android Kernel Build Workflow (Plan C Primary: Clang + GCC binutils) | ||
| # | ||
| # Key Features: | ||
| # - Matrix over requested build “targets” (ksun / suki etc.) with per-target env configs | ||
| # - Plan C: Clang primary + optional GCC (64/32) binutils; fallback to pure GCC if chosen | ||
| # - Strong validation (toolchain guards, config file presence) | ||
| # - Automatic detection & FAIL for stray literal 'false' token in compile lines | ||
| # - Optional suppression wrapper (can be enabled via input if you want to ignore 'false') | ||
| # - CCache support | ||
| # - Toolchain caching (actions/cache) to avoid re‑downloading between runs | ||
| # - Optional “release build” switch: creates a GitHub Release (draft) with artifacts | ||
| # - Optional Kconfig patching / KernelSU / KPM / AnyKernel3 packaging | ||
| # - Rich job summary (markdown) showing build metadata & artifact sizes | ||
| # - Separate “prepare-toolchains” job to avoid repeated downloads for matrix | ||
| # - Diagnostics: environment dump, defconfig diff, grep for cc-option misuse | ||
| # | ||
| # Usage: | ||
| # 1. Provide per-target env files: config-ksun.env, config-suki.env, etc. | ||
| # 2. Only put “clean” variable assignments (KEY=VALUE) in those files. | ||
| # 3. Run workflow manually via Workflow Dispatch. | ||
| # | ||
| # Notes: | ||
| # - The “false” token error you encountered is trapped early; you *must* fix the | ||
| # offending cc-option usage in the kernel tree. The workflow will exit with a | ||
| # human-readable report pointing to possible files. | ||
| # - To temporarily bypass (NOT recommended) you can set the dispatch input | ||
| # allow_false_wrapper: true (adds a wrapper that strips literal `false` args). | ||
| ################################################################################ | ||
| name: Complex Kernel Build | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| select_device: | ||
| description: 'Select device codename (must match DEVICE in defconfig name: <device>_defconfig)' | ||
| required: true | ||
| type: choice | ||
| options: | ||
| - lancelot | ||
| - merlin | ||
| build_ksun: | ||
| description: 'Build KernelSU-Next (A13+)' | ||
| required: true | ||
| default: true | ||
| type: boolean | ||
| build_ksun_old: | ||
| description: 'Build KernelSU-Next (A11+)' | ||
| required: true | ||
| default: false | ||
| type: boolean | ||
| build_suki: | ||
| description: 'Build SukiSU (A13+)' | ||
| required: true | ||
| default: true | ||
| type: boolean | ||
| build_suki_old: | ||
| description: 'Build SukiSU (A11+)' | ||
| required: true | ||
| default: false | ||
| type: boolean | ||
| release_build: | ||
| description: 'Create (draft) GitHub Release with artifacts' | ||
| required: true | ||
| default: false | ||
| type: boolean | ||
| allow_false_wrapper: | ||
| description: 'TEMPORARY: Strip stray literal "false" tokens instead of failing (debug aid)' | ||
| required: true | ||
| default: false | ||
| type: boolean | ||
| concurrency: | ||
| group: complex-kernel-${{ github.ref }}-${{ github.event.inputs.select_device }} | ||
| cancel-in-progress: true | ||
| env: | ||
| # Global defaults (can be overridden by per-target config-*.env files) | ||
| KERNEL_ARCH: arm64 | ||
| KERNEL_IMAGE_NAME: Image.gz-dtb | ||
| # Plan C defaults – expect Clang + GCC binutils | ||
| USE_CLANG: "true" | ||
| USE_GCC: "false" | ||
| USE_GCC_64: "true" | ||
| USE_GCC_32: "true" | ||
| # You should override CLANG_SOURCE in per-target configs if different | ||
| CLANG_SOURCE: https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.6/clang+llvm-17.0.6-x86_64-linux-gnu-ubuntu-22.04.tar.xz | ||
| # Artifact retention tuning | ||
| ARTIFACT_RETENTION_DAYS: 7 | ||
| # Fail the build if stray literal 'false' appears in compile command line | ||
| FAIL_ON_FALSE: "true" | ||
| permissions: | ||
| contents: write # Needed for creating a release | ||
| actions: read | ||
| checks: read | ||
| statuses: read | ||
| ################################################################################ | ||
| # Job: Generate matrix based on dispatch booleans | ||
| ################################################################################ | ||
| jobs: | ||
| generate-matrix: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| matrix: ${{ steps.mk.outputs.matrix }} | ||
| steps: | ||
| - name: Compute targets | ||
| id: mk | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| declare -a targets=() | ||
| [[ "${{ github.event.inputs.build_ksun }}" == "true" ]] && targets+=("ksun") | ||
| [[ "${{ github.event.inputs.build_ksun_old }}" == "true" ]] && targets+=("ksun-old") | ||
| [[ "${{ github.event.inputs.build_suki }}" == "true" ]] && targets+=("suki") | ||
| [[ "${{ github.event.inputs.build_suki_old }}" == "true" ]] && targets+=("suki-old") | ||
| if [[ ${#targets[@]} -eq 0 ]]; then | ||
| echo "No targets selected"; exit 1 | ||
| fi | ||
| json=$(printf '%s\n' "${targets[@]}" | jq -R . | jq -s '{target: .}') | ||
| echo "matrix=$json" >> "$GITHUB_OUTPUT" | ||
| echo "Matrix: $json" | ||
| ################################################################################ | ||
| # Job: Prepare toolchains (cached) – runs once, provides artifact or cache | ||
| ################################################################################ | ||
| prepare-toolchains: | ||
| runs-on: ubuntu-24.04 | ||
| needs: generate-matrix | ||
| outputs: | ||
| clang_path: ${{ steps.out.outputs.clang_path }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Read first target config (to pick toolchain URLs) | ||
| id: cfg | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| FIRST="${{ fromJson(needs.generate-matrix.outputs.matrix).target[0] }}" | ||
| BASE="${FIRST/-old/}" | ||
| FILE="config-${BASE}.env" | ||
| if [[ ! -f "$FILE" ]]; then | ||
| echo "Missing configuration file $FILE" >&2 | ||
| exit 1 | ||
| fi | ||
| # Export into environment; we only harvest toolchain URL overrides | ||
| grep -v -E '^#|^[[:space:]]*$' "$FILE" | sed 's/[[:space:]]*#.*//' >> "$GITHUB_ENV" | ||
| - name: Restore Clang cache | ||
| id: cache-clang | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| toolchains/clang | ||
| key: clang-${{ env.CLANG_SOURCE }} | ||
| - name: Restore GCC 64 cache | ||
| if: env.USE_GCC_64 == 'true' | ||
| id: cache-gcc64 | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: toolchains/gcc-64 | ||
| key: gcc64-${{ env.GCC_64_SOURCE }} | ||
| - name: Restore GCC 32 cache | ||
| if: env.USE_GCC_32 == 'true' | ||
| id: cache-gcc32 | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: toolchains/gcc-32 | ||
| key: gcc32-${{ env.GCC_32_SOURCE }} | ||
| - name: Download Clang (if cache miss) | ||
| if: steps.cache-clang.outputs.cache-hit != 'true' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p toolchains | ||
| cd toolchains | ||
| url="${{ env.CLANG_SOURCE }}" | ||
| echo "Downloading Clang: $url" | ||
| case "$url" in | ||
| *.tar.xz) wget -nv -O clang.tar.xz "$url"; mkdir clang; tar -C clang -Jxvf clang.tar.xz --strip-components=1; rm clang.tar.xz ;; | ||
| *.tar.gz) wget -nv -O clang.tar.gz "$url"; mkdir clang; tar -C clang -zxvf clang.tar.gz --strip-components=1; rm clang.tar.gz ;; | ||
| *) echo "Unsupported Clang archive: $url"; exit 1 ;; | ||
| esac | ||
| file clang/bin/clang | ||
| clang/bin/clang --version | ||
| - name: Download GCC 64 (if needed) | ||
| if: env.USE_GCC_64 == 'true' && steps.cache-gcc64.outputs.cache-hit != 'true' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p toolchains | ||
| cd toolchains | ||
| url="${{ env.GCC_64_SOURCE }}" | ||
| if [[ -z "$url" ]]; then | ||
| echo "GCC_64_SOURCE empty but USE_GCC_64=true"; exit 1 | ||
| fi | ||
| wget -nv -O gcc-64.tar.xz "$url" | ||
| mkdir gcc-64 | ||
| tar -C gcc-64 -Jxvf gcc-64.tar.xz --strip-components=1 | ||
| rm gcc-64.tar.xz | ||
| ls gcc-64/bin | head | ||
| - name: Download GCC 32 (if needed) | ||
| if: env.USE_GCC_32 == 'true' && steps.cache-gcc32.outputs.cache-hit != 'true' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p toolchains | ||
| cd toolchains | ||
| url="${{ env.GCC_32_SOURCE }}" | ||
| if [[ -z "$url" ]]; then | ||
| echo "GCC_32_SOURCE empty but USE_GCC_32=true"; exit 1 | ||
| fi | ||
| wget -nv -O gcc-32.tar.xz "$url" | ||
| mkdir gcc-32 | ||
| tar -C gcc-32 -Jxvf gcc-32.tar.xz --strip-components=1 | ||
| rm gcc-32.tar.xz | ||
| ls gcc-32/bin | head | ||
| - name: Archive toolchains for matrix jobs (if not cached) | ||
| # Archive only if any cache misses occurred, so matrix can reuse quickly | ||
| if: | | ||
| steps.cache-clang.outputs.cache-hit != 'true' || | ||
| (env.USE_GCC_64 == 'true' && steps.cache-gcc64.outputs.cache-hit != 'true') || | ||
| (env.USE_GCC_32 == 'true' && steps.cache-gcc32.outputs.cache-hit != 'true') | ||
| run: | | ||
| set -euo pipefail | ||
| tar -C toolchains -Jcvf toolchains.tar.xz . | ||
| shell: bash | ||
| - name: Upload toolchain bundle (only on new downloads) | ||
| if: | | ||
| steps.cache-clang.outputs.cache-hit != 'true' || | ||
| (env.USE_GCC_64 == 'true' && steps.cache-gcc64.outputs.cache-hit != 'true') || | ||
| (env.USE_GCC_32 == 'true' && steps.cache-gcc32.outputs.cache-hit != 'true') | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: toolchains-bundle | ||
| path: toolchains.tar.xz | ||
| retention-days: 3 | ||
| - name: Output clang dir | ||
| id: out | ||
| run: | | ||
| echo "clang_path=toolchains/clang" >> "$GITHUB_OUTPUT" | ||
| ################################################################################ | ||
| # Job: Build (matrix) | ||
| ################################################################################ | ||
| build: | ||
| needs: [generate-matrix, prepare-toolchains] | ||
| runs-on: ubuntu-24.04 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }} | ||
| env: | ||
| DEVICE: ${{ github.event.inputs.select_device }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Fetch toolchain bundle (if present & not cached) | ||
| if: always() | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: toolchains-bundle | ||
| path: . | ||
| - name: Extract toolchain bundle | ||
| if: hashFiles('toolchains.tar.xz') != '' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p toolchains | ||
| tar -C toolchains -Jxvf toolchains.tar.xz | ||
| - name: Install system deps | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| sudo apt-get update | ||
| sudo apt-get install -y \ | ||
| lld bc bison build-essential ccache curl flex g++-multilib gcc-multilib git git-lfs gnupg gperf \ | ||
| imagemagick lib32ncurses-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5-dev \ | ||
| libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip \ | ||
| zlib1g-dev python3 jq unzip wget cpio tar xz-utils zstd patchelf pkg-config libelf-dev \ | ||
| libdw-dev libiberty-dev file bc | ||
| - name: Prepare build workspace | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| mkdir -p "$GITHUB_WORKSPACE/kernel_workspace" | ||
| - name: Load per-target config | ||
| id: loadcfg | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| TARGET="${{ matrix.target }}" | ||
| BASE="${TARGET/-old/}" | ||
| FILE="config-${BASE}.env" | ||
| if [[ ! -f "$FILE" ]]; then | ||
| echo "Missing $FILE" >&2 | ||
| exit 1 | ||
| fi | ||
| echo "Using config file: $FILE" | ||
| grep -v -E '^#|^[[:space:]]*$' "$FILE" | sed 's/[[:space:]]*#.*//' >> "$GITHUB_ENV" | ||
| if [[ "$TARGET" == *"-old" ]]; then | ||
| echo "ANDROID_TAG=[A11+]" >> "$GITHUB_ENV" | ||
| echo "OLD_ANDROID_SUPPORT=true" >> "$GITHUB_ENV" | ||
| else | ||
| echo "ANDROID_TAG=[A13+]" >> "$GITHUB_ENV" | ||
| fi | ||
| echo "BUILD_TIME=$(TZ=UTC date '+%Y%m%d%H%M')" >> "$GITHUB_ENV" | ||
| - name: Validate toolchain mode (Plan C expectation) | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| echo "USE_CLANG=${{ env.USE_CLANG }}" | ||
| echo "USE_GCC=${{ env.USE_GCC }}" | ||
| if [[ "${{ env.USE_CLANG }}" != "true" ]]; then | ||
| echo "Plan C expects USE_CLANG=true; continuing but verify intentionally changed." | ||
| fi | ||
| if [[ "${{ env.USE_CLANG }}" == "true" && "${{ env.USE_GCC }}" == "true" ]]; then | ||
| echo "ERROR: Both USE_CLANG and USE_GCC are true. Aborting." >&2 | ||
| exit 1 | ||
| fi | ||
| if [[ "${{ env.USE_GCC_32 }}" == "true" ]]; then | ||
| echo "CROSS_COMPILE_ARM32=arm-linux-gnueabihf-" >> "$GITHUB_ENV" | ||
| echo "CROSS_COMPILE_COMPAT=arm-linux-gnueabihf-" >> "$GITHUB_ENV" | ||
| fi | ||
| - name: Place toolchains into PATH | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| if [[ -d toolchains/clang/bin ]]; then | ||
| echo "Adding Clang to PATH" | ||
| echo "$GITHUB_WORKSPACE/toolchains/clang/bin" >> $GITHUB_PATH | ||
| fi | ||
| [[ -d toolchains/gcc-64/bin ]] && echo "$GITHUB_WORKSPACE/toolchains/gcc-64/bin" >> $GITHUB_PATH | ||
| [[ -d toolchains/gcc-32/bin ]] && echo "$GITHUB_WORKSPACE/toolchains/gcc-32/bin" >> $GITHUB_PATH | ||
| - name: Toolchain sanity check | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| which clang || true | ||
| which aarch64-linux-gnu-gcc || true | ||
| which arm-linux-gnueabihf-gcc || true | ||
| clang --version || true | ||
| aarch64-linux-gnu-gcc --version || true | ||
| - name: Download kernel source | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| cd kernel_workspace | ||
| git clone --recursive "${{ env.KERNEL_SOURCE }}" -b "${{ env.KERNEL_SOURCE_BRANCH }}" android-kernel --depth=1 | ||
| cd android-kernel | ||
| echo "SOURCE_GIT_HASH=$(git rev-parse HEAD)" >> "$GITHUB_ENV" | ||
| - name: Apply optional Kconfig patch | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| cd kernel_workspace/android-kernel | ||
| if [[ -f "$GITHUB_WORKSPACE/patches/fix_kconfig.patch" ]]; then | ||
| git apply "$GITHUB_WORKSPACE/patches/fix_kconfig.patch" | ||
| fi | ||
| - name: Setup KernelSU (if enabled) | ||
| if: env.ENABLE_KERNELSU == 'true' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| cd kernel_workspace/android-kernel | ||
| curl -LSs "$KERNELSU_SETUP_SOURCE" | bash -s "${{ env.KERNELSU_TAG }}" | ||
| KSU_VERSION="_$(cd "$(echo "$KERNELSU_SETUP_SOURCE" | cut -d/ -f5)" 2>/dev/null || cd KernelSU; expr "$(git rev-list --count HEAD)" + 10200)" | ||
| echo "UPLOADNAME=-KernelSU-${{ matrix.target }}$KSU_VERSION" >> "$GITHUB_ENV" | ||
| - name: Mutate defconfig (KernelSU + extras) | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| KDEF="kernel_workspace/android-kernel/arch/${{ env.KERNEL_ARCH }}/configs/${DEVICE}_defconfig" | ||
| [[ -f "$KDEF" ]] || { echo "Defconfig $KDEF missing"; exit 1; } | ||
| if [[ "${{ env.ENABLE_KERNELSU }}" == "true" ]]; then | ||
| # Basic ensure line | ||
| grep -q '^CONFIG_KSU=' "$KDEF" || echo "CONFIG_KSU=y" >> "$KDEF" | ||
| fi | ||
| if [[ "${{ env.DISABLE_LTO }}" == "true" ]]; then | ||
| sed -i 's/CONFIG_LTO=y/CONFIG_LTO=n/' "$KDEF" || true | ||
| sed -i 's/CONFIG_LTO_CLANG=y/CONFIG_LTO_CLANG=n/' "$KDEF" || true | ||
| sed -i 's/CONFIG_THINLTO=y/CONFIG_THINLTO=n/' "$KDEF" || true | ||
| grep -q '^CONFIG_LTO_NONE=' "$KDEF" || echo "CONFIG_LTO_NONE=y" >> "$KDEF" | ||
| fi | ||
| if [[ "${{ env.DISABLE_CC_WERROR }}" == "true" ]]; then | ||
| grep -q '^CONFIG_CC_WERROR=' "$KDEF" || echo "CONFIG_CC_WERROR=n" >> "$KDEF" | ||
| fi | ||
| echo "FINAL_DEFCONFIG_SNAPSHOT<<EOF" >> "$GITHUB_ENV" | ||
| sed 's/^/DEF: /' "$KDEF" >> "$GITHUB_ENV" | ||
| echo "EOF" >> "$GITHUB_ENV" | ||
| - name: CCache setup | ||
| if: env.ENABLE_CCACHE == 'true' | ||
| uses: hendrikmuhs/ccache-action@v1.2 | ||
| with: | ||
| key: complex-${{ env.DEVICE }}-${{ matrix.target }} | ||
| max-size: 5G | ||
| - name: Add optional 'false' stripping wrapper | ||
| if: github.event.inputs.allow_false_wrapper == 'true' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| WRAP_DIR="$GITHUB_WORKSPACE/wrap" | ||
| mkdir -p "$WRAP_DIR" | ||
| cat > "$WRAP_DIR/clang" <<'EOF' | ||
| #!/usr/bin/env bash | ||
| # Wrapper drops literal 'false' tokens. | ||
| REAL="$(command -v clang | grep -v "$PWD")" | ||
| args=() | ||
| for a in "$@"; do | ||
| [[ "$a" == "false" ]] && continue | ||
| args+=("$a") | ||
| done | ||
| exec "$REAL" "${args[@]}" | ||
| EOF | ||
| chmod +x "$WRAP_DIR/clang" | ||
| echo "$WRAP_DIR" >> $GITHUB_PATH | ||
| echo "Wrapper installed. (Temporary workaround; fix cc-option fallback!)." | ||
| - name: Detect cc-option misuse before build | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| cd kernel_workspace/android-kernel | ||
| # Report any suspicious lines containing ',false)' or space false) within Make/Kbuild | ||
| echo "Scanning for cc-option fallbacks using literal 'false'..." | ||
| hits=$(grep -R --include='Makefile*' --include='Kbuild*' -nE 'cc-.*\(.*false\)' . || true) | ||
| if [[ -n "$hits" ]]; then | ||
| echo "Potential offenders:" | ||
| echo "$hits" | ||
| echo "$hits" > ../cc_option_false_hits.txt | ||
| else | ||
| echo "No obvious cc-option false patterns found." | ||
| fi | ||
| - name: Build (Plan C / fallback) | ||
| shell: bash | ||
| id: buildstep | ||
| run: | | ||
| set -euo pipefail | ||
| cd "$GITHUB_WORKSPACE/kernel_workspace/android-kernel" | ||
| # Toolchain environment | ||
| if [[ "${{ env.USE_CLANG }}" == "true" ]]; then | ||
| export CC=clang | ||
| export LD=ld.lld | ||
| export AR=llvm-ar | ||
| export NM=llvm-nm | ||
| export OBJCOPY=llvm-objcopy | ||
| export OBJDUMP=llvm-objdump | ||
| export STRIP=llvm-strip | ||
| export LLVM=1 | ||
| export LLVM_IAS=1 | ||
| export CROSS_COMPILE=aarch64-linux-gnu- | ||
| : "${CROSS_COMPILE_ARM32:=arm-linux-gnueabihf-}" | ||
| : "${CROSS_COMPILE_COMPAT:=$CROSS_COMPILE_ARM32}" | ||
| echo "Mode: Clang primary" | ||
| else | ||
| export CC=aarch64-linux-gnu-gcc | ||
| export CROSS_COMPILE=aarch64-linux-gnu- | ||
| : "${CROSS_COMPILE_ARM32:=arm-linux-gnueabihf-}" | ||
| : "${CROSS_COMPILE_COMPAT:=$CROSS_COMPILE_ARM32}" | ||
| echo "Mode: GCC only" | ||
| fi | ||
| which $CC || true | ||
| $CC --version || true | ||
| # First pass: defconfig | ||
| make V=1 -j"$(nproc)" O=out ARCH="${{ env.KERNEL_ARCH }}" "${DEVICE}_defconfig" | ||
| # OPTIONAL: compile one trivial object to detect stray 'false' | ||
| line=$(make -n V=1 O=out ARCH=${{ env.KERNEL_ARCH }} scripts/mod/empty.o 2>&1 | grep -m1 " false " || true) | ||
| if [[ -n "$line" && "${{ env.FAIL_ON_FALSE }}" == "true" && "${{ github.event.inputs.allow_false_wrapper }}" != "true" ]]; then | ||
| echo "ERROR: Detected stray literal 'false' token in compile line BEFORE full build:" | ||
| echo "$line" | ||
| echo "Likely from a cc-option fallback using 'false'. Search & remove 'false' fallback." | ||
| exit 1 | ||
| fi | ||
| # Full build | ||
| if [[ "${{ env.ENABLE_CCACHE }}" == "true" && "$CC" != "clang" ]]; then | ||
| make V=1 -j"$(nproc)" O=out ARCH="${{ env.KERNEL_ARCH }}" CC="ccache $CC" \ | ||
| CROSS_COMPILE="$CROSS_COMPILE" CROSS_COMPILE_ARM32="$CROSS_COMPILE_ARM32" CROSS_COMPILE_COMPAT="$CROSS_COMPILE_COMPAT" | ||
| else | ||
| make V=1 -j"$(nproc)" O=out ARCH="${{ env.KERNEL_ARCH }}" CC="$CC" \ | ||
| CROSS_COMPILE="$CROSS_COMPILE" CROSS_COMPILE_ARM32="$CROSS_COMPILE_ARM32" CROSS_COMPILE_COMPAT="$CROSS_COMPILE_COMPAT" | ||
| fi | ||
| OUT_IMG="out/arch/${{ env.KERNEL_ARCH }}/boot/${{ env.KERNEL_IMAGE_NAME }}" | ||
| if [[ -f "$OUT_IMG" ]]; then | ||
| echo "CHECK_FILE_IS_OK=true" >> "$GITHUB_ENV" | ||
| else | ||
| echo "Kernel image missing"; exit 1 | ||
| fi | ||
| - name: Package AnyKernel3 | ||
| if: env.CHECK_FILE_IS_OK == 'true' && env.USE_ANYKERNEL3 == 'true' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| cd kernel_workspace | ||
| src="${{ env.ANYKERNEL3_SOURCE }}" | ||
| if [[ "$src" == *'.git' ]]; then | ||
| git clone "$src" -b "${{ env.ANYKERNEL3_BRANCH }}" --depth=1 AnyKernel3 | ||
| else | ||
| mkdir -p AnyKernel3 | ||
| # Extend if you want tar/zip sources | ||
| echo "Non-git AnyKernel3 source not implemented for complex workflow yet." | ||
| fi | ||
| cp android-kernel/out/arch/${{ env.KERNEL_ARCH }}/boot/${{ env.KERNEL_IMAGE_NAME }} AnyKernel3/ | ||
| [[ "${{ env.NEED_DTBO }}" == "true" && -f android-kernel/out/arch/${{ env.KERNEL_ARCH }}/boot/dtbo.img ]] && cp android-kernel/out/arch/${{ env.KERNEL_ARCH }}/boot/dtbo.img AnyKernel3/ | ||
| rm -rf AnyKernel3/.git* | ||
| (cd AnyKernel3 && zip -r ../AnyKernel3-${{ matrix.target }}.zip .) | ||
| echo "ANYKERNEL_ZIP=kernel_workspace/AnyKernel3-${{ matrix.target }}.zip" >> "$GITHUB_ENV" | ||
| - name: Compute kernel localversion | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| DEF="kernel_workspace/android-kernel/arch/${{ env.KERNEL_ARCH }}/configs/${DEVICE}_defconfig" | ||
| RAW=$(grep -oP 'CONFIG_LOCALVERSION="\K[^"]+' "$DEF" || true) | ||
| RAW="${RAW#-}" | ||
| [[ -z "$RAW" ]] && RAW="CustomKernel" | ||
| echo "KERNEL_LOCALVERSION=$RAW" >> "$GITHUB_ENV" | ||
| - name: Upload raw kernel image | ||
| if: env.CHECK_FILE_IS_OK == 'true' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: kernel-${{ matrix.target }}-${{ env.DEVICE }}-${{ env.KERNEL_LOCALVERSION }}-${{ env.BUILD_TIME }} | ||
| path: kernel_workspace/android-kernel/out/arch/${{ env.KERNEL_ARCH }}/boot/${{ env.KERNEL_IMAGE_NAME }} | ||
| retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} | ||
| - name: Upload AnyKernel3 zip | ||
| if: env.CHECK_FILE_IS_OK == 'true' && env.USE_ANYKERNEL3 == 'true' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: AnyKernel3-${{ matrix.target }}-${{ env.DEVICE }}-${{ env.KERNEL_LOCALVERSION }}-${{ env.BUILD_TIME }} | ||
| path: ${{ env.ANYKERNEL_ZIP }} | ||
| retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} | ||
| - name: Build summary (markdown) | ||
| id: summary | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| OUT_PATH="kernel_workspace/android-kernel/out/arch/${{ env.KERNEL_ARCH }}/boot/${{ env.KERNEL_IMAGE_NAME }}" | ||
| SIZE="" | ||
| if [[ -f "$OUT_PATH" ]]; then SIZE=$(stat -c%s "$OUT_PATH"); fi | ||
| cat > build-summary.md <<EOF | ||
| # Kernel Build Summary | ||
| **Target:** ${{ matrix.target }} | ||
| **Device:** ${{ env.DEVICE }} | ||
| **Android Tag:** ${{ env.ANDROID_TAG }} | ||
| **LocalVersion:** ${{ env.KERNEL_LOCALVERSION }} | ||
| **Build Time (UTC):** ${{ env.BUILD_TIME }} | ||
| **Source Git Hash:** ${{ env.SOURCE_GIT_HASH }} | ||
| **Toolchain Mode:** $( [[ "${{ env.USE_CLANG }}" == "true" ]] && echo "Clang (Plan C)" || echo "GCC" ) | ||
| **Kernel Image Present:** ${{ env.CHECK_FILE_IS_OK }} | ||
| **Kernel Image Size (bytes):** ${SIZE:-N/A} | ||
| **AnyKernel3:** ${{ env.USE_ANYKERNEL3 }} | ||
| **KernelSU Enabled:** ${{ env.ENABLE_KERNELSU }} | ||
| **OLD ANDROID SUPPORT:** ${{ env.OLD_ANDROID_SUPPORT }} | ||
| <details> | ||
| <summary>Defconfig tail (last 40 lines)</summary> | ||
| \`\`\` | ||
| $(tail -n 40 kernel_workspace/android-kernel/arch/${{ env.KERNEL_ARCH }}/configs/${DEVICE}_defconfig) | ||
| \`\`\` | ||
| </details> | ||
| <details> | ||
| <summary>Potential cc-option false hits (if any)</summary> | ||
| \`\`\` | ||
| $(test -f kernel_workspace/cc_option_false_hits.txt && sed -n '1,120p' kernel_workspace/cc_option_false_hits.txt || echo "None") | ||
| \`\`\` | ||
| </details> | ||
| EOF | ||
| echo "HAS_SUMMARY=true" >> "$GITHUB_ENV" | ||
| - name: Upload build summary artifact | ||
| if: env.HAS_SUMMARY == 'true' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: summary-${{ matrix.target }}-${{ env.DEVICE }}-${{ env.BUILD_TIME }} | ||
| path: build-summary.md | ||
| retention-days: ${{ env.ARTIFACT_RETENTION_DAYS }} | ||
| - name: Append to Job Summary | ||
| if: env.HAS_SUMMARY == 'true' | ||
| shell: bash | ||
| run: | | ||
| cat build-summary.md >> $GITHUB_STEP_SUMMARY | ||
| ################################################################################ | ||
| # Job: Release (collect artifacts from all matrix builds) | ||
| ################################################################################ | ||
| release: | ||
| if: github.event.inputs.release_build == 'true' | ||
| needs: [build] | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Download all artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: collected | ||
| - name: Generate release notes | ||
| id: notes | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| echo "## Kernel Build Release" > RELEASE_NOTES.md | ||
| echo "" >> RELEASE_NOTES.md | ||
| find collected -type f -maxdepth 2 -printf '%P\n' | sort | while read -r f; do | ||
| sz=$(stat -c%s "collected/$f") | ||
| echo "- $f (${sz} bytes)" >> RELEASE_NOTES.md | ||
| done | ||
| echo "notes<<EOF" >> "$GITHUB_OUTPUT" | ||
| cat RELEASE_NOTES.md >> "$GITHUB_OUTPUT" | ||
| echo "EOF" >> "$GITHUB_OUTPUT" | ||
| - name: Create draft release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| tag_name: kernel-${{ github.event.inputs.select_device }}-${{ github.run_id }} | ||
| name: "Kernel Build - ${{ github.event.inputs.select_device }} - Run ${{ github.run_number }}" | ||
| draft: true | ||
| prerelease: false | ||
| body: ${{ steps.notes.outputs.notes }} | ||
| files: | | ||
| collected/**/* | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||