Integrate Android NDK with toolchains
Fixes https://github.com/bazelbuild/bazel/issues/8871
Generates toolchains for the `cc_toolchain` targets in the `@androidndk` BUILD file:
```python
toolchain(
name = "x86-clang8.0.7-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@bazel_tools//platforms:android",
"@bazel_tools//platforms:x86_32"
],
toolchain = "@androidndk//:x86-clang8.0.7-libcpp",
)
toolchain(
name = "x86_64-clang8.0.7-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@bazel_tools//platforms:android",
"@bazel_tools//platforms:x86_64"
],
toolchain = "@androidndk//:x86_64-clang8.0.7-libcpp",
)
toolchain(
name = "arm-linux-androideabi-clang8.0.7-v7a-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@bazel_tools//platforms:android",
"@bazel_tools//platforms:arm"
],
toolchain = "@androidndk//:arm-linux-androideabi-clang8.0.7-v7a-libcpp",
)
toolchain(
name = "aarch64-linux-android-clang8.0.7-libcpp_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
target_compatible_with = [
"@bazel_tools//platforms:android",
"@bazel_tools//platforms:aarch64"
],
toolchain = "@androidndk//:aarch64-linux-android-clang8.0.7-libcpp",
)
```
Users can use them by using the `--extra_toolchains=@androidndk//:all` flag or by registering them in the WORKSPACE with `register_toolchains("androidndk//:all")`.
RELNOTES: The Android NDK is now integrated with toolchains. To use them, pass the `--extra_toolchains=@androidndk//:all` flag or register them in your WORKSPACE with `register_toolchains("@androidndk//:all")`.
Closes #8918.
Change-Id: Iba708d1749efacbd47fc3584efd55634c70d2b18
PiperOrigin-RevId: 258633109
diff --git a/site/docs/android-ndk.md b/site/docs/android-ndk.md
index b75ca67..8558207 100644
--- a/site/docs/android-ndk.md
+++ b/site/docs/android-ndk.md
@@ -255,6 +255,77 @@
)
```
+## Integration with platforms and toolchains
+
+Bazel's configuration model is moving towards
+[platforms](https://docs.bazel.build/versions/master/platforms.html) and
+[toolchains](https://docs.bazel.build/versions/master/toolchains.html). If your
+build uses the `--platforms` flag to select for the architecture or operating system
+to build for, you will need to pass the `--extra_toolchains` flag to Bazel in
+order to use the NDK.
+
+For example, to integrate with the `android_arm64_cgo` toolchain provided by
+the Go rules, pass `--extra_toolchains=@androidndk//:all` in addition to the
+`--platforms` flag.
+
+```
+bazel build //my/cc:lib \
+ --platforms=@io_bazel_rules_go//go/toolchain:android_arm64_cgo \
+ --extra_toolchains=@androidndk//:all
+```
+
+You can also register them directly in the `WORKSPACE` file:
+
+```python
+android_ndk_repository(name = "androidndk")
+register_toolchains("@androidndk//:all")
+```
+
+Registering these toolchains tells Bazel to look for them in the NDK BUILD file
+(for NDK 20) when resolving architecture and operating system constraints:
+
+```python
+toolchain(
+ name = "x86-clang8.0.7-libcpp_toolchain",
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+ target_compatible_with = [
+ "@bazel_tools//platforms:android",
+ "@bazel_tools//platforms:x86_32"
+ ],
+ toolchain = "@androidndk//:x86-clang8.0.7-libcpp",
+)
+
+toolchain(
+ name = "x86_64-clang8.0.7-libcpp_toolchain",
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+ target_compatible_with = [
+ "@bazel_tools//platforms:android",
+ "@bazel_tools//platforms:x86_64"
+ ],
+ toolchain = "@androidndk//:x86_64-clang8.0.7-libcpp",
+)
+
+toolchain(
+ name = "arm-linux-androideabi-clang8.0.7-v7a-libcpp_toolchain",
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+ target_compatible_with = [
+ "@bazel_tools//platforms:android",
+ "@bazel_tools//platforms:arm"
+ ],
+ toolchain = "@androidndk//:arm-linux-androideabi-clang8.0.7-v7a-libcpp",
+)
+
+toolchain(
+ name = "aarch64-linux-android-clang8.0.7-libcpp_toolchain",
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+ target_compatible_with = [
+ "@bazel_tools//platforms:android",
+ "@bazel_tools//platforms:aarch64"
+ ],
+ toolchain = "@androidndk//:aarch64-linux-android-clang8.0.7-libcpp",
+)
+```
+
## How it works: introducing Android configuration transitions
The `android_binary` rule can explicitly ask Bazel to build its dependencies in
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java
index 375104e..89b40ae 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryFunction.java
@@ -201,6 +201,7 @@
return ccToolchainTemplate
.replace("%toolchainName%", toolchain.getToolchainIdentifier())
.replace("%cpu%", toolchain.getTargetCpu())
+ .replace("%platform_cpu%", getPlatformCpuLabel(toolchain.getTargetCpu()))
.replace("%compiler%", toolchain.getCompiler())
.replace("%version%", version)
.replace("%dynamicRuntimeLibs%", toolchain.getDynamicRuntimesFilegroup())
@@ -209,6 +210,21 @@
.replace("%toolchainFileGlobs%", toolchainFileGlobs.toString().trim());
}
+ private static String getPlatformCpuLabel(String targetCpu) {
+ // Create a mapping of CcToolchain CPU values to platform arch constraint values
+ // in @bazel_tools//platforms
+ switch (targetCpu) {
+ case "x86":
+ return "x86_32";
+ case "armeabi-v7a":
+ return "arm";
+ case "arm64-v8a":
+ return "aarch64";
+ default:
+ return "x86_64";
+ }
+ }
+
private static String getTemplate(String templateFile) {
try {
return ResourceFileLoader.loadResource(AndroidNdkRepositoryFunction.class, templateFile);
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt
index d9bd152..d622f0c 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_ndk_cc_toolchain_template.txt
@@ -26,6 +26,16 @@
version = "%version%",
)
+toolchain(
+ name = "%toolchainName%_toolchain",
+ target_compatible_with = [
+ "@bazel_tools//platforms:android",
+ "@bazel_tools//platforms:%platform_cpu%",
+ ],
+ toolchain = "@androidndk//:%toolchainName%",
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
+
filegroup(
name = "%toolchainName%-all_files",
srcs = glob(["ndk/toolchains/%toolchainDirectory%/**"]) + glob([
diff --git a/src/test/shell/bazel/android/android_ndk_integration_test.sh b/src/test/shell/bazel/android/android_ndk_integration_test.sh
index c8e85e7..4095bc8 100755
--- a/src/test/shell/bazel/android/android_ndk_integration_test.sh
+++ b/src/test/shell/bazel/android/android_ndk_integration_test.sh
@@ -400,6 +400,45 @@
--host_crosstool_top=@bazel_tools//tools/cpp:toolchain
}
+function test_platforms_and_toolchains() {
+ create_new_workspace
+ setup_android_ndk_support
+ cat > BUILD <<EOF
+cc_binary(
+ name = "foo",
+ srcs = ["foo.cc"],
+ linkopts = ["-ldl", "-lm"],
+)
+
+platform(
+ name = 'android_arm',
+ constraint_values = ['@bazel_tools//platforms:arm', '@bazel_tools//platforms:android'],
+ visibility = ['//visibility:public']
+)
+EOF
+ cat > foo.cc <<EOF
+#include <string>
+#include <jni.h>
+#include <android/log.h>
+#include <cstdio>
+#include <iostream>
+
+using namespace std;
+int main(){
+ string foo = "foo";
+ string bar = "bar";
+ string foobar = foo + bar;
+ return 0;
+}
+EOF
+ assert_build //:foo \
+ --cpu=armeabi-v7a \
+ --crosstool_top=@androidndk//:toolchain-libcpp \
+ --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
+ --platforms=//:android_arm \
+ --extra_toolchains=@androidndk//:all
+}
+
function test_crosstool_libcpp_with_multiarch() {
create_new_workspace
setup_android_sdk_support