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

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

คุณรับแหล่งที่มาของเคอร์เนลที่ใหม่กว่าได้โดยใช้ Repo ซึ่งสร้างโดยไม่ต้องกำหนดค่าเพิ่มเติมด้วยการเรียกใช้ build/build.sh จากรูทของจุดชำระเงินต้นทาง

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

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

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

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

ดูรายการของ Repo Branch (BRANCH) ที่ใช้กับคำสั่ง "repo init" ได้ก่อนหน้าที่หัวข้อสาขาของ Kernel และระบบบิลด์

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

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

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

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

หากต้องการสร้างการแจกจ่ายสำหรับเคอร์เนล GKI สําหรับสถาปัตยกรรม aarch64 ให้ตรวจสอบสาขาเคอร์เนล Android Common ที่เก่ากว่า 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 ให้เรียกใช้คำสั่งต่อไปนี้

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 หมึกกระดองและปลาทองจะรวมกันเป็นเวอร์ชันเดียวกัน จึงใช้เคอร์เนลเดียวกัน 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 และ Emulator) ดังนี้

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 จากไฟล์ Manifest ของเคอร์เนล 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

ดูข้อมูลเพิ่มเติมได้ที่พัฒนาเคอร์เนลใน 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 เพื่อปรับแต่งการกำหนดค่าเคอร์เนล โปรดดูเอกสารประกอบของ Kleaf เกี่ยวกับกลุ่มคำสั่ง defconfig

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

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

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

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

ตัวอย่างที่พบบ่อยคือการปิดใช้การเพิ่มประสิทธิภาพเวลาลิงก์ (LTO) สําหรับเคอร์เนลการแรเงาด้วยเส้นขนานระหว่างการพัฒนา แม้ว่า 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 และใช้เป็นไบนารี RAM แทนได้

เมื่อคุณมีไบนารี 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