/**
   * Generates an empty manifest for a rule that does not directly specify resources.
   *
   * <p><strong>Note:</strong> This generated manifest can then be used as the primary manifest when
   * merging with dependencies.
   *
   * @return the generated ApplicationManifest
   */
  public static ApplicationManifest generatedManifest(RuleContext ruleContext) {
    Artifact generatedManifest =
        ruleContext.getUniqueDirectoryArtifact(
            ruleContext.getRule().getName() + "_generated",
            new PathFragment("AndroidManifest.xml"),
            ruleContext.getBinOrGenfilesDirectory());

    String manifestPackage;
    if (ruleContext.attributes().isAttributeValueExplicitlySpecified("custom_package")) {
      manifestPackage = ruleContext.attributes().get("custom_package", Type.STRING);
    } else {
      manifestPackage =
          JavaUtil.getJavaFullClassname(ruleContext.getRule().getPackage().getNameFragment());
    }
    String contents =
        Joiner.on("\n")
            .join(
                "<?xml version=\"1.0\" encoding=\"utf-8\"?>",
                "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"",
                "          package=\"" + manifestPackage + "\">",
                "   <application>",
                "   </application>",
                "</manifest>");
    ruleContext
        .getAnalysisEnvironment()
        .registerAction(
            new FileWriteAction(
                ruleContext.getActionOwner(),
                generatedManifest,
                contents,
                false /* makeExecutable */));
    return new ApplicationManifest(generatedManifest);
  }
 private static void validateAssetsAndAssetsDir(RuleContext ruleContext)
     throws RuleErrorException {
   if (ruleContext.attributes().isAttributeValueExplicitlySpecified("assets")
       ^ ruleContext.attributes().isAttributeValueExplicitlySpecified("assets_dir")) {
     ruleContext.ruleError(
         "'assets' and 'assets_dir' should be either both empty or both non-empty");
     throw new RuleErrorException();
   }
 }
Exemple #3
0
 /** Returns whether the includes should include each of the proto generated headers. */
 boolean needsPerProtoIncludes() {
   if (ruleContext
       .attributes()
       .has(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN)) {
     return ruleContext
         .attributes()
         .get(ObjcProtoLibraryRule.PER_PROTO_INCLUDES_ATTR, Type.BOOLEAN);
   }
   return false;
 }
Exemple #4
0
 /** Returns whether the generated header files should have be of type pb.h or pbobjc.h. */
 boolean usesObjcHeaderNames() {
   if (ruleContext
       .attributes()
       .has(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN)) {
     return ruleContext
         .attributes()
         .get(ObjcProtoLibraryRule.USE_OBJC_HEADER_NAMES_ATTR, Type.BOOLEAN);
   }
   return false;
 }
