private void registerBundleMergeActions(
      Artifact ipaUnsigned,
      NestedSet<Artifact> bundleContentArtifacts,
      BundleMergeControlBytes controlBytes) {
    Artifact bundleMergeControlArtifact =
        ObjcRuleClasses.artifactByAppendingToBaseName(ruleContext, ".ipa-control");

    ruleContext.registerAction(
        new BinaryFileWriteAction(
            ruleContext.getActionOwner(),
            bundleMergeControlArtifact,
            controlBytes,
            /*makeExecutable=*/ false));

    ruleContext.registerAction(
        new SpawnAction.Builder()
            .setMnemonic("IosBundle")
            .setProgressMessage("Bundling iOS application: " + ruleContext.getLabel())
            .setExecutable(attributes.bundleMergeExecutable())
            .addInputArgument(bundleMergeControlArtifact)
            .addTransitiveInputs(bundleContentArtifacts)
            .addOutput(ipaUnsigned)
            .setVerboseFailuresAndSubcommandsInEnv()
            .build(ruleContext));
  }
Пример #2
0
 /** {@link CppModuleMap} that provides the clang module map for this target. */
 public CppModuleMap moduleMap() {
   String moduleName =
       ruleContext.getLabel().toString().replace("//", "").replace("/", "_").replace(":", "_");
   // To get Swift to pick up module maps, we need to name them "module.modulemap" and have their
   // parent directory in the module map search paths.
   return new CppModuleMap(appendExtensionInGenfiles(".modulemaps/module.modulemap"), moduleName);
 }
Пример #3
0
  /**
   * Returns the linked artifact resulting from a linking of the given type. Consults the feature
   * configuration to obtain an action_config that provides the artifact. If the feature
   * configuration provides no artifact, uses a default.
   *
   * <p>We cannot assume that the feature configuration contains an action_config for the link
   * action, because the linux link action depends on hardcoded values in
   * LinkCommandLine.getRawLinkArgv(), which are applied on the condition that an action_config is
   * not present. TODO(b/30393154): Assert that the given link action has an action_config.
   *
   * @throws RuleErrorException
   */
  private Artifact getLinkedArtifact(LinkTargetType linkTargetType) throws RuleErrorException {
    Artifact result = null;
    Artifact linuxDefault = CppHelper.getLinuxLinkedArtifact(ruleContext, linkTargetType);

    try {
      String templatedName =
          features.getArtifactNameForCategory(
              linkTargetType.getLinkerOutput(), ruleContext, ImmutableMap.<String, String>of());
      PathFragment artifactFragment =
          new PathFragment(ruleContext.getLabel().getName())
              .getParentDirectory()
              .getRelative(templatedName);
      result =
          ruleContext.getPackageRelativeArtifact(
              artifactFragment, ruleContext.getConfiguration().getBinDirectory());
    } catch (ExpansionException e) {
      ruleContext.throwWithRuleError(e.getMessage());
    }

    // If the linked artifact is not the linux default, then a FailAction is generated for the
    // linux default to satisfy the requirement of the implicit output.
    // TODO(b/30132703): Remove the implicit outputs of cc_library.
    if (!result.equals(linuxDefault)) {
      ruleContext.registerAction(
          new FailAction(
              ruleContext.getActionOwner(),
              ImmutableList.of(linuxDefault),
              String.format(
                  "the given toolchain supports creation of %s instead of %s",
                  linuxDefault.getExecPathString(), result.getExecPathString())));
    }

    return result;
  }
Пример #4
0
  /** Registers an action to generate a runner script based on a template. */
  ReleaseBundlingSupport registerGenerateRunnerScriptAction(
      Artifact runnerScript, Artifact ipaInput) {
    ObjcConfiguration objcConfiguration = ObjcRuleClasses.objcConfiguration(ruleContext);
    String escapedSimDevice = ShellUtils.shellEscape(objcConfiguration.getIosSimulatorDevice());
    String escapedSdkVersion = ShellUtils.shellEscape(objcConfiguration.getIosSimulatorVersion());
    ImmutableList<Substitution> substitutions =
        ImmutableList.of(
            Substitution.of("%app_name%", ruleContext.getLabel().getName()),
            Substitution.of("%ipa_file%", ipaInput.getRootRelativePath().getPathString()),
            Substitution.of("%sim_device%", escapedSimDevice),
            Substitution.of("%sdk_version%", escapedSdkVersion),
            Substitution.of("%iossim%", attributes.iossim().getRootRelativePath().getPathString()),
            Substitution.of(
                "%std_redirect_dylib_path%",
                attributes.stdRedirectDylib().getRootRelativePath().getPathString()));

    ruleContext.registerAction(
        new TemplateExpansionAction(
            ruleContext.getActionOwner(),
            attributes.runnerScriptTemplate(),
            runnerScript,
            substitutions,
            true));
    return this;
  }
