Dukungan sistem build VNDK

Di Android 8.1 dan yang lebih tinggi, sistem build memiliki dukungan VNDK bawaan. Saat dukungan VNDK diaktifkan, sistem build akan memeriksa dependensi antar modul, mem-build varian khusus vendor untuk modul vendor, dan otomatis menginstal modul tersebut ke direktori yang ditetapkan.

Contoh dukungan build VNDK

Dalam contoh ini, definisi modul Android.bp menentukan library bernama libexample. Properti vendor_available menunjukkan modul framework dan modul vendor dapat bergantung pada libexample:

libexample vendor_available:true dan vndk.enabled:true

Gambar 1. diaktifkan.

/system/bin/foo yang dapat dieksekusi framework dan /vendor/bin/bar yang dapat dieksekusi vendor bergantung pada libexample dan memiliki libexample dalam properti shared_libs-nya.

Jika libexample digunakan oleh modul framework dan modul vendor, dua varian libexample akan di-build. Varian inti (dinamai setelah libexample) digunakan oleh modul framework dan varian vendor (dinamai setelah libexample.vendor) digunakan oleh modul vendor. Kedua varian diinstal ke dalam direktori yang berbeda:

  • Varian inti diinstal ke /system/lib[64]/libexample.so.
  • Varian vendor diinstal ke VNDK APEX karena vndk.enabled adalah true.

Untuk detail selengkapnya, lihat Definisi modul.

Mengonfigurasi dukungan build

Untuk mengaktifkan dukungan sistem build penuh bagi perangkat produk, tambahkan BOARD_VNDK_VERSION ke BoardConfig.mk:

BOARD_VNDK_VERSION := current

Setelan ini memiliki efek global: Jika ditentukan di BoardConfig.mk, semua modul akan diperiksa. Karena tidak ada mekanisme untuk memblokir atau mengizinkan modul yang bermasalah, Anda harus membersihkan semua dependensi yang tidak diperlukan sebelum menambahkan BOARD_VNDK_VERSION. Anda dapat menguji dan mengompilasi modul dengan menetapkan BOARD_VNDK_VERSION di variabel lingkungan:

$ BOARD_VNDK_VERSION=current m module_name.vendor

Jika BOARD_VNDK_VERSION diaktifkan, beberapa jalur penelusuran header global default akan dihapus. Ini mencakup:

  • frameworks/av/include
  • frameworks/native/include
  • frameworks/native/opengl/include
  • hardware/libhardware/include
  • hardware/libhardware_legacy/include
  • hardware/ril/include
  • libnativehelper/include
  • libnativehelper/include_deprecated
  • system/core/include
  • system/media/audio/include

Jika modul bergantung pada header dari direktori ini, Anda harus menentukan (secara eksplisit) dependensi dengan header_libs, static_libs, dan/atau shared_libs.

VNDK APEX

Di Android 10 dan yang lebih lama, modul dengan vndk.enabled diinstal di /system/lib[64]/vndk[-sp]-${VER}. Di Android 11 dan yang lebih tinggi, library VNDK dikemas dalam format APEX dan nama VNDK APEX adalah com.android.vndk.v${VER}. Bergantung pada konfigurasi perangkat, VNDK APEX diratakan atau tidak diratakan dan tersedia dari jalur kanonis /apex/com.android.vndk.v${VER}.

APEX VNDK

Gambar 2. VNDK APEX.

Definisi modul

Untuk mem-build Android dengan BOARD_VNDK_VERSION, Anda harus merevisi definisi modul di Android.mk atau Android.bp. Bagian ini menjelaskan berbagai jenis definisi modul, beberapa properti modul terkait VNDK, dan pemeriksaan dependensi yang diterapkan dalam sistem build.

Modul vendor

Modul vendor adalah library yang dapat dieksekusi khusus vendor atau library bersama yang harus diinstal ke dalam partisi vendor. Dalam file Android.bp, modul vendor harus menetapkan properti vendor atau properti eksklusif ke true. Dalam file Android.mk, modul vendor harus menetapkan LOCAL_VENDOR_MODULE atau LOCAL_PROPRIETARY_MODULE ke true.

