VNDK Derleme Sistemi Desteği

Android 8.1 ve sonraki sürümlerde derleme sistemi yerleşik VNDK desteğine sahiptir. VNDK desteği etkinleştirildiğinde, yapı sistemi modüller arasındaki bağımlılıkları kontrol eder, satıcı modülleri için satıcıya özgü bir değişken oluşturur ve bu modülleri otomatik olarak belirlenen dizinlere yükler.

VNDK derleme desteği örneği

Bu örnekte Android.bp modül tanımı libexample adlı bir kitaplığı tanımlar. vendor_available özelliği, çerçeve modüllerinin ve satıcı modüllerinin libexample bağlı olabileceğini belirtir:

libexample satıcı_available:true ve vndk.enabled:true

Şekil 1. VNDK desteği etkin

Hem çerçeve çalıştırılabilir /system/bin/foo hem de satıcı çalıştırılabilir /vendor/bin/bar libexample bağlıdır ve onların shared_libs özelliklerinde libexample bulunur.

libexample hem çerçeve modülleri hem de satıcı modülleri tarafından kullanılıyorsa, libexample iki çeşidi oluşturulur. Çekirdek değişken ( libexample sonra adlandırılır) çerçeve modülleri tarafından kullanılır ve satıcı değişkeni ( libexample.vendor sonra adlandırılır) satıcı modülleri tarafından kullanılır. İki değişken farklı dizinlere yüklenir:

  • Çekirdek değişken /system/lib[64]/libexample.so dosyasına yüklenir.
  • vndk.enabled true olduğundan satıcı değişkeni VNDK APEX'e yüklenir.

Daha fazla ayrıntı için bkz. Modül tanımı .

Derleme desteğini yapılandırma

Bir ürün cihazı için tam yapı sistemi desteğini etkinleştirmek için BoardConfig.mk dosyasına BOARD_VNDK_VERSION ekleyin:

BOARD_VNDK_VERSION := current

Bu ayarın genel bir etkisi vardır: BoardConfig.mk tanımlandığında tüm modüller kontrol edilir. Sorunlu bir modülü kara listeye veya beyaz listeye alacak bir mekanizma olmadığından, BOARD_VNDK_VERSION eklemeden önce tüm gereksiz bağımlılıkları temizlemelisiniz. Ortam değişkenlerinizde BOARD_VNDK_VERSION ayarını yaparak bir modülü test edebilir ve derleyebilirsiniz:

$ BOARD_VNDK_VERSION=current m module_name.vendor

BOARD_VNDK_VERSION etkinleştirildiğinde, birkaç varsayılan genel başlık arama yolu kaldırılır . Bunlar şunları içerir:

  • 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

Bir modül bu dizinlerdeki başlıklara bağlıysa, bağımlılıkları header_libs , static_libs ve/veya shared_libs ile belirtmeniz gerekir (açıkça).

VNDK APEX

Android 10 ve önceki sürümlerde, vndk.enabled içeren modüller /system/lib[64]/vndk[-sp]-${VER} dizinine kuruluydu. Android 11 ve üzeri sürümlerde, VNDK kitaplıkları APEX biçiminde paketlenir ve VNDK APEX'in adı com.android.vndk.v${VER} şeklindedir. Cihaz yapılandırmasına bağlı olarak, VNDK APEX düzleştirilmiş veya düzleştirilmemiş olabilir ve /apex/com.android.vndk.v${VER} standart yolundan edinilebilir.

VNDK APEX

Şekil 2. VNDK APEX

Modül tanımı

BOARD_VNDK_VERSION ile Android oluşturmak için Android.mk veya Android.bp modül tanımını gözden geçirmelisiniz. Bu bölümde farklı türdeki modül tanımları, VNDK ile ilgili çeşitli modül özellikleri ve yapı sisteminde uygulanan bağımlılık denetimleri açıklanmaktadır.

Satıcı modülleri

Satıcı modülleri, satıcı bölümüne yüklenmesi gereken satıcıya özel yürütülebilir dosyalar veya paylaşılan kitaplıklardır. Android.bp dosyalarında satıcı modülleri, satıcı veya özel mülk özelliğini true olarak ayarlamalıdır. Android.mk dosyalarında satıcı modülleri LOCAL_VENDOR_MODULE veya LOCAL_PROPRIETARY_MODULE değerini true olarak ayarlamalıdır.

BOARD_VNDK_VERSION tanımlanırsa yapı sistemi, satıcı modülleri ile çerçeve modülleri arasındaki bağımlılıklara izin vermez ve aşağıdaki durumlarda hatalar verir:

  • vendor:true doğru olmayan bir modül, vendor:true içeren bir modüle bağlıdır veya
  • vendor:true olan bir modül, ne vendor:true ne de vendor_available:true içermeyen llndk_library olmayan bir modüle bağlıdır.