Пример #5
0
    /**
     * Creates a middleman for the compilation prerequisites.
     *
     * @return the middleman or null if there are no prerequisites
     */
    private Artifact createMiddleman(ActionOwner owner, MiddlemanFactory middlemanFactory) {
      if (compilationPrerequisites.isEmpty()) {
        return null;
      }

      // Compilation prerequisites gathered in the compilationPrerequisites
      // must be generated prior to executing C++ compilation step that depends
      // on them (since these prerequisites include all potential header files, etc
      // that could be referenced during compilation). So there is a definite need
      // to ensure scheduling edge dependency. However, those prerequisites should
      // have no effect on the decision whether C++ compilation should happen in
      // the first place - only CppCompileAction outputs (*.o and *.d files) and
      // all files referenced by the *.d file should be used to make that decision.
      // If this action was never executed, then *.d file would be missing, forcing
      // compilation to occur. If *.d file is present and has not changed then the
      // only reason that would force us to re-compile would be change in one of
      // the files referenced by the *.d file, since no other files participated
      // in the compilation. We also need to propagate errors through this
      // dependency link. So we use an error propagating middleman.
      // Such middleman will be ignored by the dependency checker yet will still
      // represent an edge in the action dependency graph - forcing proper execution
      // order and error propagation.
      return middlemanFactory.createErrorPropagatingMiddleman(
          owner,
          ruleContext.getLabel().toString(),
          purpose,
          ImmutableList.copyOf(compilationPrerequisites),
          ruleContext
              .getConfiguration()
              .getMiddlemanDirectory(ruleContext.getRule().getRepository()));
    }
