bazelbuild / rules_android_ndk

Apache License 2.0
32 stars 15 forks source link

Cross compilation issues with FFMPEG with Android #39

Closed ankit-agarwal-ai closed 7 months ago

ankit-agarwal-ai commented 1 year ago

Hi, all.

I am cross compiling android apps with the following bazel rc flags:

build --incompatible_enable_android_toolchain_resolution=true
# Use the following for building for actual device
build --android_platforms=//:arm64-v8a

working off of what is essentially bazel latest (but I was able to repro on bazel 6). Note that //:arm64-v8a is basically the same as the android pre-defined platforms.

I am noticing an issue when I try and compile an android binary with the following maven dependency:

        "com.arthenica:mobile-ffmpeg-min:4.4",

Specifically, this specific command fails with this error:

bazel-out/k8-opt-exec-2B5CBBC6/bin/external/bazel_tools/tools/android/aar_native_libs_zip_creator --input_aar external/maven/v1/https/repo1.maven.org/maven2/com/arthenica/mobile-ffmpeg-min/4.4/mobile-ffmpeg-min-4.4.aar --cpu k8 --output_zip bazel-out/android-arm64-v8a-fastbuild/bin/external/maven/_aar/com_arthenica_mobile_ffmpeg_min/native_libs.zip

with error:

AAR external/maven/v1/https/repo1.maven.org/maven2/com/arthenica/mobile-ffmpeg-min/4.4/mobile-ffmpeg-min-4.4.aar missing native libs for requested architecture: k8

It looks like the offending line is the --cpu k8, and indeed when I cd'd into the bazel sandbox and ran the command with --cpu arm64-v8a it ran without error. I tracked down the offending line to:

https://github.com/bazelbuild/bazel/blob/224d642a165c16eb0688168e2510b35c9beb5ef0/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java#L440

My code does work with:

build --fat_apk_cpu arm64-v8a
build --android_crosstool_top=@androidndk//:toolchain

However, I'd like to use android platforms since my specific application shares code with native C++ libraries that use the platforms and its a lot easier to specify a new platform os than to configure on the cpu values. If there is an analog of the platform_mappings API for android that would be good as well. For now I have a workaround, but if there's an easy way to fix this, I'd be happy to take on fixing this myself with some guidance!

Thanks :)

cpsauer commented 1 year ago

Ankit, if useful, we're currently using the following platform_mappings to get things working with Android until platforms support arrives:

//platform_mappings

flags:
    # Android
    # Mostly, native code is compiled after the android_binary rule has run a transition to compile for that platform.
    # We just detect the transition, which sets "Android configuration distinguisher", and then translate the CPU it set.
    --Android configuration distinguisher=android
    --cpu=arm64-v8a
        //Bazel/Platforms:_android-arm64
    --Android configuration distinguisher=android
    --cpu=armeabi-v7a
        //Bazel/Platforms:_android-armv7
    --Android configuration distinguisher=android
    --cpu=x86_64
        //Bazel/Platforms:_android-x86_64
    --Android configuration distinguisher=android
    --cpu=x86
        //Bazel/Platforms:_android-x86_32

//Bazel/Platforms/BUILD

# Grind through the full cartesian product of OS<>CPU, so we have the combinations available for easy use.
# config_setting()s allows easy use in select(). (Annoyingly, platforms can't be used in select(). See https://github.com/bazelbuild/bazel/issues/15575)
# List comprehension works around the lack of for loops at the top level in Starlark.
# Floated making these an official part of platforms here: https://github.com/bazelbuild/platforms/issues/36
[(
    config_setting(
        name = os + "-" + arch,
        visibility = ["//visibility:public"],
        constraint_values = [
            "@platforms//os:" + os,
            "@platforms//cpu:" + arch,
        ]
    ),
    platform( # Please don't use these outside of //platform_mappings. See that file for more details on the implementation that configures the built-in platform flags.
        name = "_" + os + "-" + arch,
        constraint_values = [
            "@platforms//os:" + os,
            "@platforms//cpu:" + arch,
        ]
    )
)
for os in ["android", "ios", "macos"] for arch in ["arm64", "armv7", "x86_64", "x86_32"]]
# ^ If you're getting errors around aarch64 not matching arm64, despite aarch64 being a deprecated alias for arm64, some dependency has dragged in an ancient version of platforms. See https://github.com/bazelbuild/bazel/issues/14605
ankit-agarwal-ai commented 1 year ago

Looks like this worked for us! Thank you :)

cpsauer commented 1 year ago

Yay! Delighted to hear it.

ankit-agarwal-ai commented 10 months ago

Hey @cpsauer we migrated to use android platforms with the latest release (since according to https://blog.bazel.build/2023/11/15/android-platforms.html it is supported) and this issue seems to still show up. I'm curious as to why it is not working. Specifically we are still seeing aar_import fail. Will we still need to wait for rules_android to be complete in order to enable it?