Bağımlılık kontrolü, Android.bp header_libs , static_libs ve shared_libs için ve Android.mk LOCAL_HEADER_LIBRARIES , LOCAL_STATIC_LIBRARIES ve LOCAL_SHARED_LIBRARIES için geçerlidir.

LL-NDK

LL-NDK paylaşılan kitaplıkları, kararlı ABI'lere sahip paylaşılan kitaplıklardır. Hem çerçeve hem de satıcı modülleri aynı ve en son uygulamayı paylaşır. Her LL-NDK paylaşılan kitaplığı için cc_library , bir sembol dosyasına sahip bir llndk özelliği içerir:

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

Sembol dosyası, satıcı modülleri tarafından görülebilen sembolleri açıklar. Örneğin:

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

Sembol dosyasına dayalı olarak yapı sistemi, satıcı modülleri için BOARD_VNDK_VERSION etkinleştirildiğinde bu kitaplıklara bağlanan bir saplama paylaşımlı kitaplık oluşturur. Bir sembol yalnızca aşağıdaki durumlarda saplama paylaşımlı kitaplığına eklenir:

  • Bölüm sonunda _PRIVATE veya _PLATFORM ile tanımlanmamış,
  • #platform-only etiketi yoktur ve
  • #introduce* etiketi yok veya etiket hedefle eşleşiyor.

VNDK

Android.bp dosyalarında cc_library , cc_library_static , cc_library_shared ve cc_library_headers modül tanımları VNDK ile ilgili üç özelliği destekler: vendor_available , vndk.enabled ve vndk.support_system_process .

vendor_available veya vndk.enabled true ise, iki değişken ( çekirdek ve satıcı ) oluşturulabilir. Çekirdek değişken bir çerçeve modülü olarak ele alınmalı ve satıcı değişkeni bir satıcı modülü olarak ele alınmalıdır. Bazı çerçeve modülleri bu modüle bağlıysa çekirdek değişken oluşturulur. Bazı satıcı modülleri bu modüle bağlıysa satıcı değişkeni oluşturulur. Derleme sistemi aşağıdaki bağımlılık kontrollerini uygular:

  • Çekirdek değişken her zaman yalnızca çerçevedir ve satıcı modülleri tarafından erişilemez.
  • Satıcı değişkenine çerçeve modülleri tarafından her zaman erişilemez.
  • header_libs , static_libs ve/veya shared_libs belirtilen satıcı değişkeninin tüm bağımlılıkları ya bir llndk_library ya da vendor_available ya da vndk.enabled içeren bir modül olmalıdır.
  • vendor_available true ise satıcı değişkenine tüm satıcı modülleri tarafından erişilebilir.
  • vendor_available false ise satıcı değişkenine yalnızca diğer VNDK veya VNDK-SP modülleri tarafından erişilebilir (yani, vendor:true olan modüller vendor_available:false modüllerine bağlanamaz).

cc_library veya cc_library_shared için varsayılan kurulum yolu aşağıdaki kurallara göre belirlenir:

  • Çekirdek değişken /system/lib[64] dizinine yüklenir.
  • Satıcı değişkeninin kurulum yolu değişiklik gösterebilir:
    • vndk.enabled false ise satıcı değişkeni /vendor/lib[64] içine yüklenir.
    • vndk.enabled true ise satıcı değişkeni VNDK APEX'e ( com.android.vndk.v${VER} ) yüklenir.

Aşağıdaki tablo, derleme sisteminin satıcı değişkenlerini nasıl ele aldığını özetlemektedir:

satıcı_available vndk
etkinleştirilmiş
vndk
destek_same_process
Satıcı çeşidi açıklamaları
true false false Satıcı çeşitleri YALNIZCA VND'dir . Paylaşılan kitaplıklar /vendor/lib[64] içine yüklenir.
true Geçersiz (Derleme hatası)
true false Satıcı çeşitleri VNDK'dır . Paylaşılan kitaplıklar VNDK APEX'e yüklenir.
true Satıcı çeşitleri VNDK-SP'dir . Paylaşılan kitaplıklar VNDK APEX'e yüklenir.

false

false

false

Satıcı çeşidi yok. Bu modül YALNIZCA FWK'dır .

true Geçersiz (Derleme hatası)
true false Satıcı çeşitleri VNDK-Private'dir . Paylaşılan kitaplıklar VNDK APEX'e yüklenir. Bunlar doğrudan satıcı modülleri tarafından kullanılmamalıdır.
true Satıcı çeşitleri VNDK-SP-Private'dir . Paylaşılan kitaplıklar VNDK APEX'e yüklenir. Bunlar doğrudan satıcı modülleri tarafından kullanılmamalıdır.

