Gradle 工具的源码研究
Gradle 工具源碼不是gradle wrapper 源碼
安裝android studio之后,Gradle 工具被緩存到 user/.gradle/cache/module-2/下面,不同的AS,緩存具體路徑還不一樣。
對(duì)于gradle-2.3.3.jar 源碼:
Context類代碼:
package com.android.build.api.transform;import java.io.File; import org.gradle.api.logging.LoggingManager;public abstract interface Context {public abstract LoggingManager getLogging();public abstract File getTemporaryDir();public abstract String getPath(); }QualifiedContent代碼:
package com.android.build.api.transform;import java.io.File; import java.util.Set;public abstract interface QualifiedContent {public abstract String getName();public abstract File getFile();public abstract Set<ContentType> getContentTypes();public abstract Set<? super Scope> getScopes();public static abstract interface ContentType{public abstract String name();public abstract int getValue();}public static enum DefaultContentTypeimplements QualifiedContent.ContentType{CLASSES(1), RESOURCES(2);private final int value;private DefaultContentType(int value){this.value = value;}public int getValue(){return this.value;}}public static abstract interface ScopeType{public abstract String name();public abstract int getValue();}public static enum Scopeimplements QualifiedContent.ScopeType{PROJECT(1), PROJECT_LOCAL_DEPS(2), SUB_PROJECTS(4), SUB_PROJECTS_LOCAL_DEPS(8), EXTERNAL_LIBRARIES(16), TESTED_CODE(32), PROVIDED_ONLY(64);private final int value;private Scope(int value){this.value = value;}public int getValue(){return this.value;}} }JarInput代碼:
package com.android.build.api.transform;public abstract interface JarInputextends QualifiedContent {public abstract Status getStatus(); }Transform類:
package com.android.build.api.transform;import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.Set;public abstract class Transform {public abstract String getName();public abstract Set<QualifiedContent.ContentType> getInputTypes();public Set<QualifiedContent.ContentType> getOutputTypes(){return getInputTypes();}public abstract Set<? super QualifiedContent.Scope> getScopes();public Set<? super QualifiedContent.Scope> getReferencedScopes(){return ImmutableSet.of();}@Deprecatedpublic Collection<File> getSecondaryFileInputs(){return ImmutableList.of();}public Collection<SecondaryFile> getSecondaryFiles(){return ImmutableList.of();}public Collection<File> getSecondaryFileOutputs(){return ImmutableList.of();}public Collection<File> getSecondaryDirectoryOutputs(){return ImmutableList.of();}public Map<String, Object> getParameterInputs(){return ImmutableMap.of();}public abstract boolean isIncremental();@Deprecatedpublic void transform(Context context, Collection<TransformInput> inputs, Collection<TransformInput> referencedInputs, TransformOutputProvider outputProvider, boolean isIncremental)throws IOException, TransformException, InterruptedException{}public void transform(TransformInvocation transformInvocation)throws TransformException, InterruptedException, IOException{transform(transformInvocation.getContext(), transformInvocation.getInputs(), transformInvocation.getReferencedInputs(), transformInvocation.getOutputProvider(), transformInvocation.isIncremental());} }TransformInput類代碼:
package com.android.build.api.transform;import java.util.Collection;public abstract interface TransformInput {public abstract Collection<JarInput> getJarInputs();public abstract Collection<DirectoryInput> getDirectoryInputs(); }TransformInvocation代碼:
package com.android.build.api.transform;import java.util.Collection;public abstract interface TransformInvocation {public abstract Context getContext();public abstract Collection<TransformInput> getInputs();public abstract Collection<TransformInput> getReferencedInputs();public abstract Collection<SecondaryInput> getSecondaryInputs();public abstract TransformOutputProvider getOutputProvider();public abstract boolean isIncremental(); }TransformOutputProvider代碼:
package com.android.build.api.transform;import java.io.File; import java.io.IOException; import java.util.Set;public abstract interface TransformOutputProvider {public abstract void deleteAll()throws IOException;public abstract File getContentLocation(String paramString, Set<QualifiedContent.ContentType> paramSet, Set<? super QualifiedContent.Scope> paramSet1, Format paramFormat); }看到 gradle.jar 定義了加載plugin 方法,沒(méi)有看到加載到哪些plugin,沒(méi)有看到加載?com.android.application plugin
-----------------------------------------------------------------------------------------------------
gradle.2.2.3.jar 源碼:
android.properties
implementation-class=com.android.build.gradle.AppPluginandroid-library.properties
implementation-class=com.android.build.gradle.LibraryPluginandroid-reporting.properties
implementation-class=com.android.build.gradle.ReportingPluginandroid.application.properties
implementation-class=com.android.build.gradle.AppPluginexternals.build.properties
implementation-class=com.android.build.gradle.internal.externalBuild.ExternalBuildPluginProductFlavorFactory類代碼:
public class ProductFlavorFactory implements NamedDomainObjectFactory<ProductFlavor> {@NonNullprivate final Instantiator instantiator;@NonNullprivate final Project project;@NonNullprivate final Logger logger;@NonNullprivate final ErrorReporter errorReporter;public ProductFlavorFactory(@NonNull Instantiator instantiator,@NonNull Project project,@NonNull Logger logger,@NonNull ErrorReporter errorReporter) {this.instantiator = instantiator;this.project = project;this.logger = logger;this.errorReporter = errorReporter;}@Overridepublic ProductFlavor create(String name) {return instantiator.newInstance(ProductFlavor.class,name, project, instantiator, logger, errorReporter);} }ExternalBuildPlugin類代碼:
/** Copyright (C) 2016 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.externalBuild;import com.android.build.gradle.internal.profile.ProfilerInitializer;import org.gradle.api.Plugin; import org.gradle.api.Project;/*** Gradle plugin for supporting InstantRun with external build system..** <p>* This plugin is private to the android build system and is not intented to be used directly in* end users projects.* </p>* Interfaces, DSL and tasks are subject to change without any notification.*/ public class ExternalBuildPlugin implements Plugin<Project> {@Overridepublic void apply(Project project) {final ExternalBuildExtension externalBuildExtension =project.getExtensions().create("externalBuild", ExternalBuildExtension.class);ProfilerInitializer.init(project);ExternalBuildTaskManager taskManager =new ExternalBuildTaskManager(project);project.afterEvaluate(project1 -> {try {taskManager.createTasks(externalBuildExtension);} catch (Exception e) {throw new RuntimeException(e);}});} }ApiObjectFactory類代碼:
/** Copyright (C) 2015 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;import com.android.annotations.NonNull; import com.android.build.gradle.BaseExtension; import com.android.build.gradle.TestedAndroidConfig; import com.android.build.gradle.api.BaseVariant; import com.android.build.gradle.internal.api.ReadOnlyObjectProvider; import com.android.build.gradle.internal.api.TestVariantImpl; import com.android.build.gradle.internal.api.TestedVariant; import com.android.build.gradle.internal.api.UnitTestVariantImpl; import com.android.build.gradle.internal.variant.ApplicationVariantFactory; import com.android.build.gradle.internal.variant.BaseVariantData; import com.android.build.gradle.internal.variant.TestVariantData; import com.android.build.gradle.internal.variant.TestedVariantData; import com.android.build.gradle.internal.variant.VariantFactory; import com.android.builder.core.AndroidBuilder;import org.gradle.internal.reflect.Instantiator;import static com.android.builder.core.VariantType.ANDROID_TEST; import static com.android.builder.core.VariantType.UNIT_TEST;/*** Factory to create ApiObject from VariantData.*/ public class ApiObjectFactory {@NonNullprivate final AndroidBuilder androidBuilder;@NonNullprivate final BaseExtension extension;@NonNullprivate final VariantFactory variantFactory;@NonNullprivate final Instantiator instantiator;@NonNullprivate final ReadOnlyObjectProvider readOnlyObjectProvider = new ReadOnlyObjectProvider();public ApiObjectFactory(@NonNull AndroidBuilder androidBuilder,@NonNull BaseExtension extension,@NonNull VariantFactory variantFactory,@NonNull Instantiator instantiator) {this.androidBuilder = androidBuilder;this.extension = extension;this.variantFactory = variantFactory;this.instantiator = instantiator;}public void create(BaseVariantData<?> variantData) {if (variantData.getType().isForTesting()) {// Testing variants are handled together with their "owners".return;}BaseVariant variantApi =variantFactory.createVariantApi(variantData, readOnlyObjectProvider);if (variantFactory.hasTestScope()) {TestVariantData androidTestVariantData =((TestedVariantData) variantData).getTestVariantData(ANDROID_TEST);if (androidTestVariantData != null) {TestVariantImpl androidTestVariant = instantiator.newInstance(TestVariantImpl.class,androidTestVariantData,variantApi,androidBuilder,readOnlyObjectProvider);// add the test output.ApplicationVariantFactory.createApkOutputApiObjects(instantiator,androidTestVariantData,androidTestVariant);((TestedAndroidConfig) extension).getTestVariants().add(androidTestVariant);((TestedVariant) variantApi).setTestVariant(androidTestVariant);}TestVariantData unitTestVariantData =((TestedVariantData) variantData).getTestVariantData(UNIT_TEST);if (unitTestVariantData != null) {UnitTestVariantImpl unitTestVariant = instantiator.newInstance(UnitTestVariantImpl.class,unitTestVariantData,variantApi,androidBuilder,readOnlyObjectProvider);((TestedAndroidConfig) extension).getUnitTestVariants().add(unitTestVariant);((TestedVariant) variantApi).setUnitTestVariant(unitTestVariant);}}// Only add the variant API object to the domain object set once it's been fully// initialized.extension.addVariant(variantApi);} }NativeLibraryFactoryImpl類代碼:
Version類:
package com.android.build.gradle.internal;public final class Version {private Version() {}public static final String ANDROID_GRADLE_PLUGIN_VERSION = "2.2.3";public static final String ANDROID_GRADLE_COMPONENT_PLUGIN_VERSION = "0.8.3"; }AppExtension類代碼:
package com.android.build.gradle;import com.android.annotations.NonNull; import com.android.build.gradle.api.ApplicationVariant; import com.android.build.gradle.api.BaseVariant; import com.android.build.gradle.internal.ExtraModelInfo; import com.android.build.gradle.internal.SdkHandler; import com.android.build.gradle.internal.dsl.BuildType; import com.android.build.gradle.internal.dsl.ProductFlavor; import com.android.build.gradle.internal.dsl.SigningConfig; import com.android.builder.core.AndroidBuilder;import org.gradle.api.DomainObjectSet; import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.internal.DefaultDomainObjectSet; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.internal.reflect.Instantiator;/*** {@code android} extension for {@code com.android.application} projects.*/ public class AppExtension extends TestedExtension {private final DefaultDomainObjectSet<ApplicationVariant> applicationVariantList= new DefaultDomainObjectSet<ApplicationVariant>(ApplicationVariant.class);public AppExtension(@NonNull ProjectInternal project, @NonNull Instantiator instantiator,@NonNull AndroidBuilder androidBuilder, @NonNull SdkHandler sdkHandler,@NonNull NamedDomainObjectContainer<BuildType> buildTypes,@NonNull NamedDomainObjectContainer<ProductFlavor> productFlavors,@NonNull NamedDomainObjectContainer<SigningConfig> signingConfigs,@NonNull ExtraModelInfo extraModelInfo, boolean isLibrary) {super(project, instantiator, androidBuilder, sdkHandler, buildTypes, productFlavors,signingConfigs, extraModelInfo, isLibrary);}/*** Returns the list of Application variants. Since the collections is built after evaluation, it* should be used with Gradle's <code>all</code> iterator to process future items.*/public DomainObjectSet<ApplicationVariant> getApplicationVariants() {return applicationVariantList;}@Overridepublic void addVariant(BaseVariant variant) {applicationVariantList.add((ApplicationVariant) variant);} }AppPlugin類代碼:
/** 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.annotations.NonNull; import com.android.build.gradle.internal.ApplicationTaskManager; import com.android.build.gradle.internal.DependencyManager; import com.android.build.gradle.internal.SdkHandler; import com.android.build.gradle.internal.TaskManager; import com.android.build.gradle.internal.ndk.NdkHandler; import com.android.build.gradle.internal.variant.ApplicationVariantFactory; import com.android.build.gradle.internal.variant.VariantFactory; import com.android.builder.core.AndroidBuilder;import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.internal.reflect.Instantiator; import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;import android.databinding.tool.DataBindingBuilder;import javax.inject.Inject;/*** Gradle plugin class for 'application' projects.*/ public class AppPlugin extends BasePlugin implements Plugin<Project> {@Injectpublic AppPlugin(Instantiator instantiator, ToolingModelBuilderRegistry registry) {super(instantiator, registry);}@Overrideprotected Class<? extends BaseExtension> getExtensionClass() {return AppExtension.class;}@Overrideprotected TaskManager createTaskManager(@NonNull Project project,@NonNull AndroidBuilder androidBuilder,@NonNull DataBindingBuilder dataBindingBuilder,@NonNull AndroidConfig extension,@NonNull SdkHandler sdkHandler,@NonNull NdkHandler ndkHandler,@NonNull DependencyManager dependencyManager,@NonNull ToolingModelBuilderRegistry toolingRegistry) {return new ApplicationTaskManager(project,androidBuilder,dataBindingBuilder,extension,sdkHandler,ndkHandler,dependencyManager,toolingRegistry);}@Overridepublic void apply(@NonNull Project project) {super.apply(project);}@Overrideprotected VariantFactory createVariantFactory() {return new ApplicationVariantFactory(instantiator, androidBuilder, extension);} }BaseExtension類代碼:
/** 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.annotations.NonNull; import com.android.annotations.Nullable; import com.android.build.api.transform.Transform; import com.android.build.api.variant.VariantFilter; import com.android.build.gradle.api.AndroidSourceSet; import com.android.build.gradle.api.BaseVariant; 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.DataBindingOptions; import com.android.build.gradle.internal.dsl.DexOptions; import com.android.build.gradle.internal.dsl.ExternalNativeBuild; 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.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.repository.Revision; import com.android.resources.Density; 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.** <p>This is never used directly. Instead,*<ul>* <li>Plugin <code>com.android.application</code> uses {@link AppExtension}</li>* <li>Plugin <code>com.android.library</code> uses {@link LibraryExtension}</li>* <li>Plugin <code>com.android.test</code> uses {@link TestExtension}</li>* </ul>*/ // All the public methods are meant to be exposed in the DSL. // We can't yet lambdas in this class (yet), because the DSL reference generator doesn't understand // them. @SuppressWarnings({"UnnecessaryInheritDoc", "WeakerAccess", "unused", "Convert2Lambda"}) public abstract class BaseExtension implements AndroidConfig {/** Secondary dependencies for the custom transform. */private final List<List<Object>> transformDependencies = Lists.newArrayList();private final AndroidBuilder androidBuilder;private final SdkHandler sdkHandler;private final ProductFlavor defaultConfig;private final AaptOptions aaptOptions;private final LintOptions lintOptions;private final ExternalNativeBuild externalNativeBuild;private final DexOptions dexOptions;private final TestOptions testOptions;private final CompileOptions compileOptions;private final PackagingOptions packagingOptions;private final JacocoOptions jacoco;private final Splits splits;private final AdbOptions adbOptions;private final NamedDomainObjectContainer<ProductFlavor> productFlavors;private final NamedDomainObjectContainer<BuildType> buildTypes;private final NamedDomainObjectContainer<SigningConfig> signingConfigs;private final List<DeviceProvider> deviceProviderList = Lists.newArrayList();private final List<TestServer> testServerList = Lists.newArrayList();private final List<Transform> transforms = Lists.newArrayList();private final DataBindingOptions dataBinding;private final NamedDomainObjectContainer<AndroidSourceSet> sourceSetsContainer;private String target;private Revision buildToolsRevision;private List<LibraryRequest> libraryRequests = Lists.newArrayList();private List<String> flavorDimensionList;private String resourcePrefix;private ExtraModelInfo extraModelInfo;private String defaultPublishConfig = "release";private boolean publishNonDefault = false;private Action<VariantFilter> variantFilter;protected Logger logger;private boolean isWritable = true;protected Project project;BaseExtension(@NonNull final ProjectInternal project,@NonNull Instantiator instantiator,@NonNull AndroidBuilder androidBuilder,@NonNull SdkHandler sdkHandler,@NonNull NamedDomainObjectContainer<BuildType> buildTypes,@NonNull NamedDomainObjectContainer<ProductFlavor> productFlavors,@NonNull NamedDomainObjectContainer<SigningConfig> signingConfigs,@NonNull ExtraModelInfo extraModelInfo,final boolean isLibrary) {this.androidBuilder = androidBuilder;this.sdkHandler = sdkHandler;this.buildTypes = buildTypes;//noinspection uncheckedthis.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(), extraModelInfo);aaptOptions = instantiator.newInstance(AaptOptions.class);dexOptions = instantiator.newInstance(DexOptions.class, extraModelInfo);lintOptions = instantiator.newInstance(LintOptions.class);externalNativeBuild = instantiator.newInstance(ExternalNativeBuild.class, instantiator, project);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<AndroidSourceSet>() {@Overridepublic 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() + "'.");createConfiguration(configurations,sourceSet.getAnnotationProcessorConfigurationName(),"Classpath for the annotation processor for '" + sourceSet.getName() +"'.");sourceSet.setRoot(String.format("src/%s", sourceSet.getName()));}});sourceSetsContainer.create(defaultConfig.getName());setDefaultConfigValues();}private void setDefaultConfigValues() {Set<Density> densities = Density.getRecommendedValuesForDevice();Set<String> strings = Sets.newHashSetWithExpectedSize(densities.size());for (Density density : densities) {strings.add(density.getResourceValue());}defaultConfig.getVectorDrawables().setGeneratedDensities(strings);defaultConfig.getVectorDrawables().setUseSupportLibrary(false);}/*** 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.* <code>android-21</code> 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();//The underlying Revision class has the maven artifact semantic,// so 20 is not the same as 20.0. For the build tools revision this// is not the desired behavior, so normalize e.g. to 20.0.0.buildToolsRevision = Revision.parseRevision(version, Revision.Precision.MICRO);}/*** <strong>Required.</strong> Version of the build tools to use.** <p>Value assigned to this property is parsed and stored in a normalized form, so reading it* back may give a slightly different string.*/@Overridepublic String getBuildToolsVersion() {return buildToolsRevision.toString();}public void setBuildToolsVersion(String version) {buildToolsVersion(version);}/*** Configures build types.*/public void buildTypes(Action<? super NamedDomainObjectContainer<BuildType>> action) {checkWritability();action.execute(buildTypes);}/*** Configures product flavors.*/public void productFlavors(Action<? super NamedDomainObjectContainer<ProductFlavor>> action) {checkWritability();action.execute(productFlavors);}/*** Configures signing configs.*/public void signingConfigs(Action<? super NamedDomainObjectContainer<SigningConfig>> action) {checkWritability();action.execute(signingConfigs);}/*** Specifies names of flavor dimensions.** <p>See <a href="http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Multi-flavor-variants">Multi-flavor variants</a>.*/public void flavorDimensions(String... dimensions) {checkWritability();flavorDimensionList = Arrays.asList(dimensions);}/*** Configures source sets.** <p>Note that the Android plugin uses its own implementation of source sets,* {@link AndroidSourceSet}.*/public void sourceSets(Action<NamedDomainObjectContainer<AndroidSourceSet>> action) {checkWritability();action.execute(sourceSetsContainer);}/*** All source sets. Note that the Android plugin uses its own implementation of* source sets, {@link AndroidSourceSet}.*/@Overridepublic NamedDomainObjectContainer<AndroidSourceSet> getSourceSets() {return sourceSetsContainer;}/*** The default configuration, inherited by all product flavors (if any are defined).*/public void defaultConfig(Action<ProductFlavor> action) {checkWritability();action.execute(defaultConfig);}/*** Configures aapt options.*/public void aaptOptions(Action<AaptOptions> action) {checkWritability();action.execute(aaptOptions);}/*** Configures dex options.*/public void dexOptions(Action<DexOptions> action) {checkWritability();action.execute(dexOptions);}/*** Configures lint options.*/public void lintOptions(Action<LintOptions> action) {checkWritability();action.execute(lintOptions);}/*** Configures external native build options.*/public void externalNativeBuild(Action<ExternalNativeBuild> action) {checkWritability();action.execute(externalNativeBuild);}/** Configures test options. */public void testOptions(Action<TestOptions> action) {checkWritability();action.execute(testOptions);}/*** Configures compile options.*/public void compileOptions(Action<CompileOptions> action) {checkWritability();action.execute(compileOptions);}/*** Configures packaging options.*/public void packagingOptions(Action<PackagingOptions> action) {checkWritability();action.execute(packagingOptions);}/*** Configures JaCoCo options.*/public void jacoco(Action<JacocoOptions> action) {checkWritability();action.execute(jacoco);}/*** Configures adb options.*/public void adbOptions(Action<AdbOptions> action) {checkWritability();action.execute(adbOptions);}/*** Configures APK splits.*/public void splits(Action<Splits> action) {checkWritability();action.execute(splits);}/*** Configures data binding options.*/public void dataBinding(Action<DataBindingOptions> action) {checkWritability();action.execute(dataBinding);}/** {@inheritDoc} */@Overridepublic DataBindingOptions getDataBinding() {return dataBinding;}public void deviceProvider(DeviceProvider deviceProvider) {checkWritability();deviceProviderList.add(deviceProvider);}@Override@NonNullpublic List<DeviceProvider> getDeviceProviders() {return deviceProviderList;}public void testServer(TestServer testServer) {checkWritability();testServerList.add(testServer);}@Override@NonNullpublic List<TestServer> getTestServers() {return testServerList;}public void registerTransform(@NonNull Transform transform, Object... dependencies) {transforms.add(transform);transformDependencies.add(Arrays.asList(dependencies));}@Override@NonNullpublic List<Transform> getTransforms() {return ImmutableList.copyOf(transforms);}@Override@NonNullpublic List<List<Object>> getTransformsDependencies() {return ImmutableList.copyOf(transformDependencies);}/** {@inheritDoc} */@Overridepublic Collection<ProductFlavor> getProductFlavors() {return productFlavors;}/** {@inheritDoc} */@Overridepublic Collection<BuildType> getBuildTypes() {return buildTypes;}/** {@inheritDoc} */@Overridepublic Collection<SigningConfig> 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.** <p>See <a href="http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Referencing-a-Library">* Referencing a Library</a>*/@Overridepublic String getDefaultPublishConfig() {return defaultPublishConfig;}public void setDefaultPublishConfig(String value) {defaultPublishConfig = value;}/*** Whether to publish artifacts for all configurations, not just the default one.** <p>See <a href="http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Referencing-a-Library">* Referencing a Library</a>*/@Overridepublic boolean getPublishNonDefault() {return publishNonDefault;}public void variantFilter(Action<VariantFilter> filter) {setVariantFilter(filter);}public void setVariantFilter(Action<VariantFilter> filter) {variantFilter = filter;}/*** Callback to control which variants should be excluded.** <p>The {@link Action} is passed a single object of type {@link VariantFilter}.* It should set the {@link VariantFilter#setIgnore(boolean)} flag to filter out the* given variant.*/@Overridepublic Action<VariantFilter> getVariantFilter() {return variantFilter;}/** {@inheritDoc} */@Overridepublic AdbOptions getAdbOptions() {return adbOptions;}/** {@inheritDoc} */@Overridepublic String getResourcePrefix() {return resourcePrefix;}/*** Returns the names of flavor dimensions.** <p>See <a href="http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Multi-flavor-variants">Multi-flavor variants</a>.*/@Overridepublic List<String> getFlavorDimensionList() {return flavorDimensionList;}/** {@inheritDoc} */@Overridepublic 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<File> generatedSourceFolders,@NonNull Iterable<String> 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);}@NonNullpublic static SourceProvider wrapJavaSourceSet(@NonNull SourceSet sourceSet) {return new SourceSetSourceProviderWrapper(sourceSet);}/*** <strong>Required.</strong> Compile SDK version.** <p>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.** <p>Setter can be called with a string like "android-21" or a number.** <p>Value assigned to this property is parsed and stored in a normalized form, so reading it* back may give a slightly different string.*/@Overridepublic String getCompileSdkVersion() {return target;}@Overridepublic Revision getBuildToolsRevision() {return buildToolsRevision;}@Overridepublic Collection<LibraryRequest> 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<File> getBootClasspath() {ensureTargetSetup();return androidBuilder.getBootClasspath(false);}/*** The adb executable from the compile SDK.*/public File getAdbExecutable() {return sdkHandler.getSdkInfo().getAdb();}@Deprecatedpublic File getAdbExe() {return getAdbExecutable();}public File getDefaultProguardFile(String name) {return ProguardFiles.getDefaultProguardFile(name, project);}// ---------------// TEMP for compatibility// by default, we do not generate pure splitsboolean 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);}@Overridepublic boolean getEnforceUniquePackageName() {return enforceUniquePackageName;}/** {@inheritDoc} */@Overridepublic ProductFlavor getDefaultConfig() {return defaultConfig;}/** {@inheritDoc} */@Overridepublic AaptOptions getAaptOptions() {return aaptOptions;}/** {@inheritDoc} */@Overridepublic CompileOptions getCompileOptions() {return compileOptions;}/** {@inheritDoc} */@Overridepublic DexOptions getDexOptions() {return dexOptions;}/** {@inheritDoc} */@Overridepublic JacocoOptions getJacoco() {return jacoco;}/** {@inheritDoc} */@Overridepublic LintOptions getLintOptions() {return lintOptions;}/** {@inheritDoc} */@Overridepublic ExternalNativeBuild getExternalNativeBuild() {return externalNativeBuild;}/** {@inheritDoc} */@Overridepublic PackagingOptions getPackagingOptions() {return packagingOptions;}/** {@inheritDoc} */@Overridepublic Splits getSplits() {return splits;}/** {@inheritDoc} */@Overridepublic 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,SdkHandler.useCachedSdk(project));}}// For compatibility with LibraryExtension.@Overridepublic Boolean getPackageBuildConfig() {throw new GradleException("packageBuildConfig is not supported.");}@Overridepublic Collection<String> getAidlPackageWhiteList() {throw new GradleException("aidlPackageWhiteList is not supported.");} }BasePlugin代碼:
/** 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 static com.android.builder.model.AndroidProject.FD_INTERMEDIATES; import static com.google.common.base.Preconditions.checkState; import static java.io.File.separator;import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.annotations.VisibleForTesting; import com.android.build.api.transform.Transform; import com.android.build.gradle.internal.ApiObjectFactory; import com.android.build.gradle.internal.BadPluginException; import com.android.build.gradle.internal.DependencyManager; import com.android.build.gradle.internal.ExecutionConfigurationUtil; import com.android.build.gradle.internal.ExtraModelInfo; import com.android.build.gradle.internal.LibraryCache; import com.android.build.gradle.internal.LoggerWrapper; import com.android.build.gradle.internal.NativeLibraryFactoryImpl; import com.android.build.gradle.internal.SdkHandler; import com.android.build.gradle.internal.TaskContainerAdaptor; import com.android.build.gradle.internal.TaskManager; import com.android.build.gradle.internal.ToolingRegistryProvider; import com.android.build.gradle.internal.VariantManager; import com.android.build.gradle.internal.coverage.JacocoPlugin; import com.android.build.gradle.internal.dependency.VariantDependencies; import com.android.build.gradle.internal.dsl.BuildType; import com.android.build.gradle.internal.dsl.BuildTypeFactory; import com.android.build.gradle.internal.dsl.ProductFlavor; import com.android.build.gradle.internal.dsl.ProductFlavorFactory; import com.android.build.gradle.internal.dsl.SigningConfig; import com.android.build.gradle.internal.dsl.SigningConfigFactory; import com.android.build.gradle.internal.model.ModelBuilder; import com.android.build.gradle.internal.model.NativeModelBuilder; import com.android.build.gradle.internal.ndk.NdkHandler; import com.android.build.gradle.internal.pipeline.TransformTask; import com.android.build.gradle.internal.process.GradleJavaProcessExecutor; import com.android.build.gradle.internal.process.GradleProcessExecutor; import com.android.build.gradle.internal.profile.ProfilerInitializer; import com.android.build.gradle.internal.profile.RecordingBuildListener; import com.android.build.gradle.internal.transforms.DexTransform; import com.android.build.gradle.internal.variant.BaseVariantData; import com.android.build.gradle.internal.variant.VariantFactory; import com.android.build.gradle.tasks.ExternalNativeBuildTaskUtils; import com.android.build.gradle.tasks.ExternalNativeJsonGenerator; import com.android.build.gradle.tasks.JackPreDexTransform; import com.android.builder.Version; import com.android.builder.core.AndroidBuilder; import com.android.builder.core.BuilderConstants; import com.android.builder.internal.compiler.JackConversionCache; import com.android.builder.internal.compiler.PreDexCache; import com.android.builder.model.AndroidProject; import com.android.builder.model.SyncIssue; import com.android.builder.profile.ProcessRecorder; import com.google.wireless.android.sdk.stats.AndroidStudioStats; import com.google.wireless.android.sdk.stats.AndroidStudioStats.GradleBuildProfileSpan.ExecutionType; import com.android.builder.profile.ProcessRecorderFactory; import com.android.builder.profile.Recorder; import com.android.builder.profile.ThreadRecorder; import com.android.builder.sdk.SdkLibData; import com.android.builder.sdk.TargetInfo; import com.android.dx.command.dexer.Main; import com.android.ide.common.internal.ExecutorSingleton; import com.android.ide.common.repository.GradleVersion; import com.android.repository.api.Channel; import com.android.repository.api.Downloader; import com.android.repository.api.SettingsController; import com.android.repository.impl.downloader.LocalFileAwareDownloader; import com.android.repository.io.FileOpUtils; import com.android.sdklib.repository.legacy.LegacyDownloader; import com.android.utils.ILogger; import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap;import org.gradle.BuildListener; import org.gradle.BuildResult; import org.gradle.api.Action; import org.gradle.api.GradleException; import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.execution.TaskExecutionGraph; import org.gradle.api.execution.TaskExecutionGraphListener; import org.gradle.api.initialization.Settings; import org.gradle.api.invocation.Gradle; import org.gradle.api.logging.LogLevel; import org.gradle.api.plugins.JavaBasePlugin; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.tasks.StopExecutionException; import org.gradle.internal.reflect.Instantiator; import org.gradle.tooling.UnsupportedVersionException; import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;import android.databinding.tool.DataBindingBuilder;import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URL; import java.net.URLClassLoader; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.jar.Manifest;/*** Base class for all Android plugins*/ public abstract class BasePlugin implements ToolingRegistryProvider {private static final GradleVersion GRADLE_MIN_VERSION = GradleVersion.parse("2.14.1");/** default retirement age in days since its inception date for RC or beta versions. */private static final int DEFAULT_RETIREMENT_AGE_FOR_NON_RELEASE_IN_DAYS = 40;protected BaseExtension extension;protected VariantManager variantManager;protected TaskManager taskManager;protected Project project;protected SdkHandler sdkHandler;private NdkHandler ndkHandler;protected AndroidBuilder androidBuilder;protected DataBindingBuilder dataBindingBuilder;protected Instantiator instantiator;protected VariantFactory variantFactory;private ToolingModelBuilderRegistry registry;private JacocoPlugin jacocoPlugin;private LoggerWrapper loggerWrapper;private ExtraModelInfo extraModelInfo;private String creator;private DependencyManager dependencyManager;private boolean hasCreatedTasks = false;BasePlugin(@NonNull Instantiator instantiator, @NonNull ToolingModelBuilderRegistry registry) {this.instantiator = instantiator;this.registry = registry;creator = "Android Gradle " + Version.ANDROID_GRADLE_PLUGIN_VERSION;verifyRetirementAge();ModelBuilder.clearCaches();}/*** Verify that this plugin execution is within its public time range.*/private void verifyRetirementAge() {Manifest manifest;URLClassLoader cl = (URLClassLoader) getClass().getClassLoader();try {URL url = cl.findResource("META-INF/MANIFEST.MF");manifest = new Manifest(url.openStream());} catch (IOException ignore) {return;}int retirementAgeInDays =getRetirementAgeInDays(manifest.getMainAttributes().getValue("Plugin-Version"));// if this plugin version will never be outdated, return.if (retirementAgeInDays == -1) {return;}String inceptionDateAttr = manifest.getMainAttributes().getValue("Inception-Date");// when running in unit tests, etc... the manifest entries are absent.if (inceptionDateAttr == null) {return;}List<String> items = ImmutableList.copyOf(Splitter.on(':').split(inceptionDateAttr));GregorianCalendar inceptionDate = new GregorianCalendar(Integer.parseInt(items.get(0)),Integer.parseInt(items.get(1)), Integer.parseInt(items.get(2)));Calendar now = GregorianCalendar.getInstance();long nowTimestamp = now.getTimeInMillis();long inceptionTimestamp = inceptionDate.getTimeInMillis();long days = TimeUnit.DAYS.convert(nowTimestamp - inceptionTimestamp, TimeUnit.MILLISECONDS);if (days > retirementAgeInDays) {// this plugin is too old.String dailyOverride = System.getenv("ANDROID_DAILY_OVERRIDE");final MessageDigest crypt;try {crypt = MessageDigest.getInstance("SHA-1");} catch (NoSuchAlgorithmException e) {return;}crypt.reset();// encode the day, not the current time.try {crypt.update(String.format("%1$s:%2$s:%3$s",now.get(Calendar.YEAR),now.get(Calendar.MONTH),now.get(Calendar.DATE)).getBytes("utf8"));} catch (UnsupportedEncodingException e) {return;}String overrideValue = new BigInteger(1, crypt.digest()).toString(16);if (dailyOverride == null) {String message = "Plugin is too old, please update to a more recent version, or " +"set ANDROID_DAILY_OVERRIDE environment variable to \"" + overrideValue + '"';System.err.println(message);throw new RuntimeException(message);} else {if (!dailyOverride.equals(overrideValue)) {String message = "Plugin is too old and ANDROID_DAILY_OVERRIDE value is " +"also outdated, please use new value :\"" + overrideValue + '"';System.err.println(message);throw new RuntimeException(message);}}}}/*** Returns the retirement age for this plugin depending on its version string, or -1 if this* plugin version will never become obsolete* @param version the plugin full version, like 1.3.4-preview5 or 1.0.2 or 1.2.3-beta4* @return the retirement age in days or -1 if no retirement*/private static int getRetirementAgeInDays(@Nullable String version) {if (version == null || version.contains("rc") || version.contains("beta")|| version.contains("alpha") || version.contains("preview")) {return DEFAULT_RETIREMENT_AGE_FOR_NON_RELEASE_IN_DAYS;}return -1;}protected abstract Class<? extends BaseExtension> getExtensionClass();protected abstract VariantFactory createVariantFactory();protected abstract TaskManager createTaskManager(@NonNull Project project,@NonNull AndroidBuilder androidBuilder,@NonNull DataBindingBuilder dataBindingBuilder,@NonNull AndroidConfig extension,@NonNull SdkHandler sdkHandler,@NonNull NdkHandler ndkHandler,@NonNull DependencyManager dependencyManager,@NonNull ToolingModelBuilderRegistry toolingRegistry);/*** Return whether this plugin creates Android library. Should be overridden if true.*/protected boolean isLibrary() {return false;}@VisibleForTestingVariantManager getVariantManager() {return variantManager;}protected ILogger getLogger() {if (loggerWrapper == null) {loggerWrapper = new LoggerWrapper(project.getLogger());}return loggerWrapper;}protected void apply(@NonNull Project project) {checkPluginVersion();this.project = project;ExecutionConfigurationUtil.setThreadPoolSize(project);checkPathForErrors();checkModulesForErrors();ProfilerInitializer.init(project);String benchmarkName = AndroidGradleOptions.getBenchmarkName(project);String benchmarkMode = AndroidGradleOptions.getBenchmarkMode(project);if (benchmarkName != null && benchmarkMode != null) {ProcessRecorder.setBenchmark(benchmarkName, benchmarkMode);}AndroidStudioStats.GradleBuildProject.PluginType pluginType =AndroidStudioStats.GradleBuildProject.PluginType.UNKNOWN_PLUGIN_TYPE;if (this instanceof AppPlugin) {pluginType = AndroidStudioStats.GradleBuildProject.PluginType.APPLICATION;} else if (this instanceof LibraryPlugin) {pluginType = AndroidStudioStats.GradleBuildProject.PluginType.LIBRARY;} else if (this instanceof TestPlugin) {pluginType = AndroidStudioStats.GradleBuildProject.PluginType.TEST;}ProcessRecorder.getProject(project.getPath()).setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION).setAndroidPlugin(pluginType).setPluginGeneration(AndroidStudioStats.GradleBuildProject.PluginGeneration.FIRST);ThreadRecorder.get().record(ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,project.getPath(), null /*variantName*/, new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {configureProject();return null;}});ThreadRecorder.get().record(ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,project.getPath(), null /*variantName*/, new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {createExtension();return null;}});ThreadRecorder.get().record(ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,project.getPath(), null /*variantName*/, new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {createTasks();return null;}});// Apply additional pluginsfor (String plugin : AndroidGradleOptions.getAdditionalPlugins(project)) {project.apply(ImmutableMap.of("plugin", plugin));}}protected void configureProject() {extraModelInfo = new ExtraModelInfo(project, isLibrary());checkGradleVersion();sdkHandler = new SdkHandler(project, getLogger());project.afterEvaluate(p -> {// TODO: Read flag from extension.if (!p.getGradle().getStartParameter().isOffline()&& AndroidGradleOptions.getUseSdkDownload(p)) {SdkLibData sdkLibData =SdkLibData.download(getDownloader(), getSettingsController());dependencyManager.setSdkLibData(sdkLibData);sdkHandler.setSdkLibData(sdkLibData);}});androidBuilder = new AndroidBuilder(project == project.getRootProject() ? project.getName() : project.getPath(),creator,new GradleProcessExecutor(project),new GradleJavaProcessExecutor(project),extraModelInfo,getLogger(),isVerbose());dataBindingBuilder = new DataBindingBuilder();dataBindingBuilder.setPrintMachineReadableOutput(extraModelInfo.getErrorFormatMode() ==ExtraModelInfo.ErrorFormatMode.MACHINE_PARSABLE);project.getPlugins().apply(JavaBasePlugin.class);jacocoPlugin = project.getPlugins().apply(JacocoPlugin.class);project.getTasks().getByName("assemble").setDescription("Assembles all variants of all applications and secondary packages.");// call back on execution. This is called after the whole build is done (not// after the current project is done).// This is will be called for each (android) projects though, so this should support// being called 2+ times.project.getGradle().addBuildListener(new BuildListener() {private final LibraryCache libraryCache = LibraryCache.getCache();@Overridepublic void buildStarted(Gradle gradle) { }@Overridepublic void settingsEvaluated(Settings settings) { }@Overridepublic void projectsLoaded(Gradle gradle) { }@Overridepublic void projectsEvaluated(Gradle gradle) { }@Overridepublic void buildFinished(BuildResult buildResult) {ExecutorSingleton.shutdown();sdkHandler.unload();ThreadRecorder.get().record(ExecutionType.BASE_PLUGIN_BUILD_FINISHED,project.getPath(), null, new Recorder.Block() {@Overridepublic Void call() throws Exception {PreDexCache.getCache().clear(new File(project.getRootProject().getBuildDir(),FD_INTERMEDIATES + "/dex-cache/cache.xml"),getLogger());JackConversionCache.getCache().clear(new File(project.getRootProject().getBuildDir(),FD_INTERMEDIATES + "/jack-cache/cache.xml"),getLogger());libraryCache.unload();Main.clearInternTables();return null;}});}});project.getGradle().getTaskGraph().addTaskExecutionGraphListener(new TaskExecutionGraphListener() {@Overridepublic void graphPopulated(TaskExecutionGraph taskGraph) {for (Task task : taskGraph.getAllTasks()) {if (task instanceof TransformTask) {Transform transform = ((TransformTask) task).getTransform();if (transform instanceof DexTransform) {PreDexCache.getCache().load(new File(project.getRootProject().getBuildDir(),FD_INTERMEDIATES + "/dex-cache/cache.xml"));break;} else if (transform instanceof JackPreDexTransform) {JackConversionCache.getCache().load(new File(project.getRootProject().getBuildDir(),FD_INTERMEDIATES + "/jack-cache/cache.xml"));break;}}}}});}private void createExtension() {final NamedDomainObjectContainer<BuildType> buildTypeContainer = project.container(BuildType.class,new BuildTypeFactory(instantiator, project, project.getLogger()));final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer = project.container(ProductFlavor.class,new ProductFlavorFactory(instantiator, project, project.getLogger(), extraModelInfo));final NamedDomainObjectContainer<SigningConfig> signingConfigContainer = project.container(SigningConfig.class,new SigningConfigFactory(instantiator));extension = project.getExtensions().create("android", getExtensionClass(),project, instantiator, androidBuilder, sdkHandler,buildTypeContainer, productFlavorContainer, signingConfigContainer,extraModelInfo, isLibrary());// create the default mapping configuration.project.getConfigurations().create("default" + VariantDependencies.CONFIGURATION_MAPPING).setDescription("Configuration for default mapping artifacts.");project.getConfigurations().create("default" + VariantDependencies.CONFIGURATION_METADATA).setDescription("Metadata for the produced APKs.");dependencyManager = new DependencyManager(project,extraModelInfo,sdkHandler);ndkHandler = new NdkHandler(project.getRootDir(),null, /* compileSkdVersion, this will be set in afterEvaluate */"gcc","" /*toolchainVersion*/);taskManager = createTaskManager(project,androidBuilder,dataBindingBuilder,extension,sdkHandler,ndkHandler,dependencyManager,registry);variantFactory = createVariantFactory();variantManager = new VariantManager(project,androidBuilder,extension,variantFactory,taskManager,instantiator);// Register a builder for the custom tooling modelModelBuilder modelBuilder = new ModelBuilder(androidBuilder,variantManager,taskManager,extension,extraModelInfo,ndkHandler,new NativeLibraryFactoryImpl(ndkHandler),isLibrary(),AndroidProject.GENERATION_ORIGINAL);registry.register(modelBuilder);// Register a builder for the native tooling modelNativeModelBuilder nativeModelBuilder = new NativeModelBuilder(variantManager);registry.register(nativeModelBuilder);// map the whenObjectAdded callbacks on the containers.signingConfigContainer.whenObjectAdded(new Action<SigningConfig>() {@Overridepublic void execute(SigningConfig signingConfig) {variantManager.addSigningConfig(signingConfig);}});buildTypeContainer.whenObjectAdded(new Action<BuildType>() {@Overridepublic void execute(BuildType buildType) {SigningConfig signingConfig = signingConfigContainer.findByName(BuilderConstants.DEBUG);buildType.init(signingConfig);variantManager.addBuildType(buildType);}});productFlavorContainer.whenObjectAdded(new Action<ProductFlavor>() {@Overridepublic void execute(ProductFlavor productFlavor) {variantManager.addProductFlavor(productFlavor);}});// map whenObjectRemoved on the containers to throw an exception.signingConfigContainer.whenObjectRemoved(new UnsupportedAction("Removing signingConfigs is not supported."));buildTypeContainer.whenObjectRemoved(new UnsupportedAction("Removing build types is not supported."));productFlavorContainer.whenObjectRemoved(new UnsupportedAction("Removing product flavors is not supported."));// create default Objects, signingConfig first as its used by the BuildTypes.variantFactory.createDefaultComponents(buildTypeContainer, productFlavorContainer, signingConfigContainer);}private static class UnsupportedAction implements Action<Object> {private final String message;UnsupportedAction(String message) {this.message = message;}@Overridepublic void execute(Object o) {throw new UnsupportedOperationException(message);}}private void createTasks() {ThreadRecorder.get().record(ExecutionType.TASK_MANAGER_CREATE_TASKS,project.getPath(), null,new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {taskManager.createTasksBeforeEvaluate(new TaskContainerAdaptor(project.getTasks()));return null;}});project.afterEvaluate(project -> {ThreadRecorder.get().record(ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,project.getPath(), null,new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {createAndroidTasks(false);return null;}});});}private void checkGradleVersion() {String currentVersion = project.getGradle().getGradleVersion();if (GRADLE_MIN_VERSION.compareTo(currentVersion) > 0) {File file = new File("gradle" + separator + "wrapper" + separator +"gradle-wrapper.properties");String errorMessage =String.format("Minimum supported Gradle version is %s. Current version is %s. "+ "If using the gradle wrapper, try editing the distributionUrl in %s "+ "to gradle-%s-all.zip",GRADLE_MIN_VERSION,currentVersion,file.getAbsolutePath(),GRADLE_MIN_VERSION);if (AndroidGradleOptions.overrideGradleVersionCheck(project)) {getLogger().warning(errorMessage);getLogger().warning("As %s is set, continuing anyways.",AndroidGradleOptions.GRADLE_VERSION_CHECK_OVERRIDE_PROPERTY);} else {extraModelInfo.handleSyncError(GRADLE_MIN_VERSION.toString(), SyncIssue.TYPE_GRADLE_TOO_OLD, errorMessage);}}}@VisibleForTestingfinal void createAndroidTasks(boolean force) {// Make sure unit tests set the required fields.checkState(extension.getBuildToolsRevision() != null,"buildToolsVersion is not specified.");checkState(extension.getCompileSdkVersion() != null, "compileSdkVersion is not specified.");ndkHandler.setCompileSdkVersion(extension.getCompileSdkVersion());// get current plugins and look for the default Java plugin.if (project.getPlugins().hasPlugin(JavaPlugin.class)) {throw new BadPluginException("The 'java' plugin has been applied, but it is not compatible with the Android plugins.");}ensureTargetSetup();// don't do anything if the project was not initialized.// Unless TEST_SDK_DIR is set in which case this is unit tests and we don't return.// This is because project don't get evaluated in the unit test setup.// See AppPluginDslTestif (!force&& (!project.getState().getExecuted() || project.getState().getFailure() != null)&& SdkHandler.sTestSdkFolder == null) {return;}if (hasCreatedTasks) {return;}hasCreatedTasks = true;extension.disableWrite();ProcessRecorder.getProject(project.getPath()).setBuildToolsVersion(extension.getBuildToolsRevision().toString());// setup SDK repositories.sdkHandler.addLocalRepositories(project);taskManager.addDataBindingDependenciesIfNecessary(extension.getDataBinding());ThreadRecorder.get().record(ExecutionType.VARIANT_MANAGER_CREATE_ANDROID_TASKS,project.getPath(), null,new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {variantManager.createAndroidTasks();ApiObjectFactory apiObjectFactory = new ApiObjectFactory(androidBuilder, extension, variantFactory, instantiator);for (BaseVariantData variantData : variantManager.getVariantDataList()) {apiObjectFactory.create(variantData);}return null;}});// Create and read external native build JSON files depending on what's happening right// now.//// CREATE PHASE:// Creates JSONs by shelling out to external build system when:// - Any one of AndroidProject.PROPERTY_INVOKED_FROM_IDE,// AndroidProject.PROPERTY_BUILD_MODEL_ONLY_ADVANCED,// AndroidProject.PROPERTY_BUILD_MODEL_ONLY,// AndroidProject.PROPERTY_REFRESH_EXTERNAL_NATIVE_MODEL are set.// - *and* AndroidProject.PROPERTY_REFRESH_EXTERNAL_NATIVE_MODEL is set// or JSON files don't exist or are out-of-date.// Create phase may cause ProcessException (from cmake.exe for example)//// READ PHASE:// Reads and deserializes JSONs when:// - Any one of AndroidProject.PROPERTY_INVOKED_FROM_IDE,// AndroidProject.PROPERTY_BUILD_MODEL_ONLY_ADVANCED,// AndroidProject.PROPERTY_BUILD_MODEL_ONLY,// AndroidProject.PROPERTY_REFRESH_EXTERNAL_NATIVE_MODEL are set.// Read phase may produce IOException if the file can't be read for standard IO reasons.// Read phase may produce JsonSyntaxException in the case that the content of the file is// corrupt.boolean forceRegeneration = AndroidGradleOptions.refreshExternalNativeModel(project);if (ExternalNativeBuildTaskUtils.shouldRegenerateOutOfDateJsons(project)) {ThreadRecorder.get().record(ExecutionType.VARIANT_MANAGER_EXTERNAL_NATIVE_CONFIG_VALUES,project.getPath(), null,new Recorder.Block<Void>() {@Overridepublic Void call() throws Exception {for (BaseVariantData variantData : variantManager.getVariantDataList()) {ExternalNativeJsonGenerator generator =variantData.getScope().getExternalNativeJsonGenerator();if (generator != null) {// This will generate any out-of-date or non-existent JSONs.// When refreshExternalNativeModel() is true it will also// force update all JSONs.generator.build(forceRegeneration);variantData.getScope().addExternalNativeBuildConfigValues(generator.readExistingNativeBuildConfigurations());}}return null;}});}}private boolean isVerbose() {return project.getLogger().isEnabled(LogLevel.INFO);}private void ensureTargetSetup() {// check if the target has been set.TargetInfo targetInfo = androidBuilder.getTargetInfo();if (targetInfo == null) {if (extension.getCompileOptions() == null) {throw new GradleException("Calling getBootClasspath before compileSdkVersion");}sdkHandler.initTarget(extension.getCompileSdkVersion(),extension.getBuildToolsRevision(),extension.getLibraryRequests(),androidBuilder,SdkHandler.useCachedSdk(project));}}/*** Check the sub-projects structure :* So far, checks that 2 modules do not have the same identification (group+name).*/private void checkModulesForErrors() {Project rootProject = project.getRootProject();Map<String, Project> subProjectsById = new HashMap<String, Project>();for (Project subProject : rootProject.getAllprojects()) {String id = subProject.getGroup().toString() + ":" + subProject.getName();if (subProjectsById.containsKey(id)) {String message = String.format("Your project contains 2 or more modules with the same " +"identification %1$s\n" +"at \"%2$s\" and \"%3$s\".\n" +"You must use different identification (either name or group) for " +"each modules.",id,subProjectsById.get(id).getPath(),subProject.getPath() );throw new StopExecutionException(message);} else {subProjectsById.put(id, subProject);}}}/*** Verify the plugin version. If a newer version of gradle-experimental plugin is applied, then* builder.jar module will be resolved to a different version than the one this gradle plugin is* compiled with. Throw an error and suggest to update this plugin.*/private static void checkPluginVersion() {String actualGradlePluginVersion = Version.getAndroidGradlePluginVersion();if(!actualGradlePluginVersion.equals(com.android.build.gradle.internal.Version.ANDROID_GRADLE_PLUGIN_VERSION)) {throw new UnsupportedVersionException(String.format("Plugin version mismatch. "+ "'com.android.tools.build:gradle-experimental:%s' was applied, and it "+ "requires 'com.android.tools.build:gradle:%s'. Current version is '%s'. "+ "Please update to version '%s'.",Version .getAndroidGradleComponentPluginVersion(),Version .getAndroidGradlePluginVersion(),com.android.build.gradle.internal.Version.ANDROID_GRADLE_PLUGIN_VERSION,Version .getAndroidGradlePluginVersion()));}}private void checkPathForErrors() {// See if we're on Windows:if (!System.getProperty("os.name").toLowerCase(Locale.US).contains("windows")) {return;}// See if the user disabled the check:if (AndroidGradleOptions.overridePathCheck(project)) {return;}// See if the path contains non-ASCII characters.if (CharMatcher.ASCII.matchesAllOf(project.getRootDir().getAbsolutePath())) {return;}String message ="Your project path contains non-ASCII characters. This will most likely "+ "cause the build to fail on Windows. Please move your project to a different "+ "directory. See http://b.android.com/95744 for details. "+ "This warning can be disabled by adding the line '"+ AndroidGradleOptions.OVERRIDE_PATH_CHECK_PROPERTY+ "=true' to gradle.properties file in the project directory.";throw new StopExecutionException(message);}@NonNull@Overridepublic ToolingModelBuilderRegistry getModelBuilderRegistry() {return registry;}private static SettingsController getSettingsController() {return new SettingsController() {@Overridepublic boolean getForceHttp() {return false;}@Overridepublic void setForceHttp(boolean force) {// Default, doesn't allow to set force HTTP.}@Nullable@Overridepublic Channel getChannel() {return Channel.DEFAULT;}};}private static Downloader getDownloader() {return new LocalFileAwareDownloader(new LegacyDownloader(FileOpUtils.create()));} }LibraryExtension類代碼:
package com.android.build.gradle;import com.android.annotations.NonNull; import com.android.build.gradle.api.BaseVariant; import com.android.build.gradle.api.LibraryVariant; 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.dsl.BuildType; import com.android.build.gradle.internal.dsl.ProductFlavor; import com.android.build.gradle.internal.dsl.SigningConfig; import com.android.builder.core.AndroidBuilder; import com.google.common.collect.Lists;import org.gradle.api.GradleException; import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.internal.DefaultDomainObjectSet; import org.gradle.api.internal.project.ProjectInternal; import org.gradle.internal.reflect.Instantiator;import java.util.Collection; import java.util.Collections;/*** {@code android} extension for {@code com.android.library} projects.*/ public class LibraryExtension extends TestedExtension {private final DefaultDomainObjectSet<LibraryVariant> libraryVariantList= new DefaultDomainObjectSet<LibraryVariant>(LibraryVariant.class);private boolean packageBuildConfig = true;private Collection<String> aidlPackageWhiteList = null;public LibraryExtension(@NonNull ProjectInternal project, @NonNull Instantiator instantiator,@NonNull AndroidBuilder androidBuilder, @NonNull SdkHandler sdkHandler,@NonNull NamedDomainObjectContainer<BuildType> buildTypes,@NonNull NamedDomainObjectContainer<ProductFlavor> productFlavors,@NonNull NamedDomainObjectContainer<SigningConfig> signingConfigs,@NonNull ExtraModelInfo extraModelInfo, boolean isLibrary) {super(project, instantiator, androidBuilder, sdkHandler, buildTypes, productFlavors,signingConfigs, extraModelInfo, isLibrary);}/*** Returns the list of library variants. Since the collections is built after evaluation, it* should be used with Gradle's <code>all</code> iterator to process future items.*/public DefaultDomainObjectSet<LibraryVariant> getLibraryVariants() {return libraryVariantList;}@Overridepublic void addVariant(BaseVariant variant) {libraryVariantList.add((LibraryVariant) variant);}public void packageBuildConfig(boolean value) {if (!value) {LoggingUtil.displayDeprecationWarning(logger, project,"Support for not packaging BuildConfig is deprecated.");}packageBuildConfig = value;}@Deprecatedpublic void setPackageBuildConfig(boolean value) {// Remove when users stop requiring this setting.packageBuildConfig(value);}@Overridepublic Boolean getPackageBuildConfig() {return packageBuildConfig;}public void aidlPackageWhiteList(String ... aidlFqcns) {if (aidlPackageWhiteList == null) {aidlPackageWhiteList = Lists.newArrayList();}Collections.addAll(aidlPackageWhiteList, aidlFqcns);}public void setAidlPackageWhiteList(Collection<String> aidlPackageWhiteList) {this.aidlPackageWhiteList = Lists.newArrayList(aidlPackageWhiteList);}@Overridepublic Collection<String> getAidlPackageWhiteList() {return aidlPackageWhiteList;} }LibraryPlugin代碼:
總結(jié)
以上是生活随笔為你收集整理的Gradle 工具的源码研究的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 快手名字大全807个
- 下一篇: DirectX是什么