Search in sources :

Example 1 with RepackZipEntriesStep

use of com.facebook.buck.zip.RepackZipEntriesStep in project buck by facebook.

the class AndroidBinary method getBuildSteps.

@SuppressWarnings("PMD.PrematureDeclaration")
@Override
public ImmutableList<Step> getBuildSteps(BuildContext context, BuildableContext buildableContext) {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();
    // The `HasInstallableApk` interface needs access to the manifest, so make sure we create our
    // own copy of this so that we don't have a runtime dep on the `AaptPackageResources` step.
    Path manifestPath = context.getSourcePathResolver().getRelativePath(getManifestPath());
    steps.add(new MkdirStep(getProjectFilesystem(), manifestPath.getParent()));
    steps.add(CopyStep.forFile(getProjectFilesystem(), context.getSourcePathResolver().getRelativePath(androidManifestPath), manifestPath));
    buildableContext.recordArtifact(manifestPath);
    // Create the .dex files if we aren't doing pre-dexing.
    DexFilesInfo dexFilesInfo = addFinalDxSteps(buildableContext, context.getSourcePathResolver(), steps);
    ////
    // BE VERY CAREFUL adding any code below here.
    // Any inputs to apkbuilder must be reflected in the hash returned by getAbiKeyForDeps.
    ////
    AndroidPackageableCollection packageableCollection = enhancementResult.getPackageableCollection();
    ImmutableSet.Builder<Path> nativeLibraryDirectoriesBuilder = ImmutableSet.builder();
    // Copy the transitive closure of native-libs-as-assets to a single directory, if any.
    ImmutableSet.Builder<Path> nativeLibraryAsAssetDirectories = ImmutableSet.builder();
    for (final APKModule module : enhancementResult.getAPKModuleGraph().getAPKModules()) {
        boolean shouldPackageAssetLibraries = packageAssetLibraries || !module.isRootModule();
        if (!ExopackageMode.enabledForNativeLibraries(exopackageModes) && enhancementResult.getCopyNativeLibraries().isPresent() && enhancementResult.getCopyNativeLibraries().get().containsKey(module)) {
            CopyNativeLibraries copyNativeLibraries = enhancementResult.getCopyNativeLibraries().get().get(module);
            if (shouldPackageAssetLibraries) {
                nativeLibraryDirectoriesBuilder.add(copyNativeLibraries.getPathToNativeLibsDir());
            } else {
                nativeLibraryDirectoriesBuilder.add(copyNativeLibraries.getPathToNativeLibsDir());
                nativeLibraryDirectoriesBuilder.add(copyNativeLibraries.getPathToNativeLibsAssetsDir());
            }
        }
        if ((!packageableCollection.getNativeLibAssetsDirectories().isEmpty()) || (!packageableCollection.getNativeLinkablesAssets().isEmpty() && shouldPackageAssetLibraries)) {
            Path pathForNativeLibsAsAssets = getPathForNativeLibsAsAssets();
            final Path libSubdirectory = pathForNativeLibsAsAssets.resolve("assets").resolve(module.isRootModule() ? "lib" : module.getName());
            ImmutableCollection<SourcePath> nativeLibDirs = packageableCollection.getNativeLibAssetsDirectories().get(module);
            getStepsForNativeAssets(context.getSourcePathResolver(), steps, nativeLibDirs == null ? Optional.empty() : Optional.of(nativeLibDirs), libSubdirectory, module.isRootModule() ? "metadata.txt" : "libs.txt", module);
            nativeLibraryAsAssetDirectories.add(pathForNativeLibsAsAssets);
        }
    }
    // If non-english strings are to be stored as assets, pass them to ApkBuilder.
    ImmutableSet.Builder<Path> zipFiles = ImmutableSet.builder();
    RichStream.from(primaryApkAssetsZips).map(context.getSourcePathResolver()::getRelativePath).forEach(zipFiles::add);
    if (ExopackageMode.enabledForNativeLibraries(exopackageModes)) {
        // We need to include a few dummy native libraries with our application so that Android knows
        // to run it as 32-bit.  Android defaults to 64-bit when no libraries are provided at all,
        // causing us to fail to load our 32-bit exopackage native libraries later.
        String fakeNativeLibraryBundle = System.getProperty("buck.native_exopackage_fake_path");
        if (fakeNativeLibraryBundle == null) {
            throw new RuntimeException("fake native bundle not specified in properties");
        }
        zipFiles.add(Paths.get(fakeNativeLibraryBundle));
    }
    ImmutableSet<Path> allAssetDirectories = ImmutableSet.<Path>builder().addAll(nativeLibraryAsAssetDirectories.build()).addAll(dexFilesInfo.secondaryDexDirs).build();
    SourcePathResolver resolver = context.getSourcePathResolver();
    Path signedApkPath = getSignedApkPath();
    final Path pathToKeystore = resolver.getAbsolutePath(keystorePath);
    Supplier<KeystoreProperties> keystoreProperties = Suppliers.memoize(() -> {
        try {
            return KeystoreProperties.createFromPropertiesFile(pathToKeystore, resolver.getAbsolutePath(keystorePropertiesPath), getProjectFilesystem());
        } catch (IOException e) {
            throw new RuntimeException();
        }
    });
    ApkBuilderStep apkBuilderCommand = new ApkBuilderStep(getProjectFilesystem(), context.getSourcePathResolver().getAbsolutePath(resourcesApkPath), getSignedApkPath(), dexFilesInfo.primaryDexPath, allAssetDirectories, nativeLibraryDirectoriesBuilder.build(), zipFiles.build(), packageableCollection.getPathsToThirdPartyJars().stream().map(resolver::getAbsolutePath).collect(MoreCollectors.toImmutableSet()), pathToKeystore, keystoreProperties, /* debugMode */
    false, javaRuntimeLauncher);
    steps.add(apkBuilderCommand);
    // The `ApkBuilderStep` delegates to android tools to build a ZIP with timestamps in it, making
    // the output non-deterministic.  So use an additional scrubbing step to zero these out.
    steps.add(new ZipScrubberStep(getProjectFilesystem(), signedApkPath));
    Path apkToRedexAndAlign;
    // Optionally, compress the resources file in the .apk.
    if (this.isCompressResources()) {
        Path compressedApkPath = getCompressedResourcesApkPath();
        apkToRedexAndAlign = compressedApkPath;
        RepackZipEntriesStep arscComp = new RepackZipEntriesStep(getProjectFilesystem(), signedApkPath, compressedApkPath, ImmutableSet.of("resources.arsc"));
        steps.add(arscComp);
    } else {
        apkToRedexAndAlign = signedApkPath;
    }
    boolean applyRedex = redexOptions.isPresent();
    Path apkPath = context.getSourcePathResolver().getRelativePath(getSourcePathToOutput());
    Path apkToAlign = apkToRedexAndAlign;
    // redex
    if (applyRedex) {
        Path proguardConfigDir = getProguardTextFilesPath();
        Path redexedApk = apkPath.getParent().resolve(apkPath.getFileName().toString() + ".redex");
        apkToAlign = redexedApk;
        ImmutableList<Step> redexSteps = ReDexStep.createSteps(getProjectFilesystem(), resolver, redexOptions.get(), apkToRedexAndAlign, redexedApk, keystoreProperties, proguardConfigDir, context.getSourcePathResolver());
        steps.addAll(redexSteps);
    }
    steps.add(new ZipalignStep(getProjectFilesystem().getRootPath(), apkToAlign, apkPath));
    buildableContext.recordArtifact(apkPath);
    return steps.build();
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) MkdirStep(com.facebook.buck.step.fs.MkdirStep) CopyStep(com.facebook.buck.step.fs.CopyStep) MkdirStep(com.facebook.buck.step.fs.MkdirStep) SymlinkFilesIntoDirectoryStep(com.facebook.buck.shell.SymlinkFilesIntoDirectoryStep) AccumulateClassNamesStep(com.facebook.buck.jvm.java.AccumulateClassNamesStep) Step(com.facebook.buck.step.Step) RepackZipEntriesStep(com.facebook.buck.zip.RepackZipEntriesStep) AbstractExecutionStep(com.facebook.buck.step.AbstractExecutionStep) MakeCleanDirectoryStep(com.facebook.buck.step.fs.MakeCleanDirectoryStep) ReDexStep(com.facebook.buck.android.redex.ReDexStep) XzStep(com.facebook.buck.step.fs.XzStep) ZipScrubberStep(com.facebook.buck.zip.ZipScrubberStep) AbstractGenruleStep(com.facebook.buck.shell.AbstractGenruleStep) SourcePath(com.facebook.buck.rules.SourcePath) ExplicitBuildTargetSourcePath(com.facebook.buck.rules.ExplicitBuildTargetSourcePath) ImmutableSet(com.google.common.collect.ImmutableSet) ZipScrubberStep(com.facebook.buck.zip.ZipScrubberStep) Path(java.nio.file.Path) SourcePath(com.facebook.buck.rules.SourcePath) ExplicitBuildTargetSourcePath(com.facebook.buck.rules.ExplicitBuildTargetSourcePath) IOException(java.io.IOException) RepackZipEntriesStep(com.facebook.buck.zip.RepackZipEntriesStep) SourcePathResolver(com.facebook.buck.rules.SourcePathResolver)

