提交 a325c37e 编写于 作者: I Iurii Makhno

Prepare for release 0.13.3.

上级 6a80c81f
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
......@@ -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)
......@@ -19,9 +19,11 @@ apply plugin: "java"
apply plugin: "maven"
repositories {
mavenLocal()
jcenter()
google()
maven {
url "https://storage.googleapis.com/r8-releases/raw"
}
}
configurations {
......@@ -32,11 +34,11 @@ 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"
......@@ -44,11 +46,11 @@ dependencies {
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"
......
release_version = 0.13.0
release_version = 0.13.3
文件模式从 100755 更改为 100644
文件模式从 100755 更改为 100644
......@@ -463,35 +463,7 @@ public abstract class BuildApksCommand {
.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
......@@ -769,4 +741,41 @@ public abstract class BuildApksCommand {
.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.");
}
}
}
}
......@@ -155,8 +155,10 @@ final class BuildApksManager {
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()) {
......@@ -508,12 +510,17 @@ final class BuildApksManager {
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();
}
......@@ -598,7 +605,9 @@ final class BuildApksManager {
if (appBundle.isApex()) {
return false;
}
return apkBuildMode.equals(ApkBuildMode.UNIVERSAL);
boolean shouldGenerateAsFallback =
enableUniversalAsFallbackForSplits && generateSplitApks() && !generateStandaloneApks();
return apkBuildMode.equals(ApkBuildMode.UNIVERSAL) || shouldGenerateAsFallback;
}
public boolean generateSystemApks() {
......
......@@ -231,9 +231,7 @@ public abstract class BuildBundleCommand {
// 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()))
......@@ -297,19 +295,30 @@ public abstract class BuildBundleCommand {
}
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) {
......
......@@ -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;
......@@ -250,7 +252,7 @@ final class ApkSerializerHelper {
entryOptionForPath(
pathInApk,
/* uncompressNativeLibs= */ !extractNativeLibs,
/* entryShouldCompress= */ entry.shouldCompress());
/* entryShouldCompress= */ entry.getShouldCompress());
if (signingConfig.isPresent()
&& wear1ApkPath.isPresent()
&& wear1ApkPath.get().equals(pathInApk)) {
......@@ -282,9 +284,7 @@ final class ApkSerializerHelper {
}
private EntryOption[] entryOptionForPath(
ZipPath path,
boolean uncompressNativeLibs,
boolean entryShouldCompress) {
ZipPath path, boolean uncompressNativeLibs, boolean entryShouldCompress) {
if (shouldCompress(path, uncompressNativeLibs, entryShouldCompress)) {
return new EntryOption[] {};
} else {
......@@ -293,9 +293,7 @@ final class ApkSerializerHelper {
}
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;
......@@ -334,7 +332,7 @@ final class ApkSerializerHelper {
zFile.add(
pathInApk.toString(),
entryInputStream,
shouldCompress(pathInApk, !extractNativeLibs, entry.shouldCompress()));
shouldCompress(pathInApk, !extractNativeLibs, entry.getShouldCompress()));
}
}
}
......@@ -344,8 +342,8 @@ final class ApkSerializerHelper {
* 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)) {
......@@ -368,7 +366,16 @@ final class ApkSerializerHelper {
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;
}
......
......@@ -94,7 +94,11 @@ public class StandaloneApkSerializer {
.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()
......
......@@ -20,6 +20,8 @@ import com.google.common.io.MoreFiles;
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;
......@@ -53,8 +55,27 @@ public class TempDirectory implements AutoCloseable {
@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);
}
......
......@@ -46,6 +46,7 @@ import com.android.tools.build.bundletool.model.ShardedSystemSplits;
import com.android.tools.build.bundletool.model.SuffixManager;
import com.android.tools.build.bundletool.model.ZipPath;
import com.android.tools.build.bundletool.model.exceptions.CommandExecutionException;
import com.android.tools.build.bundletool.model.utils.Versions;
import com.android.tools.build.bundletool.model.utils.files.BufferedIo;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ArrayListMultimap;
......@@ -55,8 +56,10 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
......@@ -354,7 +357,10 @@ public class ModuleSplitsToShardMerger {
// Don't merge if all dex files live inside a single module. If that module contains multiple
// dex files, it should have been built with multi-dex support.
return dexFilesToMergeByModule.values();
} else if (androidManifest.getEffectiveMinSdkVersion() >= Versions.ANDROID_L_API_VERSION) {
// When APK targets L+ devices we know the devices already have multi-dex support.
// In this case we can skip merging dexes and just rename original ones to be in order.
return renameDexFromAllModulesToSingleShard(dexFilesToMergeByModule);
} else {
ImmutableList<ModuleEntry> dexEntries =
ImmutableList.copyOf(dexFilesToMergeByModule.values());
......@@ -375,6 +381,32 @@ public class ModuleSplitsToShardMerger {
}
}
private static ImmutableList<ModuleEntry> renameDexFromAllModulesToSingleShard(
Multimap<BundleModuleName, ModuleEntry> dexFilesToMergeByModule) {
// We don't need to rename classes*.dex in base module.
Stream<ModuleEntry> dexFilesFromBase = dexFilesToMergeByModule.get(BASE_MODULE_NAME).stream();
// Take Dex files from all other modules and rename them to be after base module dexes.
int dexFilesCountInBase = dexFilesToMergeByModule.get(BASE_MODULE_NAME).size();
Stream<ModuleEntry> dexFilesFromNotBase =
dexFilesToMergeByModule.keys().stream()
.distinct()
.filter(moduleName -> !BASE_MODULE_NAME.equals(moduleName))
.flatMap(moduleName -> dexFilesToMergeByModule.get(moduleName).stream());
Stream<ModuleEntry> renamedDexFiles =
Streams.mapWithIndex(
dexFilesFromNotBase,
(entry, index) ->
entry.setPath(
DEX_DIRECTORY.resolve(
dexFilesCountInBase + index == 0
? "classes.dex"
: String.format("classes%d.dex", dexFilesCountInBase + index + 1))));
return Stream.concat(dexFilesFromBase, renamedDexFiles).collect(toImmutableList());
}
private ImmutableList<Path> mergeDexFiles(
List<ModuleEntry> dexEntries,
BundleMetadata bundleMetadata,
......
......@@ -20,6 +20,7 @@ import static com.android.tools.build.bundletool.model.version.VersionGuardedFea
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Streams.stream;
import com.android.aapt.Resources.XmlNode;
import com.android.tools.build.bundletool.model.BundleModule.ModuleType;
......@@ -66,6 +67,7 @@ public abstract class AndroidManifest {
public static final String ACTIVITY_ELEMENT_NAME = "activity";
public static final String SERVICE_ELEMENT_NAME = "service";
public static final String PROVIDER_ELEMENT_NAME = "provider";
public static final String SUPPORTS_GL_TEXTURE_ELEMENT_NAME = "supports-gl-texture";
public static final String DEBUGGABLE_ATTRIBUTE_NAME = "debuggable";
public static final String EXTRACT_NATIVE_LIBS_ATTRIBUTE_NAME = "extractNativeLibs";
......@@ -90,6 +92,9 @@ public abstract class AndroidManifest {
public static final String MODULE_TYPE_FEATURE_VALUE = "feature";
public static final String MODULE_TYPE_ASSET_VALUE = "asset-pack";
/** <meta-data> name that specifies native library for native activity */
public static final String NATIVE_ACTIVITY_LIB_NAME = "android.app.lib_name";
public static final int DEBUGGABLE_RESOURCE_ID = 0x0101000f;
public static final int EXTRACT_NATIVE_LIBS_RESOURCE_ID = 0x10104ea;
public static final int HAS_CODE_RESOURCE_ID = 0x101000c;
......@@ -269,6 +274,22 @@ public abstract class AndroidManifest {
: attribute.getValueAsDecimalInteger());
}
public ImmutableList<String> getSupportsGlTextures() {
return getManifestElement()
.getChildrenElements("supports-gl-texture")
.map(
supportsGlTextures ->
supportsGlTextures
.getAndroidAttribute(NAME_RESOURCE_ID)
.<ValidationException>orElseThrow(
() ->
new ValidationException(
"<supports-gl-texture> element is missing the 'android:name'"
+ " attribute.")))
.map(XmlProtoAttribute::getValueAsString)
.collect(toImmutableList());
}
private static boolean isSdkCodename(String sdkVersion) {
// Codename version can be of the form "[codename]" or "[codename].[fingerprint]".
return !sdkVersion.isEmpty()
......@@ -276,6 +297,10 @@ public abstract class AndroidManifest {
&& (sdkVersion.length() == 1 || '.' == sdkVersion.charAt(1));
}
public boolean hasApplicationElement() {
return getManifestElement().getOptionalChildElement(APPLICATION_ELEMENT_NAME).isPresent();
}
public Optional<Boolean> getHasCode() {
return getManifestElement()
.getOptionalChildElement(APPLICATION_ELEMENT_NAME)
......@@ -459,6 +484,21 @@ public abstract class AndroidManifest {
.map(XmlProtoAttribute::getValueAsString);
}
/**
* Returns whether the app explicitly defined native activities via searching for all activities
* that have 'android.app.lib_name' <meta-data>.
*/
public boolean hasExplicitlyDefinedNativeActivities() {
return stream(getManifestElement().getOptionalChildElement(APPLICATION_ELEMENT_NAME))
.flatMap(app -> app.getChildrenElements(ACTIVITY_ELEMENT_NAME))
.flatMap(activity -> activity.getChildrenElements(META_DATA_ELEMENT_NAME))
.anyMatch(
meta ->
meta.getAndroidAttribute(NAME_RESOURCE_ID)
.filter(name -> NATIVE_ACTIVITY_LIB_NAME.equals(name.getValueAsString()))
.isPresent());
}
/**
* Extracts names of the fused modules.
*
......
......@@ -34,6 +34,7 @@ import com.android.bundle.Files.ApexImages;
import com.android.bundle.Files.Assets;
import com.android.bundle.Files.NativeLibraries;
import com.android.bundle.Targeting.ModuleTargeting;
import com.android.tools.build.bundletool.model.exceptions.ValidationException;
import com.android.tools.build.bundletool.model.utils.xmlproto.XmlProtoAttribute;
import com.android.tools.build.bundletool.model.version.BundleToolVersion;
import com.google.auto.value.AutoValue;
......@@ -74,8 +75,12 @@ public abstract class BundleModule {
/** The top-level directory of an App Bundle module that contains APEX image files. */
public static final ZipPath APEX_DIRECTORY = ZipPath.create("apex");
public static final String APEX_IMAGE_SUFFIX = "img";
public static final String BUILD_INFO_SUFFIX = "build_info.pb";
/** The file of an App Bundle module that contains the APEX manifest. */
public static final ZipPath APEX_MANIFEST_PATH = ZipPath.create("root/apex_manifest.pb");
public static final ZipPath APEX_MANIFEST_JSON_PATH = ZipPath.create("root/apex_manifest.json");
/** The public key used to sign the apex */
......@@ -197,7 +202,14 @@ public abstract class BundleModule {
public boolean isIncludedInFusing() {
// The following should never throw if the module/bundle has been validated.
return isBaseModule() || getAndroidManifest().getIsModuleIncludedInFusing().get();
return isBaseModule()
|| getAndroidManifest()
.getIsModuleIncludedInFusing()
.orElseThrow(
() ->
new ValidationException(
"Unable to determine if module should be fused: missing <dist:fusing> tag"
+ " inside <dist:module> in AndroidManifest.xml"));
}
public boolean isInstantModule() {
......@@ -234,8 +246,7 @@ public abstract class BundleModule {
return moduleTargeting;
}
return moduleTargeting
.toBuilder()
return moduleTargeting.toBuilder()
.setSdkVersionTargeting(sdkVersionTargeting(sdkVersionFrom(minSdkVersion.get())))
.build();
}
......
......@@ -52,7 +52,7 @@ public class DelegatingModuleEntry extends ModuleEntry {
}
@Override
public boolean shouldCompress() {
return delegate.shouldCompress();
public boolean getShouldCompress() {
return delegate.getShouldCompress();
}
}
......@@ -48,7 +48,7 @@ public abstract class FileSystemModuleEntry extends ModuleEntry {
public abstract boolean isDirectory();
@Override
public abstract boolean shouldCompress();
public abstract boolean getShouldCompress();
abstract Path getFileSystemPath();
......
......@@ -36,7 +36,7 @@ public abstract class InMemoryModuleEntry extends ModuleEntry {
public abstract boolean isDirectory();
@Override
public abstract boolean shouldCompress();
public abstract boolean getShouldCompress();