Jika BOARD_VNDK_VERSION ditentukan, sistem build tidak mengizinkan dependensi antara modul vendor dan modul framework serta menampilkan error jika:

  • modul tanpa vendor:true bergantung pada modul dengan vendor:true, atau
  • modul dengan vendor:true bergantung pada modul non-llndk_library yang tidak memiliki vendor:true atau vendor_available:true.

Pemeriksaan dependensi berlaku untuk header_libs, static_libs, dan shared_libs dalam Android.bp, serta untuk LOCAL_HEADER_LIBRARIES, LOCAL_STATIC_LIBRARIES, dan LOCAL_SHARED_LIBRARIES dalam Android.mk.

LL-NDK

Library bersama LL-NDK adalah library bersama dengan ABI yang stabil. Modul framework dan vendor memiliki implementasi yang sama dan terbaru. Untuk setiap library bersama LL-NDK, cc_library berisi properti llndk dengan file simbol:

cc_library {
    name: "libvndksupport",
    llndk: {
        symbol_file: "libvndksupport.map.txt",
    },
}

File simbol menjelaskan simbol yang terlihat oleh modul vendor. Contoh:

LIBVNDKSUPPORT {
  global:
    android_load_sphal_library; # llndk
    android_unload_sphal_library; # llndk
  local:
    *;
};

Berdasarkan file simbol, sistem build akan menghasilkan library bersama stub untuk modul vendor, yang ditautkan dengan library ini saat BOARD_VNDK_VERSION diaktifkan. Simbol disertakan dalam library bersama stub hanya jika:

  • Tidak ditentukan di bagian yang diakhiri dengan _PRIVATE atau _PLATFORM,
  • Tidak memiliki tag #platform-only, dan
  • Tidak memiliki tag #introduce* atau tag cocok dengan target.

VNDK

Dalam file Android.bp, definisi modul cc_library, cc_library_static, cc_library_shared, dan cc_library_headers mendukung tiga properti terkait VNDK: vendor_available, vndk.enabled, dan vndk.support_system_process.

Jika vendor_available atau vndk.enabled adalah true, dua varian (core dan vendor) dapat dibuat. Varian inti harus diperlakukan sebagai modul framework dan varian vendor harus diperlakukan sebagai modul vendor. Jika beberapa modul framework bergantung pada modul ini, varian inti akan di-build. Jika beberapa modul vendor bergantung pada modul ini, varian vendor akan di-build. Sistem build menerapkan pemeriksaan dependensi berikut:

  • Varian inti selalu khusus framework dan tidak dapat diakses oleh modul vendor.
  • Varian vendor selalu tidak dapat diakses oleh modul framework.
  • Semua dependensi varian vendor, yang ditentukan dalam header_libs, static_libs, dan/atau shared_libs, harus berupa llndk_library atau modul dengan vendor_available atau vndk.enabled.
  • Jika vendor_available adalah true, varian vendor dapat diakses oleh semua modul vendor.
  • Jika vendor_available adalah false, varian vendor hanya dapat diakses oleh modul VNDK atau VNDK-SP lainnya (yaitu, modul dengan vendor:true tidak dapat menautkan modul vendor_available:false).

Jalur penginstalan default untuk cc_library atau cc_library_shared ditentukan oleh aturan berikut:

  • Varian inti diinstal ke /system/lib[64].
  • Jalur penginstalan varian vendor dapat bervariasi:
    • Jika vndk.enabled adalah false, varian vendor akan diinstal ke /vendor/lib[64].
    • Jika vndk.enabled adalah true, varian vendor akan diinstal ke VNDK APEX(com.android.vndk.v${VER}).

Tabel di bawah merangkum cara sistem build menangani varian vendor:

vendor_available vndk
enabled
vndk
support_same_process
Deskripsi varian vendor
true false false Varian vendor adalah HANYA VND. Library bersama diinstal ke /vendor/lib[64].
true Tidak valid (Error build)
true false Varian vendor adalah VNDK. Library bersama diinstal ke VNDK APEX.
true Varian vendor adalah VNDK-SP. Library bersama diinstal ke VNDK APEX.

false

false

false

Tidak ada varian vendor. Modul ini adalah HANYA FWK.

