Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | package com.google.devtools.build.lib.analysis; |
| 15 | |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 16 | import static com.google.common.base.Preconditions.checkArgument; |
| 17 | import static com.google.common.base.Preconditions.checkNotNull; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 18 | import static com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType.ABSTRACT; |
| 19 | import static com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType.TEST; |
| 20 | |
Ulf Adams | 345e15e | 2016-07-07 13:27:28 +0000 | [diff] [blame] | 21 | import com.google.common.base.Preconditions; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 22 | import com.google.common.cache.CacheBuilder; |
| 23 | import com.google.common.cache.CacheLoader; |
| 24 | import com.google.common.cache.LoadingCache; |
Cal Peyser | f296e87 | 2016-05-03 17:36:54 +0000 | [diff] [blame] | 25 | import com.google.common.collect.ImmutableBiMap; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 26 | import com.google.common.collect.ImmutableList; |
| 27 | import com.google.common.collect.ImmutableMap; |
Greg Estren | c396f9c | 2016-10-04 18:01:01 +0000 | [diff] [blame] | 28 | import com.google.common.collect.ImmutableSet; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 29 | import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory; |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 30 | import com.google.devtools.build.lib.analysis.config.BuildConfiguration; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 31 | import com.google.devtools.build.lib.analysis.config.BuildOptions; |
| 32 | import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory; |
| 33 | import com.google.devtools.build.lib.analysis.config.DefaultsPackage; |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 34 | import com.google.devtools.build.lib.analysis.config.DynamicTransitionMapper; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 35 | import com.google.devtools.build.lib.analysis.config.FragmentOptions; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 36 | import com.google.devtools.build.lib.cmdline.Label; |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 37 | import com.google.devtools.build.lib.cmdline.LabelSyntaxException; |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 38 | import com.google.devtools.build.lib.cmdline.PackageIdentifier; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 39 | import com.google.devtools.build.lib.events.EventHandler; |
| 40 | import com.google.devtools.build.lib.graph.Digraph; |
| 41 | import com.google.devtools.build.lib.graph.Node; |
| 42 | import com.google.devtools.build.lib.packages.Attribute; |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 43 | import com.google.devtools.build.lib.packages.NativeAspectClass; |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 44 | import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper; |
| 45 | import com.google.devtools.build.lib.packages.OutputFile; |
| 46 | import com.google.devtools.build.lib.packages.Rule; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 47 | import com.google.devtools.build.lib.packages.RuleClass; |
| 48 | import com.google.devtools.build.lib.packages.RuleClassProvider; |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 49 | import com.google.devtools.build.lib.packages.RuleErrorConsumer; |
| 50 | import com.google.devtools.build.lib.packages.Target; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 51 | import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; |
| 52 | import com.google.devtools.build.lib.rules.SkylarkModules; |
Janak Ramakrishnan | b92c097 | 2016-03-23 16:47:13 +0000 | [diff] [blame] | 53 | import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy; |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 54 | import com.google.devtools.build.lib.syntax.Environment; |
| 55 | import com.google.devtools.build.lib.syntax.Environment.Extension; |
Luis Fernando Pino Duque | 3fedf9e | 2016-04-28 15:47:29 +0000 | [diff] [blame] | 56 | import com.google.devtools.build.lib.syntax.Environment.Phase; |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 57 | import com.google.devtools.build.lib.syntax.Mutability; |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 58 | import com.google.devtools.build.lib.syntax.SkylarkSemanticsOptions; |
Laurent Le Brun | a31bc4e | 2016-10-27 12:48:22 +0000 | [diff] [blame] | 59 | import com.google.devtools.build.lib.syntax.SkylarkUtils; |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 60 | import com.google.devtools.build.lib.syntax.Type; |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 61 | import com.google.devtools.common.options.Options; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 62 | import com.google.devtools.common.options.OptionsClassProvider; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 63 | import java.lang.reflect.Constructor; |
| 64 | import java.lang.reflect.InvocationTargetException; |
| 65 | import java.util.ArrayList; |
Kristina Chodorow | 8612a27 | 2015-12-14 15:37:24 +0000 | [diff] [blame] | 66 | import java.util.Collection; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 67 | import java.util.HashMap; |
| 68 | import java.util.List; |
| 69 | import java.util.Map; |
Greg Estren | c396f9c | 2016-10-04 18:01:01 +0000 | [diff] [blame] | 70 | import java.util.Set; |
Ulf Adams | 345e15e | 2016-07-07 13:27:28 +0000 | [diff] [blame] | 71 | import java.util.TreeMap; |
Ulf Adams | 345e15e | 2016-07-07 13:27:28 +0000 | [diff] [blame] | 72 | import javax.annotation.Nullable; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 73 | |
| 74 | /** |
| 75 | * Knows about every rule Blaze supports and the associated configuration options. |
| 76 | * |
| 77 | * <p>This class is initialized on server startup and the set of rules, build info factories |
| 78 | * and configuration options is guarantees not to change over the life time of the Blaze server. |
| 79 | */ |
| 80 | public class ConfiguredRuleClassProvider implements RuleClassProvider { |
Kristina Chodorow | 8612a27 | 2015-12-14 15:37:24 +0000 | [diff] [blame] | 81 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 82 | /** |
| 83 | * Custom dependency validation logic. |
| 84 | */ |
Kristina Chodorow | 8612a27 | 2015-12-14 15:37:24 +0000 | [diff] [blame] | 85 | public interface PrerequisiteValidator { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 86 | /** |
| 87 | * Checks whether the rule in {@code contextBuilder} is allowed to depend on |
| 88 | * {@code prerequisite} through the attribute {@code attribute}. |
| 89 | * |
| 90 | * <p>Can be used for enforcing any organization-specific policies about the layout of the |
| 91 | * workspace. |
| 92 | */ |
| 93 | void validate( |
| 94 | RuleContext.Builder contextBuilder, ConfiguredTarget prerequisite, Attribute attribute); |
| 95 | } |
| 96 | |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 97 | /** Validator to check for and warn on the deprecation of dependencies. */ |
| 98 | public static final class DeprecationValidator implements PrerequisiteValidator { |
| 99 | /** Checks if the given prerequisite is deprecated and prints a warning if so. */ |
| 100 | @Override |
| 101 | public void validate( |
| 102 | RuleContext.Builder contextBuilder, ConfiguredTarget prerequisite, Attribute attribute) { |
| 103 | validateDirectPrerequisiteForDeprecation( |
Michael Staib | 2707a88 | 2016-09-16 21:06:40 +0000 | [diff] [blame] | 104 | contextBuilder, contextBuilder.getRule(), prerequisite, contextBuilder.forAspect()); |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Returns whether two packages are considered the same for purposes of deprecation warnings. |
| 109 | * Dependencies within the same package do not print deprecation warnings; a package in the |
| 110 | * javatests directory may also depend on its corresponding java package without a warning. |
| 111 | */ |
| 112 | public static boolean isSameLogicalPackage( |
| 113 | PackageIdentifier thisPackage, PackageIdentifier prerequisitePackage) { |
| 114 | if (thisPackage.equals(prerequisitePackage)) { |
| 115 | // If the packages are equal, they are the same logical package (and just the same package). |
| 116 | return true; |
| 117 | } |
| 118 | if (!thisPackage.getRepository().equals(prerequisitePackage.getRepository())) { |
| 119 | // If the packages are in different repositories, they are not the same logical package. |
| 120 | return false; |
| 121 | } |
| 122 | // If the packages are in the same repository, it's allowed iff this package is the javatests |
| 123 | // companion to the prerequisite java package. |
| 124 | String thisPackagePath = thisPackage.getPackageFragment().getPathString(); |
| 125 | String prerequisitePackagePath = prerequisitePackage.getPackageFragment().getPathString(); |
| 126 | return thisPackagePath.startsWith("javatests/") |
| 127 | && prerequisitePackagePath.startsWith("java/") |
| 128 | && thisPackagePath.substring("javatests/".length()).equals( |
| 129 | prerequisitePackagePath.substring("java/".length())); |
| 130 | } |
| 131 | |
| 132 | /** Returns whether a deprecation warning should be printed for the prerequisite described. */ |
| 133 | private static boolean shouldEmitDeprecationWarningFor( |
| 134 | String thisDeprecation, PackageIdentifier thisPackage, |
Michael Staib | 2707a88 | 2016-09-16 21:06:40 +0000 | [diff] [blame] | 135 | String prerequisiteDeprecation, PackageIdentifier prerequisitePackage, |
| 136 | boolean forAspect) { |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 137 | // Don't report deprecation edges from javatests to java or within a package; |
| 138 | // otherwise tests of deprecated code generate nuisance warnings. |
Michael Staib | 2707a88 | 2016-09-16 21:06:40 +0000 | [diff] [blame] | 139 | // Don't report deprecation if the current target is also deprecated, |
| 140 | // or if the current context is evaluating an aspect, |
| 141 | // as the base target would have already printed the deprecation warnings. |
| 142 | return (!forAspect |
| 143 | && prerequisiteDeprecation != null |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 144 | && !isSameLogicalPackage(thisPackage, prerequisitePackage) |
| 145 | && thisDeprecation == null); |
| 146 | } |
| 147 | |
| 148 | /** Checks if the given prerequisite is deprecated and prints a warning if so. */ |
| 149 | public static void validateDirectPrerequisiteForDeprecation( |
Michael Staib | 2707a88 | 2016-09-16 21:06:40 +0000 | [diff] [blame] | 150 | RuleErrorConsumer errors, Rule rule, ConfiguredTarget prerequisite, boolean forAspect) { |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 151 | Target prerequisiteTarget = prerequisite.getTarget(); |
| 152 | Label prerequisiteLabel = prerequisiteTarget.getLabel(); |
| 153 | PackageIdentifier thatPackage = prerequisiteLabel.getPackageIdentifier(); |
| 154 | PackageIdentifier thisPackage = rule.getLabel().getPackageIdentifier(); |
| 155 | |
| 156 | if (prerequisiteTarget instanceof Rule) { |
| 157 | Rule prerequisiteRule = (Rule) prerequisiteTarget; |
| 158 | String thisDeprecation = |
| 159 | NonconfigurableAttributeMapper.of(rule).get("deprecation", Type.STRING); |
| 160 | String thatDeprecation = |
| 161 | NonconfigurableAttributeMapper.of(prerequisiteRule).get("deprecation", Type.STRING); |
| 162 | if (shouldEmitDeprecationWarningFor( |
Michael Staib | 2707a88 | 2016-09-16 21:06:40 +0000 | [diff] [blame] | 163 | thisDeprecation, thisPackage, thatDeprecation, thatPackage, forAspect)) { |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 164 | errors.ruleWarning("target '" + rule.getLabel() + "' depends on deprecated target '" |
| 165 | + prerequisiteLabel + "': " + thatDeprecation); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | if (prerequisiteTarget instanceof OutputFile) { |
| 170 | Rule generatingRule = ((OutputFile) prerequisiteTarget).getGeneratingRule(); |
| 171 | String thisDeprecation = |
| 172 | NonconfigurableAttributeMapper.of(rule).get("deprecation", Type.STRING); |
| 173 | String thatDeprecation = |
| 174 | NonconfigurableAttributeMapper.of(generatingRule).get("deprecation", Type.STRING); |
| 175 | if (shouldEmitDeprecationWarningFor( |
Michael Staib | 2707a88 | 2016-09-16 21:06:40 +0000 | [diff] [blame] | 176 | thisDeprecation, thisPackage, thatDeprecation, thatPackage, forAspect)) { |
Michael Staib | 8618b9d | 2016-09-16 19:36:49 +0000 | [diff] [blame] | 177 | errors.ruleWarning("target '" + rule.getLabel() + "' depends on the output file " |
| 178 | + prerequisiteLabel + " of a deprecated rule " + generatingRule.getLabel() |
| 179 | + "': " + thatDeprecation); |
| 180 | } |
| 181 | } |
| 182 | } |
| 183 | } |
| 184 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 185 | /** |
Ulf Adams | e3b4af2 | 2016-10-18 12:51:15 +0000 | [diff] [blame] | 186 | * A coherent set of options, fragments, aspects and rules; each of these may declare a dependency |
| 187 | * on other such sets. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 188 | */ |
Ulf Adams | e3b4af2 | 2016-10-18 12:51:15 +0000 | [diff] [blame] | 189 | public static interface RuleSet { |
| 190 | /** Add stuff to the configured rule class provider builder. */ |
| 191 | void init(ConfiguredRuleClassProvider.Builder builder); |
| 192 | |
| 193 | /** List of required modules. */ |
| 194 | ImmutableList<RuleSet> requires(); |
| 195 | } |
| 196 | |
| 197 | /** Builder for {@link ConfiguredRuleClassProvider}. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 198 | public static class Builder implements RuleDefinitionEnvironment { |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 199 | private String productName; |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 200 | private final StringBuilder defaultWorkspaceFilePrefix = new StringBuilder(); |
| 201 | private final StringBuilder defaultWorkspaceFileSuffix = new StringBuilder(); |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 202 | private Label preludeLabel; |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 203 | private String runfilesPrefix; |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 204 | private String toolsRepository; |
Ulf Adams | 8d0be89 | 2016-10-14 13:56:46 +0000 | [diff] [blame] | 205 | private final List<ConfigurationFragmentFactory> configurationFragmentFactories = |
| 206 | new ArrayList<>(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 207 | private final List<BuildInfoFactory> buildInfoFactories = new ArrayList<>(); |
| 208 | private final List<Class<? extends FragmentOptions>> configurationOptions = new ArrayList<>(); |
| 209 | |
| 210 | private final Map<String, RuleClass> ruleClassMap = new HashMap<>(); |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 211 | private final Map<String, RuleDefinition> ruleDefinitionMap = new HashMap<>(); |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 212 | private final Map<String, NativeAspectClass> nativeAspectClassMap = |
Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 213 | new HashMap<>(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 214 | private final Map<Class<? extends RuleDefinition>, RuleClass> ruleMap = new HashMap<>(); |
| 215 | private final Digraph<Class<? extends RuleDefinition>> dependencyGraph = |
| 216 | new Digraph<>(); |
| 217 | private ConfigurationCollectionFactory configurationCollectionFactory; |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 218 | private ImmutableMap.Builder<Attribute.Transition, Attribute.Transition> dynamicTransitionMaps |
| 219 | = ImmutableMap.builder(); |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 220 | private Class<? extends BuildConfiguration.Fragment> universalFragment; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 221 | private PrerequisiteValidator prerequisiteValidator; |
Ulf Adams | fd53b61 | 2016-07-06 07:23:59 +0000 | [diff] [blame] | 222 | private ImmutableMap.Builder<String, Object> skylarkAccessibleTopLevels = |
| 223 | ImmutableMap.builder(); |
Damien Martin-Guillerez | f81c675 | 2016-02-15 10:50:12 +0000 | [diff] [blame] | 224 | private ImmutableList.Builder<Class<?>> skylarkModules = |
| 225 | ImmutableList.<Class<?>>builder().addAll(SkylarkModules.MODULES); |
Ulf Adams | fd53b61 | 2016-07-06 07:23:59 +0000 | [diff] [blame] | 226 | private ImmutableBiMap.Builder<String, Class<? extends TransitiveInfoProvider>> |
| 227 | registeredSkylarkProviders = ImmutableBiMap.builder(); |
Ulf Adams | 345e15e | 2016-07-07 13:27:28 +0000 | [diff] [blame] | 228 | private Map<String, String> platformRegexps = new TreeMap<>(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 229 | |
Yun Peng | c2c938a | 2017-07-28 10:22:57 +0200 | [diff] [blame^] | 230 | // TODO(pcloudy): Remove this field after Bazel rule definitions are not used internally. |
| 231 | private String nativeLauncherLabel; |
| 232 | |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 233 | public Builder setProductName(String productName) { |
| 234 | this.productName = productName; |
| 235 | return this; |
| 236 | } |
| 237 | |
Yun Peng | c2c938a | 2017-07-28 10:22:57 +0200 | [diff] [blame^] | 238 | public Builder setNativeLauncherLabel(String label) { |
| 239 | this.nativeLauncherLabel = label; |
| 240 | return this; |
| 241 | } |
| 242 | |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 243 | public void addWorkspaceFilePrefix(String contents) { |
| 244 | defaultWorkspaceFilePrefix.append(contents); |
| 245 | } |
| 246 | |
| 247 | public void addWorkspaceFileSuffix(String contents) { |
| 248 | defaultWorkspaceFileSuffix.append(contents); |
Kristina Chodorow | bc4b4b1 | 2015-02-11 15:54:50 +0000 | [diff] [blame] | 249 | } |
| 250 | |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 251 | public Builder setPrelude(String preludeLabelString) { |
| 252 | try { |
| 253 | this.preludeLabel = Label.parseAbsolute(preludeLabelString); |
| 254 | } catch (LabelSyntaxException e) { |
| 255 | String errorMsg = |
| 256 | String.format("Prelude label '%s' is invalid: %s", preludeLabelString, e.getMessage()); |
| 257 | throw new IllegalArgumentException(errorMsg); |
| 258 | } |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 259 | return this; |
| 260 | } |
| 261 | |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 262 | public Builder setRunfilesPrefix(String runfilesPrefix) { |
| 263 | this.runfilesPrefix = runfilesPrefix; |
| 264 | return this; |
| 265 | } |
Luis Fernando Pino Duque | 18d1322 | 2016-02-08 14:55:28 +0000 | [diff] [blame] | 266 | |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 267 | public Builder setToolsRepository(String toolsRepository) { |
| 268 | this.toolsRepository = toolsRepository; |
| 269 | return this; |
| 270 | } |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 271 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 272 | public Builder setPrerequisiteValidator(PrerequisiteValidator prerequisiteValidator) { |
| 273 | this.prerequisiteValidator = prerequisiteValidator; |
| 274 | return this; |
| 275 | } |
| 276 | |
| 277 | public Builder addBuildInfoFactory(BuildInfoFactory factory) { |
| 278 | buildInfoFactories.add(factory); |
| 279 | return this; |
| 280 | } |
| 281 | |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 282 | public Builder addRuleDefinition(RuleDefinition ruleDefinition) { |
| 283 | Class<? extends RuleDefinition> ruleDefinitionClass = ruleDefinition.getClass(); |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 284 | ruleDefinitionMap.put(ruleDefinitionClass.getName(), ruleDefinition); |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 285 | dependencyGraph.createNode(ruleDefinitionClass); |
| 286 | for (Class<? extends RuleDefinition> ancestor : ruleDefinition.getMetadata().ancestors()) { |
| 287 | dependencyGraph.addEdge(ancestor, ruleDefinitionClass); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | return this; |
| 291 | } |
| 292 | |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 293 | public Builder addNativeAspectClass(NativeAspectClass aspectFactoryClass) { |
| 294 | nativeAspectClassMap.put(aspectFactoryClass.getName(), aspectFactoryClass); |
Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 295 | return this; |
| 296 | } |
| 297 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 298 | public Builder addConfigurationOptions(Class<? extends FragmentOptions> configurationOptions) { |
| 299 | this.configurationOptions.add(configurationOptions); |
| 300 | return this; |
| 301 | } |
| 302 | |
Ulf Adams | bbcfa2f | 2016-10-18 07:24:13 +0000 | [diff] [blame] | 303 | /** |
| 304 | * Adds an options class and a corresponding factory. There's usually a 1:1:1 correspondence |
| 305 | * between option classes, factories, and fragments, such that the factory depends only on the |
| 306 | * options class and creates the fragment. This method provides a convenient way of adding both |
| 307 | * the options class and the factory in a single call. |
| 308 | */ |
| 309 | public Builder addConfig( |
| 310 | Class<? extends FragmentOptions> options, ConfigurationFragmentFactory factory) { |
| 311 | // Enforce that the factory requires the options. |
| 312 | Preconditions.checkState(factory.requiredOptions().contains(options)); |
| 313 | this.configurationOptions.add(options); |
| 314 | this.configurationFragmentFactories.add(factory); |
| 315 | return this; |
| 316 | } |
| 317 | |
Ulf Adams | 378abb2 | 2016-06-22 16:01:57 +0000 | [diff] [blame] | 318 | public Builder addConfigurationOptions( |
| 319 | Collection<Class<? extends FragmentOptions>> optionsClasses) { |
| 320 | this.configurationOptions.addAll(optionsClasses); |
| 321 | return this; |
| 322 | } |
| 323 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 324 | public Builder addConfigurationFragment(ConfigurationFragmentFactory factory) { |
Ulf Adams | 8d0be89 | 2016-10-14 13:56:46 +0000 | [diff] [blame] | 325 | configurationFragmentFactories.add(factory); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 326 | return this; |
| 327 | } |
| 328 | |
| 329 | public Builder setConfigurationCollectionFactory(ConfigurationCollectionFactory factory) { |
| 330 | this.configurationCollectionFactory = factory; |
| 331 | return this; |
| 332 | } |
| 333 | |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 334 | public Builder addDynamicTransitionMaps(Map<Attribute.Transition, Attribute.Transition> maps) { |
| 335 | dynamicTransitionMaps.putAll(maps); |
| 336 | return this; |
| 337 | } |
| 338 | |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 339 | public Builder setUniversalConfigurationFragment( |
| 340 | Class<? extends BuildConfiguration.Fragment> fragment) { |
| 341 | this.universalFragment = fragment; |
| 342 | return this; |
| 343 | } |
| 344 | |
Ulf Adams | fd53b61 | 2016-07-06 07:23:59 +0000 | [diff] [blame] | 345 | public Builder addSkylarkAccessibleTopLevels(String name, Object object) { |
| 346 | this.skylarkAccessibleTopLevels.put(name, object); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 347 | return this; |
| 348 | } |
| 349 | |
Damien Martin-Guillerez | f81c675 | 2016-02-15 10:50:12 +0000 | [diff] [blame] | 350 | public Builder addSkylarkModule(Class<?>... modules) { |
| 351 | this.skylarkModules.add(modules); |
| 352 | return this; |
| 353 | } |
| 354 | |
Cal Peyser | f296e87 | 2016-05-03 17:36:54 +0000 | [diff] [blame] | 355 | /** |
Ulf Adams | 345e15e | 2016-07-07 13:27:28 +0000 | [diff] [blame] | 356 | * Do not use - this only exists for backwards compatibility! Platform regexps are part of a |
| 357 | * legacy mechanism - {@code vardef} - that is not exposed in Bazel. |
| 358 | * |
| 359 | * <p>{@code vardef} needs explicit support in the rule implementations, and cannot express |
| 360 | * conditional dependencies, only conditional attribute values. This mechanism will be |
| 361 | * supplanted by configuration dependent attributes, and its effect can usually also be achieved |
| 362 | * with select(). |
| 363 | * |
| 364 | * <p>This is a map of platform names to regexps. When a name is used as the third argument to |
| 365 | * {@code vardef}, the corresponding regexp is used to match on the C++ abi, and the variable is |
| 366 | * only set to that value if the regexp matches. For example, the entry |
| 367 | * {@code "oldlinux": "i[34]86-libc[345]-linux"} might define a set of platforms representing |
| 368 | * certain older linux releases. |
| 369 | */ |
| 370 | public Builder addPlatformRegexps(Map<String, String> platformRegexps) { |
| 371 | this.platformRegexps.putAll(Preconditions.checkNotNull(platformRegexps)); |
| 372 | return this; |
| 373 | } |
| 374 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 375 | private RuleConfiguredTargetFactory createFactory( |
| 376 | Class<? extends RuleConfiguredTargetFactory> factoryClass) { |
| 377 | try { |
| 378 | Constructor<? extends RuleConfiguredTargetFactory> ctor = factoryClass.getConstructor(); |
| 379 | return ctor.newInstance(); |
| 380 | } catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
| 381 | | InvocationTargetException e) { |
| 382 | throw new IllegalStateException(e); |
| 383 | } |
| 384 | } |
| 385 | |
| 386 | private RuleClass commitRuleDefinition(Class<? extends RuleDefinition> definitionClass) { |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 387 | RuleDefinition instance = checkNotNull(ruleDefinitionMap.get(definitionClass.getName()), |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 388 | "addRuleDefinition(new %s()) should be called before build()", definitionClass.getName()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 389 | |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 390 | RuleDefinition.Metadata metadata = instance.getMetadata(); |
| 391 | checkArgument(ruleClassMap.get(metadata.name()) == null, metadata.name()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 392 | |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 393 | List<Class<? extends RuleDefinition>> ancestors = metadata.ancestors(); |
| 394 | |
| 395 | checkArgument( |
| 396 | metadata.type() == ABSTRACT ^ metadata.factoryClass() |
| 397 | != RuleConfiguredTargetFactory.class); |
| 398 | checkArgument( |
| 399 | (metadata.type() != TEST) |
| 400 | || ancestors.contains(BaseRuleClasses.TestBaseRule.class)); |
| 401 | |
| 402 | RuleClass[] ancestorClasses = new RuleClass[ancestors.size()]; |
| 403 | for (int i = 0; i < ancestorClasses.length; i++) { |
| 404 | ancestorClasses[i] = ruleMap.get(ancestors.get(i)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 405 | if (ancestorClasses[i] == null) { |
| 406 | // Ancestors should have been initialized by now |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 407 | throw new IllegalStateException("Ancestor " + ancestors.get(i) + " of " |
| 408 | + metadata.name() + " is not initialized"); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 409 | } |
| 410 | } |
| 411 | |
| 412 | RuleConfiguredTargetFactory factory = null; |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 413 | if (metadata.type() != ABSTRACT) { |
| 414 | factory = createFactory(metadata.factoryClass()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 415 | } |
| 416 | |
| 417 | RuleClass.Builder builder = new RuleClass.Builder( |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 418 | metadata.name(), metadata.type(), false, ancestorClasses); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 419 | builder.factory(factory); |
| 420 | RuleClass ruleClass = instance.build(builder, this); |
| 421 | ruleMap.put(definitionClass, ruleClass); |
| 422 | ruleClassMap.put(ruleClass.getName(), ruleClass); |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 423 | ruleDefinitionMap.put(ruleClass.getName(), instance); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 424 | |
| 425 | return ruleClass; |
| 426 | } |
| 427 | |
| 428 | public ConfiguredRuleClassProvider build() { |
| 429 | for (Node<Class<? extends RuleDefinition>> ruleDefinition : |
Googler | 5850503 | 2015-03-19 16:12:34 +0000 | [diff] [blame] | 430 | dependencyGraph.getTopologicalOrder()) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 431 | commitRuleDefinition(ruleDefinition.getLabel()); |
| 432 | } |
| 433 | |
| 434 | return new ConfiguredRuleClassProvider( |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 435 | productName, |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 436 | preludeLabel, |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 437 | runfilesPrefix, |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 438 | toolsRepository, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 439 | ImmutableMap.copyOf(ruleClassMap), |
| 440 | ImmutableMap.copyOf(ruleDefinitionMap), |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 441 | ImmutableMap.copyOf(nativeAspectClassMap), |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 442 | defaultWorkspaceFilePrefix.toString(), |
| 443 | defaultWorkspaceFileSuffix.toString(), |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 444 | ImmutableList.copyOf(buildInfoFactories), |
| 445 | ImmutableList.copyOf(configurationOptions), |
Ulf Adams | 8d0be89 | 2016-10-14 13:56:46 +0000 | [diff] [blame] | 446 | ImmutableList.copyOf(configurationFragmentFactories), |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 447 | configurationCollectionFactory, |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 448 | new DynamicTransitionMapper(dynamicTransitionMaps.build()), |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 449 | universalFragment, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 450 | prerequisiteValidator, |
Ulf Adams | fd53b61 | 2016-07-06 07:23:59 +0000 | [diff] [blame] | 451 | skylarkAccessibleTopLevels.build(), |
dslomov | f6a7e5a | 2017-07-05 07:23:31 -0400 | [diff] [blame] | 452 | skylarkModules.build()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 453 | } |
| 454 | |
| 455 | @Override |
| 456 | public Label getLabel(String labelValue) { |
| 457 | return LABELS.getUnchecked(labelValue); |
| 458 | } |
Luis Fernando Pino Duque | 18d1322 | 2016-02-08 14:55:28 +0000 | [diff] [blame] | 459 | |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 460 | @Override |
Luis Fernando Pino Duque | 18d1322 | 2016-02-08 14:55:28 +0000 | [diff] [blame] | 461 | public Label getToolsLabel(String labelValue) { |
| 462 | return getLabel(toolsRepository + labelValue); |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 463 | } |
Luis Fernando Pino Duque | 207ba4a | 2016-07-01 15:07:23 +0000 | [diff] [blame] | 464 | |
| 465 | @Override |
Yun Peng | c2c938a | 2017-07-28 10:22:57 +0200 | [diff] [blame^] | 466 | public Label getLauncherLabel() { |
| 467 | if (nativeLauncherLabel == null) { |
| 468 | return null; |
| 469 | } |
| 470 | return getToolsLabel(nativeLauncherLabel); |
| 471 | } |
| 472 | |
| 473 | @Override |
Luis Fernando Pino Duque | 207ba4a | 2016-07-01 15:07:23 +0000 | [diff] [blame] | 474 | public String getToolsRepository() { |
| 475 | return toolsRepository; |
| 476 | } |
Ulf Adams | 345e15e | 2016-07-07 13:27:28 +0000 | [diff] [blame] | 477 | |
| 478 | @Nullable |
| 479 | public Map<String, String> getPlatformRegexps() { |
| 480 | return platformRegexps.isEmpty() ? null : ImmutableMap.copyOf(platformRegexps); |
| 481 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 482 | } |
| 483 | |
| 484 | /** |
| 485 | * Used to make the label instances unique, so that we don't create a new |
| 486 | * instance for every rule. |
| 487 | */ |
Francois-Rene Rideau | 6e7160d | 2015-08-26 17:22:35 +0000 | [diff] [blame] | 488 | private static final LoadingCache<String, Label> LABELS = CacheBuilder.newBuilder().build( |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 489 | new CacheLoader<String, Label>() { |
| 490 | @Override |
| 491 | public Label load(String from) { |
| 492 | try { |
| 493 | return Label.parseAbsolute(from); |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 494 | } catch (LabelSyntaxException e) { |
Philipp Wollermann | f2512bb | 2015-10-22 20:33:44 +0000 | [diff] [blame] | 495 | throw new IllegalArgumentException(from, e); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 496 | } |
| 497 | } |
| 498 | }); |
| 499 | |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 500 | private final String productName; |
| 501 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 502 | /** |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 503 | * Default content that should be added at the beginning of the WORKSPACE file. |
Kristina Chodorow | bc4b4b1 | 2015-02-11 15:54:50 +0000 | [diff] [blame] | 504 | */ |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 505 | private final String defaultWorkspaceFilePrefix; |
| 506 | |
| 507 | /** |
| 508 | * Default content that should be added at the end of the WORKSPACE file. |
| 509 | */ |
| 510 | private final String defaultWorkspaceFileSuffix; |
| 511 | |
Kristina Chodorow | bc4b4b1 | 2015-02-11 15:54:50 +0000 | [diff] [blame] | 512 | |
| 513 | /** |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 514 | * Label for the prelude file. |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 515 | */ |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 516 | private final Label preludeLabel; |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 517 | |
| 518 | /** |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 519 | * The default runfiles prefix. |
| 520 | */ |
| 521 | private final String runfilesPrefix; |
Luis Fernando Pino Duque | 18d1322 | 2016-02-08 14:55:28 +0000 | [diff] [blame] | 522 | |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 523 | /** |
| 524 | * The path to the tools repository. |
| 525 | */ |
| 526 | private final String toolsRepository; |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 527 | |
| 528 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 529 | * Maps rule class name to the metaclass instance for that rule. |
| 530 | */ |
| 531 | private final ImmutableMap<String, RuleClass> ruleClassMap; |
| 532 | |
| 533 | /** |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 534 | * Maps rule class name to the rule definition objects. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 535 | */ |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 536 | private final ImmutableMap<String, RuleDefinition> ruleDefinitionMap; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 537 | |
| 538 | /** |
Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 539 | * Maps aspect name to the aspect factory meta class. |
| 540 | */ |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 541 | private final ImmutableMap<String, NativeAspectClass> nativeAspectClassMap; |
Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 542 | |
| 543 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 544 | * The configuration options that affect the behavior of the rules. |
| 545 | */ |
| 546 | private final ImmutableList<Class<? extends FragmentOptions>> configurationOptions; |
| 547 | |
Ulf Adams | 8d0be89 | 2016-10-14 13:56:46 +0000 | [diff] [blame] | 548 | /** The set of configuration fragment factories. */ |
| 549 | private final ImmutableList<ConfigurationFragmentFactory> configurationFragmentFactories; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 550 | |
| 551 | /** |
| 552 | * The factory that creates the configuration collection. |
| 553 | */ |
| 554 | private final ConfigurationCollectionFactory configurationCollectionFactory; |
| 555 | |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 556 | /** |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 557 | * The dynamic configuration transition mapper. |
| 558 | */ |
| 559 | private final DynamicTransitionMapper dynamicTransitionMapper; |
| 560 | |
| 561 | /** |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 562 | * A configuration fragment that should be available to all rules even when they don't |
| 563 | * explicitly require it. |
| 564 | */ |
| 565 | private final Class<? extends BuildConfiguration.Fragment> universalFragment; |
| 566 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 567 | private final ImmutableList<BuildInfoFactory> buildInfoFactories; |
| 568 | |
| 569 | private final PrerequisiteValidator prerequisiteValidator; |
| 570 | |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 571 | private final Environment.Frame globals; |
Janak Ramakrishnan | b6e33bc | 2015-09-06 21:05:23 +0000 | [diff] [blame] | 572 | |
Kristina Chodorow | 8612a27 | 2015-12-14 15:37:24 +0000 | [diff] [blame] | 573 | private ConfiguredRuleClassProvider( |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 574 | String productName, |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 575 | Label preludeLabel, |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 576 | String runfilesPrefix, |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 577 | String toolsRepository, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 578 | ImmutableMap<String, RuleClass> ruleClassMap, |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 579 | ImmutableMap<String, RuleDefinition> ruleDefinitionMap, |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 580 | ImmutableMap<String, NativeAspectClass> nativeAspectClassMap, |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 581 | String defaultWorkspaceFilePrefix, |
| 582 | String defaultWorkspaceFileSuffix, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 583 | ImmutableList<BuildInfoFactory> buildInfoFactories, |
| 584 | ImmutableList<Class<? extends FragmentOptions>> configurationOptions, |
| 585 | ImmutableList<ConfigurationFragmentFactory> configurationFragments, |
| 586 | ConfigurationCollectionFactory configurationCollectionFactory, |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 587 | DynamicTransitionMapper dynamicTransitionMapper, |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 588 | Class<? extends BuildConfiguration.Fragment> universalFragment, |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 589 | PrerequisiteValidator prerequisiteValidator, |
Dmitry Lomov | 899416d | 2016-04-22 12:40:30 +0000 | [diff] [blame] | 590 | ImmutableMap<String, Object> skylarkAccessibleJavaClasses, |
dslomov | f6a7e5a | 2017-07-05 07:23:31 -0400 | [diff] [blame] | 591 | ImmutableList<Class<?>> skylarkModules) { |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 592 | this.productName = productName; |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 593 | this.preludeLabel = preludeLabel; |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 594 | this.runfilesPrefix = runfilesPrefix; |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 595 | this.toolsRepository = toolsRepository; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 596 | this.ruleClassMap = ruleClassMap; |
| 597 | this.ruleDefinitionMap = ruleDefinitionMap; |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 598 | this.nativeAspectClassMap = nativeAspectClassMap; |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 599 | this.defaultWorkspaceFilePrefix = defaultWorkspaceFilePrefix; |
| 600 | this.defaultWorkspaceFileSuffix = defaultWorkspaceFileSuffix; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 601 | this.buildInfoFactories = buildInfoFactories; |
| 602 | this.configurationOptions = configurationOptions; |
Ulf Adams | 8d0be89 | 2016-10-14 13:56:46 +0000 | [diff] [blame] | 603 | this.configurationFragmentFactories = configurationFragments; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 604 | this.configurationCollectionFactory = configurationCollectionFactory; |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 605 | this.dynamicTransitionMapper = dynamicTransitionMapper; |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 606 | this.universalFragment = universalFragment; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 607 | this.prerequisiteValidator = prerequisiteValidator; |
Damien Martin-Guillerez | f81c675 | 2016-02-15 10:50:12 +0000 | [diff] [blame] | 608 | this.globals = createGlobals(skylarkAccessibleJavaClasses, skylarkModules); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 609 | } |
| 610 | |
Ulf Adams | f04cbe3 | 2016-10-28 13:23:41 +0000 | [diff] [blame] | 611 | public String getProductName() { |
| 612 | return productName; |
| 613 | } |
| 614 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 615 | public PrerequisiteValidator getPrerequisiteValidator() { |
| 616 | return prerequisiteValidator; |
| 617 | } |
| 618 | |
| 619 | @Override |
John Field | a97e17f | 2015-11-13 02:19:52 +0000 | [diff] [blame] | 620 | public Label getPreludeLabel() { |
| 621 | return preludeLabel; |
Ulf Adams | fdfdd92 | 2015-09-01 08:36:29 +0000 | [diff] [blame] | 622 | } |
| 623 | |
| 624 | @Override |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 625 | public String getRunfilesPrefix() { |
| 626 | return runfilesPrefix; |
| 627 | } |
Luis Fernando Pino Duque | 18d1322 | 2016-02-08 14:55:28 +0000 | [diff] [blame] | 628 | |
Luis Fernando Pino Duque | 90511e1 | 2016-01-28 10:49:58 +0000 | [diff] [blame] | 629 | @Override |
| 630 | public String getToolsRepository() { |
| 631 | return toolsRepository; |
| 632 | } |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 633 | |
| 634 | @Override |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 635 | public Map<String, RuleClass> getRuleClassMap() { |
| 636 | return ruleClassMap; |
| 637 | } |
| 638 | |
Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 639 | @Override |
Luis Fernando Pino Duque | e82713d | 2016-04-26 16:22:38 +0000 | [diff] [blame] | 640 | public Map<String, NativeAspectClass> getNativeAspectClassMap() { |
| 641 | return nativeAspectClassMap; |
| 642 | } |
| 643 | |
| 644 | @Override |
| 645 | public NativeAspectClass getNativeAspectClass(String key) { |
| 646 | return nativeAspectClassMap.get(key); |
Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 647 | } |
| 648 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 649 | /** |
| 650 | * Returns a list of build info factories that are needed for the supported languages. |
| 651 | */ |
| 652 | public ImmutableList<BuildInfoFactory> getBuildInfoFactories() { |
| 653 | return buildInfoFactories; |
| 654 | } |
| 655 | |
| 656 | /** |
| 657 | * Returns the set of configuration fragments provided by this module. |
| 658 | */ |
| 659 | public ImmutableList<ConfigurationFragmentFactory> getConfigurationFragments() { |
Ulf Adams | 8d0be89 | 2016-10-14 13:56:46 +0000 | [diff] [blame] | 660 | return configurationFragmentFactories; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 661 | } |
| 662 | |
| 663 | /** |
| 664 | * Returns the set of configuration options that are supported in this module. |
| 665 | */ |
| 666 | public ImmutableList<Class<? extends FragmentOptions>> getConfigurationOptions() { |
| 667 | return configurationOptions; |
| 668 | } |
| 669 | |
| 670 | /** |
| 671 | * Returns the definition of the rule class definition with the specified name. |
| 672 | */ |
Luis Fernando Pino Duque | 2b0b5cc | 2016-04-26 09:31:27 +0000 | [diff] [blame] | 673 | public RuleDefinition getRuleClassDefinition(String ruleClassName) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 674 | return ruleDefinitionMap.get(ruleClassName); |
| 675 | } |
| 676 | |
| 677 | /** |
| 678 | * Returns the configuration collection creator. |
| 679 | */ |
| 680 | public ConfigurationCollectionFactory getConfigurationCollectionFactory() { |
| 681 | return configurationCollectionFactory; |
| 682 | } |
| 683 | |
| 684 | /** |
gregce | 490b095 | 2017-07-06 18:44:38 -0400 | [diff] [blame] | 685 | * Returns the dynamic configuration transition mapper. |
| 686 | */ |
| 687 | public DynamicTransitionMapper getDynamicTransitionMapper() { |
| 688 | return dynamicTransitionMapper; |
| 689 | } |
| 690 | |
| 691 | /** |
Greg Estren | c5a352f | 2015-11-13 17:25:36 +0000 | [diff] [blame] | 692 | * Returns the configuration fragment that should be available to all rules even when they |
| 693 | * don't explicitly require it. |
| 694 | */ |
| 695 | public Class<? extends BuildConfiguration.Fragment> getUniversalFragment() { |
| 696 | return universalFragment; |
| 697 | } |
| 698 | |
| 699 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 700 | * Returns the defaults package for the default settings. |
| 701 | */ |
Janak Ramakrishnan | b92c097 | 2016-03-23 16:47:13 +0000 | [diff] [blame] | 702 | public String getDefaultsPackageContent(InvocationPolicy invocationPolicy) { |
| 703 | return DefaultsPackage.getDefaultsPackageContent(configurationOptions, invocationPolicy); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 704 | } |
| 705 | |
| 706 | /** |
| 707 | * Returns the defaults package for the given options taken from an optionsProvider. |
| 708 | */ |
| 709 | public String getDefaultsPackageContent(OptionsClassProvider optionsProvider) { |
| 710 | return DefaultsPackage.getDefaultsPackageContent( |
| 711 | BuildOptions.of(configurationOptions, optionsProvider)); |
| 712 | } |
| 713 | |
| 714 | /** |
| 715 | * Creates a BuildOptions class for the given options taken from an optionsProvider. |
| 716 | */ |
| 717 | public BuildOptions createBuildOptions(OptionsClassProvider optionsProvider) { |
gregce | 9a3028c | 2017-07-26 00:19:10 +0200 | [diff] [blame] | 718 | return BuildOptions.of(configurationOptions, optionsProvider); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 719 | } |
| 720 | |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 721 | private Environment.Frame createGlobals( |
Dmitry Lomov | 899416d | 2016-04-22 12:40:30 +0000 | [diff] [blame] | 722 | ImmutableMap<String, Object> skylarkAccessibleToplLevels, |
Damien Martin-Guillerez | f81c675 | 2016-02-15 10:50:12 +0000 | [diff] [blame] | 723 | ImmutableList<Class<?>> modules) { |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 724 | try (Mutability mutability = Mutability.create("ConfiguredRuleClassProvider globals")) { |
| 725 | Environment env = createSkylarkRuleClassEnvironment( |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 726 | mutability, |
| 727 | SkylarkModules.getGlobals(modules), |
| 728 | Options.getDefaults(SkylarkSemanticsOptions.class), |
| 729 | /*eventHandler=*/ null, |
| 730 | /*astFileContentHashCode=*/ null, |
| 731 | /*importMap=*/ null); |
Dmitry Lomov | 899416d | 2016-04-22 12:40:30 +0000 | [diff] [blame] | 732 | for (Map.Entry<String, Object> entry : skylarkAccessibleToplLevels.entrySet()) { |
| 733 | env.setup(entry.getKey(), entry.getValue()); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 734 | } |
| 735 | return env.getGlobals(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 736 | } |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 737 | } |
| 738 | |
| 739 | private Environment createSkylarkRuleClassEnvironment( |
| 740 | Mutability mutability, |
| 741 | Environment.Frame globals, |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 742 | SkylarkSemanticsOptions skylarkSemantics, |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 743 | EventHandler eventHandler, |
| 744 | String astFileContentHashCode, |
John Field | 1ea7fc3 | 2015-12-22 19:37:19 +0000 | [diff] [blame] | 745 | Map<String, Extension> importMap) { |
Laurent Le Brun | a31bc4e | 2016-10-27 12:48:22 +0000 | [diff] [blame] | 746 | Environment env = |
| 747 | Environment.builder(mutability) |
Laurent Le Brun | a31bc4e | 2016-10-27 12:48:22 +0000 | [diff] [blame] | 748 | .setGlobals(globals) |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 749 | .setSemantics(skylarkSemantics) |
Laurent Le Brun | a31bc4e | 2016-10-27 12:48:22 +0000 | [diff] [blame] | 750 | .setEventHandler(eventHandler) |
| 751 | .setFileContentHashCode(astFileContentHashCode) |
| 752 | .setImportedExtensions(importMap) |
| 753 | .setPhase(Phase.LOADING) |
| 754 | .build(); |
| 755 | SkylarkUtils.setToolsRepository(env, toolsRepository); |
| 756 | return env; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 757 | } |
| 758 | |
| 759 | @Override |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 760 | public Environment createSkylarkRuleClassEnvironment( |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 761 | Label extensionLabel, |
| 762 | Mutability mutability, |
| 763 | SkylarkSemanticsOptions skylarkSemantics, |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 764 | EventHandler eventHandler, |
| 765 | String astFileContentHashCode, |
John Field | 1ea7fc3 | 2015-12-22 19:37:19 +0000 | [diff] [blame] | 766 | Map<String, Extension> importMap) { |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 767 | return createSkylarkRuleClassEnvironment( |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 768 | mutability, |
brandjon | cc0f6a6 | 2017-05-08 13:19:21 -0400 | [diff] [blame] | 769 | globals.withLabel(extensionLabel), |
brandjon | b712f33 | 2017-04-29 16:03:32 +0200 | [diff] [blame] | 770 | skylarkSemantics, |
| 771 | eventHandler, |
| 772 | astFileContentHashCode, |
| 773 | importMap); |
Janak Ramakrishnan | b6e33bc | 2015-09-06 21:05:23 +0000 | [diff] [blame] | 774 | } |
| 775 | |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 776 | @Override |
| 777 | public String getDefaultWorkspacePrefix() { |
| 778 | return defaultWorkspaceFilePrefix; |
| 779 | } |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 780 | |
Janak Ramakrishnan | b6e33bc | 2015-09-06 21:05:23 +0000 | [diff] [blame] | 781 | @Override |
Damien Martin-Guillerez | 585c87b | 2016-03-31 08:24:37 +0000 | [diff] [blame] | 782 | public String getDefaultWorkspaceSuffix() { |
| 783 | return defaultWorkspaceFileSuffix; |
Kristina Chodorow | bc4b4b1 | 2015-02-11 15:54:50 +0000 | [diff] [blame] | 784 | } |
Greg Estren | c396f9c | 2016-10-04 18:01:01 +0000 | [diff] [blame] | 785 | |
| 786 | /** |
| 787 | * Returns all registered {@link BuildConfiguration.Fragment} classes. |
| 788 | */ |
| 789 | public Set<Class<? extends BuildConfiguration.Fragment>> getAllFragments() { |
| 790 | ImmutableSet.Builder<Class<? extends BuildConfiguration.Fragment>> fragmentsBuilder = |
| 791 | ImmutableSet.builder(); |
| 792 | for (ConfigurationFragmentFactory factory : getConfigurationFragments()) { |
| 793 | fragmentsBuilder.add(factory.creates()); |
| 794 | } |
| 795 | fragmentsBuilder.add(getUniversalFragment()); |
| 796 | return fragmentsBuilder.build(); |
| 797 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 798 | } |