Xây dựng nhân

Trang này trình bày chi tiết quy trình tạo hạt nhân tuỳ chỉnh cho các thiết bị Android. Các hướng dẫn này sẽ hướng dẫn bạn thực hiện quy trình chọn nguồn phù hợp, tạo hạt nhân và nhúng kết quả vào hình ảnh hệ thống được tạo từ Dự án nguồn mở Android (AOSP).

Bạn có thể lấy các nguồn hạt nhân mới hơn bằng cách sử dụng Repo; tạo các nguồn đó mà không cần định cấu hình thêm bằng cách chạy build/build.sh từ thư mục gốc của quy trình thanh toán nguồn.

Tải các nguồn và công cụ bản dựng xuống

Đối với các hạt nhân gần đây, hãy sử dụng repo để tải các nguồn, chuỗi công cụ và tập lệnh bản dựng xuống. Một số hạt nhân (ví dụ: hạt nhân Pixel 3) yêu cầu nguồn từ nhiều kho lưu trữ git, trong khi một số hạt nhân khác (ví dụ: hạt nhân phổ biến) chỉ yêu cầu một nguồn duy nhất. Việc sử dụng phương pháp repo đảm bảo việc thiết lập thư mục nguồn chính xác.

Tải các nguồn xuống cho nhánh thích hợp:

mkdir android-kernel && cd android-kernel
repo init -u https://android.googlesource.com/kernel/manifest -b BRANCH
repo sync

Để biết danh sách các nhánh kho lưu trữ (BRANCH) có thể sử dụng với lệnh `repo init` trước đó, hãy xem phần Nhánh nhân và hệ thống xây dựng của các nhánh đó.

Để biết thông tin chi tiết về cách tải xuống và biên dịch nhân cho các thiết bị Pixel, hãy xem phần Tạo nhân Pixel.

Tạo nhân

Tạo bằng Bazel (Kleaf)

Android 13 đã ra mắt tính năng tạo nhân bằng Bazel.

Để tạo bản phân phối cho hạt nhân GKI cho kiến trúc aarch64, hãy xem một nhánh Hạt nhân chung của Android không sớm hơn Android 13, sau đó chạy lệnh sau:

tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]

Sau đó, tệp nhị phân hạt nhân, mô-đun và hình ảnh tương ứng sẽ nằm trong thư mục $DIST_DIR. Nếu bạn không chỉ định --destdir, hãy xem kết quả của lệnh để biết vị trí của cấu phần phần mềm. Để biết thông tin chi tiết, hãy tham khảo tài liệu về AOSP.

Tạo bằng build.sh (cũ)

Đối với các nhánh ở Android 12 trở xuống, HOẶC các nhánh không có Kleaf:

build/build.sh

Tệp nhị phân nhân, mô-đun và hình ảnh tương ứng nằm trong thư mục out/BRANCH/dist.

Tạo mô-đun nhà cung cấp cho thiết bị ảo

Android 13 đã ra mắt tính năng tạo nhân bằng Bazel (Kleaf), thay thế build.sh.

Để tạo bản phân phối cho các mô-đun của virtual_device, hãy chạy:

tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist [-- --destdir=$DIST_DIR]

Để biết thêm thông tin chi tiết về cách tạo hạt nhân Android bằng Bazel, hãy xem. Kleaf – Xây dựng hạt nhân Android bằng Bazel.

Để biết thông tin chi tiết về tính năng hỗ trợ Kleaf cho từng cấu trúc, hãy xem phần Hỗ trợ Kleaf cho các thiết bị và hạt nhân.

Tạo mô-đun nhà cung cấp cho thiết bị ảo bằng build.sh (cũ)

Trong Android 12, Cuttlefish và Goldfish hội tụ, vì vậy, chúng dùng chung một hạt nhân: virtual_device. Để tạo các mô-đun của nhân đó, hãy sử dụng cấu hình bản dựng sau:

BUILD_CONFIG=common-modules/virtual-device/build.config.virtual_device.x86_64 build/build.sh

Android 11 ra mắt GKI, tách biệt hạt nhân thành một hình ảnh hạt nhân do Google duy trì và các mô-đun do nhà cung cấp duy trì, được tạo riêng biệt.

Ví dụ này cho thấy một cấu hình hình ảnh hạt nhân:

BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh

Ví dụ này cho thấy cấu hình mô-đun (Cuttlefish và Trình mô phỏng):

BUILD_CONFIG=common-modules/virtual-device/build.config.cuttlefish.x86_64 build/build.sh

Chạy hạt nhân

Có nhiều cách để chạy hạt nhân được tạo tuỳ chỉnh. Sau đây là các cách đã biết phù hợp với nhiều tình huống phát triển.

