예제 #1
0
  /**
   * Creates a generating action for {@code outApk} that builds the APK specified.
   *
   * <p>If {@code signingKey} is not null, the apk will be signed with it using the V1 signature
   * scheme.
   */
  Action[] buildApk(RuleContext ruleContext, Artifact outApk, Artifact signingKey, String message) {
    SpawnAction.Builder actionBuilder =
        new SpawnAction.Builder()
            .setExecutable(AndroidSdkProvider.fromRuleContext(ruleContext).getApkBuilder())
            .setProgressMessage(message)
            .setMnemonic("AndroidApkBuilder")
            .addOutputArgument(outApk);

    if (javaResourceZip != null) {
      actionBuilder.addArgument("-rj").addInputArgument(javaResourceZip);
    }

    Artifact nativeSymlinks = nativeLibs.createApkBuilderSymlinks(ruleContext);
    if (nativeSymlinks != null) {
      PathFragment nativeSymlinksDir = nativeSymlinks.getExecPath().getParentDirectory();
      actionBuilder
          .addInputManifest(nativeSymlinks, nativeSymlinksDir)
          .addInput(nativeSymlinks)
          .addInputs(nativeLibs.getAllNativeLibs())
          .addArgument("-nf")
          // If the native libs are "foo/bar/x86/foo.so", we need to pass "foo/bar" here
          .addArgument(nativeSymlinksDir.getPathString());
    }

    if (nativeLibs.getName() != null) {
      actionBuilder
          .addArgument("-rf")
          .addArgument(nativeLibs.getName().getExecPath().getParentDirectory().getPathString())
          .addInput(nativeLibs.getName());
    }

    if (javaResourceFile != null) {
      actionBuilder
          .addArgument("-rf")
          .addArgument((javaResourceFile.getExecPath().getParentDirectory().getPathString()))
          .addInput(javaResourceFile);
    }

    if (signingKey == null) {
      actionBuilder.addArgument("-u");
    } else {
      actionBuilder.addArgument("-ks").addArgument(signingKey.getExecPathString());
      actionBuilder.addInput(signingKey);
    }

    actionBuilder.addArgument("-z").addInputArgument(resourceApk);

    if (classesDex != null) {
      actionBuilder
          .addArgument(classesDex.getFilename().endsWith(".dex") ? "-f" : "-z")
          .addInputArgument(classesDex);
    }

    return actionBuilder.build(ruleContext);
  }
예제 #2
0
 /** Uses the zipalign tool to align the zip boundaries for uncompressed resources by 4 bytes. */
 Action[] zipalignApk(RuleContext ruleContext, Artifact inputApk, Artifact zipAlignedApk) {
   return new SpawnAction.Builder()
       .addInput(inputApk)
       .addOutput(zipAlignedApk)
       .setExecutable(AndroidSdkProvider.fromRuleContext(ruleContext).getZipalign())
       .addArgument("4")
       .addInputArgument(inputApk)
       .addOutputArgument(zipAlignedApk)
       .setProgressMessage("Zipaligning " + apkName)
       .setMnemonic("AndroidZipAlign")
       .build(ruleContext);
 }
