All Articles

Crashlytics NDK with Cmake

Crashlytics does not support NDK sources built with the “new” Cmake buildchain out of the box. This article explains why and how to get those native stack traces showing in Fabric.

Problem

First of all, the real problem is that the official guide is totally off and can’t be trusted. Seriously, it’s not mentioning that you need to add a dependency and the sample code isn’t even supported in the newest version. Maybe there’s a newer guide out there, but I couldn’t find it.

The other issue is that the Crashlytics NDK library depends on how the old ndk-build generated sources. The following structure is created when building with ndk-build:

app
└── src
    └── main
        ├── obj
        │   └── armeabi/x86/...
        └── libs
            └── armeabi/x86/...

The important directories are obj and lib where the built .so files are. The obj dir contains unstripped .so files with debug info intact, lib contains stripped files that are included in the .apk. Unfortunately the new Cmake buildchain does not have the same structure, so the Crashlytics symbol upload Gradle task can’t find them.

Here’s where the equivalent built files are placed when using cmake:

app
└── build
    └── intermediates
        ├── cmake
        │   └── release
        │       └── obj
        │           └── armeabi/x86/...
        └── bundles
            └── default
                └── jni
                    └── armeabi/x86/...

The obj dir contains built .so files with unstripped debug symbols and jni dir the stripped files. The directories are quite different, so we need to instruct Crashlytics of where to find them.

Solution

Github: build.gradle

Fortunately Cmake saves the unstripped libs as well and of course the stripped also, we just need to make Crashlytics able to locate them. Weird thing is, the dependency isn’t at all mentioned in the official guide, I found it by chance when Googling around after what felt like forever(!)

  1. Add (the secret) crashlytics ndk dependency

    compile('com.crashlytics.sdk.android:crashlytics-ndk:1.1.6@aar') {
      transitive = true
    }
    
  2. Add this closure to your build.gradle as well (the guide mentions deprecated “baseManifestPath”, ignore that)

    crashlytics {
      enableNdk true
      androidNdkOut 'build/intermediates/cmake/release/obj'
      androidNdkLibsOut 'build/intermediates/bundles/default/jni'
    }
    

Those are the correct folders right there. And the dependency that isn’t mentioned as needed in the guide, it took me forever to find it, no joke.

Aftermath

I’ve verified that it works by a manual throw in our JNI library. Crashlytics is able to proberly show a sane stack trace (actually better than JNI traces in Android Studio!)

Code hard.

Published 2 Jun 2017