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

huangapple go评论71阅读模式
英文:

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

问题

我有一个非常简单的C++库,使用RTTI,并且我想使用NDK 21和Bazel在Android上构建。

这是我的Bazel脚本:

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

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

我的WORKSPACE文件包含:

android_ndk_repository(
    name = "androidndk", # 必须的。名称必须是 "androidndk"
    api_level = 29,
)

我正在尝试使用以下平台交叉编译为Android arm64:

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

这个构建是可以的,但是我的 libtest.so 依赖于 libc++_shared.so(我使用 readelf -d libtest.so 来验证这一点)。

如何进行静态链接,以便不需要分发 libc++_shared.so

英文:

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

得分: 1

没有确切的简单方法来实现你所要求的,包含C++标准库通常由cc工具链配置控制。对于我不熟悉的Android工具链(我假设@androidndk//也定义了cc_toolchain),可能会有所偏差,但Linux上自动解析的GCC bazel配置在默认状态下最终会调用gcc进行链接,并通过default_link_libs功能添加-libc++

一种快速而不太干净的选项是在不应链接到libstdc++ solib的目标上关闭该功能:

features = ["-default_link_libs"],

或者你可以使用命令行标志--features -default_link_libs来为每个包或整体构建执行此操作。但然后你需要“重新组装”标志,以添加现在缺少的库,并进行所需的调整,例如,对于每个目标选项:

    linkopts = [
        "-l:libstdc++.a",  # 使用静态存档
        "-lm",             # 默认自动解析的tc会在这一点添加libm链接
    ],

尽管这对我来说看起来不太干净,我会说它很脆弱且容易出错,而且不容易维护。一个具有相应功能的自定义工具链,可以跨目标配置以按需使用C++标准库,似乎是更好的长期选择,尽管它的初始成本较高。

免责声明:我不熟悉使用bazel进行Android构建,只熟悉bazel和“普通”的(跨平台)构建,但假设一般概念仍然适用,我希望这仍然提供了一些有用的提示。

英文:

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.

huangapple
  • 本文由 发表于 2023年7月18日 04:57:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76708017.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定