สร้างเคอร์เนล

หน้านี้จะอธิบายรายละเอียดกระบวนการสร้าง เคอร์เนลที่กำหนดเองสำหรับอุปกรณ์ Android คำสั่งเหล่านี้จะแนะนำกระบวนการเลือกแหล่งที่มาที่เหมาะสม สร้างเคอร์เนล และฝังผลลัพธ์ลงในอิมเมจระบบที่สร้างจากโครงการโอเพนซอร์ส Android (AOSP)

ดาวน์โหลดแหล่งที่มาและเครื่องมือสร้าง

สำหรับเคอร์เนลล่าสุด ให้ใช้ repo เพื่อดาวน์โหลดแหล่งที่มา ทูลเชน และสคริปต์การสร้าง เคอร์เนลบางตัว (เช่น เคอร์เนลของ Pixel 3) ต้องใช้แหล่งที่มาจากที่เก็บ git หลายแห่ง ขณะที่เคอร์เนลอื่นๆ (เช่น เคอร์เนลทั่วไป) ต้องการแหล่งที่มาเพียงแหล่งเดียว เท่านั้น การใช้แนวทาง repo จะช่วยให้มั่นใจได้ว่าการตั้งค่าไดเรกทอรีแหล่งที่มาถูกต้อง

ดาวน์โหลดแหล่งที่มาสำหรับสาขาที่เหมาะสม

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

ดูรายการสาขาของที่เก็บ (BRANCH) ที่ใช้กับคำสั่ง `repo init` ก่อนหน้าได้ที่ Kernel branches and their build systems

ดูรายละเอียดเกี่ยวกับการดาวน์โหลดและคอมไพล์เคอร์เนลสำหรับอุปกรณ์ Pixel ได้ที่ การสร้างเคอร์เนลของ Pixel

สร้างเคอร์เนล

สร้างด้วย Bazel (Kleaf)

Android 13 เปิดตัวการสร้างเคอร์เนลด้วย Bazel

หากต้องการสร้างการจัดจำหน่ายสำหรับเคอร์เนล GKI สำหรับสถาปัตยกรรม aarch64 โปรดดู สาขาเคอร์เนลทั่วไปของ Android ที่ไม่เก่ากว่า Android 13 และ จากนั้นเรียกใช้คำสั่งต่อไปนี้

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

หลังจากนั้นไบนารีเคอร์เนล โมดูล และอิมเมจที่เกี่ยวข้องจะอยู่ในไดเรกทอรี $DIST_DIR หากไม่ได้ระบุ --destdir ให้ดูเอาต์พุต ของคำสั่งเพื่อดูตำแหน่งของอาร์ติแฟกต์ โปรดดูรายละเอียดในเอกสารประกอบเกี่ยวกับ AOSP

สร้างด้วย build.sh (เดิม)

สำหรับสาขาที่ใช้ Android 12 หรือต่ำกว่า หรือ สาขาที่ไม่มี Kleaf ให้ทำดังนี้

build/build.sh

ไบนารีของเคอร์เนล โมดูล และอิมเมจที่เกี่ยวข้องจะอยู่ในไดเรกทอรี out/BRANCH/dist

สร้างโมดูลของผู้ให้บริการสำหรับอุปกรณ์เสมือน

Android 13 ได้เปิดตัวการสร้างเคอร์เนลด้วย Bazel (Kleaf) ซึ่งมาแทนที่ build.sh

หากต้องการสร้างการเผยแพร่สำหรับโมดูลของ virtual_device's ให้เรียกใช้คำสั่งต่อไปนี้

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

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการสร้างเคอร์เนล Android ด้วย Bazel ได้ที่ Kleaf - การสร้างเคอร์เนล Android ด้วย Bazel

โปรดดูรายละเอียดเกี่ยวกับการรองรับ Kleaf สำหรับสถาปัตยกรรมแต่ละรายการที่ การรองรับ Kleaf สำหรับอุปกรณ์และเคอร์เนล

