| # When to use which `#define` | |
| Using `#ifdef` or equivalents is common when writing portable code. Which to use | |
| when can be quite tricky. This document describes the most common choices | |
| related to Android. | |
| ## `__BIONIC__` | |
| If your code is specific to Android's C library, bionic, use `__BIONIC__`. This | |
| is typically a good choice when you use libc API that's only in bionic, such as | |
| the system property functions. Common alternatives on this dimension are | |
| `__GLIBC__`, `__APPLE__`, or `_WIN32`. Note that although bionic is most often | |
| seen on Android devices, it is possible to use bionic on the host too. | |
| (Note that though `__APPLE__` and `_WIN32` are defined by the compiler, | |
| both `__BIONIC__` and `__GLIBC__` are defined by <sys/cdefs.h>, | |
| which you should include before testing either of these.) | |
| ## `__ANDROID__` | |
| If your code is specific to Android devices, use `__ANDROID__`. This isn't | |
| useful as you might think, and one of the other choices on this page is usually | |
| more appropriate. This is typically a good choice if you have code that's part | |
| of the OS and needs to behave differently on the host than on the device. | |
| Genuine cases are quite rare, and `__BIONIC__` is often more specific (but | |
| remember that it is possible -- if unusual -- to use bionic on the host). | |
| (This is defined by the compiler.) | |
| ## `ANDROID` (rarely useful) | |
| Not to be confused with `__ANDROID__`, the similar-looking but very different | |
| `ANDROID` is _not_ set by the toolchain or NDK build system. This is set by | |
| the AOSP build system for both device and host code. For that reason, it's | |
| not typically very useful except as a signal when patching third-party code --- | |
| but even then, you'd typically _not_ want this because it's true for both | |
| device and host. | |
| ## `__ANDROID_API__` | |
| If your code can be built targeting a variety of different OS versions, use | |
| `__ANDROID_API__` to test which version you're building against. This is | |
| typically useful if you can use new NDK APIs when available, but don't require | |
| them if not. | |
| One thing to note (if your code may also be built as part of the OS itself) is | |
| that for most of the year, the OS builds with this set to 10,000 rather than the | |
| obvious "next" API level such as 19. Once the API level has been decided, the | |
| value of `__ANDROID_API__` drops to that number. | |
| (This is defined by the compiler, based on the api level in your target triple.) | |
| ## `__linux__` | |
| If your code requires a Linux kernel, use `__linux__`. This is typically a good | |
| choice when you use Linux-specific API, such as a Linux-specific system call or | |
| a file in `/proc`, but aren't restricted to just Android and would work equally | |
| well on a desktop Linux distro, say. Common alternatives on this dimension | |
| are `__APPLE__` or `_WIN32`. | |
| (This is defined by the compiler.) | |
| ## `__ANDROID_NDK__` | |
| If your code can be built either as part of an app _or_ as part of the OS | |
| itself, use `__ANDROID_NDK__` to differentiate between those two circumstances. | |
| This is typically a good choice when your code uses non-NDK API if it's built as | |
| part of the OS, but sticks to just the NDK APIs otherwise. | |
| (This is available after including <sys/cdefs.h> directly or transitively.) | |
| ## `__NDK_MAJOR__`, `__NDK_MINOR__`, `__NDK_BETA__`, `__NDK_BUILD__`, `__NDK_CANARY__` | |
| If your code can be built with a variety of different NDK versions, and needs to | |
| work around issues with some of them, use these macros to detect the version of | |
| the NDK you're being built with. Usually only `__NDK_MAJOR__` will be necessary. | |
| (These are available after including <sys/cdefs.h> directly or transitively.) | |
| ## `__arm__`/`__aarch64__`, `__i386__`/`__x86_64__`, `__riscv` | |
| If your code is specific to a particular processor architecture, use | |
| these macros to conditionally compile. Note that the ABI usually called | |
| `arm64` uses the macro `__aarch64__` and the ABI usually called `x86` uses | |
| `__i386__`. Android only supports riscv64, so `__riscv` is a sufficient | |
| check for Android-only code. If you need to write code portable to other | |
| operating systems that do support riscv32, you'll also need to check | |
| whether `__riscv_xlen` is 32 or 64. | |
| (These are defined by the compiler.) | |
| ## `__ILP32__` and `__LP64__` | |
| If your code depends on "bitness" -- whether `long` and pointers are 32- | |
| or 64-bit -- use these macros to conditionally compile. Note the extra | |
| "I" in the 32-bit macro (since `int`, `long`, and pointers are all 32-bit | |
| on such systems, with `long long` being needed for a 64-bit type). | |
| (These are defined by the compiler.) |