Merge changes Ice859e8e,I44915dcd

* changes:
  Add typing info and documentation to ndk.builds.
  Provide type annotations for ndk.paths.
diff --git a/bootstrap/__init__.py b/bootstrap/__init__.py
new file mode 100644
index 0000000..27e707d
--- /dev/null
+++ b/bootstrap/__init__.py
@@ -0,0 +1,231 @@
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# 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.
+#
+"""Tools for bootstrapping Python 3."""
+import datetime
+import logging
+import multiprocessing
+import os
+import pipes
+import shutil
+import subprocess
+import sys
+import timeit
+
+
+THIS_DIR = os.path.realpath(os.path.dirname(__file__))
+
+
+def logger():
+    """Returns the module level logger."""
+    return logging.getLogger(__name__)
+
+
+def android_path(*args):
+    """Returns the absolute path rooted within the top level source tree."""
+    return os.path.normpath(os.path.join(THIS_DIR, '../..', *args))
+
+
+def _get_dir_from_env(default, env_var):
+    """Returns the path to a directory specified by the environment.
+
+    If the environment variable is not set, the default will be used. The
+    directory is created if it does not exist.
+
+    Args:
+        default: The path used if the environment variable is not set.
+        env_var: The environment variable that contains the path, if any.
+
+    Returns:
+        The absolute path to the directory.
+    """
+    path = os.path.realpath(os.getenv(env_var, default))
+    if not os.path.isdir(path):
+        os.makedirs(path)
+    return path
+
+
+def get_out_dir():
+    """Returns the out directory."""
+    return _get_dir_from_env(android_path('out'), 'OUT_DIR')
+
+
+def get_dist_dir():
+    """Returns the distribution directory.
+
+    The contents of the distribution directory are archived on the build
+    servers. Suitable for build logs and final artifacts.
+    """
+    return _get_dir_from_env(os.path.join(get_out_dir(), 'dist'), 'DIST_DIR')
+
+
+def path_in_out(dirname):
+    """Returns a path within the out directory."
+
+    Args:
+        dirname: Name of the directory.
+
+    Returns:
+        Absolute path within the out directory.
+    """
+    return os.path.join(get_out_dir(), dirname)
+
+
+def log_failure_and_exit(output):
+    """Logs the bootstrapping failure and exits.
+
+    Args:
+        output: Output of the failed command.
+    """
+    log_path = os.path.join(get_dist_dir(), 'logs/build_error.log')
+    with open(log_path, 'w') as error_log:
+        error_log.write('Bootstrapping failed!\n')
+        error_log.write(output)
+
+    logger().error(output)
+    sys.exit('Bootstrapping failed!')
+
+
+def check_output(cmd):
+    """Logged version of subprocess.check_output.
+
+    stderr is automatically forwarded to stdout.
+
+    Args:
+        cmd: argv style argument list for the process to be run.
+
+    Returns:
+        Output
+    """
+    logger().debug('Runnning: %s', ' '.join([pipes.quote(a) for a in cmd]))
+    return subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+
+
+def build_python(install_dir, build_dir):
+    """Builds and installs Python to the given directory.
+
+    Args:
+        install_dir: Install path for the built Python distribution.
+        build_dir: Directory to use for building Python.
+    """
+    logger().info('Bootstrapping Python...')
+
+    if os.path.exists(build_dir):
+        shutil.rmtree(build_dir)
+    os.makedirs(build_dir)
+
+    old_cwd = os.getcwd()
+    try:
+        os.chdir(build_dir)
+
+        python_src = android_path('external/python/cpython3')
+        check_output([
+            os.path.join(python_src, 'configure'),
+            '--prefix=' + install_dir,
+
+            # This enables PGO and requires running all the Python tests to
+            # generate those profiles. If we end up repackaging this Python to
+            # ship in the NDK we should do this, but for now it makes
+            # bootstrapping take a lot longer and we don't need the perforance
+            # since our build time is dominated by non-Python code anyway.
+            # '--enable-optimizations',
+        ])
+
+        check_output([
+            'make',
+            '-j',
+            str(multiprocessing.cpu_count()),
+            'install',
+        ])
+    except subprocess.CalledProcessError as ex:
+        log_failure_and_exit(ex.output)
+    finally:
+        os.chdir(old_cwd)
+
+
+class Timer(object):  # pylint: disable=useless-object-inheritance
+    """Execution timer.
+
+    Can be used explicitly with stop/start, but preferably is used as a context
+    manager:
+
+    >>> timer = Timer()
+    >>> with timer:
+    >>>     do_something()
+    >>> print('do_something() took {}'.format(timer.duration))
+    """
+    def __init__(self):
+        self.start_time = None
+        self.end_time = None
+        self.duration = None
+
+    def start(self):
+        """Start the timer."""
+        self.start_time = timeit.default_timer()
+
+    def finish(self):
+        """Stop the timer."""
+        self.end_time = timeit.default_timer()
+
+        # Not interested in partial seconds at this scale.
+        seconds = int(self.end_time - self.start_time)
+        self.duration = datetime.timedelta(seconds=seconds)
+
+    def __enter__(self):
+        self.start()
+
+    def __exit__(self, _exc_type, _exc_value, _traceback):
+        self.finish()
+
+
+def do_bootstrap(install_dir):
+    """Helper function for bootstrapping.
+
+    Builds and installs Python 3 if necessary, but does not modify the
+    environment.
+
+    Args:
+        install_dir: Directory in which to install Python 3.
+
+    Returns:
+        Python 3 install directory.
+    """
+    build_dir = path_in_out('bootstrap-build')
+
+    bootstrap_completed_file = path_in_out('.bootstrapped')
+    if os.path.exists(bootstrap_completed_file):
+        return
+
+    timer = Timer()
+    with timer:
+        build_python(install_dir, build_dir)
+    # TODO: Install any desired site-packages?
+    logger().info('Bootstrapping completed in %s', timer.duration)
+
+    with open(bootstrap_completed_file, 'w'):
+        pass
+
+
+def bootstrap():
+    """Creates a bootstrap Python 3 environment.
+
+    Builds and installs Python 3 for use on the current host. After execution,
+    the directory containing the python3 binary will be the first element in
+    the PATH.
+    """
+    install_dir = path_in_out('bootstrap')
+    do_bootstrap(install_dir)
+    bootstrap_bin = os.path.join(install_dir, 'bin')
+    os.environ['PATH'] = os.pathsep.join([bootstrap_bin, os.environ['PATH']])
diff --git a/build/cmake/android.toolchain.cmake b/build/cmake/android.toolchain.cmake
index 1b03647..f568453 100644
--- a/build/cmake/android.toolchain.cmake
+++ b/build/cmake/android.toolchain.cmake
@@ -407,10 +407,10 @@
 set(CMAKE_CXX_COMPILER_ID_RUN TRUE)
 set(CMAKE_C_COMPILER_ID Clang)
 set(CMAKE_CXX_COMPILER_ID Clang)
