Skip to main content
Skip table of contents

Android C++ Standard Library

The VeridiumID Mobile SDK includes components written in C++ and built with the Android NDK. If you have multiple C++ dependencies your app must include one version of the C++ standard library, provided by the Android NDK, that is compatible with them all.

Background: C++ Standard Library

Android requires that the C++ standard library, libc++, is distributed with your app as it is not part of the OS. You can only have one instance of the C++ standard library linked into a program. The best option is to use the shared variant of libc++, referred to by the NDK as c++_shared.

[The other alternative, using c++_static, is problematic unless the app includes exactly one C++ shared library; each shared library would link in the static C++ standard library, and so end up duplicating it]

Pitfalls

When building with Android Studio, the build process collects all C++/native libraries to bundle into the APK. If there are multiple copies of libraries with same filename, it may error out or pick one of them arbitrarily. It also can strip the standard library to remove unused symbols to reduce code size. This can cause incompatibilities to arise, where libraries refuse to load with unresolved symbol errors.

Android NDK r23b introduced a backward compatibility breakage. C++ components built with r23b or later may fail to link to older versions of the standard library (forwards compatibility is unaffected). If a dependancy, other than the Veridium SDK, includes the C++ shared library from an older NDK it can be arbitrarily included and cause a missing symbol error when initialising the Veridium SDK.

Troubleshooting

Scanning the app’s APK dependencies using this python script version_check.py will provide a list of native libraries and identify those causing compatibility issues.

Solutions

1. Update Dependencies

The most effective solution is to update dependencies to versions that use r23b or later. As r23b is from 2021, it is likely there are newer builds available.

2. Use a Build Task to Replace libc++_shared.so

As part of the Gradle build tree for android apps (as provided by the Gradle plugin 'com.android.application') the task merge<buildType>NativeLibs, where <builtType> is the name of the selected build type, complies together all native libraries. We can add a finaliser task using finalizedBy() to copy a version of libc++_shared.so to /intermediates/merged_native_libs/.

Edit the app’s build.gradle, The example below has two build types, release and debug, and so configures two tasks; mergeReleaseNativeLibsand mergeDebugNativeLibs. (You can observe the list of tasks in Android Studio in the Gradle tab). We add a finaliser task replaceStdLib() to each merge task that copies the contents of stdlib_nkd\ placed one directory up from the build directory.

GROOVY
apply plugin: 'com.android.application'
android {
  buildTypes {
    debug { ... }
    release { ... }
  }
}

task replaceStdLib {
    def destDir = file("$buildDir/intermediates/merged_native_libs/")
    inputs.dir("$buildDir/../stdlib_nkd")
    inputs.dir("$buildDir/intermediates/merged_native_libs/")
    doLast {
        copy {
            from(fileTree("$buildDir/../stdlib_nkd").include('**/*.so'))
            into destDir
        }
        logger.lifecycle("Merged NDK libc++_shared.so to $destDir")
    }
}

afterEvaluate { evaluated ->
    evaluated.tasks.findByName("mergeReleaseNativeLibs").finalizedBy('replaceStdLib')
    evaluated.tasks.findByName("mergeDebugNativeLibs").finalizedBy('replaceStdLib')
}
gradle_tasks.png

Android Studio - Gradle task list

stdlib_ndk.png

Directory structure of stdlib_ndk

stdlib_nkd\ can contain libc++_shared.so files taken directly from the Android NDK installation at [ndk/<version>/sources/cxx-stl/llvm-libc++/libs/], but Veridium can provide this on request. The folder should be organised to reflect the structure of $buildDir/intermediates/merged_native_libs/, hence should contain folders with your build type names.

Note, the NDK libraries include all symbols, including debug symbols. Unnecessary symbols will be stripped when the app apk is constructed later in the build process (depending on your configuration).

3. Manually strip libc++_shared.so

Manually remove libc++_shared.so from all dependency .aar files and instead include libc++_shared.so via a “dummy“ C++ library.

Change the extension of veridium-core-release.aar to .zip, extract the contents, remove every instance of libc++_shared.so, then re-zip it and change the extension back to .aar. Remove any included libc++_shared.so from third-party .aar dependencies using the same method.

Configure your own C++ libraries

Any C++ libraries you build as part of your Android Studio project must link with c++_shared rather than the default c++_static. The NDK has documentation for this, but in summary:

CMake

The section of the Gradle file which invokes CMake should set the ANDROID_STL variable.

CODE
externalNativeBuild {
    cmake {
        arguments '-DANDROID_STL=libc++_shared‘
        cppFlags ''
    }
}

ndk-build

Set APP_STL in the http://Application.mk file:

CODE
APP_STL := c++_shared

Create a 'dummy' C++ library

If you're not already building your own C++ library, you can create an empty C++ library in Android Studio and configure it as described in the previous section; this will cause Android Studio to bundle libc++_shared.so into the app.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.