| # 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") |
| LATEST_TPL = os.path.join(GIT_ROOT, "release", "cc", "latest.tpl") |
| SHA_MAP_FILE = os.path.join(GIT_ROOT, "rules/toolchain_containers.bzl") |
| CLANG_REVISION_FILE = os.path.join(GIT_ROOT, "third_party/clang/revision.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) |
| clang_revision_map = imp.load_source("clang_revision", CLANG_REVISION_FILE) |
| clang_revision = clang_revision_map.CLANG_REVISION |
| |
| 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, |
| CLANG_REVISION=clang_revision) |
| |
| build_file.write(tpl) |
| |
| |
| def update_latest_target_aliases(container_configs_list, bazel_version): |
| """Updates the alias targets pointing to latest toolchain targets. |
| |
| Example latest aliases clang-ubuntu container are located in |
| configs/ubuntu16_04_clang/latest/BUILD. |
| |
| There is one BUILD file to contain all aliases for a container_config. |
| |
| 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: |
| |
| constraints = list(container_configs.constraints) |
| |
| with open(container_configs.get_latest_aliases_build_path(), |
| "w") as build_file: |
| # Update the BUILD file with aliases for latest toolchain targets. |
| with open(LATEST_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, |
| CONFIG_TYPES=", ".join( |
| [("\"%s\"" % config_type) |
| for config_type in container_configs.config_types]), |
| EXTRA_CONSTRAINTS="\n".join( |
| [("\"%s\"," % constraint) for constraint in constraints]) |
| ) |
| |
| 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 = list(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.check_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)) |