// Copyright 2015 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.lib.packages; import com.google.common.base.Verify; import com.google.common.collect.Maps; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.cmdline.LabelSyntaxException; import com.google.devtools.build.lib.events.Location; import com.google.devtools.build.lib.events.StoredEventHandler; import com.google.devtools.build.lib.packages.Package.Builder; import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap; import com.google.devtools.build.lib.syntax.FuncallExpression; import com.google.devtools.build.lib.util.Preconditions; import java.util.Map; /** * A builder that helps constructing the //external package. */ public class ExternalPackageBuilder { public Rule createAndAddRepositoryRule( Package.Builder pkg, RuleClass ruleClass, RuleClass bindRuleClass, Map<String, Object> kwargs, FuncallExpression ast) throws RuleFactory.InvalidRuleException, Package.NameConflictException, LabelSyntaxException, InterruptedException { StoredEventHandler eventHandler = new StoredEventHandler(); BuildLangTypedAttributeValuesMap attributeValues = new BuildLangTypedAttributeValuesMap(kwargs); Rule rule = RuleFactory.createRule( pkg, ruleClass, attributeValues, eventHandler, ast, ast.getLocation(), /*env=*/ null, new AttributeContainer(ruleClass)); pkg.addEvents(eventHandler.getEvents()); overwriteRule(pkg, rule); for (Map.Entry<String, Label> entry : ruleClass.getExternalBindingsFunction().apply(rule).entrySet()) { Label nameLabel = Label.parseAbsolute("//external:" + entry.getKey()); addBindRule( pkg, bindRuleClass, nameLabel, entry.getValue(), rule.getLocation(), new AttributeContainer(bindRuleClass)); } return rule; } static void addBindRule( Builder pkg, RuleClass bindRuleClass, Label virtual, Label actual, Location location, AttributeContainer attributeContainer) throws RuleFactory.InvalidRuleException, Package.NameConflictException, InterruptedException { Map<String, Object> attributes = Maps.newHashMap(); // Bound rules don't have a name field, but this works because we don't want more than one // with the same virtual name. attributes.put("name", virtual.getName()); if (actual != null) { attributes.put("actual", actual); } StoredEventHandler handler = new StoredEventHandler(); BuildLangTypedAttributeValuesMap attributeValues = new BuildLangTypedAttributeValuesMap(attributes); Rule rule = RuleFactory.createRule( pkg, bindRuleClass, attributeValues, handler, /*ast=*/ null, location, /*env=*/ null, attributeContainer); overwriteRule(pkg, rule); rule.setVisibility(ConstantRuleVisibility.PUBLIC); } private static void overwriteRule(Package.Builder pkg, Rule rule) throws Package.NameConflictException, InterruptedException { Preconditions.checkArgument(rule.getOutputFiles().isEmpty()); Target old = pkg.targets.get(rule.getName()); if (old != null) { if (old instanceof Rule) { Verify.verify(((Rule) old).getOutputFiles().isEmpty()); } pkg.targets.remove(rule.getName()); } pkg.addRule(rule); } }