สร้างโมดูลของผู้ให้บริการสำหรับอุปกรณ์เสมือนด้วย build.sh (เดิม)

ใน Android 12 Cuttlefish และ Goldfish จะรวมกัน จึงใช้เคอร์เนลเดียวกัน: virtual_device หากต้องการสร้างโมดูลของเคอร์เนลนั้น ให้ใช้การกำหนดค่าบิลด์ต่อไปนี้

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

Android 11 เปิดตัว GKI ซึ่งแยกเคอร์เนลออกเป็นอิมเมจเคอร์เนลที่ Google ดูแลและโมดูลที่ผู้ให้บริการดูแล ซึ่งสร้างแยกกัน

ตัวอย่างนี้แสดงการกำหนดค่าอิมเมจเคอร์เนล

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

ตัวอย่างนี้แสดงการกำหนดค่าโมดูล (Cuttlefish และโปรแกรมจำลอง)

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

เรียกใช้เคอร์เนล

การเรียกใช้เคอร์เนลที่สร้างขึ้นเองทำได้หลายวิธี วิธีที่ทราบซึ่งเหมาะกับสถานการณ์การพัฒนาต่างๆ มีดังนี้

ฝังลงในการสร้างอิมเมจ Android

คัดลอก Image.lz4-dtb ไปยังตำแหน่งไบนารีของเคอร์เนลที่เกี่ยวข้อง ภายในโครงสร้าง AOSP แล้วสร้างอิมเมจบูตใหม่

หรือกำหนดตัวแปร TARGET_PREBUILT_KERNEL ขณะใช้ make bootimage (หรือบรรทัดคำสั่ง make อื่นๆ ที่สร้างอิมเมจบูต) ตัวแปรนี้รองรับในอุปกรณ์ทุกเครื่องเนื่องจากตั้งค่าผ่าน device/common/populate-new-device.sh เช่น

export TARGET_PREBUILT_KERNEL=DIST_DIR/Image.lz4-dtb

แฟลชและบูตเคอร์เนลด้วย Fastboot

อุปกรณ์ส่วนใหญ่ที่เพิ่งเปิดตัวมีส่วนขยาย Bootloader เพื่อเพิ่มประสิทธิภาพกระบวนการ สร้างและบูตอิมเมจบูต

วิธีบูตเคอร์เนลโดยไม่ต้องแฟลช

adb reboot bootloader
fastboot boot Image.lz4-dtb

การใช้วิธีนี้ไม่ได้แฟลชเคอร์เนลจริงๆ และจะไม่คงอยู่ เมื่อรีบูต

เรียกใช้เคอร์เนลใน Cuttlefish

คุณสามารถเรียกใช้เคอร์เนลในสถาปัตยกรรมที่ต้องการได้ในอุปกรณ์ Cuttlefish

หากต้องการบูตอุปกรณ์ Cuttlefish ด้วยชุดอาร์ติแฟกต์เคอร์เนลที่เฉพาะเจาะจง ให้เรียกใช้คำสั่ง cvd create โดยมีอาร์ติแฟกต์เคอร์เนลเป้าหมายเป็นพารามิเตอร์ คำสั่งตัวอย่างต่อไปนี้ใช้สิ่งประดิษฐ์ของเคอร์เนลสำหรับเป้าหมาย arm64 จาก common-android14-6.1ไฟล์ Manifest ของเคอร์เนล

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

ดูข้อมูลเพิ่มเติมได้ที่ พัฒนาเคอร์เนลใน Cuttlefish

ปรับแต่งการสร้างเคอร์เนล

หากต้องการปรับแต่งบิลด์เคอร์เนลสำหรับบิลด์ Kleaf โปรดดู เอกสารประกอบของ Kleaf

ปรับแต่งการสร้างเคอร์เนลด้วย build.sh (เดิม)