-set(CMAKE_C_COMPILER_VERSION 7.0)
-set(CMAKE_CXX_COMPILER_VERSION 7.0)
+set(CMAKE_C_COMPILER_VERSION 8.0)
+set(CMAKE_CXX_COMPILER_VERSION 8.0)
 set(CMAKE_C_STANDARD_COMPUTED_DEFAULT 11)
-set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT 98)
+set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT 14)
 set(CMAKE_C_COMPILER_TARGET   ${ANDROID_LLVM_TRIPLE})
 set(CMAKE_CXX_COMPILER_TARGET ${ANDROID_LLVM_TRIPLE})
 set(CMAKE_ASM_COMPILER_TARGET ${ANDROID_LLVM_TRIPLE})
@@ -466,7 +466,6 @@
 
 # STL specific flags.
 if(ANDROID_STL MATCHES "^c\\+\\+_")
-  list(APPEND ANDROID_COMPILER_FLAGS_CXX "-std=c++11")
   if(ANDROID_ABI MATCHES "^armeabi")
     list(APPEND ANDROID_LINKER_FLAGS "-Wl,--exclude-libs,libunwind.a")
   endif()
diff --git a/build/tools/make_standalone_toolchain.py b/build/tools/make_standalone_toolchain.py
index 3978d6b..0849cdc 100755
--- a/build/tools/make_standalone_toolchain.py
+++ b/build/tools/make_standalone_toolchain.py
@@ -121,7 +121,7 @@
         arch = 'armv7a'  # Target armv7, not armv5.
 
     target = '-'.join([arch, 'none', os_name, env])
