Android NDK รองรับการใช้ CMake เพื่อ
คอมไพล์โค้ด C และ C++ สำหรับแอปพลิเคชันของคุณ หน้านี้กล่าวถึงวิธีใช้
CMake ด้วย NDK ผ่าน ExternalNativeBuild
ของปลั๊กอิน Android Gradle หรือเมื่อ
การเรียกใช้ CMake โดยตรง
ไฟล์ Toolchain ของ CMake
NDK รองรับ CMake ผ่านไฟล์เครื่องมือเชน ไฟล์ Toolchain คือไฟล์ CMake
ที่ปรับแต่งลักษณะการทำงานของ Toolchain สำหรับการคอมไพล์แบบข้ามแพลตฟอร์ม Toolchain
ไฟล์ที่ใช้สำหรับ NDK จะอยู่ใน NDK ที่
<NDK>/build/cmake/android.toolchain.cmake
พารามิเตอร์บิลด์ เช่น ABI, minSdkVersion
ฯลฯ จะอยู่ในคำสั่ง
เมื่อเรียกใช้ cmake
ดูรายการอาร์กิวเมนต์ที่รองรับได้ที่
อาร์กิวเมนต์ Toolchain
"ใหม่" ไฟล์ Toolchain
ก่อนหน้านี้ NDK ได้ทดลองใช้ไฟล์ Toolchain ใหม่ซึ่ง จะลดความแตกต่างด้านลักษณะการทำงานระหว่างการใช้ไฟล์ Toolchain ของ NDK และ โดยใช้การสนับสนุน CMake ในตัว ซึ่งก็ต้องใช้ความพยายามอย่างมาก งาน (ซึ่งยังไม่เสร็จสมบูรณ์) แต่ไม่ได้ปรับปรุงการทำงานจริง เราจึงจะไม่จัดการกับเรื่องนี้อีกต่อไป
"ใหม่" ไฟล์ Toolchain มีการถดถอยของลักษณะการทำงานเมื่อเทียบกับ "เดิม"
Toolchain ลักษณะการทำงานเริ่มต้นคือเวิร์กโฟลว์ที่แนะนำ หากคุณ
โดยใช้ -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF
เราขอแนะนำให้นำธงออก
จากบิลด์ของคุณ ไฟล์ Toolchain ใหม่ไม่เคยเทียบเท่ากับไฟล์เดิม
Toolchain จึงมีโอกาสเกิดการถดถอยของพฤติกรรม
แม้ว่าเราจะไม่แนะนำให้ใช้ไฟล์ Toolchain ใหม่ แต่ขณะนี้ยังไม่มี วางแผนที่จะนำออกจาก NDK เนื่องจากจะทำให้บิลด์ที่ใช้องค์ประกอบ ความแตกต่างด้านลักษณะการทำงานระหว่างไฟล์ Toolchain ใหม่และไฟล์เดิม และ น่าเสียดายที่เราต้องเปลี่ยนชื่อตัวเลือกใหม่ เพื่อให้เห็นอย่างชัดเจนว่า "เวอร์ชันเดิม" จริงๆ แล้ว ที่แนะนำให้ใช้เป็นการรบกวนผู้ใช้ของตัวเลือกนี้ด้วย หากคุณพอใจกับการใช้ ไฟล์ Toolchain ใหม่ ที่คุณไม่จำเป็นต้องย้ายข้อมูล แต่โปรดทราบว่าข้อบกพร่องที่ส่ง กับลักษณะการทำงานของไฟล์ Toolchain ใหม่ อาจจะไม่ได้รับการแก้ไข และ ที่คุณต้องย้ายข้อมูล
การใช้งาน
เกรเดิล
การใช้ไฟล์ Toolchain ของ CMake เป็นไปโดยอัตโนมัติเมื่อใช้
externalNativeBuild
ดูเพิ่มโค้ด C และ C++ ลงใน
ของโปรเจ็กต์เพื่อดูข้อมูลเพิ่มเติม
บรรทัดคำสั่ง
เมื่อสร้างด้วย CMake นอก Gradle ไฟล์ Toolchain นั้นเองและ ต้องส่งอาร์กิวเมนต์ไปยัง CMake เช่น
$ cmake \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$ABI \
-DANDROID_PLATFORM=android-$MINSDKVERSION \
$OTHER_ARGS
อาร์กิวเมนต์ Toolchain
ระบบส่งอาร์กิวเมนต์ต่อไปนี้ไปยังไฟล์เครื่องมือเชน CMake ได้ หากกำลังสร้าง
ด้วย Gradle ให้เพิ่มอาร์กิวเมนต์ลงใน
android.defaultConfig.externalNativeBuild.cmake.arguments
ตามที่อธิบายไว้ใน
ExternalNativeBuild เอกสาร หากกำลังสร้างจากบรรทัดคำสั่ง ให้ส่งอาร์กิวเมนต์ไปที่
CMake ด้วย -D
เช่น บังคับให้ armeabi-v7a ไม่สร้างด้วย Neon
สนับสนุน โดยให้ผ่าน -DANDROID_ARM_NEON=FALSE
ANDROID_ABI
ABI เป้าหมาย ดูข้อมูลเกี่ยวกับ ABI ที่รองรับได้ที่ ABI ของ Android
เกรเดิล
Gradle ระบุอาร์กิวเมนต์นี้โดยอัตโนมัติ ไม่ต้องตั้งค่านี้อย่างชัดแจ้ง
ในไฟล์ build.gradle
หากต้องการควบคุมสิ่งที่ ABI Gradle กำหนดเป้าหมาย
ใช้ abiFilters
ตามที่อธิบายไว้ใน Android ABI
บรรทัดคำสั่ง
CMake บิลด์สําหรับเป้าหมายเดียวต่อบิลด์ หากต้องการกำหนดเป้าหมายเป็น Android มากกว่า 1 เครื่อง ABI คุณต้องสร้าง 1 ครั้งต่อ ABI ขอแนะนำให้ใช้บิลด์อื่น ไดเรกทอรีสำหรับ ABI แต่ละรายการเพื่อหลีกเลี่ยงการขัดแย้งระหว่างบิลด์
ค่า | หมายเหตุ |
---|---|
armeabi-v7a |
|
armeabi-v7a with NEON |
ราคาเท่ากันกับ armeabi-v7a |
arm64-v8a |
|
x86 |
|
x86_64 |
ANDROID_ARM_MODE
ระบุว่าจะสร้างคำสั่งสำหรับแขนหรือนิ้วโป้งสำหรับ armeabi-v7a ไม่มี สำหรับ ABI อื่นๆ ดูข้อมูลเพิ่มเติมได้ที่ ABI ของ Android เอกสารประกอบ
ค่า | หมายเหตุ |
---|---|
แขน | |
นิ้วโป้ง | ลักษณะการทำงานเริ่มต้น |
ANDROID_NATIVE_API_LEVEL
ชื่อแทนของ ANDROID_PLATFORM
ANDROID_PLATFORM
ระบุระดับ API ขั้นต่ำที่แอปพลิเคชันหรือไลบรารีรองรับ ช่วงเวลานี้
ตรงกับminSdkVersion
ของแอปพลิเคชัน
เกรเดิล
เมื่อใช้ปลั๊กอิน Android Gradle ค่านี้จะถูกตั้งเป็นโดยอัตโนมัติ
ตรงกับ minSdkVersion
ของแอปพลิเคชัน และไม่ควรตั้งค่าด้วยตนเอง
บรรทัดคำสั่ง
เมื่อเรียกใช้ CMake โดยตรง ค่านี้จะเริ่มต้นเป็นระดับ API ต่ำสุด รองรับการใช้งาน NDK เช่น ใช้ NDK r20 เป็นค่าเริ่มต้น เป็น API ระดับ 16
พารามิเตอร์นี้ยอมรับรูปแบบหลายรูปแบบ
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
รูปแบบ $API_LETTER
ช่วยให้คุณระบุ android-N
ได้โดยไม่ต้อง
ให้ระบุหมายเลขที่เชื่อมโยงกับรุ่นนั้นๆ โปรดทราบว่าบางรุ่น
ได้รับการเพิ่ม API โดยไม่ได้เพิ่มตัวอักษร สามารถระบุ API เหล่านี้ได้
โดยการเพิ่มส่วนต่อท้าย -MR1
ตัวอย่างเช่น API ระดับ 25 คือ android-N-MR1
ANDROID_STL
ระบุ STL ที่จะใช้สำหรับแอปพลิเคชันนี้ สำหรับข้อมูลเพิ่มเติม โปรดดูที่ C++
การสนับสนุนห้องสมุด ระบบจะใช้ c++_static
โดยค่าเริ่มต้น
ค่า | หมายเหตุ |
---|---|
c++_ แชร์ | ตัวแปรไลบรารีที่ใช้ร่วมกันของ libc++ |
c++_static | ตัวแปรไลบรารีแบบคงที่ของ libc++ |
ไม่มี | ไม่รองรับไลบรารีมาตรฐาน C++ |
ระบบ | STL ของระบบ |
จัดการแฟล็กคอมไพเลอร์
หากคุณต้องการส่งแฟล็กที่เฉพาะเจาะจงไปยังคอมไพเลอร์หรือ Linker สำหรับบิลด์ของคุณ โปรดดูเอกสารประกอบของ CMake สำหรับ set_target_compile_options และ กลุ่มตัวเลือกที่เกี่ยวข้อง คอลัมน์ "ดูเพิ่มเติม" ด้านล่างของหน้า เบาะแสบางส่วนที่มีประโยชน์
โดยทั่วไปแล้ว แนวทางปฏิบัติแนะนำคือให้ใช้แฟล็กคอมไพเลอร์ที่แคบที่สุด
ขอบเขตที่มีอยู่ การตั้งค่าสถานะที่ต้องการใช้กับเป้าหมายทั้งหมด (เช่น
-Werror
) อาจไม่สะดวกที่จะทำซ้ำในแต่ละโมดูล แต่ในบางกรณีก็แทบไม่เป็นเช่นนั้น
มีผลบังคับใช้ทั่วโลก (CMAKE_CXX_FLAGS
) เนื่องจากอาจส่งผลกระทบที่ไม่พึงประสงค์ต่อ
ทรัพยากร Dependency ของบุคคลที่สามในโปรเจ็กต์ของคุณ ในกรณีเช่นนี้ อาจมีการตั้งค่าสถานะ
ใช้กับขอบเขตไดเรกทอรี (add_compile_options
)
สำหรับแฟล็กคอมไพเลอร์ชุดย่อยๆ ก็ตั้งค่าใน create.gradle ได้เช่นกัน
ที่ใช้ cppFlags
หรือพร็อพเพอร์ตี้ที่คล้ายกัน คุณไม่ควรทำเช่นนี้ แฟล็ก
ที่ส่งไปยัง CMake จาก Gradle จะมีลักษณะการทำงานที่มีลำดับความสำคัญที่ไม่คาดคิด
กรณีที่ลบล้างการรายงานปัญหาที่ผ่านโดยปริยายโดยการติดตั้งใช้งานซึ่ง
ซึ่งจำเป็นสำหรับการสร้างโค้ด Android ชอบการจัดการลักษณะการทำงานของ CMake เสมอ
ใน CMake โดยตรง หากต้องการควบคุมแฟล็กคอมไพเลอร์ต่อ AGP buildType
ดูการใช้งานประเภทบิลด์ AGP ใน CMake
ทำงานกับบิลด์ประเภท AGP ใน CMake
หากต้องการปรับแต่งลักษณะการทำงานของ CMake ตาม Gradle ที่กำหนดเอง buildType
ให้ใช้
ประเภทบิลด์เพื่อส่งผ่านค่าสถานะ CMake เพิ่มเติม (ไม่ใช่แฟล็กคอมไพเลอร์) ที่
สคริปต์บิลด์ CMake อ่านได้ ตัวอย่างเช่น หากคุณมีคำว่า "ฟรี" และ "พรีเมียม"
ตัวแปรบิลด์ที่ควบคุมโดยbuild.gradle.kts และคุณต้องผ่าน
ข้อมูลดังกล่าวให้แก่ CMake
android {
buildTypes {
free {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
}
}
}
premium {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
}
}
}
}
}
จากนั้นให้ทำดังนี้ใน CMakeLists.txt
if (DPRODUCT_VARIANT_PREMIUM)
# Do stuff for the premium build.
else()
# Do stuff for the free build.
endif()
ชื่อของตัวแปรจะขึ้นอยู่กับคุณ แต่โปรดตรวจสอบว่าคุณหลีกเลี่ยงอะไรก็ได้ที่มี
ข้อความนำหน้า ANDROID_
, APP_
หรือ CMAKE_
เพื่อไม่ให้เกิดการชนหรือความสับสน
ที่มีอยู่
ดูตัวอย่างจากตัวอย่าง Sanitizers NDK
ทำความเข้าใจคำสั่งบิลด์ CMake
เมื่อแก้ไขข้อบกพร่องของบิลด์ CMake ควรทราบบิลด์ที่เฉพาะเจาะจง อาร์กิวเมนต์ที่ Gradle ใช้เมื่อการคอมไพล์แบบข้ามระบบสำหรับ Android
ปลั๊กอิน Android Gradle บันทึกอาร์กิวเมนต์ของบิลด์ที่ใช้สำหรับเรียกใช้
บิลด์ CMake สำหรับ ABI แต่ละรายการและประเภทบิลด์
จับคู่กับ build_command.txt
ไฟล์เหล่านี้อยู่ในรายการต่อไปนี้
ไดเรกทอรี:
<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างของอาร์กิวเมนต์ CMake เพื่อสร้าง
รุ่นที่สามารถแก้ไขข้อบกพร่องได้ของตัวอย่าง hello-jni
ซึ่งกำหนดเป้าหมายไปยัง armeabi-v7a
สถาปัตยกรรม
Executable : ${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/cmake
arguments :
-H${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/src/main/cpp
-DCMAKE_FIND_ROOT_PATH=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/prefab/armeabi-v7a/prefab
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake
-DANDROID_ABI=armeabi-v7a
-DANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DANDROID_PLATFORM=android-23
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_SYSTEM_VERSION=23
-B${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/armeabi-v7a
-GNinja
jvmArgs :
Build command args: []
Version: 1
ใช้ไลบรารีที่สร้างไว้ล่วงหน้า
หากไลบรารีที่สร้างไว้ล่วงหน้าที่คุณต้องการนำเข้ามีการเผยแพร่เป็น AAR ให้ทำตาม เอกสารทรัพยากร Dependency ของ Studio เพื่อนำเข้าและนำไปใช้ หากไม่ได้ใช้ AGP คุณสามารถติดตามได้ https://google.github.io/prefab/example-workflow.html แต่มีโอกาสมาก ย้ายข้อมูลไปยัง AGP ได้ง่ายขึ้น
สำหรับไลบรารีที่ไม่ได้กระจายเป็น AAR คำแนะนำเกี่ยวกับการใช้ที่สร้างไว้ล่วงหน้า
ไลบรารีที่มี CMake โปรดดูเอกสารประกอบ add_library
เกี่ยวกับ IMPORTED
เป้าหมายในคู่มือ CMaker
การสร้างโค้ดของบุคคลที่สาม
การสร้างโค้ดของบุคคลที่สามใน CMake ทำได้หลายวิธี โครงการ และตัวเลือกที่มีประสิทธิภาพที่สุดจะขึ้นอยู่กับสถานการณ์ของคุณ ดีที่สุด มักจะไม่ทำเช่นนี้เลย แต่ให้สร้าง AAR สำหรับฟังก์ชัน และใช้ไลบรารีนั้นในแอปพลิเคชันของคุณได้ คุณไม่จำเป็นต้อง เผยแพร่ว่า AAR โดยอาจเป็นโปรเจ็กต์ภายในโปรเจ็กต์ Gradle ของคุณ
หากไม่ได้เลือก ให้ทำดังนี้
- ผู้จำหน่าย (คัดลอก) แหล่งที่มาของบุคคลที่สามไปยังที่เก็บของคุณและการใช้งาน add_subdirectory เพื่อสร้างได้ วิธีนี้จะใช้ได้เฉพาะเมื่อไลบรารีอื่น ที่สร้างด้วย CMake
- กำหนดโปรเจ็กต์ภายนอก
- สร้างไลบรารีแยกจากโปรเจ็กต์แล้วทำตาม ใช้ไลบรารีที่สร้างไว้ล่วงหน้าเพื่อนำเข้าเป็นไลบรารีที่สร้างไว้ล่วงหน้า
การรองรับ YASM ใน CMake
NDK ให้การสนับสนุน CMake สำหรับรหัสประกอบอาคารที่เขียนด้วย YASM เพื่อเรียกใช้บน x86 และ x86-64 สถาปัตยกรรม YASM เป็นเครื่องมือประกอบแบบโอเพนซอร์สสำหรับ x86 และ x86-64 จากโมเดลประกอบของ NASM
หากต้องการสร้างโค้ดแอสเซมบลีด้วย CMake ให้ทำการเปลี่ยนแปลงต่อไปนี้ใน
CMakeLists.txt
:
- เรียกใช้
enable_language
โดยกำหนดค่าเป็นASM_NASM
- ขึ้นอยู่กับว่าคุณกำลังสร้างไลบรารีที่ใช้ร่วมกันหรือไฟล์ปฏิบัติการ
ไบนารี ให้เรียกใช้
add_library
หรือadd_executable
ใน ส่งอาร์กิวเมนต์ในรายการไฟล์ต้นฉบับที่ประกอบด้วยไฟล์.asm
ไฟล์ สำหรับโปรแกรมการประกอบใน YASM และไฟล์.c
สำหรับ C ที่เกี่ยวข้อง ไลบรารีหรือฟังก์ชัน
ตัวอย่างต่อไปนี้แสดงวิธีการกำหนดค่า CMakeLists.txt
ให้
สร้างโปรแกรม YASM เป็นไลบรารีที่ใช้ร่วมกัน
cmake_minimum_required(VERSION 3.6.0)
enable_language(ASM_NASM)
add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)
สำหรับตัวอย่างของวิธีสร้างโปรแกรม YASM เป็นไฟล์ปฏิบัติการ โปรดดู yasm ทดสอบ ในที่เก็บ Git ของ NDK
รายงานปัญหา
หากพบปัญหาเกี่ยวกับไฟล์ NDK หรือไฟล์เครื่องมือ CMake โปรดรายงาน ผ่านเครื่องมือติดตามปัญหา android-ndk/ndk บน GitHub สำหรับ Gradle หรือ ปัญหาเกี่ยวกับปลั๊กอิน Android Gradle โปรดรายงานข้อบกพร่องของ Studio แทน