| // Copyright 2014 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.analysis; |
| |
| import static com.google.common.base.Preconditions.checkArgument; |
| |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; |
| import com.google.devtools.build.lib.collect.nestedset.Order; |
| import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; |
| import com.google.devtools.build.lib.starlarkbuildapi.FilesToRunProviderApi; |
| import javax.annotation.Nullable; |
| |
| /** Returns information about executables produced by a target and the files needed to run it. */ |
| @Immutable |
| public class FilesToRunProvider implements TransitiveInfoProvider, FilesToRunProviderApi<Artifact> { |
| |
| /** The name of the field in Starlark used to access a {@link FilesToRunProvider}. */ |
| public static final String STARLARK_NAME = "files_to_run"; |
| |
| public static final FilesToRunProvider EMPTY = |
| new FilesToRunProvider(NestedSetBuilder.emptySet(Order.STABLE_ORDER)); |
| |
| public static FilesToRunProvider create( |
| NestedSet<Artifact> filesToRun, |
| @Nullable RunfilesSupport runfilesSupport, |
| @Nullable Artifact executable) { |
| if (filesToRun.isEmpty()) { |
| checkArgument(runfilesSupport == null, "No files to run with runfiles: %s", runfilesSupport); |
| checkArgument(executable == null, "No files to run with executable: %s", executable); |
| return EMPTY; |
| } |
| if (runfilesSupport == null && executable == null) { |
| return new FilesToRunProvider(filesToRun); |
| } |
| if (filesToRun.isSingleton() |
| && runfilesSupport == null |
| && filesToRun.getSingleton().equals(executable)) { |
| return new SingleExecutableFilesToRunProvider(filesToRun); |
| } |
| return new FullFilesToRunProvider(filesToRun, runfilesSupport, executable); |
| } |
| |
| private final NestedSet<Artifact> filesToRun; |
| |
| private FilesToRunProvider(NestedSet<Artifact> filesToRun) { |
| this.filesToRun = filesToRun; |
| } |
| |
| @Override |
| public final boolean isImmutable() { |
| return true; // immutable and Starlark-hashable |
| } |
| |
| /** |
| * Returns artifacts needed to run the executable for this target. |
| * |
| * <p>This method should not be used because its semantics are complicated and confusing. Instead, |
| * either use {@link #getExecutable()} or {@link #getRunfilesSupport()} if you know what you are |
| * doing and it's something very arcane. |
| */ |
| @Deprecated |
| public final NestedSet<Artifact> getFilesToRun() { |
| return filesToRun; |
| } |
| |
| @Override |
| @Nullable |
| public Artifact getExecutable() { |
| return null; |
| } |
| |
| /** |
| * Returns the {@link RunfilesSupport} object associated with the target or null if it does not |
| * exist. |
| */ |
| @Nullable |
| public RunfilesSupport getRunfilesSupport() { |
| return null; |
| } |
| |
| @Override |
| @Nullable |
| public final Artifact getRunfilesManifest() { |
| var runfilesSupport = getRunfilesSupport(); |
| return runfilesSupport != null ? runfilesSupport.getRunfilesManifest() : null; |
| } |
| |
| @Nullable |
| @Override |
| public Artifact getRepoMappingManifest() { |
| var runfilesSupport = getRunfilesSupport(); |
| return runfilesSupport != null ? runfilesSupport.getRepoMappingManifest() : null; |
| } |
| |
| /** A single executable. */ |
| private static final class SingleExecutableFilesToRunProvider extends FilesToRunProvider { |
| |
| private SingleExecutableFilesToRunProvider(NestedSet<Artifact> filesToRun) { |
| super(filesToRun); |
| } |
| |
| @Override |
| public Artifact getExecutable() { |
| return getFilesToRun().getSingleton(); |
| } |
| } |
| |
| /** A {@link FilesToRunProvider} possible with {@link RunfilesSupport} and/or an executable. */ |
| private static final class FullFilesToRunProvider extends FilesToRunProvider { |
| @Nullable private final RunfilesSupport runfilesSupport; |
| @Nullable private final Artifact executable; |
| |
| private FullFilesToRunProvider( |
| NestedSet<Artifact> filesToRun, |
| @Nullable RunfilesSupport runfilesSupport, |
| @Nullable Artifact executable) { |
| super(filesToRun); |
| this.runfilesSupport = runfilesSupport; |
| this.executable = executable; |
| } |
| |
| @Override |
| @Nullable |
| public RunfilesSupport getRunfilesSupport() { |
| return runfilesSupport; |
| } |
| |
| @Override |
| @Nullable |
| public Artifact getExecutable() { |
| return executable; |
| } |
| } |
| } |