หน้านี้จะอธิบายขั้นตอนการสร้างเคอร์เนลที่กำหนดเองสำหรับอุปกรณ์ 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