Пример #6
0
 private Artifact inUniqueObjsDir(Artifact source, String extension) {
   PathFragment uniqueDir =
       new PathFragment("_objs").getRelative(ruleContext.getLabel().getName());
   PathFragment sourceFile = uniqueDir.getRelative(source.getRootRelativePath());
   PathFragment scopeRelativePath = FileSystemUtils.replaceExtension(sourceFile, extension);
   return scopedArtifact(scopeRelativePath);
 }
 private static PathFragment getOutputFilePath(
     ConfiguredTarget base, RuleContext ruleContext, String suffix) {
   PathFragment packagePathFragment =
       ruleContext.getLabel().getPackageIdentifier().getPathFragment();
   String name = base.getLabel().getName();
   return new PathFragment(packagePathFragment, new PathFragment(name + suffix));
 }
  /**
   * 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;
    }
  }
Пример #9
0
  public RuleConfiguredTargetBuilder addTransitiveInfoProviders(
      RuleConfiguredTargetBuilder builder,
      AndroidSemantics androidSemantics,
      ResourceApk resourceApk,
      Artifact zipAlignedApk,
      Iterable<Artifact> apksUnderTest) {

    javaCommon.addTransitiveInfoProviders(builder, filesToBuild, classJar, ANDROID_COLLECTION_SPEC);
    javaCommon.addGenJarsProvider(builder, genClassJar, genSourceJar);
    idlHelper.addTransitiveInfoProviders(builder, classJar, manifestProtoOutput);

    JavaRuleOutputJarsProvider.Builder outputJarsBuilder =
        JavaRuleOutputJarsProvider.builder()
            .addOutputJar(classJar, iJar, srcJar)
            .setJdeps(outputDepsProto);
    OutputJar resourceJar = null;
    if (resourceClassJar != null && resourceIJar != null && resourceSourceJar != null) {
      resourceJar = new OutputJar(resourceClassJar, resourceIJar, resourceSourceJar);
      outputJarsBuilder.addOutputJar(resourceJar);
    }

    return builder
        .setFilesToBuild(filesToBuild)
        .add(JavaRuleOutputJarsProvider.class, outputJarsBuilder.build())
        .add(
            JavaRuntimeJarProvider.class,
            new JavaRuntimeJarProvider(javaCommon.getJavaCompilationArtifacts().getRuntimeJars()))
        .add(RunfilesProvider.class, RunfilesProvider.simple(getRunfiles()))
        .add(AndroidResourcesProvider.class, resourceApk.toResourceProvider(ruleContext.getLabel()))
        .add(
            AndroidIdeInfoProvider.class,
            createAndroidIdeInfoProvider(
                ruleContext,
                androidSemantics,
                idlHelper,
                resourceJar,
                resourceApk,
                zipAlignedApk,
                apksUnderTest))
        .add(
            JavaCompilationArgsProvider.class,
            new JavaCompilationArgsProvider(
                javaCompilationArgs,
                recursiveJavaCompilationArgs,
                compileTimeDependencyArtifacts,
                NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)))
        .add(
            JackLibraryProvider.class,
            asNeverLink
                ? jackCompilationHelper.compileAsNeverlinkLibrary()
                : jackCompilationHelper.compileAsLibrary())
        .addSkylarkTransitiveInfo(AndroidSkylarkApiProvider.NAME, new AndroidSkylarkApiProvider())
        .addOutputGroup(
            OutputGroupProvider.HIDDEN_TOP_LEVEL, collectHiddenTopLevelArtifacts(ruleContext))
        .addOutputGroup(JavaSemantics.SOURCE_JARS_OUTPUT_GROUP, transitiveSourceJars);
  }
Пример #10
0
 /**
  * Adds the given targets as dependencies - this can include explicit dependencies on other rules
  * (like from a "deps" attribute) and also implicit dependencies on runtime libraries.
  */
 public CcLibraryHelper addDeps(Iterable<? extends TransitiveInfoCollection> deps) {
   for (TransitiveInfoCollection dep : deps) {
     Preconditions.checkArgument(
         dep.getConfiguration() == null
             || configuration.equalsOrIsSupersetOf(dep.getConfiguration()),
         "dep " + dep.getLabel() + " has a different config than " + ruleContext.getLabel());
     this.deps.add(dep);
   }
   return this;
 }
Пример #11
0
    /**
     * Returns the same set of artifacts as createMiddleman() would, but without actually creating
     * middlemen.
     */
    private Artifact getMiddlemanArtifact(MiddlemanFactory middlemanFactory) {
      if (compilationPrerequisites.isEmpty()) {
        return null;
      }

      return middlemanFactory.getErrorPropagatingMiddlemanArtifact(
          ruleContext.getLabel().toString(),
          purpose,
          ruleContext
              .getConfiguration()
              .getMiddlemanDirectory(ruleContext.getRule().getRepository()));
    }
Пример #12
0
 @Override
 public ConfiguredAspect create(
     ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) {
   String information =
       parameters.isEmpty()
           ? ""
           : " data " + Iterables.getFirst(parameters.getAttribute("baz"), null);
   return new ConfiguredAspect.Builder(getClass().getName(), ruleContext)
       .addProvider(
           AspectInfo.class,
           new AspectInfo(
               collectAspectData("aspect " + ruleContext.getLabel() + information, ruleContext)))
       .build();
 }
Пример #13
0
 /**
  * Creates a new application support within the given rule context.
  *
  * <p>{@code bundleName} defaults to label name
  *
  * @param ruleContext context for the application-generating rule
  * @param objcProvider provider containing all dependencies' information as well as some of this
  *     rule's
  * @param linkedBinary whether to look for a linked binary from this rule and dependencies or just
  *     the latter
  * @param bundleDirFormat format string representing the bundle's directory with a single
  *     placeholder for the target name (e.g. {@code "Payload/%s.app"})
  * @param bundleMinimumOsVersion the minimum OS version this bundle's plist should be generated
  *     for (<b>not</b> the minimum OS version its binary is compiled with, that needs to be set
  *     through the configuration)
  */
 ReleaseBundlingSupport(
     RuleContext ruleContext,
     ObjcProvider objcProvider,
     LinkedBinary linkedBinary,
     String bundleDirFormat,
     String bundleMinimumOsVersion) {
   this(
       ruleContext,
       objcProvider,
       linkedBinary,
       bundleDirFormat,
       ruleContext.getLabel().getName(),
       bundleMinimumOsVersion);
 }
