From e666d3b88efb59f2a8f10b18882c9f13801508d9 Mon Sep 17 00:00:00 2001 From: cparsons Date: Tue, 27 Mar 2018 09:18:53 -0700 Subject: Fix and rollforward of "Convert SkylarkRuleImplementationFunctions functions to use @SkylarkCallable instead." expand_location.targets needed to be a named parameter. RELNOTES: None. PiperOrigin-RevId: 190624472 --- .../lib/analysis/skylark/SkylarkRuleContext.java | 702 ++++++++++++++++++++- 1 file changed, 697 insertions(+), 5 deletions(-) (limited to 'src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java') diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java index b1196fe1fe..45b9f02d9b 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java @@ -27,17 +27,24 @@ import com.google.common.collect.Ordering; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ArtifactRoot; import com.google.devtools.build.lib.analysis.ActionsProvider; +import com.google.devtools.build.lib.analysis.AliasProvider; +import com.google.devtools.build.lib.analysis.CommandHelper; import com.google.devtools.build.lib.analysis.ConfigurationMakeVariableContext; import com.google.devtools.build.lib.analysis.DefaultInfo; +import com.google.devtools.build.lib.analysis.FileProvider; import com.google.devtools.build.lib.analysis.FilesToRunProvider; import com.google.devtools.build.lib.analysis.LabelExpander; import com.google.devtools.build.lib.analysis.LabelExpander.NotUniqueExpansionException; +import com.google.devtools.build.lib.analysis.LocationExpander; import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.Runfiles; +import com.google.devtools.build.lib.analysis.RunfilesProvider; import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.FragmentCollection; import com.google.devtools.build.lib.analysis.config.HostTransition; import com.google.devtools.build.lib.analysis.config.transitions.NoTransition; +import com.google.devtools.build.lib.analysis.configuredtargets.AbstractConfiguredTarget; import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.stringtemplate.ExpansionException; import com.google.devtools.build.lib.analysis.test.InstrumentedFilesCollector; @@ -59,20 +66,28 @@ import com.google.devtools.build.lib.packages.RawAttributeMapper; import com.google.devtools.build.lib.shell.ShellUtils; import com.google.devtools.build.lib.shell.ShellUtils.TokenizationException; import com.google.devtools.build.lib.skylarkinterface.Param; +import com.google.devtools.build.lib.skylarkinterface.ParamType; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; import com.google.devtools.build.lib.skylarkinterface.SkylarkValue; import com.google.devtools.build.lib.syntax.ClassObject; +import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.EvalUtils; import com.google.devtools.build.lib.syntax.FuncallExpression.FuncallException; +import com.google.devtools.build.lib.syntax.Printer; import com.google.devtools.build.lib.syntax.Runtime; import com.google.devtools.build.lib.syntax.SkylarkDict; import com.google.devtools.build.lib.syntax.SkylarkIndexable; import com.google.devtools.build.lib.syntax.SkylarkList; +import com.google.devtools.build.lib.syntax.SkylarkList.MutableList; +import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; import com.google.devtools.build.lib.syntax.SkylarkSemantics; import com.google.devtools.build.lib.syntax.Type; +import com.google.devtools.build.lib.syntax.Type.ConversionException; import com.google.devtools.build.lib.syntax.Type.LabelClass; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; @@ -854,8 +869,7 @@ public final class SkylarkRuleContext implements SkylarkValue { } ) public Artifact newFile(String filename) throws EvalException { - SkylarkRuleImplementationFunctions.checkDeprecated( - "ctx.actions.declare_file", "ctx.new_file", null, skylarkSemantics); + checkDeprecated("ctx.actions.declare_file", "ctx.new_file", null, skylarkSemantics); checkMutable("new_file"); return actionFactory.declareFile(filename, Runtime.NONE); } @@ -886,8 +900,7 @@ public final class SkylarkRuleContext implements SkylarkValue { } ) public Artifact newFile(Artifact baseArtifact, String newBaseName) throws EvalException { - SkylarkRuleImplementationFunctions.checkDeprecated( - "ctx.actions.declare_file", "ctx.new_file", null, skylarkSemantics); + checkDeprecated("ctx.actions.declare_file", "ctx.new_file", null, skylarkSemantics); checkMutable("new_file"); return actionFactory.declareFile(newBaseName, baseArtifact); } @@ -917,7 +930,7 @@ public final class SkylarkRuleContext implements SkylarkValue { } ) public Artifact newDirectory(String name, Object siblingArtifactUnchecked) throws EvalException { - SkylarkRuleImplementationFunctions.checkDeprecated( + checkDeprecated( "ctx.actions.declare_directory", "ctx.experimental_new_directory", null, skylarkSemantics); checkMutable("experimental_new_directory"); return actionFactory.declareDirectory(name, siblingArtifactUnchecked); @@ -1021,4 +1034,683 @@ public final class SkylarkRuleContext implements SkylarkValue { Package pkg = ruleContext.getRule().getPackage(); return pkg.getSourceRoot().relativize(pkg.getBuildFile().getPath()).getPathString(); } + + /** + * A Skylark built-in function to create and register a SpawnAction using a dictionary of + * parameters: action( inputs = [input1, input2, ...], outputs = [output1, output2, ...], + * executable = executable, arguments = [argument1, argument2, ...], mnemonic = 'Mnemonic', + * command = 'command', ) + */ + @SkylarkCallable( + name = "action", + doc = + "DEPRECATED. Use ctx.actions.run() or" + + " ctx.actions.run_shell().
" + + "Creates an action that runs an executable or a shell command." + + " You must specify either command or executable.\n" + + "Actions and genrules are very similar, but have different use cases. Actions are " + + "used inside rules, and genrules are used inside macros. Genrules also have make " + + "variable expansion.", + parameters = { + @Param( + name = "outputs", + type = SkylarkList.class, + generic1 = Artifact.class, + named = true, + positional = false, + doc = "List of the output files of the action." + ), + @Param( + name = "inputs", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = Artifact.class, + defaultValue = "[]", + named = true, + positional = false, + doc = "List of the input files of the action." + ), + @Param( + name = "executable", + type = Object.class, + allowedTypes = { + @ParamType(type = Artifact.class), + @ParamType(type = String.class), + @ParamType(type = Runtime.NoneType.class), + }, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "The executable file to be called by the action." + ), + @Param( + name = "arguments", + allowedTypes = { + @ParamType(type = SkylarkList.class), + }, + defaultValue = "[]", + named = true, + positional = false, + doc = + "Command line arguments of the action." + + "Must be a list of strings or actions.args() objects." + ), + @Param( + name = "mnemonic", + type = String.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "A one-word description of the action, e.g. CppCompile or GoLink." + ), + @Param( + name = "command", + type = Object.class, + allowedTypes = { + @ParamType(type = String.class), + @ParamType(type = SkylarkList.class, generic1 = String.class), + @ParamType(type = Runtime.NoneType.class), + }, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Shell command to execute. It is usually preferable to " + + "use executable instead. " + + "Arguments are available with $1, $2, etc." + ), + @Param( + name = "progress_message", + type = String.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Progress message to show to the user during the build, " + + "e.g. \"Compiling foo.cc to create foo.o\"." + ), + @Param( + name = "use_default_shell_env", + type = Boolean.class, + defaultValue = "False", + named = true, + positional = false, + doc = "Whether the action should use the built in shell environment or not." + ), + @Param( + name = "env", + type = SkylarkDict.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "Sets the dictionary of environment variables." + ), + @Param( + name = "execution_requirements", + type = SkylarkDict.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "Information for scheduling the action. See " + + "tags " + + "for useful keys." + ), + @Param( + // TODO(bazel-team): The name here isn't accurate anymore. This is technically experimental, + // so folks shouldn't be too attached, but consider renaming to be more accurate/opaque. + name = "input_manifests", + type = SkylarkList.class, + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = + "(Experimental) sets the input runfiles metadata; " + + "they are typically generated by resolve_command." + ) + }, + allowReturnNones = true, + useLocation = true, + useEnvironment = true + ) + public Runtime.NoneType action( + SkylarkList outputs, + Object inputs, + Object executableUnchecked, + Object arguments, + Object mnemonicUnchecked, + Object commandUnchecked, + Object progressMessage, + Boolean useDefaultShellEnv, + Object envUnchecked, + Object executionRequirementsUnchecked, + Object inputManifestsUnchecked, + Location loc, + Environment env) + throws EvalException { + checkDeprecated( + "ctx.actions.run or ctx.actions.run_shell", "ctx.action", loc, env.getSemantics()); + checkMutable("action"); + if ((commandUnchecked == Runtime.NONE) == (executableUnchecked == Runtime.NONE)) { + throw new EvalException(loc, "You must specify either 'command' or 'executable' argument"); + } + boolean hasCommand = commandUnchecked != Runtime.NONE; + if (!hasCommand) { + actions() + .run( + outputs, + inputs, + executableUnchecked, + arguments, + mnemonicUnchecked, + progressMessage, + useDefaultShellEnv, + envUnchecked, + executionRequirementsUnchecked, + inputManifestsUnchecked); + + } else { + actions() + .runShell( + outputs, + inputs, + arguments, + mnemonicUnchecked, + commandUnchecked, + progressMessage, + useDefaultShellEnv, + envUnchecked, + executionRequirementsUnchecked, + inputManifestsUnchecked); + } + return Runtime.NONE; + } + + @SkylarkCallable( + name = "expand_location", + doc = + "Expands all $(location ...) templates in the given string by replacing " + + "$(location //x) with the path of the output file of target //x. " + + "Expansion only works for labels that point to direct dependencies of this rule or " + + "that are explicitly listed in the optional argument targets. " + + "

" + + "$(location ...) will cause an error if the referenced target has " + + "multiple outputs. In this case, please use $(locations ...) since it " + + "produces a space-separated list of output paths. It can be safely used for a " + + "single output file, too.", + parameters = { + @Param(name = "input", type = String.class, doc = "String to be expanded."), + @Param( + name = "targets", + type = SkylarkList.class, + generic1 = AbstractConfiguredTarget.class, + defaultValue = "[]", + named = true, + doc = "List of targets for additional lookup information." + ), + }, + allowReturnNones = true, + useLocation = true, + useEnvironment = true + ) + public String expandLocation(String input, SkylarkList targets, Location loc, Environment env) + throws EvalException { + checkMutable("expand_location"); + try { + return LocationExpander.withExecPaths( + getRuleContext(), + makeLabelMap(targets.getContents(TransitiveInfoCollection.class, "targets"))) + .expand(input); + } catch (IllegalStateException ise) { + throw new EvalException(loc, ise); + } + } + + @SkylarkCallable( + name = "file_action", + doc = + "DEPRECATED. Use ctx.actions.write instead.
" + + "Creates a file write action.", + parameters = { + @Param(name = "output", type = Artifact.class, named = true, doc = "The output file."), + @Param( + name = "content", + type = String.class, + named = true, + doc = "The contents of the file." + ), + @Param( + name = "executable", + type = Boolean.class, + defaultValue = "False", + named = true, + doc = "Whether the output file should be executable (default is False)." + ) + }, + allowReturnNones = true, + useLocation = true, + useEnvironment = true + ) + public Runtime.NoneType fileAction( + Artifact output, String content, Boolean executable, Location loc, Environment env) + throws EvalException { + checkDeprecated("ctx.actions.write", "ctx.file_action", loc, env.getSemantics()); + checkMutable("file_action"); + actions().write(output, content, executable); + return Runtime.NONE; + } + + @SkylarkCallable( + name = "empty_action", + doc = + "DEPRECATED. Use ctx.actions.do_nothing instead." + + "
" + + "Creates an empty action that neither executes a command nor produces any " + + "output, but that is useful for inserting 'extra actions'.", + parameters = { + @Param( + name = "mnemonic", + type = String.class, + named = true, + positional = false, + doc = "A one-word description of the action, e.g. CppCompile or GoLink." + ), + @Param( + name = "inputs", + allowedTypes = { + @ParamType(type = SkylarkList.class), + @ParamType(type = SkylarkNestedSet.class), + }, + generic1 = Artifact.class, + named = true, + positional = false, + defaultValue = "[]", + doc = "List of the input files of the action." + ), + }, + allowReturnNones = true, + useLocation = true, + useEnvironment = true + ) + public Runtime.NoneType emptyAction(String mnemonic, Object inputs, Location loc, Environment env) + throws EvalException { + checkDeprecated("ctx.actions.do_nothing", "ctx.empty_action", loc, env.getSemantics()); + checkMutable("empty_action"); + actions().doNothing(mnemonic, inputs); + return Runtime.NONE; + } + + @SkylarkCallable( + name = "template_action", + doc = + "DEPRECATED. " + + "Use ctx.actions.expand_template() " + + "instead.
Creates a template expansion action.", + parameters = { + @Param( + name = "template", + type = Artifact.class, + named = true, + positional = false, + doc = "The template file, which is a UTF-8 encoded text file." + ), + @Param( + name = "output", + type = Artifact.class, + named = true, + positional = false, + doc = "The output file, which is a UTF-8 encoded text file." + ), + @Param( + name = "substitutions", + type = SkylarkDict.class, + named = true, + positional = false, + doc = "Substitutions to make when expanding the template." + ), + @Param( + name = "executable", + type = Boolean.class, + defaultValue = "False", + named = true, + positional = false, + doc = "Whether the output file should be executable (default is False)." + ) + }, + allowReturnNones = true, + useLocation = true, + useEnvironment = true + ) + public Runtime.NoneType templateAction( + Artifact template, + Artifact output, + SkylarkDict substitutionsUnchecked, + Boolean executable, + Location loc, + Environment env) + throws EvalException { + checkDeprecated("ctx.actions.expand_template", "ctx.template_action", loc, env.getSemantics()); + checkMutable("template_action"); + actions().expandTemplate(template, output, substitutionsUnchecked, executable); + return Runtime.NONE; + } + + @SkylarkCallable( + name = "runfiles", + doc = "Creates a runfiles object.", + parameters = { + @Param( + name = "files", + type = SkylarkList.class, + generic1 = Artifact.class, + named = true, + defaultValue = "[]", + doc = "The list of files to be added to the runfiles." + ), + // TODO(bazel-team): If we have a memory efficient support for lazy list containing + // NestedSets we can remove this and just use files = [file] + list(set) + // Also, allow empty set for init + @Param( + name = "transitive_files", + type = SkylarkNestedSet.class, + generic1 = Artifact.class, + noneable = true, + defaultValue = "None", + named = true, + doc = + "The (transitive) set of files to be added to the runfiles. The depset should " + + "use the `default` order (which, as the name implies, is the default)." + ), + @Param( + name = "collect_data", + type = Boolean.class, + defaultValue = "False", + named = true, + doc = + "Whether to collect the data " + + "runfiles from the dependencies in srcs, data and deps attributes." + ), + @Param( + name = "collect_default", + type = Boolean.class, + defaultValue = "False", + named = true, + doc = + "Whether to collect the default " + + "runfiles from the dependencies in srcs, data and deps attributes." + ), + @Param( + name = "symlinks", + type = SkylarkDict.class, + defaultValue = "{}", + named = true, + doc = "The map of symlinks to be added to the runfiles, prefixed by workspace name." + ), + @Param( + name = "root_symlinks", + type = SkylarkDict.class, + defaultValue = "{}", + named = true, + doc = "The map of symlinks to be added to the runfiles." + ) + }, + useLocation = true + ) + public Runfiles runfiles( + SkylarkList files, + Object transitiveFiles, + Boolean collectData, + Boolean collectDefault, + SkylarkDict symlinks, + SkylarkDict rootSymlinks, + Location loc) + throws EvalException, ConversionException { + checkMutable("runfiles"); + Runfiles.Builder builder = + new Runfiles.Builder( + getRuleContext().getWorkspaceName(), getConfiguration().legacyExternalRunfiles()); + boolean checkConflicts = false; + if (EvalUtils.toBoolean(collectData)) { + builder.addRunfiles(getRuleContext(), RunfilesProvider.DATA_RUNFILES); + } + if (EvalUtils.toBoolean(collectDefault)) { + builder.addRunfiles(getRuleContext(), RunfilesProvider.DEFAULT_RUNFILES); + } + if (!files.isEmpty()) { + builder.addArtifacts(files.getContents(Artifact.class, "files")); + } + if (transitiveFiles != Runtime.NONE) { + builder.addTransitiveArtifacts(((SkylarkNestedSet) transitiveFiles).getSet(Artifact.class)); + } + if (!symlinks.isEmpty()) { + // If Skylark code directly manipulates symlinks, activate more stringent validity checking. + checkConflicts = true; + for (Map.Entry entry : + symlinks.getContents(String.class, Artifact.class, "symlinks").entrySet()) { + builder.addSymlink(PathFragment.create(entry.getKey()), entry.getValue()); + } + } + if (!rootSymlinks.isEmpty()) { + checkConflicts = true; + for (Map.Entry entry : + rootSymlinks.getContents(String.class, Artifact.class, "root_symlinks").entrySet()) { + builder.addRootSymlink(PathFragment.create(entry.getKey()), entry.getValue()); + } + } + Runfiles runfiles = builder.build(); + if (checkConflicts) { + runfiles.setConflictPolicy(Runfiles.ConflictPolicy.ERROR); + } + return runfiles; + } + + @SkylarkCallable( + name = "resolve_command", + // TODO(bazel-team): The naming here isn't entirely accurate (input_manifests is no longer + // manifests), but this is experimental/should be opaque to the end user. + doc = + "(Experimental) " + + "Returns a tuple (inputs, command, input_manifests) of the list of " + + "resolved inputs, the argv list for the resolved command, and the runfiles metadata" + + "required to run the command, all of them suitable for passing as the same-named " + + "arguments of the ctx.action method.", + parameters = { + @Param( + name = "command", + type = String.class, // string + defaultValue = "''", + named = true, + positional = false, + doc = "Command to resolve." + ), + @Param( + name = "attribute", + type = String.class, // string + defaultValue = "None", + noneable = true, + named = true, + positional = false, + doc = "Name of the associated attribute for which to issue an error, or None." + ), + @Param( + name = "expand_locations", + type = Boolean.class, + defaultValue = "False", + named = true, + positional = false, + doc = + "Shall we expand $(location) variables? " + + "See ctx.expand_location() for more details." + ), + @Param( + name = "make_variables", + type = SkylarkDict.class, // dict(string, string) + noneable = true, + defaultValue = "None", + named = true, + positional = false, + doc = "Make variables to expand, or None." + ), + @Param( + name = "tools", + defaultValue = "[]", + type = SkylarkList.class, + generic1 = TransitiveInfoCollection.class, + named = true, + positional = false, + doc = "List of tools (list of targets)." + ), + @Param( + name = "label_dict", + type = SkylarkDict.class, + defaultValue = "{}", + named = true, + positional = false, + doc = + "Dictionary of resolved labels and the corresponding list of Files " + + "(a dict of Label : list of Files)." + ), + @Param( + name = "execution_requirements", + type = SkylarkDict.class, + defaultValue = "{}", + named = true, + positional = false, + doc = + "Information for scheduling the action to resolve this command. See " + + "tags " + + "for useful keys." + ), + }, + useLocation = true, + useEnvironment = true + ) + public Tuple resolveCommand( + String command, + Object attributeUnchecked, + Boolean expandLocations, + Object makeVariablesUnchecked, + SkylarkList tools, + SkylarkDict labelDictUnchecked, + SkylarkDict executionRequirementsUnchecked, + Location loc, + Environment env) + throws ConversionException, EvalException { + checkMutable("resolve_command"); + Label ruleLabel = getLabel(); + Map> labelDict = checkLabelDict(labelDictUnchecked, loc, env); + // The best way to fix this probably is to convert CommandHelper to Skylark. + CommandHelper helper = + new CommandHelper( + getRuleContext(), + tools.getContents(TransitiveInfoCollection.class, "tools"), + ImmutableMap.copyOf(labelDict)); + String attribute = Type.STRING.convertOptional(attributeUnchecked, "attribute", ruleLabel); + if (expandLocations) { + command = + helper.resolveCommandAndExpandLabels(command, attribute, /*allowDataInLabel=*/ false); + } + if (!EvalUtils.isNullOrNone(makeVariablesUnchecked)) { + Map makeVariables = + Type.STRING_DICT.convert(makeVariablesUnchecked, "make_variables", ruleLabel); + command = expandMakeVariables(attribute, command, makeVariables); + } + List inputs = new ArrayList<>(); + inputs.addAll(helper.getResolvedTools()); + + ImmutableMap executionRequirements = + ImmutableMap.copyOf( + SkylarkDict.castSkylarkDictOrNoneToDict( + executionRequirementsUnchecked, + String.class, + String.class, + "execution_requirements")); + List argv = + helper.buildCommandLine(command, inputs, SCRIPT_SUFFIX, executionRequirements); + return Tuple.of( + MutableList.copyOf(env, inputs), + MutableList.copyOf(env, argv), + helper.getToolsRunfilesSuppliers()); + } + + /** + * Ensures the given {@link Map} has keys that have {@link Label} type and values that have either + * {@link Iterable} or {@link SkylarkNestedSet} type, and raises {@link EvalException} otherwise. + * Returns a corresponding map where any sets are replaced by iterables. + */ + // TODO(bazel-team): find a better way to typecheck this argument. + @SuppressWarnings("unchecked") + private static Map> checkLabelDict( + Map labelDict, Location loc, Environment env) throws EvalException { + Map> convertedMap = new HashMap<>(); + for (Map.Entry entry : labelDict.entrySet()) { + Object key = entry.getKey(); + if (!(key instanceof Label)) { + throw new EvalException(loc, Printer.format("invalid key %r in 'label_dict'", key)); + } + ImmutableList.Builder files = ImmutableList.builder(); + Object val = entry.getValue(); + Iterable valIter; + try { + valIter = EvalUtils.toIterableStrict(val, loc, env); + } catch (EvalException ex) { + // EvalException is thrown only if the type is wrong. + throw new EvalException( + loc, Printer.format("invalid value %r in 'label_dict': " + ex, val)); + } + for (Object file : valIter) { + if (!(file instanceof Artifact)) { + throw new EvalException(loc, Printer.format("invalid value %r in 'label_dict'", val)); + } + files.add((Artifact) file); + } + convertedMap.put((Label) key, files.build()); + } + return convertedMap; + } + + /** suffix of script to be used in case the command is too long to fit on a single line */ + private static final String SCRIPT_SUFFIX = ".script.sh"; + + private static void checkDeprecated( + String newApi, String oldApi, Location loc, SkylarkSemantics semantics) throws EvalException { + if (semantics.incompatibleNewActionsApi()) { + throw new EvalException( + loc, + "Use " + + newApi + + " instead of " + + oldApi + + ". \n" + + "Use --incompatible_new_actions_api=false to temporarily disable this check."); + } + } + + /** + * Builds a map: Label -> List of files from the given labels + * + * @param knownLabels List of known labels + * @return Immutable map with immutable collections as values + */ + private static ImmutableMap> makeLabelMap( + Iterable knownLabels) { + ImmutableMap.Builder> builder = ImmutableMap.builder(); + + for (TransitiveInfoCollection current : knownLabels) { + builder.put( + AliasProvider.getDependencyLabel(current), + ImmutableList.copyOf(current.getProvider(FileProvider.class).getFilesToBuild())); + } + + return builder.build(); + } } -- cgit v1.2.3