Link statically libc++ when building with Bazel using Android NDK

192 Views Asked by At

I have a very simple C++ library that uses RTTI and I want to build on Android using NDK 21 and Bazel.

Here is my Bazel script:

load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
    name = "test",
    srcs = glob(["**/*.cpp"]) + glob(["**/*.hpp"]),
    hdrs = glob(["**/*.hpp"]),
)

My WORKSPACE file contains:

android_ndk_repository(
    name = "androidndk", # Required. Name *must* be "androidndk".
    api_level = 29,
)

I am trying to crosscompile for Android arm64 using platforms:

bazel build --platforms=@io_bazel_rules_go//go/toolchain:android_arm64_cgo --extra_toolchains=@androidndk//:all //...

Thia builds fine however my libtest.so depends on libc++_shared.so (I am using readelf -d libtest.so to verify this).

How can link statically so to not need distribute libc++_shared.so?

1

There are 1 best solutions below

1
Ondrej K. On

There isn't really an exactly trivial way to accomplish what you are asking for, inclusion of C++ standard library would be generally governed by cc toolchain configuration. This may deviate for Android tooling I am not familiar with (I presume @androidndk// also defines cc_toolchain), but the auto-resolved GCC bazel configures on Linux would in its default state ultimately end up calling gcc to link and adding -libc++ via default_link_libs feature.

The sort of quick and dirty option would be to turn that feature off on targets that should not link against libstdc++ solib:

features = ["-default_link_libs"],

Or you could do that per package or build wide with command line flag --features -default_link_libs. But then you would have to "reassemble" flags to add now missing libs with a desired twist, e.g. for per target option:

    linkopts = [
        "-l:libstdc++.a",  # use static archive
        "-lm",             # the default auto-resolved tc would add libm to link at this point
    ],

This does seem very clean to me though, I would say it's fragile and error prone, also not exactly well maintainable. A custom toolchain with corresponding features to govern use of C++ standard lib as desired either across the board or configurable per target would appear as the better long term option, even though it does come at higher initial cost.

Disclaimer: I am not familiar with for Android builds using bazel, just bazel and "plain" (cross-)build, but assuming general concepts carry across, I hope this still provides some helpful hints.