สำหรับ build/build.sh ตัวแปรสภาพแวดล้อมอาจส่งผลต่อกระบวนการบิลด์และผลลัพธ์ ส่วนใหญ่เป็นตัวเลือก และแต่ละสาขาของเคอร์เนลควรมาพร้อมกับการกำหนดค่าเริ่มต้นที่เหมาะสม โดยรายการที่ใช้บ่อยที่สุดจะแสดงที่นี่ ดูรายการทั้งหมด (และรายการล่าสุด) ได้ที่ build/build.sh

ตัวแปรสภาพแวดล้อม คำอธิบาย ตัวอย่าง
BUILD_CONFIG สร้างไฟล์การกำหนดค่าจากที่ที่คุณเริ่มต้นสภาพแวดล้อมของบิลด์ ต้องกำหนดตำแหน่งที่สัมพันธ์กับไดเรกทอรีรูทของที่เก็บ ค่าเริ่มต้นคือ build.config
ต้องระบุสำหรับเคอร์เนลทั่วไป
BUILD_CONFIG=common/build.config.gki.aarch64
CC ลบล้างคอมไพเลอร์ที่จะใช้ เปลี่ยนกลับไปใช้คอมไพเลอร์เริ่มต้น ที่กำหนดโดย build.config CC=clang
DIST_DIR ไดเรกทอรีเอาต์พุตฐานสำหรับการเผยแพร่เคอร์เนล DIST_DIR=/path/to/my/dist
OUT_DIR ไดเรกทอรีเอาต์พุตฐานสำหรับการสร้างเคอร์เนล OUT_DIR=/path/to/my/out
SKIP_DEFCONFIG ข้าม make defconfig SKIP_DEFCONFIG=1
SKIP_MRPROPER ข้าม make mrproper SKIP_MRPROPER=1

การกำหนดค่าเคอร์เนลที่กำหนดเองสำหรับการสร้างในเครื่อง

ใน Android 14 ขึ้นไป คุณอาจใช้ Defconfig Fragments เพื่อปรับแต่งการกำหนดค่าเคอร์เนล โปรดดูเอกสารประกอบ Kleaf เกี่ยวกับ Defconfig Fragments

การกำหนดค่าเคอร์เนลที่กำหนดเองสำหรับการบิลด์ในเครื่องที่มีการกำหนดค่าบิลด์ (เดิม)

ใน Android 13 และต่ำกว่า ให้ดูข้อมูลต่อไปนี้

หากคุณต้องเปลี่ยนตัวเลือกการกำหนดค่าเคอร์เนลเป็นประจำ เช่น เมื่อทำงานกับฟีเจอร์ หรือหากคุณต้องการตั้งค่าตัวเลือกสำหรับการพัฒนา คุณสามารถเพิ่มความยืดหยุ่นได้โดยการรักษาการแก้ไขในเครื่องหรือสำเนาของไฟล์กำหนดค่าบิลด์

ตั้งค่าตัวแปร POST_DEFCONFIG_CMDS เป็นคำสั่งที่ ได้รับการประเมินทันทีหลังจากขั้นตอน make defconfig ปกติ เสร็จสิ้น เมื่อมีการจัดหาไฟล์ build.config ลงในสภาพแวดล้อมการสร้าง ฟังก์ชันที่กำหนดไว้ใน build.config จะเรียกใช้ได้ ซึ่งเป็นส่วนหนึ่งของคำสั่ง post-defconfig

ตัวอย่างที่พบบ่อยคือการปิดใช้การเพิ่มประสิทธิภาพเวลาลิงก์ (LTO) สำหรับเคอร์เนล Crosshatch ในระหว่างการพัฒนา แม้ว่า LTO จะมีประโยชน์สำหรับเคอร์เนลที่เผยแพร่แล้ว แต่ค่าใช้จ่ายที่เวลาบิลด์ก็อาจสูง ข้อมูลโค้ดต่อไปนี้ที่เพิ่มลงใน build.config ในเครื่องจะปิดใช้ LTO อย่างถาวรเมื่อใช้ 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)
}

