Merge "Windows: Fix libc++ tests, explicitly run python"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3b7cb7..f889c67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,17 @@
  * Updated Clang to build 4393122 based on ???
  * AArch64 now uses gold by default, matching the other architectures.
  * Updated gtest to upstream revision 0fe96607d85cf3a25ac40da369db62bbee2939a5.
+ * Fixed parsing of the NDK revision in CMake. NDK version information is now
+   available in the following CMake variables:
+     * `ANDROID_NDK_REVISION`: The full string in the source.properties file.
+     * `ANDROID_NDK_MAJOR`: The major revision of the NDK. For example: the 16
+       in r16b.
+     * `ANDROID_NDK_MINOR`: The minor revision of the NDK. For example: the b
+       (represented as 1) in r16b.
+     * `ANDROID_NDK_BUILD`: The build number of the NDK. This is 0 in the case
+       of a local development build.
+     * `ANDROID_NDK_BETA`: The beta version of the NDK. This is 0 for a stable
+       release.
 
 Known Issues
 ------------
diff --git a/build/cmake/android.toolchain.cmake b/build/cmake/android.toolchain.cmake
index 971bb94..9f64394 100644
--- a/build/cmake/android.toolchain.cmake
+++ b/build/cmake/android.toolchain.cmake
@@ -65,14 +65,29 @@
 file(TO_CMAKE_PATH "${ANDROID_NDK}" ANDROID_NDK)
 
 # Android NDK revision
+# Possible formats:
+# * r16, build 1234: 16.0.1234
+# * r16b, build 1234: 16.1.1234
+# * r16 beta 1, build 1234: 16.0.1234-beta1
+#
+# Canary builds are not specially marked.
 file(READ "${ANDROID_NDK}/source.properties" ANDROID_NDK_SOURCE_PROPERTIES)
-set(ANDROID_NDK_SOURCE_PROPERTIES_REGEX
-  "^Pkg\\.Desc = Android NDK\nPkg\\.Revision = ([0-9]+)\\.")
-if(NOT ANDROID_NDK_SOURCE_PROPERTIES MATCHES "${ANDROID_NDK_SOURCE_PROPERTIES_REGEX}")
+
+set(ANDROID_NDK_REVISION_REGEX
+  "^Pkg\\.Desc = Android NDK\nPkg\\.Revision = ([0-9]+)\\.([0-9]+)\\.([0-9]+)(-beta([0-9]+))?")
+if(NOT ANDROID_NDK_SOURCE_PROPERTIES MATCHES "${ANDROID_NDK_REVISION_REGEX}")
   message(SEND_ERROR "Failed to parse Android NDK revision: ${ANDROID_NDK}/source.properties.\n${ANDROID_NDK_SOURCE_PROPERTIES}")
 endif()
-string(REGEX REPLACE "${ANDROID_NDK_SOURCE_PROPERTIES_REGEX}" "\\1"
-  ANDROID_NDK_REVISION "${ANDROID_NDK_SOURCE_PROPERTIES}")
+
+set(ANDROID_NDK_MAJOR "${CMAKE_MATCH_1}")
+set(ANDROID_NDK_MINOR "${CMAKE_MATCH_2}")
+set(ANDROID_NDK_BUILD "${CMAKE_MATCH_3}")
+set(ANDROID_NDK_BETA "${CMAKE_MATCH_5}")
+if(ANDROID_NDK_BETA STREQUAL "")
+  set(ANDROID_NDK_BETA "0")
+endif()
+set(ANDROID_NDK_REVISION
+  "${ANDROID_NDK_MAJOR}.${ANDROID_NDK_MINOR}.${ANDROID_NDK_BUILD}${CMAKE_MATCH_4}")
 
 # Touch toolchain variable to suppress "unused variable" warning.
 # This happens if CMake is invoked with the same command line the second time.
diff --git a/build/tools/make_standalone_toolchain.py b/build/tools/make_standalone_toolchain.py
index a7d1207..a607720 100755
--- a/build/tools/make_standalone_toolchain.py
+++ b/build/tools/make_standalone_toolchain.py
@@ -246,43 +246,43 @@
                  os.path.join(install_dir, 'bin', triple + '-clang++'))
 
     if windows:
-        flags = '-target {} --sysroot %~dp0\\..\\sysroot'.format(target)
+        flags = '-target {}'.format(target)
+        flags += ' --sysroot %_BIN_DIR%..\\sysroot'
         flags += ' -D__ANDROID_API__={}'.format(api)
 
