Introducing Android Native Development Kit r14

Posted by Dan Albert, Android NDK Tech Lead

Android NDK r14


The latest version of the Android Native Development Kit (NDK), Android NDK r14, is now available for download. It is also available in the SDK manager via Android Studio.

So what's new in r14? The full changelog can be seen here, but the highlights include the following:
  • Updated all the platform headers to unified headers (covered in detail below)
  • LTO with Clang now works on Darwin and Linux
  • libc++ has been updated. You can now use thread_local for statics with non-trivial destructors (Clang only)
  • RenderScript is back!

Unified Headers

We've completely redone how we ship platform header files in the NDK. Rather than having one set of headers for every target API level, there's now a single set of headers. The availability of APIs for each Android platform is guarded in these headers by #if __ANDROID_API__ >= __ANDROID_API_FOO__ preprocessor directives.

The prior approach relied on periodically-captured snapshots of the platform headers. This meant that any time we fixed a header-only bug, the fix was only available in the latest version aside from the occasional backport. Now bugfixes are available regardless of your NDK API level.

Aside from bugfixes, this also means you'll have access to modern Linux UAPI headers at every target version. This will mostly be important for people porting existing Linux code (especially low-level things). Something important to keep in mind: just because you have the headers doesn't mean you're running on a device with a kernel new enough to support every syscall. As always with syscalls, ENOSYS is a possibility.

Beyond the Linux headers, you'll also have modern headers for OpenGL, OpenSLES, etc. This should make it easier to conditionally use new APIs when you have an older target API level. The GLES3 headers are now accessible on Ice Cream Sandwich even though that library wasn't available until KitKat. You will still need to use all the API calls via dlopen/dlsym, but you'll at least have access to all the constants and #defines that you would need for invoking those functions.
Note that we'll be removing the old headers from the NDK with r16, so the sooner you file bugs, the smoother the transition will go.

Caveats

The API #ifdef guards do not exist in third-party headers like those found in OpenGL. In those cases you'll receive a link time error (undefined reference) rather than a compile time error if you use an API that is not available in your targeted API level.

Standalone toolchains using GCC are not supported out of the box (nor will they be). To use GCC, pass -D__ANDROID_API__=$API when compiling.

Enabling Unified Headers in Your Build

To ease the transition from the legacy headers to the unified headers, we haven't enabled the new headers by default, though we'll be doing this in r15. How you opt-in to unified headers will depend on your build system.

ndk-build


In your Application.mk:

    APP_UNIFIED_HEADERS := true
You can also set this property from the command-line like this:

    $ ndk-build APP_UNIFIED_HEADERS=true

If you're using ndk-build via Gradle with externalNativeBuild, specify the following configuration settings in build.gradle:

    android {
      ...
      defaultConfig {
        ...
        externalNativeBuild {
          ndkBuild {
            ...
            arguments "APP_UNIFIED_HEADERS=true"
          }
        }
      }
    }

CMake

When configuring your build, set ANDROID_UNIFIED_HEADERS=ON. This will usually take the form of invoking CMake with cmake -DANDROID_UNIFIED_HEADERS=ON $OTHER_ARGS.

If you're using CMake via Gradle with externalNativeBuild, you can use:

    android {
      ...
      defaultConfig {
        ...
        externalNativeBuild {
          cmake {
            ...
            arguments "-DANDROID_UNIFIED_HEADERS=ON"
          }
        }
      }
    }

Standalone Toolchains

When creating your standalone toolchain, pass --unified-headers. Note that this option is not currently available in the legacy script, make-standalone-toolchain.sh, but only in make_standalone_toolchain.py.

Experimental Gradle Plugin

Coming soon! Follow along here.

Custom Build System?

We've got you covered. Instructions on adding support for unified headers to your build system can be found here.

For additional information about unified headers, see our docs and the tracking bug. If you're looking ahead to future releases, the most up-to-date version of the documentation is in the master branch.