| <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> |
| |
| <p>以下示例演示了基本概念:</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>Android.bp</code> 模块定义定义了一个名为 <code>libexample</code> 的库。<code>vendor_available</code> 属性表示框架模块和供应商模块均可能依赖于 <code>libexample</code>。在本示例中,框架可执行文件 <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> |
| |
| <p>这两个变体将安装到不同的目录中。核心变体将安装到 <code>/system/lib[64]/libexample.so</code> 中。供应商变体将安装到 <code>/system/lib[64]/vndk/libexample.so</code> 中,因为 <code>vndk.enabled</code> 为 <code>true</code>。</p> |
| |
| <p>有关更多详情,请参阅<a href="#module-definition">模块定义</a>。</p> |
| |
| <h2 id="configuration">配置</h2> |
| |
| <p>要为产品设备启用完整编译系统支持,请将 <code>BOARD_VNDK_VERSION</code> 添加到 <code>BoardConfig.mk</code>:</p> |
| |
| <pre class="prettyprint">BOARD_VNDK_VERSION := current</pre> |
| |
| <h3 id="migration-notes">迁移备注</h3> |
| |
| <p>将 <code>BOARD_VNDK_VERSION</code> 添加到 <code>BoardConfig.mk</code> 会产生全局效应。如果是在 <code>BoardConfig.mk</code> 中定义,系统会检查所有模块。没有将违规模块列入黑名单或白名单的机制。建议您在清除所有不必要的依赖项后再添加 <code>BOARD_VNDK_VERSION</code>。</p> |
| |
| <p>在迁移过程中,您可以通过在环境变量中设置 <code>BOARD_VNDK_VERSION</code> 来测试和编译模块:</p> |
| |
| <pre class="prettyprint">$ BOARD_VNDK_VERSION=current m module_name.vendor</pre> |
| |
| <p>而另一个副作用是,默认的全局标头搜索路径会被移除。<em></em>如果启用 <code>BOARD_VNDK_VERSION</code>,则在默认情况下,系统不会添加以下默认标头搜索路径:</p> |
| |
| <ul> |
| <li>frameworks/av/include</li> |
| <li>frameworks/native/include</li> |
| <li>frameworks/native/opengl/include</li> |
| <li>hardware/libhardware/include</li> |
| <li>hardware/libhardware_legacy/include</li> |
| <li>hardware/ril/include</li> |
| <li>libnativehelper/include</li> |
| <li>libnativehelper/include_deprecated</li> |
| <li>system/core/include</li> |
| <li>system/media/audio/include</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> |
| |
| <p>只有在满足以下条件时,存根共享库中才会包含符号:</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 共享库,因为供应商模块无法在常规系统映像 (GSI) 中找到它们。<em></em></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> |
| |
| <p>编译系统会强制执行以下依赖性检查:</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>vndk.support_system_process</code> 为 <code>false</code>,则供应商变体将安装到 <code>/system/lib[64]/vndk-${VER}</code> 中。 |
| </li> |
| |
| <li> |
| 否则,供应商变体将安装到 <code>/system/lib[64]/vndk-sp-${VER}</code> 中。 |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| <p>下表总结了编译系统如何处理供应商变体:</p> |
| |
| <table> |
| <tbody><tr> |
| <th rowspan="2"><p><code>vendor_available</code></p></th> |
| <th colspan="2"><p><code>vndk</code></p></th> |
| <th rowspan="2"><p><code>Vendor variant descriptions</code></p></th> |
| </tr> |
| |
| <tr> |
| <th><p><code>enabled</code></p></th> |
| <th><p><code>support_same_process</code></p></th> |
| </tr> |
| |
| <tr> |
| <td rowspan="4"><p><code>true</code></p></td> |
| <td rowspan="2"><p><code>false</code></p></td> |
| <td><p><code>false</code></p></td> |
| <td> |
| <p>供应商变体是 VND-ONLY<em></em></p> |
| <p>共享库将安装到 <code>/vendor/lib[64]</code> 中。</p> |
| </td> |
| </tr> |
| |
| <tr> |
| <td><p><code>true</code></p></td> |
| <td><p><em></em>无效(编译错误)</p></td> |
| </tr> |
| |
| <tr> |
| <td rowspan="2"><p><code>true</code></p></td> |
| <td><p><code>false</code></p></td> |
| <td> |
| <p>供应商变体是 VNDK<em></em>。</p> |
| <p>共享库将安装到 <code>/system/lib[64]/vndk-${VER}</code> 中。</p> |
| </td> |
| </tr> |
| |
| <tr> |
| <td><p><code>true</code></p></td> |
| <td> |
| <p>供应商变体是 VNDK-SP<em></em>。</p> |
| <p>共享库将安装到 <code>/system/lib[64]/vndk-sp-${VER}</code> 中。</p> |
| </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><p><code>true</code></p></td> |
| <td><p><em></em>无效(编译错误)</p></td> |
| </tr> |
| |
| <tr> |
| <td rowspan="2"><p><code>true</code></p></td> |
| <td><p><code>false</code></p></td> |
| <td> |
| <p>供应商变体是 VNDK-Private<em></em>。</p> |
| <p>共享库将安装到 <code>/system/lib[64]/vndk-${VER}</code> 中。</p> |
| <p>供应商模块不得直接使用这些变体。</p> |
| </td> |
| </tr> |
| |
| <tr> |
| <td><p><code>true</code></p></td> |
| <td> |
| <p>供应商变体是 <em></em>VNDK-SP-Private。</p> |
| <p>共享库将安装到 <code>/system/lib[64]/vndk-sp-${VER}</code> 中。</p> |
| <p>供应商模块不得直接使用这些变体。</p> |
| </td> |
| </tr> |
| </tbody></table> |
| |
| <aside class="note"><strong>注意</strong>:供应商可以为其模块设置 <code>vendor_available</code>。不过,供应商不得设置 <code>vndk.enabled</code> 和 <code>vndk.support_system_process</code>,因为供应商模块无法在 GSI 中找到它们。</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 P 中,<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> 中。</p> |
| |
| <p>如果某个模块不再依赖于 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>(例如,为其中一个变体添加或移除某项功能):(1) 核心变体(例如 <code>/system/lib[64]/libexample.so</code>)、(2) 供应商变体(例如 <code>/system/lib[64]/vndk[-sp]-${VER}/libexample.so</code>)和 (3) VNDK 扩展(例如 <code>/vendor/lib[64]/vndk[-sp]/libexample.so</code>)。 |
| |
| </p><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> |
| |
| <!-- TODO: The paragraph below looks awkward. Refine this subsection to make |
| this more fluent. --> |
| |
| <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="exclude-source-files-or-shared-libs">排除源文件或共享库</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>。</p> |
| |
| <p>另一方面,<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> 已被<br /> <code>exclude_shared_libs</code> 属性排除。 |
| |
| <!-- <h4 id="vndk-ext-header-guideline">VNDK extension header guidelines</h4> --> |
| |
| <!-- TODO: Add the guide line for VNDK extension headers. --> |
| |
| </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> |