예제 #3
0
  /**
   * Creates an action that converts {@code jarToDex} to a dex file. The output will be stored in
   * the {@link com.google.devtools.build.lib.actions.Artifact} {@code dxJar}.
   */
  public static void createDexAction(
      RuleContext ruleContext,
      Artifact jarToDex,
      Artifact classesDex,
      List<String> dexOptions,
      boolean multidex,
      Artifact mainDexList) {
    List<String> args = new ArrayList<>();
    args.add("--dex");
    // Add --no-locals to coverage builds.  Older coverage tools don't correctly preserve local
    // variable information in stack frame maps that are required since Java 7, so to avoid runtime
    // errors we just don't add local variable info in the first place.  This may no longer be
    // necessary, however, as long as we use a coverage tool that generates stack frame maps.
    if (ruleContext.getConfiguration().isCodeCoverageEnabled()) {
      args.add("--no-locals"); // TODO(bazel-team): Is this still needed?
    }

    // Multithreaded dex does not work when using --multi-dex.
    if (!multidex) {
      // Multithreaded dex tends to run faster, but only up to about 5 threads (at which point the
      // law of diminishing returns kicks in). This was determined experimentally, with 5-thread dex
      // performing about 25% faster than 1-thread dex.
      args.add("--num-threads=5");
    }

    args.addAll(dexOptions);
    if (multidex) {
      args.add("--multi-dex");
      if (mainDexList != null) {
        args.add("--main-dex-list=" + mainDexList.getExecPathString());
      }
    }
    args.add("--output=" + classesDex.getExecPathString());
    args.add(jarToDex.getExecPathString());

    SpawnAction.Builder builder =
        new SpawnAction.Builder()
            .setExecutable(AndroidSdkProvider.fromRuleContext(ruleContext).getDx())
            .addInput(jarToDex)
            .addOutput(classesDex)
            .addArguments(args)
            .setProgressMessage("Converting " + jarToDex.getExecPathString() + " to dex format")
            .setMnemonic("AndroidDexer")
            .setResources(ResourceSet.createWithRamCpuIo(4096.0, 5.0, 0.0));
    if (mainDexList != null) {
      builder.addInput(mainDexList);
    }
    ruleContext.registerAction(builder.build(ruleContext));
  }
예제 #4
0
 /**
  * Signs an APK using the ApkSignerTool. Supports both the jar signing scheme(v1) and the apk
  * signing scheme v2. Note that zip alignment is preserved by this step. Furthermore, zip
  * alignment cannot be performed after v2 signing without invalidating the signature.
  */
 private Action[] signApk(
     RuleContext ruleContext,
     Artifact signingKey,
     Artifact unsignedApk,
     Artifact signedAndZipalignedApk) {
   return new SpawnAction.Builder()
       .setExecutable(AndroidSdkProvider.fromRuleContext(ruleContext).getApkSigner())
       .setProgressMessage("Signing and zipaligning " + apkName)
       .setMnemonic("ApkSignerTool")
       .addArgument("sign")
       .addArgument("--ks")
       .addInputArgument(signingKey)
       .addArguments("--ks-pass", "pass:android")
       .addArguments("--v1-signing-enabled", Boolean.toString(signingMethod.signV1()))
       .addArguments("--v1-signer-name", "CERT")
       .addArguments("--v2-signing-enabled", Boolean.toString(signingMethod.signV2()))
       .addArgument("--out")
       .addOutputArgument(signedAndZipalignedApk)
       .addInputArgument(unsignedApk)
       .build(ruleContext);
 }
예제 #5
0
 JackCompilationHelper initJack(JavaTargetAttributes attributes) throws InterruptedException {
   AndroidSdkProvider sdk = AndroidSdkProvider.fromRuleContext(ruleContext);
   return new JackCompilationHelper.Builder()
       // blaze infrastructure
       .setRuleContext(ruleContext)
       // configuration
       .setOutputArtifact(
           ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_LIBRARY_JACK_FILE))
       // tools
       .setJackBinary(sdk.getJack())
       .setJillBinary(sdk.getJill())
       .setResourceExtractorBinary(sdk.getResourceExtractor())
       .setJackBaseClasspath(sdk.getAndroidBaseClasspathForJack())
       // sources
       .addJavaSources(attributes.getSourceFiles())
       .addSourceJars(attributes.getSourceJars())
       .addResources(attributes.getResources())
       .addProcessorNames(attributes.getProcessorNames())
       .addProcessorClasspathJars(attributes.getProcessorPath())
       .addExports(JavaCommon.getExports(ruleContext))
       .addClasspathDeps(javaCommon.targetsTreatedAsDeps(ClasspathType.COMPILE_ONLY))
       .addRuntimeDeps(javaCommon.targetsTreatedAsDeps(ClasspathType.RUNTIME_ONLY))
       .build();
 }
예제 #6
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();
  }