Exemple #5
0
 public static String getJavaPackage(RuleContext ruleContext) {
   if (ruleContext.attributes().isAttributeValueExplicitlySpecified("custom_package")) {
     return ruleContext.attributes().get("custom_package", Type.STRING);
   } else {
     PathFragment nameFragment = ruleContext.getRule().getPackage().getNameFragment();
     String packageName = JavaUtil.getJavaFullClassname(nameFragment);
     if (packageName != null) {
       return packageName;
     } else {
       // This is a workaround for libraries that don't follow the standard Bazel package format
       return nameFragment.getPathString().replace('/', '.');
     }
   }
 }
  private Bundling bundling(
      RuleContext ruleContext,
      ObjcProvider objcProvider,
      String bundleDirFormat,
      String bundleName,
      DottedVersion minimumOsVersion) {
    ImmutableList<BundleableFile> extraBundleFiles;
    AppleConfiguration appleConfiguration = ruleContext.getFragment(AppleConfiguration.class);
    if (appleConfiguration.getBundlingPlatform() == Platform.IOS_DEVICE) {
      extraBundleFiles =
          ImmutableList.of(
              new BundleableFile(
                  new Attributes(ruleContext).provisioningProfile(),
                  PROVISIONING_PROFILE_BUNDLE_FILE));
    } else {
      extraBundleFiles = ImmutableList.of();
    }

    String primaryBundleId = null;
    String fallbackBundleId = null;

    if (ruleContext.attributes().isAttributeValueExplicitlySpecified("bundle_id")) {
      primaryBundleId = ruleContext.attributes().get("bundle_id", Type.STRING);
    } else {
      fallbackBundleId = ruleContext.attributes().get("bundle_id", Type.STRING);
    }

    Bundling.Builder bundling =
        new Builder()
            .setName(bundleName)
            // Architecture that determines which nested bundles are kept.
            .setArchitecture(appleConfiguration.getDependencySingleArchitecture())
            .setBundleDirFormat(bundleDirFormat)
            .addExtraBundleFiles(extraBundleFiles)
            .setObjcProvider(objcProvider)
            .addInfoplistInputFromRule(ruleContext)
            .addInfoplistInput(getGeneratedVersionPlist())
            .addInfoplistInput(getGeneratedEnvironmentPlist())
            .setAutomaticEntriesInfoplistInput(getGeneratedAutomaticPlist())
            .setIntermediateArtifacts(ObjcRuleClasses.intermediateArtifacts(ruleContext))
            .setPrimaryBundleId(primaryBundleId)
            .setFallbackBundleId(fallbackBundleId)
            .setMinimumOsVersion(minimumOsVersion);

    if (ObjcRuleClasses.useLaunchStoryboard(ruleContext)) {
      bundling.addInfoplistInput(getLaunchStoryboardPlist());
    }

    return bundling.build();
  }
 private static Collection<Artifact> getTargetListAttribute(
     RuleContext ruleContext, String attributeName) {
   return (ruleContext.attributes().has(attributeName, BuildType.LABEL_LIST)
           && ruleContext.getAttributeMode(attributeName) == Mode.TARGET)
       ? ruleContext.getPrerequisiteArtifacts(attributeName, Mode.TARGET).list()
       : ImmutableList.<Artifact>of();
 }
Exemple #8
0
 public static PathFragment getAssetDir(RuleContext ruleContext) {
   return new PathFragment(
       ruleContext
           .attributes()
           .get(
               AndroidResourcesProvider.ResourceType.ASSETS.getAttribute() + "_dir", Type.STRING));
 }
Exemple #9
0
  /**
   * Returns the xcode version number corresponding to the {@code --xcode_version} flag, if there is
   * an available {@code xcode_version} target which recognizes the flag value as either an official
   * version or an alias. Returns null if no such target is found.
   */
  @Nullable
  private DottedVersion resolveExplicitlyDefinedVersion(RuleContext ruleContext) {
    AppleConfiguration configuration = ruleContext.getFragment(AppleConfiguration.class);
    Optional<DottedVersion> versionOverrideFlag = configuration.getXcodeVersionOverrideFlag();
    if (versionOverrideFlag.isPresent()) {
      // The version override flag is not necessarily an actual version - it may be a version
      // alias.
      DottedVersion explicitVerison =
          aliasesToVersionMap(ruleContext).get(versionOverrideFlag.get().toString());
      if (explicitVerison != null) {
        return explicitVerison;
      }
    } else { // No override specified. Use default.
      XcodeVersionProvider defaultProvider =
          ruleContext.getPrerequisite(
              XcodeConfigRule.DEFAULT_ATTR_NAME, Mode.TARGET, XcodeVersionProvider.class);

      if (defaultProvider != null) {
        return defaultProvider.getVersion();
      }
    }

    boolean requireDefinedVersions =
        ruleContext.attributes().get(XcodeConfigRule.REQUIRE_DEFINED_VERSIONS_ATTR_NAME, BOOLEAN);
    if (requireDefinedVersions) {
      ruleContext.ruleError(
          "xcode version config required an explicitly defined version, but none was available");
    }

    return null;
  }