-    flags = '-target {}{} -stdlib=libc++'.format(target, api)
+    flags = '-target {}{}'.format(target, api)
 
     # We only need mstackrealign to fix issues on 32-bit x86 pre-24. After 24,
     # this consumes an extra register unnecessarily, which can cause issues for
@@ -130,6 +130,8 @@
     if arch == 'i686' and api < 24:
         flags += ' -mstackrealign'
 
+    cxx_flags = flags + ' -stdlib=libc++'
+
     clang_path = os.path.join(install_dir, 'bin/clang')
     with open(clang_path, 'w') as clang:
         clang.write(textwrap.dedent("""\
@@ -155,7 +157,7 @@
                 # target/triple already spelled out.
                 `dirname $0`/clang{version}++ "$@"
             fi
-        """.format(version=version_number, flags=flags)))
+        """.format(version=version_number, flags=cxx_flags)))
 
     mode = os.stat(clangpp_path).st_mode
     os.chmod(clangpp_path, mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
@@ -167,6 +169,7 @@
 
     if windows:
         for pp_suffix in ('', '++'):
+            is_cpp = pp_suffix == '++'
             exe_name = 'clang{}{}.exe'.format(version_number, pp_suffix)
             clangbat_text = textwrap.dedent("""\
                 @echo off
@@ -191,7 +194,7 @@
                 exit /b
 
                 :done