Example 2 with RepackZipEntriesStep

use of com.facebook.buck.zip.RepackZipEntriesStep in project buck by facebook.

the class SmartDexingStep method createDxStepForDxPseudoRule.

/**
   * The step to produce the .dex file will be determined by the file extension of outputPath, much
   * as {@code dx} itself chooses whether to embed the dex inside a jar/zip based on the destination
   * file passed to it.  We also create a ".meta" file that contains information about the
   * compressed and uncompressed size of the dex; this information is useful later, in applications,
   * when unpacking.
   */
static Step createDxStepForDxPseudoRule(ProjectFilesystem filesystem, Collection<Path> filesToDex, Path outputPath, EnumSet<Option> dxOptions, Optional<Integer> xzCompressionLevel, Optional<String> dxMaxHeapSize) {
    String output = outputPath.toString();
    List<Step> steps = Lists.newArrayList();
    if (DexStore.XZ.matchesPath(outputPath)) {
        Path tempDexJarOutput = Paths.get(output.replaceAll("\\.jar\\.xz$", ".tmp.jar"));
        steps.add(new DxStep(filesystem, tempDexJarOutput, filesToDex, dxOptions, dxMaxHeapSize));
        // We need to make sure classes.dex is STOREd in the .dex.jar file, otherwise .XZ
        // compression won't be effective.
        Path repackedJar = Paths.get(output.replaceAll("\\.xz$", ""));
        steps.add(new RepackZipEntriesStep(filesystem, tempDexJarOutput, repackedJar, ImmutableSet.of("classes.dex"), ZipCompressionLevel.MIN_COMPRESSION_LEVEL));
        steps.add(new RmStep(filesystem, tempDexJarOutput));
        steps.add(new DexJarAnalysisStep(filesystem, repackedJar, repackedJar.resolveSibling(repackedJar.getFileName() + ".meta")));
        if (xzCompressionLevel.isPresent()) {
            steps.add(new XzStep(filesystem, repackedJar, xzCompressionLevel.get().intValue()));
        } else {
            steps.add(new XzStep(filesystem, repackedJar));
        }
    } else if (DexStore.XZS.matchesPath(outputPath)) {
        // Essentially the same logic as the XZ case above, except we compress later.
        // The differences in output file names make it worth separating into a different case.
        // Ensure classes.dex is stored.
        Path tempDexJarOutput = Paths.get(output.replaceAll("\\.jar\\.xzs\\.tmp~$", ".tmp.jar"));
        steps.add(new DxStep(filesystem, tempDexJarOutput, filesToDex, dxOptions, dxMaxHeapSize));
        steps.add(new RepackZipEntriesStep(filesystem, tempDexJarOutput, outputPath, ImmutableSet.of("classes.dex"), ZipCompressionLevel.MIN_COMPRESSION_LEVEL));
        steps.add(new RmStep(filesystem, tempDexJarOutput));
        // Write a .meta file.
        steps.add(new DexJarAnalysisStep(filesystem, outputPath, outputPath.resolveSibling(outputPath.getFileName() + ".meta")));
    } else if (DexStore.JAR.matchesPath(outputPath) || DexStore.RAW.matchesPath(outputPath) || output.endsWith("classes.dex")) {
        steps.add(new DxStep(filesystem, outputPath, filesToDex, dxOptions, dxMaxHeapSize));
        if (DexStore.JAR.matchesPath(outputPath)) {
            steps.add(new DexJarAnalysisStep(filesystem, outputPath, outputPath.resolveSibling(outputPath.getFileName() + ".meta")));
        }
    } else {
        throw new IllegalArgumentException(String.format("Suffix of %s does not have a corresponding DexStore type.", outputPath));
    }
    return new CompositeStep(steps);
}
Also used : Path(java.nio.file.Path) RmStep(com.facebook.buck.step.fs.RmStep) XzStep(com.facebook.buck.step.fs.XzStep) RmStep(com.facebook.buck.step.fs.RmStep) Step(com.facebook.buck.step.Step) RepackZipEntriesStep(com.facebook.buck.zip.RepackZipEntriesStep) CompositeStep(com.facebook.buck.step.CompositeStep) XzStep(com.facebook.buck.step.fs.XzStep) WriteFileStep(com.facebook.buck.step.fs.WriteFileStep) RepackZipEntriesStep(com.facebook.buck.zip.RepackZipEntriesStep) CompositeStep(com.facebook.buck.step.CompositeStep)

