Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 1 | # Build System Maintainers Guide |
| 2 | |
| 3 | The latest version of this document is available at |
Dan Albert | c4bdd15 | 2025-03-28 15:11:24 -0700 | [diff] [blame] | 4 | https://android.googlesource.com/platform/ndk/+/mirror-goog-main-ndk/docs/BuildSystemMaintainers.md. |
Dan Albert | 92a3be3 | 2019-02-08 15:48:51 -0800 | [diff] [blame] | 5 | Ensure that you are using the version that corresponds to your NDK. Replace |
Dan Albert | 60a8074 | 2025-03-11 12:46:32 -0700 | [diff] [blame] | 6 | `master` in the URL with the appropriate NDK release branch. For example, the |
| 7 | NDK r28 version of this document is located at |
| 8 | https://android.googlesource.com/platform/ndk/+/ndk-r28-release/docs/BuildSystemMaintainers.md. |
| 9 | For r23 and older, the branch name follows a different pattern. The r23 version |
| 10 | of this document is located at |
| 11 | https://android.googlesource.com/platform/ndk/+/ndk-release-r23/docs/BuildSystemMaintainers.md. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 12 | |
| 13 | The purpose of this guide is to instruct third-party build system maintainers in |
| 14 | adding NDK support to their build systems. This guide will not be useful to most |
| 15 | NDK users. NDK users should start with [Building Your Project]. |
| 16 | |
| 17 | Note: This guide is written assuming Linux is the host OS. Mac should be no |
| 18 | different, and the only difference on Windows is that file extensions for |
| 19 | executables and scripts will differ. |
| 20 | |
| 21 | [Building Your Project]: https://developer.android.com/ndk/guides/build |
| 22 | |
| 23 | [TOC] |
| 24 | |
| 25 | ## Introduction |
| 26 | |
Dan Albert | 48b8e52 | 2020-03-18 12:33:56 -0700 | [diff] [blame] | 27 | The NDK uses the [LLVM] family of tools for building C/C++ code. These include |
| 28 | [Clang] for compilation, [LLD] for linking, and other [LLVM tools] for other |
Dan Albert | ae0943e | 2023-04-17 13:26:01 -0700 | [diff] [blame] | 29 | tasks. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 30 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 31 | [Clang]: https://clang.llvm.org/ |
| 32 | [LLD]: https://lld.llvm.org/ |
Dan Albert | ad4282f | 2020-06-19 13:24:48 -0700 | [diff] [blame] | 33 | [LLVM tools]: https://llvm.org/docs/CommandGuide/ |
| 34 | [LLVM]: https://llvm.org/ |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 35 | |
| 36 | ### Architectures |
| 37 | [Architectures]: #architectures |
| 38 | |
| 39 | Note: In general an architecture may have multiple ABIs. An ABI (application |
| 40 | binary interface) is different from an architecture in that it also specifies a |
| 41 | calling convention, size and alignment of types, and other implementation |
| 42 | details. For Android, each architecture supports only one ABI. |
| 43 | |
| 44 | Android supports multiple architectures: ARM32, ARM64, x86, and x86_64. NDK |
| 45 | applications must build libraries for every architecture they support. 64-bit |
| 46 | devices usually also support the 32-bit variant of their architecture, but this |
| 47 | may not always be the case. While in general this means that an app with only |
| 48 | 32-bit libraries can run on 64-bit capable devices, the 64-bit ABI will have |
| 49 | improved performance. |
| 50 | |
| 51 | This document will make use of `<arch>`, `<ABI>`, and `<triple>` in describing |
| 52 | paths and arguments. The values of these variables for each architecture are as |
| 53 | follows except where otherwise noted: |
| 54 | |
| 55 | | Name | arch | ABI | triple | |
| 56 | | ------------ | ------- | ----------- | --------------------- | |
| 57 | | 32-bit ARMv7 | arm | armeabi-v7a | arm-linux-androideabi | |
| 58 | | 64-bit ARMv8 | aarch64 | aarch64-v8a | aarch64-linux-android | |
| 59 | | 32-bit Intel | x86 | x86 | i686-linux-android | |
| 60 | | 64-bit Intel | x86_64 | x86_64 | x86_64-linux-android | |
| 61 | |
Dan Albert | c81c62a | 2018-10-10 13:49:14 -0700 | [diff] [blame] | 62 | Note: Strictly speaking ARMv7 with [NEON] is a different ABI from ARMv7 without |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 63 | NEON, but it is not a *system* ABI. Both NEON and non-NEON ARMv7 code uses the |
| 64 | ARMv7 system and toolchains. |
| 65 | |
| 66 | To programatically determine the list of supported ABIs, their bitness, as well |
| 67 | as their deprecation status and whether or not it is recommended to build them |
| 68 | by default, use `<NDK>/meta/abis.json`. |
| 69 | |
| 70 | ### Thumb |
| 71 | |
| 72 | 32-bit ARM can be built using either the [Thumb] or ARM instruction sets. Thumb |
| 73 | code is smaller but may perform worse than ARM. However, smaller code makes more |
| 74 | effective use of a processor's instruction cache, so benchmarking is necessary |
| 75 | to determine which is more effective for a given application. ndk-build and the |
| 76 | NDK's CMake toolchain file generate Thumb code by default. |
| 77 | |
| 78 | The ARM or Thumb instruction sets are selected by passing `-marm` or `-mthumb` |
| 79 | to Clang respectively. By default, Clang will generate ARM code as opposed to |
| 80 | Thumb for the `armv7a-linux-androideabi` target. |
| 81 | |
| 82 | Note: For ARMv7, Thumb-2 is used. Android no longer supports ARMv5, but if your |
| 83 | build system mistakenly targets ARMv5 the less efficient Thumb-1 will be used. |
| 84 | |
| 85 | [Thumb]: https://en.wikipedia.org/wiki/ARM_architecture#Thumb-2 |
| 86 | |
| 87 | ### NEON |
| 88 | |
| 89 | Most ARM Android devices support [NEON]. This is supported by all 64-bit ARM |
| 90 | devices and nearly all 32-bit ARM devices running at least Android Marshmallow |
| 91 | (API 23). The [Android CDD] has required NEON support since that version, but it |
| 92 | is possible that extant devices that were upgraded to Marshmallow do not include |
| 93 | NEON support. |
| 94 | |
Dan Albert | a78a3dc | 2019-09-04 13:15:15 -0700 | [diff] [blame] | 95 | NEON can significantly improve application performance. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 96 | |
Dan Albert | a78a3dc | 2019-09-04 13:15:15 -0700 | [diff] [blame] | 97 | Clang automatically enables NEON for all API levels. ARM devices without NEON |
| 98 | are uncommon. To support non-NEON devices, pass `-mfpu=vfpv3-d16` when |
Dan Albert | 73c19ee | 2020-07-24 16:25:18 -0700 | [diff] [blame] | 99 | compiling. Alternatively, use the Play Console to [exclude CPUs] without NEON |
Dan Albert | a78a3dc | 2019-09-04 13:15:15 -0700 | [diff] [blame] | 100 | to disallow your app from being installed on those devices. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 101 | |
| 102 | [Android CDD]: https://source.android.com/compatibility/cdd |
| 103 | [NEON]: https://developer.arm.com/technologies/neon |
Dan Albert | 73c19ee | 2020-07-24 16:25:18 -0700 | [diff] [blame] | 104 | [exclude CPUs]: https://support.google.com/googleplay/android-developer/answer/7353455?hl=en |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 105 | |
| 106 | ### OS Versions |
| 107 | [OS Versions]: #os-versions |
| 108 | |
| 109 | As users are distributed over a wide variety of Android OS versions (see the |
| 110 | [Distribution dashboard]), applications have a minimum and maximum supported |
| 111 | version, as well as a targeted version. These are `minSdkVersion`, |
| 112 | `maxSdkVersion`, and `targetSdkVersion` respectively. See the [uses-sdk] |
| 113 | documentation for more information. |
| 114 | |
| 115 | For NDK code, the only relevant value is the minimum supported version. Any time |
| 116 | this doc refers to an API level, OS version, or target version, it is referring |
| 117 | to the application's `minSdkVersion`. |
| 118 | |
| 119 | The API level targeted by an NDK application determines which APIs will be |
Dan Albert | ac91a27 | 2022-10-06 15:13:04 -0700 | [diff] [blame] | 120 | exposed for use by the application. By default, APIs that are not present in the |
| 121 | targeted API level cannot be linked directly, but may be accessed via `dlsym`. |
| 122 | An NDK application running on a device with an API level lower than the target |
| 123 | will often not load at all. If it does load, it may not behave as expected. This |
| 124 | is not a supported configuration. This behavior can be altered by following the |
| 125 | section about [weak symbols]. Be sure your users understand the implications of |
| 126 | doing so. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 127 | |
| 128 | The major/minor version number given to an Android OS has no meaning when it |
| 129 | comes to determining its API level. See the table in the [Build numbers] |
| 130 | document to map Android code names and version numbers to API levels. |
| 131 | |
| 132 | Note: Not every API level includes new NDK APIs. If there were no new NDK APIs |
| 133 | for the given API level, there is no library directory for that API level. In |
| 134 | that case, the build system should select the closest available API that is |
| 135 | below the target API level. For example, applications with a `minSdkVersion` of |
| 136 | 20 should use API 19 for their NDK target. |
| 137 | |
| 138 | To programatically determine the list of supported API levels as well as aliases |
Dan Albert | f0f3bdf | 2024-01-22 15:48:36 -0800 | [diff] [blame] | 139 | that are accepted by ndk-build and CMake, see `<NDK>/meta/platforms.json`. For |
| 140 | ABI specific minimum supported API levels, see `<NDK>/meta/abis.json`. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 141 | |
| 142 | Note: In some contexts the API level may be referred to as a platform. In this |
| 143 | document an API level is always an integer, and a platform takes the form of |
| 144 | `android-<API level>`. The latter format is not specifically used anywhere in |
| 145 | the NDK toolchain, but is used to specify target API levels for ndk-build and |
| 146 | CMake. |
| 147 | |
| 148 | Note: As a new version of the Android OS approaches release, previews and betas |
| 149 | of that OS will be released and an NDK will be released that can make use of the |
| 150 | new APIs. Targeting a preview API level is no different than targeting a |
| 151 | released API level, with the exception that applications built targeting preview |
| 152 | releases should not be shipped to production. Consult |
| 153 | `<NDK>/meta/platforms.json` to determine the API level for a preview release. |
| 154 | |
| 155 | [Build numbers]: https://source.android.com/setup/start/build-numbers |
| 156 | [Distribution dashboard]: https://developer.android.com/about/dashboards/ |
| 157 | [uses-sdk]: https://developer.android.com/guide/topics/manifest/uses-sdk-element |
Dan Albert | ac91a27 | 2022-10-06 15:13:04 -0700 | [diff] [blame] | 158 | [weak symbols]: #weak-symbols-for-api-definitions |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 159 | |
Dan Albert | 7b4281b | 2024-03-25 14:40:17 -0700 | [diff] [blame] | 160 | ### Page sizes |
| 161 | |
| 162 | Android V will allow OEMs to ship arm64-v8a and x86_64 devices with 16KiB page |
| 163 | sizes. Devices that use this configuration will not be able to run existing apps |
| 164 | that use native code. To be compatible with these devices, applications will |
| 165 | need to rebuild all their native code to be 16KiB aligned, and rewrite any code |
| 166 | which assumes a specific page size. See [Support 16 KB page sizes] for details. |
| 167 | |
| 168 | Note: 16KiB compatible binaries are also compatible with 4KiB page devices. You |
| 169 | do not need to build both 16KiB and 4KiB variants of your libraries. |
| 170 | |
| 171 | To minimize disruption, the default configuration for NDK r27 remains 4KiB page |
| 172 | sizes. A future NDK (likely r28) will change the defaults. To support building |
| 173 | 16KiB compatible apps in your build system, do the following: |
| 174 | |
| 175 | 1. When linking arm64-v8a or x86_64 code, set the linker's max-page-size to |
| 176 | 16384: `-Wl,-z,max-page-size=16384`. This will increase the size of the |
| 177 | binaries. |
| 178 | 2. Define `__BIONIC_NO_PAGE_SIZE_MACRO` to configure libc to hide the |
| 179 | declaration of `PAGE_SIZE` from the build: `-D__BIONIC_NO_PAGE_SIZE_MACRO`. |
| 180 | There is no valid build-time constant for the page size in a world where |
| 181 | devices have varying page sizes. Runtime checks with `getpagesize()` are |
| 182 | required. |
| 183 | |
| 184 | Note that, for the time being, this only needs to be done for arm64-v8a. The |
| 185 | x86_64 emulator (see [Support 16 KB page sizes] for details) will support larger |
| 186 | page sizes for testing purposes, but there are no plans to change the page size |
| 187 | for the 32-bit ABIs, and riscv64 does not support 16KiB page sizes at all. |
| 188 | |
| 189 | [Support 16 KB page sizes]: https://developer.android.com/guide/practices/page-sizes |
| 190 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 191 | ## Clang |
| 192 | |
Dan Albert | dae41c7 | 2018-10-25 13:36:51 -0700 | [diff] [blame] | 193 | Clang is installed to `<NDK>/toolchains/llvm/prebuilt/<host-tag>/bin/clang`. |
| 194 | The C++ compiler is installed as `clang++` in the same directory. `clang++` will |
| 195 | make C++ headers available when compiling and will automatically link the C++ |
| 196 | runtime libraries when linking. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 197 | |
| 198 | `clang` should be used when compiling C source files, and `clang++` should be |
| 199 | used when compiling C++ source files. When linking, `clang` should be used if |
| 200 | the binary being linked contains no C++ code (i.e. none of the object files |
| 201 | being linked were generated from C++ files) and `clang++` should be used |
| 202 | otherwise. Using `clang++` ensures that the C++ standard library is linked. |
| 203 | |
Dan Albert | eb4cc50 | 2023-04-17 13:28:53 -0700 | [diff] [blame] | 204 | When linking a shared library, the `-Wl,-soname,$NAME_OF_LIBRARY` argument is |
| 205 | required. This is necessary to avoid the problems described in [this stack |
| 206 | overflow post](https://stackoverflow.com/a/48291044/632035). For example, when |
| 207 | building `libapp.so`, `-Wl,-soname,libapp.so` must be used. |
| 208 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 209 | ### Target Selection |
| 210 | |
James Farrell | 37befa4 | 2022-06-22 20:17:58 +0000 | [diff] [blame] | 211 | [Cross-compilation] targets can be selected in one of two ways: by using |
| 212 | the `--target` flag, or by using target-specific wrapper scripts. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 213 | |
James Farrell | 37befa4 | 2022-06-22 20:17:58 +0000 | [diff] [blame] | 214 | If possible, we recommend using the `--target` flag, which is described more |
| 215 | fully in the [Clang User Manual]. The value passed is a Clang target |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 216 | triple suffixed with an Android API level. For example, to target API 26 for |
| 217 | 32-bit ARM, use `--target armv7a-linux-androideabi26`. |
| 218 | |
| 219 | Note: "armv7a" should be used rather than simply "arm" when specifying targets |
| 220 | for Clang to generate ARMv7 code rather than the slower ARMv5 code. Specifying |
| 221 | ARMv5 and thumb code generation will result in Thumb-1 being generated rather |
| 222 | than Thumb-2, which is less efficient. |
| 223 | |
James Farrell | 37befa4 | 2022-06-22 20:17:58 +0000 | [diff] [blame] | 224 | If not possible to use the `--target` flag, we supply wrapper scripts alongside |
| 225 | the `clang` and `clang++` binaries, named `<triple><API-level>-clang` and |
| 226 | `<triple><API-level>-clang++`. For example, to target API 26 32-bit ARM, |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 227 | invoke `armv7a-linux-androideabi26-clang` or |
James Farrell | 37befa4 | 2022-06-22 20:17:58 +0000 | [diff] [blame] | 228 | `armv7a-linux-androideabi26-clang++` instead of `clang` or `clang++`. These |
| 229 | wrappers come in two forms: Bash scripts (for Mac, Linux, Cygwin, and WSL) and |
| 230 | Windows batch files (with `.cmd` extensions). |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 231 | |
James Farrell | 37befa4 | 2022-06-22 20:17:58 +0000 | [diff] [blame] | 232 | Note: For projects with many source files, the wrapper scripts may cause |
| 233 | noticeable overhead, which is why we recommend using `--target`. The overhead |
| 234 | is most significant on Windows, as `CreateProcess` is slower than `fork`. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 235 | |
| 236 | For more information on Android targets, see the [Architectures] and [OS |
| 237 | Versions] sections. |
| 238 | |
| 239 | [Clang User Manual]: https://clang.llvm.org/docs/UsersManual.html |
| 240 | [Cross-compilation]: https://en.wikipedia.org/wiki/Cross_compiler |
| 241 | |
| 242 | ## Linkers |
| 243 | |
Dan Albert | ae0943e | 2023-04-17 13:26:01 -0700 | [diff] [blame] | 244 | The NDK uses LLD for linking. The linker is installed to |
| 245 | `<NDK>/toolchains/llvm/prebuilt/<host-tag>/bin/<triple>-ld`. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 246 | |
| 247 | Note: It is usually not necessary to invoke the linkers directly since Clang |
| 248 | will do so automatically. Clang will also automatically link CRT objects and |
| 249 | default libraries and set up other target-specific options, so it is generally |
| 250 | better to use Clang for linking. |
| 251 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 252 | [Issue 70838247]: https://issuetracker.google.com/70838247 |
Dan Albert | e043c26 | 2018-11-13 15:10:18 -0800 | [diff] [blame] | 253 | |
| 254 | ## Binutils |
| 255 | |
Dan Albert | 1cc962e | 2020-06-24 13:32:45 -0700 | [diff] [blame] | 256 | LLVM's binutils tools are installed to the NDK at |
| 257 | `<NDK>/toolchains/llvm/prebuilt/<host-tag>/bin/llvm-<tool>`. These include but |
| 258 | are not limited to: |
| 259 | |
| 260 | * llvm-ar |
Dan Albert | 1cc962e | 2020-06-24 13:32:45 -0700 | [diff] [blame] | 261 | * llvm-objcopy |
| 262 | * llvm-objdump |
| 263 | * llvm-readelf |
| 264 | * llvm-strip |
| 265 | |
Dan Albert | 0ba6493 | 2023-08-01 14:30:41 -0700 | [diff] [blame] | 266 | All LLVM tools are capable of handling every target architecture. Unlike Clang, |
| 267 | no `-target` argument is required for these tools, so they should behave |
| 268 | correctly when used as drop-in replacements for their GNU equivalents. Some |
| 269 | tools may optionally accept a `-target` argument, but if omitted they will |
| 270 | select the correct target based on the input files. |
| 271 | |
Dan Albert | f52235b | 2020-06-24 15:48:52 -0700 | [diff] [blame] | 272 | Note that `llvm-as` is **not** an equivalent of GNU `as`, but rather a tool for |
| 273 | assembling LLVM IR. If you are currently using `as` directly, you will need to |
Elliott Hughes | 3e47e46 | 2021-08-24 10:30:26 -0700 | [diff] [blame] | 274 | migrate to using `clang` as a driver for building assembly. See [Clang |
| 275 | Migration Notes] for advice on fixing assembly to be LLVM compatible. |
Dan Albert | f52235b | 2020-06-24 15:48:52 -0700 | [diff] [blame] | 276 | |
Elliott Hughes | 3e47e46 | 2021-08-24 10:30:26 -0700 | [diff] [blame] | 277 | Note that by default `/usr/bin/as` is used by Clang if the |
| 278 | `-fno-integrated-as` argument is used, which is almost certainly not |
| 279 | what you want! |
| 280 | |
| 281 | [Clang Migration Notes]: ClangMigration.md |
Dan Albert | ad4282f | 2020-06-19 13:24:48 -0700 | [diff] [blame] | 282 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 283 | ## Sysroot |
| 284 | |
Dan Albert | dae41c7 | 2018-10-25 13:36:51 -0700 | [diff] [blame] | 285 | The Android sysroot is installed to |
| 286 | `<NDK>/toolchains/llvm/prebuilt/<host-tag>/sysroot` and contains the headers, |
| 287 | libraries, and CRT object files for each Android target. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 288 | |
| 289 | Headers can be found in the `usr/include` directory of the sysroot. Target |
| 290 | specific include files are installed to `usr/include/<triple>`. When using |
| 291 | Clang, it is not necessary to include these directories explicitly; Clang will |
| 292 | automatically select the sysroot. If using a compiler other than Clang, ensure |
| 293 | that the target-specific include directory takes precedence over the |
| 294 | target-generic directory. |
| 295 | |
| 296 | Libraries are found in the `usr/lib/<triple>` directory of the sysroot. |
| 297 | Version-specific libraries are installed to `usr/lib/<triple>/<API-level>`. As |
| 298 | with the header files, when using Clang it is not necessary to include these |
| 299 | directories explicitly; the sysroot will be automatically selected. If using a |
| 300 | compiler other than Clang, ensure that the version-specific library directory |
| 301 | takes precedence over the version-generic directory. |
| 302 | |
| 303 | ## Libraries |
| 304 | |
| 305 | The NDK contains three types of libraries. Static libraries have a .a file |
| 306 | extension and are linked directly into app binaries. Shared libraries have a .so |
| 307 | file extension and must be included in the app's APK if used. System stub |
| 308 | libraries are a special type of shared library that should not be included in |
| 309 | the APK. The system stub libraries define the interface of a library that is |
| 310 | provided by the Android OS but contain no implementation. They can be identified |
Dan Albert | a737dee | 2019-04-18 15:26:58 -0700 | [diff] [blame] | 311 | by their .so file extension and their presence in `<NDK>/meta/system_libs.json`. |
| 312 | The entries in this file are a key/value pair that maps library names to the |
| 313 | first API level the library is introduced. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 314 | |
Dan Albert | ac91a27 | 2022-10-06 15:13:04 -0700 | [diff] [blame] | 315 | ## Weak symbols for API definitions |
| 316 | |
| 317 | See [Issue 837]. |
| 318 | |
| 319 | The Android APIs are exposed as strong symbols by default. This means that apps |
| 320 | must not directly refer to any APIs that were not available in their |
| 321 | `minSdkVersion`, even if they will not be called at runtime. The loader will |
| 322 | reject any library with strong references to symbols that are not present at |
| 323 | load time. |
| 324 | |
| 325 | It is possible to expose Android APIs as weak symbols to alter this behavior to |
| 326 | more closely match the Java behavior, which many app developers are more |
| 327 | familiar with. The loader will allow libraries with unresolved references to |
| 328 | weak symbols to load, allowing those APIs to be safely called as long as they |
| 329 | are only called when the API is available on the device. Absent APIs will have a |
| 330 | `nullptr` address, so calling an unavailable API will segfault. |
| 331 | |
| 332 | Note: APIs that are guaranteed to be available in the `minSdkVersion` (the API |
| 333 | level passed to Clang with `-target`) will always be strong references, even |
| 334 | with this option enabled. |
| 335 | |
| 336 | This is not enabled by default because, unless used cautiously, this method is |
| 337 | prone to deferring build failures to run-time (and only on older devices, since |
| 338 | newer devices will have the API). The loader not prevent the library from |
| 339 | loading, but the function's address will be `nullptr` if the API is not |
| 340 | available (if the API is newer than the OS). The API availability should be |
| 341 | checked with `__builtin_available` before making the call: |
| 342 | |
| 343 | ```c++ |
| 344 | if (__builtin_available(android 33, *)) { |
| 345 | // Call some API that's only available in API 33+. |
| 346 | } else { |
| 347 | // Use some fallback behavior, perhaps doing nothing. |
| 348 | } |
| 349 | ``` |
| 350 | |
| 351 | Clang offers some protections for this approach via `-Wunguarded-availability`, |
| 352 | which will emit a warning unless the call to the API is guarded with |
| 353 | `__builtin_available`. |
| 354 | |
| 355 | To enable this functionality, pass `-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__` |
| 356 | to Clang when compiling. We **strongly** recommend forcing |
| 357 | `-Werror=unguarded-availability` when using this option. |
| 358 | |
| 359 | We recommend making the choice of weak or strong APIs an option in your build |
| 360 | system. Most developers will likely prefer weak APIs as they are simpler than |
| 361 | using `dlopen`/`dlsym`, and as long as `-Werror=unguarded-availability` is used, |
| 362 | it should be safe. At the time of writing, the NDK's own build systems |
| 363 | (ndk-build and CMake) use strong API references by default, but that may change |
| 364 | in the future. |
| 365 | |
| 366 | Known issues and limitations: |
| 367 | |
| 368 | * Only symbols are affected, not libraries. The only way to conditionally depend |
| 369 | on a library that is not available in the app's `minSdkVersion` is with |
| 370 | `dlopen`. We do not know how to solve this in a backwards compatible manner. |
| 371 | * APIs in bionic (libc, libm, libdl) are not currently supported. See the bug |
| 372 | for more information. If the source compatibility issues can be resolved, that |
| 373 | will change in a future NDK release. |
| 374 | * Headers authored by third-parties (e.g. `vulkan.h`, which comes directly from |
| 375 | Khronos) are not supported. The implementation of this feature requires |
| 376 | annotation of all function declarations, and the upstream headers likely do |
| 377 | not contain those annotations. Solutions to this problem are being |
| 378 | investigated. |
| 379 | |
| 380 | [Issue 837]: https://github.com/android/ndk/issues/837 |
| 381 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 382 | ## STL |
| 383 | |
| 384 | ### libc++ |
| 385 | |
| 386 | The STL provided by the NDK is [libc++]. Its headers are installed to |
Dan Albert | 7e81426 | 2018-12-18 15:49:54 -0800 | [diff] [blame] | 387 | `<NDK>/sysroot/usr/include/c++/v1`. This STL is used by default. This STL comes |
| 388 | in both a static and shared variant. The shared variant is used by default. To |
| 389 | use the static variant, pass `-static-libstdc++` when linking. If using the |
| 390 | shared variant, libc++_shared.so must be included in the APK. This library is |
| 391 | installed to `<NDK>/sysroot/usr/lib/<triple>`. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 392 | |
| 393 | Warning: There are a number of things to consider when selecting between the |
| 394 | shared and static STLs. See the [Important Considerations] section of the C++ |
| 395 | Support document for more details. |
| 396 | |
| 397 | There are version-specific libc++.so and libc++.a libraries installed to |
| 398 | `<NDK>/sysroot/usr/lib/<triple>/<version>`. These are not true libraries but |
| 399 | [implicit linker scripts]. They inform the linker how to properly link the STL |
Dan Albert | 4eea3b0 | 2022-10-13 16:49:47 -0700 | [diff] [blame] | 400 | for the given version. These scripts handle the inclusion of any libc++ |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 401 | dependencies if necessary. Linker scripts should not be included in the APK. |
| 402 | |
| 403 | Build systems should prefer to let Clang link the STL. If not using Clang, the |
| 404 | version scripts should be used. Linking libc++ and its dependencies manually |
| 405 | should only be used as a last resort. |
| 406 | |
| 407 | Note: Linking libc++ and its dependencies explicitly may be necessary to defend |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 408 | against exception unwinding bugs caused by improperly built dependencies (see |
| 409 | [Issue 379]). If not dependent on stack unwinding (the usual reason being that |
| 410 | the application does not make use of C++ exceptions) or if no dependencies were |
| 411 | improperly built, this is not necessary. If needed, link the libraries as listed |
| 412 | in the linker script and be sure to follow the instructions in [Unwinding]. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 413 | |
| 414 | [Important Considerations]: https://developer.android.com/ndk/guides/cpp-support#important_considerations |
| 415 | [Issue 379]: https://github.com/android-ndk/ndk/issues/379 |
| 416 | [implicit linker scripts]: https://sourceware.org/binutils/docs/ld/Scripts.html |
| 417 | [libc++]: https://libcxx.llvm.org/ |
| 418 | |
| 419 | ### System STL |
| 420 | |
| 421 | The legacy "system STL" is also included, but it will be removed in a future NDK |
| 422 | release. It is not in fact an STL; it contains only the barest C++ library |
| 423 | support: the C++ versions of the C library headers and basic C++ runtime support |
| 424 | like `new` and `delete`. Its headers are installed to |
Dan Albert | dae41c7 | 2018-10-25 13:36:51 -0700 | [diff] [blame] | 425 | `<NDK>/toolchains/llvm/prebuilt/<host-tag>/include/c++/4.9.x` and its library is |
| 426 | the libstdc++.so system stub library. To use this STL, use the |
| 427 | `-stdlib=libstdc++` flag. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 428 | |
| 429 | TODO: Shouldn't it be installed to sysroot like libc++? |
| 430 | |
| 431 | Note: The system STL will likely be removed in a future NDK release. |
| 432 | |
| 433 | ### No STL |
| 434 | |
| 435 | To avoid using the STL at all, pass `-nostdinc++` when compiling and |
| 436 | `-nostdlib++` when linking. This is not necessary when using `clang`, only when |
| 437 | using `clang++`. |
| 438 | |
| 439 | ## Sanitizers |
| 440 | |
| 441 | The NDK supports [Address Sanitizer] (ASan). This tool is similar to Valgrind in |
| 442 | that it diagnoses memory bugs in a running application, but ASan is much faster |
| 443 | than Valgrind (roughly 50% performance compared to an unsanitized application). |
| 444 | |
| 445 | To use ASan, pass `-fsanitize=address` when both compiling and linking. The |
Dan Albert | 2991a55 | 2023-07-21 10:32:20 -0700 | [diff] [blame] | 446 | sanitizer runtime libraries are installed to `<clang resource dir>/lib/linux`. |
| 447 | The Clang resource directory is given by `clang -print-resource-dir`. The |
| 448 | library is named `libclang_rt.asan-<arch>-android.so`. This library must be |
Dan Albert | aa7f843 | 2019-07-01 13:51:02 -0700 | [diff] [blame] | 449 | included in the APK. A [wrap.sh] file must also be included in the APK. A |
| 450 | premade wrap.sh file for ASan is installed to `<NDK>/wrap.sh`. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 451 | |
| 452 | Note: wrap.sh is only available for [debuggable] APKs running on Android Oreo |
| 453 | (API 26) or higher. ASan can still be used devices prior to Oreo but at least |
| 454 | Lollipop (API 21) if the device has been rooted. Direct users to the |
| 455 | [AddressSanitizerOnAndroid] document for instructions on using this method. |
| 456 | |
| 457 | [Address Sanitizer]: https://clang.llvm.org/docs/AddressSanitizer.html |
| 458 | [AddressSanitizerOnAndroid]: https://github.com/google/sanitizers/wiki/AddressSanitizerOnAndroid#run-time-flags |
| 459 | [debuggable]: https://developer.android.com/guide/topics/manifest/application-element#debug |
| 460 | [wrap.sh]: https://developer.android.com/ndk/guides/wrap-script |
| 461 | |
Dan Albert | e3f7078 | 2019-02-12 13:37:49 -0800 | [diff] [blame] | 462 | ## Additional Required Arguments |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 463 | |
| 464 | Note: It is a bug that any of these need to be specified by the build system. |
| 465 | All flags discussed in this section should be automatically selected by Clang, |
| 466 | but they are not yet. Check back in a future NDK release to see if any can be |
| 467 | removed from your build system. |
| 468 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 469 | For x86 targets prior to Android Nougat (API 24), `-mstackrealign` is needed to |
| 470 | properly align stacks for global constructors. See [Issue 635]. |
| 471 | |
Dan Albert | c81c62a | 2018-10-10 13:49:14 -0700 | [diff] [blame] | 472 | Android requires [Position-independent executables] beginning with API 21. Clang |
| 473 | builds PIE executables by default. If invoking the linker directly or not using |
| 474 | Clang, use `-pie` when linking. |
| 475 | |
Ryan Prichard | 1bbeeea | 2019-07-03 14:48:37 -0700 | [diff] [blame] | 476 | Android Studio's LLDB debugger uses a binary's build ID to locate debug |
| 477 | information. To ensure that LLDB works with a binary, pass an option like |
| 478 | `-Wl,--build-id=sha1` to Clang when linking. Other `--build-id=` modes are OK, |
| 479 | but avoid a plain `--build-id` argument when using LLD, because Android Studio's |
| 480 | version of LLDB doesn't recognize LLD's default 8-byte build ID. See [Issue |
| 481 | 885]. |
| 482 | |
Dan Albert | cfdc5e2 | 2020-06-25 15:53:55 -0700 | [diff] [blame] | 483 | The unwinder used for crash handling on Android devices prior to API 29 cannot |
| 484 | correctly unwind binaries built with `-Wl,--rosegment`. This flag is enabled by |
| 485 | default when using LLD, so if using LLD and targeting devices older than API 29 |
| 486 | you must pass `-Wl,--no-rosegment` when linking for correct stack traces in |
| 487 | logcat. See [Issue 1196]. |
| 488 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 489 | [Issue 635]: https://github.com/android-ndk/ndk/issues/635 |
Ryan Prichard | 1bbeeea | 2019-07-03 14:48:37 -0700 | [diff] [blame] | 490 | [Issue 885]: https://github.com/android-ndk/ndk/issues/885 |
Dan Albert | e3f7078 | 2019-02-12 13:37:49 -0800 | [diff] [blame] | 491 | [Issue 906]: https://github.com/android-ndk/ndk/issues/906 |
Dan Albert | cfdc5e2 | 2020-06-25 15:53:55 -0700 | [diff] [blame] | 492 | [Issue 1196]: https://github.com/android/ndk/issues/1196 |
Dan Albert | c81c62a | 2018-10-10 13:49:14 -0700 | [diff] [blame] | 493 | [Position-independent executables]: https://en.wikipedia.org/wiki/Position-independent_code#Position-independent_executables |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 494 | |
| 495 | ## Useful Arguments |
| 496 | |
| 497 | ### Dependency Management |
| 498 | |
| 499 | It is recommended that `-Wl,--exclude-libs,<library file name>` be used for each |
| 500 | static library linked. This causes the linker to give symbols imported from a |
| 501 | static library hidden [visibility]. This prevents a binary from unintentionally |
| 502 | re-exporting an API other than its own. If the intent is to re-export all the |
| 503 | symbols in a static library, `-Wl,--whole-archive <library> |
| 504 | -Wl,--no-whole-archive` should be used to ensure that the whole archive is |
| 505 | preserved. By default, only symbols in used sections will be included in the |
| 506 | linked binary. |
| 507 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 508 | [visibility]: https://gcc.gnu.org/wiki/Visibility |
| 509 | |
| 510 | ### Controlling Binary Size |
| 511 | |
| 512 | To minimize the size of an APK, it may be desirable to use the `-Oz` |
| 513 | optimization mode. This will generate somewhat slower code than `-O2` or `-O3`, |
| 514 | but it will be smaller. |
| 515 | |
| 516 | Note: `-Os` behavior is not the same with Clang as it is with GCC. Clang's `-Oz` |
| 517 | behaves similarly to GCC's `-Os`. `-Os` with Clang is a middle ground between |
| 518 | size and speed optimizations. |
| 519 | |
| 520 | To aid the linker in removing as much unused code as possible, the compiler |
| 521 | flags `-ffunction-sections` and `-fdata-sections` may be used. These flags |
| 522 | should only be used in conjunction with the `-Wl,--gc-sections` linker flag. |
| 523 | Failing to use `-Wl,--gc-sections` will cause the former flags to *increase* |
| 524 | output size. The linker is only able to discard unused sections, so it can only |
| 525 | discard at per-function or per-variable granularity if each is in its own |
| 526 | section. |
| 527 | |
| 528 | While `-Wl,--gc-sections` should always be used, whether or not to enable |
| 529 | `-ffunction-sections` and `-fdata-sections` depends on how the object file being |
| 530 | compiled is expected to be used. If it will be used in a shared library then all |
| 531 | of its [public symbols] will be preserved and the additional overhead of placing |
| 532 | each item in its own section may make the shared library *larger* rather than |
| 533 | smaller. If it will be used only in a static library or an executable then it |
| 534 | will depend on how much of the resulting object file is expected to be unused. |
| 535 | |
| 536 | [public symbols]: #dependency-management |
| 537 | |
Dan Albert | f8ddc6b | 2021-09-22 16:02:43 -0700 | [diff] [blame] | 538 | #### RELR and relocation packing |
| 539 | |
| 540 | Note that each of the flags below will prevent the library or executable from |
| 541 | loading on older devices. If your `minSdkVersion` is at least the supported API |
| 542 | level, these flags are typically beneficial. A future release of the NDK will |
| 543 | likely enable this by default based on the `minSdkVersion` passed to Clang. See |
| 544 | [Issue 909] for more information. |
| 545 | |
| 546 | Beginning with API level 23 it is possible to compress the relation data in |
| 547 | libraries and executables. Libraries with large numbers of relocations will |
| 548 | benefit from this. Enable with `-Wl,--pack-dyn-relocs=android` at link time. |
| 549 | |
| 550 | API level 28 adds support for relative relocations (RELR) which can further |
| 551 | reduce the size of relocations. Enable with `-Wl,--pack-dyn-relocs=android+relr` |
| 552 | at link time. API levels 28 and 29 predate the standardization of this feature |
| 553 | in ELF, so for those API levels also pass `-Wl,--use-android-relr-tags` at link |
| 554 | time. |
| 555 | |
| 556 | [Issue 909]: https://github.com/android/ndk/issues/909 |
| 557 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 558 | ### Helpful Warnings |
| 559 | |
| 560 | It is recommended that build systems promote the following warnings to errors. |
| 561 | These warnings indicate either a bug or undefined behavior, the latter of which |
| 562 | Clang will usually turn into a bug. |
| 563 | |
| 564 | * `-Werror=return-type`: A non-void function is missing a return statement. |
| 565 | Clang may "optimize" this function to fall through into the next one. |
| 566 | * `-Werror=int-to-pointer-cast` and `-Werror=pointer-to-int-cast`: These |
| 567 | indicate bugs that will affect the 64-bit version of the application. |
| 568 | * `-Werror=implicit-function-declaration`: Undeclared functions may be inferred |
| 569 | to have a return type of `int` in C. For functions that return a pointer, the |
| 570 | return type will be silently truncated to a 32-bit `int`, resulting in bugs |
| 571 | that will affect the 64-bit version of the application. |
| 572 | |
| 573 | For more information on Clang's supported arguments, see the [Clang User |
| 574 | Manual]. |
| 575 | |
Dan Albert | ff3acaf | 2019-09-04 13:20:59 -0700 | [diff] [blame] | 576 | ### Hardening |
| 577 | |
Dan Albert | 9c6bc63 | 2019-09-18 14:51:01 -0700 | [diff] [blame] | 578 | #### Stack protectors |
| 579 | |
Dan Albert | ff3acaf | 2019-09-04 13:20:59 -0700 | [diff] [blame] | 580 | It is recommented to build all code with `-fstack-protector-strong`. This causes |
| 581 | the compiler to emit stack guards to protect against security vulnerabilities |
| 582 | caused by buffer overruns. |
| 583 | |
| 584 | Note: ndk-build and the NDK's CMake toolchain file enable this option by |
| 585 | default. |
| 586 | |
Dan Albert | 9c6bc63 | 2019-09-18 14:51:01 -0700 | [diff] [blame] | 587 | #### Fortify |
| 588 | |
| 589 | FORTIFY is a set of extensions to the C standard library that tries to catch the |
| 590 | incorrect use of standard functions, such as `memset`, `sprintf`, and `open`. |
| 591 | Where possible, runtime bugs will be diagnosed as errors at compile-time. If not |
| 592 | provable at compile-time, a run-time check is used. Note that the specific set |
| 593 | of APIs checked depends on the `minSdkVersion` used, since run-time support is |
| 594 | required. See [FORTIFY in Android] for more details. |
| 595 | |
| 596 | To enable this feature in your build define `_FORTIFY_SOURCE=2` when compiling. |
| 597 | |
| 598 | Note: ndk-build and the NDK's CMake toolchain file enable this option by |
| 599 | default. |
| 600 | |
| 601 | [FORTIFY in Android]: https://android-developers.googleblog.com/2017/04/fortify-in-android.html |
| 602 | |
Dan Albert | a79281a | 2022-10-13 16:31:52 -0700 | [diff] [blame] | 603 | ### Version script validation |
| 604 | |
| 605 | LLD will not raise any errors for symbols named in version scripts that are |
| 606 | absent from the library. This is either a mistake in the version script, or a |
| 607 | missing definition in the library. To have LLD diagnose these errors, pass |
| 608 | `-Wl,--no-undefined-version` when linking. |
| 609 | |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 610 | ## Common Issues |
| 611 | |
| 612 | ### Unwinding |
| 613 | [Unwinding]: #unwinding |
| 614 | |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 615 | The NDK uses LLVM's libunwind. libunwind is needed to provide C++ exception |
| 616 | handling support and C's `__attribute__((cleanup))`. The unwinder is linked |
| 617 | automatically by Clang, and is built with hidden visibility to avoid shared |
| 618 | libraries re-exporting the unwind interface. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 619 | |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 620 | Until NDK r23, libgcc was the unwinder for all architectures other than 32-bit |
| 621 | ARM, and even 32-bit ARM used libgcc to provide compiler runtime support. |
| 622 | Libraries built with NDKs older than r23 by build systems that did not follow |
| 623 | the advice in this document may re-export that incompatible unwinder. In this |
| 624 | case those libraries can prevent the correct unwinder from being used by your |
| 625 | build, resulting in crashes or incorrect behavior at runtime. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 626 | |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 627 | The best way to avoid this problem is to ensure all libraries in the application |
Dan Albert | 3cb2674 | 2023-05-02 18:04:22 -0700 | [diff] [blame] | 628 | were built with NDK r23 or newer, but even libraries built by older NDKs are |
| 629 | unlikely to have this problem. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 630 | |
Dan Albert | 3cb2674 | 2023-05-02 18:04:22 -0700 | [diff] [blame] | 631 | For build systems that want to protect their users against improperly built |
| 632 | libraries, read on. **Neither ndk-build nor CMake make this effort.** |
| 633 | |
| 634 | To protect against improperly built libraries, build systems can ensure that |
| 635 | shared libraries are always linked **after** static libraries, and explicitly |
| 636 | link the unwinder between each group. The linker will prefer definitions that |
| 637 | appear sooner in the link order, so libunwind appearing **before** the shared |
| 638 | libraries will prevent the linker from considering the incompatible unwinder |
| 639 | provided by the broken library. libunwind must be linked after other static |
| 640 | libraries to provide the unwind interface to those static libraries. |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 641 | |
| 642 | The following link order will protect against incorrectly built dependencies: |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 643 | |
| 644 | 1. crtbegin |
| 645 | 2. object files |
| 646 | 3. static libraries |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 647 | 4. libunwind |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 648 | 5. shared libraries |
| 649 | 6. crtend |
| 650 | |
| 651 | Unless using `-nostdlib` when linking, crtend and crtbegin will be linked |
Dan Albert | d471b92 | 2021-03-17 16:52:35 -0700 | [diff] [blame] | 652 | automatically by Clang. libunwind can be manually linked with `-lunwind`. |
Dan Albert | db23138 | 2018-09-07 16:33:36 -0700 | [diff] [blame] | 653 | |
| 654 | ## Windows Specific Issues |
| 655 | |
| 656 | ### Command Line Length Limits |
| 657 | |
| 658 | Command line length limits on Windows are short enough that they can pose |
| 659 | problems when building large projects. Commands executed via cmd.exe are limited |
| 660 | to [8,191 characters] and commands executed with `CreateProcess` are limited to |
| 661 | [32,768 characters]. |
| 662 | |
| 663 | To work around these issues, Clang, the linkers, and the archiver all accept a |
| 664 | response file that specifies the input files in place of specifying each input |
| 665 | explicitly on the command line. Response files are identified on the command |
| 666 | line with a "@" prefix and are formatted as space separated arguments. For |
| 667 | example: |
| 668 | |
| 669 | $ ar crsD liba.a @inputs.rsp |
| 670 | |
| 671 | If the contents of `inputs.rsp` are `a.o b.o c.o` then `ar` will insert `a.o`, |
| 672 | `b.o`, and `c.o` into `liba.a`. |
| 673 | |
| 674 | [8,191 characters]: https://support.microsoft.com/en-us/help/830473/command-prompt-cmd-exe-command-line-string-limitation |
| 675 | [32,768 characters]: https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa |
| 676 | |
| 677 | ### Path Length Limits |
| 678 | |
| 679 | Windows paths are limited to 260 characters, including the drive letter, colon, |
| 680 | backslash, and terminating null. See Microsoft's documentation on [path length |
| 681 | limits] for possible solutions. |
| 682 | |
| 683 | [path length limits]: https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation |
| 684 | |
| 685 | ### Performance Differences |
| 686 | |
| 687 | Our experience shows that builds on Windows are generally slower than they are |
| 688 | on Linux. The cost of `CreateProcess` in comparison to `fork` accounts for much |
| 689 | of the difference, so it is best to minimize process creation in your build |
| 690 | system. |
| 691 | |
| 692 | File system performance can also make a large difference. This also appears to |
| 693 | be the reason that Mac, while it has better build performance than Windows, |
| 694 | still underperforms Linux. |
| 695 | |
| 696 | Windows and Mac users will see optimum build performance in a Linux VM. |