-            """.format(exe=exe_name, flags=flags))
+            """.format(exe=exe_name, flags=cxx_flags if is_cpp else flags))
 
             for triple_prefix in ('', triple + '-'):
                 clangbat_path = os.path.join(
diff --git a/build/tools/prebuilt-common.sh b/build/tools/prebuilt-common.sh
index 5d57227..b3c6a01 100644
--- a/build/tools/prebuilt-common.sh
+++ b/build/tools/prebuilt-common.sh
@@ -1247,7 +1247,7 @@
 {
     local NAME DIR BINPREFIX
     local SYSTEM=${1:-$(get_prebuilt_host_tag)}
-    local VERSION=r339409b
+    local VERSION=r344140b
     SYSTEM=${SYSTEM%_64} # Trim _64 suffix. We only have one LLVM.
     BINPREFIX=$ANDROID_BUILD_TOP/prebuilts/clang/host/$SYSTEM/clang-$VERSION/bin
     echo "$BINPREFIX"
diff --git a/checkbuild.py b/checkbuild.py
index 25b29c0..da676df 100755
--- a/checkbuild.py
+++ b/checkbuild.py
@@ -20,214 +20,17 @@
 allowing this script to bootstrap our build with a specific version of Python.
 """
 import argparse
-import datetime
 import logging
-import multiprocessing
 import os
-import pipes
-import shutil
 import subprocess
 import sys
-import timeit
+
+from bootstrap import bootstrap
 
 
 THIS_DIR = os.path.realpath(os.path.dirname(__file__))
 
 
-def logger():
-    """Returns the module level logger."""
-    return logging.getLogger(__name__)
-
-
-def android_path(*args):
-    """Returns the absolute path rooted within the top level source tree."""
-    return os.path.normpath(os.path.join(THIS_DIR, '..', *args))
-
-
-def ndk_path(*args):
-    """Returns the absolute path rooted within the NDK source tree."""
-    return android_path('ndk', *args)
-
-
-def _get_dir_from_env(default, env_var):
-    """Returns the path to a directory specified by the environment.
-
-    If the environment variable is not set, the default will be used. The
-    directory is created if it does not exist.
-
-    Args:
-        default: The path used if the environment variable is not set.
-        env_var: The environment variable that contains the path, if any.
-
-    Returns:
-        The absolute path to the directory.
-    """
-    path = os.path.realpath(os.getenv(env_var, default))
-    if not os.path.isdir(path):
-        os.makedirs(path)
-    return path
-
-
-def get_out_dir():
-    """Returns the out directory."""
-    return _get_dir_from_env(android_path('out'), 'OUT_DIR')
-
-
-def get_dist_dir():
-    """Returns the distribution directory.
-
-    The contents of the distribution directory are archived on the build
-    servers. Suitable for build logs and final artifacts.
-    """
-    return _get_dir_from_env(os.path.join(get_out_dir(), 'dist'), 'DIST_DIR')
-
-
-def path_in_out(dirname):
-    """Returns a path within the out directory."
-
-    Args:
-        dirname: Name of the directory.
-
-    Returns:
-        Absolute path within the out directory.
-    """
-    return os.path.join(get_out_dir(), dirname)
-
-
-def log_failure_and_exit(output):
-    """Logs the bootstrapping failure and exits.
-
-    Args:
-        output: Output of the failed command.
-    """
-    log_path = os.path.join(get_dist_dir(), 'logs/build_error.log')
-    with open(log_path, 'w') as error_log:
-        error_log.write('Bootstrapping failed!\n')
-        error_log.write(output)
-
-    logger().error(output)
-    sys.exit('Bootstrapping failed!')
-
-
-def check_output(cmd):
-    """Logged version of subprocess.check_output.
-
-    stderr is automatically forwarded to stdout.
-
-    Args:
-        cmd: argv style argument list for the process to be run.
-
-    Returns:
-        Output
-    """
-    logger().debug('Runnning: %s', ' '.join([pipes.quote(a) for a in cmd]))
-    return subprocess.check_output(cmd, stderr=subprocess.STDOUT)
-
-
-def build_python(install_dir, build_dir):
-    """Builds and installs Python to the given directory.
-
-    Args:
-        install_dir: Install path for the built Python distribution.
-        build_dir: Directory to use for building Python.
-    """
-    logger().info('Bootstrapping Python...')
-
-    if os.path.exists(build_dir):
-        shutil.rmtree(build_dir)
-    os.makedirs(build_dir)
-
-    old_cwd = os.getcwd()
-    try:
-        os.chdir(build_dir)
-
-        python_src = android_path('external/python/cpython3')
-        check_output([
-            os.path.join(python_src, 'configure'),
-            '--prefix=' + install_dir,
-
-            # This enables PGO and requires running all the Python tests to
-            # generate those profiles. If we end up repackaging this Python to
-            # ship in the NDK we should do this, but for now it makes
-            # bootstrapping take a lot longer and we don't need the perforance
-            # since our build time is dominated by non-Python code anyway.
-            # '--enable-optimizations',
-        ])
-
-        check_output([
-            'make',
-            '-j',
-            str(multiprocessing.cpu_count()),
-            'install',
-        ])
-    except subprocess.CalledProcessError as ex:
-        log_failure_and_exit(ex.output)
-    finally:
-        os.chdir(old_cwd)
-
-
-class Timer(object):  # pylint: disable=useless-object-inheritance
-    """Execution timer.
-
-    Can be used explicitly with stop/start, but preferably is used as a context
-    manager:
-
-    >>> timer = Timer()
-    >>> with timer:
-    >>>     do_something()
-    >>> print('do_something() took {}'.format(timer.duration))
-    """
-    def __init__(self):
-        self.start_time = None
-        self.end_time = None
-        self.duration = None
-
-    def start(self):
-        """Start the timer."""
-        self.start_time = timeit.default_timer()
-
-    def finish(self):
-        """Stop the timer."""
-        self.end_time = timeit.default_timer()
-
-        # Not interested in partial seconds at this scale.
-        seconds = int(self.end_time - self.start_time)
-        self.duration = datetime.timedelta(seconds=seconds)
-
-    def __enter__(self):
-        self.start()
-
-    def __exit__(self, _exc_type, _exc_value, _traceback):
-        self.finish()
-
-
-def bootstrap():
-    """Bootstraps the NDK's build.
-
-    Builds the Python distribution needed for building the NDK.
-
-    Returns:
-        Install directory for the built Python distribution.
-    """
-    install_dir = path_in_out('bootstrap')
-    build_dir = path_in_out('bootstrap-build')
-
-    bootstrap_completed_file = path_in_out('.bootstrapped')
-    if os.path.exists(bootstrap_completed_file):
-        return install_dir
-
-    timer = Timer()
-    with timer:
-        build_python(install_dir, build_dir)
-    # TODO: Install any desired site-packages?
-    logger().info('Bootstrapping completed in %s', timer.duration)
-
-    with open(bootstrap_completed_file, 'w'):
-        pass
-
-    return install_dir
-
-
 def parse_args():
     """Parses and returns command line arguments."""
     parser = argparse.ArgumentParser()
@@ -253,11 +56,9 @@
     else:
         logging.basicConfig(level=logging.INFO)
 
-    python_install = bootstrap()
-    bootstrap_bin = os.path.join(python_install, 'bin')
-    os.environ['PATH'] = os.pathsep.join([bootstrap_bin, os.environ['PATH']])
-    subprocess.check_call(['python3', ndk_path('do_checkbuild.py')] +
-                          sys.argv[1:])
+    bootstrap()
+    subprocess.check_call(
+        ['python3', os.path.join(THIS_DIR, 'do_checkbuild.py')] + sys.argv[1:])
 
 
 if __name__ == '__main__':
diff --git a/docs/changelogs/Changelog-r19.md b/docs/changelogs/Changelog-r19.md
index 98c754e..d4a5e2e 100644
--- a/docs/changelogs/Changelog-r19.md
+++ b/docs/changelogs/Changelog-r19.md
@@ -54,6 +54,7 @@
 -------
 
  * Updated Clang to r339409.
+     * C++ compilation now defaults to C++14.
  * [Issue 780]: A complete NDK toolchain is now installed to the Clang
    directory. See the announcements section for more information.
  * ndk-build no longer removes artifacts from `NDK_LIBS_OUT` for ABIs not
diff --git a/docs/changelogs/Changelog-r20.md b/docs/changelogs/Changelog-r20.md
index a9a0db4..6b95c4f 100644
--- a/docs/changelogs/Changelog-r20.md
+++ b/docs/changelogs/Changelog-r20.md
@@ -20,6 +20,8 @@
 
 ## Changes
 
+ * Updated Clang to r344140.
+
 ## Known Issues
 
  * This is not intended to be a comprehensive list of all outstanding bugs.
diff --git a/ndk/checkbuild.py b/ndk/checkbuild.py
index a44e029..4444006 100755
--- a/ndk/checkbuild.py
+++ b/ndk/checkbuild.py
@@ -227,7 +227,7 @@
 class Clang(ndk.builds.Module):
     name = 'clang'
     path = 'toolchains/llvm/prebuilt/{host}'
-    version = 'clang-r339409b'
+    version = 'clang-r344140b'
     notice_group = ndk.builds.NoticeGroup.TOOLCHAIN
 
     @property