true Tidak valid (Error build)
true false Varian vendor adalah VNDK-Private. Library bersama diinstal ke VNDK APEX. Solusi ini tidak boleh langsung digunakan oleh modul vendor.
true Varian vendor adalah VNDK-SP-Private. Library bersama diinstal ke VNDK APEX. Ini tidak boleh digunakan langsung oleh modul vendor.

Ekstensi VNDK

Ekstensi VNDK adalah library bersama VNDK dengan API tambahan. Ekstensi diinstal ke /vendor/lib[64]/vndk[-sp] (tanpa akhiran versi) dan mengganti library bersama VNDK asli saat runtime.

Menentukan ekstensi VNDK

Di Android 9 dan yang lebih baru, Android.bp secara native mendukung ekstensi VNDK. Untuk mem-build ekstensi VNDK, tentukan modul lain dengan properti vendor:true dan extends:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
}

Modul dengan properti vendor:true, vndk.enabled:true, dan extends menentukan ekstensi VNDK:

  • Properti extends harus menentukan nama library bersama VNDK dasar (atau nama library bersama VNDK-SP).
  • Ekstensi VNDK (atau ekstensi VNDK-SP) diberi nama berdasarkan nama modul dasar tempat ekstensi tersebut berasal. Misalnya, biner output libvndk_ext adalah libvndk.so, bukan libvndk_ext.so.
  • Ekstensi VNDK diinstal ke /vendor/lib[64]/vndk.
  • Ekstensi VNDK-SP diinstal ke /vendor/lib[64]/vndk-sp.
  • Library bersama dasar harus memiliki vndk.enabled:true dan vendor_available:true.

Ekstensi VNDK-SP harus diperluas dari library bersama VNDK-SP (vndk.support_system_process harus sama):

cc_library {
    name: "libvndk_sp",
    vendor_available: true,
    vndk: {
        enabled: true,
        support_system_process: true,
    },
}

cc_library {
    name: "libvndk_sp_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk_sp",
        support_system_process: true,
    },
}

Ekstensi VNDK (atau ekstensi VNDK-SP) dapat bergantung pada library bersama vendor lain:

cc_library {
    name: "libvndk",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libvndk_ext",
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libvndk",
    },
    shared_libs: [
        "libvendor",
    ],
}

cc_library {
    name: "libvendor",
    vendor: true,
}

Menggunakan ekstensi VNDK

Jika modul vendor bergantung pada API tambahan yang ditentukan oleh ekstensi VNDK, modul harus menentukan nama ekstensi VNDK dalam properti shared_libs-nya:

// A vendor shared library example
cc_library {
    name: "libvendor",
    vendor: true,
    shared_libs: [
        "libvndk_ext",
    ],
}

// A vendor executable example
cc_binary {
    name: "vendor-example",
    vendor: true,
    shared_libs: [
        "libvndk_ext",
    ],
}

Jika modul vendor bergantung pada ekstensi VNDK, ekstensi VNDK tersebut akan diinstal ke /vendor/lib[64]/vndk[-sp] secara otomatis. Jika modul tidak lagi bergantung pada ekstensi VNDK, tambahkan langkah pembersihan ke CleanSpec.mk untuk menghapus library bersama. Contoh:

$(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so)

Kompilasi bersyarat

Bagian ini menjelaskan cara menangani perbedaan kecil (misalnya menambahkan atau menghapus fitur dari salah satu varian) antara tiga library bersama VNDK berikut:

  • Varian inti (misalnya, /system/lib[64]/libexample.so)
  • Varian vendor (misalnya /apex/com.android.vndk.v${VER}/lib[64]/libexample.so)
  • Ekstensi VNDK (misalnya, /vendor/lib[64]/vndk[-sp]/libexample.so)

Flag compiler bersyarat

Sistem build Android menentukan __ANDROID_VNDK__ untuk varian vendor dan ekstensi VNDK secara default. Anda dapat melindungi kode dengan penjaga preprocessor C:

void all() { }

#if !defined(__ANDROID_VNDK__)
void framework_only() { }
#endif

#if defined(__ANDROID_VNDK__)
void vndk_only() { }
#endif

