CMake

Android NDK hỗ trợ sử dụng CMake để biên dịch mã C và C ++ cho ứng dụng của bạn. Trang này thảo luận về cách sử dụng CMake bằng NDK thông qua ExternalNativeBuild của Trình bổ trợ Android cho Gradle hoặc khi gọi trực tiếp CMake.

Tệp chuỗi công cụ CMake

NDK hỗ trợ CMake thông qua một tệp chuỗi công cụ. Tệp chuỗi công cụ là các tệp CMake tuỳ chỉnh hành vi của chuỗi công cụ để biên dịch chéo. Tệp chuỗi công cụ dành cho NDK nằm trong NDK tại <NDK>/build/cmake/android.toolchain.cmake.

Các tham số bản dựng như ABI, minSdkVersion, v.v. được cung cấp trên dòng lệnh khi gọi cmake. Để biết danh sách các đối số được hỗ trợ, hãy xem phần Các đối số chuỗi công cụ.

Cách sử dụng

Gradle

Tệp chuỗi công cụ CMake tự động được sử dụng trong trường hợp dùng externalNativeBuild. Xem hướng dẫn Thêm mã C và C++ của vào dự án của Android Studio để biết thêm thông tin.

Dòng lệnh

Khi tạo bằng CMake bên ngoài Gradle, chính tệp chuỗi công cụ và đối số của tệp phải được truyền đến CMake. Ví dụ:

$ cmake \
    -DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
    -DANDROID_ABI=$ABI \
    -DANDROID_PLATFORM=android-$MINSDKVERSION \
    $OTHER_ARGS

Đối số chuỗi công cụ

Bạn có thể truyền các đối số sau đến tệp chuỗi công cụ CMake. Nếu tạo bằng Gradle, hãy thêm các đối số vào android.defaultConfig.externalNativeBuild.cmake.arguments như mô tả trong tài liệu ExternalNativeBuild. Nếu tạo từ dòng lệnh, hãy truyền các đối số đến CMake bằng -D. Ví dụ: Để buộc armeabi-v7a luôn tạo bằng tính năng hỗ trợ Neon, hãy truyền -DANDROID_ARM_NEON=TRUE.

ANDROID_ABI

ABI (Giao diện nhị phân ứng dụng) mục tiêu. Để biết thông tin về các ABI (Giao diện nhị phân ứng dụng) được hỗ trợ, hãy xem ABI Android.

Gradle

Gradle sẽ tự động cung cấp đối số này. Không đặt đối số này một cách rõ ràng trong tệp build.gradle. Để kiểm soát loại ABI mà Gradle nhắm mục tiêu đến, hãy sử dụng abiFilters như mô tả trong ABI Android.

Dòng lệnh

CMake xây dựng cho một mục tiêu duy nhất/bản dựng. Để nhắm mục tiêu đến nhiều ABI Android, bạn phải tạo một bản dựng cho mỗi ABI. Bạn nên sử dụng nhiều thư mục bản dựng khác nhau cho từng ABI để tránh xung đột giữa các bản dựng.

Giá trị Ghi chú
armeabi-v7a
armeabi-v7a with NEON Tương tự như -DANDROID_ABI=armeabi-v7a -DANDROID_ARM_NEON=ON
arm64-v8a
x86
x86_64

ANDROID_ARM_MODE

Chỉ định xem có tạo hướng dẫn về ARM hoặc Thumb cho armeabi-v7a hay không. Không có hiệu lực đối với các ABI khác. Để biết thêm thông tin, hãy xem tài liệu về ABI Android.

Giá trị Ghi chú
arm
thumb Hành động mặc định.

ANDROID_ARM_NEON

Bật hoặc tắt NEON cho armeabi-v7a. Không ảnh hưởng đến các ABI khác. Giá trị mặc định là đúng cho API (minSdkVersion hoặc ANDROID_PLATFORM) cấp 23 trở lên, nếu không là sai. Để biết thêm thông tin, hãy xem tài liệu Hỗ trợ Neon.

Giá trị Ghi chú
TRUE Chế độ mặc định cho API cấp 23 trở lên.
FALSE Chế độ mặc định cho API cấp 22 trở về trước.

ANDROID_LD

Chọn trình liên kết muốn sử dụng. lld hiện đang được thử nghiệm cho NDK và có thể được bật với đối số này.

Giá trị Ghi chú
lld Bật lld.
mặc định Dùng trình liên kết mặc định cho ABI đã cho.

ANDROID_NATIVE_API_LEVEL

Bí danh cho ANDROID_PLATFORM.

ANDROID_PLATFORM

Chỉ định cấp độ API tối thiểu mà ứng dụng hoặc thư viện hỗ trợ. Giá trị này tương ứng với minSdkVersion của ứng dụng.

Gradle

Khi sử dụng Trình bổ trợ Android cho Gradle, giá trị này sẽ tự động được đặt cho khớp với minSdkVersion của ứng dụng và không được đặt theo cách thủ công.

Dòng lệnh

Khi gọi trực tiếp CMake, giá trị này sẽ mặc định áp dụng cho API cấp thấp nhất mà NDK bạn sử dụng hỗ trợ. Ví dụ: Với NDK r20, giá trị này mặc định áp dụng cho API cấp 16.