ระบุเวอร์ชันเคอร์เนล

คุณระบุเวอร์ชันที่ถูกต้องเพื่อใช้สร้างได้จาก 2 แหล่งที่มา ได้แก่ ทรี AOSP และอิมเมจระบบ

เวอร์ชันเคอร์เนลจากโครงสร้าง AOSP

โครงสร้าง AOSP มีเคอร์เนลเวอร์ชันที่สร้างไว้ล่วงหน้า บันทึก git จะแสดงเวอร์ชันที่ถูกต้องเป็นส่วนหนึ่งของข้อความคอมมิต

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

หากไม่มีเวอร์ชันเคอร์เนลในบันทึก git ให้รับจากอิมเมจระบบตามที่อธิบายไว้ด้านล่าง

เวอร์ชันเคอร์เนลจากอิมเมจระบบ

หากต้องการตรวจสอบเวอร์ชันเคอร์เนลที่ใช้ในอิมเมจระบบ ให้เรียกใช้คำสั่งต่อไปนี้กับไฟล์เคอร์เนล

file kernel

สำหรับไฟล์ Image.lz4-dtb ให้เรียกใช้คำสั่งต่อไปนี้

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

สร้างอิมเมจการบูต

คุณสร้างอิมเมจบูตได้โดยใช้สภาพแวดล้อมการสร้างเคอร์เนล

สร้างอิมเมจการบูตสำหรับอุปกรณ์ที่มี init_boot

สำหรับอุปกรณ์ที่มี พาร์ติชัน init_boot ระบบจะสร้างอิมเมจบูตพร้อมกับเคอร์เนล ไม่ได้ฝังรูปภาพ initramfs ในอิมเมจบูต

เช่น เมื่อใช้ Kleaf คุณอาจสร้างอิมเมจการบูต GKI ด้วยคำสั่งต่อไปนี้

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

เมื่อใช้ build/build.sh (เดิม) คุณจะสร้างอิมเมจบูต GKI ได้ด้วย

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

อิมเมจบูต GKI อยู่ใน $DIST_DIR

สร้างอิมเมจการบูตสำหรับอุปกรณ์ที่ไม่มี init_boot (เดิม)

สำหรับอุปกรณ์ที่ไม่มีพาร์ติชัน init_boot คุณต้องมีไบนารี ramdisk ซึ่งคุณจะได้รับโดยดาวน์โหลดอิมเมจบูต GKI และแตกไฟล์ อิมเมจบูต GKI จาก Android รุ่นที่เกี่ยวข้องจะใช้งานได้

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

โฟลเดอร์เป้าหมายคือไดเรกทอรีระดับบนสุดของโครงสร้างเคอร์เนล (ไดเรกทอรีการทำงานปัจจุบัน)

หากคุณกำลังพัฒนาด้วยสาขาการเผยแพร่ AOSP ล่าสุด คุณสามารถดาวน์โหลด ramdisk-recovery.imgอาร์ติแฟกต์การสร้างจากบิลด์ aosp_arm64 ใน ci.android.com แทน แล้วใช้เป็นไบนารี ramdisk

เมื่อมีไบนารี ramdisk และคัดลอกไปยัง gki-ramdisk.lz4 ในรูท ของไดเรกทอรีการสร้างเคอร์เนลแล้ว คุณจะสร้างอิมเมจการบูตได้โดยการเรียกใช้คำสั่งต่อไปนี้

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

หากคุณใช้สถาปัตยกรรมที่ใช้ x86 ให้แทนที่ Image ด้วย bzImage และ aarch64 ด้วย 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

ไฟล์ดังกล่าวอยู่ในไดเรกทอรีอาร์ติแฟกต์ $KERNEL_ROOT/out/$KERNEL_VERSION/dist

อิมเมจบูตอยู่ที่ out/<kernel branch>/dist/boot.img