Exemple #10
0
 /** Returns the options file, or null if it was not specified. */
 @Nullable
 Artifact getOptionsFile() {
   if (ruleContext.attributes().has(ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, LABEL)) {
     return ruleContext.getPrerequisiteArtifact(
         ObjcProtoLibraryRule.OPTIONS_FILE_ATTR, Mode.HOST);
   }
   return null;
 }
  /**
   * 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;
    }
  }
Exemple #12
0
 /** Returns the list of portable proto filters. */
 ImmutableList<Artifact> getPortableProtoFilters() {
   if (ruleContext
       .attributes()
       .has(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, LABEL_LIST)) {
     return ruleContext
         .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, Mode.HOST)
         .list();
   }
   return ImmutableList.of();
 }
  private String getOverridePackage(RuleContext ruleContext) {
    // It seems that we sometimes rename the app for God-knows-what reason. If that is the case,
    // pass this information to the stubifier script.
    if (ruleContext.attributes().isAttributeValueExplicitlySpecified("application_id")) {
      return ruleContext.attributes().get("application_id", Type.STRING);
    }

    TransitiveInfoCollection resourcesPrerequisite =
        ruleContext.getPrerequisite("resources", Mode.TARGET);
    if (resourcesPrerequisite != null) {
      ResourceContainer resourceContainer =
          Iterables.getOnlyElement(
              resourcesPrerequisite
                  .getProvider(AndroidResourcesProvider.class)
                  .getTransitiveAndroidResources());
      return resourceContainer.getRenameManifestPackage();
    } else {
      return null;
    }
  }
 /** Validates that there are no resources defined if there are resource attribute defined. */
 private static void validateNoResourcesAttribute(RuleContext ruleContext)
     throws RuleErrorException {
   if (ruleContext.attributes().isAttributeValueExplicitlySpecified("resources")) {
     ruleContext.attributeError(
         "resources",
         String.format(
             "resources cannot be set when any of %s are defined.",
             Joiner.on(", ").join(RESOURCES_ATTRIBUTES)));
     throw new RuleErrorException();
   }
 }
