英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论