如何使用bazel为Android构建cc_test

时间:2019-02-26 12:44:15

标签: bazel

我正在尝试使用bazel作为构建系统。 我的项目如下:

  • 包含一堆类和函数的静态库
  • 使用与静态库相同的代码的动态库(so / dll)(由于Windows而需要它,cc_library规则不会在Windows上自动构建dll)
  • 构建可执行文件的cc_test规则。它包含基于Google测试框架的单元测试 在Windows和Linux上运行时,它可以工作。 尝试像这样构建Android时,测试规则失败

bazel build //unit:unit --crosstool_top=@androidndk//:default_crosstool --cpu=armeabi-v7a

INFO: Invocation ID: b7c88128-3448-4eb7-bf25-ce8269895956 ERROR: ../yg32wcuz/external/androidndk/BUILD.bazel:39:1: in cc_toolchain_suite rule @androidndk//:toolchain-gnu-libstdcpp: cc_toolchain_suite '@androidndk//:toolchain-gnu-libstdcpp' does not contain a toolchain for cpu 'x64_windows' ERROR: Analysis of target '//unit:unit' failed; build aborted: Analysis of target '@androidndk//:toolchain-gnu-libstdcpp' failed; build aborted

看起来bazel似乎对cc_test和android工具链有问题

有什么方法可以使用bazel为Android构建和运行可执行文件吗?也许我错过了一些命令行参数

编辑:

尝试了以下解决方案并添加了sh_test规则,但该规则再次失败 使用@androidsdk //:adb并导致以下错误

ERROR: missing input file '@androidsdk//:platform-tools/adb' 
ERROR: unit/BUILD:61:1: //unit:unit_android: missing input file '@androidsdk//:platform-tools/adb' Target //unit:unit_android failed to build 
ERROR: unit/BUILD:61:1 1 input file(s) do not exist

我还需要使用$ ANDROID_HOME / platform-tools / adb来获取adb二进制文件。 external / androidsdk / platform-tools / adb不起作用。我的BUILD文件位于工作区的子文件夹中,也许是问题所在。

删除@androidsdk //:adb可修复此错误。 sh_test规则中需要进行一些调整,例如:

sh_test(
    name = "unit_android",
    srcs = ["unit_android.sh"],
    data = [
        ":unit",
        #"@androidsdk//:adb",
    ],
    deps = [
        "@bazel_tools//tools/bash/runfiles", # to access the manifest
    ],
)

使用runfiles依赖项允许我通过Shell脚本中的$(rlocation ..)访问二进制文件。但现在似乎还有另一个问题:

当使用“ bazel run”时: 看来bazel试图将文件上传到msys shell(我正在使用Windows)而不是设备:

adb: error: failed to copy '.../_bazel_exb_a/yg32wcuz/execroot/test/bazel-out/armeabi-v7a-fastbuild/bin/unit/unit' to 'C:/Development/msys2/data/local/tmp/unit'

使用“ bazel测试”时: 它只是指出一个错误,并且测试日志的内容是

unknown parameter - /users

编辑2: 关于android sdk / ndk的WORKSPACE文件

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

android_sdk_repository(
    name = "androidsdk", # Required. Name *must* be "androidsdk".
    api_level = 26
)

在两种情况下,我都假设设置了环境变量ANDROID_NDK_HOME(指向ndk),ANDROID_SDK_HOME(指向sdk)和ANDROID_HOME(指向sdk)。我还检查了外部目录,SDK在其中。删除“ @androidsdk // :: adb”似乎可行,但是bazel shell环境现在尝试在“ / data / local / tmp”之前添加前缀,并尝试上传到不存在的文件夹。 忘记“ / users”的问题(Windows路径问题...)

欢呼

1 个答案:

答案 0 :(得分:1)

--crosstool_top本身可以设置目标和宿主工具,因此您可能只需要将--host_crosstool_top设置为默认值:--host_crosstool_top=@bazel_tools//tools/cpp:toolchain

编辑:

很遗憾,bazel test不支持在设备上运行测试。需要有一些测试运行者知道如何将测试放在设备上,运行它并收集结果。一个非常简单的版本可能看起来像:

test.cc

int main(int argc, char** argv) {
  // Test always passes.
  // Return non-zero for test failure.
  return 0;
}

example_android_cc_test.sh

adb=external/androidsdk/platform-tools/adb

# The test requires a running emulator or connected device.
# The name of the cc_test binary can be passed in using the
# args attribute of sh_test to make this script generic.
$adb push example_test /data/local/tmp

# adb shell returns the exit code of the command
# that was executed, and the exit code of the
# test shell script determines if the sh_test target
# passes or fails.
$adb shell "/data/local/tmp/example_test"

BUILD

cc_test(
  name = "example_test",
  srcs = ["test.cc"],
  linkopts = ["-pie"],
  linkstatic = 1,
)

sh_test(
  name = "example_android_cc_test",
  srcs = ["example_android_cc_test.sh"],
  data = [
      ":example_test",
      "@androidsdk//:adb",
  ],
)

请注意,这种方法不是封闭的,因为它依赖于已在运行的仿真器或已连接的设备。作为测试的一部分,可以启动仿真器,但这涉及更多。