Пример #14
0
  private ReleaseBundlingSupport registerSignBundleAction(
      Artifact entitlements, Artifact ipaOutput, Artifact ipaUnsigned) {
    // TODO(bazel-team): Support variable substitution

    ImmutableList.Builder<String> dirsToSign = new ImmutableList.Builder<>();

    // Explicitly sign Swift dylibs. Unfortunately --deep option on codesign doesn't do this
    // automatically.
    // The order here is important. The innermost code must singed first.
    String bundleDir = ShellUtils.shellEscape(bundling.getBundleDir());
    if (objcProvider.is(USES_SWIFT)) {
      dirsToSign.add(bundleDir + "/Frameworks/*");
    }
    dirsToSign.add(bundleDir);

    StringBuilder codesignCommandLineBuilder = new StringBuilder();
    for (String dir : dirsToSign.build()) {
      codesignCommandLineBuilder
          .append(codesignCommand(entitlements, "${t}/" + dir))
          .append(" && ");
    }

    // TODO(bazel-team): Support nested code signing.
    String shellCommand =
        "set -e && "
            + "t=$(mktemp -d -t signing_intermediate) && "
            + "trap \"rm -rf ${t}\" EXIT && "
            // Get an absolute path since we need to cd into the temp directory for zip.
            + "signed_ipa=${PWD}/"
            + ipaOutput.getShellEscapedExecPathString()
            + " && "
            + "/usr/bin/unzip -qq "
            + ipaUnsigned.getShellEscapedExecPathString()
            + " -d ${t} && "
            + codesignCommandLineBuilder.toString()
            // Using zip since we need to preserve permissions
            + "cd ${t} && /usr/bin/zip -q -r \"${signed_ipa}\" .";
    ruleContext.registerAction(
        ObjcRuleClasses.spawnBashOnDarwinActionBuilder(ruleContext, shellCommand)
            .setMnemonic("IosSignBundle")
            .setProgressMessage("Signing iOS bundle: " + ruleContext.getLabel())
            .addInput(ipaUnsigned)
            .addInput(attributes.provisioningProfile())
            .addInput(entitlements)
            .addOutput(ipaOutput)
            .build(ruleContext));

    return this;
  }
Пример #15
0
 /**
  * Adds common xcode settings to the given provider builder, explicitly specifying architecture to
  * use.
  *
  * @param objcProvider provider containing all dependencies' information as well as some of this
  *     rule's
  * @param productType type of this rule's Xcode target
  * @param architecture architecture to filter all dependencies with (only matching ones will be
  *     included in the final targets generated)
  * @param configurationDistinguisher distinguisher that will cause this target's xcode provider to
  *     discard any dependencies from sources that are tagged with a different distinguisher
  * @return this xcode support
  */
 XcodeSupport addXcodeSettings(
     Builder xcodeProviderBuilder,
     ObjcProvider objcProvider,
     XcodeProductType productType,
     String architecture,
     ConfigurationDistinguisher configurationDistinguisher) {
   xcodeProviderBuilder
       .setLabel(ruleContext.getLabel())
       .setArchitecture(architecture)
       .setConfigurationDistinguisher(configurationDistinguisher)
       .setObjcProvider(objcProvider)
       .setProductType(productType)
       .addXcodeprojBuildSettings(XcodeSupport.defaultXcodeSettings());
   return this;
 }
