Home | History | Annotate | Download | only in source
      1 <html devsite>
      2   <head>
      3     <title>Understanding 64-bit Builds</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 
     26 <h2 id=overview>Overview</h2>
     27 
     28 <p>From the build systems perspective, the most notable change is that now it
     29 supports building binaries for two target CPU architectures (64-bit and 32-bit)
     30 in the same build. Thats also known as <em>Multilib build</em>.</p>
     31 
     32 <p>For native static libraries and shared libraries, the build system sets up
     33 rules to build binaries for both architectures. The product configuration
     34 (<code>PRODUCT_PACKAGES</code>), together with the dependency graph, determines which
     35 binaries are built and installed to the system image.</p>
     36 
     37 <p>For executables and apps, the build system builds only the 64-bit version by
     38 default, but you can override this setting by using a global
     39 <code>BoardConfig.mk</code> variable or a module-scoped variable.</p>
     40 
     41 <p class="caution"><strong>Caution:</strong> If an app exposes an API to other
     42 apps that can be either 32- or 64-bit, the app must have the
     43 <code>android:multiarch</code> property set to a value of <code>true</code>
     44 within its manifest to avoid potential errors.</p>
     45 
     46 <h2 id=product_configuration>Product Configuration</h2>
     47 
     48 
     49 <p>In <code>BoardConfig.mk</code>, we added the following variables to
     50 configure the second CPU architecture and ABI:</p>
     51 
     52 <pre>
     53 TARGET_2ND_ARCH
     54 TARGET_2ND_ARCH_VARIANT
     55 TARGET_2ND_CPU_VARIANT
     56 TARGET_2ND_CPU_ABI
     57 TARGET_2ND_CPU_ABI2
     58 </pre>
     59 
     60 
     61 <p>You can see an example in <code>build/target/board/generic_arm64/BoardConfig.mk</code>.</p>
     62 
     63 <p>If you want the build system to build 32-bit executables and apps by default,
     64 set the following variable:</p>
     65 
     66 <pre class="devsite-click-to-copy">
     67 TARGET_PREFER_32_BIT := true
     68 </pre>
     69 
     70 <p>However, you can override this setting  by using module-specific variables in
     71 <code>Android.mk</code>.</p>
     72 
     73 <p>In a Multilib build, module names in <code>PRODUCT_PACKAGES</code> cover
     74 both the 32-bit and 64-bit binaries, as long as they are defined by the build
     75 system. For libraries pulled in by dependency, a 32-bit library is installed
     76 only if its required by another 32-bit library or executable. The same is true
     77 for 64-bit libraries.</p>
     78 
     79 <p>However, module names on the <code>make</code> command line cover only the
     80 64-bit version. For example, after running <code>lunch
     81 aosp_arm64-eng</code>,<code>make libc</code> builds only the 64-bit libc. To
     82 build the 32-bit libc, you need to run <code>make libc_32</code>.</p>
     83 
     84 <h2 id=module_definition_in_android_mk>Module Definition in Android.mk</h2>
     85 
     86 <p>You can use the <code>LOCAL_MULTILIB</code> variable to configure your build
     87 for 32-bit and/or 64-bit and override the global
     88 <code>TARGET_PREFER_32_BIT</code>.</p>
     89 
     90 <p>Set <code>LOCAL_MULTILIB</code> to one of the following:</p>
     91 
     92 <ul>
     93   <li>"both: build both 32-bit and 64-bit.</li>
     94   <li>32: build only 32-bit.</li>
     95   <li>64: build only 64-bit.</li>
     96   <li>first: build for only the first arch (32-bit in 32-bit devices and 64-bit
     97 in 64-bit devices).</li>
     98   <li>: the default; the build system decides what arch to build based on the
     99 module class and other <code>LOCAL_</code> variables, such as <code>LOCAL_MODULE_TARGET_ARCH</code>,
    100 <code>LOCAL_32_BIT_ONLY</code>, etc.</li>
    101 </ul>
    102 
    103 <p>In a Multilib build, conditionals like <code>ifeq $(TARGET_ARCH)</code> dont work any
    104 more. </p>
    105 
    106 <p>If you want to build your module for some specific arch(s), the following
    107 variables can help you:</p>
    108 
    109 <ul>
    110   <li><code>LOCAL_MODULE_TARGET_ARCH</code><br>It can be set to a list of archs, something
    111 like arm x86 arm64. Only if the arch being built is among that list will the
    112 current module be included by the build system.</li>
    113 
    114   <li><code>LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH</code><br>The opposite of
    115 <code>LOCAL_MODULE_TARGET_ARCH</code>. Only if the arch being built is not among the list,
    116 the current module will be included.</li>
    117 </ul>
    118 
    119 <p>There are minor variants of the above two variables:</p>
    120 
    121 <ul>
    122   <li><code>LOCAL_MODULE_TARGET_ARCH_WARN</code></li>
    123   <li><code>LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN</code></li>
    124 </ul>
    125 
    126 <p>The build system will give warning if the current module is skipped due to
    127 archs limited by them.</p>
    128 
    129 <p>To set up arch-specific build flags, use the arch-specific <code>LOCAL_</code> variables. An
    130 arch-specific <code>LOCAL_</code> variable is a normal <code>LOCAL_</code> variable with an arch suffix,
    131 for example:</p>
    132 
    133 <ul>
    134   <li> <code>LOCAL_SRC_FILES_arm, LOCAL_SRC_FILES_x86,</code>
    135   <li> <code>LOCAL_CFLAGS_arm, LOCAL_CFLAGS_arm64,</code>
    136   <li> <code>LOCAL_LDFLAGS_arm, LOCAL_LDFLAGS_arm64,</code>
    137 </ul>
    138 
    139 <p>Those variables will be applied only if a binary is  currently being built for
    140 that arch.</p>
    141 
    142 <p>Sometimes its more convenient to set up flags based on whether the binary is
    143 currently being built for 32-bit or 64-bit. In that case you can use the <code>LOCAL_</code>
    144 variable with a <code>_32</code> or <code>_64</code> suffix, for example:</p>
    145 
    146 <ul>
    147   <li> <code>LOCAL_SRC_FILES_32, LOCAL_SRC_FILES_64,</code>
    148   <li> <code>LOCAL_CFLAGS_32, LOCAL_CFLAGS_64,</code>
    149   <li> <code>LOCAL_LDFLAGS_32, LOCAL_LDFLAGS_64,</code>
    150 </ul>
    151 
    152 <p>Note that not all of the <code>LOCAL_</code> variables support the arch-specific variants.
    153 For an up-to-date list of such variables, refer to <code>build/core/clear_vars.mk</code>.</p>
    154 
    155 <h2 id=install_path>Install path</h2>
    156 
    157 
    158 <p>In the past, you could use <code>LOCAL_MODULE_PATH</code> to install a library to a
    159 location other than the default one. For example, <code>LOCAL_MODULE_PATH :=
    160 $(TARGET_OUT_SHARED_LIBRARIES)/hw</code>.</p>
    161 
    162 <p>In Multilib build, use <code>LOCAL_MODULE_RELATIVE_PATH</code> instead:</p>
    163 
    164 <pre class="devsite-click-to-copy">
    165 LOCAL_MODULE_RELATIVE_PATH := hw
    166 </pre>
    167 
    168 
    169 <p>so that both the 64-bit and 32-bit libraries can be installed to the right
    170 place.</p>
    171 
    172 <p>If you build an executable as both 32-bit and 64-bit, youll need to use one of
    173 the following variables to distinguish the install path:</p>
    174 
    175 <ul>
    176   <li><code>LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64</code><br>Specifies the installed file name.
    177   <li><code>LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64</code><br>Specifies the install path.
    178 </ul>
    179 
    180 <h2 id=generated_sources>Generated sources </h2>
    181 
    182 <p>In a Multilib build,  if you generate source files to
    183 <code>$(local-intermediates-dir)</code> (or <code>$(intermediates-dir-for)
    184 </code>with explicit variables), it wont reliably work any more. Thats
    185 because the intermediate generated sources will be required by both 32-bit and
    186 64-bit build, but <code>$(local-intermediates-dir)</code> only points to one of
    187 the two intermediate directories.</p>
    188 
    189 <p>Happily, the build system now provides a dedicated, Multilib-friendly,
    190 intermediate directory for generating sources. You can call<code>
    191 $(local-generated-sources-dir)</code> or
    192 <code>$(generated-sources-dir-for)</code> to get the directorys path. Their
    193 usages are similar to <code>$(local-intermediates-dir)</code> and
    194 <code>$(intermediates-dir-for)</code>. </p>
    195 
    196 <p>If a source file is generated to the new dedicated directory and picked up
    197 by <code>LOCAL_GENERATED_SOURCES</code>, it is built for both 32-bit and 64-bit
    198 in multilib build.</p>
    199 
    200 <h2 id=prebuilts>Prebuilts</h2>
    201 
    202 
    203 <p>In Multilib, you cant use <code>TARGET_ARCH</code> (or together with
    204 <code>TARGET_2ND_ARCH</code>) to tell the build system what arch the prebuilt
    205 binary is targeted for. Use the aforementioned <code>LOCAL_</code> variable
    206 <code>LOCAL_MODULE_TARGET_ARCH</code> or
    207 <code>LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH</code> instead.</p>
    208 
    209 <p>With these variables, the build system can choose the corresponding 32-bit
    210 prebuilt binary even if its currently doing a 64-bit Multilib build.</p>
    211 
    212 <p>If you want to use the chosen arch to compute the source path for the prebuilt
    213 binary , you can call<code> $(get-prebuilt-src-arch)</code>.</p>
    214 
    215 <h2 id=dex-preopt>Dex-preopt</h2>
    216 
    217 
    218 <p>For 64-bit devices, by default we generate both 32-bit and 64-bit odex files
    219 for the boot image and any Java libraries. For APKs, by default we generate
    220 odex only for the primary 64-bit arch. If an app will be launched in both
    221 32-bit and 64-bit processes, please use <code>LOCAL_MULTILIB := both</code> to make sure
    222 both 32-bit and 64-bit odex files are generated. That flag also tells the build
    223 system to include both 32-bit and 64-bit JNI libraries, if the app has any.</p>
    224 
    225 
    226   </body>
    227 </html>
    228