All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.android.build.gradle.BaseExtension Maven / Gradle / Ivy

There is a newer version: 2.3.0
Show newest version
/*
 * 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;

import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.gradle.api.AndroidSourceSet;
import com.android.build.gradle.api.BaseVariant;
import com.android.build.gradle.api.VariantFilter;
import com.android.build.gradle.internal.CompileOptions;
import com.android.build.gradle.internal.ExtraModelInfo;
import com.android.build.gradle.internal.LoggingUtil;
import com.android.build.gradle.internal.SdkHandler;
import com.android.build.gradle.internal.SourceSetSourceProviderWrapper;
import com.android.build.gradle.internal.coverage.JacocoOptions;
import com.android.build.gradle.internal.dsl.AaptOptions;
import com.android.build.gradle.internal.dsl.AdbOptions;
import com.android.build.gradle.internal.dsl.AndroidSourceSetFactory;
import com.android.build.gradle.internal.dsl.BuildType;
import com.android.build.gradle.internal.dsl.DexOptions;
import com.android.build.gradle.internal.dsl.DataBindingOptions;
import com.android.build.gradle.internal.dsl.LintOptions;
import com.android.build.gradle.internal.dsl.PackagingOptions;
import com.android.build.gradle.internal.dsl.ProductFlavor;
import com.android.build.gradle.internal.dsl.SigningConfig;
import com.android.build.gradle.internal.dsl.Splits;
import com.android.build.gradle.internal.dsl.TestOptions;
import com.android.build.api.transform.Transform;
import com.android.builder.core.AndroidBuilder;
import com.android.builder.core.BuilderConstants;
import com.android.builder.core.LibraryRequest;
import com.android.builder.model.SourceProvider;
import com.android.builder.sdk.TargetInfo;
import com.android.builder.testing.api.DeviceProvider;
import com.android.builder.testing.api.TestServer;
import com.android.resources.Density;
import com.android.sdklib.repository.FullRevision;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ConfigurationContainer;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import org.gradle.api.tasks.SourceSet;
import org.gradle.internal.reflect.Instantiator;

import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * Base 'android' extension for all android plugins.
 *
 * 

This is never used directly. Instead, *

    *
  • Plugin com.android.application uses {@link AppExtension}
  • *
  • Plugin com.android.library uses {@link LibraryExtension}
  • *
  • Plugin com.android.test uses {@link TestExtension}
  • *
*/ @SuppressWarnings("UnnecessaryInheritDoc") public abstract class BaseExtension implements AndroidConfig { private String target; private FullRevision buildToolsRevision; private List libraryRequests = Lists.newArrayList(); /** Default config, shared by all flavors. */ final ProductFlavor defaultConfig; /** Options for aapt, tool for packaging resources. */ final AaptOptions aaptOptions; /** Lint options. */ final LintOptions lintOptions; /** Dex options. */ final DexOptions dexOptions; /** Options for running tests. */ final TestOptions testOptions; /** Compile options */ final CompileOptions compileOptions; /** Packaging options. */ final PackagingOptions packagingOptions; /** JaCoCo options. */ final JacocoOptions jacoco; /** * APK splits options. * *

See APK Splits. */ final Splits splits; /** All product flavors used by this project. */ final NamedDomainObjectContainer productFlavors; /** Build types used by this project. */ final NamedDomainObjectContainer buildTypes; /** Signing configs used by this project. */ final NamedDomainObjectContainer signingConfigs; private ExtraModelInfo extraModelInfo; protected Project project; /** Adb options */ final AdbOptions adbOptions; /** A prefix to be used when creating new resources. Used by Studio */ String resourcePrefix; List flavorDimensionList; private String defaultPublishConfig = "release"; private boolean publishNonDefault = false; private Action variantFilter; private final List deviceProviderList = Lists.newArrayList(); private final List testServerList = Lists.newArrayList(); private final List transforms = Lists.newArrayList(); // secondary dependencies for the custom transform. private final List> transformDependencies = Lists.newArrayList(); private final AndroidBuilder androidBuilder; private final SdkHandler sdkHandler; protected Logger logger; private boolean isWritable = true; /** Data Binding options */ final DataBindingOptions dataBinding; /** * The source sets container. */ final NamedDomainObjectContainer sourceSetsContainer; BaseExtension( @NonNull final ProjectInternal project, @NonNull Instantiator instantiator, @NonNull AndroidBuilder androidBuilder, @NonNull SdkHandler sdkHandler, @NonNull NamedDomainObjectContainer buildTypes, @NonNull NamedDomainObjectContainer productFlavors, @NonNull NamedDomainObjectContainer signingConfigs, @NonNull ExtraModelInfo extraModelInfo, final boolean isLibrary) { this.androidBuilder = androidBuilder; this.sdkHandler = sdkHandler; this.buildTypes = buildTypes; //noinspection unchecked this.productFlavors = (NamedDomainObjectContainer) productFlavors; this.signingConfigs = signingConfigs; this.extraModelInfo = extraModelInfo; this.project = project; logger = Logging.getLogger(this.getClass()); defaultConfig = instantiator.newInstance(ProductFlavor.class, BuilderConstants.MAIN, project, instantiator, project.getLogger()); aaptOptions = instantiator.newInstance(AaptOptions.class); dexOptions = instantiator.newInstance(DexOptions.class); lintOptions = instantiator.newInstance(LintOptions.class); testOptions = instantiator.newInstance(TestOptions.class); compileOptions = instantiator.newInstance(CompileOptions.class); packagingOptions = instantiator.newInstance(PackagingOptions.class); jacoco = instantiator.newInstance(JacocoOptions.class); adbOptions = instantiator.newInstance(AdbOptions.class); splits = instantiator.newInstance(Splits.class, instantiator); dataBinding = instantiator.newInstance(DataBindingOptions.class); sourceSetsContainer = project.container(AndroidSourceSet.class, new AndroidSourceSetFactory(instantiator, project, isLibrary)); sourceSetsContainer.whenObjectAdded(new Action() { @Override public void execute(AndroidSourceSet sourceSet) { ConfigurationContainer configurations = project.getConfigurations(); createConfiguration( configurations, sourceSet.getCompileConfigurationName(), "Classpath for compiling the " + sourceSet.getName() + " sources."); String packageConfigDescription; if (isLibrary) { packageConfigDescription = "Classpath only used when publishing '" + sourceSet.getName() + "'."; } else { packageConfigDescription = "Classpath packaged with the compiled '" + sourceSet.getName() + "' classes."; } createConfiguration( configurations, sourceSet.getPackageConfigurationName(), packageConfigDescription); createConfiguration( configurations, sourceSet.getProvidedConfigurationName(), "Classpath for only compiling the " + sourceSet.getName() + " sources."); createConfiguration( configurations, sourceSet.getWearAppConfigurationName(), "Link to a wear app to embed for object '" + sourceSet.getName() + "'."); sourceSet.setRoot(String.format("src/%s", sourceSet.getName())); } }); sourceSetsContainer.create(defaultConfig.getName()); setDefaultConfigValues(); } private void setDefaultConfigValues() { Set densities = Density.getRecommendedValuesForDevice(); Set strings = Sets.newHashSetWithExpectedSize(densities.size()); for (Density density : densities) { strings.add(density.getResourceValue()); } defaultConfig.setGeneratedDensities(strings); } /** * Disallow further modification on the extension. */ public void disableWrite() { isWritable = false; } protected void checkWritability() { if (!isWritable) { throw new GradleException( "Android tasks have already been created.\n" + "This happens when calling android.applicationVariants,\n" + "android.libraryVariants or android.testVariants.\n" + "Once these methods are called, it is not possible to\n" + "continue configuring the model."); } } protected void createConfiguration( @NonNull ConfigurationContainer configurations, @NonNull String configurationName, @NonNull String configurationDescription) { logger.info("Creating configuration {}", configurationName); Configuration configuration = configurations.findByName(configurationName); if (configuration == null) { configuration = configurations.create(configurationName); } configuration.setVisible(false); configuration.setDescription(configurationDescription); } /** * Sets the compile SDK version, based on full SDK version string, e.g. * android-21 for Lollipop. */ public void compileSdkVersion(String version) { checkWritability(); this.target = version; } /** * Sets the compile SDK version, based on API level, e.g. 21 for Lollipop. */ public void compileSdkVersion(int apiLevel) { compileSdkVersion("android-" + apiLevel); } public void setCompileSdkVersion(int apiLevel) { compileSdkVersion(apiLevel); } public void setCompileSdkVersion(String target) { compileSdkVersion(target); } /** * Request the use a of Library. The library is then added to the classpath. * @param name the name of the library. */ public void useLibrary(String name) { useLibrary(name, true); } /** * Request the use a of Library. The library is then added to the classpath. * @param name the name of the library. * @param required if using the library requires a manifest entry, the entry will * indicate that the library is not required. */ public void useLibrary(String name, boolean required) { libraryRequests.add(new LibraryRequest(name, required)); } public void buildToolsVersion(String version) { checkWritability(); buildToolsRevision = FullRevision.parseRevision(version); } /** * Required. Version of the build tools to use. * *

Value assigned to this property is parsed and stored in a normalized form, so reading it * back may give a slightly different string. */ @Override public String getBuildToolsVersion() { return buildToolsRevision.toString(); } public void setBuildToolsVersion(String version) { buildToolsVersion(version); } /** * Configures build types. */ public void buildTypes(Action> action) { checkWritability(); action.execute(buildTypes); } /** * Configures product flavors. */ public void productFlavors(Action> action) { checkWritability(); action.execute(productFlavors); } /** * Configures signing configs. */ public void signingConfigs(Action> action) { checkWritability(); action.execute(signingConfigs); } /** * Specifies names of flavor dimensions. * *

See Multi-flavor variants. */ public void flavorDimensions(String... dimensions) { checkWritability(); flavorDimensionList = Arrays.asList(dimensions); } /** * Configures source sets. * *

Note that the Android plugin uses its own implementation of source sets, * {@link AndroidSourceSet}. */ public void sourceSets(Action> action) { checkWritability(); action.execute(sourceSetsContainer); } /** * All source sets. Note that the Android plugin uses its own implementation of * source sets, {@link AndroidSourceSet}. */ @Override public NamedDomainObjectContainer getSourceSets() { return sourceSetsContainer; } /** * The default configuration, inherited by all product flavors (if any are defined). */ public void defaultConfig(Action action) { checkWritability(); action.execute(defaultConfig); } /** * Configures aapt options. */ public void aaptOptions(Action action) { checkWritability(); action.execute(aaptOptions); } /** * Configures dex options. */ public void dexOptions(Action action) { checkWritability(); action.execute(dexOptions); } /** * Configures lint options. */ public void lintOptions(Action action) { checkWritability(); action.execute(lintOptions); } /** Configures test options. */ public void testOptions(Action action) { checkWritability(); action.execute(testOptions); } /** * Configures compile options. */ public void compileOptions(Action action) { checkWritability(); action.execute(compileOptions); } /** * Configures packaging options. */ public void packagingOptions(Action action) { checkWritability(); action.execute(packagingOptions); } /** * Configures JaCoCo options. */ public void jacoco(Action action) { checkWritability(); action.execute(jacoco); } /** * Configures adb options. */ public void adbOptions(Action action) { checkWritability(); action.execute(adbOptions); } /** * Configures APK splits. */ public void splits(Action action) { checkWritability(); action.execute(splits); } /** * Configures data binding options */ public void dataBinding(Action action) { checkWritability(); action.execute(dataBinding); } /** {@inheritDoc} */ @Override public DataBindingOptions getDataBinding() { return dataBinding; } public void deviceProvider(DeviceProvider deviceProvider) { checkWritability(); deviceProviderList.add(deviceProvider); } @Override @NonNull public List getDeviceProviders() { return deviceProviderList; } public void testServer(TestServer testServer) { checkWritability(); testServerList.add(testServer); } @Override @NonNull public List getTestServers() { return testServerList; } public void registerTransform(@NonNull Transform transform, Object... dependencies) { transforms.add(transform); transformDependencies.add(Arrays.asList(dependencies)); } @Override @NonNull public List getTransforms() { return ImmutableList.copyOf(transforms); } @Override @NonNull public List> getTransformsDependencies() { return ImmutableList.copyOf(transformDependencies); } /** {@inheritDoc} */ @Override public Collection getProductFlavors() { return productFlavors; } /** {@inheritDoc} */ @Override public Collection getBuildTypes() { return buildTypes; } /** {@inheritDoc} */ @Override public Collection getSigningConfigs() { return signingConfigs; } public void defaultPublishConfig(String value) { setDefaultPublishConfig(value); } public void publishNonDefault(boolean value) { publishNonDefault = value; } /** * Name of the configuration used to build the default artifact of this project. * *

See * Referencing a Library */ @Override public String getDefaultPublishConfig() { return defaultPublishConfig; } public void setDefaultPublishConfig(String value) { defaultPublishConfig = value; } /** * Whether to publish artifacts for all configurations, not just the default one. * *

See * Referencing a Library */ @Override public boolean getPublishNonDefault() { return publishNonDefault; } public void variantFilter(Action filter) { setVariantFilter(filter); } public void setVariantFilter(Action filter) { variantFilter = filter; } /** * Callback to control which variants should be excluded. * *

The {@link Action} is passed a single object of type * {@link com.android.build.gradle.api.VariantFilter}. It should set the * {@link VariantFilter#setIgnore(boolean)} flag to filter out the given variant. */ @Override public Action getVariantFilter() { return variantFilter; } /** {@inheritDoc} */ @Override public AdbOptions getAdbOptions() { return adbOptions; } /** {@inheritDoc} */ @Override public String getResourcePrefix() { return resourcePrefix; } /** * Returns the names of flavor dimensions. * *

See Multi-flavor variants. */ @Override public List getFlavorDimensionList() { return flavorDimensionList; } /** {@inheritDoc} */ @Override public boolean getGeneratePureSplits() { return generatePureSplits; } public void resourcePrefix(String prefix) { resourcePrefix = prefix; } public abstract void addVariant(BaseVariant variant); public void registerArtifactType(@NonNull String name, boolean isTest, int artifactType) { extraModelInfo.registerArtifactType(name, isTest, artifactType); } public void registerBuildTypeSourceProvider( @NonNull String name, @NonNull BuildType buildType, @NonNull SourceProvider sourceProvider) { extraModelInfo.registerBuildTypeSourceProvider(name, buildType, sourceProvider); } public void registerProductFlavorSourceProvider( @NonNull String name, @NonNull ProductFlavor productFlavor, @NonNull SourceProvider sourceProvider) { extraModelInfo.registerProductFlavorSourceProvider(name, productFlavor, sourceProvider); } public void registerJavaArtifact( @NonNull String name, @NonNull BaseVariant variant, @NonNull String assembleTaskName, @NonNull String javaCompileTaskName, @NonNull Collection generatedSourceFolders, @NonNull Iterable ideSetupTaskNames, @NonNull Configuration configuration, @NonNull File classesFolder, @NonNull File javaResourceFolder, @Nullable SourceProvider sourceProvider) { extraModelInfo.registerJavaArtifact(name, variant, assembleTaskName, javaCompileTaskName, generatedSourceFolders, ideSetupTaskNames, configuration, classesFolder, javaResourceFolder, sourceProvider); } public void registerMultiFlavorSourceProvider( @NonNull String name, @NonNull String flavorName, @NonNull SourceProvider sourceProvider) { extraModelInfo.registerMultiFlavorSourceProvider(name, flavorName, sourceProvider); } @NonNull public SourceProvider wrapJavaSourceSet(@NonNull SourceSet sourceSet) { return new SourceSetSourceProviderWrapper(sourceSet); } /** * Required. Compile SDK version. * *

Your code will be compiled against the android.jar from this API level. You should * generally use the most up-to-date SDK version here. Use the Lint tool to make sure you don't * use APIs not available in earlier platform version without checking. * *

Setter can be called with a string like "android-21" or a number. * *

Value assigned to this property is parsed and stored in a normalized form, so reading it * back may give a slightly different string. */ @Override public String getCompileSdkVersion() { return target; } @Override public FullRevision getBuildToolsRevision() { return buildToolsRevision; } @Override public Collection getLibraryRequests() { return libraryRequests; } /** * Returns the SDK directory used. */ public File getSdkDirectory() { return sdkHandler.getSdkFolder(); } /** * ReturnS the NDK directory used. */ public File getNdkDirectory() { return sdkHandler.getNdkFolder(); } public List getBootClasspath() { ensureTargetSetup(); return androidBuilder.getBootClasspath(false); } public File getAdbExe() { return sdkHandler.getSdkInfo().getAdb(); } public File getDefaultProguardFile(String name) { File sdkDir = sdkHandler.getAndCheckSdkFolder(); return new File(sdkDir, SdkConstants.FD_TOOLS + File.separatorChar + SdkConstants.FD_PROGUARD + File.separatorChar + name); } // --------------- // TEMP for compatibility // by default, we do not generate pure splits boolean generatePureSplits = false; public void generatePureSplits(boolean flag) { setGeneratePureSplits(flag); } public void setGeneratePureSplits(boolean flag) { if (flag) { logger.warn("Pure splits are not supported by PlayStore yet."); } this.generatePureSplits = flag; } private boolean enforceUniquePackageName = true; public void enforceUniquePackageName(boolean value) { if (!value) { LoggingUtil.displayDeprecationWarning(logger, project, "Support for libraries with same package name is deprecated and will be removed in a future release."); } enforceUniquePackageName = value; } public void setEnforceUniquePackageName(boolean value) { enforceUniquePackageName(value); } @Override public boolean getEnforceUniquePackageName() { return enforceUniquePackageName; } /** {@inheritDoc} */ @Override public ProductFlavor getDefaultConfig() { return defaultConfig; } /** {@inheritDoc} */ @Override public AaptOptions getAaptOptions() { return aaptOptions; } /** {@inheritDoc} */ @Override public CompileOptions getCompileOptions() { return compileOptions; } /** {@inheritDoc} */ @Override public DexOptions getDexOptions() { return dexOptions; } /** {@inheritDoc} */ @Override public JacocoOptions getJacoco() { return jacoco; } /** {@inheritDoc} */ @Override public LintOptions getLintOptions() { return lintOptions; } /** {@inheritDoc} */ @Override public PackagingOptions getPackagingOptions() { return packagingOptions; } /** {@inheritDoc} */ @Override public Splits getSplits() { return splits; } /** {@inheritDoc} */ @Override public TestOptions getTestOptions() { return testOptions; } private void ensureTargetSetup() { // check if the target has been set. TargetInfo targetInfo = androidBuilder.getTargetInfo(); if (targetInfo == null) { sdkHandler.initTarget( getCompileSdkVersion(), buildToolsRevision, libraryRequests, androidBuilder); } } // For compatibility with LibraryExtension. @Override public Boolean getPackageBuildConfig() { throw new GradleException("packageBuildConfig is not supported."); } @Override public Collection getAidlPackageWhiteList() { throw new GradleException("aidlPackageWhiteList is not supported."); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy