diff --git a/.github/workflows/build-kernel.yml b/.github/workflows/build-kernel.yml index e324ce6fc5..30dff8f372 100644 --- a/.github/workflows/build-kernel.yml +++ b/.github/workflows/build-kernel.yml @@ -9,7 +9,10 @@ on: config: description: "Config file to build (path, relative to the repo root)" required: false - default: "config.env" + # This branch is the Mi 8 baseline stage. Keeping its profile as the + # dispatch default prevents an accidental build of the repository's + # generic config.env (which targets a different device). + default: "config/dipper-baseline.env" type: string # "config" on the options below means "use whatever the config file says". # It is the default so that running the form without touching anything @@ -186,7 +189,44 @@ jobs: max-size: 2G - name: Build kernel - run: bash scripts/build.sh all + shell: bash + run: | + # Keep the web log readable. The complete compiler output remains + # available as an artifact below when a deeper investigation is + # needed. + build_log="$RUNNER_TEMP/kernel-build.log" + if bash scripts/build.sh all >"$build_log" 2>&1; then + echo "Kernel build completed. Last 80 log lines:" + tail -n 80 "$build_log" + exit 0 + else + status=$? + echo "::error::Kernel build failed. Showing the first error with context; download the kernel-build-log artifact for the complete output." + # DTC reports failures as uppercase "ERROR:", while make itself + # may be the only process that prints an error marker. Match both + # forms so parallel compiler output cannot hide the true failure. + first_error=$(grep -ni -m1 -E '(^|[[:space:]])(fatal[[:space:]]+)?error:|undefined reference|collect2: error|make(\[[0-9]+\])?: \*\*\*' "$build_log" || true) + if [ -n "$first_error" ]; then + line=${first_error%%:*} + start=$(( line > 25 ? line - 25 : 1 )) + end=$(( line + 40 )) + echo "First error at log line $line:" + sed -n "${start},${end}p" "$build_log" + else + echo "No compiler-style error line was found; last 120 log lines:" + tail -n 120 "$build_log" + fi + exit "$status" + fi + + - name: Upload complete kernel build log + if: always() + uses: actions/upload-artifact@v4 + with: + name: kernel-build-log-${{ env.DEVICE }}-${{ github.run_id }} + path: ${{ runner.temp }}/kernel-build.log + if-no-files-found: warn + retention-days: 7 - name: Package artifacts run: bash scripts/package.sh all diff --git a/config/dipper-baseline.env b/config/dipper-baseline.env new file mode 100644 index 0000000000..d789f68da7 --- /dev/null +++ b/config/dipper-baseline.env @@ -0,0 +1,52 @@ +KERNEL_SOURCE=https://github.com/LineageOS/android_kernel_xiaomi_sdm845.git +KERNEL_SOURCE_BRANCH=lineage-22.1 + +KERNEL_CONFIG=vendor/xiaomi/mi845_defconfig +KERNEL_IMAGE_NAME=Image.gz-dtb +ARCH=arm64 + +# Kernel 4.9: dùng toolchain cũ/an toàn hơn +CLANG_BRANCH=master-kernel-build-2022 +CLANG_VERSION=r450784e + +USE_LLVM=false +ENABLE_GCC_ARM64=true +ENABLE_GCC_ARM32=true + +# The Android-targeted Clang prebuilt is rejected by this 4.9 Kbuild unless +# its GNU binutils target is stated explicitly. Keep this baseline-only: +# it changes no kernel configuration or runtime behaviour. +CUSTOM_CMDS=CLANG_TRIPLE=aarch64-linux-gnu- +# Use the linker and integrated assembler shipped with the same AOSP Clang +# package. Clang 14 otherwise delegates VDSO assembly to the legacy GNU +# assembler, which rejects Clang's generated .file directives. +# The generic SDM845 build also emits an incomplete QVR-only DTS that refers +# to touchscreen labels absent from this source tree. Dipper's DTS does not +# use those labels; retain every other DTC check and suppress only that one. +EXTRA_CMDS=LD=ld.lld LLVM_IAS=1 DTC_FLAGS=-Eno-phandle_references + +# ----- ROOT ----- +KSU_VARIANT=none +KSU_REF= +KSU_HOOK_MODE=none + +# ----- SUSFS ----- +ENABLE_SUSFS=false +ENABLE_PATH_UMOUNT=false +ENABLE_HIDE_STUFF=false +ENABLE_KPM=false + +# Không tự bật KPROBES +ADD_KPROBES_CONFIG=false + +ADD_OVERLAYFS_CONFIG=true +# This 4.9 vendor tree promotes diagnostics introduced by modern Clang to +# errors (for example packed-member and int-in-bool-context). It does not +# affect the generated kernel; it only lets the legacy tree compile. +DISABLE_CC_WERROR=true + +# Chưa đóng gói boot.img tự động +BUILD_BOOT_IMG=false +NEED_DTBO=false + +ENABLE_CCACHE=true diff --git a/scripts/build.sh b/scripts/build.sh index 0f62c1bb0d..1bf20e24f4 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -97,6 +97,10 @@ make_args() { [ -n "${EXTRA_CMDS:-}" ] && printf ' %s' "$EXTRA_CMDS" [ -n "${GCC_64:-}" ] && printf ' %s' "$GCC_64" [ -n "${GCC_32:-}" ] && printf ' %s' "$GCC_32" + # Some Android 4.9 vendor trees append -Werror directly in their Makefiles, + # so CONFIG_CC_WERROR alone cannot override it. KCFLAGS is appended after + # the tree's flags, preserving diagnostics while making them non-fatal. + is_true "${DISABLE_CC_WERROR:-false}" && printf ' KCFLAGS=-Wno-error' if is_true "${USE_LLVM:-false}"; then printf ' LLVM=1 LLVM_IAS=1' [ -n "${GCC_64:-}" ] || printf ' CROSS_COMPILE=aarch64-linux-gnu-' @@ -124,9 +128,15 @@ build_kernel() { fi local cc="clang" args + # Android 4.9's compat VDSO links through CC directly, bypassing the make + # variable LD. When a profile selects ld.lld, make Clang select it too so + # VDSO32 cannot accidentally invoke the runner's x86 /usr/bin/ld. + case " ${EXTRA_CMDS:-} " in + *" LD=ld.lld "*) cc="clang -fuse-ld=lld" ;; + esac args=$(make_args) if is_true "${ENABLE_CCACHE:-true}" && command -v ccache >/dev/null; then - cc="ccache clang" + cc="ccache ${cc}" export CCACHE_DIR="${CCACHE_DIR:-${WORKSPACE}/.ccache}" info "ccache enabled (dir: ${CCACHE_DIR})" fi diff --git a/scripts/lib.sh b/scripts/lib.sh index 3dc909eab0..01dec46d00 100644 --- a/scripts/lib.sh +++ b/scripts/lib.sh @@ -103,13 +103,42 @@ retry() { # ------------------------------------------------------------- downloading --- -# fetch URL DEST -- resumable, retrying download. +# fetch URL DEST -- retrying download with an integrity check for archives. fetch() { - local url=$1 dest=$2 + local url=$1 dest=$2 tmp="${2}.partial" + local attempt=1 delay=5 info "fetching ${url}" - retry 4 curl -fsSL --connect-timeout 30 --retry 3 --retry-delay 3 -o "$dest" "$url" \ - || die "failed to download ${url}" - [ -s "$dest" ] || die "downloaded file is empty: ${url}" + rm -f "$dest" "$tmp" + + while [ "$attempt" -le 4 ]; do + # Do not write straight to DEST: a proxy/server can terminate a streamed + # archive cleanly enough for curl to exit 0, while gzip/tar later finds an + # unexpected EOF. Only promote a verified file to DEST. + if curl -fsSL --connect-timeout 30 --retry 3 --retry-delay 3 \ + --retry-all-errors -o "$tmp" "$url" && [ -s "$tmp" ]; then + case "$dest" in + *.tar.gz | *.tgz) gzip -t "$tmp" ;; + *.tar.xz) xz -t "$tmp" ;; + *.tar.zst) zstd -tq "$tmp" ;; + *.tar.bz2) bzip2 -t "$tmp" ;; + *.tar) tar -tf "$tmp" >/dev/null ;; + *.zip) unzip -tqq "$tmp" ;; + *) true ;; + esac && { + mv "$tmp" "$dest" + return 0 + } + fi + + rm -f "$tmp" + if [ "$attempt" -lt 4 ]; then + warn "download was incomplete or invalid; retrying in ${delay}s (${attempt}/4): ${url}" + sleep "$delay" + delay=$((delay * 2)); [ "$delay" -gt 60 ] && delay=60 + fi + attempt=$((attempt + 1)) + done + die "failed to download a valid file after 4 attempts: ${url}" } # fetch_stdout URL -- print a URL's body, retrying. Used for small text files.