blob: 1668a7c40c4854acd25df72adfe8a39ee87e44b5 [file] [view]
# 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.)