blob: 937747a883bbe13d22ac6dd157441fd91807d5e5 [file] [log] [blame]
/*
* Copyright 2012-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.android;
import com.android.sdklib.build.ApkBuilder;
import com.facebook.buck.shell.ShellStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.MoreStrings;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
/**
* Runs the Android Asset Packaging Tool ({@code aapt}), which creates an {@code .apk} file.
* Frequently, the {@code pathsToRawFilesDirs} excludes {@code classes.dex}, as {@code classes.dex}
* will be added separately to the final APK via {@link ApkBuilder}.
*/
public class AaptStep extends ShellStep {
// aapt, unless specified a pattern, ignores certain files and directories. We follow the same
// logic as the default pattern found at http://goo.gl/OTTK88 and line 61.
private static final String DEFAULT_IGNORE_ASSETS_PATTERN =
"\\!.svn:\\!.git:\\!.ds_store:\\!*.scc:.*:<dir>_*:\\!CVS:\\!thumbs.db:\\!picasa.ini:\\!*~";
// Ignore *.orig files generated by mercurial.
public static final String IGNORE_ASSETS_PATTERN = DEFAULT_IGNORE_ASSETS_PATTERN + ":*.orig";
/**
* Determines whether the default AAPT ignore pattern in
* {@link com.facebook.buck.android.AaptStep#DEFAULT_IGNORE_ASSETS_PATTERN}
* would silently ignore a file.
*
* @param path The path of the file we are interested in.
* @return Whether the file would be silently ignored.
*/
public static boolean isSilentlyIgnored(Path path) {
String fileName = path.getFileName().toString();
return
".svn".equalsIgnoreCase(fileName) ||
".git".equalsIgnoreCase(fileName) ||
".ds_store".equalsIgnoreCase(fileName) ||
MoreStrings.endsWithIgnoreCase(fileName, ".scc") ||
"cvs".equalsIgnoreCase(fileName) ||
"thumbs.db".equalsIgnoreCase(fileName) ||
"picasa.ini".equalsIgnoreCase(fileName) ||
fileName.endsWith("~");
}
private final Path androidManifest;
private final ImmutableList<Path> resDirectories;
private final Optional<Path> assetsDirectory;
private final Path pathToOutputApkFile;
private final Path pathToRDotTxtDir;
private final Optional<Path> pathToGeneratedProguardConfig;
private final boolean isCrunchPngFiles;
public AaptStep(
Path androidManifest,
ImmutableList<Path> resDirectories,
Optional<Path> assetsDirectory,
Path pathToOutputApkFile,
Path pathToRDotTxtDir,
Optional<Path> pathToGeneratedProguardConfig,
boolean isCrunchPngFiles) {
this.androidManifest = androidManifest;
this.resDirectories = resDirectories;
this.assetsDirectory = assetsDirectory;
this.pathToOutputApkFile = pathToOutputApkFile;
this.pathToRDotTxtDir = pathToRDotTxtDir;
this.pathToGeneratedProguardConfig = pathToGeneratedProguardConfig;
this.isCrunchPngFiles = isCrunchPngFiles;
}
@Override
protected ImmutableList<String> getShellCommandInternal(ExecutionContext context) {
ImmutableList.Builder<String> builder = ImmutableList.builder();
AndroidPlatformTarget androidPlatformTarget = context.getAndroidPlatformTarget();
builder.add(androidPlatformTarget.getAaptExecutable().toString());
builder.add("package");
// verbose flag, if appropriate.
if (context.getVerbosity().shouldUseVerbosityFlagIfAvailable()) {
builder.add("-v");
}
// Force overwrite of existing files.
builder.add("-f");
if (pathToGeneratedProguardConfig.isPresent()) {
builder.add("-G", pathToGeneratedProguardConfig.get().toString());
}
// --no-crunch, if appropriate.
if (!isCrunchPngFiles) {
builder.add("--no-crunch");
}
// Include all of the res/ directories.
builder.add("--auto-add-overlay");
for (Path res : resDirectories) {
builder.add("-S", res.toString());
}
// Include the assets/ directory, if any.
// According to the aapt documentation, it appears that it should be possible to specify the -A
// flag multiple times; however, in practice, when it is specified multiple times, only one of
// the folders is included in the final APK.
if (assetsDirectory.isPresent()) {
builder.add("-A", assetsDirectory.get().toString());
}
builder.add("--output-text-symbols").add(pathToRDotTxtDir.toString());
builder.add("-J").add(pathToRDotTxtDir.toString());
builder.add("-M").add(androidManifest.toString());
builder.add("-I", androidPlatformTarget.getAndroidJar().toString());
builder.add("-F", pathToOutputApkFile.toString());
builder.add("--ignore-assets", IGNORE_ASSETS_PATTERN);
return builder.build();
}
@Override
public String getShortName() {
return String.format("aapt_package");
}
}