VNDK uzantıları

VNDK uzantıları, ek API'lere sahip VNDK paylaşılan kitaplıklarıdır. Uzantılar /vendor/lib[64]/vndk[-sp] dizinine yüklenir (sürüm eki olmadan) ve çalışma zamanında orijinal VNDK paylaşılan kitaplıklarını geçersiz kılar.

VNDK uzantılarını tanımlama

Android 9 ve üzeri sürümlerde, Android.bp yerel olarak VNDK uzantılarını destekler. Bir VNDK uzantısı oluşturmak için, vendor:true ve extends özelliğine sahip başka bir modül tanımlayın:

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

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

vendor:true , vndk.enabled:true ve extends özelliklerine sahip bir modül, VNDK uzantısını tanımlar:

  • extends özelliğinin temel bir VNDK paylaşılan kitaplık adı (veya VNDK-SP paylaşılan kitaplık adı) belirtmesi gerekir.
  • VNDK uzantıları (veya VNDK-SP uzantıları), genişletildikleri temel modül adlarına göre adlandırılır. Örneğin, libvndk_ext çıktı ikili dosyası libvndk_ext.so yerine libvndk.so .
  • VNDK uzantıları /vendor/lib[64]/vndk dosyasına yüklenir.
  • VNDK-SP uzantıları /vendor/lib[64]/vndk-sp dosyasına yüklenir.
  • Temel paylaşılan kitaplıklarda hem vndk.enabled:true hem de vendor_available:true bulunmalıdır.

Bir VNDK-SP uzantısı, bir VNDK-SP paylaşılan kitaplığından genişletilmelidir ( vndk.support_system_process eşit olmalıdır):

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,
    },
}

VNDK uzantıları (veya VNDK-SP uzantıları), satıcının paylaştığı diğer kitaplıklara bağlı olabilir:

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,
}

VNDK uzantılarını kullanma

Bir satıcı modülü, VNDK uzantıları tarafından tanımlanan ek API'lere bağlıysa modülün, shared_libs özelliğinde VNDK uzantısının adını belirtmesi gerekir:

// 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",
    ],
}

Bir satıcı modülü VNDK uzantılarına bağlıysa, bu VNDK uzantıları otomatik olarak /vendor/lib[64]/vndk[-sp] dizinine yüklenir. Bir modül artık bir VNDK uzantısına bağlı değilse, paylaşılan kitaplığı kaldırmak için CleanSpec.mk temiz bir adım ekleyin. Örneğin:

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

Koşullu derleme

Bu bölüm, aşağıdaki üç VNDK paylaşılan kitaplığı arasındaki ince farklarla (örneğin, varyantlardan birine özellik eklemek veya bir özelliği kaldırmak) nasıl başa çıkılacağını açıklamaktadır:

  • Çekirdek değişkeni (örneğin /system/lib[64]/libexample.so )
  • Satıcı çeşidi (örneğin /apex/com.android.vndk.v${VER}/lib[64]/libexample.so )
  • VNDK uzantısı (örneğin /vendor/lib[64]/vndk[-sp]/libexample.so )

Koşullu derleyici bayrakları

Android derleme sistemi, satıcı değişkenleri ve VNDK uzantıları için varsayılan olarak __ANDROID_VNDK__ öğesini tanımlar. Kodu C ön işlemci korumalarıyla koruyabilirsiniz:

void all() { }

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

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

__ANDROID_VNDK__ ye ek olarak Android.bp farklı cflags veya cppflags belirtilebilir. target.vendor belirtilen cflags veya cppflags satıcı değişkenine özeldir.

Örneğin, aşağıdaki Android.bp libexample ve libexample_ext tanımlar:

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",
    ],
}

Bu da src/example.c dosyasının kod listesidir:

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

Bu iki dosyaya göre derleme sistemi, aşağıdaki dışa aktarılan sembollerle paylaşılan kitaplıklar oluşturur:

Kurulum yolu Dışa aktarılan semboller
/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

Dışa aktarılan sembollerle ilgili gereksinimler

VNDK ABI denetleyicisi, VNDK sağlayıcı değişkenlerinin ve VNDK uzantılarının ABI'sini prebuilts/abi-dumps/vndk altındaki referans ABI dökümleriyle karşılaştırır.

  • VNDK sağlayıcı değişkenleri (örn. /apex/com.android.vndk.v${VER}/lib[64]/libexample.so ) tarafından dışa aktarılan semboller, ABI dökümlerinde tanımlanan sembollerle aynı (üst kümeleri değil) olmalıdır.
  • VNDK uzantıları tarafından dışa aktarılan semboller (örn. /vendor/lib[64]/vndk/libexample.so ), ABI dökümlerinde tanımlanan sembollerin üst kümeleri olmalıdır.