Nhúng vào bản dựng hình ảnh Android

Sao chép Image.lz4-dtb vào vị trí nhị phân của nhân tương ứng trong cây AOSP và tạo lại hình ảnh khởi động.

Ngoài ra, hãy xác định biến TARGET_PREBUILT_KERNEL trong khi sử dụng make bootimage (hoặc bất kỳ dòng lệnh make nào khác tạo hình ảnh khởi động). Tất cả thiết bị đều hỗ trợ biến này vì biến này được thiết lập thông qua device/common/populate-new-device.sh. Ví dụ:

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

Truyền tệp và khởi động hạt nhân bằng fastboot

Hầu hết các thiết bị mới đây đều có tiện ích trình tải khởi động để đơn giản hoá quá trình tạo và khởi động hình ảnh khởi động.

Cách khởi động hạt nhân mà không cần cài đặt ROM:

adb reboot bootloader
fastboot boot Image.lz4-dtb

Khi sử dụng phương thức này, nhân hệ điều hành sẽ không thực sự cài đặt ROM và không duy trì sau khi khởi động lại.

Chạy nhân trên Cuttlefish

Bạn có thể chạy nhân trong cấu trúc mà bạn chọn trên thiết bị Cuttlefish.

Để khởi động thiết bị Cuttlefish bằng một tập hợp cấu phần phần mềm nhân hệ điều hành cụ thể, hãy chạy lệnh cvd create với các cấu phần phần mềm nhân hệ điều hành mục tiêu làm tham số. Lệnh ví dụ sau đây sử dụng cấu phần phần mềm nhân cho mục tiêu arm64 từ tệp kê khai nhân common-android14-6.1.

cvd create \
    -kernel_path=/$PATH/$TO/common-android14-6.1/out/android14-6.1/dist/Image \
    -initramfs_path=/$PATH/$TO/common-android14-6.1/out/android14-6.1/dist/initramfs.img

Để biết thêm thông tin, hãy xem bài viết Phát triển hạt nhân trên mực ống.

Tuỳ chỉnh bản dựng hạt nhân

Để tuỳ chỉnh bản dựng hạt nhân cho bản dựng Kleaf, hãy xem tài liệu về Kleaf.

Tuỳ chỉnh bản dựng nhân bằng build.sh (cũ)

Đối với build/build.sh, các biến môi trường có thể ảnh hưởng đến quy trình và kết quả xây dựng. Hầu hết các cấu hình này đều không bắt buộc và mỗi nhánh nhân đều phải đi kèm với một cấu hình mặc định thích hợp. Những loại thường dùng nhất được liệt kê tại đây. Để xem danh sách đầy đủ (và mới nhất), hãy tham khảo build/build.sh.

Biến môi trường Mô tả Ví dụ
BUILD_CONFIG Tệp cấu hình bản dựng từ nơi bạn khởi chạy môi trường tạo bản dựng. Vị trí phải được xác định tương ứng với thư mục gốc của Repo. Giá trị mặc định là build.config.
Bắt buộc đối với các hạt nhân phổ biến.
BUILD_CONFIG=common/build.config.gki.aarch64
CC Ghi đè trình biên dịch sẽ được sử dụng. Quay lại trình biên dịch mặc định do build.config xác định. CC=clang
DIST_DIR Thư mục đầu ra cơ sở cho bản phân phối nhân. DIST_DIR=/path/to/my/dist
OUT_DIR Thư mục đầu ra cơ sở cho bản dựng nhân. OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG Bỏ qua make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER Bỏ qua make mrproper SKIP_MRPROPER=1

Cấu hình hạt nhân tuỳ chỉnh cho các bản dựng cục bộ

Trong Android 14 trở lên, bạn có thể sử dụng các mảnh defconfig để tuỳ chỉnh cấu hình hạt nhân. Hãy xem tài liệu về Kleaf trên các mảnh defconfig.

Cấu hình hạt nhân tuỳ chỉnh cho các bản dựng cục bộ có cấu hình bản dựng (cũ)

Trong Android 13 trở xuống, hãy xem những mục sau.

Nếu cần thường xuyên chuyển đổi tuỳ chọn cấu hình hạt nhân, chẳng hạn như khi làm việc trên một tính năng hoặc nếu cần đặt một tuỳ chọn cho mục đích phát triển, bạn có thể đạt được sự linh hoạt đó bằng cách duy trì một bản sửa đổi hoặc bản sao cục bộ của cấu hình bản dựng.

Đặt biến POST_DEFCONFIG_CMDS thành một câu lệnh được đánh giá ngay sau khi hoàn tất bước make defconfig thông thường. Khi các tệp build.config được lấy nguồn vào môi trường bản dựng, các hàm được xác định trong build.config có thể được gọi trong các lệnh sau defconfig.

