Skip to content

Commit

Permalink
Prepare for release 0.13.3.
Browse files Browse the repository at this point in the history
  • Loading branch information
Iurii Makhno committed Mar 11, 2020
1 parent 6a80c81 commit a325c37
Show file tree
Hide file tree
Showing 72 changed files with 1,334 additions and 406 deletions.
Empty file modified .github/ISSUE_TEMPLATE/Bug_report.md
100755 → 100644
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/Custom.md
100755 → 100644
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/Feature_request.md
100755 → 100644
Empty file.
Empty file modified .gitignore
100755 → 100644
Empty file.
Empty file modified CONTRIBUTING.md
100755 → 100644
Empty file.
Empty file modified LICENSE
100755 → 100644
Empty file.
2 changes: 1 addition & 1 deletion README.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ https://developer.android.com/studio/command-line/bundletool

## Releases

Latest release: [0.13.0](https://github.com/google/bundletool/releases)
Latest release: [0.13.3](https://github.com/google/bundletool/releases)
16 changes: 9 additions & 7 deletions build.gradle
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ apply plugin: "java"
apply plugin: "maven"

repositories {
mavenLocal()
jcenter()
google()
maven {
url "https://storage.googleapis.com/r8-releases/raw"
}
}

configurations {
Expand All @@ -32,23 +34,23 @@ configurations {

// The repackaging rules are defined in the "shadowJar" task below.
dependencies {
compile "com.android.tools:r8:1.5.68"
compile "com.android.tools:r8:2.0.23"
compile "com.android.tools.build:apkzlib:3.4.0-beta01"
compile "com.android.tools.ddms:ddmlib:26.2.0"

shadow "com.android.tools.build:aapt2-proto:0.4.0"
shadow "com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524"
shadow "com.google.auto.value:auto-value-annotations:1.6.2"
annotationProcessor "com.google.auto.value:auto-value:1.6.2"
shadow "com.google.errorprone:error_prone_annotations:2.3.1"
shadow "com.google.guava:guava:27.0.1-jre"
shadow "com.google.protobuf:protobuf-java:3.4.0"
shadow "com.google.protobuf:protobuf-java-util:3.4.0"

compileWindows "com.android.tools.build:aapt2:3.5.0-alpha03-5252756:windows"
compileMacOs "com.android.tools.build:aapt2:3.5.0-alpha03-5252756:osx"
compileLinux "com.android.tools.build:aapt2:3.5.0-alpha03-5252756:linux"
compileWindows "com.android.tools.build:aapt2:4.1.0-alpha01-6193524:windows"
compileMacOs "com.android.tools.build:aapt2:4.1.0-alpha01-6193524:osx"
compileLinux "com.android.tools.build:aapt2:4.1.0-alpha01-6193524:linux"

testCompile "com.android.tools.build:aapt2-proto:0.4.0"
testCompile "com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524"
testCompile "com.google.auto.value:auto-value-annotations:1.6.2"
testAnnotationProcessor "com.google.auto.value:auto-value:1.6.2"
testCompile "com.google.errorprone:error_prone_annotations:2.3.1"
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1 +1 @@
release_version = 0.13.0
release_version = 0.13.3
Empty file modified gradle/wrapper/gradle-wrapper.jar
100755 → 100644
Empty file.
Empty file modified gradle/wrapper/gradle-wrapper.properties
100755 → 100644
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -463,35 +463,7 @@ static BuildApksCommand fromFlags(
.setExecutorServiceCreatedByBundleTool(true));
OPTIMIZE_FOR_FLAG.getValue(flags).ifPresent(buildApksCommand::setOptimizationDimensions);

// Signing-related arguments.
Optional<Path> keystorePath = KEYSTORE_FLAG.getValue(flags);
Optional<String> keyAlias = KEY_ALIAS_FLAG.getValue(flags);
Optional<Password> keystorePassword = KEYSTORE_PASSWORD_FLAG.getValue(flags);
Optional<Password> keyPassword = KEY_PASSWORD_FLAG.getValue(flags);

if (keystorePath.isPresent() && keyAlias.isPresent()) {
buildApksCommand.setSigningConfiguration(
SigningConfiguration.extractFromKeystore(
keystorePath.get(), keyAlias.get(), keystorePassword, keyPassword));
} else if (keystorePath.isPresent() && !keyAlias.isPresent()) {
throw new CommandExecutionException("Flag --ks-key-alias is required when --ks is set.");
} else if (!keystorePath.isPresent() && keyAlias.isPresent()) {
throw new CommandExecutionException("Flag --ks is required when --ks-key-alias is set.");
} else {
// Try to use debug keystore if present.
Optional<SigningConfiguration> debugConfig =
DebugKeystoreUtils.getDebugSigningConfiguration(systemEnvironmentProvider);
if (debugConfig.isPresent()) {
out.printf(
"INFO: The APKs will be signed with the debug keystore found at '%s'.%n",
DebugKeystoreUtils.DEBUG_KEYSTORE_CACHE.getUnchecked(systemEnvironmentProvider).get());
buildApksCommand.setSigningConfiguration(debugConfig.get());
} else {
out.println(
"WARNING: The APKs won't be signed and thus not installable unless you also pass a "
+ "keystore via the flag --ks. See the command help for more information.");
}
}
populateSigningConfigurationFromFlags(buildApksCommand, flags, out, systemEnvironmentProvider);

boolean connectedDeviceMode = CONNECTED_DEVICE_FLAG.getValue(flags).orElse(false);
CONNECTED_DEVICE_FLAG
Expand Down Expand Up @@ -769,4 +741,41 @@ private static String joinFlagOptions(Enum<?>... flagOptions) {
.map(String::toLowerCase)
.collect(Collectors.joining("|"));
}

private static void populateSigningConfigurationFromFlags(
Builder buildApksCommand,
ParsedFlags flags,
PrintStream out,
SystemEnvironmentProvider systemEnvironmentProvider) {
// Signing-related arguments.
Optional<Path> keystorePath = KEYSTORE_FLAG.getValue(flags);
Optional<String> keyAlias = KEY_ALIAS_FLAG.getValue(flags);
Optional<Password> keystorePassword = KEYSTORE_PASSWORD_FLAG.getValue(flags);
Optional<Password> keyPassword = KEY_PASSWORD_FLAG.getValue(flags);

if (keystorePath.isPresent() && keyAlias.isPresent()) {
buildApksCommand.setSigningConfiguration(
SigningConfiguration.extractFromKeystore(
keystorePath.get(), keyAlias.get(), keystorePassword, keyPassword));
} else if (keystorePath.isPresent() && !keyAlias.isPresent()) {
throw new CommandExecutionException("Flag --ks-key-alias is required when --ks is set.");
} else if (!keystorePath.isPresent() && keyAlias.isPresent()) {
throw new CommandExecutionException("Flag --ks is required when --ks-key-alias is set.");
} else {
// Try to use debug keystore if present.
Optional<SigningConfiguration> debugConfig =
DebugKeystoreUtils.getDebugSigningConfiguration(systemEnvironmentProvider);
if (debugConfig.isPresent()) {
out.printf(
"INFO: The APKs will be signed with the debug keystore found at '%s'.%n",
DebugKeystoreUtils.DEBUG_KEYSTORE_CACHE.getUnchecked(systemEnvironmentProvider).get());
buildApksCommand.setSigningConfiguration(debugConfig.get());
} else {
out.println(
"WARNING: The APKs won't be signed and thus not installable unless you also pass a "
+ "keystore via the flag --ks. See the command help for more information.");
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,10 @@ private void executeWithZip(ZipFile bundleZip, Optional<DeviceSpec> deviceSpec)
GeneratedApks.Builder generatedApksBuilder = GeneratedApks.builder();
GeneratedAssetSlices.Builder generatedAssetSlices = GeneratedAssetSlices.builder();

boolean enableUniversalAsFallbackForSplits = false;
ApksToGenerate apksToGenerate =
new ApksToGenerate(appBundle, command.getApkBuildMode(), deviceSpec);
new ApksToGenerate(
appBundle, command.getApkBuildMode(), enableUniversalAsFallbackForSplits, deviceSpec);

// Split APKs
if (apksToGenerate.generateSplitApks()) {
Expand Down Expand Up @@ -508,12 +510,17 @@ private static LocalTestingInfo getLocalTestingInfo(AppBundle bundle) {
private static class ApksToGenerate {
private final AppBundle appBundle;
private final ApkBuildMode apkBuildMode;
private final boolean enableUniversalAsFallbackForSplits;
private final Optional<DeviceSpec> deviceSpec;

private ApksToGenerate(
AppBundle appBundle, ApkBuildMode apkBuildMode, Optional<DeviceSpec> deviceSpec) {
AppBundle appBundle,
ApkBuildMode apkBuildMode,
boolean enableUniversalAsFallbackForSplits,
Optional<DeviceSpec> deviceSpec) {
this.appBundle = appBundle;
this.apkBuildMode = apkBuildMode;
this.enableUniversalAsFallbackForSplits = enableUniversalAsFallbackForSplits;
this.deviceSpec = deviceSpec;
validate();
}
Expand Down Expand Up @@ -598,7 +605,9 @@ public boolean generateUniversalApk() {
if (appBundle.isApex()) {
return false;
}
return apkBuildMode.equals(ApkBuildMode.UNIVERSAL);
boolean shouldGenerateAsFallback =
enableUniversalAsFallbackForSplits && generateSplitApks() && !generateStandaloneApks();
return apkBuildMode.equals(ApkBuildMode.UNIVERSAL) || shouldGenerateAsFallback;
}

public boolean generateSystemApks() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,7 @@ public void execute() {

// Read the Bundle Config file if provided by the developer.
BundleConfig bundleConfig =
getBundleConfig()
.orElse(BundleConfig.getDefaultInstance())
.toBuilder()
getBundleConfig().orElse(BundleConfig.getDefaultInstance()).toBuilder()
.setBundletool(
Bundletool.newBuilder()
.setVersion(BundleToolVersion.getCurrentVersion().toString()))
Expand Down Expand Up @@ -297,19 +295,30 @@ private static Optional<NativeLibraries> generateNativeLibrariesTargeting(Bundle
}

private static Optional<ApexImages> generateApexImagesTargeting(BundleModule module) {
// Validation ensures that files under "apex/" conform to the pattern
// Validation ensures that image files under "apex/" conform to the pattern
// "apex/<abi1>.<abi2>...<abiN>.img".
ImmutableList<ZipPath> apexImageFiles =
module
.findEntriesUnderPath(BundleModule.APEX_DIRECTORY)
.map(ModuleEntry::getPath)
.filter(p -> p.toString().endsWith(BundleModule.APEX_IMAGE_SUFFIX))
.collect(toImmutableList());

// Validation ensures if build info is present then we have one per image.
boolean hasBuildInfo =
module
.findEntriesUnderPath(BundleModule.APEX_DIRECTORY)
.map(ModuleEntry::getPath)
.anyMatch(p -> p.toString().endsWith(BundleModule.BUILD_INFO_SUFFIX));

if (apexImageFiles.isEmpty()) {
return Optional.empty();
}

return Optional.of(new TargetingGenerator().generateTargetingForApexImages(apexImageFiles));
return Optional.of(
new TargetingGenerator()
.generateTargetingForApexImages(
module.getBundleConfig().getApexConfig(), apexImageFiles, hasBuildInfo));
}

private static BundleConfig parseBundleConfigJson(Path bundleConfigJsonPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.android.tools.build.bundletool.io;

import static com.android.tools.build.bundletool.model.BundleModule.APEX_DIRECTORY;
import static com.android.tools.build.bundletool.model.BundleModule.APEX_IMAGE_SUFFIX;
import static com.android.tools.build.bundletool.model.BundleModule.BUILD_INFO_SUFFIX;
import static com.android.tools.build.bundletool.model.BundleModule.DEX_DIRECTORY;
import static com.android.tools.build.bundletool.model.BundleModule.MANIFEST_FILENAME;
import static com.android.tools.build.bundletool.model.BundleModule.ROOT_DIRECTORY;
Expand Down Expand Up @@ -250,7 +252,7 @@ private Path writeProtoApk(ModuleSplit split, Path outputPath, Path tempDir) {
entryOptionForPath(
pathInApk,
/* uncompressNativeLibs= */ !extractNativeLibs,
/* entryShouldCompress= */ entry.shouldCompress());
/* entryShouldCompress= */ entry.getShouldCompress());
if (signingConfig.isPresent()
&& wear1ApkPath.isPresent()
&& wear1ApkPath.get().equals(pathInApk)) {
Expand Down Expand Up @@ -282,9 +284,7 @@ private Path writeProtoApk(ModuleSplit split, Path outputPath, Path tempDir) {
}

private EntryOption[] entryOptionForPath(
ZipPath path,
boolean uncompressNativeLibs,
boolean entryShouldCompress) {
ZipPath path, boolean uncompressNativeLibs, boolean entryShouldCompress) {
if (shouldCompress(path, uncompressNativeLibs, entryShouldCompress)) {
return new EntryOption[] {};
} else {
Expand All @@ -293,9 +293,7 @@ private EntryOption[] entryOptionForPath(
}

private boolean shouldCompress(
ZipPath path,
boolean uncompressNativeLibs,
boolean entryShouldCompress) {
ZipPath path, boolean uncompressNativeLibs, boolean entryShouldCompress) {
if (uncompressedPathMatchers.stream()
.anyMatch(pathMatcher -> pathMatcher.matches(path.toString()))) {
return false;
Expand Down Expand Up @@ -334,7 +332,7 @@ private void addNonAapt2Files(ZFile zFile, ModuleSplit split) throws IOException
zFile.add(
pathInApk.toString(),
entryInputStream,
shouldCompress(pathInApk, !extractNativeLibs, entry.shouldCompress()));
shouldCompress(pathInApk, !extractNativeLibs, entry.getShouldCompress()));
}
}
}
Expand All @@ -344,8 +342,8 @@ private void addNonAapt2Files(ZFile zFile, ModuleSplit split) throws IOException
* Transforms the entry path in the module to the final path in the module split.
*
* <p>The entries from root/, dex/, manifest/ directories will be moved to the top level of the
* split. Entries from apex/ will be moved to the top level and named "apex_payload.img". There
* should only be one such entry.
* split. Entries from apex/ will be moved to the top level and named "apex_payload.img" for
* images or "apex_build_info.pb" for APEX build info. There should only be one such entry.
*/
private ZipPath toApkEntryPath(ZipPath pathInModule) {
if (pathInModule.startsWith(DEX_DIRECTORY)) {
Expand All @@ -368,7 +366,16 @@ private ZipPath toApkEntryPath(ZipPath pathInModule) {
pathInModule.getNameCount() >= 2,
"Only files inside the apex directory are supported but found: %s",
pathInModule);
return ZipPath.create("apex_payload.img");
checkArgument(
pathInModule.toString().endsWith(APEX_IMAGE_SUFFIX)
|| pathInModule.toString().endsWith(BUILD_INFO_SUFFIX),
"Unexpected filename in apex directory: %s",
pathInModule);
if (pathInModule.toString().endsWith(APEX_IMAGE_SUFFIX)) {
return ZipPath.create("apex_payload.img");
} else {
return ZipPath.create("apex_build_info.pb");
}
}
return pathInModule;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ ApkDescription writeToDiskInternal(
.setTargeting(standaloneSplit.getApkTargeting());

if (standaloneSplit.isApex()) {
apkDescription.setApexApkMetadata(ApexApkMetadata.getDefaultInstance());
apkDescription.setApexApkMetadata(
ApexApkMetadata.newBuilder()
.addAllApexEmbeddedApkConfig(
standaloneSplit.getApexConfig().get().getApexEmbeddedApkConfigList())
.build());
} else {
apkDescription.setStandaloneApkMetadata(
StandaloneApkMetadata.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import com.google.common.io.RecursiveDeleteOption;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.annotation.Nullable;
Expand Down Expand Up @@ -53,8 +55,27 @@ public Path getPath() {

@Override
public void close() {
closeWithRetry(/* numAttempt= */ 1);
}

private void closeWithRetry(int numAttempt) {
try {
MoreFiles.deleteRecursively(dirPath, RecursiveDeleteOption.ALLOW_INSECURE);
} catch (FileSystemException e) {
// See https://github.com/google/bundletool/issues/61
// Retrying because Windows sometimes doesn't delete everything synchronously.
if (e.getCause() instanceof DirectoryNotEmptyException) {
if (numAttempt == 5) {
throw new UncheckedIOException(
"Unable to delete temporary directory after 5 attempts.", e);
}
try {
Thread.sleep(200L);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
closeWithRetry(numAttempt + 1);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down
Loading

0 comments on commit a325c37

Please sign in to comment.