Пример #16
0
  private void createFakeSourceAction(
      String outputName,
      CcCompilationOutputs.Builder result,
      AnalysisEnvironment env,
      CppCompileActionBuilder builder,
      ArtifactCategory outputCategory,
      boolean addObject,
      PathFragment ccRelativeName,
      PathFragment execPath,
      boolean usePic,
      boolean generateDotd) {
    String outputNameBase = getOutputNameBaseWith(outputName, usePic);
    String tempOutputName =
        ruleContext
            .getConfiguration()
            .getBinFragment()
            .getRelative(CppHelper.getObjDirectory(ruleContext.getLabel()))
            .getRelative(
                CppHelper.getCompileArtifactName(
                    ruleContext,
                    outputCategory,
                    getOutputNameBaseWith(outputName + ".temp", usePic)))
            .getPathString();
    builder
        .setPicMode(usePic)
        .setOutputs(outputCategory, outputNameBase, generateDotd)
        .setTempOutputFile(new PathFragment(tempOutputName));

    setupCompileBuildVariables(
        builder,
        usePic,
        ccRelativeName,
        execPath,
        /*gcnoFile=*/ null,
        /*dwoFile=*/ null,
        ImmutableMap.<String, String>of());
    semantics.finalizeCompileActionBuilder(ruleContext, builder);
    CppCompileAction action = builder.build();
    env.registerAction(action);
    if (addObject) {
      if (usePic) {
        result.addPicObjectFile(action.getOutputFile());
      } else {
        result.addObjectFile(action.getOutputFile());
      }
    }
  }
Пример #17
0
  private JavaCompilationHelper initAttributes(
      JavaTargetAttributes.Builder attributes, JavaSemantics semantics) {
    JavaCompilationHelper helper =
        new JavaCompilationHelper(ruleContext, semantics, javaCommon.getJavacOpts(), attributes);

    helper.addLibrariesToAttributes(javaCommon.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY));
    helper.addProvidersToAttributes(
        JavaCommon.compilationArgsFromSources(ruleContext), asNeverLink);
    attributes.setStrictJavaDeps(getStrictAndroidDeps());
    attributes.setRuleKind(ruleContext.getRule().getRuleClass());
    attributes.setTargetLabel(ruleContext.getLabel());

    JavaCommon.validateConstraint(
        ruleContext, "android", javaCommon.targetsTreatedAsDeps(ClasspathType.BOTH));
    ruleContext.checkSrcsSamePackage(true);
    return helper;
  }
Пример #18
0
  /** Returns the include paths for the generated protos. */
  public ImmutableSet<PathFragment> getUserHeaderSearchPaths() {
    PathFragment workspaceRelativeOutputDir = getWorkspaceRelativeOutputDir();

    ImmutableSet.Builder<PathFragment> searchPathEntriesBuilder =
        new ImmutableSet.Builder<PathFragment>().add(workspaceRelativeOutputDir);

    if (attributes.needsPerProtoIncludes()) {
      PathFragment generatedProtoDir =
          new PathFragment(workspaceRelativeOutputDir, ruleContext.getLabel().getPackageFragment());

      searchPathEntriesBuilder
          .add(generatedProtoDir)
          .addAll(Iterables.transform(getGeneratedHeaders(), PARENT_PATHFRAGMENT));
    }

    return searchPathEntriesBuilder.build();
  }
Пример #19
0
    @Override
    public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {

      RuleConfiguredTargetBuilder builder =
          new RuleConfiguredTargetBuilder(ruleContext)
              .addProvider(
                  RuleInfo.class,
                  new RuleInfo(collectAspectData("rule " + ruleContext.getLabel(), ruleContext)))
              .setFilesToBuild(NestedSetBuilder.<Artifact>create(Order.STABLE_ORDER))
              .setRunfilesSupport(null, null)
              .add(RunfilesProvider.class, RunfilesProvider.simple(Runfiles.EMPTY));

      if (ruleContext.getRule().getRuleClassObject().getName().equals("honest")) {
        builder.addProvider(RequiredProvider.class, new RequiredProvider());
      }

      return builder.build();
    }
