Android + Bazel + OpenCV

I’ve been tinkering with the Guillemot Sensor app lately, trying to get OpenCV for Android SDK0 integrated, after having switched to Bazel1 because Gradle is annoying.

Overall I’m liking Bazel a lot! I can reference my other repos directly which means no more Maven packaging nightmares. It’s fast. It makes sense. The only thing I’m still working out is how to make Android Studio just be an editor and stop bothering me about Gradle all the time.

I used the OpenCV for Android SDK with Eclipse way back while working on my masters thesis and I remember it took awhile to get all the settings just right, but then it was pretty nice. The nice thing about Bazel is once you figure out how to get OpenCV pulled in then it’s one of those things you can just commit and never worry about ever again. I thought I’d share my approach and BUILD files so that everyone else can hopefully never worry about it ever again.

Basic SDK Setup

I searched for “android opencv bazel” and found a thing on Stack Overflow2 It’s not specific to Android but kind of gives a lead for compiling from source which sounds hard. I tinkered with it for a bit and decided I’d rather try something more like the old Eclipse setup using the provided SDK download.

The SDK approach worked great! I made an android_library target called “sdk” depending on a cc_library target called “jni”. It’s easy enough to point those to their respective source files. The only tricky part was configuring the .aidl stuff.

I could bazel build @org_opencv//:sdk and everything Just Worked. Yay!

Sample Projects

The SDK also comes with a handful of example Android apps, some of which use NDK. All the pure-Java ones were really easy to setup; I even made a “sample” macro for them. But the apps using NDK were a bit more tricky.

For some reason, the .apk artifacts didn’t include any .so files? Maybe I was doing something wrong? After searching a bit more I found out there’s a secret argument for android_binary called legacy_native_support which, if set to 0, does cause a .so file to get packaged.

Next hurdle was the .so file was named wrong. Apparently it’s impossible to control its name except for changing the name of the android_binary target so that’s what I did. Only other option would be to somehow modify the source of the SDK samples which is out of the question.

Last hurdle was something to do with how the name mangling works between Bazel and the OpenCV Manager thing meant that none of the NDK code worked. If you include the correct .so files as part of the “jni” cc_library then those work. Only downside is each app includes its own copy of the OpenCV runtime; this was maybe a problem in the early days of Android but it’s definitely not a problem for me. It’s actually kind of nice to not have to deal with the separate Manager app.

TL;DR

Ha OK so I told my long boring story but where are the files!? I’ve hosted them on github in a new “bazel” repo. I suppose I’ll use it to share other Bazel tricks if/when I figure them out. Enjoy!

https://github.com/chris-blay/bazel