Automate more parts of config release. (#126)

* Automate more parts of config release.
diff --git a/.gitignore b/.gitignore
index 62c8d69..f4f2b91 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,6 @@
 /bazel-*
 # Ignore outputs generated during Bazel bootstrapping.
 /output/
+# Python runtime generated from .bzl files.
+*.bzlc
+*.pyc
diff --git a/WORKSPACE b/WORKSPACE
index 4f70e76..514424d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -99,7 +99,7 @@
 # l.gcr.io/google/clang-debian8:r328903
 container_pull(
     name = "debian8-clang",
-    digest = "sha256:8bb65bf0a0da8be48bbac07ebe743805f3dc5259203e19517098162bd23a768f",
+    digest = toolchain_container_sha256s()["debian8_clang"],
     registry = "l.gcr.io",
     repository = "google/clang-debian8",
 )
@@ -108,7 +108,7 @@
 # l.gcr.io/google/clang-ubuntu:r328903
 container_pull(
     name = "ubuntu16_04-clang",
-    digest = "sha256:d553634f23f7c437ca35bbc4b6f1f38bb81be32b9ef2df4329dcd36762277bf7",
+    digest = toolchain_container_sha256s()["ubuntu16_04_clang"],
     registry = "l.gcr.io",
     repository = "google/clang-ubuntu",
 )
diff --git a/release/bazelrc.py b/release/bazelrc.py
new file mode 100644
index 0000000..c4bddda
--- /dev/null
+++ b/release/bazelrc.py
@@ -0,0 +1,63 @@
+# Copyright 2016 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.
+"""Module to generate sample bazelrc file."""
+
+import os
+from string import Template
+
+from util import get_git_root
+
+GIT_ROOT = get_git_root()
+BAZELRC_DIR = os.path.join(GIT_ROOT, "bazelrc")
+LATEST_BAZELRC_LINK = BAZELRC = os.path.join(BAZELRC_DIR, "latest.bazelrc")
+LICENCE_TPL = os.path.join(GIT_ROOT, "release", "license.tpl")
+BAZELRC_TPL = os.path.join(GIT_ROOT, "release", "bazelrc.tpl")
+
+
+def create_bazelrc_and_update_link(bazel_version):
+  """Creates new sample .bazelrc file and update latest.bazelrc symlink.
+
+  Example bazelrc files can be found in directory bazelrc/.
+
+  There is one sample bazelrc file Bazel version. bazelrc/latest.bazelrc should
+  always be symlinked to the .bazelrc file for the latest version of Bazel.
+
+  If the file already exists in this repo, the script will delete it and
+  generate new one.
+
+  Args:
+    bazel_version: string, the version of Bazel used to generate the configs.
+
+  """
+  bazelrc_path = os.path.join(
+      BAZELRC_DIR, "bazel-{version}.bazelrc".format(version=bazel_version))
+
+  # Remove old version of this .bazelrc file.
+  if os.path.exists(bazelrc_path):
+    os.remove(bazelrc_path)
+
+  with open(bazelrc_path, "w") as bazelrc_file:
+    # Write license header.
+    with open(LICENCE_TPL, "r") as license_header:
+      bazelrc_file.write(license_header.read())
+
+    # Write sample .bazelrc body.
+    with open(BAZELRC_TPL, "r") as tpl_file:
+      tpl = Template(tpl_file.read()).substitute(BAZEL_VERSION=bazel_version)
+      bazelrc_file.write(tpl)
+
+  # Update latest.bazelrc link
+  if os.path.exists(LATEST_BAZELRC_LINK):
+    os.remove(LATEST_BAZELRC_LINK)
+  os.symlink(os.path.basename(bazelrc_path), LATEST_BAZELRC_LINK)
diff --git a/release/bazelrc.tpl b/release/bazelrc.tpl
new file mode 100644
index 0000000..43dbd95
--- /dev/null
+++ b/release/bazelrc.tpl
@@ -0,0 +1,126 @@
+# This file is auto-generated from release/bazelrc.tpl and should not be
+# modified directly.
+
+# This .bazelrc file contains all of the flags required for the toolchain,
+# Remote Build Execution, and the Bazel Build Results UI. Specific flags in
+# your Bazel command allow you to use only the remote build, to use only the
+# results UI, or to use them both together.
+#
+# This .bazelrc file also contains all of the flags required for the local
+# docker sandboxing.
+
+# Remote Build Execution requires a strong hash function, such as SHA256.
+startup --host_jvm_args=-Dbazel.DigestFunction=SHA256
+
+# Depending on how many machines are in the remote execution instance, setting
+# this higher can make builds faster by allowing more jobs to run in parallel.
+# Setting it too high can result in jobs that timeout, however, while waiting
+# for a remote machine to execute them.
+build:remote --jobs=50
+
+# Set several flags related to specifying the platform, toolchain and java
+# properties.
+# These flags are duplicated rather than imported from (for example)
+# %workspace%/configs/ubuntu16_04_clang/1.0/toolchain.bazelrc to make this
+# bazelrc a standalone file that can be copied more easily.
+# These flags should only be used as is for the rbe-ubuntu16-04 container
+# and need to be adapted to work with other toolchain containers.
+build:remote --host_javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:jdk8
+build:remote --javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:jdk8
+build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
+build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
+build:remote --crosstool_top=@bazel_toolchains//configs/ubuntu16_04_clang/1.0/bazel_${BAZEL_VERSION}/default:toolchain
+build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
+# Platform flags:
+# The toolchain container used for execution is defined in the target indicated
+# by "extra_execution_platforms", "host_platform" and "platforms".
+# If you are using your own toolchain container, you need to create a platform
+# target with "constraint_values" that allow for the toolchain specified with
+# "extra_toolchains" to be selected (given constraints defined in
+# "exec_compatible_with").
+# More about platforms: https://docs.bazel.build/versions/master/platforms.html
+build:remote --extra_toolchains=@bazel_toolchains//configs/ubuntu16_04_clang/1.0/bazel_${BAZEL_VERSION}/cpp:cc-toolchain-clang-x86_64-default
+build:remote --extra_execution_platforms=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:rbe_ubuntu1604
+build:remote --host_platform=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:rbe_ubuntu1604
+build:remote --platforms=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:rbe_ubuntu1604
+
+# Set various strategies so that all actions execute remotely. Mixing remote
+# and local execution will lead to errors unless the toolchain and remote
+# machine exactly match the host machine.
+build:remote --spawn_strategy=remote
+build:remote --strategy=Javac=remote
+build:remote --strategy=Closure=remote
+build:remote --genrule_strategy=remote
+build:remote --define=EXECUTOR=remote
+
+# Enable the remote cache so action results can be shared across machines,
+# developers, and workspaces.
+build:remote --remote_cache=remotebuildexecution.googleapis.com
+
+# Enable remote execution so actions are performed on the remote systems.
+build:remote --remote_executor=remotebuildexecution.googleapis.com
+
+# Enable encryption.
+build:remote --tls_enabled=true
+
+# Enforce stricter environment rules, which eliminates some non-hermetic
+# behavior and therefore improves both the remote cache hit rate and the
+# correctness and repeatability of the build.
+build:remote --experimental_strict_action_env=true
+
+# Set a higher timeout value, just in case.
+build:remote --remote_timeout=3600
+
+# Enable authentication. This will pick up application default credentials by
+# default. You can use --auth_credentials=some_file.json to use a service
+# account credential instead.
+build:remote --auth_enabled=true
+
+# Set flags for uploading to BES in order to view results in the Bazel Build
+# Results UI.
+build:results --bes_backend="buildeventservice.googleapis.com"
+build:results --bes_timeout=60s
+
+# If the upload to BES fails, the build will fail.
+build:results --bes_best_effort=false
+
+# Output BES results url
+build:results --bes_results_url="https://source.cloud.google.com/results/invocations/"
+
+# Set flags for uploading to BES without Remote Build Execution.
+build:results-local --bes_backend="buildeventservice.googleapis.com"
+build:results-local --bes_timeout=60s
+build:results-local --bes_best_effort=false
+build:results-local --tls_enabled=true
+build:results-local --auth_enabled=true
+build:results-local --spawn_strategy=local
+build:results-local --experimental_remote_spawn_cache
+build:results-local --remote_cache=remotebuildexecution.googleapis.com
+build:results-local --remote_timeout=3600
+build:results-local --bes_results_url="https://source.cloud.google.com/results/invocations/"
+
+# The following flags are only necessary for local docker sandboxing
+# with the rbe-ubuntu16-04 container. Use of these flags is still experimental.
+build:docker-sandbox --host_javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:jdk8
+build:docker-sandbox --javabase=@bazel_toolchains//configs/ubuntu16_04_clang/1.0:jdk8
+build:docker-sandbox --crosstool_top=@bazel_toolchains//configs/ubuntu16_04_clang/1.0/bazel_${BAZEL_VERSION}/default:toolchain
+build:docker-sandbox --experimental_docker_image=gcr.io/cloud-marketplace/google/rbe-ubuntu16-04@sha256:59bf0e191a6b5cc1ab62c2224c810681d1326bad5a27b1d36c9f40113e79da7f
+build:docker-sandbox --spawn_strategy=docker
+build:docker-sandbox --strategy=Javac=docker
+build:docker-sandbox --strategy=Closure=docker
+build:docker-sandbox --genrule_strategy=docker
+build:docker-sandbox --define=EXECUTOR=remote
+build:docker-sandbox --experimental_docker_verbose
+build:docker-sandbox --experimental_enable_docker_sandbox
+
+# The following flags enable the remote cache so action results can be shared
+# across machines, developers, and workspaces.
+build:remote-cache --remote_cache=remotebuildexecution.googleapis.com
+build:remote-cache --tls_enabled=true
+build:remote-cache --experimental_strict_action_env=true
+build:remote-cache --remote_timeout=3600
+build:remote-cache --auth_enabled=true
+build:remote-cache --spawn_strategy=standalone
+build:remote-cache --strategy=Javac=standalone
+build:remote-cache --strategy=Closure=standalone
+build:remote-cache --genrule_strategy=standalone
diff --git a/release/cc/__init__.py b/release/cc/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/release/cc/__init__.py
diff --git a/release/cc/cpp.tpl b/release/cc/cpp.tpl
new file mode 100644
index 0000000..d2cd6d9
--- /dev/null
+++ b/release/cc/cpp.tpl
@@ -0,0 +1,17 @@
+# This target is auto-generated from release/cpp.tpl and should not be
+# modified directly.
+toolchain(
+    name = "cc-toolchain-clang-x86_64-${TYPE}",
+    exec_compatible_with = [
+        "@bazel_tools//platforms:linux",
+        "@bazel_tools//platforms:x86_64",
+        "@bazel_tools//tools/cpp:clang",
+        ${EXTRA_CONSTRAINTS}
+    ],
+    target_compatible_with = [
+        "@bazel_tools//platforms:linux",
+        "@bazel_tools//platforms:x86_64",
+    ],
+    toolchain = "//${PACKAGE}/${CONFIG_VERSION}/bazel_${BAZEL_VERSION}/${TYPE}:cc-compiler-k8",
+    toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
diff --git a/release/cc/create_artifacts.py b/release/cc/create_artifacts.py
new file mode 100644
index 0000000..b43313b
--- /dev/null
+++ b/release/cc/create_artifacts.py
@@ -0,0 +1,181 @@
+# Copyright 2016 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.
+"""Module to add METADATA and cc toolchain targets to BUILD for all configs."""
+
+import imp
+import os
+import shlex
+import shutil
+from string import Template
+import subprocess
+
+from util import get_autoconfig_target_name
+from util import get_date
+from util import get_git_root
+
+BUILD_EXTRA_LICENCE = """
+licenses(["notice"])  # Apache 2.0
+
+package(default_visibility = ["//visibility:public"])
+"""
+
+GIT_ROOT = get_git_root()
+LICENCE_TPL = os.path.join(GIT_ROOT, "release", "license.tpl")
+CPP_TPL = os.path.join(GIT_ROOT, "release", "cc", "cpp.tpl")
+SHA_MAP_FILE = os.path.join(GIT_ROOT, "rules/toolchain_containers.bzl")
+
+
+def create_targets(container_configs_list, bazel_version):
+  """Creates the new docker_toolchain_autoconfig target if not exists.
+
+  An example target located in configs/ubuntu16_04_clang/BUILD is:
+  //configs/ubuntu16_04_clang:msan-ubuntu16_04-clang-1.0-bazel_0.15.0-autoconfig
+
+  There is one target per container per Bazel version per config type.
+
+  The script only creates new targets in the BUILD file if they do not exist,
+  i.e. if a target for the given version of Bazel, type and config version
+  already exists, then the script does not re-create it.
+
+  Args:
+    container_configs_list: list of ContainerConfigs, the list of
+      ContainerConfigs to generate configs for.
+    bazel_version: string, the version of Bazel used to generate the configs.
+
+  """
+
+  container_sha_map = imp.load_source("toolchain_containers", SHA_MAP_FILE)
+
+  for container_configs in container_configs_list:
+
+    # Get the sha256 value of the container used to generate the configs.
+    sha = container_sha_map.toolchain_container_sha256s()[
+        "%s_clang" % container_configs.distro]
+
+    for config in container_configs.configs:
+
+      # Get target basename from config definitions.
+      target = get_autoconfig_target_name(
+          config_type=config.config_type,
+          distro=container_configs.distro,
+          config_version=container_configs.version,
+          bazel_version=bazel_version)
+
+      with open(container_configs.get_target_build_path(), "a+") as build_file:
+        if target not in build_file.read():
+          tpl_file_path = os.path.join(GIT_ROOT, "release", "cc",
+                                       "%s.tpl" % config.config_type)
+          with open(tpl_file_path, "r") as tpl_file:
+            tpl = Template(tpl_file.read()).substitute(
+                DATE=get_date(),
+                DISTRO=container_configs.distro,
+                CONFIG_VERSION=container_configs.version,
+                BAZEL_VERSION=bazel_version,
+                NAME=container_configs.image,
+                SHA=sha)
+
+            build_file.write(tpl)
+
+
+def generate_toolchain_definition(container_configs_list, bazel_version):
+  """Generates new cpp toolchain definitions.
+
+  Example cpp toolchain definitions for clang-ubuntu container are located in
+  configs/ubuntu16_04_clang/1.0/bazel_0.15.0/cpp/.
+
+  There is one BUILD file to contain all cpp toolchain definitions for each
+  config type (e.g. default, msan) per container per Bazel version.
+
+  If the file already exists in this repo, the script will delete it and
+  generate new one.
+
+  Args:
+    container_configs_list: list of ContainerConfigs, the list of
+      ContainerConfigs to generate configs for.
+    bazel_version: string, the version of Bazel used to generate the configs.
+
+  """
+
+  for container_configs in container_configs_list:
+
+    cpp_dir = os.path.dirname(container_configs.get_cpp_build_path())
+
+    # Remove old cpp directory if exists.
+    if os.path.exists(cpp_dir):
+      print("\nOld version of cpp toolchain definition already exists. "
+            "Deleting and generating again.")
+      shutil.rmtree(cpp_dir)
+    os.makedirs(cpp_dir)
+
+    with open(container_configs.get_cpp_build_path(), "w") as build_file:
+      # Write license header.
+      with open(LICENCE_TPL, "r") as license_header:
+        build_file.write(license_header.read())
+
+      # Write extra license string required for BUILD file.
+      build_file.write(BUILD_EXTRA_LICENCE)
+
+    for config in container_configs.configs:
+
+      with open(container_configs.get_cpp_build_path(), "a") as build_file:
+        with open(CPP_TPL, "r") as tpl_file:
+
+          # Merge constraint lists. Remove duplicates while perserving order.
+          constraints = container_configs.constraints
+          for constraint in config.constraints:
+            if constraint not in constraints:
+              constraints.append(constraint)
+
+          tpl = Template(tpl_file.read()).substitute(
+              TYPE=config.config_type,
+              CONFIG_VERSION=container_configs.version,
+              BAZEL_VERSION=bazel_version,
+              PACKAGE=container_configs.package,
+              EXTRA_CONSTRAINTS="\n".join(
+                  [("\"%s\"," % constraint) for constraint in constraints]))
+
+          build_file.write(tpl)
+
+      subprocess.call(
+          shlex.split("buildifier %s" % container_configs.get_cpp_build_path()))
+
+
+def generate_metadata(container_configs_list):
+  """Creates the METADATA file with the container register path.
+
+  Example METADATA file can be found at
+  configs/ubuntu16_04_clang/1.0/bazel_0.15.0/default/METADATA.
+
+  There is one METADATA file per container per Bazel version per config type.
+
+  If the file already exists in this repo, the script will delete it and
+  generate new one.
+
+  Args:
+    container_configs_list: list of ContainerConfigs, the list of
+      ContainerConfigs to generate configs for.
+
+  """
+
+  container_sha_map = imp.load_source("toolchain_containers", SHA_MAP_FILE)
+
+  for container_configs in container_configs_list:
+    # Get the sha256 value of the container used to generate the configs.
+    sha = container_sha_map.toolchain_container_sha256s()[
+        "%s_clang" % container_configs.distro]
+
+    for config in container_configs.configs:
+      with open(config.get_metadata_path(), "w") as metadata_file:
+        metadata_file.write("{image}@{sha}\n".format(
+            image=container_configs.image, sha=sha))
diff --git a/release/cc/default.tpl b/release/cc/default.tpl
new file mode 100644
index 0000000..0a9bb35
--- /dev/null
+++ b/release/cc/default.tpl
@@ -0,0 +1,15 @@
+# This target is auto-generated from release/default.tpl and should not be
+# modified directly.
+# Created on ${DATE}
+# Container: ${NAME}@${SHA}
+docker_toolchain_autoconfig(
+    name = "default-${DISTRO}-clang-${CONFIG_VERSION}-bazel_${BAZEL_VERSION}-autoconfig",
+    additional_repos = ${DISTRO}_clang_default_repos(),
+    base = "@${DISTRO}-clang//image",
+    bazel_version = "${BAZEL_VERSION}",
+    env = clang_env(),
+    keys = ${DISTRO}_clang_default_keys(),
+    packages = ${DISTRO}_clang_default_packages(),
+    tags = ["manual"],
+    test = True,
+)
diff --git a/release/cc/execute_targets.py b/release/cc/execute_targets.py
new file mode 100644
index 0000000..b533500
--- /dev/null
+++ b/release/cc/execute_targets.py
@@ -0,0 +1,102 @@
+# Copyright 2016 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.
+"""Module to exec cc toolchain targets and extract contents for all configs."""
+
+from __future__ import print_function
+
+import atexit
+import os
+import shlex
+import shutil
+import subprocess
+import tarfile
+
+from util import get_autoconfig_target_name
+from util import get_git_root
+
+GIT_ROOT = get_git_root()
+CONFIG_REPO = "local_config_cc"
+CONFIG_FILES = ["CROSSTOOL", "BUILD", "cc_wrapper.sh", "dummy_toolchain.bzl"]
+TMP_DIR = os.path.join(GIT_ROOT, "release", "tmp")
+
+
+def _cleanup():
+  """Cleanup generated files."""
+  if os.path.exists(TMP_DIR):
+    shutil.rmtree(TMP_DIR)
+
+
+def execute_and_extract_configs(container_configs_list, bazel_version):
+  """Executes the docker_toolchain_autoconfig targets and extract configs.
+
+  If configs already exist in this repo, the script will delete them and
+  generate new ones.
+
+  It generate cc configs which currently includes: CROSSTOOL, BUILD,
+  cc_wrapper.sh and dummy_toolchain.bzl. Examples can be found in
+  configs/ubuntu16_04_clang/1.0/bazel_0.15.0/default/.
+
+  There is one such set of cc configs per container per Bazel version per config
+  type.
+
+  Args:
+    container_configs_list: list of ContainerConfigs, the list of
+      ContainerConfigs to generate configs for.
+    bazel_version: string, the version of Bazel used to generate the configs.
+
+  """
+
+  atexit.register(_cleanup)
+
+  # Create temporary directory to store generated tarballs of configs.
+  if os.path.exists(TMP_DIR):
+    shutil.rmtree(TMP_DIR)
+  os.makedirs(TMP_DIR)
+
+  for container_configs in container_configs_list:
+    for config in container_configs.configs:
+
+      # Get target basename from config definitions.
+      target = get_autoconfig_target_name(
+          config_type=config.config_type,
+          distro=container_configs.distro,
+          config_version=container_configs.version,
+          bazel_version=bazel_version)
+
+      # Remove old config dir if exists.
+      if os.path.exists(config.get_config_dir()):
+        print("\nOld version of toolchain configs for {target} already exists. "
+              "Deleting and generating again.".format(target=target))
+        shutil.rmtree(config.get_config_dir())
+
+      # Generate config directory.
+      os.makedirs(config.get_config_dir())
+
+      command = ("bazel run --define=DOCKER_AUTOCONF_OUTPUT={OUTPUT_DIR} "
+                 "//{PACKAGE}:{TARGET}").format(
+                     OUTPUT_DIR=TMP_DIR,
+                     PACKAGE=container_configs.package,
+                     TARGET=target)
+      print("\nExecuting command: %s\n" % command)
+      subprocess.call(shlex.split(command))
+
+      # Extract toolchain configs.
+      tar_path = os.path.join(TMP_DIR, "%s.tar" % target)
+      tar = tarfile.open(tar_path)
+
+      for config_file in CONFIG_FILES:
+        # Extract toolchain config without the CONFIG_REPO name.
+        member = tar.getmember(os.path.join(CONFIG_REPO, config_file))
+        member.name = os.path.basename(member.name)
+        tar.extract(member, config.get_config_dir())
diff --git a/release/cc/msan.tpl b/release/cc/msan.tpl
new file mode 100644
index 0000000..dc65fa6
--- /dev/null
+++ b/release/cc/msan.tpl
@@ -0,0 +1,17 @@
+# This target is auto-generated from release/msan.tpl and should not be
+# modified directly.
+# Created on ${DATE}
+# Container: ${NAME}@${SHA}
+docker_toolchain_autoconfig(
+    name = "msan-${DISTRO}-clang-${CONFIG_VERSION}-bazel_${BAZEL_VERSION}-autoconfig",
+    additional_repos = ${DISTRO}_clang_default_repos(),
+    base = "@${DISTRO}-clang//image",
+    bazel_version = "${BAZEL_VERSION}",
+    env = clang_env() + {
+        "BAZEL_LINKOPTS": "-lc++:-lc++abi:-lm",
+    },
+    keys = ${DISTRO}_clang_default_keys(),
+    packages = ${DISTRO}_clang_default_packages(),
+    tags = ["manual"],
+    test = True,
+)
diff --git a/release/config.py b/release/config.py
new file mode 100644
index 0000000..ec0ca90
--- /dev/null
+++ b/release/config.py
@@ -0,0 +1,186 @@
+# Copyright 2016 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.
+"""Data structures of toolchain configs."""
+
+import os
+
+
+class ContainerConfigs(object):
+  """Group of configs that are generated using the same container.
+
+  Attributes:
+    distro: string, base distro of container used to generate configs.
+    version: string, version of the configs.
+    image: string, the container registry entry of the image used to
+      generated the configs, e.g. gcr.io/cloud-marketplace/google/clang-ubuntu.
+    package: string, the Bazel package in which we will generate the target to
+      build configs.
+    platform_target: string, the platform target name of the corresponding RBE
+      container these configs will be used together with, e.g. rbe_ubuntu1604.
+      This is required to set value for flags:
+         --extra_execution_platforms, --host_platform and --platforms.
+        (Platform: https://docs.bazel.build/versions/master/platforms.html)
+    constraints: string, additional toolchain constraints needed for the cpp
+      toolchain definition.
+      These must be valid targets in this repo or @bazel_tools.
+      (Toolchain: https://docs.bazel.build/versions/master/toolchains.html)
+    configs: list of Config object, a list of configs for each supported types
+      generated using the container specified in the current ContainerConfig.
+  """
+
+  # Currently supported distros.
+  _SUPPORTED_DISTROS = ["debian8", "ubuntu16_04"]
+
+  # Map from the container distro to additional pre-defined cpp toolchain
+  # definition constraints.
+  _DISTRO_CONSTRAINTS_MAP = {
+      "debian8": ["//constraints:jessie"],
+      "ubuntu16_04": ["//constraints:xenial"]
+  }
+
+  def __init__(self, distro, version, image, package, config_types,
+               platform_target, git_root, bazel_version):
+    """Inits ContainerConfigs.
+
+    Args:
+      distro: string, base distro of container used to generate configs.
+      version: string, version of the configs.
+      image: string, the container registry entry of the image used to
+        generated the configs, e.g.
+        gcr.io/cloud-marketplace/google/clang-ubuntu.
+      package: string, the Bazel package in which we will generate the target to
+      build configs.
+      config_types: types of config to generated with this container, e.g.
+        default, msan.
+      platform_target: string, the platform target name of the corresponding RBE
+        container these configs will be used together with  e.g. rbe_ubuntu1604.
+        This is required to set value for flags:
+          --extra_execution_platforms, --host_platform and --platforms.
+          (Platform: https://docs.bazel.build/versions/master/platforms.html)
+      git_root: the absolute path of the root directory of the current
+        repository.
+      bazel_version: the version of Bazel used to generated the configs.
+
+    Returns:
+      A ContainerConfigs object.
+    Raises:
+      ValueError: An error occurred when input distro is not supported.
+    """
+
+    # Validate distro is supported.
+    if distro not in ContainerConfigs._SUPPORTED_DISTROS:
+      raise ValueError(
+          "Input distro: %s is not supported. Supported distros are %s" %
+          (distro, " ".join(ContainerConfigs._SUPPORTED_DISTROS)))
+
+    self._git_root = git_root
+    self._bazel_version = bazel_version
+
+    self.distro = distro
+    self.version = version
+    self.image = image
+    self.package = package
+    self.platform_target = platform_target
+    self.constraints = ContainerConfigs._DISTRO_CONSTRAINTS_MAP[distro]
+
+    self.configs = [
+        Config(root=self._get_config_base_dir(), config_type=config_type)
+        for config_type in config_types
+    ]
+
+  def get_target_build_path(self):
+    """Returns the absolute path of the target BUILD file."""
+    return os.path.join(self._git_root, self.package, "BUILD")
+
+  def get_toolchain_bazelrc_path(self):
+    """Returns the absolute path of the toolchain.bazelrc file."""
+    return os.path.join(self._git_root, self.package, self.version,
+                        "toolchain.bazelrc")
+
+  def get_platform_build_path(self):
+    """Returns the absolute path of BUILD file with platform definition."""
+    return os.path.join(self._git_root, self.package, self.version, "BUILD")
+
+  def get_java_runtime_build_path(self):
+    """Returns the absolute path of BUILD file with java runtime."""
+    return self.get_platform_build_path()
+
+  def get_cpp_build_path(self):
+    """Returns the absolute path of BUILD file with cpp toolchain definition."""
+    return os.path.join(self._get_config_base_dir(), "cpp", "BUILD")
+
+  def _get_config_base_dir(self):
+    """Returns the absolute path of bazel_{version} directory.
+
+    This returns the absolute path of bazel_{version} directory where configs
+    are stored in the bazel-toolchains repo.
+
+    For example: /.../configs/ubuntu16_04_clang/1.0/bazel_0.15.0/
+    """
+    return os.path.join(self._git_root, self.package, self.version,
+                        "bazel_%s" % self._bazel_version)
+
+
+class Config(object):
+  """Configs of a single type that are generated using a container.
+
+  Attributes:
+    config_type: string, type of the configs, e.g. default, msan.
+    constraints: string, additional toolchain constraints needed for the cpp
+      toolchain definition.
+      These must be valid targets in this repo or @bazel_tools.
+      (Toolchain: https://docs.bazel.build/versions/master/toolchains.html)
+  """
+
+  # Currently supported config types.
+  _SUPPORTED_CONFIG_TYPES = ["default", "msan"]
+
+  # Map from the config type to additional pre-defined cpp toolchain
+  # definition constraints.
+  _TYPE_CONSTRAINTS_MAP = {
+      "default": [],
+      "msan": ["//constraints/sanitizers:support_msan"]
+  }
+
+  def __init__(self, root, config_type):
+    """Inits Config.
+
+    Args:
+      root: string, absolute path to the bazel_{version} directory, e.g.
+        /.../configs/ubuntu16_04_clang/1.0/bazel_0.15.0/.
+      config_type: string, type of the configs.
+
+    Returns:
+      A Config object.
+    Raises:
+      ValueError: An error occurred when input config type is not supported.
+    """
+
+    # Validate config_type is supported.
+    if config_type not in Config._SUPPORTED_CONFIG_TYPES:
+      raise ValueError(
+          "Input config type: %s is not supported. Supported types are %s" %
+          (config_type, " ".join(Config._SUPPORTED_CONFIG_TYPES)))
+
+    self._root = root
+    self.config_type = config_type
+    self.constraints = Config._TYPE_CONSTRAINTS_MAP[config_type]
+
+  def get_config_dir(self):
+    """Returns the absolute path of the cc toolchain configs directory."""
+    return os.path.join(self._root, self.config_type)
+
+  def get_metadata_path(self):
+    """Returns the absolute path of the METADATA file."""
+    return os.path.join(self.get_config_dir(), "METADATA")
diff --git a/release/config_release.py b/release/config_release.py
new file mode 100644
index 0000000..f8e991b
--- /dev/null
+++ b/release/config_release.py
@@ -0,0 +1,121 @@
+# Copyright 2016 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.
+"""Script to generate toolchain configs for all config types and containers."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+
+# Do not generate .pyc files.
+sys.dont_write_bytecode = True
+
+import bazelrc
+import cc.create_artifacts as cc_create
+import cc.execute_targets as cc_execute
+from config import ContainerConfigs
+import toolchain_flags
+from util import get_git_root
+
+CONFIG_TYPES = ["default", "msan"]
+
+# Define path constants.
+GIT_ROOT = get_git_root()
+
+
+def _get_container_configs_list(bazel_version):
+  """Gets the list of container configs to generate.
+
+  Args:
+    bazel_version: string, the version of Bazel used to generate configs.
+
+  Returns:
+    A list of ContainerConfigs objects corresponding to the configs to generate.
+  """
+  debian8_clang_configs = ContainerConfigs(
+      distro="debian8",
+      version="0.3.0",
+      image="gcr.io/cloud-marketplace/google/clang-debian8",
+      package="configs/debian8_clang",
+      config_types=CONFIG_TYPES,
+      platform_target="rbe_debian8",
+      git_root=GIT_ROOT,
+      bazel_version=bazel_version)
+
+  ubuntu16_04_clang_configs = ContainerConfigs(
+      distro="ubuntu16_04",
+      version="1.0",
+      image="gcr.io/cloud-marketplace/google/clang-ubuntu",
+      package="configs/ubuntu16_04_clang",
+      config_types=CONFIG_TYPES,
+      platform_target="rbe_ubuntu1604",
+      git_root=GIT_ROOT,
+      bazel_version=bazel_version)
+
+  return [debian8_clang_configs, ubuntu16_04_clang_configs]
+
+
+def _parse_arguments():
+  """Parses command line arguments for the script.
+
+  Returns:
+    args object containing the arguments
+  """
+  parser = argparse.ArgumentParser()
+  parser.add_argument(
+      "-b",
+      "--bazel_version",
+      required=True,
+      help="the version of Bazel used to generate toolchain configs")
+  return parser.parse_args()
+
+
+def main(bazel_version):
+  """Main function.
+
+  Examples of usage:
+    python release/config_release.py -b 0.15.0
+
+  Args:
+    bazel_version: string, the version of Bazel used to generate the configs.
+
+  """
+
+  # Get current supported list of container configs to generate.
+  container_configs_list = _get_container_configs_list(bazel_version)
+
+  # Only create the new target in the BUILD file if it does not exist.
+  cc_create.create_targets(container_configs_list, bazel_version)
+
+  # Execute the target and extract toolchain configs.
+  cc_execute.execute_and_extract_configs(container_configs_list, bazel_version)
+
+  # Generate METADATA file.
+  cc_create.generate_metadata(container_configs_list)
+
+  # Generate new cpp toolchain definition targets.
+  cc_create.generate_toolchain_definition(container_configs_list, bazel_version)
+
+  # Update toolchain.bazelrc file.
+  toolchain_flags.update_toolchain_bazelrc_file(container_configs_list,
+                                                bazel_version)
+
+  # Create sample .bazelrc file and update latest.bazelrc symlink.
+  bazelrc.create_bazelrc_and_update_link(bazel_version)
+
+
+if __name__ == "__main__":
+
+  args = _parse_arguments()
+  main(args.bazel_version)
diff --git a/release/license.tpl b/release/license.tpl
new file mode 100644
index 0000000..18a2a14
--- /dev/null
+++ b/release/license.tpl
@@ -0,0 +1,14 @@
+# Copyright 2016 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.
+
diff --git a/release/toolchain.bazelrc.tpl b/release/toolchain.bazelrc.tpl
new file mode 100644
index 0000000..f055c77
--- /dev/null
+++ b/release/toolchain.bazelrc.tpl
@@ -0,0 +1,40 @@
+# This file is auto-generated from release/toolchain.bazelrc.tpl and should not
+# be modified directly.
+
+# Toolchain related flags to append at the end of your .bazelrc file.
+build:remote --host_javabase=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}:jdk8
+build:remote --javabase=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}:jdk8
+build:remote --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
+build:remote --java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8
+build:remote --crosstool_top=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}/bazel_${BAZEL_VERSION}/default:toolchain
+build:remote --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
+# Platform flags:
+# The toolchain container used for execution is defined in the target indicated
+# by "extra_execution_platforms", "host_platform" and "platforms".
+# If you are using your own toolchain container, you need to create a platform
+# target with "constraint_values" that allow for the toolchain specified with
+# "extra_toolchains" to be selected (given constraints defined in
+# "exec_compatible_with").
+# More about platforms: https://docs.bazel.build/versions/master/platforms.html
+build:remote --extra_toolchains=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}/bazel_${BAZEL_VERSION}/cpp:cc-toolchain-clang-x86_64-default
+build:remote --extra_execution_platforms=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}:${PLATFORM}
+build:remote --host_platform=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}:${PLATFORM}
+build:remote --platforms=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}:${PLATFORM}
+
+# Experimental configs for sanitizers, use --config=remote,remote-xxsan,remote-<asan/tsan/msan> (in that order)
+# See https://github.com/bazelbuild/bazel/issues/5291.
+build:remote-xxsan --copt=-gmlt
+build:remote-xxsan --strip=never
+
+build:remote-asan --copt=-fsanitize=address
+build:remote-asan --linkopt=-fsanitize=address
+
+build:remote-tsan --copt=-fsanitize=thread
+build:remote-tsan --linkopt=-fsanitize=thread
+
+build:remote-msan --copt=-fsanitize=memory
+build:remote-msan --linkopt=-fsanitize=memory
+build:remote-msan --cxxopt=--stdlib=libc++
+build:remote-msan --copt=-fsanitize-memory-track-origins
+build:remote-msan --host_crosstool_top=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}/bazel_${BAZEL_VERSION}/default:toolchain
+build:remote-msan --crosstool_top=@bazel_toolchains//${PACKAGE}/${CONFIG_VERSION}/bazel_${BAZEL_VERSION}/msan:toolchain
diff --git a/release/toolchain_flags.py b/release/toolchain_flags.py
new file mode 100644
index 0000000..5dec5fd
--- /dev/null
+++ b/release/toolchain_flags.py
@@ -0,0 +1,54 @@
+# Copyright 2016 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.
+"""Module to create or update sample toolchain.bazelrc file."""
+
+import os
+from string import Template
+
+from util import get_git_root
+
+TPL = os.path.join(get_git_root(), "release", "toolchain.bazelrc.tpl")
+
+
+def update_toolchain_bazelrc_file(container_configs_list, bazel_version):
+  """Creates/updates toolchain.bazelrc file.
+
+  Example toolchain.bazelrc file can be found at
+  configs/ubuntu16_04_clang/1.0/toolchain.bazelrc.
+
+  There is one toolchain.bazelrc file per container per config version.
+
+  If the file already exists in this repo, the script will delete it and
+  generate new one.
+
+  Args:
+    container_configs_list: list of ContainerConfigs, the list of
+      ContainerConfigs to generate configs for.
+    bazel_version: string, the version of Bazel used to generate the configs.
+
+  """
+
+  for container_configs in container_configs_list:
+    with open(container_configs.get_toolchain_bazelrc_path(),
+              "w") as toolchain_bazelrc_file:
+      # Create or update toolchain.bazelrc file.
+      with open(TPL, "r") as tpl_file:
+        tpl = Template(tpl_file.read()).substitute(
+            CONFIG_VERSION=container_configs.version,
+            BAZEL_VERSION=bazel_version,
+            PACKAGE=container_configs.package,
+            PLATFORM=container_configs.platform_target,
+        )
+
+        toolchain_bazelrc_file.write(tpl)
diff --git a/release/util.py b/release/util.py
new file mode 100644
index 0000000..74eac14
--- /dev/null
+++ b/release/util.py
@@ -0,0 +1,50 @@
+# Copyright 2016 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.
+"""A set of utility functions."""
+
+import datetime
+import subprocess
+
+
+def get_git_root():
+  """Returns the root directory of current git repository."""
+  return subprocess.check_output(["git", "rev-parse",
+                                  "--show-toplevel"]).strip()
+
+
+def get_date():
+  """Returns the current date in YYYY.MM.DD format."""
+  now = datetime.datetime.now()
+  return "%s.%s.%s" % (now.year, now.month, now.day)
+
+
+def get_autoconfig_target_name(config_type, distro, config_version,
+                               bazel_version):
+  """Generates the docker_toolchain_autoconfig target name.
+
+  Args:
+    config_type: string, the type of the configs, e.g. default, msan.
+    distro: string, base distro of container used to generate configs.
+    config_version: string, the version of the configs.
+    bazel_version: string, the version of Bazel used to generate the configs.
+  Returns:
+    The docker_toolchain_autoconfig target to generate the configs.
+  """
+
+  return ("{type}-{distro}-clang-{config_version}-"
+          "bazel_{bazel_version}-autoconfig").format(
+              type=config_type,
+              distro=distro,
+              config_version=config_version,
+              bazel_version=bazel_version)
diff --git a/rules/toolchain_containers.bzl b/rules/toolchain_containers.bzl
index 8fbc658..924fb2f 100644
--- a/rules/toolchain_containers.bzl
+++ b/rules/toolchain_containers.bzl
@@ -17,4 +17,12 @@
         "debian8_python3": "sha256:ace668f0f01e5e562ad09c3f128488ec33fa9126313f16505a86ae77865d1696",
         # gcr.io/google-appengine/python:latest
         "ubuntu16_04_python3": "sha256:67fd35064a812fd0ba0a6e9485410f9f2710ebf7b0787a7b350ce6a20f166bfe",
+
+        ###########################################################
+        # Clang images                                            #
+        ###########################################################
+        # gcr.io/cloud-marketplace/google/clang-debian8:r328903
+        "debian8_clang": "sha256:8bb65bf0a0da8be48bbac07ebe743805f3dc5259203e19517098162bd23a768f",
+        # gcr.io/cloud-marketplace/google/clang-ubuntu:r328903
+        "ubuntu16_04_clang": "sha256:d553634f23f7c437ca35bbc4b6f1f38bb81be32b9ef2df4329dcd36762277bf7",
     }