Reputation: 211
I am trying to use bazel as build system. My project looks like this:
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
It looks like that bazel seems to have problem with cc_test and android toolchain
Is there any way to build and run an executable for android using bazel? Maybe I missed some command line arguments
Edit:
tried the solution below and added a sh_test rule but it fails again using @androidsdk//:adb and leads to the following error
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
I also need to use $ANDROID_HOME/platform-tools/adb to get the adb binary. external/androidsdk/platform-tools/adb does not work. my BUILD file is in a sub folder of the workspace, maybe this is the issue.
removing @androidsdk//:adb fixes this error. there are some adjustments needed in sh_test rule like:
sh_test(
name = "unit_android",
srcs = ["unit_android.sh"],
data = [
":unit",
#"@androidsdk//:adb",
],
deps = [
"@bazel_tools//tools/bash/runfiles", # to access the manifest
],
)
using runfiles dependency allows me to access the binary via $(rlocation ..) in shell script. but now there seems to be another issue:
when using 'bazel run': It looks like that bazel is trying to upload the file to msys shell (i am using windows) and not to the device:
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'
when using 'bazel test': it just states an error and the content of test log is
unknown parameter - /users
Edit 2: WORKSPACE file about android sdk/ndk
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
)
In both case I assume env var ANDROID_NDK_HOME (points to ndk), ANDROID_SDK_HOME (points to sdk) and ANDROID_HOME (points to sdk) are set. I also checked the external dir, sdk is in there. Removing "@androidsdk//:adb" seem to work but the bazel shell environment now tries to add a prefix before "/data/local/tmp" and tries to upload to a non existing folder. forget about the issue with "/users" (windows path issue ...)
Upvotes: 0
Views: 1745
Reputation: 5016
--crosstool_top
by itself sets both the target and host crosstool, so you may just need to set --host_crosstool_top
back to the default: --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
Edit:
Running the test on a device is unfortunately not supported out of the box by bazel test
. There needs to be some test runner that knows how to put the test on the device, run it, and collect the results. A very simple version of that might look like:
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",
],
)
Note that this approach is not hermetic because it relies on an emulator to already be running, or a device to be already connected. It's possible to start an emulator as part of the test, but that's more involved.
Upvotes: 1