blob: 3761f9c09df072c0f726ee5cc3a33594d19b5f14 [file] [log] [blame]
<html devsite><head>
<title>启用 VNDK</title>
<meta name="project_path" value="/_project.yaml"/>
<meta name="book_path" value="/_book.yaml"/>
</head>
<body>
<!--
Copyright 2018 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>为了区隔供应商模块与系统模块,您在启用 VNDK 前需要对代码库进行一些更改。请按照以下指南在供应商/OEM 代码库中启用 VNDK。</p>
<h2 id="build-system-libraries">编译系统库</h2>
<p>编译系统包含多种类型的对象,其中包括库(共享、静态或标头)和二进制文件:</p>
<img src="../images/treble_vndk_build_system_libraries.png"/>
<figcaption><strong>图 1.</strong> 编译系统库。</figcaption>
<ul>
<li><strong>core</strong>:位于系统映像中,由系统映像使用。<code>vendor</code><code>vendor_available</code><code>vndk</code><code>vndk-sp</code> 库不能使用此类库。
<pre class="prettyprint">
cc_library {
name: "libThatIsCore",
...
}
</pre>
</li>
<li><strong>vendor-only</strong>(或 <code>proprietary</code>):位于供应商映像中,由供应商映像使用。
<pre class="prettyprint">
cc_library {
name: "libThatIsVendorOnly",
proprietary: true,
# or: vendor: true, # (for things in AOSP)
...
}
</pre></li>
<li><strong>vendor_available</strong>:位于供应商映像中,由供应商映像使用(可能包含 <code>core</code> 的重复项)。
<pre class="prettyprint">
cc_library {
name: "libThatIsVendorAvailable",
vendor_available: true,
...
}
</pre>
</li>
<li><strong>vndk</strong>:位于系统映像中,由供应商映像使用(<code>vendor_available</code> 的子集)。
<pre class="prettyprint">
cc_library {
name: "libThatIsVndk",
vendor_available: true,
vndk: {
enabled: true,
}
...
}
</pre>
</li>
<li><strong>vndk-sp</strong>:位于系统映像中,由系统映像间接使用(<code>core</code> 的子集)。
<pre class="prettyprint">
cc_library {
name: "libThatIsVndkSp",
vendor_available: true,
vndk: {
enabled: true,
support_system_process: true,
}
...
}
</pre>
</li>
<li><strong>llndk</strong>:同时由系统映像和供应商映像使用。
<pre class="prettyprint">
llndk_library {
name: "libThasIsLlndk",
}
</pre>
</li>
</ul>
<p>当一个库被标记为 <code>vendor_available:true</code> 时,它将编译两次:</p>
<ul>
<li>一次是为平台编译(因此被安装到 <code>/system/lib</code> 中)。</li>
<li>一次是为供应商编译(因此被安装到 <code>/vendor/lib</code><code>/system/lib/vndk</code><code>/system/lib/vndk-sp</code> 中)。</li>
</ul>
<p>库的供应商版本使用 <code>-D__ANDROID_VNDK__</code> 标记编译。您可以使用此标记停用在 Android 未来版本中可能会发生显著变化的专用系统组件。此外,不同的库会导出一组不同的标头(例如 <code>liblog</code>)。可以在 <code>Android.bp</code> 文件中指定相应目标的供应商变体特有的选项:</p>
<pre class="prettyprint">target: { vendor: { … } }</pre>
<h2 id="enabling">为代码库启用 VNDK</h2>
<p>要为代码库启用 VNDK,请执行以下操作:</p>
<ol>
<li>通过计算 <code>vendor.img</code><code>system.img</code> 分区的所需大小来确定是否符合条件。</li>
<li>启用 <code>BOARD_VNDK_VERSION=current</code>。您可以将其添加到 <code>BoardConfig.mk</code>,也可以直接使用此选项来编译组件(即 <code>m -j BOARD_VNDK_VERSION=current <var>MY-LIB</var></code>)。</li>
</ol>
<p>在启用 <code>BOARD_VNDK_VERSION=current</code> 后,编译系统会强制执行以下依赖项和标头要求。</p>
<h3 id="managing-dependencies">管理依赖项</h3>
<p>如果 <code>vendor</code> 对象依赖的 <code>core</code> 组件在 <code>vndk</code> 中不存在或未以 <code>vendor</code> 对象的形式存在,则必须通过以下某种方式解决该问题:</p>
<ul>
<li>可以移除该依赖项。</li>
<li>如果该 <code>core</code> 组件归 <code>vendor</code> 所有,则可将其标记为 <code>vendor_available</code><code>vendor</code></li>
<li>可以在上游向 Google 提交更改请求,以便将此核心对象列入 <code>vndk</code></li>
</ul>
<p>此外,如果有 <code>core</code> 组件依赖于 <code>vendor</code> 组件,则必须使此 <code>vendor</code> 组件成为 <code>core</code> 组件,<strong>或者</strong>以其他方式移除此依赖项(例如,通过移除依赖项或将其移到 <code>vendor</code> 组件中)。</p>
<h3 id="managing-headers">管理标头</h3>
<p>必须移除全局标头依赖项,编译系统才能知道在编译标头时是否带 <code>-D__ANDROID_VNDK__</code>。例如,您仍然可以使用标头库 <a href="https://android.googlesource.com/platform/system/core/+/master/libutils/include/utils" class="external"><code>libutils_headers</code></a> 来访问<code>utils/StrongPointer.h</code> 等 libutils 标头。
</p>
<p>某些标头(例如 <code>unistd.h</code>)无法再以传递方式包含在内,但可以包含在本地。</p>
<p>最后,<code>private/android_filesystem_config.h</code> 的公共部分已移至 <code>cutils/android_filesystem_config.h</code>。要管理这些标头,请执行下列操作之一:</p>
<ul>
<li>通过将所有 <code>AID_*</code> 宏替换为 <code><a href="http://man7.org/linux/man-pages/man3/getgrnam.3.html" class="external">getgrnam</a></code>/<code><a href="http://man7.org/linux/man-pages/man3/getpwnam.3.html" class="external">getpwnam</a></code> 调用(如果可能),去除对 <code>private/android_filesystem_config.h</code> 的依赖。例如:
<ul>
<li><code>(uid_t)AID_WIFI</code> 会变为 <code>getpwnam("wifi")-&gt;pw_uid</code></li>
<li><code>(gid_t)AID_SDCARD_R</code> 会变为 <code>getgrnam("sdcard_r")-&gt;gr_gid</code></li>
</ul>
如需了解详情,请参阅 <code><a href="https://android.googlesource.com/platform/system/core/+/master/libcutils/include/private/android_filesystem_config.h" class="external">private/android_filesystem_config.h</a></code>
</li>
<li>对于硬编码的 AIS,请包含 <code>cutils/android_filesystem_config.h</code></li>
</ul>
</body></html>