Пример #20
0
 /**
  * Registers the actions that transform and copy the breakpad files from the CPU-specific binaries
  * that are part of this application. There are two steps involved: 1) The breakpad files have to
  * be renamed to include their corresponding CPU architecture as a suffix. 2) The first line of
  * the breakpad file has to be rewritten, as it has to include the name of the application instead
  * of the name of the binary artifact.
  *
  * <p>Example:<br>
  * The ios_application "PrenotCalculator" is specified to use "PrenotCalculatorBinary" as its
  * binary. Assuming that the application is built for armv7 and arm64 CPUs, in the build process
  * two binaries with a corresponding breakpad file each will be built:
  *
  * <pre>blaze-out/xyz-crosstool-ios-arm64/.../PrenotCalculatorBinary_bin
  * blaze-out/xyz-crosstool-ios-arm64/.../PrenotCalculatorBinary.breakpad
  * blaze-out/xyz-crosstool-ios-armv7/.../PrenotCalculatorBinary_bin
  * blaze-out/xyz-crosstool-ios-armv7/.../PrenotCalculatorBinary.breakpad</pre>
  *
  * <p>The first line of the breakpad files will look like this:
  *
  * <pre>MODULE mac arm64 8A7A2DDD28E83E27B339E63631ADBEF30 PrenotCalculatorBinary_bin</pre>
  *
  * <p>For our application, we have to transform & copy these breakpad files like this:
  *
  * <pre>$ head -n1 blaze-bin/.../PrenotCalculator_arm64.breakpad
  * MODULE mac arm64 8A7A2DDD28E83E27B339E63631ADBEF30 PrenotCalculator</pre>
  */
 private void registerTransformAndCopyBreakpadFilesAction() {
   for (Entry<Artifact, Artifact> breakpadFiles : getBreakpadFiles().entrySet()) {
     ruleContext.registerAction(
         new SpawnAction.Builder()
             .setMnemonic("CopyBreakpadFile")
             .setShellCommand(
                 String.format(
                     // This sed command replaces the last word of the first line with the
                     // application
                     // name.
                     "sed \"1 s/^\\(MODULE \\w* \\w* \\w*\\).*$/\\1 %s/\" < %s > %s",
                     ruleContext.getLabel().getName(),
                     breakpadFiles.getKey().getExecPathString(),
                     breakpadFiles.getValue().getExecPathString()))
             .addInput(breakpadFiles.getKey())
             .addOutput(breakpadFiles.getValue())
             .build(ruleContext));
   }
 }
Пример #21
0
  private void createJarJarActions(
      JavaTargetAttributes.Builder attributes,
      ImmutableList.Builder<Artifact> jarsProducedForRuntime,
      Iterable<ResourceContainer> resourceContainers,
      String originalPackage,
      Artifact binaryResourcesJar) {
    // Now use jarjar for the rest of the resources. We need to make a copy
    // of the final generated resources for each of the targets included in
    // the transitive closure of this binary.
    for (ResourceContainer otherContainer : resourceContainers) {
      if (otherContainer.getLabel().equals(ruleContext.getLabel())) {
        continue;
      }

      Artifact resourcesJar = createResourceJarArtifact(ruleContext, otherContainer, ".jar");
      // combined resource constants copy needs to come before library classes that may contain
      // their local resource constants
      attributes.addRuntimeClassPathEntry(resourcesJar);

      Artifact jarJarRuleFile =
          createResourceJarArtifact(ruleContext, otherContainer, ".jar_jarjar_rules.txt");

      String jarJarRule =
          String.format("rule %s.* %s.@1", originalPackage, otherContainer.getJavaPackage());
      ruleContext.registerAction(
          new FileWriteAction(ruleContext.getActionOwner(), jarJarRuleFile, jarJarRule, false));

      FilesToRunProvider jarjar = ruleContext.getExecutablePrerequisite("$jarjar_bin", Mode.HOST);

      ruleContext.registerAction(
          new SpawnAction.Builder()
              .setExecutable(jarjar)
              .addArgument("process")
              .addInputArgument(jarJarRuleFile)
              .addInputArgument(binaryResourcesJar)
              .addOutputArgument(resourcesJar)
              .setProgressMessage("Repackaging jar")
              .setMnemonic("AndroidRepackageJar")
              .build(ruleContext));
      jarsProducedForRuntime.add(resourcesJar);
    }
  }
Пример #22
0
 @Override
 public ConfiguredAspect create(
     ConfiguredTarget base, RuleContext ruleContext, AspectParameters parameters) {
   StringBuilder information = new StringBuilder("aspect " + ruleContext.getLabel());
   if (!parameters.isEmpty()) {
     information.append(" data " + Iterables.getFirst(parameters.getAttribute("baz"), null));
     information.append(" ");
   }
   List<? extends TransitiveInfoCollection> deps =
       ruleContext.getPrerequisites("$dep", Mode.TARGET);
   information.append("$dep:[");
   for (TransitiveInfoCollection dep : deps) {
     information.append(" ");
     information.append(dep.getLabel());
   }
   information.append("]");
   return new ConfiguredAspect.Builder(getClass().getName(), ruleContext)
       .addProvider(
           AspectInfo.class,
           new AspectInfo(collectAspectData(information.toString(), ruleContext)))
       .build();
 }
