/** * Create a Rule Configured Target from the ruleContext and the ruleImplementation. The * registeredProviderTypes map indicates which keys in structs returned by skylark rules should be * interpreted as native TransitiveInfoProvider instances of type (map value). */ public static ConfiguredTarget buildRule( RuleContext ruleContext, BaseFunction ruleImplementation, Map<String, Class<? extends TransitiveInfoProvider>> registeredProviderTypes) throws InterruptedException { String expectFailure = ruleContext.attributes().get("expect_failure", Type.STRING); try (Mutability mutability = Mutability.create("configured target")) { SkylarkRuleContext skylarkRuleContext = new SkylarkRuleContext(ruleContext, Kind.RULE); Environment env = Environment.builder(mutability) .setSkylark() .setCallerLabel(ruleContext.getLabel()) .setGlobals( ruleContext .getRule() .getRuleClassObject() .getRuleDefinitionEnvironment() .getGlobals()) .setEventHandler(ruleContext.getAnalysisEnvironment().getEventHandler()) .build(); // NB: loading phase functions are not available: this is analysis already, // so we do *not* setLoadingPhase(). Object target = ruleImplementation.call( ImmutableList.<Object>of(skylarkRuleContext), ImmutableMap.<String, Object>of(), /*ast=*/ null, env); if (ruleContext.hasErrors()) { return null; } else if (!(target instanceof SkylarkClassObject) && target != Runtime.NONE && !(target instanceof Iterable)) { ruleContext.ruleError( String.format( "Rule should return a return a struct or a list, but got %s", SkylarkType.typeOf(target))); return null; } else if (!expectFailure.isEmpty()) { ruleContext.ruleError("Expected failure not found: " + expectFailure); return null; } ConfiguredTarget configuredTarget = createTarget(ruleContext, target, registeredProviderTypes); SkylarkProviderValidationUtil.checkOrphanArtifacts(ruleContext); return configuredTarget; } catch (EvalException e) { addRuleToStackTrace(e, ruleContext.getRule(), ruleImplementation); // If the error was expected, return an empty target. if (!expectFailure.isEmpty() && getMessageWithoutStackTrace(e).matches(expectFailure)) { return new com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder(ruleContext) .add(RunfilesProvider.class, RunfilesProvider.EMPTY) .build(); } ruleContext.ruleError("\n" + e.print()); return null; } }
/** Create a Rule Configured Target from the ruleContext and the ruleImplementation. */ public static ConfiguredTarget buildRule( RuleContext ruleContext, BaseFunction ruleImplementation) { String expectFailure = ruleContext.attributes().get("expect_failure", Type.STRING); try { SkylarkRuleContext skylarkRuleContext = new SkylarkRuleContext(ruleContext); SkylarkEnvironment env = ruleContext .getRule() .getRuleClassObject() .getRuleDefinitionEnvironment() .cloneEnv(ruleContext.getAnalysisEnvironment().getEventHandler()); // Collect the symbols to disable statically and pass at the next call, so we don't need to // clone the RuleDefinitionEnvironment. env.disableOnlyLoadingPhaseObjects(); Object target = ruleImplementation.call( ImmutableList.<Object>of(skylarkRuleContext), ImmutableMap.<String, Object>of(), null, env); if (ruleContext.hasErrors()) { return null; } else if (!(target instanceof SkylarkClassObject) && target != Environment.NONE) { ruleContext.ruleError("Rule implementation doesn't return a struct"); return null; } else if (!expectFailure.isEmpty()) { ruleContext.ruleError("Expected failure not found: " + expectFailure); return null; } ConfiguredTarget configuredTarget = createTarget(ruleContext, target); checkOrphanArtifacts(ruleContext); return configuredTarget; } catch (InterruptedException e) { ruleContext.ruleError(e.getMessage()); return null; } catch (EvalException e) { // If the error was expected, return an empty target. if (!expectFailure.isEmpty() && e.getMessage().matches(expectFailure)) { return new com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder(ruleContext) .add(RunfilesProvider.class, RunfilesProvider.EMPTY) .build(); } ruleContext.ruleError("\n" + e.print()); return null; } }
public JavaTargetAttributes init( JavaSemantics javaSemantics, AndroidSemantics androidSemantics, ResourceApk resourceApk, boolean addCoverageSupport, boolean collectJavaCompilationArgs) throws InterruptedException { classJar = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LIBRARY_CLASS_JAR); idlHelper = new AndroidIdlHelper(ruleContext, classJar); JavaTargetAttributes.Builder attributes = javaCommon .initCommon( idlHelper.getIdlGeneratedJavaSources(), androidSemantics.getJavacArguments()) .setBootClassPath( ImmutableList.of(AndroidSdkProvider.fromRuleContext(ruleContext).getAndroidJar())); JavaCompilationArtifacts.Builder artifactsBuilder = new JavaCompilationArtifacts.Builder(); ImmutableList.Builder<Artifact> jarsProducedForRuntime = ImmutableList.builder(); NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.<Artifact>stableOrder(); Artifact resourcesJar = resourceApk.getResourceJavaSrcJar(); if (resourcesJar != null) { filesBuilder.add(resourcesJar); compileResources( javaSemantics, resourcesJar, artifactsBuilder, attributes, filesBuilder, jarsProducedForRuntime); if (resourceApk.isLegacy()) { // Repackages the R.java for each dependency package and places the resultant jars before // the dependency libraries to ensure that the generated resource ids are correct. createJarJarActions( attributes, jarsProducedForRuntime, resourceApk.getResourceDependencies().getResources(), resourceApk.getPrimaryResource().getJavaPackage(), resourceClassJar); } } JavaCompilationHelper helper = initAttributes(attributes, javaSemantics); if (ruleContext.hasErrors()) { return null; } if (addCoverageSupport) { androidSemantics.addCoverageSupport( ruleContext, this, javaSemantics, true, attributes, artifactsBuilder); if (ruleContext.hasErrors()) { return null; } } jackCompilationHelper = initJack(helper.getAttributes()); if (ruleContext.hasErrors()) { return null; } initJava(helper, artifactsBuilder, collectJavaCompilationArgs, filesBuilder); if (ruleContext.hasErrors()) { return null; } this.jarsProducedForRuntime = jarsProducedForRuntime.add(classJar).build(); return helper.getAttributes(); }
private void initJava( JavaCompilationHelper helper, JavaCompilationArtifacts.Builder javaArtifactsBuilder, boolean collectJavaCompilationArgs, NestedSetBuilder<Artifact> filesBuilder) throws InterruptedException { JavaTargetAttributes attributes = helper.getAttributes(); if (ruleContext.hasErrors()) { // Avoid leaving filesToBuild set to null, otherwise we'll get a NullPointerException masking // the real error. filesToBuild = filesBuilder.build(); return; } Artifact jar = null; if (attributes.hasSourceFiles() || attributes.hasSourceJars() || attributes.hasResources()) { // We only want to add a jar to the classpath of a dependent rule if it has content. javaArtifactsBuilder.addRuntimeJar(classJar); jar = classJar; } filesBuilder.add(classJar); 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. if (helper.usesAnnotationProcessing()) { genClassJar = helper.createGenJar(classJar); genSourceJar = helper.createGensrcJar(classJar); helper.createGenJarAction(classJar, manifestProtoOutput, genClassJar); } srcJar = ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LIBRARY_SOURCE_JAR); helper.createSourceJarAction(srcJar, genSourceJar); outputDepsProto = helper.createOutputDepsProtoArtifact(classJar, javaArtifactsBuilder); helper.createCompileActionWithInstrumentation( classJar, manifestProtoOutput, genSourceJar, outputDepsProto, javaArtifactsBuilder); compileTimeDependencyArtifacts = javaCommon.collectCompileTimeDependencyArtifacts(outputDepsProto); filesToBuild = filesBuilder.build(); if ((attributes.hasSourceFiles() || attributes.hasSourceJars()) && jar != null) { iJar = helper.createCompileTimeJarAction(jar, javaArtifactsBuilder); } javaCommon.setJavaCompilationArtifacts(javaArtifactsBuilder.build()); javaCommon.setClassPathFragment( new ClasspathConfiguredFragment( javaCommon.getJavaCompilationArtifacts(), attributes, asNeverLink, helper.getBootclasspathOrDefault())); transitiveNeverlinkLibraries = collectTransitiveNeverlinkLibraries( ruleContext, javaCommon.getDependencies(), javaCommon.getJavaCompilationArtifacts().getRuntimeJars()); topLevelSourceJars = ImmutableList.of(srcJar); transitiveSourceJars = javaCommon.collectTransitiveSourceJars(srcJar); if (collectJavaCompilationArgs) { boolean hasSources = attributes.hasSourceFiles() || attributes.hasSourceJars(); this.javaCompilationArgs = collectJavaCompilationArgs(exportDeps, asNeverLink, hasSources); this.recursiveJavaCompilationArgs = collectJavaCompilationArgs(true, asNeverLink, /* hasSources */ true); } }
@Override public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException { ImmutableList<Artifact> srcJars = ImmutableList.of(); ImmutableList<Artifact> jars = collectJars(ruleContext); Artifact srcJar = ruleContext.getPrerequisiteArtifact("srcjar", Mode.TARGET); if (ruleContext.hasErrors()) { return null; } ImmutableList<TransitiveInfoCollection> targets = ImmutableList.<TransitiveInfoCollection>builder() .addAll(ruleContext.getPrerequisites("deps", Mode.TARGET)) .addAll(ruleContext.getPrerequisites("exports", Mode.TARGET)) .build(); final JavaCommon common = new JavaCommon(ruleContext, semantics, targets, targets, targets); semantics.checkRule(ruleContext, common); // No need for javac options - no compilation happening here. JavaCompilationHelper helper = new JavaCompilationHelper( ruleContext, semantics, ImmutableList.<String>of(), new JavaTargetAttributes.Builder(semantics)); ImmutableMap.Builder<Artifact, Artifact> compilationToRuntimeJarMap = ImmutableMap.builder(); ImmutableList<Artifact> interfaceJars = processWithIjar(jars, helper, compilationToRuntimeJarMap); common.setJavaCompilationArtifacts(collectJavaArtifacts(jars, interfaceJars)); CppCompilationContext transitiveCppDeps = common.collectTransitiveCppDeps(); NestedSet<LinkerInput> transitiveJavaNativeLibraries = common.collectTransitiveJavaNativeLibraries(); boolean neverLink = JavaCommon.isNeverLink(ruleContext); JavaCompilationArgs javaCompilationArgs = common.collectJavaCompilationArgs(false, neverLink, compilationArgsFromSources()); JavaCompilationArgs recursiveJavaCompilationArgs = common.collectJavaCompilationArgs(true, neverLink, compilationArgsFromSources()); NestedSet<Artifact> transitiveJavaSourceJars = collectTransitiveJavaSourceJars(ruleContext, srcJar); if (srcJar != null) { srcJars = ImmutableList.of(srcJar); } // The "neverlink" attribute is transitive, so if it is enabled, we don't add any // runfiles from this target or its dependencies. Runfiles runfiles = neverLink ? Runfiles.EMPTY : new Runfiles.Builder(ruleContext.getWorkspaceName()) // add the jars to the runfiles .addArtifacts(common.getJavaCompilationArtifacts().getRuntimeJars()) .addTargets(targets, RunfilesProvider.DEFAULT_RUNFILES) .addRunfiles(ruleContext, RunfilesProvider.DEFAULT_RUNFILES) .addTargets(targets, JavaRunfilesProvider.TO_RUNFILES) .add(ruleContext, JavaRunfilesProvider.TO_RUNFILES) .build(); CcLinkParamsStore ccLinkParamsStore = new CcLinkParamsStore() { @Override protected void collect( CcLinkParams.Builder builder, boolean linkingStatically, boolean linkShared) { builder.addTransitiveTargets( common.targetsTreatedAsDeps(ClasspathType.BOTH), JavaCcLinkParamsProvider.TO_LINK_PARAMS, CcLinkParamsProvider.TO_LINK_PARAMS); } }; RuleConfiguredTargetBuilder ruleBuilder = new RuleConfiguredTargetBuilder(ruleContext); NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder(); filesBuilder.addAll(jars); semantics.addProviders( ruleContext, common, ImmutableList.<String>of(), null /* classJar */, srcJar /* srcJar */, null /* genJar */, null /* gensrcJar */, compilationToRuntimeJarMap.build(), helper, filesBuilder, ruleBuilder); NestedSet<Artifact> filesToBuild = filesBuilder.build(); JavaSourceInfoProvider javaSourceInfoProvider = new JavaSourceInfoProvider.Builder() .setJarFiles(jars) .setSourceJarsForJarFiles(srcJars) .build(); NestedSet<Artifact> proguardSpecs = new ProguardLibrary(ruleContext).collectProguardSpecs(); common.addTransitiveInfoProviders(ruleBuilder, filesToBuild, null); return ruleBuilder .setFilesToBuild(filesToBuild) .add( JavaRuntimeJarProvider.class, new JavaRuntimeJarProvider(common.getJavaCompilationArtifacts().getRuntimeJars())) .addSkylarkTransitiveInfo(JavaSkylarkApiProvider.NAME, new JavaSkylarkApiProvider()) .add(JavaNeverlinkInfoProvider.class, new JavaNeverlinkInfoProvider(neverLink)) .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles)) .add(CcLinkParamsProvider.class, new CcLinkParamsProvider(ccLinkParamsStore)) .add( JavaCompilationArgsProvider.class, new JavaCompilationArgsProvider(javaCompilationArgs, recursiveJavaCompilationArgs)) .add( JavaNativeLibraryProvider.class, new JavaNativeLibraryProvider(transitiveJavaNativeLibraries)) .add(CppCompilationContext.class, transitiveCppDeps) .add(JavaSourceInfoProvider.class, javaSourceInfoProvider) .add( JavaSourceJarsProvider.class, new JavaSourceJarsProvider(transitiveJavaSourceJars, srcJars)) .add(ProguardSpecProvider.class, new ProguardSpecProvider(proguardSpecs)) .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveJavaSourceJars) .addOutputGroup(OutputGroupProvider.HIDDEN_TOP_LEVEL, proguardSpecs) .build(); }