| <html devsite><head> |
| <title>VNDK 编译系统支持</title> |
| <meta name="project_path" value="/_project.yaml"/> |
| <meta name="book_path" value="/_book.yaml"/> |
| </head> |
| <body> |
| <!-- |
| Copyright 2017 The Android Open Source Project |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <p> |
| 在 Android 8.1 及更高版本中,编译系统具有内置的 VNDK 支持。如果启用了 VNDK 支持,编译系统就会检查各模块之间的依赖关系,为供应商模块编译特定于供应商的变体,并自动将这些模块安装到指定目录中。 |
| </p> |
| |
| <h2 id="vndk-build-support-example">VNDK 编译支持示例</h2> |
| |
| <p> |
| 在此示例中,<code>Android.bp</code> 模块定义定义了一个名为 <code>libexample</code> 的库。<code>vendor_available</code> 属性表示框架模块和供应商模块均可能依赖于 <code>libexample</code>。 |
| </p> |
| |
| <p> |
| <img src="../images/treble_vndk_androidbp.png" alt="具有 vendor_available:true 和 vndk.enabled:true 的 libexample"/> |
| </p> |
| <figcaption> |
| <strong>图 1.</strong> 已启用 VNDK 支持 |
| </figcaption> |
| |
| <p> |
| 框架可执行文件 <code>/system/bin/foo</code> 和供应商可执行文件 <code>/vendor/bin/bar</code> 均依赖于 <code>libexample</code>,并且在其 <code>shared_libs</code> 属性中具有 <code>libexample</code>。 |
| </p> |
| |
| <p> |
| 如果框架模块和供应商模块均使用 <code>libexample</code>,则编译 <code>libexample</code> 的两个变体。核心变体(以 <code>libexample</code> 命名)由框架模块使用,供应商变体(以 <code>libexample.vendor</code> 命名)由供应商模块使用。这两个变体将安装到不同的目录中。 |
| </p> |
| |
| <ul> |
| <li>核心变体将安装到 <code>/system/lib[64]/libexample.so</code> 中。</li> |
| <li>供应商变体将安装到 <code>/system/lib[64]/vndk/libexample.so</code> 中,因为 <code>vndk.enabled</code> 为 <code>true</code>。</li> |
| </ul> |
| |
| <p> |
| 如需了解详情,请参阅<a href="#module-definition">模块定义</a>。 |
| </p> |
| |
| <h2 id="configuring-build-support">配置编译支持</h2> |
| |
| <p> |
| 要为产品设备启用完整编译系统支持,请将 <code>BOARD_VNDK_VERSION</code> 添加到 <code>BoardConfig.mk</code>: |
| </p> |
| |
| <pre class="prettyprint">BOARD_VNDK_VERSION := current</pre> |
| |
| <p> |
| 此设置会产生<strong>全局</strong>效应:如果在 <code>BoardConfig.mk</code> 中定义,系统会检查所有模块。由于没有将违规模块列入黑名单或白名单的机制,因此在添加 <code>BOARD_VNDK_VERSION</code> 之前应清除所有不必要的依赖项。您可以通过在环境变量中设置 <code>BOARD_VNDK_VERSION</code> 来测试和编译模块: |
| </p> |
| |
| <pre class="prettyprint">$ BOARD_VNDK_VERSION=current m module_name.vendor</pre> |
| |
| <p>如果启用 <code>BOARD_VNDK_VERSION</code>,系统会移除多个默认的全局标头搜索路径。<em></em>其中包括: |
| </p> |
| |
| <ul> |
| <li><code>frameworks/av/include</code></li> |
| <li><code>frameworks/native/include</code></li> |
| <li><code>frameworks/native/opengl/include</code></li> |
| <li><code>hardware/libhardware/include</code></li> |
| <li><code>hardware/libhardware_legacy/include</code></li> |
| <li><code>hardware/ril/include</code></li> |
| <li><code>libnativehelper/include</code></li> |
| <li><code>libnativehelper/include_deprecated</code></li> |
| <li><code>system/core/include</code></li> |
| <li><code>system/media/audio/include</code></li> |
| </ul> |
| |
| <p> |
| 如果某个模块依赖于上述目录中的标头,则您必须明确指定与 <code>header_libs</code>、<code>static_libs</code> 和/或 <code>shared_libs</code> 的依赖关系。 |
| </p> |
| |
| <h2 id="module-definition">模块定义</h2> |
| |
| <p> |
| 要使用 <code>BOARD_VNDK_VERSION</code> 编译 Android,您必须在 <code>Android.mk</code> 或 <code>Android.bp</code> 中修改模块定义。此部分介绍了不同种类的模块定义,一些与 VNDK 相关的模块属性,以及在编译系统中实现的依赖性检查。 |
| </p> |
| |
| <h3 id="vendor-modules">供应商模块</h3> |
| |
| <p> |
| 供应商模块是特定于供应商的可执行文件或共享库(必须将这些模块安装到供应商分区中)。在 <code>Android.bp</code> 文件中,供应商模块必须将供应商或专有属性设置为 <code>true</code>。在 <code>Android.mk</code> 文件中,供应商模块必须将 <code>LOCAL_VENDOR_MODULE</code> 或 <code>LOCAL_PROPRIETARY_MODULE</code> 设置为 <code>true</code>。 |
| </p> |
| |
| <p> |
| 如果定义了 <code>BOARD_VNDK_VERSION</code>,则编译系统不允许在供应商模块和框架模块之间建立依赖关系,并且编译系统会在以下情况下发出错误: |
| </p> |
| |
| <ul> |
| <li>不具有 <code>vendor:true</code> 的模块依赖于具有 <code>vendor:true</code> 的模块,或</li> |
| <li>具有 <code>vendor:true</code> 的模块依赖于既不具有 <code>vendor:true</code> 也不具有 <code>vendor_available:true</code> 的非 <code>llndk_library</code> 模块。</li> |
| </ul> |
| |
| <p> |
| 依赖性检查适用于 <code>Android.bp</code> 中的 <code>header_libs</code>、<code>static_libs</code> 和 <code>shared_libs</code> 以及 <code>Android.mk</code> 中的 <code>LOCAL_HEADER_LIBRARIES</code>、<code>LOCAL_STATIC_LIBRARIES</code> 和 <code>LOCAL_SHARED_LIBRARIES</code>。 |
| </p> |
| |
| <h3 id="ll-ndk">LL-NDK</h3> |
| |
| <p> |
| LL-NDK 共享库是具有稳定 ABI 的共享库。框架模块和供应商模块均具有相同的最新实现。对于每个 LL-NDK 共享库,<code>Android.bp</code> 都包含一个 <code>llndk_library</code> 模块定义: |
| </p> |
| |
| <pre class="prettyprint"> |
| llndk_library { |
| name: "libvndksupport", |
| symbol_file: "libvndksupport.map.txt", |
| } |
| </pre> |
| |
| <p> |
| 该模块定义指定了模块名称和符号文件,后者描述了对供应商模块可见的符号。例如: |
| </p> |
| |
| <pre class="prettyprint"> |
| LIBVNDKSUPPORT { |
| global: |
| android_load_sphal_library; # vndk |
| android_unload_sphal_library; # vndk |
| local: |
| *; |
| }; |
| </pre> |
| |
| <p> |
| 编译系统会根据符号文件为供应商模块生成存根共享库。如果启用了 <code>BOARD_VNDK_VERSION</code>,供应商模块将与这些存根共享库建立关联。只有在满足以下条件时,存根共享库中才会包含符号: |
| </p> |
| |
| <ul> |
| <li>它未在以 <code>_PRIVATE</code> 或 <code>_PLATFORM</code> 结尾的部分中定义,</li> |
| <li>它不含 <code>#platform-only</code> 标记,并且</li> |
| <li>不含 <code>#introduce*</code> 标记或者该标记与目标匹配。</li> |
| </ul> |
| |
| <aside class="note"> |
| <strong>注意</strong>:供应商不得定义自己的 LL-NDK 共享库,因为供应商模块无法在<a href="/setup/build/gsi">通用系统映像 (GSI)</a> 中找到它们。 |
| </aside> |
| |
| <h3 id="vndk">VNDK</h3> |
| |
| <p> |
| 在 <code>Android.bp</code> 文件中,<code>cc_library</code>、<code>cc_library_static</code>、<code>cc_library_shared</code> 和 <code>cc_library_headers</code> 模块定义支持三个与 VNDK 相关的属性:<code>vendor_available</code>、<code>vndk.enabled</code> 和 <code>vndk.support_system_process</code>。 |
| </p> |
| |
| <p> |
| 如果 <code>vendor_available</code> 或 <code>vndk.enabled</code> 为 <code>true</code>,则可以编译两种变体(核心变体和供应商变体)。<em></em><em></em>核心变体应被视为框架模块,而供应商变体应被视为供应商模块。如果某些框架模块依赖于此模块,则会编译核心变体。如果某些供应商模块依赖于此模块,则会编译供应商变体。编译系统会强制执行以下依赖性检查: |
| </p> |
| |
| <ul> |
| <li>核心变体始终供框架专用,无法供供应商模块访问。</li> |
| <li>供应商变体始终无法供框架模块访问。</li> |
| <li>供应商变体的所有依赖项(在 <code>header_libs</code>、<code>static_libs</code> 和/或 <code>shared_libs</code> 中指定)必须是 <code>llndk_library</code> 或具有 <code>vendor_available</code> 或 <code>vndk.enabled</code> 的模块。</li> |
| <li>如果 <code>vendor_available</code> 为 <code>true</code>,则供应商变体可供所有供应商模块访问。</li> |
| <li>如果 <code>vendor_available</code> 为 <code>false</code>,则供应商变体仅可供其他 VNDK 或 VNDK-SP 模块访问(即,具有 <code>vendor:true</code> 的模块无法与 <code>vendor_available:false</code> 模块相关联)。</li> |
| </ul> |
| |
| <p> |
| 系统将通过以下规则确定 <code>cc_library</code> 或 <code>cc_library_shared</code> 的默认安装路径: |
| </p> |
| |
| <ul> |
| <li>将核心变体安装到 <code>/system/lib[64]</code> 中。</li> |
| <li>供应商变体安装路径可能会有所不同: |
| <ul> |
| <li>如果 <code>vndk.enabled</code> 为 <code>false</code>,则将供应商变体将安装到 <code>/vendor/lib[64]</code> 中。</li> |
| <li>如果 <code>vndk.enabled</code> 为 <code>true</code>,则 <code>vndk.support_system_process</code> 可以是 <code>true</code> 或 <code>false</code>。如果: |
| <ul> |
| <li>为 <code>false</code>,则供应商变体将安装到 <code>/system/lib[64]/vndk-${VER}</code> 中。</li> |
| <li>为 <code>true</code>,则供应商变体将安装到 <code>/system/lib[64]/vndk-sp-${VER}</code> 中。</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p> |
| 下表总结了编译系统如何处理供应商变体: |
| </p> |
| <table> |
| <tbody><tr> |
| <th>vendor_available</th> |
| <th style="text-align: center">vndk<br />已启用</th> |
| <th style="text-align: center">vndk<br />support_same_process</th> |
| <th>供应商变体说明</th> |
| </tr> |
| |
| <tr> |
| <td rowspan="4"><code>true</code></td> |
| <td rowspan="2"><code>false</code></td> |
| <td><code>false</code></td> |
| <td>供应商变体为 VND-ONLY。共享库将安装到 <code>/vendor/lib[64]</code> 中。<em></em></td> |
| </tr> |
| |
| <tr> |
| <td><code>true</code></td> |
| <td>无效(编译错误)<em></em></td> |
| </tr> |
| |
| <tr> |
| <td rowspan="2"><code>true</code></td> |
| <td><code>false</code></td> |
| <td>供应商变体为 VNDK。共享库将安装到 <code>/system/lib[64]/vndk-${VER}</code> 中。<em></em></td> |
| </tr> |
| |
| <tr> |
| <td><code>true</code></td> |
| <td>供应商变体为 VNDK-SP。共享库将安装到 <code>/system/lib[64]/vndk-sp-${VER}</code> 中。<em></em></td> |
| </tr> |
| |
| <tr> |
| <td rowspan="4"><p><code>false</code></p></td> |
| <td rowspan="2"><p><code>false</code></p></td> |
| <td><p><code>false</code></p></td> |
| <td><p>没有供应商变体。此模块为 FWK-ONLY。<em></em></p></td> |
| </tr> |
| |
| <tr> |
| <td><code>true</code></td> |
| <td>无效(编译错误)<em></em></td> |
| </tr> |
| |
| <tr> |
| <td rowspan="2"><code>true</code></td> |
| <td><code>false</code></td> |
| <td>供应商变体为 VNDK-Private。<em></em>共享库将安装到 <code>/system/lib[64]/vndk-${VER}</code> 中。供应商模块不得直接使用这些变体。</td> |
| </tr> |
| |
| <tr> |
| <td><code>true</code></td> |
| <td>供应商变体为 VNDK-SP-Private。<em></em>共享库将安装到 <code>/system/lib[64]/vndk-sp-${VER}</code> 中。供应商模块不得直接使用这些变体。</td> |
| </tr> |
| </tbody></table> |
| |
| <aside class="note"> |
| <strong>注意</strong>:供应商可以为其模块设置 <code>vendor_available</code>,但不得设置 <code>vndk.enabled</code> 和 <code>vndk.support_system_process</code>,因为供应商模块无法在<a href="/setup/build/gsi">通用系统映像 (GSI)</a> 中找到它们。 |
| </aside> |
| |
| <h3 id="vndk-extensions">VNDK 扩展</h3> |
| |
| <p> |
| VNDK 扩展是具有额外 API 的 VNDK 共享库,将安装到 <code>/vendor/lib[64]/vndk[-sp]</code> 中(不含版本后缀),并在系统运行时会替换原始的 VNDK 共享库。 |
| </p> |
| |
| <h4 id="defining-vndk-extensions">定义 VNDK 扩展</h4> |
| |
| <p> |
| 在 Android 9 及更高版本中,<code>Android.bp</code> 本身支持 VNDK 扩展。要编译 VNDK 扩展,请定义另一个具有 <code>vendor:true</code> 和 <code>extends</code> 属性的模块: |
| </p> |
| |
| <pre class="prettyprint"> |
| cc_library { |
| name: "libvndk", |
| vendor_available: true, |
| vndk: { |
| enabled: true, |
| }, |
| } |
| |
| cc_library { |
| name: "libvndk_ext", |
| vendor: true, |
| vndk: { |
| enabled: true, |
| extends: "libvndk", |
| }, |
| } |
| </pre> |
| |
| <p> |
| 具有 <code>vendor:true</code>、<code>vndk.enabled:true</code> 和 <code>extends</code> 属性的模块可定义 VNDK 扩展:</p> |
| |
| <ul> |
| <li><code>extends</code> 属性必须指定基础 VNDK 共享库名称(或 VNDK-SP 共享库名称)。</li> |
| <li>VNDK 扩展(或 VNDK-SP 扩展)以扩展时所基于的基础模块名称命名。例如,<code>libvndk_ext</code> 的输出二进制文件是 <code>libvndk.so</code>,而非 <code>libvndk_ext.so</code>。</li> |
| <li>VNDK 扩展将安装到 <code>/vendor/lib[64]/vndk</code> 中。</li> |
| <li>VNDK-SP 扩展将安装到 <code>/vendor/lib[64]/vndk-sp</code> 中。</li> |
| <li>基础共享库必须同时具有 <code>vndk.enabled:true</code> 和 <code>vendor_available:true</code>。</li> |
| </ul> |
| |
| <p> |
| VNDK-SP 扩展必须从 VNDK-SP 共享库进行扩展(<code>vndk.support_system_process</code> 必须相等): |
| </p> |
| |
| <pre class="prettyprint"> |
| 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, |
| }, |
| } |
| </pre> |
| |
| <p> |
| VNDK 扩展(或 VNDK-SP 扩展)可以依赖于其他供应商共享库: |
| </p> |
| |
| <pre class="prettyprint"> |
| 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, |
| } |
| </pre> |
| |
| <aside class="note"> |
| <strong>注意</strong>:与 SP-HAL-Dep 类似,VNDK-SP 扩展及其依赖项(包括供应商库)在 sepolicy 中必须标记为 <code>same_process_hal_file</code>。 |
| </aside> |
| |
| <h4 id="using-vndk-extensions">使用 VNDK 扩展</h4> |
| |
| <p> |
| 如果供应商模块依赖于由 VNDK 扩展定义的其他 API,则该模块必须在其 <code>shared_libs</code> 属性中指定 VNDK 扩展的名称: |
| </p> |
| |
| <pre class="prettyprint"> |
| // 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", |
| ], |
| } |
| </pre> |
| |
| <p> |
| 如果供应商模块依赖于 VNDK 扩展,则这些 VNDK 扩展将自动安装到 <code>/vendor/lib[64]/vndk[-sp]</code> 中。如果某个模块不再依赖于 VNDK 扩展,请向 <code>CleanSpec.mk</code> 添加一个清理步骤,以移除共享库。例如: |
| </p> |
| |
| <pre class="prettyprint"> |
| $(call add-clean-step, rm -rf $(TARGET_OUT_VENDOR)/lib/libvndk.so) |
| </pre> |
| |
| <h3 id="conditional-compilation">条件编译</h3> |
| |
| <p> |
| 本节介绍了如何处理以下三个 VNDK 共享库之间的细微差别(例如,为其中一个变体添加或移除某项功能):<em></em> |
| </p> |
| |
| <ul> |
| <li>核心变体(例如 <code>/system/lib[64]/libexample.so</code>)</li> |
| <li>供应商变体(例如 <code>/system/lib[64]/vndk[-sp]-${VER}/libexample.so</code>)</li> |
| <li>VNDK 扩展(例如 <code>/vendor/lib[64]/vndk[-sp]/libexample.so</code>) |
| </li> |
| </ul> |
| |
| <h4 id="conditional-cflags">条件编译器标记</h4> |
| |
| <p> |
| 默认情况下,Android 编译系统会为供应商变体(包括 VNDK 扩展)定义 <code>__ANDROID_VNDK__</code>。您可以使用 C 预处理器防护程序来保护相应代码: |
| </p> |
| |
| <pre class="prettyprint"> |
| void all() { } |
| |
| #if !defined(__ANDROID_VNDK__) |
| void framework_only() { } |
| #endif |
| |
| #if defined(__ANDROID_VNDK__) |
| void vndk_only() { } |
| #endif |
| </pre> |
| |
| <p> |
| 除了 <code>__ANDROID_VNDK__</code>,还可以在 <code>Android.bp</code> 中指定不同的 <code>cflags</code> 或 <code>cppflags</code>。在 <code>target.vendor</code> 中指定的 <code>cflags</code> 或 <code>cppflags</code> 是专门针对供应商变体的。例如,以下代码示例是针对 <code>libexample</code> 和 <code>libexample_ext</code> 的 <code>Android.bp</code> 模块定义: |
| </p> |
| |
| <pre class="prettyprint"> |
| cc_library { |
| name: "libexample", |
| srcs: ["example.c"], |
| vendor_available: true, |
| vndk: { |
| enabled: true, |
| }, |
| target: { |
| vendor: { |
| cflags: ["-DLIBEXAMPLE_ENABLE_VNDK=1"], |
| }, |
| }, |
| } |
| |
| cc_library { |
| name: "libexample_ext", |
| srcs: ["example.c"], |
| vendor: true, |
| vndk: { |
| enabled: true, |
| extends: "libexample", |
| }, |
| cflags: [ |
| "-DLIBEXAMPLE_ENABLE_VNDK=1", |
| "-DLIBEXAMPLE_ENABLE_VNDK_EXT=1", |
| ], |
| } |
| </pre> |
| |
| <p> |
| <code>example.c</code> 的代码清单: |
| </p> |
| |
| <pre class="prettyprint"> |
| 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 |
| </pre> |
| |
| <p> |
| 针对每个变体导出的符号: |
| </p> |
| |
| <table> |
| <tbody><tr> |
| <th>安装路径</th> |
| <th>导出的符号</th> |
| </tr> |
| |
| <tr> |
| <td><code>/system/lib[64]/libexample.so</code></td> |
| <td><code>all</code>、<code>framework_only</code></td> |
| </tr> |
| |
| <tr> |
| <td><code>/system/lib[64]/vndk-${VER}/libexample.so</code></td> |
| <td><code>all</code>、<code>vndk</code></td> |
| </tr> |
| |
| <tr> |
| <td><code>/vendor/lib[64]/vndk/libexample.so</code></td> |
| <td><code>all</code>、<code>vndk</code>、<code>vndk_ext</code></td> |
| </tr> |
| </tbody></table> |
| |
| <p> |
| VNDK ABI 合规性检查工具会将 VNDK 和 VNDK 扩展的 ABI 同 <code>prebuilts/abi-dumps/vndk</code> 下的 ABI 转储进行比较: |
| </p> |
| |
| <ul> |
| <li>通过原始 VNDK 共享库导出的符号必须与 ABI 转储中定义的符号相同(而不是后者的超集)。</li> |
| <li>通过 VNDK 扩展导出的符号必须是 ABI 转储中定义的符号的超集。</li> |
| </ul> |
| |
| <h4 id="excluding">排除源文件或共享库</h4> |
| |
| <p> |
| 要从供应商变体中排除源文件,请将相应文件添加到 <code>exclude_srcs</code> 属性中。同样,要确保共享库未与供应商变体相关联,请将这些库添加到 <code>exclude_shared_libs</code> 属性中。例如: |
| </p> |
| |
| <pre class="prettyprint"> |
| cc_library { |
| name: "libcond_exclude_example", |
| srcs: ["fwk.c", "both.c"], |
| shared_libs: ["libfwk_only", "libboth"], |
| target: { |
| vendor: { |
| exclude_srcs: ["fwk.c"], |
| exclude_shared_libs: ["libfwk_only"], |
| }, |
| }, |
| } |
| </pre> |
| |
| <p> |
| 在本示例中,<code>libcond_exclude_example</code> 的核心变体包含 <code>fwk.c</code> 和 <code>both.c</code> 中的代码,并且依赖于共享库 <code>libfwk_only</code> 和 <code>libboth</code>。<code>libcond_exclude_example</code> 的供应商变体仅包含 <code>both.c</code> 中的代码,因为 <code>fwk.c</code> 已被 <code>exclude_srcs</code> 属性排除。同样,<code>libcond_exclude_example</code> 仅依赖于共享库 <code>libboth</code>,因为 <code>libfwk_only</code> 已被 <code>exclude_shared_libs</code> 属性排除。 |
| </p> |
| |
| <h3 id="product-packages">产品包</h3> |
| |
| <p> |
| 在 Android 编译系统中,变量 <code>PRODUCT_PACKAGES</code> 指定应安装到设备中的可执行文件、共享库或软件包。指定模块的传递依赖项也会隐式安装到设备中。 |
| </p> |
| |
| <p> |
| 如果启用了 <code>BOARD_VNDK_VERSION</code>,具有 <code>vendor_available</code> 或 <code>vndk.enabled</code> 的模块会得到特殊处理。如果框架模块依赖于具有 <code>vendor_available</code> 或 <code>vndk.enabled</code> 的模块,则核心变体将纳入传递安装集中。同样,如果供应商模块依赖于具有 <code>vendor_available</code> 或 <code>vndk.enabled</code> 的模块,则供应商变体将纳入传递安装集中。 |
| </p> |
| |
| <p> |
| 当相关依赖项对编译系统不可见时(例如,可以在运行时使用 <code>dlopen()</code> 打开的共享库),您应该在 <code>PRODUCT_PACKAGES</code> 中指定模块名称来明确安装这些模块。 |
| </p> |
| |
| <p> |
| 如果某个模块具有 <code>vendor_available</code> 或 <code>vndk.enabled</code>,则模块名称代表该模块的核心变体。要在 <code>PRODUCT_PACKAGES</code> 中明确指定供应商变体,请将 <code>.vendor</code> 后缀附加到模块名称上。例如: |
| </p> |
| |
| <pre class="prettyprint"> |
| cc_library { |
| name: "libexample", |
| srcs: ["example.c"], |
| vendor_available: true, |
| } |
| </pre> |
| |
| <p> |
| 在本示例中,<code>libexample</code> 代表 <code>/system/lib[64]/libexample.so</code>、<code>libexample.vendor</code> 代表 <code>/vendor/lib[64]/libexample.so</code>。要安装 <code>/vendor/lib[64]/libexample.so</code>,请将 <code>libexample.vendor</code> 添加到 <code>PRODUCT_PACKAGES</code>: |
| </p> |
| |
| <pre class="prettyprint">PRODUCT_PACKAGES += libexample.vendor</pre> |
| |
| </body></html> |