Selain __ANDROID_VNDK__, cflags atau cppflags yang berbeda dapat ditentukan di Android.bp. cflags atau cppflags yang ditentukan dalam target.vendor bersifat khusus untuk varian vendor.

Misalnya, Android.bp berikut menentukan libexample dan libexample_ext:

cc_library {
    name: "libexample",
    srcs: ["src/example.c"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    target: {
        vendor: {
            cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"],
        },
    },
}

cc_library {
    name: "libexample_ext",
    srcs: ["src/example.c"],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample",
    },
    cflags: [
        "-DLIBEXAMPLE_ENABLE_VNDK=1",
        "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1",
    ],
}

Dan ini adalah listingan kode src/example.c:

void all() { }

#if !defined(LIBEXAMPLE_ENABLE_VNDK)
void framework_only() { }
#endif

#if defined(LIBEXAMPLE_ENABLE_VNDK)
void vndk() { }
#endif

#if defined(LIBEXAMPLE_ENABLE_VNDK_EXT)
void vndk_ext() { }
#endif

Menurut kedua file ini, sistem build menghasilkan library bersama dengan simbol yang diekspor berikut:

Jalur penginstalan Simbol yang diekspor
/system/lib[64]/libexample.so all, framework_only
/apex/com.android.vndk.v${VER}/lib[64]/libexample.so all, vndk
/vendor/lib[64]/vndk/libexample.so all, vndk, vndk_ext

Persyaratan pada simbol yang diekspor

Pemeriksa ABI VNDK membandingkan ABI varian vendor VNDK dan ekstensi VNDK dengan dump ABI referensi di prebuilts/abi-dumps/vndk.

  • Simbol yang diekspor oleh varian vendor VNDK (misalnya /apex/com.android.vndk.v${VER}/lib[64]/libexample.so) harus identik dengan (bukan superset) simbol yang ditentukan dalam dump ABI.
  • Simbol yang diekspor oleh ekstensi VNDK (misalnya, /vendor/lib[64]/vndk/libexample.so) harus berupa superset simbol yang ditentukan dalam dump ABI.

Jika Varian vendor VNDK atau ekstensi VNDK gagal mengikuti persyaratan di atas, pemeriksa ABI VNDK akan memunculkan error build dan menghentikan build.

Mengecualikan file sumber atau library bersama dari varian vendor

Untuk mengecualikan file sumber dari varian vendor, tambahkan file tersebut ke properti exclude_srcs. Demikian pula, untuk memastikan library bersama tidak ditautkan dengan varian vendor, tambahkan library tersebut ke properti exclude_shared_libs. Contoh:

cc_library {
    name: "libexample_cond_exclude",
    srcs: ["fwk.c", "both.c"],
    shared_libs: ["libfwk_only", "libboth"],
    vendor_available: true,
    target: {
        vendor: {
            exclude_srcs: ["fwk.c"],
            exclude_shared_libs: ["libfwk_only"],
        },
    },
}

Dalam contoh ini, varian inti libexample_cond_exclude menyertakan kode dari fwk.c dan both.c serta bergantung pada library bersama libfwk_only dan libboth. Varian vendor libexample_cond_exclude hanya menyertakan kode dari both.c karena fwk.c dikecualikan oleh properti exclude_srcs. Demikian pula, kode ini hanya bergantung pada library bersama libboth karena libfwk_only dikecualikan oleh properti exclude_shared_libs.

Mengekspor header dari ekstensi VNDK

Ekstensi VNDK dapat menambahkan class baru atau fungsi baru ke library bersama VNDK. Sebaiknya simpan deklarasi tersebut dalam header independen dan hindari mengubah header yang ada.

Misalnya, file header baru include-ext/example/ext/feature_name.h dibuat untuk ekstensi VNDK libexample_ext:

  • Android.bp
  • include-ext/example/ext/feature_name.h
  • include/example/example.h
  • src/example.c
  • src/ext/feature_name.c

Dalam Android.bp berikut, libexample hanya mengekspor include, sedangkan libexample_ext mengekspor include dan include-ext. Hal ini memastikan feature_name.h tidak akan salah disertakan oleh pengguna libexample:

