Bazel 主机 (x86 linux) linkopts 传播到目标 (android)

Bazel host (x86 linux) linkopts propogating to target (android)

我有一个基于 bazel 的 c++ 项目,它使用了符合 proto_library 规则的原型。

我的 .bazelrc 有一个 android 配置,指定 android 配置(在 example here 之后)和

build:android_arm64 --cpu=arm64-v8a
build:android_arm64 --fat_apk_cpu=arm64-v8a
build:android_arm64 --crosstool_top=//external:android/crosstool
build:android_arm64 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain

protobuf BUILD 文件有一个 android 配置,它使用相同的 crosstool_top 值,它控制是否 link pthread 与 -lpthread (因为 libpthread.so 在 android 上不存在)。所以应该启用 android 配置。

如果我使用 bazel build :my_project_cc_binary --config=android_arm64 构建,我在 my_project_binary 的最后 link 步骤中收到关于 ld: cannot find -lpthread 的错误。因此看起来用于 protoc 主机二进制文件的 linkopts 的 //conditions:default 配置被添加到 android 目标的 linkopts。

据我了解,我的 android cc_binary 应该针对 libprotobuf linked 并且它是 linkopts。它不应该 link 反对 protoc 的 linkopts,即使它包含在依赖关系图中,因为主机需要构建和 运行 它来编译 protos。

我通过将 protobuf LINK_OPTS 中的 -lpthread 更改为 //conditions:default 的 -lnotareallibrary 来验证这一点,但我收到了一个错误。我可以确认 ndk 工具链二进制文件用于大多数规则,因此我相信 crosstool_top 设置正确。

为什么主机规则中的 linkopts 出现在我的 cc_binary 目标的 linkopts 中?需要构建主机工具的 android 目标不支持 cc_binary 吗?我也很好奇 android_binary 是否以某种方式解决了这个问题,但无法看到它是如何定义的。

# com_google_protobuf/BUILD
config_setting(
    name = "android",
    values = {
        "crosstool_top": "//external:android/crosstool",
    },
)
...
# Android and MSVC builds do not need to link in a separate pthread library.    
LINK_OPTS = select({                                                            
    ":android": [],                                                             
    ":android-libcpp": [],                                                      
    ":android-gnu-libstdcpp": [],                                               
    ":msvc": [                                                                  
        # Suppress linker warnings about files with no symbols defined.         
        "-ignore:4221",                                                         
    ],                                                                          
    "//conditions:default": [                                                   
        "-lpthread",                                                            
        "-lm",                                                                  
    ],                                                                          
})   
...
cc_binary(                                              
    name = "protoc",                                    
    srcs = ["src/google/protobuf/compiler/main.cc"],    
    linkopts = LINK_OPTS,                               
    visibility = ["//visibility:public"],               
    deps = [":protoc_lib"],                             
)                                                                                                                                  
                                                                                

我已经解决了这个问题。这里的问题不是关于 protoc/protobuf 的主机 linkopts,而是关于无条件使用 -lpthread 的另一个库 (gflags)。添加相同的 android 配置和 protobuf 使用的 select 语句修复了这个问题 (PR)。关于使用不存在的 -lnotareallibrary 的红鲱鱼是 protoc 的链接器错误,而不是我的目标可执行文件。

为了方便描述调试过程,我在自动生成的 bazel-myreponame/external 目录的 BUILD 文件和 .bzl 文件中搜索了 -lpthread。 (一开始只想着搜索BUILD文件,漏了这个库)