Bazel: Android target for a _transitive closure_ library aar

Created on 29 Jul 2015  路  20Comments  路  Source: bazelbuild/bazel

One of my work projects is an Android library with a substantial JNI footprint, designed for inclusion in third-party Android apps. I'd love to be able to specify it as a single bazel target (say for an aar, which seems to be what the Android people want us to generate these days) that depends on my android_library and cc_library.

My current planned stopgap is to build an android_binary and then take the .jar and .so out of the target for redistribution. Improvements and suggestions welcome.

P2 team-Android feature request

Most helpful comment

@jcayzac , please file a separate issue. If I understand what you mean, that is probably a much easier problem to solve. The JNI issue is a little tricky because at the moment android_library doesn't do any linking.

All 20 comments

android_library has an implicit AAR output called name.aar.

As an example,

$ cat java/com/foo/BUILD
cc_library(
    name = "cc_lib",
    srcs = ["foo.cc"],
)
android_library(
    name = "android_lib",
    srcs = ["Foo.java"],
    deps = [":cc_lib"],
)
$ bazel build //java/com/foo:android_lib.aar
INFO: Found 1 target...
Target //java/com/foo:android_lib.aar up-to-date:
  bazel-bin/java/com/foo/android_lib.aar
INFO: Elapsed time: 4.138s, Critical Path: 3.59s
$

Augh, I should not have closed this. Per the documentation of android_library:

name.aar: An android 'aar' bundle containing the java archive and resources of this target. It does not contain the transitive closure.

https://bazel.build/versions/master/docs/be/android.html#android_library

So the .aar output of android_library will not contain the .so from the cc_library.

I'm going to use this as the tracking bug for support transitive-closure-aars from android_library.

This would also be useful for TensorFlow so that we can build a full Android distributable in a single file (using only Bazel) during our nightly build process.

edit: We'd like to be able to package all relevant architectures in the same AAR, much like --fat_apk_cpu packages multiple target architectures in APKs.

+1. Any update of expected support for this?

We're working on getting our testing for android apps in better shape, this is something we'll likely work on after that.

hey guys, i'm having another issue: the cc_library on which my android_library depends is not built when building via name.aar.
And when I build via name, it seems it is not built for the android ndk (unable to include jni.h, for instance)

+1

Use sample in https://github.com/spinorx/grpc_andr_ios to unblock urself till this is fixed.

@spinorx thank you very much. I can build the app using the provided project, but the android_library target (eg. bazel build --config android //android:GreeterClient) won't build in this example either.

Yeah, android_library does not propogate needed config to cc_library yet. See detailed discussion in: https://github.com/bazelbuild/bazel/issues/3924

@steeve, see my response in https://github.com/bazelbuild/bazel/issues/4407#issuecomment-356658776 if you want to build the cc_library for Android directly. Note that that will not get you a .so. To build a .so outside of android_binary, you need a cc_binary.

@aj-michael thanks! however, I'm trying to build an aar (not an apk) file that depends on the cc_library.
I would assume the toolchain configuration to be transitive to the cc_library with android_library the way android_binary does.

Also, there is the case of fat apks, which is better handled by building for the Android env via android_{binary,library} rules imho.

Yes, I was responding to your comment:

And when I build via name, it seems it is not built for the android ndk (unable to include jni.h, for instance)

android_library .aar output does not currently support bundling native libraries. This is a known deficiency that I believe @dkelmer has plans to work on.

If you're so inclined, you could workaround this deficiency by creating an additional android_binary and a genrule for the android_library, something like this:

genrule(
    name = "aar_with_jni",
    srcs = [
        ":abin_unsigned.apk",
        ":alib.aar",
    ],
    outs = ["alib_with_jni.aar"],
    cmd = """
cp $(location :alib.aar) $(location :alib_with_jni.aar)
chmod +w $(location :alib_with_jni.aar)
origdir=$$PWD
cd $$(mktemp -d)
unzip $$origdir/$(location :abin_unsigned.apk) "lib/*"
cp -r lib jni
zip -r $$origdir/$(location :alib_with_jni.aar) jni/*/*.so
""",
)

android_binary(
    name = "abin",
    manifest = "AndroidManifest.xml",
    custom_package = "does.not.matter",
    deps = [":alib"],
)

android_library(
    name = "alib",
    srcs = ["A.java"],
    deps = [":clib"],
)

cc_library(
    name = "clib",
    srcs = ["c.cc"],
)

nice, I hadn't though about this! thanks @aj-michael

This is a common enough request (JNI in .aar) that I decided to throw together an example repository for how to workaround it:

https://github.com/aj-michael/aar_with_jni

FWIW you can just use zip -ur to add files to an existing archive (we do this to create the TensorFlow AAR for release), no need to unzip first.

@aj-michael adding to this discussion, in my understanding the aar produced by bazel are also "incomplete" in the sense there is no (obvious) way to specify a _consumer_ proguard file yet.

Should I file a separate issue for this, or better keep it here together with the related jni problem?

@jcayzac , please file a separate issue. If I understand what you mean, that is probably a much easier problem to solve. The JNI issue is a little tricky because at the moment android_library doesn't do any linking.

Ran across this while looking for a workaround for our team. Can confirm that there are still people who'd use this :) (looks like Tensorflow/MediaPipe are also using AJ's good workaround.)

Any updates on official support?

Once starlark rules_android lands (they are in alpha iirc), it'll be much easier to add it

Was this page helpful?
0 / 5 - 0 ratings