Пример #23
0
  private ReleaseBundlingSupport registerExtractEntitlementsAction(Artifact entitlements) {
    // See Apple Glossary (http://goo.gl/EkhXOb)
    // An Application Identifier is constructed as: TeamID.BundleID
    // TeamID is extracted from the provisioning profile.
    // BundleID consists of a reverse-DNS string to identify the app, where the last component
    // is the application name, and is specified as an attribute.
    String shellCommand =
        "set -e && "
            + "PLIST=$(mktemp -t entitlements.plist) && trap \"rm ${PLIST}\" EXIT && "
            + extractPlistCommand(attributes.provisioningProfile())
            + " > ${PLIST} && "
            + "/usr/libexec/PlistBuddy -x -c 'Print Entitlements' ${PLIST} > "
            + entitlements.getShellEscapedExecPathString();
    ruleContext.registerAction(
        ObjcRuleClasses.spawnBashOnDarwinActionBuilder(ruleContext, shellCommand)
            .setMnemonic("ExtractIosEntitlements")
            .setProgressMessage("Extracting entitlements: " + ruleContext.getLabel())
            .addInput(attributes.provisioningProfile())
            .addOutput(entitlements)
            .build(ruleContext));

    return this;
  }
Пример #24
0
 /**
  * Add the corresponding files as source files. These may also be header files, in which case they
  * will not be compiled, but also not made visible as includes to dependent rules.
  */
 public CcLibraryHelper addSources(Collection<Artifact> sources) {
   for (Artifact source : sources) {
     addSource(source, ruleContext.getLabel());
   }
   return this;
 }
Пример #25
0
 /** Debug symbol file generated for a linked binary, for a specific architecture. */
 public Artifact dsymSymbol(DsymOutputType dsymOutputType, String suffix) {
   return appendExtension(
       String.format(
           "%s/Contents/Resources/DWARF/%s_%s",
           dsymOutputType.getSuffix(), ruleContext.getLabel().getName(), suffix));
 }
Пример #26
0
 /** @return the pic header module artifact for the current target. */
 public Artifact getPicHeaderModule(Artifact moduleMapArtifact) {
   PathFragment objectDir = CppHelper.getObjDirectory(ruleContext.getLabel());
   PathFragment outputName =
       objectDir.getRelative(semantics.getEffectiveSourcePath(moduleMapArtifact));
   return ruleContext.getRelatedArtifact(outputName, ".pic.pcm");
 }