Aggregations

Step (com.facebook.buck.step.Step)2 XzStep (com.facebook.buck.step.fs.XzStep)2 RepackZipEntriesStep (com.facebook.buck.zip.RepackZipEntriesStep)2 Path (java.nio.file.Path)2 ReDexStep (com.facebook.buck.android.redex.ReDexStep)1 AccumulateClassNamesStep (com.facebook.buck.jvm.java.AccumulateClassNamesStep)1 ExplicitBuildTargetSourcePath (com.facebook.buck.rules.ExplicitBuildTargetSourcePath)1 SourcePath (com.facebook.buck.rules.SourcePath)1 SourcePathResolver (com.facebook.buck.rules.SourcePathResolver)1 AbstractGenruleStep (com.facebook.buck.shell.AbstractGenruleStep)1 SymlinkFilesIntoDirectoryStep (com.facebook.buck.shell.SymlinkFilesIntoDirectoryStep)1 AbstractExecutionStep (com.facebook.buck.step.AbstractExecutionStep)1 CompositeStep (com.facebook.buck.step.CompositeStep)1 CopyStep (com.facebook.buck.step.fs.CopyStep)1 MakeCleanDirectoryStep (com.facebook.buck.step.fs.MakeCleanDirectoryStep)1 MkdirStep (com.facebook.buck.step.fs.MkdirStep)1 RmStep (com.facebook.buck.step.fs.RmStep)1 WriteFileStep (com.facebook.buck.step.fs.WriteFileStep)1 ZipScrubberStep (com.facebook.buck.zip.ZipScrubberStep)1 ImmutableList (com.google.common.collect.ImmutableList)1