Exemple #15
0
  public static AndroidResourcesProvider getAndroidResources(RuleContext ruleContext) {
    if (!ruleContext.attributes().has("resources", BuildType.LABEL)) {
      return null;
    }

    TransitiveInfoCollection prerequisite = ruleContext.getPrerequisite("resources", Mode.TARGET);
    if (prerequisite == null) {
      return null;
    }

    return prerequisite.getProvider(AndroidResourcesProvider.class);
  }
    NestedSet<? extends Artifact> dependentLinkedBinaries() {
      if (ruleContext.attributes().getAttributeDefinition("binary") == null) {
        return NestedSetBuilder.emptySet(Order.STABLE_ORDER);
      }

      NestedSetBuilder<Artifact> linkedBinaries = NestedSetBuilder.stableOrder();
      for (ObjcProvider provider :
          ruleContext.getPrerequisites("binary", Mode.DONT_CHECK, ObjcProvider.class)) {
        linkedBinaries.addTransitive(provider.get(ObjcProvider.LINKED_BINARY));
      }

      return linkedBinaries.build();
    }
 private void validateLaunchScreen() {
   if (ruleContext.attributes().isAttributeValueExplicitlySpecified("launch_storyboard")) {
     DottedVersion minimumOs = ObjcRuleClasses.objcConfiguration(ruleContext).getMinimumOs();
     if (ObjcRuleClasses.useLaunchStoryboard(ruleContext)) {
       if (ruleContext.attributes().isAttributeValueExplicitlySpecified("launch_image")) {
         ruleContext.attributeWarning(
             "launch_image",
             String.format(
                 "launch_image was specified but since --ios_minimum_os=%s (>=8.0), the also "
                     + "specified launch_storyboard will be used instead",
                 minimumOs));
       }
     } else {
       if (!ruleContext.attributes().isAttributeValueExplicitlySpecified("launch_image")) {
         ruleContext.attributeWarning(
             "launch_storyboard",
             String.format(
                 "launch_storyboard was specified but since --ios_minimum_os=%s (<8.0) and no "
                     + "launch_image was specified instead it will be ignored",
                 minimumOs));
       }
     }
   }
 }
  /** 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;
    }
  }
  /**
   * Validity-checks this rule's constraint-related attributes. Returns true if all is good, returns
   * false and reports appropriate errors if there are any problems.
   */
  private static boolean validateAttributes(RuleContext ruleContext) {
    AttributeMap attributes = ruleContext.attributes();

    // Report an error if "restricted to" is explicitly set to nothing. Even if this made
    // conceptual sense, we don't know which groups we should apply that to.
    String restrictionAttr = RuleClass.RESTRICTED_ENVIRONMENT_ATTR;
    List<? extends TransitiveInfoCollection> restrictionEnvironments =
        ruleContext.getPrerequisites(restrictionAttr, RuleConfiguredTarget.Mode.DONT_CHECK);
    if (restrictionEnvironments.isEmpty()
        && attributes.isAttributeValueExplicitlySpecified(restrictionAttr)) {
      ruleContext.attributeError(restrictionAttr, "attribute cannot be empty");
      return false;
    }

    return true;
  }
  /** Returns all dependencies that should be constraint-checked against the current rule. */
  private static Iterable<TransitiveInfoCollection> getConstraintCheckedDependencies(
      RuleContext ruleContext) {
    Set<TransitiveInfoCollection> depsToCheck = new LinkedHashSet<>();
    AttributeMap attributes = ruleContext.attributes();

    for (String attr : attributes.getAttributeNames()) {
      Attribute attrDef = attributes.getAttributeDefinition(attr);
      Type<?> attrType = attributes.getAttributeType(attr);

      // TODO(bazel-team): support a user-definable API for choosing which attributes are checked
      if (!attrDef.checkConstraintsOverride()) {
        if ((attrType != BuildType.LABEL && attrType != BuildType.LABEL_LIST)
            || RuleClass.isConstraintAttribute(attr)
            || attr.equals("visibility")
            // Use the same implicit deps check that query uses. This facilitates running queries to
            // determine exactly which rules need to be constraint-annotated for depot migrations.
            || !Rule.NO_IMPLICIT_DEPS.apply(ruleContext.getRule(), attrDef)
            // We can't identify host deps by calling BuildConfiguration.isHostConfiguration()
            // because --nodistinct_host_configuration subverts that call.
            || attrDef.getConfigurationTransition() == Attribute.ConfigurationTransition.HOST) {
          continue;
        }
      }

      for (TransitiveInfoCollection dep :
          ruleContext.getPrerequisites(attr, RuleConfiguredTarget.Mode.DONT_CHECK)) {
        // Output files inherit the environment spec of their generating rule.
        if (dep instanceof OutputFileConfiguredTarget) {
          // Note this reassignment means constraint violation errors reference the generating
          // rule, not the file. This makes the source of the environmental mismatch more clear.
          dep = ((OutputFileConfiguredTarget) dep).getGeneratingRule();
        }
        // Input files don't support environments. We may subsequently opt them into constraint
        // checking, but for now just pass them by.
        if (dep.getProvider(SupportedEnvironmentsProvider.class) != null) {
          depsToCheck.add(dep);
        }
      }
    }

    return depsToCheck;
  }
 ImmutableMap<String, Artifact> cpuSpecificBreakpadFiles() {
   ImmutableMap.Builder<String, Artifact> results = ImmutableMap.builder();
   if (ruleContext.attributes().has("binary", BuildType.LABEL)) {
     for (TransitiveInfoCollection prerequisite :
         ruleContext.getPrerequisites("binary", Mode.DONT_CHECK)) {
       ObjcProvider prerequisiteProvider = prerequisite.getProvider(ObjcProvider.class);
       if (prerequisiteProvider != null) {
         Artifact sourceBreakpad =
             Iterables.getOnlyElement(
                 prerequisiteProvider.get(ObjcProvider.BREAKPAD_FILE), null);
         if (sourceBreakpad != null) {
           String cpu =
               prerequisite.getConfiguration().getFragment(ObjcConfiguration.class).getIosCpu();
           results.put(cpu, sourceBreakpad);
         }
       }
     }
   }
   return results.build();
 }