-        clangbat_path = os.path.join(install_dir, 'bin/clang.cmd')
-        with open(clangbat_path, 'w') as clangbat:
-            clangbat.write(textwrap.dedent("""\
+        for pp_suffix in ('', '++'):
+            exe_name = 'clang{}{}.exe'.format(version_number, pp_suffix)
+            clangbat_text = textwrap.dedent("""\
                 @echo off
+                setlocal
+                call :find_bin
                 if "%1" == "-cc1" goto :L
-                %~dp0\\clang{version}.exe {flags} %*
+
+                set "_BIN_DIR=" && %_BIN_DIR%{exe} {flags} %*
                 if ERRORLEVEL 1 exit /b 1
                 goto :done
+
                 :L
                 rem target/triple already spelled out.
-                %~dp0\\clang{version}.exe %*
-                if ERRORLEVEL 1 exit /b 1
-                :done
-            """.format(version=version_number, flags=flags)))
-
-        clangbatpp_path = os.path.join(install_dir, 'bin/clang++.cmd')
-        with open(clangbatpp_path, 'w') as clangbatpp:
-            clangbatpp.write(textwrap.dedent("""\
-                @echo off
-                if "%1" == "-cc1" goto :L
-                %~dp0\\clang{version}++.exe {flags} %*
+                set "_BIN_DIR=" && %_BIN_DIR%{exe} %*
                 if ERRORLEVEL 1 exit /b 1
                 goto :done
-                :L
-                rem target/triple already spelled out.
-                %~dp0\\clang{version}++.exe %*
-                if ERRORLEVEL 1 exit /b 1
-                :done
-            """.format(version=version_number, flags=flags)))
 
-        shutil.copy2(os.path.join(install_dir, 'bin/clang.cmd'),
-                     os.path.join(install_dir, 'bin', triple + '-clang.cmd'))
-        shutil.copy2(os.path.join(install_dir, 'bin/clang++.cmd'),
-                     os.path.join(install_dir, 'bin', triple + '-clang++.cmd'))
+                :find_bin
+                rem Accommodate a quoted arg0, e.g.: "clang"
+                rem https://github.com/android-ndk/ndk/issues/616
+                set _BIN_DIR=%~dp0
+                exit /b
+
+                :done
+            """.format(exe=exe_name, flags=flags))
+
+            for triple_prefix in ('', triple + '-'):
+                clangbat_path = os.path.join(
+                    install_dir, 'bin',
+                    '{}clang{}.cmd'.format(triple_prefix, pp_suffix))
+                with open(clangbat_path, 'w') as clangbat:
+                    clangbat.write(clangbat_text)
 
 
 def copy_gnustl_abi_headers(src_dir, dst_dir, gcc_ver, triple, abi,
diff --git a/checkbuild.py b/checkbuild.py
index 64d15be..d3befb4 100755
--- a/checkbuild.py
+++ b/checkbuild.py
@@ -1585,6 +1585,13 @@
     return [m.name for m in ALL_MODULES]
 
 
+def build_number(value):
+    if value.startswith('P'):
+        # Treehugger build. Treat as a local development build.
+        return '0'
+    return value
+
+
 def parse_args():
     parser = argparse.ArgumentParser(
         description=inspect.getdoc(sys.modules[__name__]))
@@ -1622,7 +1629,7 @@
         help='Skip building tests after building the NDK.')
 
     parser.add_argument(
-        '--build-number', default='dev',
+        '--build-number', default='0', type=build_number,
         help='Build number for use in version files.')
     parser.add_argument(
         '--release', help='Ignored. Temporarily compatibility.')
diff --git a/docs/Roadmap.md b/docs/Roadmap.md
index 8d3f9e2..2a33c00 100644
--- a/docs/Roadmap.md
+++ b/docs/Roadmap.md
@@ -84,8 +84,8 @@
 reduced.
 
 
-NDK r20
--------
+NDK r20+
+--------
 
 Estimated release: Q4 2018
 
@@ -119,6 +119,18 @@
 
 [cdep]: https://github.com/jomof/cdep
 
+### Unify CMake NDK Support Implementations
+
+CMake added their own NDK support about the same time we added our toolchain
+file. The two often conflict with each other, and a toolchain file is a messy
+way to implement this support. However, fully switching to the integrated
+support puts NDK policy deicisions (default options, NDK layout, etc) fully into
+the hands of CMake, which makes them impossible to update without the user also
+updating their CMake version.
+
+We should send patches to the CMake implementation that will load as much
+information about the NDK as possible from tables we provide in the NDK.
+
 
 Historical releases
 -------------------
diff --git a/tests/build/cmake-ANDROID_NDK_REVISION/CMakeLists.txt b/tests/build/cmake-ANDROID_NDK_REVISION/CMakeLists.txt
new file mode 100644
index 0000000..a13664a
--- /dev/null
+++ b/tests/build/cmake-ANDROID_NDK_REVISION/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.6.0)
+
+add_definitions(
+  -DNDK_MAJOR_FROM_CMAKE=${ANDROID_NDK_MAJOR}
+  -DNDK_MINOR_FROM_CMAKE=${ANDROID_NDK_MINOR}
+  -DNDK_BUILD_FROM_CMAKE=${ANDROID_NDK_BUILD}
+  -DNDK_BETA_FROM_CMAKE=${ANDROID_NDK_BETA}
+)
+
+add_executable(foo foo.cpp)
diff --git a/tests/build/cmake-ANDROID_NDK_REVISION/foo.cpp b/tests/build/cmake-ANDROID_NDK_REVISION/foo.cpp
new file mode 100644
index 0000000..0afb529
--- /dev/null
+++ b/tests/build/cmake-ANDROID_NDK_REVISION/foo.cpp
@@ -0,0 +1,19 @@
+#include <android/ndk-version.h>
+
+#if __NDK_MAJOR__ != NDK_MAJOR_FROM_CMAKE
+#error __NDK_MAJOR__ != NDK_MAJOR_FROM_CMAKE
+#endif
+
+#if __NDK_MINOR__ != NDK_MINOR_FROM_CMAKE
+#error __NDK_MINOR__ != NDK_MINOR_FROM_CMAKE
+#endif
+
+#if __NDK_BETA__ != NDK_BETA_FROM_CMAKE
+#error __NDK_BETA__ != NDK_BETA_FROM_CMAKE
+#endif
+
+#if __NDK_BUILD__ != NDK_BUILD_FROM_CMAKE
+#error __NDK_BUILD__ != NDK_BUILD_FROM_CMAKE
+#endif
+
+int main() {}