use of com.google.devtools.build.lib.analysis.RunfilesProvider in project bazel by bazelbuild.
the class JavaBinary method create.
@Override
public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException, RuleErrorException {
final JavaCommon common = new JavaCommon(ruleContext, semantics);
DeployArchiveBuilder deployArchiveBuilder = new DeployArchiveBuilder(semantics, ruleContext);
Runfiles.Builder runfilesBuilder = new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles());
List<String> jvmFlags = new ArrayList<>();
JavaTargetAttributes.Builder attributesBuilder = common.initCommon();
attributesBuilder.addClassPathResources(ruleContext.getPrerequisiteArtifacts("classpath_resources", Mode.TARGET).list());
// Add Java8 timezone resource data
addTimezoneResourceForJavaBinaries(ruleContext, attributesBuilder);
List<String> userJvmFlags = JavaCommon.getJvmFlags(ruleContext);
ruleContext.checkSrcsSamePackage(true);
boolean createExecutable = ruleContext.attributes().get("create_executable", Type.BOOLEAN);
if (!createExecutable) {
// TODO(cushon): disallow combining launcher=JDK_LAUNCHER_LABEL with create_executable=0
// and use isAttributeExplicitlySpecified here
Label launcherAttribute = ruleContext.attributes().get("launcher", BuildType.LABEL);
if (launcherAttribute != null && !JavaHelper.isJdkLauncher(ruleContext, launcherAttribute)) {
ruleContext.ruleError("launcher specified but create_executable is false");
}
}
semantics.checkRule(ruleContext, common);
semantics.checkForProtoLibraryAndJavaProtoLibraryOnSameProto(ruleContext, common);
String mainClass = semantics.getMainClass(ruleContext, common.getSrcsArtifacts());
String originalMainClass = mainClass;
if (ruleContext.hasErrors()) {
return null;
}
// Collect the transitive dependencies.
JavaCompilationHelper helper = new JavaCompilationHelper(ruleContext, semantics, common.getJavacOpts(), attributesBuilder);
List<TransitiveInfoCollection> deps = // Do not remove <TransitiveInfoCollection>: workaround for Java 7 type inference.
Lists.<TransitiveInfoCollection>newArrayList(common.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
helper.addLibrariesToAttributes(deps);
attributesBuilder.addNativeLibraries(collectNativeLibraries(common.targetsTreatedAsDeps(ClasspathType.BOTH)));
// deploy_env is valid for java_binary, but not for java_test.
if (ruleContext.getRule().isAttrDefined("deploy_env", BuildType.LABEL_LIST)) {
for (JavaRuntimeClasspathProvider envTarget : ruleContext.getPrerequisites("deploy_env", Mode.TARGET, JavaRuntimeClasspathProvider.class)) {
attributesBuilder.addExcludedArtifacts(envTarget.getRuntimeClasspath());
}
}
Artifact srcJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_SOURCE_JAR);
JavaSourceJarsProvider.Builder javaSourceJarsProviderBuilder = JavaSourceJarsProvider.builder().addSourceJar(srcJar).addAllTransitiveSourceJars(common.collectTransitiveSourceJars(srcJar));
Artifact classJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_CLASS_JAR);
JavaRuleOutputJarsProvider.Builder ruleOutputJarsProviderBuilder = JavaRuleOutputJarsProvider.builder().addOutputJar(classJar, null, /* iJar */
ImmutableList.of(srcJar));
CppConfiguration cppConfiguration = ruleContext.getConfiguration().getFragment(CppConfiguration.class);
boolean stripAsDefault = cppConfiguration.useFission() && cppConfiguration.getCompilationMode() == CompilationMode.OPT;
Artifact launcher = semantics.getLauncher(ruleContext, common, deployArchiveBuilder, runfilesBuilder, jvmFlags, attributesBuilder, stripAsDefault);
DeployArchiveBuilder unstrippedDeployArchiveBuilder = null;
Artifact unstrippedLauncher = null;
if (stripAsDefault) {
unstrippedDeployArchiveBuilder = new DeployArchiveBuilder(semantics, ruleContext);
unstrippedLauncher = semantics.getLauncher(ruleContext, common, unstrippedDeployArchiveBuilder, runfilesBuilder, jvmFlags, attributesBuilder, false);
}
JavaCompilationArtifacts.Builder javaArtifactsBuilder = new JavaCompilationArtifacts.Builder();
Artifact instrumentationMetadata = helper.createInstrumentationMetadata(classJar, javaArtifactsBuilder);
NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
Artifact executableForRunfiles = null;
if (createExecutable) {
// This artifact is named as the rule itself, e.g. //foo:bar_bin -> bazel-bin/foo/bar_bin
executableForRunfiles = ruleContext.createOutputArtifact();
filesBuilder.add(classJar).add(executableForRunfiles);
if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
mainClass = semantics.addCoverageSupport(helper, attributesBuilder, executableForRunfiles, instrumentationMetadata, javaArtifactsBuilder, mainClass);
}
} else {
filesBuilder.add(classJar);
}
JavaTargetAttributes attributes = helper.getAttributes();
List<Artifact> nativeLibraries = attributes.getNativeLibraries();
if (!nativeLibraries.isEmpty()) {
jvmFlags.add("-Djava.library.path=" + JavaCommon.javaLibraryPath(nativeLibraries, ruleContext.getRule().getPackage().getWorkspaceName()));
}
JavaConfiguration javaConfig = ruleContext.getFragment(JavaConfiguration.class);
if (attributes.hasMessages()) {
helper.setTranslations(semantics.translate(ruleContext, javaConfig, attributes.getMessages()));
}
if (attributes.hasSourceFiles() || attributes.hasSourceJars() || attributes.hasResources() || attributes.hasClassPathResources()) {
// We only want to add a jar to the classpath of a dependent rule if it has content.
javaArtifactsBuilder.addRuntimeJar(classJar);
}
GeneratedExtensionRegistryProvider generatedExtensionRegistryProvider = semantics.createGeneratedExtensionRegistry(ruleContext, common, filesBuilder, javaArtifactsBuilder, ruleOutputJarsProviderBuilder, javaSourceJarsProviderBuilder);
Artifact outputDepsProto = helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder);
ruleOutputJarsProviderBuilder.setJdeps(outputDepsProto);
JavaCompilationArtifacts javaArtifacts = javaArtifactsBuilder.build();
common.setJavaCompilationArtifacts(javaArtifacts);
Artifact manifestProtoOutput = helper.createManifestProtoOutput(classJar);
// The gensrc jar is created only if the target uses annotation processing. Otherwise,
// it is null, and the source jar action will not depend on the compile action.
Artifact genSourceJar = null;
Artifact genClassJar = null;
if (helper.usesAnnotationProcessing()) {
genClassJar = helper.createGenJar(classJar);
genSourceJar = helper.createGensrcJar(classJar);
helper.createGenJarAction(classJar, manifestProtoOutput, genClassJar);
}
helper.createCompileAction(classJar, manifestProtoOutput, genSourceJar, outputDepsProto, instrumentationMetadata);
helper.createSourceJarAction(srcJar, genSourceJar);
common.setClassPathFragment(new ClasspathConfiguredFragment(javaArtifacts, attributes, false, helper.getBootclasspathOrDefault()));
// Collect the action inputs for the runfiles collector here because we need to access the
// analysis environment, and that may no longer be safe when the runfiles collector runs.
Iterable<Artifact> dynamicRuntimeActionInputs = CppHelper.getToolchain(ruleContext, ":cc_toolchain").getDynamicRuntimeLinkInputs();
Iterables.addAll(jvmFlags, semantics.getJvmFlags(ruleContext, common.getSrcsArtifacts(), userJvmFlags));
if (ruleContext.hasErrors()) {
return null;
}
Artifact executableToRun = executableForRunfiles;
if (createExecutable) {
// Create a shell stub for a Java application
executableToRun = semantics.createStubAction(ruleContext, common, jvmFlags, executableForRunfiles, mainClass, JavaCommon.getJavaBinSubstitution(ruleContext, launcher));
if (!executableToRun.equals(executableForRunfiles)) {
filesBuilder.add(executableToRun);
runfilesBuilder.addArtifact(executableToRun);
}
}
JavaSourceJarsProvider sourceJarsProvider = javaSourceJarsProviderBuilder.build();
NestedSet<Artifact> transitiveSourceJars = sourceJarsProvider.getTransitiveSourceJars();
// TODO(bazel-team): if (getOptions().sourceJars) then make this a dummy prerequisite for the
// DeployArchiveAction ? Needs a few changes there as we can't pass inputs
SingleJarActionBuilder.createSourceJarAction(ruleContext, ImmutableMap.<PathFragment, Artifact>of(), transitiveSourceJars.toCollection(), ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_DEPLOY_SOURCE_JAR));
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
builder.add(JavaPrimaryClassProvider.class, new JavaPrimaryClassProvider(semantics.getPrimaryClass(ruleContext, common.getSrcsArtifacts())));
semantics.addProviders(ruleContext, common, jvmFlags, classJar, srcJar, genClassJar, genSourceJar, ImmutableMap.<Artifact, Artifact>of(), filesBuilder, builder);
if (generatedExtensionRegistryProvider != null) {
builder.add(GeneratedExtensionRegistryProvider.class, generatedExtensionRegistryProvider);
}
Artifact deployJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_DEPLOY_JAR);
boolean runProguard = applyProguardIfRequested(ruleContext, deployJar, common.getBootClasspath(), mainClass, semantics, filesBuilder);
if (javaConfig.isEnforceOneVersion()) {
Artifact oneVersionOutput = ruleContext.getAnalysisEnvironment().getDerivedArtifact(replaceExtension(classJar.getRootRelativePath(), "-one-version.txt"), classJar.getRoot());
filesBuilder.add(oneVersionOutput);
NestedSet<Artifact> transitiveDependencies = NestedSetBuilder.fromNestedSet(attributes.getRuntimeClassPath()).add(classJar).build();
OneVersionCheckActionBuilder.build(ruleContext, transitiveDependencies, oneVersionOutput);
}
NestedSet<Artifact> filesToBuild = filesBuilder.build();
// Need not include normal runtime classpath in runfiles if Proguard is used because _deploy.jar
// is used as classpath instead. Keeping runfiles unchanged has however the advantage that
// manually running executable without --singlejar works (although it won't depend on Proguard).
collectDefaultRunfiles(runfilesBuilder, ruleContext, common, javaArtifacts, filesToBuild, launcher, dynamicRuntimeActionInputs);
Runfiles defaultRunfiles = runfilesBuilder.build();
RunfilesSupport runfilesSupport = null;
if (createExecutable) {
List<String> extraArgs = new ArrayList<>(semantics.getExtraArguments(ruleContext, common.getSrcsArtifacts()));
if (runProguard) {
// Instead of changing the classpath written into the wrapper script, pass --singlejar when
// running the script (which causes the deploy.jar written by Proguard to be used instead of
// the normal classpath). It's a bit odd to do this b/c manually running the script wouldn't
// use Proguard's output unless --singlejar is explicitly supplied. On the other hand the
// behavior of the script is more consistent: the (proguarded) deploy.jar is only used with
// --singlejar. Moreover, people will almost always run tests using blaze test, which does
// use Proguard's output thanks to this extra arg when enabled. Also, it's actually hard to
// get the classpath changed in the wrapper script (would require calling
// JavaCommon.setClasspathFragment with a new fragment at the *end* of this method because
// the classpath is evaluated lazily when generating the wrapper script) and the wrapper
// script would essentially have an if (--singlejar was set), set classpath to deploy jar,
// otherwise, set classpath to deploy jar.
extraArgs.add("--wrapper_script_flag=--singlejar");
}
// The executable we pass here will be used when creating the runfiles directory. E.g. for the
// stub script called bazel-bin/foo/bar_bin, the runfiles directory will be created under
// bazel-bin/foo/bar_bin.runfiles . On platforms where there's an extra stub script (Windows)
// which dispatches to this one, we still create the runfiles directory for the shell script,
// but use the dispatcher script (a batch file) as the RunfilesProvider's executable.
runfilesSupport = RunfilesSupport.withExecutable(ruleContext, defaultRunfiles, executableForRunfiles, extraArgs);
}
RunfilesProvider runfilesProvider = RunfilesProvider.withData(defaultRunfiles, new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).merge(runfilesSupport).build());
ImmutableList<String> deployManifestLines = getDeployManifestLines(ruleContext, originalMainClass);
// When running Proguard:
// (1) write single jar to intermediate destination; Proguard will write _deploy.jar file
// (2) Don't depend on runfiles to avoid circular dependency, since _deploy.jar is itself part
// of runfiles when Proguard runs (because executable then needs it) and _deploy.jar depends
// on this single jar.
// (3) Don't bother with compression since Proguard will write the final jar anyways
deployArchiveBuilder.setOutputJar(runProguard ? ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_BINARY_MERGED_JAR) : deployJar).setJavaStartClass(mainClass).setDeployManifestLines(deployManifestLines).setAttributes(attributes).addRuntimeJars(javaArtifacts.getRuntimeJars()).setIncludeBuildData(true).setRunfilesMiddleman(runProguard || runfilesSupport == null ? null : runfilesSupport.getRunfilesMiddleman()).setCompression(runProguard ? UNCOMPRESSED : COMPRESSED).setLauncher(launcher).build();
Artifact unstrippedDeployJar = ruleContext.getImplicitOutputArtifact(JavaSemantics.JAVA_UNSTRIPPED_BINARY_DEPLOY_JAR);
if (stripAsDefault) {
unstrippedDeployArchiveBuilder.setOutputJar(unstrippedDeployJar).setJavaStartClass(mainClass).setDeployManifestLines(deployManifestLines).setAttributes(attributes).addRuntimeJars(javaArtifacts.getRuntimeJars()).setIncludeBuildData(true).setRunfilesMiddleman(runfilesSupport == null ? null : runfilesSupport.getRunfilesMiddleman()).setCompression(COMPRESSED).setLauncher(unstrippedLauncher);
unstrippedDeployArchiveBuilder.build();
} else {
// Write an empty file as the name_deploy.jar.unstripped when the default output jar is not
// stripped.
ruleContext.registerAction(FileWriteAction.create(ruleContext, unstrippedDeployJar, "", false));
}
JavaRuleOutputJarsProvider ruleOutputJarsProvider = ruleOutputJarsProviderBuilder.build();
JavaSkylarkApiProvider.Builder skylarkApiProvider = JavaSkylarkApiProvider.builder().setRuleOutputJarsProvider(ruleOutputJarsProvider).setSourceJarsProvider(sourceJarsProvider);
common.addTransitiveInfoProviders(builder, skylarkApiProvider, filesToBuild, classJar);
common.addGenJarsProvider(builder, skylarkApiProvider, genClassJar, genSourceJar);
return builder.setFilesToBuild(filesToBuild).addSkylarkTransitiveInfo(JavaSkylarkApiProvider.NAME, skylarkApiProvider.build()).add(JavaRuleOutputJarsProvider.class, ruleOutputJarsProvider).add(RunfilesProvider.class, runfilesProvider).setRunfilesSupport(runfilesSupport, executableToRun).add(JavaRuntimeClasspathProvider.class, new JavaRuntimeClasspathProvider(common.getRuntimeClasspath())).add(JavaSourceInfoProvider.class, JavaSourceInfoProvider.fromJavaTargetAttributes(attributes, semantics)).add(JavaSourceJarsProvider.class, sourceJarsProvider).addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars).build();
}
use of com.google.devtools.build.lib.analysis.RunfilesProvider in project bazel by bazelbuild.
the class PyBinary method init.
static RuleConfiguredTargetBuilder init(RuleContext ruleContext, PythonSemantics semantics, PyCommon common) throws InterruptedException {
CcLinkParamsStore ccLinkParamsStore = initializeCcLinkParamStore(ruleContext);
List<Artifact> srcs = common.validateSrcs();
List<Artifact> allOutputs = new ArrayList<>(semantics.precompiledPythonFiles(ruleContext, srcs, common));
if (ruleContext.hasErrors()) {
return null;
}
common.initBinary(allOutputs);
semantics.validate(ruleContext, common);
if (ruleContext.hasErrors()) {
return null;
}
NestedSet<PathFragment> imports = common.collectImports(ruleContext, semantics);
if (ruleContext.hasErrors()) {
return null;
}
semantics.createExecutable(ruleContext, common, ccLinkParamsStore, imports);
Runfiles commonRunfiles = collectCommonRunfiles(ruleContext, common, semantics);
Runfiles.Builder defaultRunfilesBuilder = new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).merge(commonRunfiles);
semantics.collectDefaultRunfilesForBinary(ruleContext, defaultRunfilesBuilder);
Runfiles defaultRunfiles = defaultRunfilesBuilder.build();
RunfilesSupport runfilesSupport = RunfilesSupport.withExecutable(ruleContext, defaultRunfiles, common.getExecutable(), ruleContext.shouldCreateRunfilesSymlinks());
if (ruleContext.hasErrors()) {
return null;
}
// Only include common runfiles and middleman. Default runfiles added by semantics are
// excluded. The middleman is necessary to ensure the runfiles trees are generated for all
// dependency binaries.
Runfiles dataRunfiles = new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).merge(commonRunfiles).addArtifact(runfilesSupport.getRunfilesMiddleman()).build();
RunfilesProvider runfilesProvider = RunfilesProvider.withData(defaultRunfiles, dataRunfiles);
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext);
common.addCommonTransitiveInfoProviders(builder, semantics, common.getFilesToBuild());
semantics.postInitBinary(ruleContext, runfilesSupport, common);
return builder.setFilesToBuild(common.getFilesToBuild()).add(RunfilesProvider.class, runfilesProvider).setRunfilesSupport(runfilesSupport, common.getExecutable()).add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore)).add(PythonImportsProvider.class, new PythonImportsProvider(imports));
}
use of com.google.devtools.build.lib.analysis.RunfilesProvider in project bazel by bazelbuild.
the class SkylarkRuleConfiguredTargetBuilder method addSimpleProviders.
private static void addSimpleProviders(RuleConfiguredTargetBuilder builder, RuleContext ruleContext, Location loc, Artifact executable, Runfiles statelessRunfiles, Runfiles dataRunfiles, Runfiles defaultRunfiles, SkylarkClassObject defaultProvider) throws EvalException {
if ((statelessRunfiles != null) && (dataRunfiles != null || defaultRunfiles != null)) {
throw new EvalException(loc, "Cannot specify the provider 'runfiles' " + "together with 'data_runfiles' or 'default_runfiles'");
}
if (statelessRunfiles == null && dataRunfiles == null && defaultRunfiles == null) {
// No runfiles specified, set default
statelessRunfiles = Runfiles.EMPTY;
}
RunfilesProvider runfilesProvider = statelessRunfiles != null ? RunfilesProvider.simple(merge(statelessRunfiles, executable, ruleContext)) : RunfilesProvider.withData(// This is to keep skylark genrule consistent with the original genrule.
defaultRunfiles != null ? defaultRunfiles : Runfiles.EMPTY, dataRunfiles != null ? dataRunfiles : Runfiles.EMPTY);
builder.addProvider(RunfilesProvider.class, runfilesProvider);
Runfiles computedDefaultRunfiles = runfilesProvider.getDefaultRunfiles();
// This works because we only allowed to call a rule *_test iff it's a test type rule.
boolean testRule = TargetUtils.isTestRuleName(ruleContext.getRule().getRuleClass());
if (testRule && computedDefaultRunfiles.isEmpty()) {
throw new EvalException(loc, "Test rules have to define runfiles");
}
if (executable != null || testRule) {
RunfilesSupport runfilesSupport = computedDefaultRunfiles.isEmpty() ? null : RunfilesSupport.withExecutable(ruleContext, computedDefaultRunfiles, executable);
builder.setRunfilesSupport(runfilesSupport, executable);
}
if (ruleContext.getRule().getRuleClassObject().isSkylarkTestable()) {
SkylarkClassObject actions = ActionsProvider.create(ruleContext.getAnalysisEnvironment().getRegisteredActions());
builder.addSkylarkDeclaredProvider(actions, loc);
}
// Populate default provider fields and build it
ImmutableMap.Builder<String, Object> attrBuilder = new ImmutableMap.Builder<>();
// TODO: Add actual attributes that users expect to access from default providers
attrBuilder.put("runfiles", runfilesProvider);
SkylarkClassObject statelessDefaultProvider = new SkylarkClassObject(SkylarkRuleContext.getDefaultProvider(), attrBuilder.build());
// Add the default provider
builder.addSkylarkDeclaredProvider(statelessDefaultProvider, (defaultProvider == null) ? loc : Optional.fromNullable(defaultProvider.getCreationLocOrNull()).or(loc));
}
use of com.google.devtools.build.lib.analysis.RunfilesProvider in project bazel by bazelbuild.
the class Filegroup method create.
@Override
public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException {
String outputGroupName = ruleContext.attributes().get("output_group", Type.STRING);
if (outputGroupName.endsWith(INTERNAL_SUFFIX)) {
ruleContext.throwWithAttributeError("output_group", String.format(ILLEGAL_OUTPUT_GROUP_ERROR, outputGroupName));
}
NestedSet<Artifact> filesToBuild = outputGroupName.isEmpty() ? PrerequisiteArtifacts.nestedSet(ruleContext, "srcs", Mode.TARGET) : getArtifactsForOutputGroup(outputGroupName, ruleContext.getPrerequisites("srcs", Mode.TARGET));
NestedSet<Artifact> middleman = CompilationHelper.getAggregatingMiddleman(ruleContext, Actions.escapeLabel(ruleContext.getLabel()), filesToBuild);
InstrumentedFilesProvider instrumentedFilesProvider = InstrumentedFilesCollector.collect(ruleContext, // what do *we* know about whether this is a source file or not
new InstrumentationSpec(FileTypeSet.ANY_FILE, "srcs", "deps", "data"), InstrumentedFilesCollector.NO_METADATA_COLLECTOR, filesToBuild);
RunfilesProvider runfilesProvider = RunfilesProvider.withData(new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES).build(), // If you're visiting a filegroup as data, then we also visit its data as data.
new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).addTransitiveArtifacts(filesToBuild).addDataDeps(ruleContext).build());
return new RuleConfiguredTargetBuilder(ruleContext).add(RunfilesProvider.class, runfilesProvider).setFilesToBuild(filesToBuild).setRunfilesSupport(null, getExecutable(filesToBuild)).add(InstrumentedFilesProvider.class, instrumentedFilesProvider).add(MiddlemanProvider.class, new MiddlemanProvider(middleman)).add(FilegroupPathProvider.class, new FilegroupPathProvider(getFilegroupPath(ruleContext))).build();
}
use of com.google.devtools.build.lib.analysis.RunfilesProvider in project bazel by bazelbuild.
the class GenRuleBase method create.
@Override
public ConfiguredTarget create(RuleContext ruleContext) throws RuleErrorException, InterruptedException {
NestedSet<Artifact> filesToBuild = NestedSetBuilder.wrap(Order.STABLE_ORDER, ruleContext.getOutputArtifacts());
NestedSetBuilder<Artifact> resolvedSrcsBuilder = NestedSetBuilder.stableOrder();
if (filesToBuild.isEmpty()) {
ruleContext.attributeError("outs", "Genrules without outputs don't make sense");
}
if (ruleContext.attributes().get("executable", Type.BOOLEAN) && Iterables.size(filesToBuild) > 1) {
ruleContext.attributeError("executable", "if genrules produce executables, they are allowed only one output. " + "If you need the executable=1 argument, then you should split this genrule into " + "genrules producing single outputs");
}
ImmutableMap.Builder<Label, NestedSet<Artifact>> labelMap = ImmutableMap.builder();
for (TransitiveInfoCollection dep : ruleContext.getPrerequisites("srcs", Mode.TARGET)) {
// This target provides specific types of files for genrules.
GenRuleSourcesProvider provider = dep.getProvider(GenRuleSourcesProvider.class);
NestedSet<Artifact> files = (provider != null) ? provider.getGenruleFiles() : dep.getProvider(FileProvider.class).getFilesToBuild();
resolvedSrcsBuilder.addTransitive(files);
labelMap.put(AliasProvider.getDependencyLabel(dep), files);
}
NestedSet<Artifact> resolvedSrcs = resolvedSrcsBuilder.build();
CommandHelper commandHelper = new CommandHelper(ruleContext, ruleContext.getPrerequisites("tools", Mode.HOST), labelMap.build());
if (ruleContext.hasErrors()) {
return null;
}
String baseCommand = commandHelper.resolveCommandAndExpandLabels(ruleContext.attributes().get("heuristic_label_expansion", Type.BOOLEAN), false);
// Adds the genrule environment setup script before the actual shell command
String command = String.format("source %s; %s", ruleContext.getPrerequisiteArtifact("$genrule_setup", Mode.HOST).getExecPath(), baseCommand);
command = resolveCommand(command, ruleContext, resolvedSrcs, filesToBuild);
String message = ruleContext.attributes().get("message", Type.STRING);
if (message.isEmpty()) {
message = "Executing genrule";
}
ImmutableMap<String, String> env = ruleContext.getConfiguration().getLocalShellEnvironment();
ImmutableSet<String> clientEnvVars = ruleContext.getConfiguration().getVariableShellEnvironment();
Map<String, String> executionInfo = Maps.newLinkedHashMap();
executionInfo.putAll(TargetUtils.getExecutionInfo(ruleContext.getRule()));
if (ruleContext.attributes().get("local", Type.BOOLEAN)) {
executionInfo.put("local", "");
}
executionInfo.putAll(getExtraExecutionInfo(ruleContext, baseCommand));
NestedSetBuilder<Artifact> inputs = NestedSetBuilder.stableOrder();
inputs.addAll(resolvedSrcs);
inputs.addAll(commandHelper.getResolvedTools());
FilesToRunProvider genruleSetup = ruleContext.getPrerequisite("$genrule_setup", Mode.HOST, FilesToRunProvider.class);
inputs.addAll(genruleSetup.getFilesToRun());
List<String> argv = commandHelper.buildCommandLine(command, inputs, ".genrule_script.sh", ImmutableMap.copyOf(executionInfo));
// TODO(bazel-team): Make the make variable expander pass back a list of these.
if (requiresCrosstool(baseCommand)) {
// If cc is used, silently throw in the crosstool filegroup as a dependency.
inputs.addTransitive(CppHelper.getToolchain(ruleContext, ":cc_toolchain").getCrosstoolMiddleman());
}
if (requiresJdk(baseCommand)) {
// If javac is used, silently throw in the jdk filegroup as a dependency.
// Note we expand Java-related variables with the *host* configuration.
inputs.addTransitive(JavaHelper.getHostJavabaseInputs(ruleContext));
}
for (NestedSet<Artifact> extraInputs : getExtraInputArtifacts(ruleContext, baseCommand)) {
inputs.addTransitive(extraInputs);
}
if (isStampingEnabled(ruleContext)) {
inputs.add(ruleContext.getAnalysisEnvironment().getStableWorkspaceStatusArtifact());
inputs.add(ruleContext.getAnalysisEnvironment().getVolatileWorkspaceStatusArtifact());
}
ruleContext.registerAction(new GenRuleAction(ruleContext.getActionOwner(), ImmutableList.copyOf(commandHelper.getResolvedTools()), inputs.build(), filesToBuild, argv, env, clientEnvVars, ImmutableMap.copyOf(executionInfo), new CompositeRunfilesSupplier(commandHelper.getToolsRunfilesSuppliers()), message + ' ' + ruleContext.getLabel()));
RunfilesProvider runfilesProvider = RunfilesProvider.withData(// No runfiles provided if not a data dependency.
Runfiles.EMPTY, // configuration.
new Runfiles.Builder(ruleContext.getWorkspaceName(), ruleContext.getConfiguration().legacyExternalRunfiles()).addTransitiveArtifacts(filesToBuild).build());
RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(ruleContext).setFilesToBuild(filesToBuild).setRunfilesSupport(null, getExecutable(ruleContext, filesToBuild)).addProvider(RunfilesProvider.class, runfilesProvider);
builder = updateBuilder(builder, ruleContext, filesToBuild);
return builder.build();
}
Aggregations