Exemple #22
0
  public static AndroidIdeInfoProvider createAndroidIdeInfoProvider(
      RuleContext ruleContext,
      AndroidSemantics semantics,
      AndroidIdlHelper idlHelper,
      OutputJar resourceJar,
      ResourceApk resourceApk,
      Artifact zipAlignedApk,
      Iterable<Artifact> apksUnderTest) {
    AndroidIdeInfoProvider.Builder ideInfoProviderBuilder =
        new AndroidIdeInfoProvider.Builder()
            .setIdlClassJar(idlHelper.getIdlClassJar())
            .setIdlSourceJar(idlHelper.getIdlSourceJar())
            .setResourceJar(resourceJar)
            .addIdlParcelables(idlHelper.getIdlParcelables())
            .addIdlSrcs(idlHelper.getIdlSources())
            .addIdlGeneratedJavaFiles(idlHelper.getIdlGeneratedJavaSources())
            .addAllApksUnderTest(apksUnderTest);

    if (zipAlignedApk != null) {
      ideInfoProviderBuilder.setApk(zipAlignedApk);
    }

    // If the rule defines resources, put those in the IDE info. Otherwise, proxy the data coming
    // from the android_resources rule in its direct dependencies, if such a thing exists.
    if (LocalResourceContainer.definesAndroidResources(ruleContext.attributes())) {
      ideInfoProviderBuilder
          .setDefinesAndroidResources(true)
          .addResourceSources(resourceApk.getPrimaryResource().getArtifacts(ResourceType.RESOURCES))
          .addAssetSources(
              resourceApk.getPrimaryResource().getArtifacts(ResourceType.ASSETS),
              getAssetDir(ruleContext))
          // Sets the possibly merged manifest and the raw manifest.
          .setGeneratedManifest(resourceApk.getPrimaryResource().getManifest())
          .setManifest(ruleContext.getPrerequisiteArtifact("manifest", Mode.TARGET))
          .setJavaPackage(getJavaPackage(ruleContext));
    } else {
      semantics.addNonLocalResources(ruleContext, resourceApk, ideInfoProviderBuilder);
    }

    return ideInfoProviderBuilder.build();
  }
Exemple #23
0
  @Override
  public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
    ObjcCommon common =
        common(
            ruleContext,
            ImmutableList.<SdkFramework>of(),
            ruleContext.attributes().get("alwayslink", Type.BOOLEAN),
            new ExtraImportLibraries(),
            ImmutableList.<ObjcProvider>of());

    XcodeProvider.Builder xcodeProviderBuilder = new XcodeProvider.Builder();
    NestedSetBuilder<Artifact> filesToBuild =
        NestedSetBuilder.<Artifact>stableOrder().addAll(common.getCompiledArchive().asSet());

    new CompilationSupport(ruleContext)
        .registerCompileAndArchiveActions(common)
        .addXcodeSettings(xcodeProviderBuilder, common)
        .validateAttributes();

    new ResourceSupport(ruleContext).validateAttributes().addXcodeSettings(xcodeProviderBuilder);

    new XcodeSupport(ruleContext)
        .addFilesToBuild(filesToBuild)
        .addXcodeSettings(xcodeProviderBuilder, common.getObjcProvider(), LIBRARY_STATIC)
        .addDependencies(xcodeProviderBuilder, new Attribute("bundles", Mode.TARGET))
        .addDependencies(xcodeProviderBuilder, new Attribute("deps", Mode.TARGET))
        .addNonPropagatedDependencies(
            xcodeProviderBuilder, new Attribute("non_propagated_deps", Mode.TARGET))
        .registerActions(xcodeProviderBuilder.build());

    return ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build())
        .addProvider(XcodeProvider.class, xcodeProviderBuilder.build())
        .addProvider(ObjcProvider.class, common.getObjcProvider())
        .addProvider(J2ObjcSrcsProvider.class, J2ObjcSrcsProvider.buildFrom(ruleContext))
        .addProvider(
            J2ObjcMappingFileProvider.class, ObjcRuleClasses.j2ObjcMappingFileProvider(ruleContext))
        .build();
  }