Hệ thống chấp nhận nhiều định dạng cho tham số này:

  • android-$API_LEVEL
  • $API_LEVEL
  • android-$API_LETTER

Định dạng $API_LETTER cho phép bạn chỉ định android-N mà không cần xác định số liên kết với bản phát hành đó. Xin lưu ý rằng một số bản phát hành đã tăng cấp độ API nhưng không tăng chữ cái. Bạn có thể chỉ định các API này bằng cách thêm hậu tố -MR1. Ví dụ: API cấp 25 là android-N-MR1.

ANDROID_STL

Chỉ định STL bạn muốn sử dụng cho ứng dụng này. Để biết thêm thông tin, hãy xem phần Hỗ trợ thư viện C++. Theo mặc định, c++_static sẽ được sử dụng.

Giá trị Ghi chú
c++_shared Biến thể thư viện dùng chung của libc++.
c++_static Biến thể thư viện tĩnh của libc++.
none Không hỗ trợ thư viện chuẩn C++.
system STL hệ thống

Tìm hiểu về lệnh bản dựng CMake

Khi gỡ lỗi các vấn đề về bản dựng CMake, bạn nên biết các đối số bản dựng cụ thể mà Gradle sử dụng khi biên dịch chéo cho Android.

Trình bổ trợ Android cho Gradle sẽ lưu các đối số bản dựng mà công cụ này sử dụng để thực thi bản dựng CMake dành cho mỗi cặp ABI và loại hình xây dựng vào build_command.txt. Các tệp này có trong thư mục sau:

<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/

Đoạn mã sau đây cho thấy ví dụ về các đối số CMake để tạo một bản phát hành có thể gỡ lỗi của mẫu hello-jni nhắm mục tiêu đến cấu trúc 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

Sử dụng thư viện tạo sẵn

Nếu thư viện tạo sẵn mà bạn cần nhập được phân phối dưới dạng AAR (đề xuất được tự động áp dụng), hãy làm theo tài liệu về phần phụ thuộc của Studio để nhập và sử dụng những thư viện đó. Nếu không dùng AGP, bạn có thể làm theo hướng dẫn trên https://google.github.io/prefab/example-workflow.html nhưng rất có thể việc di chuyển sang AGP sẽ dễ dàng hơn rất nhiều.

Đối với các thư viện không được phân phối dưới dạng AAR, để được hướng dẫn về cách sử dụng thư viện tạo sẵn bằng CMake, hãy xem tài liệu add_library về các mục tiêu IMPORTED trong hướng dẫn sử dụng CMake.

Tạo mã bên thứ ba

Có một số cách để tạo mã bên thứ ba trong dự án CMake và cách nào hiệu quả nhất sẽ tuỳ thuộc vào tình huống của bạn. Thông thường, cách tốt nhất là hoàn toàn không làm việc này. Thay vào đó, hãy tạo AAR cho thư viện rồi dùng đề xuất đó trong ứng dụng. Bạn không nhất thiết phải phát hành AAR đó. Bạn có thể dùng riêng AAR đó trong dự án Gradle của mình.

Nếu cách này không phù hợp:

  • Nhà cung cấp (tức là sao chép) nguồn bên thứ ba vào kho lưu trữ của bạn và dùng add_subdirectory để tạo kho lưu trữ đó. Cách này chỉ hiệu quả nếu thư viện khác cũng được tạo bằng CMake.
  • Xác định ExternalProject.
  • Tạo thư viện riêng biệt với dự án của bạn và làm theo hướng dẫn Sử dụng thư viện tạo sẵn để nhập thư viện đó làm thư viện tạo sẵn.

Hỗ trợ YASM trong CMake

NDK hỗ trợ dùng CMake để tạo mã tập hợp được ghi trong YASM nhằm chạy trên cấu trúc x86 và x86-64. YASM là một trình tập hợp nguồn mở cho các cấu trúc x86 và x86-64, dựa trên trình tập hợp NASM.

Để tạo mã tập hợp bằng CMake, hãy thực hiện các thay đổi sau trong CMakeLists.txt của dự án:

  1. Gọi enable_language với giá trị được đặt thành ASM_NASM.
  2. Tuỳ thuộc vào việc bạn đang tạo thư viện dùng chung hay tệp nhị phân có thể thực thi, hãy gọi add_library hoặc add_executable. Trong các đối số, hãy truyền một danh sách các tệp nguồn chứa các tệp .asm cho chương trình tập hợp trong YASM và tệp .c cho các hàm hoặc thư viện C liên kết.

Đoạn mã sau đây cho biết cách bạn có thể định cấu hình CMakeLists.txt để tạo chương trình YASM dưới dạng thư viện dùng chung.

cmake_minimum_required(VERSION 3.6.0)

enable_language(ASM_NASM)

add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)

Để biết ví dụ về cách tạo chương trình YASM dưới dạng tệp thực thi, hãy xem kiểm thử yasm trong kho lưu trữ git NDK.

Báo cáo sự cố

Nếu bạn gặp bất kỳ sự cố nào với NDK hoặc tệp chuỗi công cụ CMake, hãy báo cáo thông qua công cụ theo dõi lỗi android-ndk/ndk trên GitHub. Đối với các sự cố về Gradle hoặc Trình bổ trợ Android cho Gradle, hãy báo cáo lỗi Studio.