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

Viewed 230

I have a bazel-based c++ project that has uses protos with the proto_library rule.

My .bazelrc has an android config that specifies an android config (following the example here) with

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

The protobuf BUILD file has an android config that uses the same crosstool_top value, which controls whether or not to link pthread with -lpthread (since libpthread.so doesn't exist on android). So the android config should be enabled.

If I build with bazel build :my_project_cc_binary --config=android_arm64 I get an error about ld: cannot find -lpthread in the final link step for my_project_binary. So it looks like the //conditions:default config that is used for the protoc host binary's linkopts are being added to the linkopts for the android target.

As I understand it, my android cc_binary should be linked against libprotobuf and it's linkopts. It should not be linked against protoc's linkopts, even though it is included in the dependency graph because the host needs to build and run it to compile protos.

I verified this by changing -lpthread in the protobuf LINK_OPTS to -lnotareallibrary for //conditions:default and I get an error about that. I can confirm that the ndk toolchain binaries are used for most rules, so I believe that crosstool_top is set correctly.

Why are linkopts from the host's rules showing up in my cc_binary target's linkopts? Is cc_binary not supported for android targets that require building host tools? I was also curious if android_binary solved this somehow, but wasn't able to see how it is defined.

# 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"],                             
)                                                                                                                                  
                                                                                

1 Answers

I've resolved this problem. The issue here was not about host linkopts with protoc/protobuf, but with another library (gflags) that used -lpthread unconditionally. Adding the same android config and select statement used by protobuf fixed this issue (PR). The red herring about using a non-existent -lnotareallibrary was a linker error for protoc, not my target executable.

In case it's helpful to describe the debugging process, I searched the autogenerated bazel-myreponame/external directory's BUILD files and .bzl files for -lpthread. (At first, I only thought to search BUILD files, which missed this library)

Related