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

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

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

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

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

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

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

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

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

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

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

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

หากต้องการสร้างการกระจายสำหรับเคอร์เนล GKI สำหรับสถาปัตยกรรม AArc64 โปรดดูที่ สาขา Kernel ของ 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 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 ด้วยชุดเคอร์เนลที่เฉพาะเจาะจง” อาร์ติแฟกต์ ให้เรียกใช้คำสั่ง 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 กระบวนการและผลลัพธ์การสร้างอาจได้รับอิทธิพลจากตัวแปรสภาพแวดล้อม ซึ่งส่วนใหญ่จะเป็นแบบไม่บังคับ และ Kernel Branch แต่ละรายการควรมาพร้อมกับ การกำหนดค่าเริ่มต้น รายการที่ใช้บ่อยที่สุดจะแสดงอยู่ที่นี่ สำหรับ รายการที่ครบถ้วน (และเป็นปัจจุบัน) โปรดดู 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 ขึ้นไป คุณอาจใช้ Fragment defconfig ได้ เพื่อปรับแต่งการกำหนดค่าเคอร์เนล ดู เอกสารประกอบของ Kleaf เกี่ยวกับส่วนย่อย defconfig

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

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

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

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

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

เวอร์ชัน Kernel จากอิมเมจของระบบ

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

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 คุณจะต้องมีไบนารีของแรมดิสก์ ซึ่งคุณรับได้โดยการดาวน์โหลดอิมเมจการบูต 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

เมื่อคุณมีไบนารี RAM และคัดลอกไปยัง 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