/**
   * 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;
    }
  }
示例#3
0
  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();
  }
示例#4
0
  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);
    }
  }
示例#5
0
  @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();
  }