Пример #27
0
  /** Create context for cc compile action from generated inputs. */
  private CppCompilationContext initializeCppCompilationContext(CppModel model) {
    CppCompilationContext.Builder contextBuilder = new CppCompilationContext.Builder(ruleContext);

    // Setup the include path; local include directories come before those inherited from deps or
    // from the toolchain; in case of aliasing (same include file found on different entries),
    // prefer the local include rather than the inherited one.

    // Add in the roots for well-formed include names for source files and
    // generated files. It is important that the execRoot (EMPTY_FRAGMENT) comes
    // before the genfilesFragment to preferably pick up source files. Otherwise
    // we might pick up stale generated files.
    PathFragment repositoryPath =
        ruleContext.getLabel().getPackageIdentifier().getRepository().getPathFragment();
    contextBuilder.addQuoteIncludeDir(repositoryPath);
    contextBuilder.addQuoteIncludeDir(
        ruleContext.getConfiguration().getGenfilesFragment().getRelative(repositoryPath));

    for (PathFragment systemIncludeDir : systemIncludeDirs) {
      contextBuilder.addSystemIncludeDir(systemIncludeDir);
    }
    for (PathFragment includeDir : includeDirs) {
      contextBuilder.addIncludeDir(includeDir);
    }

    contextBuilder.mergeDependentContexts(
        AnalysisUtils.getProviders(deps, CppCompilationContext.class));
    CppHelper.mergeToolchainDependentContext(ruleContext, contextBuilder);

    // But defines come after those inherited from deps.
    contextBuilder.addDefines(defines);

    // There are no ordering constraints for declared include dirs/srcs, or the pregrepped headers.
    contextBuilder.addDeclaredIncludeSrcs(publicHeaders);
    contextBuilder.addDeclaredIncludeSrcs(publicTextualHeaders);
    contextBuilder.addDeclaredIncludeSrcs(privateHeaders);
    contextBuilder.addPregreppedHeaderMap(
        CppHelper.createExtractInclusions(ruleContext, semantics, publicHeaders));
    contextBuilder.addPregreppedHeaderMap(
        CppHelper.createExtractInclusions(ruleContext, semantics, publicTextualHeaders));
    contextBuilder.addPregreppedHeaderMap(
        CppHelper.createExtractInclusions(ruleContext, semantics, privateHeaders));
    contextBuilder.addCompilationPrerequisites(prerequisites);

    // Add this package's dir to declaredIncludeDirs, & this rule's headers to declaredIncludeSrcs
    // Note: no include dir for STRICT mode.
    if (headersCheckingMode == HeadersCheckingMode.WARN) {
      contextBuilder.addDeclaredIncludeWarnDir(ruleContext.getLabel().getPackageFragment());
      for (PathFragment looseIncludeDir : looseIncludeDirs) {
        contextBuilder.addDeclaredIncludeWarnDir(looseIncludeDir);
      }
    } else if (headersCheckingMode == HeadersCheckingMode.LOOSE) {
      contextBuilder.addDeclaredIncludeDir(ruleContext.getLabel().getPackageFragment());
      for (PathFragment looseIncludeDir : looseIncludeDirs) {
        contextBuilder.addDeclaredIncludeDir(looseIncludeDir);
      }
    }

    if (featureConfiguration.isEnabled(CppRuleClasses.MODULE_MAPS)) {
      CppModuleMap cppModuleMap = CppHelper.addCppModuleMapToContext(ruleContext, contextBuilder);
      // TODO(bazel-team): addCppModuleMapToContext second-guesses whether module maps should
      // actually be enabled, so we need to double-check here. Who would write code like this?
      if (cppModuleMap != null) {
        CppModuleMapAction action =
            new CppModuleMapAction(
                ruleContext.getActionOwner(),
                cppModuleMap,
                privateHeaders,
                publicHeaders,
                collectModuleMaps(),
                additionalExportedHeaders,
                featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULES),
                featureConfiguration.isEnabled(CppRuleClasses.MODULE_MAP_HOME_CWD),
                featureConfiguration.isEnabled(CppRuleClasses.GENERATE_SUBMODULES),
                !featureConfiguration.isEnabled(CppRuleClasses.MODULE_MAP_WITHOUT_EXTERN_MODULE));
        ruleContext.registerAction(action);
      }
      if (model.getGeneratesPicHeaderModule()) {
        contextBuilder.setPicHeaderModule(model.getPicHeaderModule(cppModuleMap.getArtifact()));
      }
      if (model.getGeneratesNoPicHeaderModule()) {
        contextBuilder.setHeaderModule(model.getHeaderModule(cppModuleMap.getArtifact()));
      }
      if (featureConfiguration.isEnabled(CppRuleClasses.USE_HEADER_MODULES)
          && featureConfiguration.isEnabled(CppRuleClasses.TRANSITIVE_MODULE_MAPS)) {
        contextBuilder.setProvideTransitiveModuleMaps(true);
      }
    }

    semantics.setupCompilationContext(ruleContext, contextBuilder);
    return contextBuilder.build();
  }
Пример #28
0
 /** The {@code .a} file which contains all the compiled sources for a rule. */
 public Artifact archive() {
   // The path will be RULE_PACKAGE/libRULEBASENAME.a
   String basename = new PathFragment(ruleContext.getLabel().getName()).getBaseName();
   return scopedArtifact(
       new PathFragment(String.format("lib%s%s.a", basename, archiveFileNameSuffix)));
 }
Пример #29
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();
  }
Пример #30
0
 /**
  * Adds {@code headers} as public header files. These files will be made visible to dependent
  * rules. They may be parsed/preprocessed or compiled into a header module depending on the
  * configuration.
  */
 public CcLibraryHelper addPublicHeaders(Collection<Artifact> headers) {
   for (Artifact header : headers) {
     addHeader(header, ruleContext.getLabel());
   }
   return this;
 }