Google is committed to advancing racial equity for Black communities. See how.
Эта страница переведена с помощью Cloud Translation API.
Switch to English

Поддержка системы сборки VNDK

В Android 8.1 и выше в систему сборки встроена поддержка VNDK. Когда поддержка VNDK включена, система сборки проверяет зависимости между модулями, строит вариант, зависящий от поставщика, для модулей поставщика и автоматически устанавливает эти модули в указанные каталоги.

Пример поддержки сборки VNDK

В этом примере определение модуля Android.bp определяет библиотеку с именем libexample . Свойство vendor_available указывает, что модули фреймворка и модули поставщика могут зависеть от libexample :

libexample vendor_available: true и vndk.enabled: true

Рисунок 1. Включена поддержка VNDK.

И исполняемый файл фреймворка /system/bin/foo и исполняемый файл поставщика /vendor/bin/bar зависят от libexample и имеют libexample в своих свойствах shared_libs .

Если libexample используется как модулями фреймворка, так и модулями поставщика, libexample два варианта libexample . Основной вариант (названный в честь libexample ) используется модулями фреймворка, а вариант поставщика (названный в честь libexample.vendor ) - модулями поставщика. Два варианта устанавливаются в разные каталоги:

  • Основной вариант устанавливается в /system/lib[64]/libexample.so .
  • Вариант поставщика устанавливается в VNDK APEX, потому что vndk.enabled true .

Подробнее см. Определение модуля .

Настройка поддержки сборки

Чтобы включить полную поддержку системы сборки для устройства продукта, добавьте BOARD_VNDK_VERSION в BoardConfig.mk :

BOARD_VNDK_VERSION := current

Этот параметр имеет глобальный эффект: если он определен в BoardConfig.mk , BoardConfig.mk все модули. Поскольку нет механизма для внесения в черный или белый список проблемного модуля, вам следует очистить все ненужные зависимости перед добавлением BOARD_VNDK_VERSION . Вы можете протестировать и скомпилировать модуль, установив BOARD_VNDK_VERSION в переменных среды:

$ BOARD_VNDK_VERSION=current m module_name.vendor

Когда BOARD_VNDK_VERSION включен, несколько путей поиска глобального заголовка по умолчанию удаляются . Они включают:

  • 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

Если модуль зависит от заголовков из этих каталогов, вы должны указать (явно) зависимости с header_libs , static_libs и / или shared_libs .

VNDK APEX

В Android 10 и ниже модули с vndk.enabled устанавливались в /system/lib[64]/vndk[-sp]-${VER} . В Android 11 и более поздних версиях библиотеки VNDK упакованы в формате APEX, а имя VNDK APEX - com.android.vndk.v${VER} . В зависимости от конфигурации устройства, VNDK APEX сплющена или неуплощающаяся и доступен из канонического пути /apex/com.android.vndk.v${VER} .

VNDK APEX

Рисунок 2. VNDK APEX

Определение модуля

Чтобы собрать Android с BOARD_VNDK_VERSION , вы должны BOARD_VNDK_VERSION определение модуля в Android.mk или Android.bp . В этом разделе описаны различные виды определений модулей, несколько свойств модуля, связанных с VNDK, и проверки зависимостей, реализованные в системе сборки.

Модули поставщика

Модули поставщика - это исполняемые файлы конкретного поставщика или разделяемые библиотеки, которые необходимо установить в раздел поставщика. В файлах Android.bp модули поставщика должны установить свойство vendor или proprietary в значение true . В файлах Android.mk модули поставщика должны установить для LOCAL_VENDOR_MODULE или LOCAL_PROPRIETARY_MODULE значение true .

Если BOARD_VNDK_VERSION определен, система сборки запрещает зависимости между модулями поставщика и модулями платформы и выдает ошибки, если:

  • модуль без vendor:true зависит от модуля с vendor:true , или
  • модуль с vendor:true зависит от модуля, llndk_library , у которого нет vendor:true и vendor_available:true .

Проверка зависимости применяется к header_libs , static_libs и shared_libs в Android.bp , а также к LOCAL_HEADER_LIBRARIES , LOCAL_STATIC_LIBRARIES и LOCAL_SHARED_LIBRARIES в Android.mk .

LL-NDK

Разделяемые библиотеки LL-NDK - это разделяемые библиотеки со стабильными ABI. И фреймворк, и модули поставщика используют одну и ту же самую последнюю реализацию. Для каждой разделяемой библиотеки LL-NDK llndk_library Android.bp содержит определение модуля llndk_library :

llndk_library {
    name: "libvndksupport",
    symbol_file: "libvndksupport.map.txt",
}

Это определение модуля задает имя модуля и файл символов, который описывает символы, видимые модулям поставщика. Например:

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

На основе файла символов система сборки генерирует общую библиотеку-заглушку для модулей поставщика, которые связываются с этими библиотеками при BOARD_VNDK_VERSION . Символ включается в общую библиотеку-заглушку только в том случае, если он:

  • Не определяется в конце раздела с помощью _PRIVATE или _PLATFORM ,
  • Не имеет тега #platform-only и
  • Не имеет тегов #introduce* или тег совпадает с целью.

