aboutsummaryrefslogtreecommitdiff
path: root/zh-cn/devices/architecture/vndk/build-system.html
blob: 6c88a0ce861eded4bcf26459a61dbaf724ef38b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
<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>(Android 8.1 的唯一有效值),则所有供应商模块均可访问供应商变体。</li>

 <li>在 AOSP master 中,如果 <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</code> 中。
     </li>

     <li>
      反之,将供应商变体安装到 <code>/system/lib[64]/vndk-sp</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</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</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-Indirect。<em></em></p>
   <p>共享库将安装到 <code>/system/lib[64]/vndk</code> 中。</p>
   <p>这些变体不得由供应商模块直接使用。</p>
   <p>AOSP master(而非 Android 8.1)中的新设置。</p>
  </td>
 </tr>

 <tr>
  <td><p><code>true</code></p></td>
  <td>
   <p>供应商变体是 VNDK-SP-Indirect-Private。<em></em></p>
   <p>共享库将安装到 <code>/system/lib[64]/vndk-sp</code> 中。</p>
   <p>这些变体不得由供应商模块直接使用。</p>
   <p>AOSP master(而非 Android 8.1)中的新设置。</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="conditional-compilation">条件编译</h3>

<p>如果核心变体和供应商变体之间存在一些细微差异,您可以使用 <code>target.vendor</code> 为条件编译指定不同的选项。例如:</p>

<pre class="prettyprint">cc_library {
    name: "libconditional_example",
    srcs: ["fwk.c", "both.c"],
    shared_libs: ["libfwk_only", "libboth"],
    target: {
        vendor: {
            exclude_srcs: ["fwk.c"],
            exclude_shared_libs: ["libfwk_only"],
            cflags: ["-DVENDOR_VARIANT=1"],
            cppflags: ["-DVENDOR_VARIANT=1"],
        },
    },
}</pre>

<p>在本示例中,<code>libconditional_example</code> 的核心变体包含 <code>fwk.c</code> 和 <code>both.c</code> 的代码,并且依赖于共享库 <code>libfwk_only</code> 和 <code>libboth</code>。</p>

<p>另一方面,<code>libconditional_example</code> 的供应商变体仅包含 <code>both.c</code> 中的代码,因为 <code>fwk.c</code> 已被 <code>exclude_srcs</code> 属性排除。同样,<code>libconditional_example</code> 仅依赖于共享库 <code>libboth</code>,因为 <code>libfwk_only</code> 已被 <code>exclude_shared_libs</code> 属性排除。<code>cflags</code> 和 <code>cppflags</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>