Introducing Android Native Development Kit r16

Posted by Dan Albert, Android NDK Tech Lead

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

NDK r16 is a big milestone for us, because it's the first release that we're
ready to recommend that people start migrating to libc++! More on this later.

We've also updated libc++ and its related projects, so this release has improved
support for C++1z. Keep in mind that until C++1z becomes C++17, everything
included is subject to change.

You can find the release notes for this release here.

libc++ and libandroid_support

The NDK has a library called libandroid_support that backports libc APIs that
libc++ depends on that weren't available on older releases. The reason we've
been unable to endorse libc++ (as implemented in the NDK) until now has been a
lack of confidence in this library. The focus of r16 was to rewrite this library
for improved stability.

Since libandroid_support is now a smaller library, your app's behavior should
more closely match the behavior of the system. As an example, libandroid_support
previously included an alternative implementation of part of stdio. While some
features got backported to ICS, it also meant that any bugs in the alternate
implementation would be present on all OS releases since the bug was
baked into your app. In the new version of libandroid_support, we've removed
this so you'll be missing some features on older devices (almost exclusively
things that no one uses, like %a support in format strings), but
your apps using libc++ will be smaller and more reliable for not having these

Switching to libc++

So, why should you switch to libc++? First and foremost, the other STLs will not
be supported going forward (this has been noted in our roadmap
for quite some time). We've been using libc++ for the Android platform since
Lollipop, and that's been a change that our engineers have been overwhelmingly
happy with. We were able to make this transition in the platform earlier than we
could in the NDK because we didn't need libandroid_support, and could instead
just update libc in place.

In contrast to the other STLs currently available in the NDK, libc++ fully
supports C++11, C++14, and most of C++1z! Stlport hasn't had an update since
2008, and gnustl (what we call GNU's libstdc++, to avoid confusion with Bionic's
libstdc++, which isn't an STL) historically hasn't worked very well with Clang,
particularly in headers that are closely tied to compiler builtins like
<atomic> and <type_traits>.

We'll most likely be making libc++ the default in the next NDK release, but for
now you can opt-in if you're not using it already by following the instructions

Like the other STLs, libc++ is available as both a static and shared library.
Which one you should use depends on your specific circumstances as described in
, but tl;dr use the static version if you have one and only one shared
library in your application, and use the shared one in all other cases.


Add the following to your file:

APP_STL := c++_shared


Pass the following when invoking CMake:


If you're using CMake via Gradle, add the following to your build.gradle:

externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"

Standalone Toolchain

When you create your standalone toolchain, pass --stl=libc++.

The Future of libandroid_support

If you've read our
, you've seen that we've planned to expand libandroid_support to
backport as much of libc/libm as possible. Whenever we've spoken with people
about this, we've received lukewarm responses at best. Given that this doesn't
seem to be a thing that people are interested in, and that it would be something
that increases library size (and therefore APK size, which is something
everyone seems very interested in), we no longer plan to do this.

If we've misinterpreted your response or if we haven't heard from you and this
is something you want, please let us know!


tl;dr: Don't set _FILE_OFFSET_BITS=64 if you want to keep the
behavior present in old NDKs.

Historically, setting _FILE_OFFSET_BITS=64 in the NDK did nothing.
This feature was not present in the deprecated headers at all. With unified
headers, the NDK now has up to date headers with support for this feature.

_FILE_OFFSET_BITS=64 is a macro you can define in your application
to get support for a 64-bit off_t in 32-bit code. This works by
both making off_t 64-bit (by default it is 32-bit in 32-bit code)
and by implicitly replacing calls to APIs like lseek with calls to

Support for _FILE_OFFSET_BITS=64 was not added to Android in a
single release. One API, lseek64, has always been in bionic. Most
APIs were added in Lollipop, and a few more were not added until later releases.

If you're targeting a release that does not support the 64-bit
off_t variant of a function you are using and have set
_FILE_OFFSET_BITS=64, the function will not be available. This is
in contrast to the behavior for r15 and r15b (but matches r15c) where the
functions were wrongly exposed with a 32-bit off_t that would be
silently truncated.

Note that the 64-bit off_t APIs are still available without
_FILE_OFFSET_BITS=64 under different names. For example, instead of
lseek, call lseek64. Instead of off_t,
use off64_t.

Finally, since this feature is new to the NDK with unified headers, if you just
want to return to the pre-unified headers behavior, all you need to do is stop
setting _FILE_OFFSET_BITS=64.

For more information about off_t ABI details in bionic, see the Bionic
32-bit ABI bugs doc

Related Posts

Subscribe Our Newsletter