Một ví dụ phổ biến là tắt tính năng tối ưu hoá thời gian liên kết (LTO) cho các hạt nhân chéo trong quá trình phát triển. Mặc dù LTO có lợi cho các hạt nhân đã phát hành, nhưng chi phí hao tổn tại thời điểm tạo bản dựng có thể đáng kể. Đoạn mã sau đây được thêm vào build.config cục bộ sẽ tắt LTO liên tục khi sử dụng build/build.sh.

POST_DEFCONFIG_CMDS="check_defconfig && update_debug_config"
function update_debug_config() {
    ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
         -d LTO \
         -d LTO_CLANG \
         -d CFI \
         -d CFI_PERMISSIVE \
         -d CFI_CLANG
    (cd ${OUT_DIR} && \
     make O=${OUT_DIR} $archsubarch CC=${CC} CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
}

Xác định phiên bản hạt nhân

Bạn có thể xác định phiên bản chính xác để tạo từ hai nguồn: cây AOSP và hình ảnh hệ thống.

Phiên bản kernel từ cây AOSP

Cây AOSP chứa các phiên bản hạt nhân tạo sẵn. Nhật ký git cho biết phiên bản chính xác trong thông báo xác nhận:

cd $AOSP/device/VENDOR/NAME
git log --max-count=1

Nếu phiên bản hạt nhân không có trong nhật ký git, hãy lấy phiên bản đó từ hình ảnh hệ thống, như mô tả dưới đây.

Phiên bản hạt nhân từ hình ảnh hệ thống

Để xác định phiên bản hạt nhân được dùng trong hình ảnh hệ thống, hãy chạy lệnh sau đây đối với tệp hạt nhân:

file kernel

Đối với tệp Image.lz4-dtb, hãy chạy:

grep -a 'Linux version' Image.lz4-dtb

Tạo hình ảnh khởi động

Bạn có thể tạo hình ảnh khởi động bằng môi trường xây dựng hạt nhân.

Tạo hình ảnh khởi động cho các thiết bị có init_boot

Đối với các thiết bị có phân vùng init_boot, hình ảnh khởi động được tạo cùng với hạt nhân. Hình ảnh initramfs không được nhúng trong hình ảnh khởi động.

Ví dụ: với Kleaf, bạn có thể tạo hình ảnh khởi động GKI bằng:

tools/bazel run //common:kernel_aarch64_dist [-- --destdir=$DIST_DIR]

Với build/build.sh (cũ), bạn có thể tạo hình ảnh khởi động GKI bằng:

BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh

Hình ảnh khởi động GKI nằm trong $DIST_DIR.

Tạo hình ảnh khởi động cho các thiết bị không có init_boot (cũ)

Đối với các thiết bị không có phân vùng init_boot, bạn cần có tệp nhị phân ramdisk. Bạn có thể có được tệp nhị phân này bằng cách tải hình ảnh khởi động GKI xuống rồi giải nén hình ảnh đó. Mọi hình ảnh khởi động GKI từ bản phát hành Android liên kết đều sẽ hoạt động.

tools/mkbootimg/unpack_bootimg.py --boot_img=boot-5.4-gz.img
mv $KERNEL_ROOT/out/ramdisk gki-ramdisk.lz4

Thư mục đích là thư mục cấp cao nhất của cây nhân (thư mục đang hoạt động).

Nếu đang phát triển bằng AOSP chính, bạn có thể tải cấu phần phần mềm bản dựng ramdisk-recovery.img xuống từ bản dựng aosp_arm64 trên ci.android.com và sử dụng cấu phần phần mềm đó làm tệp nhị phân ramdisk.

Khi có một tệp nhị phân ramdisk và đã sao chép tệp đó vào gki-ramdisk.lz4 trong thư mục gốc của bản dựng nhân, bạn có thể tạo hình ảnh khởi động bằng cách thực thi:

BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=Image GKI_RAMDISK_PREBUILT_BINARY=gki-ramdisk.lz4 BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh

Nếu bạn đang làm việc với kiến trúc dựa trên x86, hãy thay thế Image bằng bzImageaarch64 bằng x86_64:

BUILD_BOOT_IMG=1 SKIP_VENDOR_BOOT=1 KERNEL_BINARY=bzImage GKI_RAMDISK_PREBUILT_BINARY=gki-ramdisk.lz4 BUILD_CONFIG=common/build.config.gki.x86_64 build/build.sh

Tệp đó nằm trong thư mục cấu phần phần mềm $KERNEL_ROOT/out/$KERNEL_VERSION/dist.

Hình ảnh khởi động nằm ở out/<kernel branch>/dist/boot.img.