| // Copyright 2015 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.packages.util; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableList; |
| import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig; |
| import com.google.protobuf.TextFormat; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.LinkedHashSet; |
| import java.util.Set; |
| |
| /** |
| * A helper class to create a crosstool package containing a CROSSTOOL file, and the various |
| * rules needed for a mock - use this only for configured target tests, not for execution tests. |
| */ |
| final class Crosstool { |
| private static final ImmutableList<String> CROSSTOOL_BINARIES = |
| ImmutableList.of("compile", "dwp", "link", "objcopy"); |
| |
| private final MockToolsConfig config; |
| |
| private final String crosstoolTop; |
| private String version; |
| private String crosstoolFileContents; |
| private boolean addEmbeddedRuntimes; |
| private String staticRuntimesLabel; |
| private String dynamicRuntimesLabel; |
| private ImmutableList<String> archs; |
| private boolean addModuleMap; |
| private boolean supportsHeaderParsing; |
| |
| Crosstool(MockToolsConfig config, String crosstoolTop) { |
| this.config = config; |
| this.crosstoolTop = crosstoolTop; |
| } |
| |
| public Crosstool setAddModuleMap(boolean addModuleMap) { |
| this.addModuleMap = addModuleMap; |
| return this; |
| } |
| |
| public Crosstool setCrosstoolFile(String version, String crosstoolFileContents) { |
| this.version = version; |
| this.crosstoolFileContents = crosstoolFileContents; |
| return this; |
| } |
| |
| public Crosstool setSupportedArchs(ImmutableList<String> archs) { |
| this.archs = archs; |
| return this; |
| } |
| |
| public Crosstool setSupportsHeaderParsing(boolean supportsHeaderParsing) { |
| this.supportsHeaderParsing = supportsHeaderParsing; |
| return this; |
| } |
| |
| public Crosstool setEmbeddedRuntimes( |
| boolean addEmbeddedRuntimes, String staticRuntimesLabel, String dynamicRuntimesLabel) { |
| this.addEmbeddedRuntimes = addEmbeddedRuntimes; |
| this.staticRuntimesLabel = staticRuntimesLabel; |
| this.dynamicRuntimesLabel = dynamicRuntimesLabel; |
| return this; |
| } |
| |
| public void write() throws IOException { |
| String runtimes = ""; |
| for (String arch : archs) { |
| runtimes += |
| Joiner.on('\n') |
| .join( |
| "filegroup(name = 'dynamic-runtime-libs-" + arch + "',", |
| " licenses = ['unencumbered'],", |
| " srcs = ['libdynamic-runtime-lib-source.so'])", |
| "filegroup(name = 'static-runtime-libs-" + arch + "',", |
| " licenses = ['unencumbered'],", |
| " srcs = ['static-runtime-lib-source.a'])\n"); |
| } |
| |
| StringBuilder compilationTools = new StringBuilder(); |
| for (String compilationTool : CROSSTOOL_BINARIES) { |
| Collection<String> archTargets = new ArrayList<>(); |
| for (String arch : archs) { |
| archTargets.add(compilationTool + '-' + arch); |
| } |
| |
| compilationTools.append( |
| String.format( |
| "filegroup(name = '%s', srcs = ['%s'])\n", |
| compilationTool, |
| Joiner.on("', '").join(archTargets))); |
| for (String archTarget : archTargets) { |
| compilationTools.append( |
| String.format("filegroup(name = '%s', srcs = [':everything-multilib'])\n", archTarget)); |
| } |
| } |
| |
| CrosstoolConfig.CrosstoolRelease.Builder configBuilder = |
| CrosstoolConfig.CrosstoolRelease.newBuilder(); |
| TextFormat.merge(crosstoolFileContents, configBuilder); |
| StringBuilder compilerMap = new StringBuilder(); |
| // Remove duplicates |
| Set<String> keys = new LinkedHashSet<>(); |
| for (CrosstoolConfig.CToolchain toolchain : configBuilder.build().getToolchainList()) { |
| String key = String.format("%s|%s", toolchain.getTargetCpu(), toolchain.getCompiler()); |
| if (!keys.contains(key)) { |
| keys.add(key); |
| compilerMap.append( |
| String.format("'%s': ':cc-compiler-%s',\n", key, toolchain.getTargetCpu())); |
| } |
| } |
| |
| for (String arch : archs) { |
| String compilerRule; |
| String staticRuntimesString = |
| staticRuntimesLabel == null ? "" : ", '" + staticRuntimesLabel + "'"; |
| String dynamicRuntimesString = |
| dynamicRuntimesLabel == null ? "" : ", '" + dynamicRuntimesLabel + "'"; |
| |
| compilerRule = |
| Joiner.on("\n") |
| .join( |
| "cc_toolchain(", |
| " name = 'cc-compiler-" + arch + "',", |
| " output_licenses = ['unencumbered'],", |
| addModuleMap ? " module_map = 'crosstool.cppmap'," : "", |
| " cpu = '" + arch + "',", |
| " compiler_files = 'compile-" + arch + "',", |
| " dwp_files = 'dwp-" + arch + "',", |
| " linker_files = 'link-" + arch + "',", |
| " strip_files = ':every-file',", |
| " objcopy_files = 'objcopy-" + arch + "',", |
| " all_files = ':every-file',", |
| " licenses = ['unencumbered'],", |
| supportsHeaderParsing ? " supports_header_parsing = 1," : "", |
| " dynamic_runtime_libs = ['dynamic-runtime-libs-" |
| + arch |
| + "'" |
| + dynamicRuntimesString |
| + "],", |
| " static_runtime_libs = ['static-runtime-libs-" |
| + arch |
| + "'" |
| + staticRuntimesString |
| + "])"); |
| |
| compilationTools.append(compilerRule + "\n"); |
| } |
| |
| String build = |
| Joiner.on("\n") |
| .join( |
| "package(default_visibility=['//visibility:public'])", |
| "licenses(['restricted'])", |
| "", |
| "alias(name = 'toolchain', actual = 'everything')", |
| "filegroup(name = 'everything-multilib',", |
| " srcs = glob(['" + version + "/**/*'],", |
| " exclude_directories = 1),", |
| " output_licenses = ['unencumbered'])", |
| "", |
| String.format( |
| "cc_toolchain_suite(name = 'everything', toolchains = {%s})", compilerMap), |
| "", |
| String.format( |
| "filegroup(name = 'every-file', srcs = ['%s'%s%s])", |
| Joiner.on("', '").join(CROSSTOOL_BINARIES), |
| addEmbeddedRuntimes ? ", ':dynamic-runtime-libs-k8'" : "", |
| addEmbeddedRuntimes ? ", ':static-runtime-libs-k8'" : ""), |
| "", |
| compilationTools.toString(), |
| runtimes, |
| "", |
| // We add an empty :malloc target in case we need it. |
| "cc_library(name = 'malloc')"); |
| |
| config.create(crosstoolTop + "/" + version + "/x86/bin/gcc"); |
| config.create(crosstoolTop + "/" + version + "/x86/bin/ld"); |
| config.getPath(crosstoolTop + "/CROSSTOOL"); |
| config.overwrite(crosstoolTop + "/BUILD", build); |
| config.overwrite(crosstoolTop + "/CROSSTOOL", crosstoolFileContents); |
| config.create(crosstoolTop + "/crosstool.cppmap", "module crosstool {}"); |
| } |
| } |