/* * Copyright (C) 2012 The Android Open Source Project * * 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.android.build.gradle.internal.dsl; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.annotations.VisibleForTesting; import com.android.builder.core.AndroidBuilder; import com.android.builder.core.BuilderConstants; import com.android.builder.core.DefaultBuildType; import com.android.builder.model.BaseConfig; import com.android.builder.model.ClassField; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.logging.Logger; import org.gradle.internal.reflect.Instantiator; import java.io.Serializable; /** * DSL object to configure build types. */ public class BuildType extends DefaultBuildType implements CoreBuildType, Serializable { private static final long serialVersionUID = 1L; @NonNull private final Project project; @NonNull private final Logger logger; @Nullable private final NdkOptions ndkConfig; @Nullable private Boolean useJack; private boolean shrinkResources = false; // opt-in for now until we've validated it in the field public BuildType(@NonNull String name, @NonNull Project project, @NonNull Instantiator instantiator, @NonNull Logger logger) { super(name); this.project = project; this.logger = logger; ndkConfig = instantiator.newInstance(NdkOptions.class); } @VisibleForTesting BuildType(@NonNull String name, @NonNull Project project, @NonNull Logger logger) { super(name); this.project = project; this.logger = logger; ndkConfig = null; } @Override @Nullable public CoreNdkOptions getNdkConfig() { return ndkConfig; } /** * Initialize the DSL object. Not meant to be used from the build scripts. */ public void init(SigningConfig debugSigningConfig) { if (BuilderConstants.DEBUG.equals(getName())) { setDebuggable(true); setEmbedMicroApp(false); assert debugSigningConfig != null; setSigningConfig(debugSigningConfig); } else if (BuilderConstants.RELEASE.equals(getName())) { // no config needed for now. } } /** The signing configuration. */ @Override @Nullable public SigningConfig getSigningConfig() { return (SigningConfig) super.getSigningConfig(); } @Override protected void _initWith(@NonNull BaseConfig that) { super._initWith(that); BuildType thatBuildType = (BuildType) that; shrinkResources = thatBuildType.isShrinkResources(); useJack = thatBuildType.getUseJack(); } public int hashCode() { int result = super.hashCode(); result = 31 * result + (useJack != null ? useJack.hashCode() : 0); result = 31 * result + (shrinkResources ? 1 : 0); return result; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof BuildType)) return false; if (!super.equals(o)) return false; BuildType other = (BuildType) o; if (useJack != other.getUseJack()) return false; if (shrinkResources != other.isShrinkResources()) return false; return true; } // -- DSL Methods. TODO remove once the instantiator does what I expect it to do. /** * Adds a new field to the generated BuildConfig class. * * <p>The field is generated as: <code><type> <name> = <value>;</code> * * <p>This means each of these must have valid Java content. If the type is a String, then the * value should include quotes. * * @param type the type of the field * @param name the name of the field * @param value the value of the field */ public void buildConfigField( @NonNull String type, @NonNull String name, @NonNull String value) { ClassField alreadyPresent = getBuildConfigFields().get(name); if (alreadyPresent != null) { logger.info("BuildType({}): buildConfigField '{}' value is being replaced: {} -> {}", getName(), name, alreadyPresent.getValue(), value); } addBuildConfigField(AndroidBuilder.createClassField(type, name, value)); } /** * Adds a new generated resource. * * @param type the type of the resource * @param name the name of the resource * @param value the value of the resource */ public void resValue( @NonNull String type, @NonNull String name, @NonNull String value) { ClassField alreadyPresent = getResValues().get(name); if (alreadyPresent != null) { logger.info("BuildType({}): resValue '{}' value is being replaced: {} -> {}", getName(), name, alreadyPresent.getValue(), value); } addResValue(AndroidBuilder.createClassField(type, name, value)); } /** * Adds a new ProGuard configuration file. * * <p><code>proguardFile getDefaultProguardFile('proguard-android.txt')</code></p> * * <p>There are 2 default rules files * <ul> * <li>proguard-android.txt * <li>proguard-android-optimize.txt * </ul> * <p>They are located in the SDK. Using <code>getDefaultProguardFile(String filename)</code> * will return the full path to the files. They are identical except for enabling optimizations. */ @NonNull public BuildType proguardFile(@NonNull Object proguardFile) { getProguardFiles().add(project.file(proguardFile)); return this; } /** * Adds new ProGuard configuration files. */ @NonNull public BuildType proguardFiles(@NonNull Object... proguardFileArray) { getProguardFiles().addAll(project.files(proguardFileArray).getFiles()); return this; } /** * Sets the ProGuard configuration files. */ @NonNull public BuildType setProguardFiles(@NonNull Iterable<?> proguardFileIterable) { getProguardFiles().clear(); for (Object proguardFile : proguardFileIterable) { getProguardFiles().add(project.file(proguardFile)); } return this; } /** * Specifies a proguard rule file to be included in the published AAR. * * This proguard rule file will then be used by any application project that consume the AAR * (if proguard is enabled). * * This allows AAR to specify shrinking or obfuscation exclude rules. * * This is only valid for Library project. This is ignored in Application project. */ @NonNull public BuildType testProguardFile(@NonNull Object proguardFile) { getTestProguardFiles().add(project.file(proguardFile)); return this; } /** * Adds new ProGuard configuration files. */ @NonNull public BuildType testProguardFiles(@NonNull Object... proguardFileArray) { getTestProguardFiles().addAll(project.files(proguardFileArray).getFiles()); return this; } @NonNull public BuildType consumerProguardFiles(@NonNull Object... proguardFileArray) { getConsumerProguardFiles().addAll(project.files(proguardFileArray).getFiles()); return this; } /** * Specifies a proguard rule file to be included in the published AAR. * * This proguard rule file will then be used by any application project that consume the AAR * (if proguard is enabled). * * This allows AAR to specify shrinking or obfuscation exclude rules. * * This is only valid for Library project. This is ignored in Application project. */ @NonNull public BuildType setConsumerProguardFiles(@NonNull Iterable<?> proguardFileIterable) { getConsumerProguardFiles().clear(); for (Object proguardFile : proguardFileIterable) { getConsumerProguardFiles().add(project.file(proguardFile)); } return this; } public void ndk(@NonNull Action<NdkOptions> action) { action.execute(ndkConfig); } /** * Whether the experimental Jack toolchain should be used. */ @Override @Nullable public Boolean getUseJack() { return useJack; } /** * Whether the experimental Jack toolchain should be used. */ public void setUseJack(@Nullable Boolean useJack) { this.useJack = useJack; } /** * Whether the experimental Jack toolchain should be used. */ public void useJack(@Nullable Boolean useJack) { setUseJack(useJack); } /** * Whether shrinking of unused resources is enabled. * * Default is false; */ @Override public boolean isShrinkResources() { return shrinkResources; } public void setShrinkResources(boolean shrinkResources) { this.shrinkResources = shrinkResources; } /** * Whether shrinking of unused resources is enabled. * * Default is false; */ public void shrinkResources(boolean flag) { this.shrinkResources = flag; } public void jarJarRuleFile(@NonNull Object file) { getJarJarRuleFiles().add(project.file(file)); } public void jarJarRuleFiles(@NonNull Object... files) { getJarJarRuleFiles().clear(); for (Object file : files) { getJarJarRuleFiles().add(project.file(file)); } } }