cc_library {
    name: "libexample",
    srcs: ["src/example.c"],
    export_include_dirs: ["include"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libexample_ext",
    srcs: [
        "src/example.c",
        "src/ext/feature_name.c",
    ],
    export_include_dirs: [
        "include",
        "include-ext",
    ],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample",
    },
}

Jika memisahkan ekstensi ke file header independen tidak memungkinkan, alternatifnya adalah menambahkan penjaga #ifdef. Namun, pastikan semua pengguna ekstensi VNDK menambahkan flag definisi. Anda dapat menentukan cc_defaults untuk menambahkan flag yang ditentukan ke cflags dan menautkan library bersama dengan shared_libs.

Misalnya, untuk menambahkan fungsi anggota baru Example2::get_b() ke ekstensi VNDK libexample2_ext, Anda harus mengubah file header yang ada dan menambahkan guard #ifdef:

#ifndef LIBEXAMPLE2_EXAMPLE_H_
#define LIBEXAMPLE2_EXAMPLE_H_

class Example2 {
 public:
  Example2();

  void get_a();

#ifdef LIBEXAMPLE2_ENABLE_VNDK_EXT
  void get_b();
#endif

 private:
  void *impl_;
};

#endif  // LIBEXAMPLE2_EXAMPLE_H_

cc_defaults bernama libexample2_ext_defaults ditentukan untuk pengguna libexample2_ext:

cc_library {
    name: "libexample2",
    srcs: ["src/example2.cpp"],
    export_include_dirs: ["include"],
    vendor_available: true,
    vndk: {
        enabled: true,
    },
}

cc_library {
    name: "libexample2_ext",
    srcs: ["src/example2.cpp"],
    export_include_dirs: ["include"],
    vendor: true,
    vndk: {
        enabled: true,
        extends: "libexample2",
    },
    cflags: [
        "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1",
    ],
}

cc_defaults {
    name: "libexample2_ext_defaults",
    shared_libs: [
        "libexample2_ext",
    ],
    cflags: [
        "-DLIBEXAMPLE2_ENABLE_VNDK_EXT=1",
    ],
}

Pengguna libexample2_ext cukup menyertakan libexample2_ext_defaults dalam properti defaults mereka:

cc_binary {
    name: "example2_user_executable",
    defaults: ["libexample2_ext_defaults"],
    vendor: true,
}

Paket produk

Dalam sistem build Android, variabel PRODUCT_PACKAGES menentukan file yang dapat dieksekusi, library bersama, atau paket yang harus diinstal ke dalam perangkat. Dependensi transitif dari modul yang ditentukan juga diinstal secara implisit ke dalam perangkat.

Jika BOARD_VNDK_VERSION diaktifkan, modul dengan vendor_available atau vndk.enabled akan mendapatkan perlakuan khusus. Jika modul framework bergantung pada modul dengan vendor_available atau vndk.enabled, varian inti akan disertakan dalam kumpulan penginstalan transitif. Jika modul vendor bergantung pada modul dengan vendor_available, varian vendor akan disertakan dalam kumpulan penginstalan transitif. Namun, varian vendor modul dengan vndk.enabled diinstal, terlepas dari apakah modul tersebut digunakan oleh modul vendor atau tidak.

Jika dependensi tidak terlihat oleh sistem build (misalnya, library bersama yang dapat dibuka dengan dlopen() dalam runtime), Anda harus menentukan nama modul di PRODUCT_PACKAGES untuk menginstal modul tersebut secara eksplisit.

Jika modul memiliki vendor_available atau vndk.enabled, nama modul akan mewakili varian intinya. Untuk menentukan varian vendor secara eksplisit di PRODUCT_PACKAGES, tambahkan akhiran .vendor ke nama modul. Contoh:

cc_library {
    name: "libexample",
    srcs: ["example.c"],
    vendor_available: true,
}

Dalam contoh ini, libexample adalah singkatan dari /system/lib[64]/libexample.so dan libexample.vendor adalah singkatan dari /vendor/lib[64]/libexample.so. Untuk menginstal /vendor/lib[64]/libexample.so, tambahkan libexample.vendor ke PRODUCT_PACKAGES:

PRODUCT_PACKAGES += libexample.vendor