Repository: bazelbuild/bazel
Issue: Support NDK 17
Labels: type: feature request
P1

r17 is expected to land [in May 2018.](https://github.com/android-ndk/ndk/wiki#release-schedule)

Betas 1 and 2 will be released this month (March) and next month (April) respectively.

 https://android.googlesource.com/platform/ndk/+/ndk-release-r17/CHANGELOG.md

[Relevant changes:](https://android.googlesource.com/platform/ndk/+/master/docs/Roadmap.md#ndk-r17)
- `libc++`/`@androidndk//:toolchain-libcpp` will become the default STL. The other STLs will be removed in r18, or moved to another project.
- GCC will no longer be supported.
- Removed support for building against `armeabi`, `mips`, and `mips64`.
- ~Removed support for API levels 14 and 15. New minimum is 16.~
- [clang is updated to v6.0.2, build 4691093](https://android.googlesource.com/platform/prebuilts/clang/host/darwin-x86/+/refs/heads/ndk-release-r17/clang-4691093/AndroidVersion.txt)

Issue comments:
NDK17 is was released. I haven't tested with bazel 0.14rc, but I don't see this being in the changelog.
I haven't had free cycles to work on this yet. Bumping to P1 for re-prioritization. 
That's great thank you!
@steeve WIP: https://github.com/bazelbuild/bazel/pull/5371
When calling `./configure` in tensorflow I get
```
WARNING: The API level of the NDK in ../Android/Sdk/ndk-bundle is 17, which is not supported by Bazel (officially supported versions: [10, 11, 12, 13, 14, 15, 16]). Please use another version.
```
Can someone please confirm I can ignore this warning?
Yes, you can ignore it. Bazel supports up to r18 now.

On Mon, Nov 12, 2018 at 10:34 AM Rudolf A. Braun <notifications@github.com>
wrote:

> When calling ./configure in tensorflow I get
>
> WARNING: The API level of the NDK in /home/seni/Android/Sdk/ndk-bundle is 17, which is not supported by Bazel (officially supported versions: [10, 11, 12, 13, 14, 15, 16]). Please use another version.
>
> Can someone please confirm I can ignore this warning?
>
> —
> You are receiving this because you were assigned.
> Reply to this email directly, view it on GitHub
> <https://github.com/bazelbuild/bazel/issues/4742#issuecomment-437924576>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAVPDsbXGuSn1pdoajyGCq0wQM_Pt-1aks5uuZUHgaJpZM4SYfDw>
> .
>


Pull request review comments:
This will "pass" on CI because the test is disabled. The CI has r15, not r17.

Patch that resolved the issue:
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java
index c5aedb7df5d5c3..8823899c055306 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/AndroidNdkCrosstools.java
@@ -21,6 +21,7 @@
 import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r12.NdkMajorRevisionR12;
 import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r13.NdkMajorRevisionR13;
 import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r15.NdkMajorRevisionR15;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17.NdkMajorRevisionR17;
 import com.google.devtools.build.lib.util.OS;
 import java.util.Map;
 
@@ -46,6 +47,7 @@ private AndroidNdkCrosstools() {}
           // The only difference between r15 and r16 is that old headers are removed, forcing
           // usage of the unified headers. Support for unified headers were added in r15.
           .put(16, new NdkMajorRevisionR15("5.0.300080")) // no changes relevant to Bazel
+          .put(17, new NdkMajorRevisionR17("6.0.2"))
           .build();
 
   public static final Map.Entry<Integer, NdkMajorRevision> LATEST_KNOWN_REVISION =
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/AndroidNdkCrosstoolsR17.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/AndroidNdkCrosstoolsR17.java
new file mode 100644
index 00000000000000..fca2b82a09f294
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/AndroidNdkCrosstoolsR17.java
@@ -0,0 +1,109 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkPaths;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.DefaultCpuToolchain;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/** Generates a CrosstoolRelease proto for the Android NDK. */
+final class AndroidNdkCrosstoolsR17 {
+
+  /**
+   * Creates a CrosstoolRelease proto for the Android NDK, given the API level to use and the
+   * release revision. The crosstools are generated through code rather than checked in as a flat
+   * file to reduce the amount of templating needed (for parameters like the release name and
+   * certain paths), to reduce duplication, and to make it easier to support future versions of the
+   * NDK. TODO(bazel-team): Eventually we should move this into Skylark so the crosstools can be
+   * updated independently of Bazel itself.
+   *
+   * @return A CrosstoolRelease for the Android NDK.
+   */
+  static CrosstoolRelease create(
+      NdkPaths ndkPaths, StlImpl stlImpl, String hostPlatform, String clangVersion) {
+    return CrosstoolRelease.newBuilder()
+        .setMajorVersion("android")
+        .setMinorVersion("")
+        .setDefaultTargetCpu("armeabi")
+        .addAllDefaultToolchain(getDefaultCpuToolchains(stlImpl, clangVersion))
+        .addAllToolchain(createToolchains(ndkPaths, stlImpl, hostPlatform, clangVersion))
+        .build();
+  }
+
+  private static ImmutableList<CToolchain> createToolchains(
+      NdkPaths ndkPaths, StlImpl stlImpl, String hostPlatform, String clangVersion) {
+
+    List<CToolchain.Builder> toolchainBuilders = new ArrayList<>();
+    toolchainBuilders.addAll(new ArmCrosstools(ndkPaths, stlImpl, clangVersion).createCrosstools());
+    toolchainBuilders.addAll(new X86Crosstools(ndkPaths, stlImpl, clangVersion).createCrosstools());
+
+    ImmutableList.Builder<CToolchain> toolchains = new ImmutableList.Builder<>();
+
+    // Set attributes common to all toolchains.
+    for (CToolchain.Builder toolchainBuilder : toolchainBuilders) {
+      toolchainBuilder
+          .setHostSystemName(hostPlatform)
+          .setTargetLibc("local")
+          .setAbiVersion(toolchainBuilder.getTargetCpu())
+          .setAbiLibcVersion("local");
+
+      // builtin_sysroot is set individually on each toolchain.
+      // platforms/arch sysroot
+      toolchainBuilder.addCxxBuiltinIncludeDirectory("%sysroot%/usr/include");
+      // unified headers sysroot, from ndk15 and up
+      toolchainBuilder.addCxxBuiltinIncludeDirectory(
+          ndkPaths.createBuiltinSysroot() + "/usr/include");
+      toolchainBuilder.addUnfilteredCxxFlag(
+          "-isystem%ndk%/usr/include".replace("%ndk%", ndkPaths.createBuiltinSysroot()));
+
+      toolchains.add(toolchainBuilder.build());
+    }
+
+    return toolchains.build();
+  }
+
+  private static ImmutableList<DefaultCpuToolchain> getDefaultCpuToolchains(
+      StlImpl stlImpl, String clangVersion) {
+    // TODO(bazel-team): It would be better to auto-generate this somehow.
+
+    ImmutableMap<String, String> defaultCpus =
+        ImmutableMap.<String, String>builder()
+            // arm
+            .put("armeabi-v7a", "arm-linux-androideabi-clang" + clangVersion + "-v7a")
+            .put("arm64-v8a", "aarch64-linux-android-clang" + clangVersion)
+
+            // x86
+            .put("x86", "x86-clang" + clangVersion)
+            .put("x86_64", "x86_64-clang" + clangVersion)
+            .build();
+
+    ImmutableList.Builder<DefaultCpuToolchain> defaultCpuToolchains = ImmutableList.builder();
+    for (Map.Entry<String, String> defaultCpu : defaultCpus.entrySet()) {
+      defaultCpuToolchains.add(
+          DefaultCpuToolchain.newBuilder()
+              .setCpu(defaultCpu.getKey())
+              .setToolchainIdentifier(defaultCpu.getValue() + "-" + stlImpl.getName())
+              .build());
+    }
+    return defaultCpuToolchains.build();
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/ApiLevelR17.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/ApiLevelR17.java
new file mode 100644
index 00000000000000..46a0ba4d2a5b71
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/ApiLevelR17.java
@@ -0,0 +1,67 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17;
+
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.ApiLevel;
+import com.google.devtools.build.lib.events.EventHandler;
+
+/** Class which encodes information from the Android NDK makefiles about API levels. */
+final class ApiLevelR17 extends ApiLevel {
+  /** This is the contents of {@code platforms/android-*} */
+  private static final ImmutableListMultimap<String, String> API_LEVEL_TO_ARCHITECTURES =
+      ImmutableListMultimap.<String, String>builder()
+          .putAll("14", "arm", "x86")
+          .putAll("15", "arm", "x86")
+          .putAll("16", "arm", "x86")
+          .putAll("17", "arm", "x86")
+          .putAll("18", "arm", "x86")
+          .putAll("19", "arm", "x86")
+          .putAll("21", "arm", "x86", "arm64", "x86_64")
+          .putAll("22", "arm", "x86", "arm64", "x86_64")
+          .putAll("23", "arm", "x86", "arm64", "x86_64")
+          .putAll("24", "arm", "x86", "arm64", "x86_64")
+          .putAll("26", "arm", "x86", "arm64", "x86_64")
+          .putAll("27", "arm", "x86", "arm64", "x86_64")
+          .putAll("28", "arm", "x86", "arm64", "x86_64")
+          .build();
+
+  /** This map fill in the gaps of {@code API_LEVEL_TO_ARCHITECTURES}. */
+  private static final ImmutableMap<String, String> API_EQUIVALENCIES =
+      ImmutableMap.<String, String>builder()
+          .put("10", "14")
+          .put("11", "14")
+          .put("12", "14")
+          .put("13", "14")
+          .put("14", "14")
+          .put("15", "14")
+          .put("16", "16")
+          .put("17", "16")
+          .put("18", "18")
+          .put("19", "19")
+          .put("20", "19")
+          .put("21", "21")
+          .put("22", "22")
+          .put("23", "23")
+          .put("24", "24")
+          .put("25", "24")
+          .put("26", "26")
+          .put("27", "27")
+          .put("28", "28")
+          .build();
+
+  ApiLevelR17(EventHandler eventHandler, String repositoryName, String apiLevel) {
+    super(API_LEVEL_TO_ARCHITECTURES, API_EQUIVALENCIES, eventHandler, repositoryName, apiLevel); } }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/ArmCrosstools.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/ArmCrosstools.java
new file mode 100644
index 00000000000000..eb6a0fec7fa226
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/ArmCrosstools.java
@@ -0,0 +1,171 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkPaths;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CompilationMode;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CompilationModeFlags;
+
+/**
+ * Crosstool definitions for ARM. These values are based on the setup.mk files in the Android NDK
+ * toolchain directories.
+ */
+final class ArmCrosstools {
+  private final NdkPaths ndkPaths;
+  private final StlImpl stlImpl;
+  private final String clangVersion;
+
+  ArmCrosstools(NdkPaths ndkPaths, StlImpl stlImpl, String clangVersion) {
+    this.ndkPaths = ndkPaths;
+    this.stlImpl = stlImpl;
+    this.clangVersion = clangVersion;
+  }
+
+  ImmutableList<CToolchain.Builder> createCrosstools() {
+    CToolchain.Builder aarch64Toolchain = createAarch64ClangToolchain();
+    CToolchain.Builder armeabiToolchain = createArmeabiClangToolchain();
+
+    stlImpl.addStlImpl(aarch64Toolchain, "4.9");
+    stlImpl.addStlImpl(armeabiToolchain, "4.9");
+
+    return ImmutableList.<CToolchain.Builder>builder()
+        .add(aarch64Toolchain)
+        .add(armeabiToolchain)
+        .build();
+  }
+
+  private CToolchain.Builder createAarch64ClangToolchain() {
+    String toolchainName = "aarch64-linux-android-4.9";
+    String targetPlatform = "aarch64-linux-android";
+    String gccToolchain = ndkPaths.createGccToolchainPath(toolchainName);
+    String llvmTriple = "aarch64-none-linux-android";
+
+    return CToolchain.newBuilder()
+        .setToolchainIdentifier("aarch64-linux-android-clang" + clangVersion)
+        .setTargetSystemName(targetPlatform)
+        .setTargetCpu("arm64-v8a")
+        .setCompiler("clang" + clangVersion)
+        .addAllToolPath(ndkPaths.createClangToolpaths(toolchainName, targetPlatform, null))
+        .addCxxBuiltinIncludeDirectory(
+            ndkPaths.createClangToolchainBuiltinIncludeDirectory(clangVersion))
+        .setBuiltinSysroot(ndkPaths.createBuiltinSysroot("arm64"))
+
+        // Compiler flags
+        .addCompilerFlag("-gcc-toolchain")
+        .addCompilerFlag(gccToolchain)
+        .addCompilerFlag("-target")
+        .addCompilerFlag(llvmTriple)
+        .addCompilerFlag("-ffunction-sections")
+        .addCompilerFlag("-funwind-tables")
+        .addCompilerFlag("-fstack-protector-strong")
+        .addCompilerFlag("-fpic")
+        .addCompilerFlag("-Wno-invalid-command-line-argument")
+        .addCompilerFlag("-Wno-unused-command-line-argument")
+        .addCompilerFlag("-no-canonical-prefixes")
+        .addCompilerFlag(
+            "-isystem%ndk%/usr/include/%triple%"
+                .replace("%ndk%", ndkPaths.createBuiltinSysroot())
+                .replace("%triple%", targetPlatform))
+        .addCompilerFlag("-D__ANDROID_API__=" + ndkPaths.getCorrectedApiLevel("arm"))
+
+        // Linker flags
+        .addLinkerFlag("-gcc-toolchain")
+        .addLinkerFlag(gccToolchain)
+        .addLinkerFlag("-target")
+        .addLinkerFlag(llvmTriple)
+        .addLinkerFlag("-no-canonical-prefixes")
+
+        // Additional release flags
+        .addCompilationModeFlags(
+            CompilationModeFlags.newBuilder()
+                .setMode(CompilationMode.OPT)
+                .addCompilerFlag("-O2")
+                .addCompilerFlag("-g")
+                .addCompilerFlag("-DNDEBUG"))
+
+        // Additional debug flags
+        .addCompilationModeFlags(
+            CompilationModeFlags.newBuilder()
+                .setMode(CompilationMode.DBG)
+                .addCompilerFlag("-O0")
+                .addCompilerFlag("-UNDEBUG"));
+  }
+
+  private CToolchain.Builder createArmeabiClangToolchain() {
+    String toolchainName = "arm-linux-androideabi-4.9";
+    String targetPlatform = "arm-linux-androideabi";
+    String gccToolchain = ndkPaths.createGccToolchainPath("arm-linux-androideabi-4.9");
+
+    return CToolchain.newBuilder()
+        .setToolchainIdentifier("arm-linux-androideabi-clang" + clangVersion + "-v7a")
+        .setTargetCpu("armeabi-v7a")
+        .setTargetSystemName("arm-linux-androideabi")
+        .setCompiler("clang" + clangVersion)
+        .addAllToolPath(ndkPaths.createClangToolpaths(toolchainName, targetPlatform, null))
+        .addCxxBuiltinIncludeDirectory(
+            ndkPaths.createClangToolchainBuiltinIncludeDirectory(clangVersion))
+        .setBuiltinSysroot(ndkPaths.createBuiltinSysroot("arm"))
+        .addCompilerFlag("-D__ANDROID_API__=" + ndkPaths.getCorrectedApiLevel("arm"))
+        .addCompilerFlag(
+            "-isystem%ndk%/usr/include/%triple%"
+                .replace("%ndk%", ndkPaths.createBuiltinSysroot())
+                .replace("%triple%", targetPlatform))
+
+        // Compiler flags
+        .addCompilerFlag("-target")
+        .addCompilerFlag("armv7-none-linux-androideabi") // LLVM_TRIPLE
+        .addCompilerFlag("-march=armv7-a")
+        .addCompilerFlag("-mfloat-abi=softfp")
+        .addCompilerFlag("-mfpu=vfpv3-d16")
+        .addCompilerFlag("-gcc-toolchain")
+        .addCompilerFlag(gccToolchain)
+        .addCompilerFlag("-fpic")
+        .addCompilerFlag("-ffunction-sections")
+        .addCompilerFlag("-funwind-tables")
+        .addCompilerFlag("-fstack-protector-strong")
+        .addCompilerFlag("-Wno-invalid-command-line-argument")
+        .addCompilerFlag("-Wno-unused-command-line-argument")
+        .addCompilerFlag("-no-canonical-prefixes")
+
+        // Linker flags
+        .addLinkerFlag("-target")
+        .addLinkerFlag("armv7-none-linux-androideabi") // LLVM_TRIPLE
+        .addLinkerFlag("-Wl,--fix-cortex-a8")
+        .addLinkerFlag("-gcc-toolchain")
+        .addLinkerFlag(gccToolchain)
+        .addLinkerFlag("-no-canonical-prefixes")
+
+        // Additional release flags
+        .addCompilationModeFlags(
+            CompilationModeFlags.newBuilder()
+                .setMode(CompilationMode.OPT)
+                .addCompilerFlag("-mthumb")
+                .addCompilerFlag("-Os")
+                .addCompilerFlag("-g")
+                .addCompilerFlag("-DNDEBUG"))
+
+        // Additional debug flags
+        .addCompilationModeFlags(
+            CompilationModeFlags.newBuilder()
+                .setMode(CompilationMode.DBG)
+                .addCompilerFlag("-g")
+                .addCompilerFlag("-fno-strict-aliasing")
+                .addCompilerFlag("-O0")
+                .addCompilerFlag("-UNDEBUG"));
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/NdkMajorRevisionR17.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/NdkMajorRevisionR17.java
new file mode 100644
index 00000000000000..22e01b17df850d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/NdkMajorRevisionR17.java
@@ -0,0 +1,43 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17;
+
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.ApiLevel;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkMajorRevision;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkPaths;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl;
+import com.google.devtools.build.lib.events.EventHandler;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CrosstoolRelease;
+
+/** Logic specific to Android NDK R17. */
+public class NdkMajorRevisionR17 implements NdkMajorRevision {
+  private final String clangVersion;
+
+  public NdkMajorRevisionR17(String clangVersion) {
+    this.clangVersion = clangVersion;
+  }
+
+  @Override
+  public CrosstoolRelease crosstoolRelease(
+      NdkPaths ndkPaths, StlImpl stlImpl, String hostPlatform) {
+    return AndroidNdkCrosstoolsR17
+        .create(ndkPaths, stlImpl, hostPlatform, clangVersion);
+  }
+
+  @Override
+  public ApiLevel apiLevel(EventHandler eventHandler, String name, String apiLevel) {
+    return new ApiLevelR17(eventHandler, name, apiLevel);
+  }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/X86Crosstools.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/X86Crosstools.java
new file mode 100644
index 00000000000000..e2887b8e707539
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/ndkcrosstools/r17/X86Crosstools.java
@@ -0,0 +1,118 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.r17;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.NdkPaths;
+import com.google.devtools.build.lib.bazel.rules.android.ndkcrosstools.StlImpl;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CompilationMode;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CompilationModeFlags;
+
+/**
+ * Crosstool definitions for x86. These values are based on the setup.mk files in the Android NDK
+ * toolchain directories.
+ */
+final class X86Crosstools {
+  private final NdkPaths ndkPaths;
+  private final StlImpl stlImpl;
+  private final String clangVersion;
+
+  X86Crosstools(NdkPaths ndkPaths, StlImpl stlImpl, String clangVersion) {
+    this.ndkPaths = ndkPaths;
+    this.stlImpl = stlImpl;
+    this.clangVersion = clangVersion;
+  }
+
+  ImmutableList<CToolchain.Builder> createCrosstools() {
+    /** x86 */
+    // clang
+    CToolchain.Builder x86Clang =
+        createBaseX86ClangToolchain("x86", "i686", "i686-linux-android")
+            // Workaround for https://code.google.com/p/android/issues/detail?id=220159.
+            .addCompilerFlag("-mstackrealign")
+            .setToolchainIdentifier("x86-clang" + clangVersion)
+            .setTargetCpu("x86")
+            .addAllToolPath(ndkPaths.createClangToolpaths("x86-4.9", "i686-linux-android", null))
+            .setBuiltinSysroot(ndkPaths.createBuiltinSysroot("x86"));
+
+    stlImpl.addStlImpl(x86Clang, "4.9");
+
+    /** x86_64 */
+    CToolchain.Builder x8664Clang =
+        createBaseX86ClangToolchain("x86_64", "x86_64", "x86_64-linux-android")
+            .setToolchainIdentifier("x86_64-clang" + clangVersion)
+            .setTargetCpu("x86_64")
+            .addAllToolPath(
+                ndkPaths.createClangToolpaths("x86_64-4.9", "x86_64-linux-android", null))
+            .setBuiltinSysroot(ndkPaths.createBuiltinSysroot("x86_64"));
+
+    stlImpl.addStlImpl(x8664Clang, "4.9");
+
+    return ImmutableList.of(x86Clang, x8664Clang);
+  }
+
+  private CToolchain.Builder createBaseX86ClangToolchain(
+      String x86Arch, String llvmArch, String triple) {
+    String gccToolchain = ndkPaths.createGccToolchainPath(x86Arch + "-4.9");
+    String llvmTriple = llvmArch + "-none-linux-android";
+
+    return CToolchain.newBuilder()
+        .setCompiler("clang" + clangVersion)
+        .addCxxBuiltinIncludeDirectory(
+            ndkPaths.createClangToolchainBuiltinIncludeDirectory(clangVersion))
+
+        // Compiler flags
+        .addCompilerFlag("-gcc-toolchain")
+        .addCompilerFlag(gccToolchain)
+        .addCompilerFlag("-target")
+        .addCompilerFlag(llvmTriple)
+        .addCompilerFlag("-ffunction-sections")
+        .addCompilerFlag("-funwind-tables")
+        .addCompilerFlag("-fstack-protector-strong")
+        .addCompilerFlag("-fPIC")
+        .addCompilerFlag("-Wno-invalid-command-line-argument")
+        .addCompilerFlag("-Wno-unused-command-line-argument")
+        .addCompilerFlag("-no-canonical-prefixes")
+        .addCompilerFlag(
+            "-isystem%ndk%/usr/include/%triple%"
+                .replace("%ndk%", ndkPaths.createBuiltinSysroot())
+                .replace("%triple%", triple))
+        .addCompilerFlag("-D__ANDROID_API__=" + ndkPaths.getCorrectedApiLevel(x86Arch))
+
+        // Linker flags
+        .addLinkerFlag("-gcc-toolchain")
+        .addLinkerFlag(gccToolchain)
+        .addLinkerFlag("-target")
+        .addLinkerFlag(llvmTriple)
+        .addLinkerFlag("-no-canonical-prefixes")
+
+        // Additional release flags
+        .addCompilationModeFlags(
+            CompilationModeFlags.newBuilder()
+                .setMode(CompilationMode.OPT)
+                .addCompilerFlag("-O2")
+                .addCompilerFlag("-g")
+                .addCompilerFlag("-DNDEBUG"))
+
+        // Additional debug flags
+        .addCompilationModeFlags(
+            CompilationModeFlags.newBuilder()
+                .setMode(CompilationMode.DBG)
+                .addCompilerFlag("-O0")
+                .addCompilerFlag("-g"))
+        .setTargetSystemName("x86-linux-android");
+  }
+}


Test patch:
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java
index 232a553d5d6652..a6811235841331 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidNdkRepositoryTest.java
@@ -102,7 +102,7 @@ public void testInvalidNdkReleaseTxt() throws Exception {
         eventCollector,
         "The revision of the Android NDK referenced by android_ndk_repository rule 'androidndk' "
             + "could not be determined (the revision string found is 'not a valid release string')."
-            + " Bazel will attempt to treat the NDK as if it was r16.");
+            + " Bazel will attempt to treat the NDK as if it was r17.");
   }
 
   @Test
@@ -128,7 +128,7 @@ public void testInvalidNdkSourceProperties() throws Exception {
         eventCollector,
         "The revision of the Android NDK referenced by android_ndk_repository rule 'androidndk' "
             + "could not be determined (the revision string found is 'invalid package revision'). "
-            + "Bazel will attempt to treat the NDK as if it was r16.");
+            + "Bazel will attempt to treat the NDK as if it was r17.");
   }
 
   @Test
@@ -145,16 +145,16 @@ public void testUnsupportedNdkVersion() throws Exception {
     scratch.overwriteFile(
         "/ndk/source.properties",
         "Pkg.Desc = Android NDK",
-        "Pkg.Revision = 17.0.3675639-beta2");
+        "Pkg.Revision = 18.0.3675639-beta2");
     invalidatePackages();
 
     assertThat(getConfiguredTarget("@androidndk//:files")).isNotNull();
     MoreAsserts.assertContainsEvent(
         eventCollector,
         "The major revision of the Android NDK referenced by android_ndk_repository rule "
-            + "'androidndk' is 17. The major revisions supported by Bazel are "
-            + "[10, 11, 12, 13, 14, 15, 16]. Bazel will attempt to treat the NDK as if it was "
-            + "r16.");
+            + "'androidndk' is 18. The major revisions supported by Bazel are "
+            + "[10, 11, 12, 13, 14, 15, 16, 17]. Bazel will attempt to treat the NDK as if it was "
+            + "r17.");
   }
 
   @Test
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 c8e85e7ee304a4..cf4a99a7485a61 100755
--- a/src/test/shell/bazel/android/android_ndk_integration_test.sh
+++ b/src/test/shell/bazel/android/android_ndk_integration_test.sh
@@ -175,7 +175,7 @@ EOF
 
 function check_num_sos() {
   num_sos=$(unzip -Z1 bazel-bin/java/bazel/bin.apk '*.so' | wc -l | sed -e 's/[[:space:]]//g')
-  assert_equals "5" "$num_sos"
+  assert_equals "4" "$num_sos"
 }
 
 function check_soname() {
@@ -202,9 +202,9 @@ function test_android_binary() {
   setup_android_ndk_support
   create_android_binary
 
-  cpus="armeabi,armeabi-v7a,arm64-v8a,x86,x86_64"
+  cpus="armeabi-v7a,arm64-v8a,x86,x86_64"
 
-  bazel build -s //java/bazel:bin --fat_apk_cpu="$cpus" || fail "build failed"
+  assert_build //java/bazel:bin --fat_apk_cpu="$cpus"
   check_num_sos
   check_soname
 }
@@ -215,12 +215,9 @@ function test_android_binary_clang() {
   setup_android_ndk_support
   create_android_binary
 
-  cpus="armeabi,armeabi-v7a,arm64-v8a,x86,x86_64"
+  cpus="armeabi-v7a,arm64-v8a,x86,x86_64"
 
-  bazel build -s //java/bazel:bin \
-      --fat_apk_cpu="$cpus" \
-      --android_compiler=clang5.0.300080 \
-      || fail "build failed"
+  assert_build //java/bazel:bin --fat_apk_cpu="$cpus"
   check_num_sos
   check_soname
 }
@@ -240,12 +237,11 @@ EOF
 #include <arm_neon.h>
 int main() { return 0; }
 EOF
-  bazel build //:foo \
-    --compiler=clang5.0.300080 \
+  assert_build :foo \
+    --compiler=clang6.0.2 \
     --cpu=armeabi-v7a \
     --crosstool_top=//external:android/crosstool \
-    --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
-    || fail "build failed"
+    --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
 }
 
 function test_android_ndk_repository_path_from_environment() {
@@ -270,8 +266,8 @@ android_ndk_repository(
     api_level = 25,
 )
 EOF
-  bazel build @androidndk//:files >& $TEST_log && fail "Should have failed"
-  expect_log "Either the path attribute of android_ndk_repository"
+  assert_build_fails @androidndk//:files \
+    "Either the path attribute of android_ndk_repository"
 }
 
 function test_android_ndk_repository_wrong_path() {
@@ -284,8 +280,8 @@ android_ndk_repository(
     path = "$TEST_TMPDIR/some_dir",
 )
 EOF
-  bazel build @androidndk//:files >& $TEST_log && fail "Should have failed"
-  expect_log "Unable to read the Android NDK at $TEST_TMPDIR/some_dir, the path may be invalid." \
+  assert_build_fails @androidndk//:files \
+    "Unable to read the Android NDK at $TEST_TMPDIR/some_dir, the path may be invalid." \
     " Is the path in android_ndk_repository() or \$ANDROID_NDK_HOME set correctly?"
 }
 
@@ -301,7 +297,7 @@ EOF
   cat > foo.cc <<EOF
 int main() { return 0; }
 EOF
-  bazel build //:foo.stripped \
+  assert_build //:foo.stripped \
     --cpu=armeabi-v7a \
     --crosstool_top=//external:android/crosstool \
     --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
@@ -406,7 +402,7 @@ function test_crosstool_libcpp_with_multiarch() {
   setup_android_ndk_support
   create_android_binary
 
-  cpus="armeabi,armeabi-v7a,arm64-v8a,x86,x86_64"
+  cpus="armeabi-v7a,arm64-v8a,x86,x86_64"
 
   assert_build //java/bazel:bin \
     --fat_apk_cpu="$cpus" \