ВНДК

В файлах Android.bp cc_library , cc_library_static , cc_library_shared и cc_library_headers поддерживают три свойства, связанные с vendor_available : vendor_available , vndk.enabled и vndk.support_system_process .

Если vendor_available или vndk.enabled true , могут быть построены два варианта ( основной и поставщик ). Основной вариант следует рассматривать как модуль инфраструктуры, а вариант поставщика - как модуль поставщика. Если некоторые модули фреймворка зависят от этого модуля, создается базовый вариант. Если некоторые модули поставщика зависят от этого модуля, создается вариант поставщика. Система сборки принудительно выполняет следующие проверки зависимостей:

  • Основной вариант всегда доступен только для платформы и недоступен для модулей поставщика.
  • Вариант вендора всегда недоступен для модулей фреймворка.
  • Все зависимости варианта поставщика, которые указаны в header_libs , static_libs и / или shared_libs , должны быть либо llndk_library либо модулем с vendor_available или vndk.enabled .
  • Если vendor_available true , вариант поставщика доступен для всех модулей поставщика.
  • Если vendor_available имеет значение false , вариант поставщика доступен только для других модулей VNDK или VNDK-SP (т. Е. Модули с vendor:true не могут связывать vendor_available:false ).

Путь установки по умолчанию для cc_library или cc_library_shared определяется следующими правилами:

  • Основной вариант устанавливается в /system/lib[64] .
  • Путь установки варианта поставщика может отличаться:
    • Если vndk.enabled имеет значение false , вариант поставщика устанавливается в /vendor/lib[64] .
    • Если vndk.enabled имеет значение true , вариант поставщика устанавливается в VNDK APEX ( com.android.vndk.v${VER} ).

В таблице ниже показано, как система сборки обрабатывает варианты поставщиков:

vendor_available vndk
включен
vndk
support_same_process
Описание вариантов поставщика
true false false Варианты поставщиков ТОЛЬКО для донгов . Общие библиотеки устанавливаются в /vendor/lib[64] .
true Недействительно (ошибка сборки)
true false Варианты поставщика: VNDK . Общие библиотеки устанавливаются в VNDK APEX.
true Варианты от производителя: ВНДК-СП . Общие библиотеки устанавливаются в VNDK APEX.

false

false

false

Вариантов поставщика нет. Этот модуль предназначен ТОЛЬКО для FWK .

true Недействительно (ошибка сборки)
true false Варианты поставщика - VNDK-Private . Общие библиотеки устанавливаются в VNDK APEX. Они не должны напрямую использоваться модулями поставщика.
true Варианты поставщика: VNDK-SP-Private . Общие библиотеки устанавливаются в VNDK APEX. Они не должны напрямую использоваться модулями поставщика.

Расширения VNDK

Расширения VNDK - это общие библиотеки VNDK с дополнительными API. Расширения устанавливаются в /vendor/lib[64]/vndk[-sp] (без суффикса версии) и заменяют исходные разделяемые библиотеки VNDK во время выполнения.

Определение расширений VNDK

В Android 9 и выше Android.bp изначально поддерживает расширения VNDK. Чтобы создать расширение VNDK, определите другой модуль с vendor:true и свойством extends :

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 и extends определяет расширение VNDK:

  • Свойство extends должно указывать базовое имя разделяемой библиотеки VNDK (или имя разделяемой библиотеки VNDK-SP).
  • Расширения VNDK (или расширения VNDK-SP) названы по именам базовых модулей, от которых они происходят. Например, выходной двоичный файл libvndk_ext - это libvndk.so вместо libvndk_ext.so .
  • Расширения VNDK устанавливаются в /vendor/lib[64]/vndk .
  • Расширения VNDK-SP устанавливаются в /vendor/lib[64]/vndk-sp .
  • Базовые разделяемые библиотеки должны иметь как vndk.enabled:true и vendor_available:true .

Расширение VNDK-SP должно происходить из разделяемой библиотеки VNDK-SP ( vndk.support_system_process должен быть равен):

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 (или расширения VNDK-SP) могут зависеть от разделяемых библиотек других поставщиков:

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

Если модуль поставщика зависит от дополнительных API, определенных расширениями VNDK, модуль должен указать имя расширения shared_libs свойстве shared_libs :

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

Если модуль поставщика зависит от расширений VNDK, эти расширения VNDK устанавливаются в /vendor/lib[64]/vndk[-sp] автоматически. Если модуль больше не зависит от расширения VNDK, добавьте чистый шаг в CleanSpec.mk чтобы удалить общую библиотеку. Например:

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

Условная компиляция

В этом разделе описывается, как справиться с небольшими различиями (например, добавлением или удалением функции из одного из вариантов) между следующими тремя разделяемыми библиотеками VNDK:

  • Основной вариант (например, / /system/lib[64]/libexample.so ] /system/lib[64]/libexample.so )
  • Вариант поставщика (например, /apex/com.android.vndk.v${VER}/lib[64]/libexample.so )
  • Расширение VNDK (например, / /vendor/lib[64]/vndk[-sp]/libexample.so )

Условные флаги компилятора