VNDK satıcı değişkenleri veya VNDK uzantıları yukarıdaki gereksinimleri karşılayamazsa, VNDK ABI denetleyicisi derleme hataları verir ve derlemeyi durdurur.

Kaynak dosyaları veya paylaşılan kitaplıkları satıcı varyantlarından hariç tutma

Kaynak dosyalarını satıcı değişkeninin dışında bırakmak için bunları exclude_srcs özelliğine ekleyin. Benzer şekilde, paylaşılan kitaplıkların satıcı değişkenine bağlı olmadığından emin olmak için bu kitaplıkları exclude_shared_libs özelliğine ekleyin. Örneğin:

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"],
        },
    },
}

Bu örnekte, libexample_cond_exclude çekirdek değişkeni fwk.c ve both.c kodlarını içerir ve paylaşılan libfwk_only ve libboth kitaplıklarına bağlıdır. libexample_cond_exclude sağlayıcısının değişkeni, yalnızca both.c kodu içerir çünkü fwk.c exclude_srcs özelliği tarafından hariç tutulur. Benzer şekilde, libfwk_only exclude_shared_libs özelliği tarafından hariç tutulduğundan, yalnızca paylaşılan kitaplık libboth bağlıdır.

VNDK uzantılarından başlıkları dışa aktarın

Bir VNDK uzantısı, VNDK paylaşılan kitaplığına yeni sınıflar veya yeni işlevler ekleyebilir. Bu bildirimlerin bağımsız başlıklarda tutulması ve mevcut başlıkların değiştirilmesinden kaçınılması önerilir.

Örneğin, VNDK uzantısı libexample_ext için yeni bir başlık dosyası include-ext/example/ext/feature_name.h oluşturulur:

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

Aşağıdaki Android.bp , libexample dışa aktarmaları yalnızca include , libexample_ext dışa aktarmaları hem include hem de include-ext içerir. Bu, feature_name.h libexample kullanıcıları tarafından hatalı bir şekilde dahil edilmemesini sağlar:

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",
    },
}

Uzantıları bağımsız başlık dosyalarına ayırmak mümkün değilse #ifdef korumaları eklemek bir alternatiftir. Ancak tüm VNDK uzantısı kullanıcılarının tanımlama işaretlerini eklediklerinden emin olun. cflags tanımlama bayrakları eklemek ve paylaşılan kitaplıkları shared_libs ile bağlamak için cc_defaults tanımını yapabilirsiniz.

Örneğin, VNDK uzantısı libexample2_ext yeni bir üye işlevi Example2::get_b() eklemek için mevcut başlık dosyasını değiştirmeniz ve bir #ifdef koruması eklemeniz gerekir:

#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_

libexample2_ext_defaults adlı bir cc_defaults libexample2_ext kullanıcıları için tanımlanır:

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",
    ],
}

libexample2_ext kullanıcıları, defaults özelliklerine libexample2_ext_defaults kolayca dahil edebilir:

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

Ürün paketleri

Android derleme sisteminde PRODUCT_PACKAGES değişkeni, cihaza yüklenmesi gereken yürütülebilir dosyaları, paylaşılan kitaplıkları veya paketleri belirtir. Belirtilen modüllerin geçişli bağımlılıkları da örtülü olarak cihaza yüklenir.

BOARD_VNDK_VERSION etkinleştirilirse, vendor_available veya vndk.enabled içeren modüller özel muamele görür. Bir çerçeve modülü, vendor_available veya vndk.enabled özelliğine sahip bir modüle bağlıysa, çekirdek değişken, geçişli kurulum kümesine dahil edilir. Satıcı modülü vendor_available sahip bir modüle bağlıysa satıcı değişkeni geçişli kurulum setine dahil edilir. Ancak vndk.enabled içeren modüllerin satıcı çeşitleri, satıcı modüller tarafından kullanılsın veya kullanılmasın yüklenir.

Bağımlılıklar yapı sistemi tarafından görülemediğinde (örneğin, çalışma zamanında dlopen() ile açılabilen paylaşılan kütüphaneler), bu modülleri açıkça kurmak için PRODUCT_PACKAGES içinde modül adlarını belirtmelisiniz.

Bir modülde vendor_available veya vndk.enabled varsa, modül adı onun temel değişkenini belirtir. PRODUCT_PACKAGES öğesinde satıcı çeşidini açıkça belirtmek için modül adına bir .vendor son eki ekleyin. Örneğin:

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

Bu örnekte, libexample , /system/lib[64]/libexample.so anlamına gelir ve libexample.vendor /vendor/lib[64]/libexample.so anlamına gelir. /vendor/lib[64]/libexample.so yüklemek için libexample.vendor PRODUCT_PACKAGES ekleyin:

PRODUCT_PACKAGES += libexample.vendor