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

หน้านี้จะอธิบายรายละเอียดกระบวนการสร้างเคอร์เนลที่กำหนดเองสำหรับอุปกรณ์ Android วิธีการเหล่านี้จะแนะนำกระบวนการเลือกแหล่งที่มาที่เหมาะสม สร้างเคอร์เนล และฝังผลลัพธ์ลงในอิมเมจระบบที่สร้างจาก Android Open Source Project (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 ให้เรียกใช้คำสั่งต่อไปนี้

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 Fragment เพื่อปรับแต่งการกำหนดค่าเคอร์เนล โปรดดูเอกสารประกอบ Kleaf เกี่ยวกับ Defconfig Fragment

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

ใน 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