Система сборки Android по умолчанию определяет __ANDROID_VNDK__ для вариантов поставщика и расширений VNDK. Вы можете защитить код с помощью средств препроцессора C:

void all() { }

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

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

Помимо __ANDROID_VNDK__ , в Android.bp могут быть указаны другие cflags или cppflags . cflags или cppflags указанные в target.vendor , специфичны для варианта поставщика.

Например, следующий Android.bp определяет libexample и 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",
    ],
}

А это листинг кода 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

В соответствии с этими двумя файлами система сборки генерирует общие библиотеки со следующими экспортируемыми символами:

Путь установки Экспортированные символы
/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

Требования к экспортируемым символам

Средство проверки VNDK ABI сравнивает ABI вариантов поставщика VNDK и расширений VNDK с эталонными prebuilts/abi-dumps/vndk ABI в prebuilts/abi-dumps/vndk .

  • Символы, экспортируемые вариантами поставщика VNDK (например, /apex/com.android.vndk.v${VER}/lib[64]/libexample.so ) должны быть идентичны (а не надмножествам) символов, определенных в дампах ABI.
  • Символы, экспортируемые расширениями VNDK (например, /vendor/lib[64]/vndk/libexample.so ), должны быть надмножествами символов, определенных в /vendor/lib[64]/vndk/libexample.so ABI.

Если варианты поставщика VNDK или расширения VNDK не соответствуют приведенным выше требованиям, средство проверки VNDK ABI выдает ошибки сборки и останавливает сборку.

Исключение исходных файлов или общих библиотек из вариантов поставщика

Чтобы исключить исходные файлы из варианта поставщика, добавьте их в свойство exclude_srcs . Точно так же, чтобы гарантировать, что общие библиотеки не связаны с вариантом поставщика, добавьте эти библиотеки в свойство exclude_shared_libs . Например:

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

В этом примере основной вариант libexample_cond_exclude включает код из fwk.c и both.c и зависит от разделяемых библиотек libfwk_only и libboth . Вариант libexample_cond_exclude от libexample_cond_exclude включает только код из both.c потому что fwk.c исключен свойством exclude_srcs . Точно так же это зависит только от разделяемой библиотеки libboth потому что libfwk_only исключается свойством exclude_shared_libs .

Экспорт заголовков из расширений VNDK

Расширение VNDK может добавлять новые классы или новые функции в общую библиотеку VNDK. Предлагается хранить эти объявления в независимых заголовках и избегать изменения существующих заголовков.

Например, новый файл заголовка include-ext/example/ext/feature_name.h создается для расширения libexample_ext :

  • Android.bp
  • include-ext / example / ext / имя_функции.h
  • включить / example / example.h
  • src / example.c
  • SRC / ext / имя_функции.c

В следующем libexample Android.bp libexample экспортирует только include , тогда как libexample_ext экспортирует и include и include-ext . Это гарантирует, что feature_name.h не будет неправильно включен пользователями 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",
    },
}

Если разделение расширений на независимые файлы заголовков невозможно, можно добавить защиту #ifdef . Однако убедитесь, что все пользователи расширения VNDK добавили флаги определения. Вы можете определить cc_defaults чтобы добавить флаги определения к cflags и связать разделяемые библиотеки с shared_libs .

Например, чтобы добавить новую функцию - член Example2::get_b() для расширения VNDK libexample2_ext , необходимо изменить существующий файл заголовка и добавить #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 именем libexample2_ext_defaults определен для пользователей 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",
    ],
}

Пользователи libexample2_ext могут просто включить libexample2_ext_defaults в свое свойство defaults :

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

Пакеты продуктов

В системе сборки Android переменная PRODUCT_PACKAGES указывает исполняемые файлы, общие библиотеки или пакеты, которые должны быть установлены на устройство. Транзитивные зависимости указанных модулей также неявно устанавливаются в устройство.

Если BOARD_VNDK_VERSION включен, модули с vendor_available или vndk.enabled особым образом. Если модуль инфраструктуры зависит от модуля с vendor_available или vndk.enabled , основной вариант включается в переходный установочный набор. Если модуль поставщика зависит от модуля с vendor_available , вариант поставщика включается в переходный установочный набор. Однако варианты модулей поставщика с vndk.enabled устанавливаются независимо от того, используются они модулями поставщика или нет.

Когда зависимости невидимы для системы сборки (например, разделяемые библиотеки, которые можно открыть с помощью dlopen() во время выполнения), вы должны указать имена модулей в PRODUCT_PACKAGES чтобы установить эти модули явно.

Если у модуля есть vendor_available или vndk.enabled , имя модуля соответствует его vendor_available варианту. Чтобы явно указать вариант поставщика в PRODUCT_PACKAGES , добавьте суффикс .vendor к имени модуля. Например:

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

В этом примере libexample означает / /system/lib[64]/libexample.so libexample.vendor /system/lib[64]/libexample.so а libexample.vendor означает / /vendor/lib[64]/libexample.so . Чтобы установить /vendor/lib[64]/libexample.so , добавьте libexample.vendor в PRODUCT_PACKAGES :

PRODUCT_PACKAGES += libexample.vendor