Exemple #24
0
  @Override
  public ConfiguredTarget create(RuleContext ruleContext)
      throws RuleErrorException, InterruptedException {
    TransitiveInfoCollection lipoContextCollector =
        ruleContext.getPrerequisite(":lipo_context_collector", Mode.DONT_CHECK);
    if (lipoContextCollector != null
        && lipoContextCollector.getProvider(LipoContextProvider.class) == null) {
      ruleContext.ruleError("--lipo_context must point to a cc_binary or a cc_test rule");
      return null;
    }

    CppConfiguration cppConfiguration =
        Preconditions.checkNotNull(ruleContext.getFragment(CppConfiguration.class));
    Path fdoZip =
        ruleContext.getConfiguration().getCompilationMode() == CompilationMode.OPT
            ? cppConfiguration.getFdoZip()
            : null;
    SkyKey fdoKey =
        FdoSupportValue.key(
            cppConfiguration.getLipoMode(), fdoZip, cppConfiguration.getFdoInstrument());

    SkyFunction.Environment skyframeEnv = ruleContext.getAnalysisEnvironment().getSkyframeEnv();
    FdoSupportValue fdoSupport;
    try {
      fdoSupport =
          (FdoSupportValue)
              skyframeEnv.getValueOrThrow(fdoKey, FdoException.class, IOException.class);
    } catch (FdoException | IOException e) {
      ruleContext.ruleError("cannot initialize FDO: " + e.getMessage());
      return null;
    }

    if (skyframeEnv.valuesMissing()) {
      return null;
    }

    final Label label = ruleContext.getLabel();
    final NestedSet<Artifact> crosstool =
        ruleContext
            .getPrerequisite("all_files", Mode.HOST)
            .getProvider(FileProvider.class)
            .getFilesToBuild();
    final NestedSet<Artifact> crosstoolMiddleman = getFiles(ruleContext, "all_files");
    final NestedSet<Artifact> compile = getFiles(ruleContext, "compiler_files");
    final NestedSet<Artifact> strip = getFiles(ruleContext, "strip_files");
    final NestedSet<Artifact> objcopy = getFiles(ruleContext, "objcopy_files");
    final NestedSet<Artifact> link = getFiles(ruleContext, "linker_files");
    final NestedSet<Artifact> dwp = getFiles(ruleContext, "dwp_files");
    final NestedSet<Artifact> libcLink = inputsForLibc(ruleContext);
    String purposePrefix = Actions.escapeLabel(label) + "_";
    String runtimeSolibDirBase = "_solib_" + "_" + Actions.escapeLabel(label);
    final PathFragment runtimeSolibDir =
        ruleContext.getConfiguration().getBinFragment().getRelative(runtimeSolibDirBase);

    // Static runtime inputs.
    TransitiveInfoCollection staticRuntimeLibDep =
        selectDep(ruleContext, "static_runtime_libs", cppConfiguration.getStaticRuntimeLibsLabel());
    final NestedSet<Artifact> staticRuntimeLinkInputs;
    final Artifact staticRuntimeLinkMiddleman;
    if (cppConfiguration.supportsEmbeddedRuntimes()) {
      staticRuntimeLinkInputs =
          staticRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild();
    } else {
      staticRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }

    if (!staticRuntimeLinkInputs.isEmpty()) {
      NestedSet<Artifact> staticRuntimeLinkMiddlemanSet =
          CompilationHelper.getAggregatingMiddleman(
              ruleContext, purposePrefix + "static_runtime_link", staticRuntimeLibDep);
      staticRuntimeLinkMiddleman =
          staticRuntimeLinkMiddlemanSet.isEmpty()
              ? null
              : Iterables.getOnlyElement(staticRuntimeLinkMiddlemanSet);
    } else {
      staticRuntimeLinkMiddleman = null;
    }

    Preconditions.checkState(
        (staticRuntimeLinkMiddleman == null) == staticRuntimeLinkInputs.isEmpty());

    // Dynamic runtime inputs.
    TransitiveInfoCollection dynamicRuntimeLibDep =
        selectDep(
            ruleContext, "dynamic_runtime_libs", cppConfiguration.getDynamicRuntimeLibsLabel());
    final NestedSet<Artifact> dynamicRuntimeLinkInputs;
    final Artifact dynamicRuntimeLinkMiddleman;
    if (cppConfiguration.supportsEmbeddedRuntimes()) {
      NestedSetBuilder<Artifact> dynamicRuntimeLinkInputsBuilder = NestedSetBuilder.stableOrder();
      for (Artifact artifact :
          dynamicRuntimeLibDep.getProvider(FileProvider.class).getFilesToBuild()) {
        if (CppHelper.SHARED_LIBRARY_FILETYPES.matches(artifact.getFilename())) {
          dynamicRuntimeLinkInputsBuilder.add(
              SolibSymlinkAction.getCppRuntimeSymlink(
                  ruleContext, artifact, runtimeSolibDirBase, ruleContext.getConfiguration()));
        } else {
          dynamicRuntimeLinkInputsBuilder.add(artifact);
        }
      }
      dynamicRuntimeLinkInputs = dynamicRuntimeLinkInputsBuilder.build();
    } else {
      dynamicRuntimeLinkInputs = NestedSetBuilder.emptySet(Order.STABLE_ORDER);
    }

    if (!dynamicRuntimeLinkInputs.isEmpty()) {
      List<Artifact> dynamicRuntimeLinkMiddlemanSet =
          CppHelper.getAggregatingMiddlemanForCppRuntimes(
              ruleContext,
              purposePrefix + "dynamic_runtime_link",
              dynamicRuntimeLibDep,
              runtimeSolibDirBase,
              ruleContext.getConfiguration());
      dynamicRuntimeLinkMiddleman =
          dynamicRuntimeLinkMiddlemanSet.isEmpty()
              ? null
              : Iterables.getOnlyElement(dynamicRuntimeLinkMiddlemanSet);
    } else {
      dynamicRuntimeLinkMiddleman = null;
    }

    Preconditions.checkState(
        (dynamicRuntimeLinkMiddleman == null) == dynamicRuntimeLinkInputs.isEmpty());

    CppCompilationContext.Builder contextBuilder = new CppCompilationContext.Builder(ruleContext);
    CppModuleMap moduleMap = createCrosstoolModuleMap(ruleContext);
    if (moduleMap != null) {
      contextBuilder.setCppModuleMap(moduleMap);
    }
    final CppCompilationContext context = contextBuilder.build();
    boolean supportsParamFiles = ruleContext.attributes().get("supports_param_files", BOOLEAN);
    boolean supportsHeaderParsing =
        ruleContext.attributes().get("supports_header_parsing", BOOLEAN);

    NestedSetBuilder<Pair<String, String>> coverageEnvironment = NestedSetBuilder.compileOrder();

    coverageEnvironment.add(
        Pair.of("COVERAGE_GCOV_PATH", cppConfiguration.getGcovExecutable().getPathString()));
    if (cppConfiguration.getFdoInstrument() != null) {
      coverageEnvironment.add(
          Pair.of("FDO_DIR", cppConfiguration.getFdoInstrument().getPathString()));
    }

    CcToolchainProvider provider =
        new CcToolchainProvider(
            cppConfiguration,
            crosstool,
            fullInputsForCrosstool(ruleContext, crosstoolMiddleman),
            compile,
            strip,
            objcopy,
            fullInputsForLink(ruleContext, link),
            dwp,
            libcLink,
            staticRuntimeLinkInputs,
            staticRuntimeLinkMiddleman,
            dynamicRuntimeLinkInputs,
            dynamicRuntimeLinkMiddleman,
            runtimeSolibDir,
            context,
            supportsParamFiles,
            supportsHeaderParsing,
            getBuildVariables(ruleContext),
            getBuiltinIncludes(ruleContext),
            coverageEnvironment.build());
    RuleConfiguredTargetBuilder builder =
        new RuleConfiguredTargetBuilder(ruleContext)
            .add(CcToolchainProvider.class, provider)
            .add(FdoSupportProvider.class, new FdoSupportProvider(fdoSupport.getFdoSupport()))
            .setFilesToBuild(new NestedSetBuilder<Artifact>(Order.STABLE_ORDER).build())
            .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));

    // If output_license is specified on the cc_toolchain rule, override the transitive licenses
    // with that one. This is necessary because cc_toolchain is used in the target configuration,
    // but it is sort-of-kind-of a tool, but various parts of it are linked into the output...
    // ...so we trust the judgment of the author of the cc_toolchain rule to figure out what
    // licenses should be propagated to C++ targets.
    License outputLicense = ruleContext.getRule().getToolOutputLicense(ruleContext.attributes());
    if (outputLicense != null && outputLicense != License.NO_LICENSE) {
      final NestedSet<TargetLicense> license =
          NestedSetBuilder.create(
              Order.STABLE_ORDER, new TargetLicense(ruleContext.getLabel(), outputLicense));
      LicensesProvider licensesProvider =
          new LicensesProvider() {
            @Override
            public NestedSet<TargetLicense> getTransitiveLicenses() {
              return license;
            }
          };

      builder.add(LicensesProvider.class, licensesProvider);
    }

    return builder.build();
  }
 private static Collection<String> getStringListAttribute(
     RuleContext ruleContext, String attributeName) {
   return ruleContext.attributes().has(attributeName, Type.STRING_LIST)
       ? ruleContext.attributes().get(attributeName, Type.STRING_LIST)
       : ImmutableList.<String>of();
 }
Exemple #26
0
 /** Returns whether to use the protobuf library instead of the PB2 library. */
 boolean hasPortableProtoFilters() {
   return ruleContext
       .attributes()
       .isAttributeValueExplicitlySpecified(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR);
 }
Exemple #27
0
 /** Returns whether the generated files should be C++ or Objective C. */
 boolean outputsCpp() {
   if (ruleContext.attributes().has(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN)) {
     return ruleContext.attributes().get(ObjcProtoLibraryRule.OUTPUT_CPP_ATTR, Type.BOOLEAN);
   }
   return false;
 }
 @Nullable
 private String stringAttribute(String attribute) {
   String value = ruleContext.attributes().get(attribute, Type.STRING);
   return value.isEmpty() ? null : value;
 }
Exemple #29
0
 private List<String> iosDeviceArgs() {
   return ruleContext.attributes().get("ios_device_arg", Type.STRING_LIST);
 }
Exemple #30
0
 protected static boolean isXcTest(RuleContext ruleContext) {
   return ruleContext.attributes().get(IS_XCTEST_ATTR, Type.BOOLEAN);
 }