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 | |
| 15 | package com.google.devtools.build.lib.packages; |
| 16 | |
| 17 | import com.google.common.annotations.VisibleForTesting; |
tomlu | a155b53 | 2017-11-08 20:12:47 +0100 | [diff] [blame] | 18 | import com.google.common.base.Preconditions; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 19 | import com.google.common.collect.ImmutableList; |
| 20 | import com.google.common.collect.ImmutableMap; |
| 21 | import com.google.common.collect.ImmutableSet; |
| 22 | import com.google.common.collect.ImmutableSortedSet; |
| 23 | import com.google.common.collect.Iterables; |
| 24 | import com.google.common.collect.Lists; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 25 | import com.google.devtools.build.lib.cmdline.Label; |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 26 | import com.google.devtools.build.lib.cmdline.LabelSyntaxException; |
Kristina Chodorow | 73fa203 | 2015-08-28 17:57:46 +0000 | [diff] [blame] | 27 | import com.google.devtools.build.lib.cmdline.PackageIdentifier; |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 28 | import com.google.devtools.build.lib.cmdline.RepositoryName; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 29 | import com.google.devtools.build.lib.collect.CollectionUtils; |
| 30 | import com.google.devtools.build.lib.collect.ImmutableSortedKeyMap; |
| 31 | import com.google.devtools.build.lib.events.Event; |
| 32 | import com.google.devtools.build.lib.events.EventHandler; |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 33 | import com.google.devtools.build.lib.events.ExtendedEventHandler.Postable; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 34 | import com.google.devtools.build.lib.events.Location; |
| 35 | import com.google.devtools.build.lib.packages.AttributeMap.AcceptsLabelAttribute; |
| 36 | import com.google.devtools.build.lib.packages.License.DistributionType; |
michajlo | 095a341 | 2018-02-13 16:45:05 -0800 | [diff] [blame] | 37 | import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext; |
shahan | fae34b9 | 2018-02-13 10:08:47 -0800 | [diff] [blame] | 38 | import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec; |
michajlo | 095a341 | 2018-02-13 16:45:05 -0800 | [diff] [blame] | 39 | import com.google.devtools.build.lib.skyframe.serialization.SerializationContext; |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 40 | import com.google.devtools.build.lib.skyframe.serialization.SerializationException; |
brandjon | fba45f5 | 2017-10-26 18:03:24 +0200 | [diff] [blame] | 41 | import com.google.devtools.build.lib.syntax.SkylarkSemantics; |
Laurent Le Brun | d8b80c3 | 2016-06-03 14:38:19 +0000 | [diff] [blame] | 42 | import com.google.devtools.build.lib.util.SpellChecker; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 43 | import com.google.devtools.build.lib.vfs.Path; |
| 44 | import com.google.devtools.build.lib.vfs.PathFragment; |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 45 | import com.google.devtools.build.lib.vfs.Root; |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 46 | import com.google.protobuf.CodedInputStream; |
| 47 | import com.google.protobuf.CodedOutputStream; |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 48 | import java.io.IOException; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 49 | import java.io.PrintStream; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 50 | import java.util.ArrayList; |
| 51 | import java.util.Collection; |
| 52 | import java.util.Collections; |
| 53 | import java.util.HashMap; |
| 54 | import java.util.List; |
| 55 | import java.util.Map; |
lberki | 0d8d4cf | 2017-09-05 16:01:44 +0200 | [diff] [blame] | 56 | import java.util.Objects; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 57 | import java.util.Set; |
lberki | 3ef288c | 2018-03-23 03:06:27 -0700 | [diff] [blame] | 58 | import java.util.TreeMap; |
Han-Wen Nienhuys | 67e6f98 | 2016-01-15 15:54:12 +0000 | [diff] [blame] | 59 | import javax.annotation.Nullable; |
| 60 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 61 | /** |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 62 | * A package, which is a container of {@link Rule}s, each of which contains a dictionary of named |
| 63 | * attributes. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 64 | * |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 65 | * <p>Package instances are intended to be immutable and for all practical purposes can be treated |
| 66 | * as such. Note, however, that some member variables exposed via the public interface are not |
| 67 | * strictly immutable, so until their types are guaranteed immutable we're not applying the |
| 68 | * {@code @Immutable} annotation here. |
janakr | cbf8c0a | 2018-02-16 12:16:36 -0800 | [diff] [blame] | 69 | * |
| 70 | * <p>When changing this class, make sure to make corresponding changes to serialization! |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 71 | */ |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 72 | @SuppressWarnings("JavaLangClash") |
Michajlo Matijkiw | 17f11eb | 2015-10-14 04:19:28 +0000 | [diff] [blame] | 73 | public class Package { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 74 | /** |
| 75 | * Common superclass for all name-conflict exceptions. |
| 76 | */ |
| 77 | public static class NameConflictException extends Exception { |
| 78 | protected NameConflictException(String message) { |
| 79 | super(message); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | /** |
| 84 | * The repository identifier for this package. |
| 85 | */ |
| 86 | private final PackageIdentifier packageIdentifier; |
| 87 | |
| 88 | /** |
| 89 | * The name of the package, e.g. "foo/bar". |
| 90 | */ |
| 91 | protected final String name; |
| 92 | |
| 93 | /** |
| 94 | * Like name, but in the form of a PathFragment. |
| 95 | */ |
| 96 | private final PathFragment nameFragment; |
| 97 | |
| 98 | /** |
| 99 | * The filename of this package's BUILD file. |
| 100 | */ |
| 101 | protected Path filename; |
| 102 | |
| 103 | /** |
| 104 | * The directory in which this package's BUILD file resides. All InputFile |
| 105 | * members of the packages are located relative to this directory. |
| 106 | */ |
| 107 | private Path packageDirectory; |
| 108 | |
| 109 | /** |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 110 | * The name of the workspace this package is in. Used as a prefix for the runfiles directory. |
| 111 | * This can be set in the WORKSPACE file. This must be a valid target name. |
| 112 | */ |
Ulf Adams | d13207c | 2015-09-04 14:53:43 +0000 | [diff] [blame] | 113 | protected String workspaceName; |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 114 | |
| 115 | /** |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 116 | * The root of the source tree in which this package was found. It is an invariant that {@code |
| 117 | * sourceRoot.getRelative(packageId.getSourceRoot()).equals(packageDirectory)}. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 118 | */ |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 119 | private Root sourceRoot; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 120 | |
| 121 | /** |
| 122 | * The "Make" environment of this package, containing package-local |
| 123 | * definitions of "Make" variables. |
| 124 | */ |
lberki | 3ef288c | 2018-03-23 03:06:27 -0700 | [diff] [blame] | 125 | private ImmutableMap<String, String> makeEnv; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 126 | |
carmi | 31c6a61 | 2017-05-17 22:56:19 +0200 | [diff] [blame] | 127 | /** The collection of all targets defined in this package, indexed by name. */ |
| 128 | protected ImmutableSortedKeyMap<String, Target> targets; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 129 | |
| 130 | /** |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 131 | * Default visibility for rules that do not specify it. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 132 | */ |
| 133 | private RuleVisibility defaultVisibility; |
| 134 | private boolean defaultVisibilitySet; |
| 135 | |
| 136 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 137 | * Default package-level 'testonly' value for rules that do not specify it. |
| 138 | */ |
| 139 | private boolean defaultTestOnly = false; |
| 140 | |
| 141 | /** |
| 142 | * Default package-level 'deprecation' value for rules that do not specify it. |
| 143 | */ |
| 144 | private String defaultDeprecation; |
| 145 | |
| 146 | /** |
| 147 | * Default header strictness checking for rules that do not specify it. |
| 148 | */ |
| 149 | private String defaultHdrsCheck; |
| 150 | |
Carmi Grushko | 81dca61 | 2016-07-27 02:12:15 +0000 | [diff] [blame] | 151 | /** Default copts for cc_* rules. The rules' individual copts will append to this value. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 152 | private ImmutableList<String> defaultCopts; |
| 153 | |
| 154 | /** |
| 155 | * The InputFile target corresponding to this package's BUILD file. |
| 156 | */ |
| 157 | private InputFile buildFile; |
| 158 | |
| 159 | /** |
| 160 | * True iff this package's BUILD files contained lexical or grammatical |
| 161 | * errors, or experienced errors during evaluation, or semantic errors during |
| 162 | * the construction of any rule. |
| 163 | * |
| 164 | * <p>Note: A package containing errors does not necessarily prevent a build; |
| 165 | * if all the rules needed for a given build were constructed prior to the |
| 166 | * first error, the build may proceed. |
| 167 | */ |
| 168 | private boolean containsErrors; |
| 169 | |
| 170 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 171 | * The list of transitive closure of the Skylark file dependencies. |
| 172 | */ |
| 173 | private ImmutableList<Label> skylarkFileDependencies; |
| 174 | |
| 175 | /** |
| 176 | * The package's default "licenses" and "distribs" attributes, as specified |
| 177 | * in calls to licenses() and distribs() in the BUILD file. |
| 178 | */ |
| 179 | // These sets contain the values specified by the most recent licenses() or |
| 180 | // distribs() declarations encountered during package parsing: |
| 181 | private License defaultLicense; |
| 182 | private Set<License.DistributionType> defaultDistributionSet; |
| 183 | |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 184 | /** |
| 185 | * The map from each repository to that repository's remappings map. |
| 186 | * This is only used in the //external package, it is an empty map for all other packages. |
| 187 | * For example, an entry of {"@foo" : {"@x", "@y"}} indicates that, within repository foo, |
| 188 | * "@x" should be remapped to "@y". |
| 189 | */ |
| 190 | private ImmutableMap<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>> |
| 191 | externalPackageRepositoryMappings; |
| 192 | |
| 193 | /** |
| 194 | * The map of repository reassignments for BUILD packages. This will be empty for packages |
| 195 | * within the main workspace. |
| 196 | */ |
| 197 | private ImmutableMap<RepositoryName, RepositoryName> repositoryMapping; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 198 | |
| 199 | /** |
| 200 | * The names of the package() attributes that declare default values for rule |
| 201 | * {@link RuleClass#COMPATIBLE_ENVIRONMENT_ATTR} and {@link RuleClass#RESTRICTED_ENVIRONMENT_ATTR} |
| 202 | * values when not explicitly specified. |
| 203 | */ |
| 204 | public static final String DEFAULT_COMPATIBLE_WITH_ATTRIBUTE = "default_compatible_with"; |
| 205 | public static final String DEFAULT_RESTRICTED_TO_ATTRIBUTE = "default_restricted_to"; |
| 206 | |
| 207 | private Set<Label> defaultCompatibleWith = ImmutableSet.of(); |
| 208 | private Set<Label> defaultRestrictedTo = ImmutableSet.of(); |
| 209 | |
| 210 | private ImmutableSet<String> features; |
| 211 | |
| 212 | private ImmutableList<Event> events; |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 213 | private ImmutableList<Postable> posts; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 214 | |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 215 | private ImmutableList<String> registeredExecutionPlatforms; |
| 216 | private ImmutableList<String> registeredToolchains; |
John Cater | 64a6c15 | 2017-07-11 16:50:27 +0200 | [diff] [blame] | 217 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 218 | /** |
| 219 | * Package initialization, part 1 of 3: instantiates a new package with the |
| 220 | * given name. |
| 221 | * |
| 222 | * <p>As part of initialization, {@link Builder} constructs {@link InputFile} |
| 223 | * and {@link PackageGroup} instances that require a valid Package instance where |
| 224 | * {@link Package#getNameFragment()} is accessible. That's why these settings are |
| 225 | * applied here at the start. |
| 226 | * |
| 227 | * @precondition {@code name} must be a suffix of |
| 228 | * {@code filename.getParentDirectory())}. |
| 229 | */ |
kchodorow | 6357092 | 2017-07-11 22:22:22 +0200 | [diff] [blame] | 230 | protected Package(PackageIdentifier packageId, String runfilesPrefix) { |
| 231 | this.packageIdentifier = packageId; |
| 232 | this.workspaceName = runfilesPrefix; |
shreyax | a1f90ce | 2018-02-15 12:05:13 -0800 | [diff] [blame] | 233 | this.nameFragment = packageId.getPackageFragment(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 234 | this.name = nameFragment.getPathString(); |
| 235 | } |
| 236 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 237 | /** Returns this packages' identifier. */ |
| 238 | public PackageIdentifier getPackageIdentifier() { |
| 239 | return packageIdentifier; |
| 240 | } |
| 241 | |
| 242 | /** |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 243 | * Returns the repository mapping for the requested external repository. |
| 244 | * |
| 245 | * @throws UnsupportedOperationException if called from a package other than |
| 246 | * the //external package |
| 247 | */ |
| 248 | public ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping( |
| 249 | RepositoryName repository) { |
| 250 | if (!isWorkspace()) { |
| 251 | throw new UnsupportedOperationException("Can only access the external package repository" |
| 252 | + "mappings from the //external package"); |
| 253 | } |
| 254 | return externalPackageRepositoryMappings.getOrDefault(repository, ImmutableMap.of()); |
| 255 | } |
| 256 | |
| 257 | /** |
dannark | c7c5ab1 | 2018-06-21 14:40:46 -0700 | [diff] [blame] | 258 | * Returns the repository mapping for the requested external repository. |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 259 | * |
| 260 | * @throws LabelSyntaxException if repository is not a valid {@link RepositoryName} |
dannark | c7c5ab1 | 2018-06-21 14:40:46 -0700 | [diff] [blame] | 261 | * @throws UnsupportedOperationException if called from any package other than the //external |
| 262 | * package |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 263 | */ |
dannark | c7c5ab1 | 2018-06-21 14:40:46 -0700 | [diff] [blame] | 264 | public ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping(String repository) |
| 265 | throws LabelSyntaxException, UnsupportedOperationException { |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 266 | RepositoryName repositoryName = RepositoryName.create(repository); |
| 267 | return getRepositoryMapping(repositoryName); |
| 268 | } |
| 269 | |
dannark | c7c5ab1 | 2018-06-21 14:40:46 -0700 | [diff] [blame] | 270 | /** Get the repository mapping for this package. */ |
| 271 | public ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping() { |
| 272 | return repositoryMapping; |
| 273 | } |
| 274 | |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 275 | /** |
| 276 | * Gets the global name for a repository within an external repository. |
| 277 | * |
| 278 | * <p>{@code localName} is a repository name reference found in a BUILD file within a repository |
| 279 | * external to the main workspace. This method returns the main workspace's global remapped name |
| 280 | * for {@code localName}. |
| 281 | */ |
| 282 | public RepositoryName getGlobalName(RepositoryName localName) { |
| 283 | RepositoryName globalname = repositoryMapping.get(localName); |
| 284 | return globalname != null ? globalname : localName; |
| 285 | } |
| 286 | |
| 287 | /** Returns whether we are in the WORKSPACE file or not. */ |
| 288 | public boolean isWorkspace() { |
| 289 | return getPackageIdentifier().equals(Label.EXTERNAL_PACKAGE_IDENTIFIER); |
| 290 | } |
| 291 | |
| 292 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 293 | * Package initialization: part 2 of 3: sets this package's default header |
| 294 | * strictness checking. |
| 295 | * |
| 296 | * <p>This is needed to support C++-related rule classes |
| 297 | * which accesses {@link #getDefaultHdrsCheck} from the still-under-construction |
| 298 | * package. |
| 299 | */ |
| 300 | protected void setDefaultHdrsCheck(String defaultHdrsCheck) { |
| 301 | this.defaultHdrsCheck = defaultHdrsCheck; |
| 302 | } |
| 303 | |
| 304 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 305 | * Set the default 'testonly' value for this package. |
| 306 | */ |
| 307 | protected void setDefaultTestOnly(boolean testOnly) { |
| 308 | defaultTestOnly = testOnly; |
| 309 | } |
| 310 | |
| 311 | /** |
| 312 | * Set the default 'deprecation' value for this package. |
| 313 | */ |
| 314 | protected void setDefaultDeprecation(String deprecation) { |
| 315 | defaultDeprecation = deprecation; |
| 316 | } |
| 317 | |
| 318 | /** |
| 319 | * Sets the default value to use for a rule's {@link RuleClass#COMPATIBLE_ENVIRONMENT_ATTR} |
| 320 | * attribute when not explicitly specified by the rule. |
| 321 | */ |
| 322 | protected void setDefaultCompatibleWith(Set<Label> environments) { |
| 323 | defaultCompatibleWith = environments; |
| 324 | } |
| 325 | |
| 326 | /** |
| 327 | * Sets the default value to use for a rule's {@link RuleClass#RESTRICTED_ENVIRONMENT_ATTR} |
| 328 | * attribute when not explicitly specified by the rule. |
| 329 | */ |
| 330 | protected void setDefaultRestrictedTo(Set<Label> environments) { |
| 331 | defaultRestrictedTo = environments; |
| 332 | } |
| 333 | |
Klaus Aehlig | 6e7c208 | 2018-01-12 10:36:06 -0800 | [diff] [blame] | 334 | /** |
| 335 | * Returns the source root (a directory) beneath which this package's BUILD file was found. |
| 336 | * |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 337 | * <p>Assumes invariant: {@code |
| 338 | * getSourceRoot().getRelative(packageId.getSourceRoot()).equals(getPackageDirectory())} |
Klaus Aehlig | 6e7c208 | 2018-01-12 10:36:06 -0800 | [diff] [blame] | 339 | */ |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 340 | public Root getSourceRoot() { |
Klaus Aehlig | 6e7c208 | 2018-01-12 10:36:06 -0800 | [diff] [blame] | 341 | return sourceRoot; |
| 342 | } |
| 343 | |
Ulf Adams | a28b540 | 2017-02-24 09:28:44 +0000 | [diff] [blame] | 344 | // This must always be consistent with Root.computeSourceRoot; otherwise computing source roots |
| 345 | // from exec paths does not work, which can break the action cache for input-discovering actions. |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 346 | private static Root getSourceRoot(Path buildFile, PathFragment packageFragment) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 347 | Path current = buildFile.getParentDirectory(); |
Kristina Chodorow | b6fbab7 | 2016-01-28 14:38:31 +0000 | [diff] [blame] | 348 | for (int i = 0, len = packageFragment.segmentCount(); |
| 349 | i < len && !packageFragment.equals(PathFragment.EMPTY_FRAGMENT); i++) { |
Klaus Aehlig | 30ef629 | 2018-06-08 07:23:34 -0700 | [diff] [blame] | 350 | if (current != null) { |
| 351 | current = current.getParentDirectory(); |
| 352 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 353 | } |
tomlu | ee6a686 | 2018-01-17 14:36:26 -0800 | [diff] [blame] | 354 | return Root.fromPath(current); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 355 | } |
| 356 | |
| 357 | /** |
| 358 | * Package initialization: part 3 of 3: applies all other settings and completes |
| 359 | * initialization of the package. |
| 360 | * |
| 361 | * <p>Only after this method is called can this package be considered "complete" |
| 362 | * and be shared publicly. |
| 363 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 364 | protected void finishInit(Builder builder) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 365 | // If any error occurred during evaluation of this package, consider all |
| 366 | // rules in the package to be "in error" also (even if they were evaluated |
| 367 | // prior to the error). This behaviour is arguably stricter than need be, |
| 368 | // but stopping a build only for some errors but not others creates user |
| 369 | // confusion. |
| 370 | if (builder.containsErrors) { |
| 371 | for (Rule rule : builder.getTargets(Rule.class)) { |
| 372 | rule.setContainsErrors(); |
| 373 | } |
| 374 | } |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 375 | this.filename = builder.getFilename(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 376 | this.packageDirectory = filename.getParentDirectory(); |
| 377 | |
Dmitry Lomov | e36a66c | 2017-02-17 14:48:48 +0000 | [diff] [blame] | 378 | this.sourceRoot = getSourceRoot(filename, packageIdentifier.getSourceRoot()); |
Klaus Aehlig | 30ef629 | 2018-06-08 07:23:34 -0700 | [diff] [blame] | 379 | if ((sourceRoot.asPath() == null |
| 380 | || !sourceRoot.getRelative(packageIdentifier.getSourceRoot()).equals(packageDirectory)) |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 381 | && !filename.getBaseName().equals("WORKSPACE")) { |
| 382 | throw new IllegalArgumentException( |
Kristina Chodorow | dc30c07 | 2015-04-22 13:48:47 +0000 | [diff] [blame] | 383 | "Invalid BUILD file name for package '" + packageIdentifier + "': " + filename); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 384 | } |
kchodorow | 6357092 | 2017-07-11 22:22:22 +0200 | [diff] [blame] | 385 | |
lberki | 3ef288c | 2018-03-23 03:06:27 -0700 | [diff] [blame] | 386 | this.makeEnv = ImmutableMap.copyOf(builder.makeEnv); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 387 | this.targets = ImmutableSortedKeyMap.copyOf(builder.targets); |
| 388 | this.defaultVisibility = builder.defaultVisibility; |
| 389 | this.defaultVisibilitySet = builder.defaultVisibilitySet; |
| 390 | if (builder.defaultCopts == null) { |
| 391 | this.defaultCopts = ImmutableList.of(); |
| 392 | } else { |
| 393 | this.defaultCopts = ImmutableList.copyOf(builder.defaultCopts); |
| 394 | } |
| 395 | this.buildFile = builder.buildFile; |
| 396 | this.containsErrors = builder.containsErrors; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 397 | this.skylarkFileDependencies = builder.skylarkFileDependencies; |
| 398 | this.defaultLicense = builder.defaultLicense; |
| 399 | this.defaultDistributionSet = builder.defaultDistributionSet; |
| 400 | this.features = ImmutableSortedSet.copyOf(builder.features); |
| 401 | this.events = ImmutableList.copyOf(builder.events); |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 402 | this.posts = ImmutableList.copyOf(builder.posts); |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 403 | this.registeredExecutionPlatforms = ImmutableList.copyOf(builder.registeredExecutionPlatforms); |
| 404 | this.registeredToolchains = ImmutableList.copyOf(builder.registeredToolchains); |
dannark | a19a56d | 2018-06-26 11:55:40 -0700 | [diff] [blame] | 405 | this.repositoryMapping = Preconditions.checkNotNull(builder.repositoryMapping); |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 406 | ImmutableMap.Builder<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>> |
| 407 | repositoryMappingsBuilder = ImmutableMap.builder(); |
| 408 | if (!builder.externalPackageRepositoryMappings.isEmpty() && !builder.isWorkspace()) { |
| 409 | // 'repo_mapping' should only be used in the //external package, i.e. should only appear |
| 410 | // in WORKSPACE files. Currently, if someone tries to use 'repo_mapping' in a BUILD rule, they |
| 411 | // will get a "no such attribute" error. This check is to protect against a 'repo_mapping' |
| 412 | // attribute being added to a rule in the future. |
| 413 | throw new IllegalArgumentException( |
| 414 | "'repo_mapping' may only be used in the //external package"); |
| 415 | } |
| 416 | builder.externalPackageRepositoryMappings.forEach((k, v) -> |
| 417 | repositoryMappingsBuilder.put(k, ImmutableMap.copyOf(v))); |
| 418 | this.externalPackageRepositoryMappings = repositoryMappingsBuilder.build(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 419 | } |
| 420 | |
| 421 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 422 | * Returns the list of transitive closure of the Skylark file dependencies of this package. |
| 423 | */ |
| 424 | public ImmutableList<Label> getSkylarkFileDependencies() { |
| 425 | return skylarkFileDependencies; |
| 426 | } |
| 427 | |
| 428 | /** |
| 429 | * Returns the filename of the BUILD file which defines this package. The |
| 430 | * parent directory of the BUILD file is the package directory. |
| 431 | */ |
| 432 | public Path getFilename() { |
| 433 | return filename; |
| 434 | } |
| 435 | |
| 436 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 437 | * Returns the directory containing the package's BUILD file. |
| 438 | */ |
| 439 | public Path getPackageDirectory() { |
| 440 | return packageDirectory; |
| 441 | } |
| 442 | |
| 443 | /** |
| 444 | * Returns the name of this package. If this build is using external repositories then this name |
| 445 | * may not be unique! |
| 446 | */ |
| 447 | public String getName() { |
| 448 | return name; |
| 449 | } |
| 450 | |
| 451 | /** |
| 452 | * Like {@link #getName}, but has type {@code PathFragment}. |
| 453 | */ |
| 454 | public PathFragment getNameFragment() { |
| 455 | return nameFragment; |
| 456 | } |
| 457 | |
| 458 | /** |
Laurent Le Brun | e8ce847 | 2015-03-12 14:20:01 +0000 | [diff] [blame] | 459 | * Returns all make variables for a given platform. |
| 460 | */ |
lberki | 3ef288c | 2018-03-23 03:06:27 -0700 | [diff] [blame] | 461 | public ImmutableMap<String, String> getMakeEnvironment() { |
| 462 | return makeEnv; |
Laurent Le Brun | e8ce847 | 2015-03-12 14:20:01 +0000 | [diff] [blame] | 463 | } |
| 464 | |
| 465 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 466 | * Returns the label of this package's BUILD file. |
| 467 | * |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 468 | * <p> Typically <code>getBuildFileLabel().getName().equals("BUILD")</code> -- |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 469 | * though not necessarily: data in a subdirectory of a test package may use a |
| 470 | * different filename to avoid inadvertently creating a new package. |
| 471 | */ |
Mark Schaller | 4fa83ac | 2015-07-10 16:59:37 +0000 | [diff] [blame] | 472 | public Label getBuildFileLabel() { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 473 | return buildFile.getLabel(); |
| 474 | } |
| 475 | |
| 476 | /** |
| 477 | * Returns the InputFile target for this package's BUILD file. |
| 478 | */ |
| 479 | public InputFile getBuildFile() { |
| 480 | return buildFile; |
| 481 | } |
| 482 | |
| 483 | /** |
| 484 | * Returns true if errors were encountered during evaluation of this package. |
| 485 | * (The package may be incomplete and its contents should not be relied upon |
| 486 | * for critical operations. However, any Rules belonging to the package are |
| 487 | * guaranteed to be intact, unless their <code>containsErrors()</code> flag |
| 488 | * is set.) |
| 489 | */ |
| 490 | public boolean containsErrors() { |
| 491 | return containsErrors; |
| 492 | } |
| 493 | |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 494 | public List<Postable> getPosts() { |
| 495 | return posts; |
| 496 | } |
| 497 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 498 | public List<Event> getEvents() { |
| 499 | return events; |
| 500 | } |
| 501 | |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 502 | /** Returns an (immutable, ordered) view of all the targets belonging to this package. */ |
carmi | 31c6a61 | 2017-05-17 22:56:19 +0200 | [diff] [blame] | 503 | public ImmutableSortedKeyMap<String, Target> getTargets() { |
| 504 | return targets; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 505 | } |
| 506 | |
| 507 | /** |
carmi | 31c6a61 | 2017-05-17 22:56:19 +0200 | [diff] [blame] | 508 | * Common getTargets implementation, accessible by {@link Package.Builder}. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 509 | */ |
| 510 | private static Collection<Target> getTargets(Map<String, Target> targetMap) { |
| 511 | return Collections.unmodifiableCollection(targetMap.values()); |
| 512 | } |
| 513 | |
| 514 | /** |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 515 | * Returns a (read-only, ordered) iterable of all the targets belonging |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 516 | * to this package which are instances of the specified class. |
| 517 | */ |
| 518 | public <T extends Target> Iterable<T> getTargets(Class<T> targetClass) { |
| 519 | return getTargets(targets, targetClass); |
| 520 | } |
| 521 | |
| 522 | /** |
| 523 | * Common getTargets implementation, accessible by both {@link Package} and |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 524 | * {@link Package.Builder}. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 525 | */ |
| 526 | private static <T extends Target> Iterable<T> getTargets(Map<String, Target> targetMap, |
| 527 | Class<T> targetClass) { |
| 528 | return Iterables.filter(targetMap.values(), targetClass); |
| 529 | } |
| 530 | |
| 531 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 532 | * Returns the rule that corresponds to a particular BUILD target name. Useful |
| 533 | * for walking through the dependency graph of a target. |
| 534 | * Fails if the target is not a Rule. |
| 535 | */ |
Ulf Adams | b313a97 | 2015-05-04 12:05:57 +0000 | [diff] [blame] | 536 | @VisibleForTesting // Should be package-private |
| 537 | public Rule getRule(String targetName) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 538 | return (Rule) targets.get(targetName); |
| 539 | } |
| 540 | |
John Cater | b4f461e | 2016-10-25 16:16:35 +0000 | [diff] [blame] | 541 | /** Returns all rules in the package that match the given rule class. */ |
| 542 | public Iterable<Rule> getRulesMatchingRuleClass(final String ruleClass) { |
| 543 | Iterable<Rule> targets = getTargets(Rule.class); |
laurentlb | 3d2a68c | 2017-06-30 00:32:04 +0200 | [diff] [blame] | 544 | return Iterables.filter(targets, rule -> rule.getRuleClass().equals(ruleClass)); |
John Cater | b4f461e | 2016-10-25 16:16:35 +0000 | [diff] [blame] | 545 | } |
| 546 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 547 | /** |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 548 | * Returns this package's workspace name. |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 549 | */ |
Kristina Chodorow | 734e7f7 | 2016-01-29 15:04:31 +0000 | [diff] [blame] | 550 | public String getWorkspaceName() { |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 551 | return workspaceName; |
| 552 | } |
| 553 | |
| 554 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 555 | * Returns the features specified in the <code>package()</code> declaration. |
| 556 | */ |
| 557 | public ImmutableSet<String> getFeatures() { |
| 558 | return features; |
| 559 | } |
| 560 | |
| 561 | /** |
| 562 | * Returns the target (a member of this package) whose name is "targetName". |
| 563 | * First rules are searched, then output files, then input files. The target |
| 564 | * name must be valid, as defined by {@code LabelValidator#validateTargetName}. |
| 565 | * |
| 566 | * @throws NoSuchTargetException if the specified target was not found. |
| 567 | */ |
| 568 | public Target getTarget(String targetName) throws NoSuchTargetException { |
| 569 | Target target = targets.get(targetName); |
| 570 | if (target != null) { |
| 571 | return target; |
| 572 | } |
| 573 | |
| 574 | // No such target. |
| 575 | |
| 576 | // If there's a file on the disk that's not mentioned in the BUILD file, |
| 577 | // produce a more informative error. NOTE! this code path is only executed |
| 578 | // on failure, which is (relatively) very rare. In the common case no |
| 579 | // stat(2) is executed. |
| 580 | Path filename = getPackageDirectory().getRelative(targetName); |
| 581 | String suffix; |
twerth | c4ba94c | 2018-05-30 11:48:57 -0700 | [diff] [blame] | 582 | if (!PathFragment.isNormalized(targetName) || "*".equals(targetName)) { |
| 583 | // Don't check for file existence if the target name is not normalized |
| 584 | // because the error message would be confusing and wrong. If the |
| 585 | // targetName is "foo/bar/.", and there is a directory "foo/bar", it |
| 586 | // doesn't mean that "//pkg:foo/bar/." is a valid label. |
| 587 | // Also don't check if the target name is a single * character since |
| 588 | // it's invalid on Windows. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 589 | suffix = ""; |
| 590 | } else if (filename.isDirectory()) { |
| 591 | suffix = "; however, a source directory of this name exists. (Perhaps add " |
| 592 | + "'exports_files([\"" + targetName + "\"])' to " + name + "/BUILD, or define a " |
| 593 | + "filegroup?)"; |
| 594 | } else if (filename.exists()) { |
| 595 | suffix = "; however, a source file of this name exists. (Perhaps add " |
| 596 | + "'exports_files([\"" + targetName + "\"])' to " + name + "/BUILD?)"; |
| 597 | } else { |
Laurent Le Brun | 57badf4 | 2017-01-02 15:12:24 +0000 | [diff] [blame] | 598 | suffix = SpellChecker.didYouMean(targetName, targets.keySet()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 599 | } |
| 600 | |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 601 | throw makeNoSuchTargetException(targetName, suffix); |
| 602 | } |
| 603 | |
| 604 | protected NoSuchTargetException makeNoSuchTargetException(String targetName, String suffix) { |
| 605 | Label label; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 606 | try { |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 607 | label = createLabel(targetName); |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 608 | } catch (LabelSyntaxException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 609 | throw new IllegalArgumentException(targetName); |
| 610 | } |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 611 | String msg = String.format( |
| 612 | "target '%s' not declared in package '%s'%s defined by %s", |
| 613 | targetName, |
| 614 | name, |
| 615 | suffix, |
| 616 | filename); |
| 617 | return new NoSuchTargetException(label, msg); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 618 | } |
| 619 | |
| 620 | /** |
| 621 | * Creates a label for a target inside this package. |
| 622 | * |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 623 | * @throws LabelSyntaxException if the {@code targetName} is invalid |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 624 | */ |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 625 | public Label createLabel(String targetName) throws LabelSyntaxException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 626 | return Label.create(packageIdentifier, targetName); |
| 627 | } |
| 628 | |
| 629 | /** |
| 630 | * Returns the default visibility for this package. |
| 631 | */ |
| 632 | public RuleVisibility getDefaultVisibility() { |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 633 | return defaultVisibility; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 634 | } |
| 635 | |
| 636 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 637 | * Returns the default testonly value. |
| 638 | */ |
| 639 | public Boolean getDefaultTestOnly() { |
| 640 | return defaultTestOnly; |
| 641 | } |
| 642 | |
| 643 | /** |
Greg Estren | c48214d | 2015-03-17 22:43:19 +0000 | [diff] [blame] | 644 | * Returns the default deprecation value. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 645 | */ |
| 646 | public String getDefaultDeprecation() { |
| 647 | return defaultDeprecation; |
| 648 | } |
| 649 | |
Carmi Grushko | 81dca61 | 2016-07-27 02:12:15 +0000 | [diff] [blame] | 650 | /** Gets the default header checking mode. */ |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 651 | public String getDefaultHdrsCheck() { |
Googler | 198a54f | 2016-01-18 11:02:10 +0000 | [diff] [blame] | 652 | return defaultHdrsCheck != null ? defaultHdrsCheck : "strict"; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 653 | } |
| 654 | |
| 655 | /** |
| 656 | * Returns the default copts value, to which rules should append their |
| 657 | * specific copts. |
| 658 | */ |
| 659 | public ImmutableList<String> getDefaultCopts() { |
| 660 | return defaultCopts; |
| 661 | } |
| 662 | |
| 663 | /** |
| 664 | * Returns whether the default header checking mode has been set or it is the |
| 665 | * default value. |
| 666 | */ |
| 667 | public boolean isDefaultHdrsCheckSet() { |
| 668 | return defaultHdrsCheck != null; |
| 669 | } |
| 670 | |
| 671 | public boolean isDefaultVisibilitySet() { |
| 672 | return defaultVisibilitySet; |
| 673 | } |
| 674 | |
| 675 | /** |
| 676 | * Gets the parsed license object for the default license |
| 677 | * declared by this package. |
| 678 | */ |
| 679 | public License getDefaultLicense() { |
| 680 | return defaultLicense; |
| 681 | } |
| 682 | |
| 683 | /** |
| 684 | * Returns the parsed set of distributions declared as the default for this |
| 685 | * package. |
| 686 | */ |
| 687 | public Set<License.DistributionType> getDefaultDistribs() { |
| 688 | return defaultDistributionSet; |
| 689 | } |
| 690 | |
| 691 | /** |
| 692 | * Returns the default value to use for a rule's {@link RuleClass#COMPATIBLE_ENVIRONMENT_ATTR} |
| 693 | * attribute when not explicitly specified by the rule. |
| 694 | */ |
| 695 | public Set<Label> getDefaultCompatibleWith() { |
| 696 | return defaultCompatibleWith; |
| 697 | } |
| 698 | |
| 699 | /** |
| 700 | * Returns the default value to use for a rule's {@link RuleClass#RESTRICTED_ENVIRONMENT_ATTR} |
| 701 | * attribute when not explicitly specified by the rule. |
| 702 | */ |
| 703 | public Set<Label> getDefaultRestrictedTo() { |
| 704 | return defaultRestrictedTo; |
| 705 | } |
| 706 | |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 707 | public ImmutableList<String> getRegisteredExecutionPlatforms() { |
| 708 | return registeredExecutionPlatforms; |
John Cater | 0b29e64 | 2018-01-22 05:21:06 -0800 | [diff] [blame] | 709 | } |
| 710 | |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 711 | public ImmutableList<String> getRegisteredToolchains() { |
| 712 | return registeredToolchains; |
John Cater | 64a6c15 | 2017-07-11 16:50:27 +0200 | [diff] [blame] | 713 | } |
| 714 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 715 | @Override |
| 716 | public String toString() { |
Han-Wen Nienhuys | 58070da | 2015-04-20 11:37:58 +0000 | [diff] [blame] | 717 | return "Package(" + name + ")=" |
| 718 | + (targets != null ? getTargets(Rule.class) : "initializing..."); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 719 | } |
| 720 | |
| 721 | /** |
| 722 | * Dumps the package for debugging. Do not depend on the exact format/contents of this debugging |
| 723 | * output. |
| 724 | */ |
| 725 | public void dump(PrintStream out) { |
| 726 | out.println(" Package " + getName() + " (" + getFilename() + ")"); |
| 727 | |
| 728 | // Rules: |
| 729 | out.println(" Rules"); |
| 730 | for (Rule rule : getTargets(Rule.class)) { |
| 731 | out.println(" " + rule.getTargetKind() + " " + rule.getLabel()); |
| 732 | for (Attribute attr : rule.getAttributes()) { |
| 733 | for (Object possibleValue : AggregatingAttributeMapper.of(rule) |
| 734 | .visitAttribute(attr.getName(), attr.getType())) { |
| 735 | out.println(" " + attr.getName() + " = " + possibleValue); |
| 736 | } |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | // Files: |
| 741 | out.println(" Files"); |
| 742 | for (FileTarget file : getTargets(FileTarget.class)) { |
| 743 | out.print(" " + file.getTargetKind() + " " + file.getLabel()); |
| 744 | if (file instanceof OutputFile) { |
| 745 | out.println(" (generated by " + ((OutputFile) file).getGeneratingRule().getLabel() + ")"); |
| 746 | } else { |
| 747 | out.println(); |
| 748 | } |
| 749 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 750 | } |
| 751 | |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 752 | public static Builder newExternalPackageBuilder(Builder.Helper helper, Path workspacePath, |
| 753 | String runfilesPrefix) { |
| 754 | Builder b = new Builder(helper.createFreshPackage( |
| 755 | Label.EXTERNAL_PACKAGE_IDENTIFIER, runfilesPrefix)); |
Han-Wen Nienhuys | f172d39 | 2015-09-18 17:37:51 +0000 | [diff] [blame] | 756 | b.setFilename(workspacePath); |
Han-Wen Nienhuys | f172d39 | 2015-09-18 17:37:51 +0000 | [diff] [blame] | 757 | return b; |
| 758 | } |
| 759 | |
Nathan Harmata | caa000a | 2016-06-07 17:46:19 +0000 | [diff] [blame] | 760 | /** |
| 761 | * A builder for {@link Package} objects. Only intended to be used by {@link PackageFactory} and |
| 762 | * {@link com.google.devtools.build.lib.skyframe.PackageFunction}. |
| 763 | */ |
Han-Wen Nienhuys | f172d39 | 2015-09-18 17:37:51 +0000 | [diff] [blame] | 764 | public static class Builder { |
John Cater | 64a6c15 | 2017-07-11 16:50:27 +0200 | [diff] [blame] | 765 | |
nharmata | 23319fc | 2018-02-28 13:03:12 -0800 | [diff] [blame] | 766 | public interface Helper { |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 767 | /** |
| 768 | * Returns a fresh {@link Package} instance that a {@link Builder} will internally mutate |
Nathan Harmata | caa000a | 2016-06-07 17:46:19 +0000 | [diff] [blame] | 769 | * during package loading. Called by {@link PackageFactory}. |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 770 | */ |
| 771 | Package createFreshPackage(PackageIdentifier packageId, String runfilesPrefix); |
Nathan Harmata | caa000a | 2016-06-07 17:46:19 +0000 | [diff] [blame] | 772 | |
| 773 | /** |
| 774 | * Called after {@link com.google.devtools.build.lib.skyframe.PackageFunction} is completely |
nharmata | 23319fc | 2018-02-28 13:03:12 -0800 | [diff] [blame] | 775 | * done loading the given {@link Package}. |
| 776 | * |
| 777 | * @param pkg the loaded {@link Package} |
| 778 | * @param skylarkSemantics are the semantics used to load the package |
nharmata | a2fc4e3 | 2018-03-07 16:25:10 -0800 | [diff] [blame] | 779 | * @param loadTimeMs the wall time, in ms, that it took to load the package. More precisely, |
| 780 | * this is the wall time of the call to {@link PackageFactory#createPackageFromAst}. |
| 781 | * Notably, this does not include the time to read and parse the package's BUILD file, nor |
| 782 | * the time to read, parse, or evaluate any of the transitively loaded .bzl files. |
Nathan Harmata | caa000a | 2016-06-07 17:46:19 +0000 | [diff] [blame] | 783 | */ |
nharmata | 23319fc | 2018-02-28 13:03:12 -0800 | [diff] [blame] | 784 | void onLoadingComplete(Package pkg, SkylarkSemantics skylarkSemantics, long loadTimeMs); |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 785 | } |
| 786 | |
| 787 | /** {@link Helper} that simply calls the {@link Package} constructor. */ |
| 788 | public static class DefaultHelper implements Helper { |
| 789 | public static final DefaultHelper INSTANCE = new DefaultHelper(); |
| 790 | |
| 791 | private DefaultHelper() { |
| 792 | } |
| 793 | |
| 794 | @Override |
| 795 | public Package createFreshPackage(PackageIdentifier packageId, String runfilesPrefix) { |
| 796 | return new Package(packageId, runfilesPrefix); |
| 797 | } |
Nathan Harmata | caa000a | 2016-06-07 17:46:19 +0000 | [diff] [blame] | 798 | |
| 799 | @Override |
nharmata | 23319fc | 2018-02-28 13:03:12 -0800 | [diff] [blame] | 800 | public void onLoadingComplete( |
| 801 | Package pkg, SkylarkSemantics skylarkSemantics, long loadTimeMs) { |
Nathan Harmata | caa000a | 2016-06-07 17:46:19 +0000 | [diff] [blame] | 802 | } |
Ulf Adams | 4226be2 | 2015-09-03 17:00:54 +0000 | [diff] [blame] | 803 | } |
| 804 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 805 | /** |
| 806 | * The output instance for this builder. Needs to be instantiated and |
| 807 | * available with name info throughout initialization. All other settings |
Michajlo Matijkiw | 17f11eb | 2015-10-14 04:19:28 +0000 | [diff] [blame] | 808 | * are applied during {@link #build}. See {@link Package#Package} |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 809 | * and {@link Package#finishInit} for details. |
| 810 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 811 | protected Package pkg; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 812 | |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 813 | // The map from each repository to that repository's remappings map. |
| 814 | // This is only used in the //external package, it is an empty map for all other packages. |
| 815 | private final HashMap<RepositoryName, HashMap<RepositoryName, RepositoryName>> |
| 816 | externalPackageRepositoryMappings = new HashMap<>(); |
| 817 | // The map of repository reassignments for BUILD packages loaded within external repositories. |
dannark | c82074a | 2018-08-01 16:01:23 -0700 | [diff] [blame^] | 818 | // It contains an entry from "@<main workspace name>" to "@" for packages within |
| 819 | // the main workspace. |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 820 | private ImmutableMap<RepositoryName, RepositoryName> repositoryMapping = ImmutableMap.of(); |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 821 | private Path filename = null; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 822 | private Label buildFileLabel = null; |
| 823 | private InputFile buildFile = null; |
lberki | 3ef288c | 2018-03-23 03:06:27 -0700 | [diff] [blame] | 824 | // TreeMap so that the iteration order of variables is predictable. This is useful so that the |
| 825 | // serialized representation is deterministic. |
| 826 | private TreeMap<String, String> makeEnv = new TreeMap<>(); |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 827 | private RuleVisibility defaultVisibility = ConstantRuleVisibility.PRIVATE; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 828 | private boolean defaultVisibilitySet; |
| 829 | private List<String> defaultCopts = null; |
| 830 | private List<String> features = new ArrayList<>(); |
| 831 | private List<Event> events = Lists.newArrayList(); |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 832 | private List<Postable> posts = Lists.newArrayList(); |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 833 | @Nullable String ioExceptionMessage = null; |
| 834 | @Nullable private IOException ioException = null; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 835 | private boolean containsErrors = false; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 836 | |
| 837 | private License defaultLicense = License.NO_LICENSE; |
| 838 | private Set<License.DistributionType> defaultDistributionSet = License.DEFAULT_DISTRIB; |
| 839 | |
| 840 | protected Map<String, Target> targets = new HashMap<>(); |
| 841 | protected Map<Label, EnvironmentGroup> environmentGroups = new HashMap<>(); |
| 842 | |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 843 | protected ImmutableList<Label> skylarkFileDependencies = ImmutableList.of(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 844 | |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 845 | protected List<String> registeredExecutionPlatforms = new ArrayList<>(); |
| 846 | protected List<String> registeredToolchains = new ArrayList<>(); |
John Cater | 64a6c15 | 2017-07-11 16:50:27 +0200 | [diff] [blame] | 847 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 848 | /** |
| 849 | * True iff the "package" function has already been called in this package. |
| 850 | */ |
| 851 | private boolean packageFunctionUsed; |
| 852 | |
| 853 | /** |
| 854 | * The collection of the prefixes of every output file. Maps every prefix |
| 855 | * to an output file whose prefix it is. |
| 856 | * |
| 857 | * <p>This is needed to make the output file prefix conflict check be |
| 858 | * reasonably fast. However, since it can potentially take a lot of memory and |
| 859 | * is useless after the package has been loaded, it isn't passed to the |
| 860 | * package itself. |
| 861 | */ |
| 862 | private Map<String, OutputFile> outputFilePrefixes = new HashMap<>(); |
| 863 | |
| 864 | private boolean alreadyBuilt = false; |
| 865 | |
| 866 | private EventHandler builderEventHandler = new EventHandler() { |
| 867 | @Override |
| 868 | public void handle(Event event) { |
| 869 | addEvent(event); |
| 870 | } |
| 871 | }; |
| 872 | |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 873 | protected Builder(Package pkg) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 874 | this.pkg = pkg; |
| 875 | if (pkg.getName().startsWith("javatests/")) { |
| 876 | setDefaultTestonly(true); |
| 877 | } |
| 878 | } |
| 879 | |
Nathan Harmata | 42fb560 | 2016-05-25 20:32:08 +0000 | [diff] [blame] | 880 | public Builder(Helper helper, PackageIdentifier id, String runfilesPrefix) { |
| 881 | this(helper.createFreshPackage(id, runfilesPrefix)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 882 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 883 | |
| 884 | protected PackageIdentifier getPackageIdentifier() { |
| 885 | return pkg.getPackageIdentifier(); |
| 886 | } |
| 887 | |
Damien Martin-Guillerez | 8ca065c2 | 2015-11-27 16:22:59 +0000 | [diff] [blame] | 888 | /** Determine if we are in the WORKSPACE file or not */ |
| 889 | public boolean isWorkspace() { |
Lukacs Berki | e19ee27 | 2015-12-10 11:34:29 +0000 | [diff] [blame] | 890 | return pkg.getPackageIdentifier().equals(Label.EXTERNAL_PACKAGE_IDENTIFIER); |
Damien Martin-Guillerez | 8ca065c2 | 2015-11-27 16:22:59 +0000 | [diff] [blame] | 891 | } |
| 892 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 893 | /** |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 894 | * Updates the externalPackageRepositoryMappings entry for {@code repoWithin}. Adds new |
| 895 | * entry from {@code localName} to {@code mappedName} in {@code repoWithin}'s map. |
| 896 | * |
| 897 | * @param repoWithin the RepositoryName within which the mapping should apply |
| 898 | * @param localName the RepositoryName that actually appears in the WORKSPACE and BUILD files |
| 899 | * in the {@code repoWithin} repository |
| 900 | * @param mappedName the RepositoryName by which localName should be referenced |
| 901 | */ |
| 902 | public Builder addRepositoryMappingEntry( |
| 903 | RepositoryName repoWithin, RepositoryName localName, RepositoryName mappedName) { |
| 904 | HashMap<RepositoryName, RepositoryName> mapping = |
| 905 | externalPackageRepositoryMappings |
| 906 | .computeIfAbsent(repoWithin, (RepositoryName k) -> new HashMap<>()); |
| 907 | mapping.put(localName, mappedName); |
| 908 | return this; |
| 909 | } |
| 910 | |
| 911 | /** Adds all the mappings from a given {@link Package}. */ |
| 912 | public Builder addRepositoryMappings(Package aPackage) { |
| 913 | ImmutableMap<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>> |
| 914 | repositoryMappings = aPackage.externalPackageRepositoryMappings; |
| 915 | for (Map.Entry<RepositoryName, ImmutableMap<RepositoryName, RepositoryName>> repositoryName : |
| 916 | repositoryMappings.entrySet()) { |
| 917 | for (Map.Entry<RepositoryName, RepositoryName> repositoryNameRepositoryNameEntry : |
| 918 | repositoryName.getValue().entrySet()) { |
| 919 | addRepositoryMappingEntry( |
| 920 | repositoryName.getKey(), |
| 921 | repositoryNameRepositoryNameEntry.getKey(), |
| 922 | repositoryNameRepositoryNameEntry.getValue()); |
| 923 | } |
| 924 | } |
| 925 | return this; |
| 926 | } |
| 927 | |
| 928 | /** |
| 929 | * Sets the repository mapping for a regular, BUILD file package (i.e. not the //external |
| 930 | * package) |
| 931 | */ |
| 932 | Builder setRepositoryMapping(ImmutableMap<RepositoryName, RepositoryName> repositoryMapping) { |
dannark | a19a56d | 2018-06-26 11:55:40 -0700 | [diff] [blame] | 933 | this.repositoryMapping = Preconditions.checkNotNull(repositoryMapping); |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 934 | return this; |
| 935 | } |
| 936 | |
dannark | f24479d | 2018-06-21 11:55:44 -0700 | [diff] [blame] | 937 | /** Get the repository mapping for this package */ |
| 938 | ImmutableMap<RepositoryName, RepositoryName> getRepositoryMapping() { |
| 939 | return this.repositoryMapping; |
| 940 | } |
| 941 | |
dannark | c349585 | 2018-06-04 13:53:22 -0700 | [diff] [blame] | 942 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 943 | * Sets the name of this package's BUILD file. |
| 944 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 945 | Builder setFilename(Path filename) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 946 | this.filename = filename; |
| 947 | try { |
| 948 | buildFileLabel = createLabel(filename.getBaseName()); |
| 949 | addInputFile(buildFileLabel, Location.fromFile(filename)); |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 950 | } catch (LabelSyntaxException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 951 | // This can't actually happen. |
| 952 | throw new AssertionError("Package BUILD file has an illegal name: " + filename); |
| 953 | } |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 954 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 955 | } |
| 956 | |
| 957 | public Label getBuildFileLabel() { |
| 958 | return buildFileLabel; |
| 959 | } |
| 960 | |
| 961 | Path getFilename() { |
| 962 | return filename; |
| 963 | } |
| 964 | |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 965 | public List<Postable> getPosts() { |
| 966 | return posts; |
| 967 | } |
| 968 | |
Janak Ramakrishnan | 0a4c6e4 | 2015-09-17 00:37:58 +0000 | [diff] [blame] | 969 | public List<Event> getEvents() { |
| 970 | return events; |
| 971 | } |
| 972 | |
lberki | 3ef288c | 2018-03-23 03:06:27 -0700 | [diff] [blame] | 973 | Builder setMakeVariable(String name, String value) { |
| 974 | this.makeEnv.put(name, value); |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 975 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 976 | } |
| 977 | |
| 978 | /** |
| 979 | * Sets the default visibility for this package. Called at most once per |
| 980 | * package from PackageFactory. |
| 981 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 982 | Builder setDefaultVisibility(RuleVisibility visibility) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 983 | this.defaultVisibility = visibility; |
| 984 | this.defaultVisibilitySet = true; |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 985 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 986 | } |
| 987 | |
| 988 | /** |
| 989 | * Sets whether the default visibility is set in the BUILD file. |
| 990 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 991 | Builder setDefaultVisibilitySet(boolean defaultVisibilitySet) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 992 | this.defaultVisibilitySet = defaultVisibilitySet; |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 993 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 994 | } |
| 995 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 996 | /** Sets the default value of 'testonly'. Rule-level 'testonly' will override this. */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 997 | Builder setDefaultTestonly(boolean defaultTestonly) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 998 | pkg.setDefaultTestOnly(defaultTestonly); |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 999 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1000 | } |
| 1001 | |
| 1002 | /** |
| 1003 | * Sets the default value of 'deprecation'. Rule-level 'deprecation' will append to this. |
| 1004 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1005 | Builder setDefaultDeprecation(String defaultDeprecation) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1006 | pkg.setDefaultDeprecation(defaultDeprecation); |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1007 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1008 | } |
| 1009 | |
| 1010 | /** |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 1011 | * Uses the workspace name from {@code //external} to set this package's workspace name. |
| 1012 | */ |
Han-Wen Nienhuys | 2cffe03 | 2015-09-21 15:28:40 +0000 | [diff] [blame] | 1013 | @VisibleForTesting |
| 1014 | public Builder setWorkspaceName(String workspaceName) { |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 1015 | pkg.workspaceName = workspaceName; |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1016 | return this; |
Kristina Chodorow | 91876f0 | 2015-02-27 17:14:12 +0000 | [diff] [blame] | 1017 | } |
| 1018 | |
| 1019 | /** |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1020 | * Returns whether the "package" function has been called yet |
| 1021 | */ |
| 1022 | public boolean isPackageFunctionUsed() { |
| 1023 | return packageFunctionUsed; |
| 1024 | } |
| 1025 | |
| 1026 | public void setPackageFunctionUsed() { |
| 1027 | packageFunctionUsed = true; |
| 1028 | } |
| 1029 | |
| 1030 | /** |
| 1031 | * Sets the default header checking mode. |
| 1032 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1033 | public Builder setDefaultHdrsCheck(String hdrsCheck) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1034 | // Note that this setting is propagated directly to the package because |
| 1035 | // other code needs the ability to read this info directly from the |
| 1036 | // under-construction package. See {@link Package#setDefaultHdrsCheck}. |
| 1037 | pkg.setDefaultHdrsCheck(hdrsCheck); |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1038 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1039 | } |
| 1040 | |
Carmi Grushko | 81dca61 | 2016-07-27 02:12:15 +0000 | [diff] [blame] | 1041 | /** Sets the default value of copts. Rule-level copts will append to this. */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1042 | public Builder setDefaultCopts(List<String> defaultCopts) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1043 | this.defaultCopts = defaultCopts; |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1044 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1045 | } |
| 1046 | |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1047 | public Builder addFeatures(Iterable<String> features) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1048 | Iterables.addAll(this.features, features); |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1049 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1050 | } |
| 1051 | |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1052 | Builder setIOExceptionAndMessage(IOException e, String message) { |
| 1053 | this.ioException = e; |
| 1054 | this.ioExceptionMessage = message; |
| 1055 | return setContainsErrors(); |
| 1056 | } |
| 1057 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1058 | /** |
| 1059 | * Declares that errors were encountering while loading this package. |
| 1060 | */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1061 | public Builder setContainsErrors() { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1062 | containsErrors = true; |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1063 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1064 | } |
| 1065 | |
| 1066 | public boolean containsErrors() { |
| 1067 | return containsErrors; |
| 1068 | } |
| 1069 | |
Klaus Aehlig | 5c04d2a | 2017-06-13 18:14:15 +0200 | [diff] [blame] | 1070 | public Builder addPosts(Iterable<Postable> posts) { |
| 1071 | for (Postable post : posts) { |
| 1072 | addPost(post); |
| 1073 | } |
| 1074 | return this; |
| 1075 | } |
| 1076 | |
| 1077 | public Builder addPost(Postable post) { |
| 1078 | this.posts.add(post); |
| 1079 | return this; |
| 1080 | } |
| 1081 | |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1082 | public Builder addEvents(Iterable<Event> events) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1083 | for (Event event : events) { |
| 1084 | addEvent(event); |
| 1085 | } |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1086 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1087 | } |
| 1088 | |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1089 | public Builder addEvent(Event event) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1090 | this.events.add(event); |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1091 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1092 | } |
| 1093 | |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1094 | Builder setSkylarkFileDependencies(ImmutableList<Label> skylarkFileDependencies) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1095 | this.skylarkFileDependencies = skylarkFileDependencies; |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1096 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1097 | } |
| 1098 | |
| 1099 | /** |
| 1100 | * Sets the default license for this package. |
| 1101 | */ |
| 1102 | void setDefaultLicense(License license) { |
| 1103 | this.defaultLicense = license; |
| 1104 | } |
| 1105 | |
| 1106 | License getDefaultLicense() { |
| 1107 | return defaultLicense; |
| 1108 | } |
| 1109 | |
| 1110 | /** |
| 1111 | * Initializes the default set of distributions for targets in this package. |
| 1112 | * |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 1113 | * <p> TODO(bazel-team): (2011) consider moving the license & distribs info into Metadata--maybe |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1114 | * even in the Build language. |
| 1115 | */ |
| 1116 | void setDefaultDistribs(Set<DistributionType> dists) { |
| 1117 | this.defaultDistributionSet = dists; |
| 1118 | } |
| 1119 | |
| 1120 | Set<DistributionType> getDefaultDistribs() { |
| 1121 | return defaultDistributionSet; |
| 1122 | } |
| 1123 | |
| 1124 | /** |
| 1125 | * Sets the default value to use for a rule's {@link RuleClass#COMPATIBLE_ENVIRONMENT_ATTR} |
| 1126 | * attribute when not explicitly specified by the rule. Records a package error if |
| 1127 | * any labels are duplicated. |
| 1128 | */ |
| 1129 | void setDefaultCompatibleWith(List<Label> environments, String attrName, Location location) { |
| 1130 | if (!checkForDuplicateLabels(environments, "package " + pkg.getName(), attrName, location, |
| 1131 | builderEventHandler)) { |
| 1132 | setContainsErrors(); |
| 1133 | } |
| 1134 | pkg.setDefaultCompatibleWith(ImmutableSet.copyOf(environments)); |
| 1135 | } |
| 1136 | |
| 1137 | /** |
| 1138 | * Sets the default value to use for a rule's {@link RuleClass#RESTRICTED_ENVIRONMENT_ATTR} |
| 1139 | * attribute when not explicitly specified by the rule. Records a package error if |
| 1140 | * any labels are duplicated. |
| 1141 | */ |
| 1142 | void setDefaultRestrictedTo(List<Label> environments, String attrName, Location location) { |
| 1143 | if (!checkForDuplicateLabels(environments, "package " + pkg.getName(), attrName, location, |
| 1144 | builderEventHandler)) { |
| 1145 | setContainsErrors(); |
| 1146 | } |
| 1147 | |
| 1148 | pkg.setDefaultRestrictedTo(ImmutableSet.copyOf(environments)); |
| 1149 | } |
| 1150 | |
| 1151 | /** |
Mark Schaller | ee62445 | 2016-01-13 18:41:24 +0000 | [diff] [blame] | 1152 | * Creates a new {@link Rule} {@code r} where {@code r.getPackage()} is the {@link Package} |
| 1153 | * associated with this {@link Builder}. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1154 | * |
Mark Schaller | ee62445 | 2016-01-13 18:41:24 +0000 | [diff] [blame] | 1155 | * <p>The created {@link Rule} will have no attribute values, no output files, and therefore |
| 1156 | * will be in an invalid state. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1157 | */ |
Mark Schaller | ee62445 | 2016-01-13 18:41:24 +0000 | [diff] [blame] | 1158 | Rule createRule( |
| 1159 | Label label, |
| 1160 | RuleClass ruleClass, |
| 1161 | Location location, |
Michajlo Matijkiw | 1a75907 | 2015-10-22 13:52:00 +0000 | [diff] [blame] | 1162 | AttributeContainer attributeContainer) { |
Michajlo Matijkiw | 6d47141 | 2016-08-09 20:35:45 +0000 | [diff] [blame] | 1163 | return new Rule( |
| 1164 | pkg, |
| 1165 | label, |
| 1166 | ruleClass, |
| 1167 | location, |
| 1168 | attributeContainer); |
| 1169 | } |
| 1170 | |
| 1171 | /** |
Michajlo Matijkiw | 0433a68 | 2016-08-15 15:02:36 +0000 | [diff] [blame] | 1172 | * Same as {@link #createRule(Label, RuleClass, Location, AttributeContainer)}, except |
Michajlo Matijkiw | 6d47141 | 2016-08-09 20:35:45 +0000 | [diff] [blame] | 1173 | * allows specifying an {@link ImplicitOutputsFunction} override. Only use if you know what |
| 1174 | * you're doing. |
| 1175 | */ |
| 1176 | Rule createRule( |
| 1177 | Label label, |
| 1178 | RuleClass ruleClass, |
| 1179 | Location location, |
| 1180 | AttributeContainer attributeContainer, |
| 1181 | ImplicitOutputsFunction implicitOutputsFunction) { |
| 1182 | return new Rule( |
| 1183 | pkg, |
| 1184 | label, |
| 1185 | ruleClass, |
| 1186 | location, |
| 1187 | attributeContainer, |
| 1188 | implicitOutputsFunction); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1189 | } |
| 1190 | |
Han-Wen Nienhuys | 67e6f98 | 2016-01-15 15:54:12 +0000 | [diff] [blame] | 1191 | @Nullable |
| 1192 | public Target getTarget(String name) { |
| 1193 | return targets.get(name); |
| 1194 | } |
| 1195 | |
Klaus Aehlig | 6e7c208 | 2018-01-12 10:36:06 -0800 | [diff] [blame] | 1196 | public Collection<Target> getTargets() { |
| 1197 | return Package.getTargets(targets); |
| 1198 | } |
| 1199 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1200 | /** |
| 1201 | * Returns an (immutable, unordered) view of all the targets belonging to |
| 1202 | * this package which are instances of the specified class. |
| 1203 | */ |
| 1204 | <T extends Target> Iterable<T> getTargets(Class<T> targetClass) { |
| 1205 | return Package.getTargets(targets, targetClass); |
| 1206 | } |
| 1207 | |
| 1208 | /** |
| 1209 | * An input file name conflicts with an existing package member. |
| 1210 | */ |
| 1211 | static class GeneratedLabelConflict extends NameConflictException { |
| 1212 | private GeneratedLabelConflict(String message) { |
| 1213 | super(message); |
| 1214 | } |
| 1215 | } |
| 1216 | |
| 1217 | /** |
| 1218 | * Creates an input file target in this package with the specified name. |
| 1219 | * |
| 1220 | * @param targetName name of the input file. This must be a valid target |
| 1221 | * name as defined by {@link |
| 1222 | * com.google.devtools.build.lib.cmdline.LabelValidator#validateTargetName}. |
| 1223 | * @return the newly-created InputFile, or the old one if it already existed. |
| 1224 | * @throws GeneratedLabelConflict if the name was already taken by a Rule or |
| 1225 | * an OutputFile target. |
| 1226 | * @throws IllegalArgumentException if the name is not a valid label |
| 1227 | */ |
| 1228 | InputFile createInputFile(String targetName, Location location) |
| 1229 | throws GeneratedLabelConflict { |
| 1230 | Target existing = targets.get(targetName); |
| 1231 | if (existing == null) { |
| 1232 | try { |
| 1233 | return addInputFile(createLabel(targetName), location); |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 1234 | } catch (LabelSyntaxException e) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1235 | throw new IllegalArgumentException("FileTarget in package " + pkg.getName() |
| 1236 | + " has illegal name: " + targetName); |
| 1237 | } |
| 1238 | } else if (existing instanceof InputFile) { |
| 1239 | return (InputFile) existing; // idempotent |
| 1240 | } else { |
| 1241 | throw new GeneratedLabelConflict("generated label '//" + pkg.getName() + ":" |
| 1242 | + targetName + "' conflicts with existing " |
| 1243 | + existing.getTargetKind()); |
| 1244 | } |
| 1245 | } |
| 1246 | |
| 1247 | /** |
| 1248 | * Sets the visibility and license for an input file. The input file must already exist as |
| 1249 | * a member of this package. |
| 1250 | * @throws IllegalArgumentException if the input file doesn't exist in this |
| 1251 | * package's target map. |
| 1252 | */ |
| 1253 | void setVisibilityAndLicense(InputFile inputFile, RuleVisibility visibility, License license) { |
| 1254 | String filename = inputFile.getName(); |
| 1255 | Target cacheInstance = targets.get(filename); |
Ulf Adams | 07dba94 | 2015-03-05 14:47:37 +0000 | [diff] [blame] | 1256 | if (!(cacheInstance instanceof InputFile)) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1257 | throw new IllegalArgumentException("Can't set visibility for nonexistent FileTarget " |
| 1258 | + filename + " in package " + pkg.getName() + "."); |
| 1259 | } |
| 1260 | if (!((InputFile) cacheInstance).isVisibilitySpecified() |
| 1261 | || cacheInstance.getVisibility() != visibility |
lberki | 0d8d4cf | 2017-09-05 16:01:44 +0200 | [diff] [blame] | 1262 | || !Objects.equals(cacheInstance.getLicense(), license)) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1263 | targets.put(filename, new InputFile( |
| 1264 | pkg, cacheInstance.getLabel(), cacheInstance.getLocation(), visibility, license)); |
| 1265 | } |
| 1266 | } |
| 1267 | |
| 1268 | /** |
| 1269 | * Creates a label for a target inside this package. |
| 1270 | * |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 1271 | * @throws LabelSyntaxException if the {@code targetName} is invalid |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1272 | */ |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 1273 | Label createLabel(String targetName) throws LabelSyntaxException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1274 | return Label.create(pkg.getPackageIdentifier(), targetName); |
| 1275 | } |
| 1276 | |
| 1277 | /** |
| 1278 | * Adds a package group to the package. |
| 1279 | */ |
| 1280 | void addPackageGroup(String name, Collection<String> packages, Collection<Label> includes, |
| 1281 | EventHandler eventHandler, Location location) |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 1282 | throws NameConflictException, LabelSyntaxException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1283 | PackageGroup group = |
| 1284 | new PackageGroup(createLabel(name), pkg, packages, includes, eventHandler, location); |
| 1285 | Target existing = targets.get(group.getName()); |
| 1286 | if (existing != null) { |
| 1287 | throw nameConflict(group, existing); |
| 1288 | } |
| 1289 | |
| 1290 | targets.put(group.getName(), group); |
| 1291 | |
| 1292 | if (group.containsErrors()) { |
| 1293 | setContainsErrors(); |
| 1294 | } |
| 1295 | } |
| 1296 | |
| 1297 | /** |
| 1298 | * Checks if any labels in the given list appear multiple times and reports an appropriate |
| 1299 | * error message if so. Returns true if no duplicates were found, false otherwise. |
| 1300 | * |
Laurent Le Brun | 41079bd | 2015-06-19 09:37:25 +0000 | [diff] [blame] | 1301 | * <p> TODO(bazel-team): apply this to all build functions (maybe automatically?), possibly |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1302 | * integrate with RuleClass.checkForDuplicateLabels. |
| 1303 | */ |
| 1304 | private static boolean checkForDuplicateLabels(Collection<Label> labels, String owner, |
| 1305 | String attrName, Location location, EventHandler eventHandler) { |
| 1306 | Set<Label> dupes = CollectionUtils.duplicatedElementsOf(labels); |
| 1307 | for (Label dupe : dupes) { |
| 1308 | eventHandler.handle(Event.error(location, String.format( |
| 1309 | "label '%s' is duplicated in the '%s' list of '%s'", dupe, attrName, owner))); |
| 1310 | } |
| 1311 | return dupes.isEmpty(); |
| 1312 | } |
| 1313 | |
| 1314 | /** |
| 1315 | * Adds an environment group to the package. |
| 1316 | */ |
| 1317 | void addEnvironmentGroup(String name, List<Label> environments, List<Label> defaults, |
| 1318 | EventHandler eventHandler, Location location) |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 1319 | throws NameConflictException, LabelSyntaxException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1320 | |
| 1321 | if (!checkForDuplicateLabels(environments, name, "environments", location, eventHandler) |
| 1322 | || !checkForDuplicateLabels(defaults, name, "defaults", location, eventHandler)) { |
| 1323 | setContainsErrors(); |
| 1324 | return; |
| 1325 | } |
| 1326 | |
| 1327 | EnvironmentGroup group = new EnvironmentGroup(createLabel(name), pkg, environments, |
| 1328 | defaults, location); |
| 1329 | Target existing = targets.get(group.getName()); |
| 1330 | if (existing != null) { |
| 1331 | throw nameConflict(group, existing); |
| 1332 | } |
| 1333 | |
| 1334 | targets.put(group.getName(), group); |
| 1335 | Collection<Event> membershipErrors = group.validateMembership(); |
| 1336 | if (!membershipErrors.isEmpty()) { |
| 1337 | for (Event error : membershipErrors) { |
| 1338 | eventHandler.handle(error); |
| 1339 | } |
| 1340 | setContainsErrors(); |
| 1341 | return; |
| 1342 | } |
| 1343 | |
| 1344 | // For each declared environment, make sure it doesn't also belong to some other group. |
| 1345 | for (Label environment : group.getEnvironments()) { |
| 1346 | EnvironmentGroup otherGroup = environmentGroups.get(environment); |
| 1347 | if (otherGroup != null) { |
| 1348 | eventHandler.handle(Event.error(location, "environment " + environment + " belongs to" |
| 1349 | + " both " + group.getLabel() + " and " + otherGroup.getLabel())); |
| 1350 | setContainsErrors(); |
| 1351 | } else { |
| 1352 | environmentGroups.put(environment, group); |
| 1353 | } |
| 1354 | } |
| 1355 | } |
| 1356 | |
Nathan Harmata | cf73844 | 2016-06-28 14:52:21 +0000 | [diff] [blame] | 1357 | /** |
| 1358 | * Same as {@link #addRule}, except with no name conflict checks. |
| 1359 | * |
| 1360 | * <p>Don't call this function unless you know what you're doing. |
| 1361 | */ |
| 1362 | void addRuleUnchecked(Rule rule) { |
Lukacs Berki | 4867ef7 | 2016-05-17 11:15:19 +0000 | [diff] [blame] | 1363 | Preconditions.checkArgument(rule.getPackage() == pkg); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1364 | // Now, modify the package: |
| 1365 | for (OutputFile outputFile : rule.getOutputFiles()) { |
| 1366 | targets.put(outputFile.getName(), outputFile); |
nharmata | b4060b6 | 2017-04-04 17:11:39 +0000 | [diff] [blame] | 1367 | PathFragment outputFileFragment = PathFragment.create(outputFile.getName()); |
tomlu | e7552c5 | 2018-01-19 10:25:19 -0800 | [diff] [blame] | 1368 | int segmentCount = outputFileFragment.segmentCount(); |
| 1369 | for (int i = 1; i < segmentCount; i++) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1370 | String prefix = outputFileFragment.subFragment(0, i).toString(); |
laurentlb | 3d2a68c | 2017-06-30 00:32:04 +0200 | [diff] [blame] | 1371 | outputFilePrefixes.putIfAbsent(prefix, outputFile); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1372 | } |
| 1373 | } |
| 1374 | targets.put(rule.getName(), rule); |
| 1375 | if (rule.containsErrors()) { |
| 1376 | this.setContainsErrors(); |
| 1377 | } |
| 1378 | } |
| 1379 | |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 1380 | void addRule(Rule rule) throws NameConflictException, InterruptedException { |
Nathan Harmata | cf73844 | 2016-06-28 14:52:21 +0000 | [diff] [blame] | 1381 | checkForConflicts(rule); |
| 1382 | addRuleUnchecked(rule); |
| 1383 | } |
| 1384 | |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 1385 | public void addRegisteredExecutionPlatforms(List<String> platforms) { |
| 1386 | this.registeredExecutionPlatforms.addAll(platforms); |
John Cater | 0b29e64 | 2018-01-22 05:21:06 -0800 | [diff] [blame] | 1387 | } |
| 1388 | |
John Cater | 0084e16 | 2018-03-12 18:50:56 -0700 | [diff] [blame] | 1389 | void addRegisteredToolchains(List<String> toolchains) { |
| 1390 | this.registeredToolchains.addAll(toolchains); |
John Cater | 64a6c15 | 2017-07-11 16:50:27 +0200 | [diff] [blame] | 1391 | } |
| 1392 | |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1393 | private Builder beforeBuild(boolean discoverAssumedInputFiles) |
| 1394 | throws InterruptedException, NoSuchPackageException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1395 | Preconditions.checkNotNull(pkg); |
| 1396 | Preconditions.checkNotNull(filename); |
| 1397 | Preconditions.checkNotNull(buildFileLabel); |
| 1398 | Preconditions.checkNotNull(makeEnv); |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1399 | if (ioException != null) { |
| 1400 | throw new NoSuchPackageException(getPackageIdentifier(), ioExceptionMessage, ioException); |
| 1401 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1402 | |
| 1403 | // We create the original BUILD InputFile when the package filename is set; however, the |
| 1404 | // visibility may be overridden with an exports_files directive, so we need to obtain the |
| 1405 | // current instance here. |
| 1406 | buildFile = (InputFile) Preconditions.checkNotNull(targets.get(buildFileLabel.getName())); |
| 1407 | |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 1408 | // The Iterable returned by getTargets is sorted, so when we build up the list of tests by |
| 1409 | // processing it in order below, that list will be sorted too. |
| 1410 | Iterable<Rule> sortedRules = Lists.newArrayList(getTargets(Rule.class)); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1411 | |
Michajlo Matijkiw | aa09648 | 2016-10-19 14:50:32 +0000 | [diff] [blame] | 1412 | if (discoverAssumedInputFiles) { |
| 1413 | // All labels mentioned in a rule that refer to an unknown target in the |
| 1414 | // current package are assumed to be InputFiles, so let's create them: |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 1415 | for (final Rule rule : sortedRules) { |
Michajlo Matijkiw | aa09648 | 2016-10-19 14:50:32 +0000 | [diff] [blame] | 1416 | AggregatingAttributeMapper.of(rule).visitLabels(new AcceptsLabelAttribute() { |
| 1417 | @Override |
| 1418 | public void acceptLabelAttribute(Label label, Attribute attribute) { |
| 1419 | createInputFileMaybe(label, rule.getAttributeLocation(attribute.getName())); |
| 1420 | } |
| 1421 | }); |
| 1422 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1423 | } |
| 1424 | |
| 1425 | // "test_suite" rules have the idiosyncratic semantics of implicitly |
| 1426 | // depending on all tests in the package, iff tests=[] and suites=[]. |
| 1427 | // Note, we implement this here when the Package is fully constructed, |
| 1428 | // since clearly this information isn't available at Rule construction |
| 1429 | // time, as forward references are permitted. |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 1430 | List<Label> sortedTests = new ArrayList<>(); |
| 1431 | for (Rule rule : sortedRules) { |
Greg Estren | c48214d | 2015-03-17 22:43:19 +0000 | [diff] [blame] | 1432 | if (TargetUtils.isTestRule(rule) && !TargetUtils.hasManualTag(rule)) { |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 1433 | sortedTests.add(rule.getLabel()); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1434 | } |
| 1435 | } |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 1436 | for (Rule rule : sortedRules) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1437 | AttributeMap attributes = NonconfigurableAttributeMapper.of(rule); |
| 1438 | if (rule.getRuleClass().equals("test_suite") |
Greg Estren | c83a701 | 2016-12-21 00:05:46 +0000 | [diff] [blame] | 1439 | && attributes.get("tests", BuildType.LABEL_LIST).isEmpty()) { |
nharmata | 59c16f6 | 2017-08-07 19:49:09 +0200 | [diff] [blame] | 1440 | rule.setAttributeValueByName("$implicit_tests", sortedTests); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1441 | } |
| 1442 | } |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1443 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1444 | } |
| 1445 | |
Michajlo Matijkiw | 9140718 | 2015-05-29 14:27:09 +0000 | [diff] [blame] | 1446 | /** Intended for use by {@link com.google.devtools.build.lib.skyframe.PackageFunction} only. */ |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1447 | public Builder buildPartial() throws InterruptedException, NoSuchPackageException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1448 | if (alreadyBuilt) { |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1449 | return this; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1450 | } |
Michajlo Matijkiw | aa09648 | 2016-10-19 14:50:32 +0000 | [diff] [blame] | 1451 | return beforeBuild(/*discoverAssumedInputFiles=*/ true); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1452 | } |
| 1453 | |
Nathan Harmata | 6b253fa | 2016-05-24 15:27:18 +0000 | [diff] [blame] | 1454 | /** |
| 1455 | * Removes a target from the {@link Package} under construction. Intended to be used only by |
| 1456 | * {@link com.google.devtools.build.lib.skyframe.PackageFunction} to remove targets whose |
| 1457 | * labels cross subpackage boundaries. |
| 1458 | */ |
| 1459 | public void removeTarget(Target target) { |
| 1460 | if (target.getPackage() == pkg) { |
| 1461 | this.targets.remove(target.getName()); |
| 1462 | } |
| 1463 | } |
| 1464 | |
Michajlo Matijkiw | 9140718 | 2015-05-29 14:27:09 +0000 | [diff] [blame] | 1465 | /** Intended for use by {@link com.google.devtools.build.lib.skyframe.PackageFunction} only. */ |
Han-Wen Nienhuys | 086e5f2 | 2015-04-21 11:39:59 +0000 | [diff] [blame] | 1466 | public Package finishBuild() { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1467 | if (alreadyBuilt) { |
| 1468 | return pkg; |
| 1469 | } |
Han-Wen Nienhuys | f172d39 | 2015-09-18 17:37:51 +0000 | [diff] [blame] | 1470 | |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1471 | // Freeze targets and distributions. |
| 1472 | targets = ImmutableMap.copyOf(targets); |
| 1473 | defaultDistributionSet = |
| 1474 | Collections.unmodifiableSet(defaultDistributionSet); |
| 1475 | |
Greg Estren | d0f10dc | 2015-03-17 22:19:37 +0000 | [diff] [blame] | 1476 | // Now all targets have been loaded, so we validate the group's member environments. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1477 | for (EnvironmentGroup envGroup : ImmutableSet.copyOf(environmentGroups.values())) { |
Greg Estren | d0f10dc | 2015-03-17 22:19:37 +0000 | [diff] [blame] | 1478 | Collection<Event> errors = envGroup.processMemberEnvironments(targets); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1479 | if (!errors.isEmpty()) { |
| 1480 | addEvents(errors); |
| 1481 | setContainsErrors(); |
| 1482 | } |
| 1483 | } |
| 1484 | |
| 1485 | // Build the package. |
| 1486 | pkg.finishInit(this); |
| 1487 | alreadyBuilt = true; |
| 1488 | return pkg; |
| 1489 | } |
| 1490 | |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1491 | public Package build() throws InterruptedException, NoSuchPackageException { |
Michajlo Matijkiw | aa09648 | 2016-10-19 14:50:32 +0000 | [diff] [blame] | 1492 | return build(/*discoverAssumedInputFiles=*/ true); |
| 1493 | } |
| 1494 | |
| 1495 | /** |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1496 | * Build the package, optionally adding any labels in the package not already associated with a |
| 1497 | * target as an input file. |
Michajlo Matijkiw | aa09648 | 2016-10-19 14:50:32 +0000 | [diff] [blame] | 1498 | */ |
janakr | 28adce5 | 2017-07-13 19:55:32 +0200 | [diff] [blame] | 1499 | public Package build(boolean discoverAssumedInputFiles) |
| 1500 | throws InterruptedException, NoSuchPackageException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1501 | if (alreadyBuilt) { |
| 1502 | return pkg; |
| 1503 | } |
Michajlo Matijkiw | aa09648 | 2016-10-19 14:50:32 +0000 | [diff] [blame] | 1504 | beforeBuild(discoverAssumedInputFiles); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1505 | return finishBuild(); |
| 1506 | } |
| 1507 | |
| 1508 | /** |
| 1509 | * If "label" refers to a non-existent target in the current package, create |
| 1510 | * an InputFile target. |
| 1511 | */ |
| 1512 | void createInputFileMaybe(Label label, Location location) { |
Damien Martin-Guillerez | 4997805 | 2016-01-21 19:55:07 +0000 | [diff] [blame] | 1513 | if (label != null && label.getPackageIdentifier().equals(pkg.getPackageIdentifier())) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1514 | if (!targets.containsKey(label.getName())) { |
| 1515 | addInputFile(label, location); |
| 1516 | } |
| 1517 | } |
| 1518 | } |
| 1519 | |
| 1520 | private InputFile addInputFile(Label label, Location location) { |
| 1521 | InputFile inputFile = new InputFile(pkg, label, location); |
| 1522 | Target prev = targets.put(label.getName(), inputFile); |
| 1523 | Preconditions.checkState(prev == null); |
| 1524 | return inputFile; |
| 1525 | } |
| 1526 | |
| 1527 | /** |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 1528 | * Precondition check for addRule. We must maintain these invariants of the package: |
| 1529 | * |
| 1530 | * <ul> |
| 1531 | * <li>Each name refers to at most one target. |
| 1532 | * <li>No rule with errors is inserted into the package. |
| 1533 | * <li>The generating rule of every output file in the package must itself be in the package. |
| 1534 | * </ul> |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1535 | */ |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 1536 | private void checkForConflicts(Rule rule) throws NameConflictException, InterruptedException { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1537 | String name = rule.getName(); |
| 1538 | Target existing = targets.get(name); |
| 1539 | if (existing != null) { |
| 1540 | throw nameConflict(rule, existing); |
| 1541 | } |
| 1542 | Map<String, OutputFile> outputFiles = new HashMap<>(); |
| 1543 | |
| 1544 | for (OutputFile outputFile : rule.getOutputFiles()) { |
| 1545 | String outputFileName = outputFile.getName(); |
| 1546 | if (outputFiles.put(outputFileName, outputFile) != null) { // dups within a single rule: |
| 1547 | throw duplicateOutputFile(outputFile, outputFile); |
| 1548 | } |
| 1549 | existing = targets.get(outputFileName); |
| 1550 | if (existing != null) { |
| 1551 | throw duplicateOutputFile(outputFile, existing); |
| 1552 | } |
| 1553 | |
| 1554 | // Check if this output file is the prefix of an already existing one |
| 1555 | if (outputFilePrefixes.containsKey(outputFileName)) { |
| 1556 | throw conflictingOutputFile(outputFile, outputFilePrefixes.get(outputFileName)); |
| 1557 | } |
| 1558 | |
| 1559 | // Check if a prefix of this output file matches an already existing one |
nharmata | b4060b6 | 2017-04-04 17:11:39 +0000 | [diff] [blame] | 1560 | PathFragment outputFileFragment = PathFragment.create(outputFileName); |
tomlu | e7552c5 | 2018-01-19 10:25:19 -0800 | [diff] [blame] | 1561 | int segmentCount = outputFileFragment.segmentCount(); |
| 1562 | for (int i = 1; i < segmentCount; i++) { |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1563 | String prefix = outputFileFragment.subFragment(0, i).toString(); |
| 1564 | if (outputFiles.containsKey(prefix)) { |
| 1565 | throw conflictingOutputFile(outputFile, outputFiles.get(prefix)); |
| 1566 | } |
| 1567 | if (targets.containsKey(prefix) |
| 1568 | && targets.get(prefix) instanceof OutputFile) { |
| 1569 | throw conflictingOutputFile(outputFile, (OutputFile) targets.get(prefix)); |
| 1570 | } |
| 1571 | |
laurentlb | 3d2a68c | 2017-06-30 00:32:04 +0200 | [diff] [blame] | 1572 | outputFilePrefixes.putIfAbsent(prefix, outputFile); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1573 | } |
| 1574 | } |
| 1575 | |
| 1576 | checkForInputOutputConflicts(rule, outputFiles.keySet()); |
| 1577 | } |
| 1578 | |
| 1579 | /** |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 1580 | * A utility method that checks for conflicts between input file names and output file names for |
| 1581 | * a rule from a build file. |
| 1582 | * |
| 1583 | * @param rule the rule whose inputs and outputs are to be checked for conflicts. |
| 1584 | * @param outputFiles a set containing the names of output files to be generated by the rule. |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1585 | * @throws NameConflictException if a conflict is found. |
| 1586 | */ |
| 1587 | private void checkForInputOutputConflicts(Rule rule, Set<String> outputFiles) |
Janak Ramakrishnan | 3c0adb2 | 2016-08-15 21:54:55 +0000 | [diff] [blame] | 1588 | throws NameConflictException, InterruptedException { |
Klaus Aehlig | 6e7c208 | 2018-01-12 10:36:06 -0800 | [diff] [blame] | 1589 | PackageIdentifier packageIdentifier = rule.getLabel().getPackageIdentifier(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1590 | for (Label inputLabel : rule.getLabels()) { |
Klaus Aehlig | 6e7c208 | 2018-01-12 10:36:06 -0800 | [diff] [blame] | 1591 | if (packageIdentifier.equals(inputLabel.getPackageIdentifier()) |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1592 | && outputFiles.contains(inputLabel.getName())) { |
| 1593 | throw inputOutputNameConflict(rule, inputLabel.getName()); |
| 1594 | } |
| 1595 | } |
| 1596 | } |
| 1597 | |
| 1598 | /** An output file conflicts with another output file or the BUILD file. */ |
| 1599 | private NameConflictException duplicateOutputFile(OutputFile duplicate, Target existing) { |
| 1600 | return new NameConflictException(duplicate.getTargetKind() + " '" + duplicate.getName() |
| 1601 | + "' in rule '" + duplicate.getGeneratingRule().getName() + "' " |
| 1602 | + conflictsWith(existing)); |
| 1603 | } |
| 1604 | |
| 1605 | /** The package contains two targets with the same name. */ |
| 1606 | private NameConflictException nameConflict(Target duplicate, Target existing) { |
| 1607 | return new NameConflictException(duplicate.getTargetKind() + " '" + duplicate.getName() |
| 1608 | + "' in package '" + duplicate.getLabel().getPackageName() + "' " |
| 1609 | + conflictsWith(existing)); |
| 1610 | } |
| 1611 | |
| 1612 | /** A a rule has a input/output name conflict. */ |
| 1613 | private NameConflictException inputOutputNameConflict(Rule rule, String conflictingName) { |
| 1614 | return new NameConflictException("rule '" + rule.getName() + "' has file '" |
| 1615 | + conflictingName + "' as both an input and an output"); |
| 1616 | } |
| 1617 | |
| 1618 | private static NameConflictException conflictingOutputFile( |
| 1619 | OutputFile added, OutputFile existing) { |
| 1620 | if (added.getGeneratingRule() == existing.getGeneratingRule()) { |
| 1621 | return new NameConflictException(String.format( |
| 1622 | "rule '%s' has conflicting output files '%s' and '%s'", added.getGeneratingRule() |
| 1623 | .getName(), added.getName(), existing.getName())); |
| 1624 | } else { |
| 1625 | return new NameConflictException(String.format( |
| 1626 | "output file '%s' of rule '%s' conflicts with output file '%s' of rule '%s'", added |
| 1627 | .getName(), added.getGeneratingRule().getName(), existing.getName(), existing |
| 1628 | .getGeneratingRule().getName())); |
| 1629 | } |
| 1630 | } |
| 1631 | |
| 1632 | /** |
| 1633 | * Utility function for generating exception messages. |
| 1634 | */ |
| 1635 | private static String conflictsWith(Target target) { |
| 1636 | String message = "conflicts with existing "; |
| 1637 | if (target instanceof OutputFile) { |
Laurent Le Brun | 1159cc2 | 2017-01-04 12:27:39 +0000 | [diff] [blame] | 1638 | message += |
| 1639 | "generated file from rule '" |
| 1640 | + ((OutputFile) target).getGeneratingRule().getName() |
| 1641 | + "'"; |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1642 | } else { |
Laurent Le Brun | 1159cc2 | 2017-01-04 12:27:39 +0000 | [diff] [blame] | 1643 | message += target.getTargetKind(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1644 | } |
Laurent Le Brun | 1159cc2 | 2017-01-04 12:27:39 +0000 | [diff] [blame] | 1645 | return message + ", defined at " + target.getLocation(); |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1646 | } |
| 1647 | } |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 1648 | |
| 1649 | /** Package codec implementation. */ |
shahan | 20f35b4 | 2018-02-28 15:57:33 -0800 | [diff] [blame] | 1650 | @VisibleForTesting |
| 1651 | static final class PackageCodec implements ObjectCodec<Package> { |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 1652 | @Override |
| 1653 | public Class<Package> getEncodedClass() { |
| 1654 | return Package.class; |
| 1655 | } |
| 1656 | |
| 1657 | @Override |
| 1658 | public void serialize( |
michajlo | 095a341 | 2018-02-13 16:45:05 -0800 | [diff] [blame] | 1659 | SerializationContext context, |
michajlo | e45c055 | 2018-02-11 09:23:55 -0800 | [diff] [blame] | 1660 | Package input, |
| 1661 | CodedOutputStream codedOut) |
cpeyser | 47c04a1 | 2018-01-30 09:17:49 -0800 | [diff] [blame] | 1662 | throws IOException, SerializationException { |
janakr | 459b244 | 2018-06-05 10:26:02 -0700 | [diff] [blame] | 1663 | context.checkClassExplicitlyAllowed(Package.class); |
shahan | fae34b9 | 2018-02-13 10:08:47 -0800 | [diff] [blame] | 1664 | PackageCodecDependencies codecDeps = context.getDependency(PackageCodecDependencies.class); |
michajlo | 095a341 | 2018-02-13 16:45:05 -0800 | [diff] [blame] | 1665 | codecDeps.getPackageSerializer().serialize(context, input, codedOut); |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 1666 | } |
| 1667 | |
| 1668 | @Override |
michajlo | e45c055 | 2018-02-11 09:23:55 -0800 | [diff] [blame] | 1669 | public Package deserialize( |
michajlo | 095a341 | 2018-02-13 16:45:05 -0800 | [diff] [blame] | 1670 | DeserializationContext context, |
michajlo | e45c055 | 2018-02-11 09:23:55 -0800 | [diff] [blame] | 1671 | CodedInputStream codedIn) |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 1672 | throws SerializationException, IOException { |
shahan | fae34b9 | 2018-02-13 10:08:47 -0800 | [diff] [blame] | 1673 | PackageCodecDependencies codecDeps = context.getDependency(PackageCodecDependencies.class); |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 1674 | try { |
michajlo | 095a341 | 2018-02-13 16:45:05 -0800 | [diff] [blame] | 1675 | return codecDeps.getPackageDeserializer().deserialize(context, codedIn); |
shahan | c7667ae8 | 2018-01-11 10:10:37 -0800 | [diff] [blame] | 1676 | } catch (InterruptedException e) { |
| 1677 | throw new IllegalStateException( |
| 1678 | "Unexpected InterruptedException during Package deserialization", e); |
| 1679 | } |
| 1680 | } |
| 1681 | } |
Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 1682 | } |