diff options
82 files changed, 1771 insertions, 1040 deletions
diff --git a/builder-model/src/main/java/com/android/builder/NdkConfig.java b/builder-model/src/main/java/com/android/builder/NdkConfig.java index 761871d..fbebf49 100644 --- a/builder-model/src/main/java/com/android/builder/NdkConfig.java +++ b/builder-model/src/main/java/com/android/builder/NdkConfig.java @@ -41,7 +41,7 @@ public interface NdkConfig { * The LD Libs */ @Nullable - public String getLdLibs(); + public Set<String> getLdLibs(); /** * The ABI Filters diff --git a/builder-model/src/main/java/com/android/builder/model/BaseConfig.java b/builder-model/src/main/java/com/android/builder/model/BaseConfig.java index fbf6eb4..713b344 100644 --- a/builder-model/src/main/java/com/android/builder/model/BaseConfig.java +++ b/builder-model/src/main/java/com/android/builder/model/BaseConfig.java @@ -27,11 +27,11 @@ import java.util.List; public interface BaseConfig { /** - * List of Build Config lines. - * @return a non-null list of lines (possibly empty) + * List of Build Config Fields + * @return a non-null list of class fields (possibly empty) */ @NonNull - List<String> getBuildConfig(); + List<ClassField> getBuildConfigFields(); /** * Returns the list of proguard rule files. diff --git a/builder-model/src/main/java/com/android/builder/model/ClassField.java b/builder-model/src/main/java/com/android/builder/model/ClassField.java new file mode 100644 index 0000000..d6b6a26 --- /dev/null +++ b/builder-model/src/main/java/com/android/builder/model/ClassField.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2013 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.builder.model; + +import com.android.annotations.NonNull; + +/** + * A Simple class field with name, type and value, all as strings. + */ +public interface ClassField { + @NonNull + String getType(); + + @NonNull + String getName(); + + @NonNull + String getValue(); +} diff --git a/builder-model/src/main/java/com/android/builder/model/Variant.java b/builder-model/src/main/java/com/android/builder/model/Variant.java index 21ef33e..2f32c66 100644 --- a/builder-model/src/main/java/com/android/builder/model/Variant.java +++ b/builder-model/src/main/java/com/android/builder/model/Variant.java @@ -91,6 +91,13 @@ public interface Variant { ProductFlavor getMergedFlavor(); /** + * The variant specific SourceProvider. + * @return a source provider or null + */ + @Nullable + SourceProvider getSourceProvider(); + + /** * Returns the resource configuration for this variant. * TODO implement this. * diff --git a/builder/build.gradle b/builder/build.gradle index a9f1bbe..c765b0d 100644 --- a/builder/build.gradle +++ b/builder/build.gradle @@ -15,6 +15,7 @@ dependencies { compile "com.android.tools.build:manifest-merger:$project.ext.baseAndroidVersion" compile "com.android.tools.ddms:ddmlib:$project.ext.baseAndroidVersion" + compile 'com.squareup:javawriter:2.2.1' compile 'org.bouncycastle:bcpkix-jdk15on:1.48' testCompile 'junit:junit:3.8.1' diff --git a/builder/src/main/java/com/android/builder/AndroidBuilder.java b/builder/src/main/java/com/android/builder/AndroidBuilder.java index feaa7c8..24ff0c8 100644 --- a/builder/src/main/java/com/android/builder/AndroidBuilder.java +++ b/builder/src/main/java/com/android/builder/AndroidBuilder.java @@ -22,7 +22,7 @@ import com.android.annotations.VisibleForTesting; import com.android.builder.compiling.DependencyFileProcessor; import com.android.builder.dependency.ManifestDependency; import com.android.builder.dependency.SymbolFileProvider; -import com.android.builder.internal.BuildConfigGenerator; +import com.android.builder.internal.ClassFieldImpl; import com.android.builder.internal.SymbolLoader; import com.android.builder.internal.SymbolWriter; import com.android.builder.internal.TestManifestGenerator; @@ -33,6 +33,7 @@ import com.android.builder.internal.compiler.SourceSearcher; import com.android.builder.internal.packaging.JavaResourceProcessor; import com.android.builder.internal.packaging.Packager; import com.android.builder.model.AaptOptions; +import com.android.builder.model.ClassField; import com.android.builder.model.ProductFlavor; import com.android.builder.model.SigningConfig; import com.android.builder.packaging.DuplicateFileException; @@ -80,7 +81,6 @@ import static com.google.common.base.Preconditions.checkNotNull; * create a builder with {@link #AndroidBuilder(SdkParser, String, ILogger, boolean)} * * then build steps can be done with - * {@link #generateBuildConfig(String, boolean, java.util.List, String)} * {@link #processManifest(java.io.File, java.util.List, java.util.List, String, int, String, int, int, String)} * {@link #processTestManifest(String, int, int, String, String, Boolean, Boolean, java.util.List, String)} * {@link #processResources(java.io.File, java.io.File, java.io.File, java.util.List, String, String, String, String, String, com.android.builder.VariantConfiguration.Type, boolean, com.android.builder.model.AaptOptions)} @@ -265,24 +265,9 @@ public class AndroidBuilder { return mCmdLineRunner; } - /** - * Generate the BuildConfig class for the project. - * @param packageName the package in which to generate the class - * @param debuggable whether the app is considered debuggable - * @param javaLines additional java lines to put in the class. These must be valid Java lines. - * @param sourceOutputDir directory where to put this. This is the source folder, not the - * package folder. - * @throws IOException - */ - public void generateBuildConfig( - @NonNull String packageName, - boolean debuggable, - @NonNull List<String> javaLines, - @NonNull String sourceOutputDir) throws IOException { - - BuildConfigGenerator generator = new BuildConfigGenerator( - sourceOutputDir, packageName, debuggable); - generator.generate(javaLines); + @NonNull + public static ClassField createClassField(@NonNull String type, @NonNull String name, @NonNull String value) { + return new ClassFieldImpl(type, name, value); } /** diff --git a/builder/src/main/java/com/android/builder/DefaultManifestParser.java b/builder/src/main/java/com/android/builder/DefaultManifestParser.java index 97d8533..e8d70d6 100644 --- a/builder/src/main/java/com/android/builder/DefaultManifestParser.java +++ b/builder/src/main/java/com/android/builder/DefaultManifestParser.java @@ -67,6 +67,27 @@ public class DefaultManifestParser implements ManifestParser { } @Override + public int getVersionCode(@NonNull File manifestFile) { + XPath xpath = AndroidXPathFactory.newXPath(); + + try { + String value= xpath.evaluate("/manifest/@android:versionCode", + new InputSource(new FileInputStream(manifestFile))); + if (value != null) { + return Integer.parseInt(value); + } + } catch (XPathExpressionException e) { + // won't happen. + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } catch (NumberFormatException e) { + // return -1 below. + } + + return -1; + } + + @Override public int getMinSdkVersion(@NonNull File manifestFile) { try { Object value = AndroidManifest.getMinSdkVersion(new FileWrapper(manifestFile)); diff --git a/builder/src/main/java/com/android/builder/ManifestParser.java b/builder/src/main/java/com/android/builder/ManifestParser.java index 5b6411c..3b8e4a3 100644 --- a/builder/src/main/java/com/android/builder/ManifestParser.java +++ b/builder/src/main/java/com/android/builder/ManifestParser.java @@ -21,14 +21,56 @@ import com.android.annotations.Nullable; import java.io.File; +/** + * A Manifest parser + */ public interface ManifestParser { + /** + * Returns the package name parsed from the given manifest file. + * + * @param manifestFile the manifest file to parse + * + * @return the package name or null if not found. + */ @Nullable String getPackage(@NonNull File manifestFile); + /** + * Returns the minSdkVersion parsed from the given manifest file. + * + * @param manifestFile the manifest file to parse + * + * @return the minSdkVersion or 1 if not found. + */ int getMinSdkVersion(@NonNull File manifestFile); + + /** + * Returns the targetSdkVersion parsed from the given manifest file. + * + * @param manifestFile the manifest file to parse + * + * @return the targetSdkVersion or -1 if not found. + */ int getTargetSdkVersion(@NonNull File manifestFile); + /** + * Returns the version name parsed from the given manifest file. + * + * @param manifestFile the manifest file to parse + * + * @return the version name or null if not found. + */ @Nullable String getVersionName(@NonNull File manifestFile); + + /** + * Returns the version code parsed from the given manifest file. + * + * @param manifestFile the manifest file to parse + * + * @return the version code or -1 if not found. + */ + int getVersionCode(@NonNull File manifestFile); + } diff --git a/builder/src/main/java/com/android/builder/VariantConfiguration.java b/builder/src/main/java/com/android/builder/VariantConfiguration.java index 72fbf9a..7c5f6b1 100644 --- a/builder/src/main/java/com/android/builder/VariantConfiguration.java +++ b/builder/src/main/java/com/android/builder/VariantConfiguration.java @@ -23,6 +23,9 @@ import com.android.builder.dependency.DependencyContainer; import com.android.builder.dependency.JarDependency; import com.android.builder.dependency.LibraryDependency; import com.android.builder.internal.NdkConfigImpl; +import com.android.builder.internal.StringHelper; +import com.android.builder.model.ClassField; +import com.android.builder.model.ProductFlavor; import com.android.builder.model.SigningConfig; import com.android.builder.model.SourceProvider; import com.android.builder.testing.TestData; @@ -33,6 +36,7 @@ import com.google.common.collect.Sets; import java.io.File; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Set; @@ -46,20 +50,52 @@ public class VariantConfiguration implements TestData { private static final ManifestParser sManifestParser = new DefaultManifestParser(); + /** + * Full, unique name of the variant in camel case, including BuildType and Flavors (and Test) + */ + private String mFullName; + /** + * Flavor Name of the variant, including all flavors in camel case (starting with a lower + * case). + */ + private String mFlavorName; + /** + * Full, unique name of the variant, including BuildType, flavors and test, dash separated. + * (similar to full name but with dashes) + */ + private String mBaseName; + /** + * Unique directory name (can include multiple folders) for the variant, based on build type, + * flavor and test. + * This always uses forward slashes ('/') as separator on all platform. + * + */ + private String mDirName; + + @NonNull private final DefaultProductFlavor mDefaultConfig; + @NonNull private final SourceProvider mDefaultSourceProvider; + @NonNull private final DefaultBuildType mBuildType; /** SourceProvider for the BuildType. Can be null */ + @Nullable private final SourceProvider mBuildTypeSourceProvider; private final List<DefaultProductFlavor> mFlavorConfigs = Lists.newArrayList(); private final List<SourceProvider> mFlavorSourceProviders = Lists.newArrayList(); + /** + * Variant specific source provider, may be null + */ + @Nullable + private SourceProvider mVariantSourceProvider; + + @NonNull private final Type mType; /** Optional tested config in case type is Type#TEST */ private final VariantConfiguration mTestedConfig; - private final String mDebugName; /** An optional output that is only valid if the type is Type#LIBRARY so that the test * for the library can use the library as if it was a normal dependency. */ private LibraryDependency mOutput; @@ -100,18 +136,16 @@ public class VariantConfiguration implements TestData { * @param defaultSourceProvider the default source provider. Required * @param buildType the build type for this variant. Required. * @param buildTypeSourceProvider the source provider for the build type. Required. - * @param debugName an optional debug name */ public VariantConfiguration( @NonNull DefaultProductFlavor defaultConfig, @NonNull SourceProvider defaultSourceProvider, @NonNull DefaultBuildType buildType, - @Nullable SourceProvider buildTypeSourceProvider, - @Nullable String debugName) { - this(defaultConfig, defaultSourceProvider, + @Nullable SourceProvider buildTypeSourceProvider) { + this( + defaultConfig, defaultSourceProvider, buildType, buildTypeSourceProvider, - Type.DEFAULT, null /*testedConfig*/, - debugName); + Type.DEFAULT, null /*testedConfig*/); } /** @@ -122,19 +156,17 @@ public class VariantConfiguration implements TestData { * @param buildType the build type for this variant. Required. * @param buildTypeSourceProvider the source provider for the build type. * @param type the type of the project. - * @param debugName an optional debug name */ public VariantConfiguration( @NonNull DefaultProductFlavor defaultConfig, @NonNull SourceProvider defaultSourceProvider, @NonNull DefaultBuildType buildType, @Nullable SourceProvider buildTypeSourceProvider, - @NonNull Type type, - @Nullable String debugName) { - this(defaultConfig, defaultSourceProvider, + @NonNull Type type) { + this( + defaultConfig, defaultSourceProvider, buildType, buildTypeSourceProvider, - type, null /*testedConfig*/, - debugName); + type, null /*testedConfig*/); } /** @@ -146,7 +178,6 @@ public class VariantConfiguration implements TestData { * @param buildTypeSourceProvider the source provider for the build type. * @param type the type of the project. * @param testedConfig the reference to the tested project. Required if type is Type.TEST - * @param debugName an optional debug name */ public VariantConfiguration( @NonNull DefaultProductFlavor defaultConfig, @@ -154,15 +185,13 @@ public class VariantConfiguration implements TestData { @NonNull DefaultBuildType buildType, @Nullable SourceProvider buildTypeSourceProvider, @NonNull Type type, - @Nullable VariantConfiguration testedConfig, - @Nullable String debugName) { + @Nullable VariantConfiguration testedConfig) { mDefaultConfig = checkNotNull(defaultConfig); mDefaultSourceProvider = checkNotNull(defaultSourceProvider); mBuildType = checkNotNull(buildType); mBuildTypeSourceProvider = buildTypeSourceProvider; mType = checkNotNull(type); mTestedConfig = testedConfig; - mDebugName = debugName; checkState(mType != Type.TEST || mTestedConfig != null); mMergedFlavor = mDefaultConfig; @@ -178,6 +207,144 @@ public class VariantConfiguration implements TestData { } /** + * Returns the full, unique name of the variant in camel case (starting with a lower case), + * including BuildType, Flavors and Test (if applicable). + * + * @return the name of the variant + */ + @NonNull + public String getFullName() { + if (mFullName == null) { + StringBuilder sb = new StringBuilder(); + String flavorName = getFlavorName(); + if (!flavorName.isEmpty()) { + sb.append(flavorName); + sb.append(StringHelper.capitalize(mBuildType.getName())); + } else { + sb.append(mBuildType.getName()); + } + + if (mType == Type.TEST) { + sb.append("Test"); + } + + mFullName = sb.toString(); + } + + return mFullName; + } + + + /** + * Returns the flavor name of the variant, including all flavors in camel case (starting + * with a lower case). If the variant has no flavor, then an empty string is returned. + * + * @return the flavor name or an empty string. + */ + @NonNull + public String getFlavorName() { + if (mFlavorName == null) { + if (mFlavorConfigs.isEmpty()) { + mFlavorName = ""; + } else { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (DefaultProductFlavor flavor : mFlavorConfigs) { + sb.append(first ? flavor.getName() : StringHelper.capitalize(flavor.getName())); + first = false; + } + + mFlavorName = sb.toString(); + } + } + + return mFlavorName; + } + + /** + * Returns the full, unique name of the variant, including BuildType, flavors and test, + * dash separated. (similar to full name but with dashes) + * + * @return the name of the variant + */ + @NonNull + public String getBaseName() { + if (mBaseName == null) { + StringBuilder sb = new StringBuilder(); + + if (!mFlavorConfigs.isEmpty()) { + for (ProductFlavor pf : mFlavorConfigs) { + sb.append(pf.getName()).append('-'); + } + } + + sb.append(mBuildType.getName()); + + if (mType == Type.TEST) { + sb.append('-').append("test"); + } + + mBaseName = sb.toString(); + } + + return mBaseName; + } + + /** + * Returns a unique directory name (can include multiple folders) for the variant, + * based on build type, flavor and test. + * This always uses forward slashes ('/') as separator on all platform. + * + * @return the directory name for the variant + */ + @NonNull + public String getDirName() { + if (mDirName == null) { + StringBuilder sb = new StringBuilder(); + + if (mType == Type.TEST) { + sb.append("test/"); + } + + if (!mFlavorConfigs.isEmpty()) { + for (DefaultProductFlavor flavor : mFlavorConfigs) { + sb.append(flavor.getName()); + } + + sb.append('/').append(mBuildType.getName()); + + } else { + sb.append(mBuildType.getName()); + } + + mDirName = sb.toString(); + + } + + return mDirName; + } + + /** + * Return the names of the applied flavors. + * + * @return the list, possibly empty if there are no flavors. + */ + @NonNull + public List<String> getFlavorNames() { + if (mFlavorConfigs.isEmpty()) { + return Collections.emptyList(); + } + + List<String> names = Lists.newArrayListWithCapacity(mFlavorConfigs.size()); + for (DefaultProductFlavor flavor : mFlavorConfigs) { + names.add(flavor.getName()); + } + + return names; + } + + + /** * Add a new configured ProductFlavor. * * If multiple flavors are added, the priority follows the order they are added when it @@ -185,13 +352,14 @@ public class VariantConfiguration implements TestData { * latter added ones). * * @param productFlavor the configured product flavor - * @param sourceProvider + * @param sourceProvider the source provider for the product flavor * * @return the config object */ @NonNull public VariantConfiguration addProductFlavor(@NonNull DefaultProductFlavor productFlavor, @NonNull SourceProvider sourceProvider) { + mFlavorConfigs.add(productFlavor); mFlavorSourceProviders.add(sourceProvider); @@ -201,6 +369,27 @@ public class VariantConfiguration implements TestData { return this; } + /** + * Sets the variant-specific source provider. + * @param sourceProvider the source provider for the product flavor + * + * @return the config object + */ + public VariantConfiguration setVariantSourceProvider(@Nullable SourceProvider sourceProvider) { + mVariantSourceProvider = sourceProvider; + + return this; + } + + /** + * Returns the variant specific source provider + * @return the source provider or null if none has been provided. + */ + @Nullable + public SourceProvider getVariantSourceProvider() { + return mVariantSourceProvider; + } + private void computeNdkConfig() { mMergedNdkConfig.reset(); @@ -412,7 +601,7 @@ public class VariantConfiguration implements TestData { } if (packageName == null) { - throw new RuntimeException("Failed get query package name for " + mDebugName); + throw new RuntimeException("Failed get query package name for " + getFullName()); } return packageName; @@ -473,7 +662,11 @@ public class VariantConfiguration implements TestData { if (versionSuffix != null && versionSuffix.length() > 0) { if (versionName == null) { - versionName = getVersionNameFromManifest(); + if (mType != Type.TEST) { + versionName = getVersionNameFromManifest(); + } else { + versionName = ""; + } } versionName = versionName + versionSuffix; @@ -482,6 +675,24 @@ public class VariantConfiguration implements TestData { return versionName; } + /** + * Returns the version code for this variant. This could be coming from the manifest or + * could be overridden through the product flavors, and can have a suffix specified by + * the build type. + * + * @return the version code or -1 if there was non defined. + */ + public int getVersionCode() { + int versionCode = mMergedFlavor.getVersionCode(); + + if (versionCode == -1 && mType != Type.TEST) { + + versionCode = getVersionCodeFromManifest(); + } + + return versionCode; + } + private final static String DEFAULT_TEST_RUNNER = "android.test.InstrumentationTestRunner"; private final static Boolean DEFAULT_HANDLE_PROFILING = false; private final static Boolean DEFAULT_FUNCTIONAL_TEST = false; @@ -554,6 +765,14 @@ public class VariantConfiguration implements TestData { } /** + * Reads the version code from the manifest. + */ + public int getVersionCodeFromManifest() { + File manifestLocation = mDefaultSourceProvider.getManifestFile(); + return sManifestParser.getVersionCode(manifestLocation); + } + + /** * Return the minSdkVersion for this variant. * * This uses both the value from the manifest (if present), and the override coming @@ -612,6 +831,13 @@ public class VariantConfiguration implements TestData { public List<File> getManifestOverlays() { List<File> inputs = Lists.newArrayList(); + if (mVariantSourceProvider != null) { + File variantLocation = mVariantSourceProvider.getManifestFile(); + if (variantLocation.isFile()) { + inputs.add(variantLocation); + } + } + if (mBuildTypeSourceProvider != null) { File typeLocation = mBuildTypeSourceProvider.getManifestFile(); if (typeLocation.isFile()) { @@ -682,6 +908,7 @@ public class VariantConfiguration implements TestData { resourceSets.add(resourceSet); } + // build type overrides the flavors if (mBuildTypeSourceProvider != null) { Set<File> typeResDirs = mBuildTypeSourceProvider.getResDirectories(); resourceSet = new ResourceSet(mBuildType.getName()); @@ -689,6 +916,14 @@ public class VariantConfiguration implements TestData { resourceSets.add(resourceSet); } + // variant specific overrides all + if (mVariantSourceProvider != null) { + Set<File> variantResDirs = mVariantSourceProvider.getResDirectories(); + resourceSet = new ResourceSet(getFullName()); + resourceSet.addSources(variantResDirs); + resourceSets.add(resourceSet); + } + return resourceSets; } @@ -737,6 +972,7 @@ public class VariantConfiguration implements TestData { assetSets.add(assetSet); } + // build type overrides flavors if (mBuildTypeSourceProvider != null) { Set<File> typeResDirs = mBuildTypeSourceProvider.getAssetsDirectories(); assetSet = new AssetSet(mBuildType.getName()); @@ -744,6 +980,14 @@ public class VariantConfiguration implements TestData { assetSets.add(assetSet); } + // variant specific overrides all + if (mVariantSourceProvider != null) { + Set<File> variantResDirs = mVariantSourceProvider.getAssetsDirectories(); + assetSet = new AssetSet(getFullName()); + assetSet.addSources(variantResDirs); + assetSets.add(assetSet); + } + return assetSets; } @@ -799,6 +1043,10 @@ public class VariantConfiguration implements TestData { } } + if (mVariantSourceProvider != null) { + sourceList.addAll(mVariantSourceProvider.getRenderscriptDirectories()); + } + return sourceList; } @@ -833,6 +1081,31 @@ public class VariantConfiguration implements TestData { } } + if (mVariantSourceProvider != null) { + sourceList.addAll(mVariantSourceProvider.getAidlDirectories()); + } + + return sourceList; + } + + @NonNull + public List<File> getJniSourceList() { + List<File> sourceList = Lists.newArrayList(); + sourceList.addAll(mDefaultSourceProvider.getJniDirectories()); + if (mType != Type.TEST && mBuildTypeSourceProvider != null) { + sourceList.addAll(mBuildTypeSourceProvider.getJniDirectories()); + } + + if (hasFlavors()) { + for (SourceProvider flavorSourceSet : mFlavorSourceProviders) { + sourceList.addAll(flavorSourceSet.getJniDirectories()); + } + } + + if (mVariantSourceProvider != null) { + sourceList.addAll(mVariantSourceProvider.getJniDirectories()); + } + return sourceList; } @@ -894,27 +1167,52 @@ public class VariantConfiguration implements TestData { return Lists.newArrayList(jars); } + /** + * Returns a list of items for the BuildConfig class. + * + * Items can be either fields (instance of {@link com.android.builder.model.ClassField}) + * or comments (instance of String). + * + * @return a list of items. + */ @NonNull - public List<String> getBuildConfigLines() { - List<String> fullList = Lists.newArrayList(); + public List<Object> getBuildConfigItems() { + List<Object> fullList = Lists.newArrayList(); - List<String> list = mDefaultConfig.getBuildConfig(); - if (!list.isEmpty()) { - fullList.add("// lines from default config."); - fullList.addAll(list); - } + Set<String> usedFieldNames = Sets.newHashSet(); - list = mBuildType.getBuildConfig(); + List<ClassField> list = mBuildType.getBuildConfigFields(); if (!list.isEmpty()) { - fullList.add("// lines from build type: " + mBuildType.getName()); - fullList.addAll(list); + fullList.add("Fields from build type: " + mBuildType.getName()); + for (ClassField f : list) { + usedFieldNames.add(f.getName()); + fullList.add(f); + } } for (DefaultProductFlavor flavor : mFlavorConfigs) { - list = flavor.getBuildConfig(); + list = flavor.getBuildConfigFields(); if (!list.isEmpty()) { - fullList.add("// lines from product flavor: " + flavor.getName()); - fullList.addAll(list); + fullList.add("Fields from product flavor: " + flavor.getName()); + for (ClassField f : list) { + String name = f.getName(); + if (!usedFieldNames.contains(name)) { + usedFieldNames.add(f.getName()); + fullList.add(f); + } + } + } + } + + list = mDefaultConfig.getBuildConfigFields(); + if (!list.isEmpty()) { + fullList.add("Fields from default config."); + for (ClassField f : list) { + String name = f.getName(); + if (!usedFieldNames.contains(name)) { + usedFieldNames.add(f.getName()); + fullList.add(f); + } } } diff --git a/builder/src/main/java/com/android/builder/compiling/BuildConfigGenerator.java b/builder/src/main/java/com/android/builder/compiling/BuildConfigGenerator.java new file mode 100644 index 0000000..1e298b4 --- /dev/null +++ b/builder/src/main/java/com/android/builder/compiling/BuildConfigGenerator.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2011 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.builder.compiling; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.builder.AndroidBuilder; +import com.android.builder.model.ClassField; +import com.google.common.collect.Lists; +import com.squareup.javawriter.JavaWriter; + +import javax.lang.model.element.Modifier; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Class able to generate a BuildConfig class in Android project. + * The BuildConfig class contains constants related to the build target. + */ +public class BuildConfigGenerator { + + public final static String BUILD_CONFIG_NAME = "BuildConfig.java"; + + private final String mGenFolder; + private final String mBuildConfigPackageName; + + private final List<ClassField> mFields = Lists.newArrayList(); + private List<Object> mItems = Lists.newArrayList(); + + /** + * Creates a generator + * @param genFolder the gen folder of the project + * @param buildConfigPackageName the package in which to create the class. + */ + public BuildConfigGenerator(@NonNull String genFolder, @NonNull String buildConfigPackageName) { + mGenFolder = checkNotNull(genFolder); + mBuildConfigPackageName = checkNotNull(buildConfigPackageName); + } + + public BuildConfigGenerator addField( + @NonNull String type, @NonNull String name, @NonNull String value) { + mFields.add(AndroidBuilder.createClassField(type, name, value)); + return this; + } + + public BuildConfigGenerator addItems(@Nullable Collection<Object> items) { + if (items != null) { + mItems.addAll(items); + } + return this; + } + + /** + * Returns a File representing where the BuildConfig class will be. + */ + public File getFolderPath() { + File genFolder = new File(mGenFolder); + return new File(genFolder, mBuildConfigPackageName.replace('.', File.separatorChar)); + } + + public File getBuildConfigFile() { + File folder = getFolderPath(); + return new File(folder, BUILD_CONFIG_NAME); + } + + /** + * Generates the BuildConfig class. + */ + public void generate() throws IOException { + File pkgFolder = getFolderPath(); + if (!pkgFolder.isDirectory()) { + if (!pkgFolder.mkdirs()) { + throw new RuntimeException("Failed to create " + pkgFolder.getAbsolutePath()); + } + } + + File buildConfigJava = new File(pkgFolder, BUILD_CONFIG_NAME); + FileWriter out = new FileWriter(buildConfigJava); + + JavaWriter writer = new JavaWriter(out); + + Set<Modifier> publicFinal = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL); + Set<Modifier> publicFinalStatic = EnumSet.of(Modifier.PUBLIC, Modifier.FINAL, Modifier.STATIC); + + writer.emitJavadoc("Automatically generated file. DO NOT MODIFY") + .emitPackage(mBuildConfigPackageName) + .beginType("BuildConfig", "class", publicFinal); + + for (ClassField field : mFields) { + writer.emitField( + field.getType(), + field.getName(), + publicFinalStatic, + field.getValue()); + } + + for (Object item : mItems) { + if (item instanceof ClassField) { + ClassField field = (ClassField)item; + writer.emitField( + field.getType(), + field.getName(), + publicFinalStatic, + field.getValue()); + + } else if (item instanceof String) { + writer.emitSingleLineComment((String) item); + } + } + + writer.endType(); + + out.close(); + } +} diff --git a/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java b/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java index 044420b..62653d3 100644 --- a/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java +++ b/builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java @@ -18,11 +18,13 @@ package com.android.builder.internal; import com.android.annotations.NonNull; import com.android.builder.model.BaseConfig; +import com.android.builder.model.ClassField; import com.google.common.collect.Lists; import java.io.File; import java.io.Serializable; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -31,24 +33,28 @@ import java.util.List; public class BaseConfigImpl implements Serializable, BaseConfig { private static final long serialVersionUID = 1L; - private final List<String> mBuildConfigLines = Lists.newArrayList(); + private final List<ClassField> mBuildConfigFields = Lists.newArrayList(); private final List<File> mProguardFiles = Lists.newArrayList(); private final List<File> mConsumerProguardFiles = Lists.newArrayList(); - public void setBuildConfig(String... lines) { - mBuildConfigLines.clear(); - mBuildConfigLines.addAll(Arrays.asList(lines)); + public void setBuildConfigFields(@NonNull ClassField... fields) { + mBuildConfigFields.clear(); + mBuildConfigFields.addAll(Arrays.asList(fields)); } - public void setBuildConfig(String line) { - mBuildConfigLines.clear(); - mBuildConfigLines.add(line); + public void setBuildConfigFields(@NonNull Collection<ClassField> fields) { + mBuildConfigFields.clear(); + mBuildConfigFields.addAll(fields); + } + + public void addBuildConfigField(@NonNull ClassField field) { + mBuildConfigFields.add(field); } @Override @NonNull - public List<String> getBuildConfig() { - return mBuildConfigLines; + public List<ClassField> getBuildConfigFields() { + return mBuildConfigFields; } @Override @@ -64,8 +70,7 @@ public class BaseConfigImpl implements Serializable, BaseConfig { } protected void _initWith(BaseConfig that) { - mBuildConfigLines.clear(); - mBuildConfigLines.addAll(that.getBuildConfig()); + setBuildConfigFields(that.getBuildConfigFields()); mProguardFiles.clear(); mProguardFiles.addAll(that.getProguardFiles()); @@ -81,7 +86,7 @@ public class BaseConfigImpl implements Serializable, BaseConfig { BaseConfigImpl that = (BaseConfigImpl) o; - if (!mBuildConfigLines.equals(that.mBuildConfigLines)) return false; + if (!mBuildConfigFields.equals(that.mBuildConfigFields)) return false; if (!mProguardFiles.equals(that.mProguardFiles)) return false; if (!mConsumerProguardFiles.equals(that.mConsumerProguardFiles)) return false; @@ -90,7 +95,7 @@ public class BaseConfigImpl implements Serializable, BaseConfig { @Override public int hashCode() { - int result = mBuildConfigLines.hashCode(); + int result = mBuildConfigFields.hashCode(); result = 31 * result + mProguardFiles.hashCode(); result = 31 * result + mConsumerProguardFiles.hashCode(); return result; diff --git a/builder/src/main/java/com/android/builder/internal/BuildConfigGenerator.java b/builder/src/main/java/com/android/builder/internal/BuildConfigGenerator.java deleted file mode 100644 index 2d01734..0000000 --- a/builder/src/main/java/com/android/builder/internal/BuildConfigGenerator.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2011 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.builder.internal; - -import com.android.annotations.NonNull; -import com.android.annotations.Nullable; -import com.google.common.collect.Maps; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Class able to generate a BuildConfig class in Android project. - * The BuildConfig class contains constants related to the build target. - */ -public class BuildConfigGenerator { - - private final static String TEMPLATE = "BuildConfig.template"; - private final static String PH_PACKAGE = "#PACKAGE#"; - private final static String PH_DEBUG = "#DEBUG#"; - private final static String PH_LINES = "#ADDITIONAL_LINES#"; - - private final String mGenFolder; - private final String mAppPackage; - private final boolean mDebug; - - public final static String BUILD_CONFIG_NAME = "BuildConfig.java"; - - /** - * Creates a generator - * @param genFolder the gen folder of the project - * @param appPackage the application package - * @param debug whether it's a debug build - */ - public BuildConfigGenerator(@NonNull String genFolder, @NonNull String appPackage, - boolean debug) { - mGenFolder = checkNotNull(genFolder); - mAppPackage = checkNotNull(appPackage); - mDebug = debug; - } - - /** - * Returns a File representing where the BuildConfig class will be. - */ - public File getFolderPath() { - File genFolder = new File(mGenFolder); - return new File(genFolder, mAppPackage.replace('.', File.separatorChar)); - } - - public File getBuildConfigFile() { - File folder = getFolderPath(); - return new File(folder, BUILD_CONFIG_NAME); - } - - /** - * Generates the BuildConfig class. - * @param additionalLines a list of additional lines to be added to the class. - */ - public void generate(@Nullable List<String> additionalLines) throws IOException { - Map<String, String> map = Maps.newHashMap(); - map.put(PH_PACKAGE, mAppPackage); - - // Hack (see IDEA-100046): We want to avoid reporting "condition is always true" - // from the data flow inspection, so use a non-constant value. However, that defeats - // the purpose of this flag (when not in debug mode, if (BuildConfig.DEBUG && ...) will - // be completely removed by the compiler), so as a hack we do it only for the case - // where debug is true, which is the most likely scenario while the user is looking - // at source code. - //map.put(PH_DEBUG, Boolean.toString(mDebug)); - map.put(PH_DEBUG, mDebug ? "Boolean.parseBoolean(\"true\")" : "false"); - - if (additionalLines != null) { - StringBuilder sb = new StringBuilder(); - for (String line : additionalLines) { - sb.append(" ").append(line).append('\n'); - } - map.put(PH_LINES, sb.toString()); - - } else { - map.put(PH_LINES, ""); - } - - File pkgFolder = getFolderPath(); - if (!pkgFolder.isDirectory()) { - pkgFolder.mkdirs(); - } - - File buildConfigJava = new File(pkgFolder, BUILD_CONFIG_NAME); - - TemplateProcessor processor = new TemplateProcessor( - BuildConfigGenerator.class.getResourceAsStream(TEMPLATE), map); - processor.generate(buildConfigJava); - } -} diff --git a/builder/src/main/java/com/android/builder/internal/ClassFieldImpl.java b/builder/src/main/java/com/android/builder/internal/ClassFieldImpl.java new file mode 100644 index 0000000..44824b4 --- /dev/null +++ b/builder/src/main/java/com/android/builder/internal/ClassFieldImpl.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 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.builder.internal; + +import com.android.annotations.NonNull; +import com.android.builder.model.ClassField; + +import java.io.Serializable; + +/** + */ +public final class ClassFieldImpl implements ClassField, Serializable { + + private static final long serialVersionUID = 1L; + + @NonNull + private final String type; + @NonNull + private final String name; + @NonNull + private final String value; + + public ClassFieldImpl(@NonNull String type, @NonNull String name, @NonNull String value) { + //noinspection ConstantConditions + if (type == null || name == null || value == null) { + throw new NullPointerException("Build Config field cannot have a null parameter"); + } + this.type = type; + this.name = name; + this.value = value; + } + + @Override + @NonNull + public String getType() { + return type; + } + + @Override + @NonNull + public String getName() { + return name; + } + + @Override + @NonNull + public String getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ClassFieldImpl that = (ClassFieldImpl) o; + + if (!name.equals(that.name)) return false; + if (!type.equals(that.type)) return false; + if (!value.equals(that.value)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = type.hashCode(); + result = 31 * result + name.hashCode(); + result = 31 * result + value.hashCode(); + return result; + } +} diff --git a/builder/src/main/java/com/android/builder/internal/NdkConfigImpl.java b/builder/src/main/java/com/android/builder/internal/NdkConfigImpl.java index 88422e9..153d702 100644 --- a/builder/src/main/java/com/android/builder/internal/NdkConfigImpl.java +++ b/builder/src/main/java/com/android/builder/internal/NdkConfigImpl.java @@ -29,7 +29,7 @@ public class NdkConfigImpl implements NdkConfig { private String moduleName; private String cFlags; - private String ldLibs; + private Set<String> ldLibs; private Set<String> abiFilters; private String stl; @@ -54,7 +54,7 @@ public class NdkConfigImpl implements NdkConfig { @Override @Nullable - public String getLdLibs() { + public Set<String> getLdLibs() { return ldLibs; } @@ -80,6 +80,7 @@ public class NdkConfigImpl implements NdkConfig { stl = ndkConfig.getStl(); } + // append if (ndkConfig.getAbiFilters() != null) { if (abiFilters == null) { abiFilters = Sets.newHashSetWithExpectedSize(ndkConfig.getAbiFilters().size()); @@ -89,17 +90,19 @@ public class NdkConfigImpl implements NdkConfig { abiFilters.addAll(ndkConfig.getAbiFilters()); } - // append if (cFlags == null) { cFlags = ndkConfig.getcFlags(); } else if (ndkConfig.getcFlags() != null) { cFlags = cFlags + " " + ndkConfig.getcFlags(); } - if (ldLibs == null) { - ldLibs = ndkConfig.getLdLibs(); - } else if (ndkConfig.getLdLibs() != null) { - ldLibs = ldLibs + " " + ndkConfig.getLdLibs(); + if (ndkConfig.getLdLibs() != null) { + if (ldLibs == null) { + ldLibs = Sets.newHashSetWithExpectedSize(ndkConfig.getLdLibs().size()); + } else { + ldLibs.clear(); + } + ldLibs.addAll(ndkConfig.getLdLibs()); } } } diff --git a/builder/src/main/java/com/android/builder/internal/StringHelper.java b/builder/src/main/java/com/android/builder/internal/StringHelper.java new file mode 100644 index 0000000..4a59a82 --- /dev/null +++ b/builder/src/main/java/com/android/builder/internal/StringHelper.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013 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.builder.internal; + +import com.android.annotations.NonNull; + +import java.util.Locale; + +/** + */ +public class StringHelper { + + @NonNull + public static String capitalize(@NonNull String string) { + StringBuilder sb = new StringBuilder(); + sb.append(string.substring(0, 1).toUpperCase(Locale.US)).append(string.substring(1)); + + return sb.toString(); + } +} diff --git a/builder/src/main/resources/com/android/builder/internal/BuildConfig.template b/builder/src/main/resources/com/android/builder/internal/BuildConfig.template deleted file mode 100644 index 71b4b9c..0000000 --- a/builder/src/main/resources/com/android/builder/internal/BuildConfig.template +++ /dev/null @@ -1,7 +0,0 @@ -/** Automatically generated file. DO NOT MODIFY */ -package #PACKAGE#; - -public final class BuildConfig { - public static final boolean DEBUG = #DEBUG#; - -#ADDITIONAL_LINES#}
\ No newline at end of file diff --git a/builder/src/test/java/com/android/builder/VariantConfigurationTest.java b/builder/src/test/java/com/android/builder/VariantConfigurationTest.java index 6d244ac..dfe8ea4 100644 --- a/builder/src/test/java/com/android/builder/VariantConfigurationTest.java +++ b/builder/src/test/java/com/android/builder/VariantConfigurationTest.java @@ -57,6 +57,11 @@ public class VariantConfigurationTest extends TestCase { public String getVersionName(@NonNull File manifestFile) { return "1.0"; } + + @Override + public int getVersionCode(@NonNull File manifestFile) { + return 1; + } } @Override @@ -128,7 +133,7 @@ public class VariantConfigurationTest extends TestCase { VariantConfiguration variant = new VariantConfiguration( mDefaultConfig, new MockSourceProvider("main"), mBuildType, new MockSourceProvider("debug"), - VariantConfiguration.Type.DEFAULT, "test") { + VariantConfiguration.Type.DEFAULT) { // don't do validation. @Override protected void validate() { @@ -145,7 +150,7 @@ public class VariantConfigurationTest extends TestCase { VariantConfiguration variant = new VariantConfiguration( mDefaultConfig, new MockSourceProvider("main"), mBuildType, new MockSourceProvider("debug"), - VariantConfiguration.Type.DEFAULT, "test") { + VariantConfiguration.Type.DEFAULT) { @Override public String getPackageFromManifest() { return packageName; @@ -165,7 +170,7 @@ public class VariantConfigurationTest extends TestCase { VariantConfiguration variant = new VariantConfiguration( mDefaultConfig, new MockSourceProvider("main"), mBuildType, new MockSourceProvider("debug"), - VariantConfiguration.Type.DEFAULT, "test") { + VariantConfiguration.Type.DEFAULT) { @Override public String getVersionNameFromManifest() { return versionName; diff --git a/builder/src/test/java/com/android/builder/compiling/BuildConfigGeneratorTest.java b/builder/src/test/java/com/android/builder/compiling/BuildConfigGeneratorTest.java new file mode 100644 index 0000000..0bb2200 --- /dev/null +++ b/builder/src/test/java/com/android/builder/compiling/BuildConfigGeneratorTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013 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.builder.compiling; + +import com.android.builder.AndroidBuilder; +import com.google.common.base.Charsets; +import com.google.common.collect.Lists; +import com.google.common.io.Files; +import junit.framework.TestCase; + +import java.io.File; +import java.util.List; + +@SuppressWarnings("ResultOfMethodCallIgnored") +public class BuildConfigGeneratorTest extends TestCase { + public void testFalse() throws Exception { + File tempDir = Files.createTempDir(); + BuildConfigGenerator generator = new BuildConfigGenerator(tempDir.getPath(), + "my.app.pkg"); + + generator.addField("boolean", "DEBUG", "false").generate(); + + File file = generator.getBuildConfigFile(); + assertTrue(file.exists()); + String actual = Files.toString(file, Charsets.UTF_8); + assertEquals( + "/**\n" + + " * Automatically generated file. DO NOT MODIFY\n" + + " */\n" + + "package my.app.pkg;\n" + + "\n" + + "public final class BuildConfig {\n" + + " public static final boolean DEBUG = false;\n" + + "}\n", actual); + file.delete(); + tempDir.delete(); + } + + public void testTrue() throws Exception { + File tempDir = Files.createTempDir(); + BuildConfigGenerator generator = new BuildConfigGenerator(tempDir.getPath(), + "my.app.pkg"); + generator.addField("boolean", "DEBUG", "Boolean.parseBoolean(\"true\")").generate(); + + File file = generator.getBuildConfigFile(); + assertTrue(file.exists()); + String actual = Files.toString(file, Charsets.UTF_8); + assertEquals( + "/**\n" + + " * Automatically generated file. DO NOT MODIFY\n" + + " */\n" + + "package my.app.pkg;\n" + + "\n" + + "public final class BuildConfig {\n" + + " public static final boolean DEBUG = Boolean.parseBoolean(\"true\");\n" + + "}\n", actual); + file.delete(); + tempDir.delete(); + } + + public void testExtra() throws Exception { + File tempDir = Files.createTempDir(); + BuildConfigGenerator generator = new BuildConfigGenerator(tempDir.getPath(), + "my.app.pkg"); + + List<Object> items = Lists.newArrayList(); + items.add("Extra line"); + items.add(AndroidBuilder.createClassField("int", "EXTRA", "42")); + + generator.addItems(items).generate(); + + File file = generator.getBuildConfigFile(); + assertTrue(file.exists()); + String actual = Files.toString(file, Charsets.UTF_8); + assertEquals( + "/**\n" + + " * Automatically generated file. DO NOT MODIFY\n" + + " */\n" + + "package my.app.pkg;\n" + + "\n" + + "public final class BuildConfig {\n" + + " // Extra line\n" + + " public static final int EXTRA = 42;\n" + + "}\n", actual); + file.delete(); + tempDir.delete(); + } +} diff --git a/builder/src/test/java/com/android/builder/internal/BuildConfigGeneratorTest.java b/builder/src/test/java/com/android/builder/internal/BuildConfigGeneratorTest.java deleted file mode 100644 index 0f5ecd3..0000000 --- a/builder/src/test/java/com/android/builder/internal/BuildConfigGeneratorTest.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.android.builder.internal; - -import com.google.common.base.Charsets; -import com.google.common.io.Files; - -import junit.framework.TestCase; - -import java.io.File; -import java.util.Arrays; -import java.util.Collections; - -@SuppressWarnings("ResultOfMethodCallIgnored") -public class BuildConfigGeneratorTest extends TestCase { - public void testFalse() throws Exception { - File tempDir = Files.createTempDir(); - BuildConfigGenerator generator = new BuildConfigGenerator(tempDir.getPath(), - "my.app.pkg", false); - generator.generate(Collections.<String>emptyList()); - File file = generator.getBuildConfigFile(); - assertTrue(file.exists()); - String actual = Files.toString(file, Charsets.UTF_8); - assertEquals( - "/** Automatically generated file. DO NOT MODIFY */\n" - + "package my.app.pkg;\n" - + "\n" - + "public final class BuildConfig {\n" - + " public static final boolean DEBUG = false;\n" - + "\n" - + "}", actual); - file.delete(); - tempDir.delete(); - } - - public void testTrue() throws Exception { - File tempDir = Files.createTempDir(); - BuildConfigGenerator generator = new BuildConfigGenerator(tempDir.getPath(), - "my.app.pkg", true); - generator.generate(Collections.<String>emptyList()); - File file = generator.getBuildConfigFile(); - assertTrue(file.exists()); - String actual = Files.toString(file, Charsets.UTF_8); - assertEquals( - "/** Automatically generated file. DO NOT MODIFY */\n" - + "package my.app.pkg;\n" - + "\n" - + "public final class BuildConfig {\n" - + " public static final boolean DEBUG = Boolean.parseBoolean(\"true\");\n" - + "\n" - + "}", actual); - file.delete(); - tempDir.delete(); - } - - public void testExtra() throws Exception { - File tempDir = Files.createTempDir(); - BuildConfigGenerator generator = new BuildConfigGenerator(tempDir.getPath(), - "my.app.pkg", false); - generator.generate(Arrays.asList("// Extra line:", "public static int EXTRA = 42;")); - File file = generator.getBuildConfigFile(); - assertTrue(file.exists()); - String actual = Files.toString(file, Charsets.UTF_8); - assertEquals( - "/** Automatically generated file. DO NOT MODIFY */\n" - + "package my.app.pkg;\n" - + "\n" - + "public final class BuildConfig {\n" - + " public static final boolean DEBUG = false;\n" - + "\n" - + " // Extra line:\n" - + " public static int EXTRA = 42;\n" - + "}", actual); - file.delete(); - tempDir.delete(); - } -} diff --git a/changelog.txt b/changelog.txt index 563b9c7..b5809d6 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,9 +1,31 @@ 0.7.0 - Requires Gradle 1.9 +- You can now have a variant specific source folder if you have flavors. + Only for app (not library or test). Name is src/flavorDebug/... or src/flavor1Flavor2Debug/ + (note the camelcase naming, with lower case for first letter). + Its components (res, manifest, etc...) have higher priority than components from build type + or flavors. + It also comes with dependency configuration, so you can do + flavorDebugCompile '...' +- Build config improvements and DSL changes. + The previous DSL proprety: + buildConfigLine "<value>" + has changed to + buildConfigField "<type>", "<name>", "<value>" + This allows override a field (see 'basic' sample) + Also, BuildConfig now automatically contains constants for + PACKAGE_NAME, VERSION_CODE, VERSION_NAME, BUILD_TYPE, FLAVOR as well as FLAVOR1, FLAVOR2, etc... if there are several flavor dimensions. - Switch to ProGuard 4.10 - Added ability to test proguarded (obfuscated) apps. - Jar files are now pre-dexed for faster dexing. - First pass at NDK integration +- API to add new generated source folders: + variant.addJavaSourceFoldersToModel(sourceFolder1, sourceFolders2,...) + This adds the source folder to the model (for IDE support). + Another API: + variant.registerJavaGeneratingTask(task, sourceFolder1, sourceFolders2,...) + This automatically adds the dependency on the task, sets up the JavaCompile task inputs and propagates + the folders to the model for IDE integration. 0.6.3 - Fixed ClassNotFoundException:MergingException introduced in 0.6.2 diff --git a/gradle-model/src/test/java/com/android/build/gradle/model/AndroidProjectTest.java b/gradle-model/src/test/java/com/android/build/gradle/model/AndroidProjectTest.java index 0af75cc..cee947a 100644 --- a/gradle-model/src/test/java/com/android/build/gradle/model/AndroidProjectTest.java +++ b/gradle-model/src/test/java/com/android/build/gradle/model/AndroidProjectTest.java @@ -191,8 +191,8 @@ public class AndroidProjectTest extends TestCase { assertEquals("Variant Count", 2 , variants.size()); // debug variant - Variant debugVariant = variants.get("Debug"); - assertNotNull("Debug Variant null-check", debugVariant); + Variant debugVariant = variants.get("debug"); + assertNotNull("debug Variant null-check", debugVariant); new ProductFlavorTester(debugVariant.getMergedFlavor(), "Debug Merged Flavor") .setVersionCode(12) .setVersionName("2.0") @@ -220,12 +220,12 @@ public class AndroidProjectTest extends TestCase { assertNotNull("Test output file null-check", debugTestInfo.getOutputFile()); assertTrue("Test signed check", debugTestInfo.isSigned()); assertEquals("Test signingConfig name", "myConfig", debugTestInfo.getSigningConfigName()); - assertEquals("Test sourceGenTask", "generateTestSources", debugTestInfo.getSourceGenTaskName()); - assertEquals("Test javaCompileTask", "compileTestJava", debugTestInfo.getJavaCompileTaskName()); + assertEquals("Test sourceGenTask", "generateDebugTestSources", debugTestInfo.getSourceGenTaskName()); + assertEquals("Test javaCompileTask", "compileDebugTestJava", debugTestInfo.getJavaCompileTaskName()); // release variant, not tested. - Variant releaseVariant = variants.get("Release"); - assertNotNull("Release Variant null-check", releaseVariant); + Variant releaseVariant = variants.get("release"); + assertNotNull("release Variant null-check", releaseVariant); ArtifactInfo relMainInfo = releaseVariant.getMainArtifactInfo(); assertNotNull("Release main info null-check", relMainInfo); @@ -360,11 +360,11 @@ public class AndroidProjectTest extends TestCase { Map<String, Variant> variants = model.getVariants(); assertEquals("Variant Count", 8 , variants.size()); - Variant f1faDebugVariant = variants.get("F1FaDebug"); - assertNotNull("F1faDebug Variant null-check", f1faDebugVariant); + Variant f1faDebugVariant = variants.get("f1FaDebug"); + assertNotNull("f1faDebug Variant null-check", f1faDebugVariant); new ProductFlavorTester(f1faDebugVariant.getMergedFlavor(), "F1faDebug Merged Flavor") .test(); - new VariantTester(f1faDebugVariant, projectDir, "flavors-f1fa-debug-unaligned.apk").test(); + new VariantTester(f1faDebugVariant, projectDir, "flavors-f1-fa-debug-unaligned.apk").test(); } public void testTicTacToe() throws Exception { @@ -377,7 +377,7 @@ public class AndroidProjectTest extends TestCase { ProjectData appModelData = map.get(":app"); assertNotNull("app module model null-check", appModelData); - Dependencies dependencies = appModelData.model.getVariants().get("Debug").getMainArtifactInfo().getDependencies(); + Dependencies dependencies = appModelData.model.getVariants().get("debug").getMainArtifactInfo().getDependencies(); assertNotNull(dependencies); List<AndroidLibrary> libs = dependencies.getLibraries(); @@ -407,7 +407,7 @@ public class AndroidProjectTest extends TestCase { ProductFlavorContainer flavor1 = model.getProductFlavors().get("flavor1"); assertNotNull(flavor1); - Variant flavor1Debug = variants.get("Flavor1Debug"); + Variant flavor1Debug = variants.get("flavor1Debug"); assertNotNull(flavor1Debug); Dependencies dependencies = flavor1Debug.getMainArtifactInfo().getDependencies(); @@ -423,7 +423,7 @@ public class AndroidProjectTest extends TestCase { ProductFlavorContainer flavor2 = model.getProductFlavors().get("flavor2"); assertNotNull(flavor2); - Variant flavor2Debug = variants.get("Flavor2Debug"); + Variant flavor2Debug = variants.get("flavor2Debug"); assertNotNull(flavor2Debug); dependencies = flavor2Debug.getMainArtifactInfo().getDependencies(); @@ -447,8 +447,8 @@ public class AndroidProjectTest extends TestCase { Map<String, Variant> variants = model.getVariants(); assertEquals("Variant count", 2, variants.size()); - Variant variant = variants.get("Release"); - assertNotNull("Release variant null-check", variant); + Variant variant = variants.get("release"); + assertNotNull("release variant null-check", variant); ArtifactInfo mainInfo = variant.getMainArtifactInfo(); assertNotNull("Main Artifact null-check", mainInfo); @@ -467,6 +467,40 @@ public class AndroidProjectTest extends TestCase { assertEquals("jar dep count", 2, jars.size()); } + public void testGenFolderApi() throws Exception { + // Load the custom model for the project + ProjectData projectData = getModelForProject("genFolderApi"); + + AndroidProject model = projectData.model; + File projectDir = projectData.projectDir; + + File buildDir = new File(projectDir, "build"); + + for (Variant variant : model.getVariants().values()) { + + ArtifactInfo mainInfo = variant.getMainArtifactInfo(); + assertNotNull( + "Null-check on mainArtifactInfo for " + variant.getDisplayName(), + mainInfo); + + // get the generated source folders. + List<File> genFolder = mainInfo.getGeneratedSourceFolders(); + + // We're looking for a custom folder + String folderStart = new File(buildDir, "customCode").getAbsolutePath() + File.separatorChar; + boolean found = false; + for (File f : genFolder) { + if (f.getAbsolutePath().startsWith(folderStart)) { + found = true; + break; + } + } + + assertTrue("custom generated source folder check", found); + } + } + + /** * Returns the SDK folder as built from the Android source tree. * @return the SDK diff --git a/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java b/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java index b7fcc98..5372005 100644 --- a/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java +++ b/gradle/src/build-test/groovy/com/android/build/gradle/AutomatedBuildTest.java @@ -35,11 +35,11 @@ public class AutomatedBuildTest extends BuildTest { private static final String[] sBuiltProjects = new String[] { "aidl", "api", "applibtest", "assets", "attrOrder", "basic", "dependencies", - "dependencyChecker", "flavored", "flavorlib", "flavors", "libProguardJarDep", - "libProguardLibDep", "libTestDep", "libsTest", "localJars", "migrated", "multiproject", - "multires", "ndkSanAngeles", "overlay1", "overlay2", "pkgOverride", "proguard", - "proguardLib", "renderscript", "renderscriptInLib", "renderscriptMultiSrc", - "rsSupportMode", "sameNamedLibs", "tictactoe" /*, "autorepo"*/ + "dependencyChecker", "flavored", "flavorlib", "flavors", "genFolderApi", + "libProguardJarDep", "libProguardLibDep", "libTestDep", "libsTest", "localJars", + "migrated", "multiproject", "multires", "ndkSanAngeles", "overlay1", "overlay2", + "pkgOverride", "proguard", "proguardLib", "renderscript", "renderscriptInLib", + "renderscriptMultiSrc", "rsSupportMode", "sameNamedLibs", "tictactoe" /*, "autorepo"*/ }; private static final String[] sReportProjects = new String[] { diff --git a/gradle/src/main/groovy/com/android/build/gradle/AppPlugin.groovy b/gradle/src/main/groovy/com/android/build/gradle/AppPlugin.groovy index 77e9807..33db4c3 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/AppPlugin.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/AppPlugin.groovy @@ -20,6 +20,7 @@ import com.android.annotations.Nullable import com.android.build.gradle.api.BaseVariant import com.android.build.gradle.internal.BuildTypeData import com.android.build.gradle.internal.ConfigurationProvider +import com.android.build.gradle.internal.ConfigurationProviderImpl import com.android.build.gradle.internal.ProductFlavorData import com.android.build.gradle.internal.api.ApplicationVariantImpl import com.android.build.gradle.internal.api.DefaultAndroidSourceSet @@ -139,7 +140,7 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr throw new RuntimeException("BuildType names cannot collide with ProductFlavor names") } - def sourceSet = extension.sourceSetsContainer.create(name) + def sourceSet = extension.sourceSetsContainer.maybeCreate(name) BuildTypeData buildTypeData = new BuildTypeData(buildType, sourceSet, project) project.tasks.assemble.dependsOn buildTypeData.assembleTask @@ -161,9 +162,9 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr throw new RuntimeException("ProductFlavor names cannot collide with BuildType names") } - def mainSourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.create(productFlavor.name) + def mainSourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(productFlavor.name) String testName = "${INSTRUMENT_TEST}${productFlavor.name.capitalize()}" - def testSourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.create(testName) + def testSourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(testName) ProductFlavorData<GroupableProductFlavorDsl> productFlavorData = new ProductFlavorData<GroupableProductFlavorDsl>( @@ -296,12 +297,13 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr defaultConfigData.productFlavor, defaultConfigData.sourceSet, buildTypeData.buildType, - buildTypeData.sourceSet, project.name) + buildTypeData.sourceSet) // create the variant and get its internal storage object. ApplicationVariantData appVariantData = new ApplicationVariantData(variantConfig) VariantDependencies variantDep = VariantDependencies.compute( - project, appVariantData.name, buildTypeData, defaultConfigData.mainProvider) + project, appVariantData.variantConfiguration.fullName, + buildTypeData, defaultConfigData.mainProvider) appVariantData.setVariantDependency(variantDep) variantDataList.add(appVariantData) @@ -319,8 +321,7 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr defaultConfigData.testSourceSet, testData.buildType, null, - VariantConfiguration.Type.TEST, testedVariantData.variantConfiguration, - project.name) + VariantConfiguration.Type.TEST, testedVariantData.variantConfiguration) // create the internal storage for this variant. def testVariantData = new TestVariantData(testVariantConfig, testedVariantData) @@ -330,7 +331,8 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr // dependencies for the test variant VariantDependencies variantDep = VariantDependencies.compute( - project, testVariantData.name, defaultConfigData.testProvider) + project, testVariantData.variantConfiguration.fullName, + defaultConfigData.testProvider) testVariantData.setVariantDependency(variantDep) // now loop on the VariantDependency and resolve them, and create the tasks @@ -434,8 +436,7 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr extension.defaultConfig, getDefaultConfigData().sourceSet, buildTypeData.buildType, - buildTypeData.sourceSet, - project.name) + buildTypeData.sourceSet) for (ProductFlavorData data : flavorDataList) { variantConfig.addProductFlavor( @@ -449,8 +450,13 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr // create the variant and get its internal storage object. ApplicationVariantData appVariantData = new ApplicationVariantData(variantConfig) + + DefaultAndroidSourceSet sourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(variantConfig.fullName) + variantConfig.setVariantSourceProvider(sourceSet) + variantProviders.add(new ConfigurationProviderImpl(project, sourceSet)) + VariantDependencies variantDep = VariantDependencies.compute( - project, appVariantData.name, + project, appVariantData.variantConfiguration.fullName, variantProviders.toArray(new ConfigurationProvider[variantProviders.size()])) appVariantData.setVariantDependency(variantDep) @@ -470,7 +476,7 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr testData.buildType, null, VariantConfiguration.Type.TEST, - testedVariantData.variantConfiguration, project.name) + testedVariantData.variantConfiguration) /// add the container of dependencies // the order of the libraries is important. In descending order: @@ -495,7 +501,7 @@ class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Pr // dependencies for the test variant VariantDependencies variantDep = VariantDependencies.compute( - project, testVariantData.name, + project, testVariantData.variantConfiguration.fullName, testVariantProviders.toArray(new ConfigurationProvider[testVariantProviders.size()])) testVariantData.setVariantDependency(variantDep) diff --git a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy index b556641..f3d3fbe 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy @@ -346,7 +346,8 @@ public abstract class BasePlugin { protected void createProcessManifestTask(BaseVariantData variantData, String manifestOurDir) { - def processManifestTask = project.tasks.create("process${variantData.name}Manifest", + def processManifestTask = project.tasks.create( + "process${variantData.variantConfiguration.fullName.capitalize()}Manifest", ProcessAppManifest) variantData.processManifestTask = processManifestTask processManifestTask.dependsOn variantData.prepareDependenciesTask @@ -373,7 +374,7 @@ public abstract class BasePlugin { getManifestDependencies(config.directLibraries) } processManifestTask.conventionMapping.versionCode = { - mergedFlavor.versionCode + config.versionCode } processManifestTask.conventionMapping.minSdkVersion = { mergedFlavor.minSdkVersion @@ -383,13 +384,14 @@ public abstract class BasePlugin { } processManifestTask.conventionMapping.manifestOutputFile = { project.file( - "$project.buildDir/${manifestOurDir}/$variantData.dirName/AndroidManifest.xml") + "$project.buildDir/${manifestOurDir}/${variantData.variantConfiguration.dirName}/AndroidManifest.xml") } } protected void createProcessTestManifestTask(BaseVariantData variantData, String manifestOurDir) { - def processTestManifestTask = project.tasks.create("process${variantData.name}TestManifest", + def processTestManifestTask = project.tasks.create( + "process${variantData.variantConfiguration.fullName.capitalize()}Manifest", ProcessTestManifest) variantData.processManifestTask = processTestManifestTask processTestManifestTask.dependsOn variantData.prepareDependenciesTask @@ -425,14 +427,15 @@ public abstract class BasePlugin { } processTestManifestTask.conventionMapping.manifestOutputFile = { project.file( - "$project.buildDir/${manifestOurDir}/$variantData.dirName/AndroidManifest.xml") + "$project.buildDir/${manifestOurDir}/${variantData.variantConfiguration.dirName}/AndroidManifest.xml") } } protected void createRenderscriptTask(BaseVariantData variantData) { VariantConfiguration config = variantData.variantConfiguration - def renderscriptTask = project.tasks.create("compile${variantData.name}Renderscript", + def renderscriptTask = project.tasks.create( + "compile${variantData.variantConfiguration.fullName.capitalize()}Renderscript", RenderscriptCompile) variantData.renderscriptCompileTask = renderscriptTask @@ -450,16 +453,16 @@ public abstract class BasePlugin { renderscriptTask.conventionMapping.importDirs = { config.renderscriptImports } renderscriptTask.conventionMapping.sourceOutputDir = { - project.file("$project.buildDir/source/rs/$variantData.dirName") + project.file("$project.buildDir/source/rs/${variantData.variantConfiguration.dirName}") } renderscriptTask.conventionMapping.resOutputDir = { - project.file("$project.buildDir/res/rs/$variantData.dirName") + project.file("$project.buildDir/res/rs/${variantData.variantConfiguration.dirName}") } renderscriptTask.conventionMapping.objOutputDir = { - project.file("$project.buildDir/rs/$variantData.dirName/obj") + project.file("$project.buildDir/rs/${variantData.variantConfiguration.dirName}/obj") } renderscriptTask.conventionMapping.libOutputDir = { - project.file("$project.buildDir/rs/$variantData.dirName/lib") + project.file("$project.buildDir/rs/${variantData.variantConfiguration.dirName}/lib") } renderscriptTask.conventionMapping.ndkConfig = { config.ndkConfig } } @@ -469,7 +472,7 @@ public abstract class BasePlugin { MergeResources mergeResourcesTask = basicCreateMergeResourcesTask( variantData, "merge", - "$project.buildDir/res/all/$variantData.dirName", + "$project.buildDir/res/all/${variantData.variantConfiguration.dirName}", true /*includeDependencies*/, process9Patch) variantData.mergeResourcesTask = mergeResourcesTask @@ -482,13 +485,14 @@ public abstract class BasePlugin { final boolean includeDependencies, final boolean process9Patch) { MergeResources mergeResourcesTask = project.tasks.create( - "$taskNamePrefix${variantData.name}Resources", MergeResources) + "$taskNamePrefix${variantData.variantConfiguration.fullName.capitalize()}Resources", + MergeResources) mergeResourcesTask.dependsOn variantData.prepareDependenciesTask, variantData.renderscriptCompileTask mergeResourcesTask.plugin = this mergeResourcesTask.variant = variantData mergeResourcesTask.incrementalFolder = project.file( - "$project.buildDir/incremental/${taskNamePrefix}Resources/$variantData.dirName") + "$project.buildDir/incremental/${taskNamePrefix}Resources/${variantData.variantConfiguration.dirName}") mergeResourcesTask.process9Patch = process9Patch @@ -507,17 +511,19 @@ public abstract class BasePlugin { @Nullable String outputLocation, final boolean includeDependencies) { if (outputLocation == null) { - outputLocation = "$project.buildDir/assets/$variantData.dirName" + outputLocation = "$project.buildDir/assets/${variantData.variantConfiguration.dirName}" } - def mergeAssetsTask = project.tasks.create("merge${variantData.name}Assets", MergeAssets) + def mergeAssetsTask = project.tasks.create( + "merge${variantData.variantConfiguration.fullName.capitalize()}Assets", + MergeAssets) variantData.mergeAssetsTask = mergeAssetsTask mergeAssetsTask.dependsOn variantData.prepareDependenciesTask mergeAssetsTask.plugin = this mergeAssetsTask.variant = variantData mergeAssetsTask.incrementalFolder = - project.file("$project.buildDir/incremental/mergeAssets/$variantData.dirName") + project.file("$project.buildDir/incremental/mergeAssets/${variantData.variantConfiguration.dirName}") mergeAssetsTask.conventionMapping.inputAssetSets = { variantData.variantConfiguration.getAssetSets(includeDependencies) @@ -527,7 +533,8 @@ public abstract class BasePlugin { protected void createBuildConfigTask(BaseVariantData variantData) { def generateBuildConfigTask = project.tasks.create( - "generate${variantData.name}BuildConfig", GenerateBuildConfig) + "generate${variantData.variantConfiguration.fullName.capitalize()}BuildConfig", + GenerateBuildConfig) variantData.generateBuildConfigTask = generateBuildConfigTask VariantConfiguration variantConfiguration = variantData.variantConfiguration @@ -542,29 +549,54 @@ public abstract class BasePlugin { generateBuildConfigTask.plugin = this generateBuildConfigTask.variant = variantData - generateBuildConfigTask.conventionMapping.packageName = { + generateBuildConfigTask.conventionMapping.buildConfigPackageName = { variantConfiguration.originalPackageName } + generateBuildConfigTask.conventionMapping.appPackageName = { + variantConfiguration.packageName + } + + generateBuildConfigTask.conventionMapping.versionName = { + variantConfiguration.versionName + } + + generateBuildConfigTask.conventionMapping.versionCode = { + variantConfiguration.versionCode + } + generateBuildConfigTask.conventionMapping.debuggable = { variantConfiguration.buildType.isDebuggable() } - generateBuildConfigTask.conventionMapping.javaLines = { - variantConfiguration.buildConfigLines + generateBuildConfigTask.conventionMapping.buildTypeName = { + variantConfiguration.buildType.name + } + + generateBuildConfigTask.conventionMapping.flavorName = { + variantConfiguration.flavorName + } + + generateBuildConfigTask.conventionMapping.flavorNames = { + variantConfiguration.flavorNames + } + + generateBuildConfigTask.conventionMapping.items = { + variantConfiguration.buildConfigItems } generateBuildConfigTask.conventionMapping.sourceOutputDir = { - project.file("$project.buildDir/source/buildConfig/${variantData.dirName}") + project.file("$project.buildDir/source/buildConfig/${variantData.variantConfiguration.dirName}") } } protected void createProcessResTask(BaseVariantData variantData) { - createProcessResTask(variantData, "$project.buildDir/symbols/$variantData.dirName") + createProcessResTask(variantData, "$project.buildDir/symbols/${variantData.variantConfiguration.dirName}") } protected void createProcessResTask(BaseVariantData variantData, final String symbolLocation) { - def processResources = project.tasks.create("process${variantData.name}Resources", + def processResources = project.tasks.create( + "process${variantData.variantConfiguration.fullName.capitalize()}Resources", ProcessAndroidResources) variantData.processResourcesTask = processResources @@ -597,18 +629,18 @@ public abstract class BasePlugin { // TODO: unify with generateBuilderConfig, compileAidl, and library packaging somehow? processResources.conventionMapping.sourceOutputDir = { - project.file("$project.buildDir/source/r/$variantData.dirName") + project.file("$project.buildDir/source/r/${variantData.variantConfiguration.dirName}") } processResources.conventionMapping.textSymbolOutputDir = { project.file(symbolLocation) } processResources.conventionMapping.packageOutputFile = { project.file( - "$project.buildDir/libs/${project.archivesBaseName}-${variantData.baseName}.ap_") + "$project.buildDir/libs/${project.archivesBaseName}-${variantData.variantConfiguration.baseName}.ap_") } if (variantConfiguration.buildType.runProguard) { processResources.conventionMapping.proguardOutputFile = { - project.file("$project.buildDir/proguard/${variantData.dirName}/aapt_rules.txt") + project.file("$project.buildDir/proguard/${variantData.variantConfiguration.dirName}/aapt_rules.txt") } } @@ -620,7 +652,8 @@ public abstract class BasePlugin { protected void createProcessJavaResTask(BaseVariantData variantData) { VariantConfiguration variantConfiguration = variantData.variantConfiguration - Copy processResources = project.tasks.create("process${variantData.name}JavaRes", + Copy processResources = project.tasks.create( + "process${variantData.variantConfiguration.fullName.capitalize()}JavaRes", ProcessResources); variantData.processJavaResourcesTask = processResources @@ -638,14 +671,16 @@ public abstract class BasePlugin { } processResources.conventionMapping.destinationDir = { - project.file("$project.buildDir/javaResources/$variantData.dirName") + project.file("$project.buildDir/javaResources/${variantData.variantConfiguration.dirName}") } } protected void createAidlTask(BaseVariantData variantData) { VariantConfiguration variantConfiguration = variantData.variantConfiguration - def compileTask = project.tasks.create("compile${variantData.name}Aidl", AidlCompile) + def compileTask = project.tasks.create( + "compile${variantData.variantConfiguration.fullName.capitalize()}Aidl", + AidlCompile) variantData.aidlCompileTask = compileTask variantData.sourceGenTask.dependsOn compileTask @@ -654,19 +689,21 @@ public abstract class BasePlugin { compileTask.plugin = this compileTask.variant = variantData compileTask.incrementalFolder = - project.file("$project.buildDir/incremental/aidl/$variantData.dirName") + project.file("$project.buildDir/incremental/aidl/${variantData.variantConfiguration.dirName}") compileTask.conventionMapping.sourceDirs = { variantConfiguration.aidlSourceList } compileTask.conventionMapping.importDirs = { variantConfiguration.aidlImports } compileTask.conventionMapping.sourceOutputDir = { - project.file("$project.buildDir/source/aidl/$variantData.dirName") + project.file("$project.buildDir/source/aidl/${variantData.variantConfiguration.dirName}") } } protected void createCompileTask(BaseVariantData variantData, BaseVariantData testedVariantData) { - def compileTask = project.tasks.create("compile${variantData.name}Java", JavaCompile) + def compileTask = project.tasks.create( + "compile${variantData.variantConfiguration.fullName.capitalize()}Java", + JavaCompile) variantData.javaCompileTask = compileTask compileTask.dependsOn variantData.sourceGenTask @@ -707,10 +744,10 @@ public abstract class BasePlugin { compileTask.dependsOn project.configurations.compile.buildDependencies compileTask.conventionMapping.destinationDir = { - project.file("$project.buildDir/classes/$variantData.dirName") + project.file("$project.buildDir/classes/${variantData.variantConfiguration.dirName}") } compileTask.conventionMapping.dependencyCacheDir = { - project.file("$project.buildDir/dependency-cache/$variantData.dirName") + project.file("$project.buildDir/dependency-cache/${variantData.variantConfiguration.dirName}") } // set source/target compatibility @@ -732,14 +769,15 @@ public abstract class BasePlugin { protected void createNdkTasks(@NonNull BaseVariantData variantData) { createNdkTasks( variantData, - { project.file("$project.buildDir/ndk/$variantData.dirName/lib") } + { project.file("$project.buildDir/ndk/${variantData.variantConfiguration.dirName}/lib") } ) } protected void createNdkTasks(@NonNull BaseVariantData variantData, @NonNull Closure<File> soFolderClosure) { NdkCompile ndkCompile = project.tasks.create( - "compile${variantData.name}Ndk", NdkCompile) + "compile${variantData.variantConfiguration.fullName.capitalize()}Ndk", + NdkCompile) ndkCompile.plugin = this ndkCompile.variant = variantData @@ -747,26 +785,10 @@ public abstract class BasePlugin { VariantConfiguration variantConfig = variantData.variantConfiguration - ndkCompile.conventionMapping.sourceFolders = { - - Set<File> sourceList = Sets.newHashSet() - - sourceList.addAll(((AndroidSourceSet) variantConfig.defaultSourceSet).jni.srcDirs) - - if (variantConfig.getType() != VariantConfiguration.Type.TEST) { - sourceList.addAll(((AndroidSourceSet) variantConfig.buildTypeSourceSet).jni.srcDirs) - } - if (variantConfig.hasFlavors()) { - for (SourceProvider flavorSourceSet : variantConfig.flavorSourceSets) { - sourceList.addAll(((AndroidSourceSet) flavorSourceSet).jni.srcDirs) - } - } - - return sourceList - } + ndkCompile.conventionMapping.sourceFolders = { variantConfig.jniSourceList } ndkCompile.conventionMapping.generatedMakefile = { - project.file("$project.buildDir/ndk/$variantData.dirName/Android.mk") + project.file("$project.buildDir/ndk/${variantData.variantConfiguration.dirName}/Android.mk") } ndkCompile.conventionMapping.ndkConfig = { variantConfig.ndkConfig } @@ -776,7 +798,7 @@ public abstract class BasePlugin { } ndkCompile.conventionMapping.objFolder = { - project.file("$project.buildDir/ndk/$variantData.dirName/obj") + project.file("$project.buildDir/ndk/${variantData.variantConfiguration.dirName}/obj") } ndkCompile.conventionMapping.soFolder = soFolderClosure } @@ -794,7 +816,7 @@ public abstract class BasePlugin { // to test both. if (!variantData.isSigned()) { throw new GradleException( - "Tested Variant '${testedVariantData.name}' is not configured to create a signed APK.") + "Tested Variant '${testedVariantData.variantConfiguration.fullName}' is not configured to create a signed APK.") } createAnchorTasks(variantData) @@ -866,7 +888,7 @@ public abstract class BasePlugin { int count = variantDataList.size() for (int i = 0 ; i < count ; i++) { final BaseVariantData baseVariantData = variantDataList.get(i) - String variantName = baseVariantData.computeName() + String variantName = baseVariantData.variantConfiguration.fullName Task lintCheck = project.tasks.create("lint" + variantName, Lint) lintCheck.dependsOn baseVariantData.javaCompileTask, lintCompile lint.dependsOn lintCheck @@ -891,6 +913,9 @@ public abstract class BasePlugin { if (config.getType() != VariantConfiguration.Type.TEST) { javaSource.add(config.buildTypeSourceSet.javaDirectories) } + if (config.variantSourceProvider != null) { + javaSource.add(config.variantSourceProvider.javaDirectories) + } resourceSource.add(config.defaultSourceSet.resDirectories) if (config.getType() != VariantConfiguration.Type.TEST) { @@ -928,7 +953,8 @@ public abstract class BasePlugin { // set lint project options lintCheck.setSources(javaSource) - lintCheck.setClasspath("$project.buildDir/classes/$baseVariantData.dirName") + lintCheck.setClasspath( + "$project.buildDir/classes/$baseVariantData.variantConfiguration.dirName") lintCheck.setLintResources(resourceSource) } } @@ -1013,8 +1039,8 @@ public abstract class BasePlugin { // first the connected one. def connectedTask = createDeviceProviderInstrumentTestTask( hasFlavors ? - "${connectedRootName}${baseVariantData.name}" : connectedRootName, - "Installs and runs the tests for Build '${baseVariantData.name}' on connected devices.", + "${connectedRootName}${baseVariantData.variantConfiguration.fullName}" : connectedRootName, + "Installs and runs the tests for Build '${baseVariantData.variantConfiguration.fullName}' on connected devices.", isLibraryTest ? DeviceProviderInstrumentTestLibraryTask : DeviceProviderInstrumentTestTask, @@ -1031,9 +1057,9 @@ public abstract class BasePlugin { for (DeviceProvider deviceProvider : providers) { DefaultTask providerTask = createDeviceProviderInstrumentTestTask( hasFlavors ? - "${deviceProvider.name}${INSTRUMENT_TEST.capitalize()}${baseVariantData.name}" : + "${deviceProvider.name}${INSTRUMENT_TEST.capitalize()}${baseVariantData.variantConfiguration.fullName}" : "${deviceProvider.name}${INSTRUMENT_TEST.capitalize()}", - "Installs and runs the tests for Build '${baseVariantData.name}' using Provider '${deviceProvider.name.capitalize()}'.", + "Installs and runs the tests for Build '${baseVariantData.variantConfiguration.fullName}' using Provider '${deviceProvider.name.capitalize()}'.", isLibraryTest ? DeviceProviderInstrumentTestLibraryTask : DeviceProviderInstrumentTestTask, @@ -1056,10 +1082,10 @@ public abstract class BasePlugin { for (TestServer testServer : servers) { DefaultTask serverTask = project.tasks.create( hasFlavors ? - "${testServer.name}${"upload".capitalize()}${baseVariantData.name}" : + "${testServer.name}${"upload".capitalize()}${baseVariantData.variantConfiguration.fullName}" : "${testServer.name}${"upload".capitalize()}", TestServerTask) - serverTask.description = "Uploads APKs for Build '${baseVariantData.name}' to Test Server '${testServer.name.capitalize()}'." + serverTask.description = "Uploads APKs for Build '${baseVariantData.variantConfiguration.fullName}' to Test Server '${testServer.name.capitalize()}'." serverTask.group = JavaBasePlugin.VERIFICATION_GROUP serverTask.dependsOn testVariantData.assembleTask, baseVariantData.assembleTask @@ -1070,7 +1096,7 @@ public abstract class BasePlugin { serverTask.conventionMapping.testedApk = { baseVariantData.outputFile } } - serverTask.conventionMapping.variantName = { baseVariantData.name } + serverTask.conventionMapping.variantName = { baseVariantData.variantConfiguration.fullName } deviceCheck.dependsOn serverTask @@ -1116,7 +1142,7 @@ public abstract class BasePlugin { testTask.plugin = this testTask.variant = variantData - testTask.flavorName = variantData.flavorName + testTask.flavorName = variantData.variantConfiguration.flavorName.capitalize() testTask.deviceProvider = deviceProvider testTask.conventionMapping.testApp = { variantData.outputFile } @@ -1129,7 +1155,7 @@ public abstract class BasePlugin { extension.testOptions.resultsDir : "$project.buildDir/$FD_INSTRUMENT_RESULTS" - String flavorFolder = variantData.flavorDirName + String flavorFolder = variantData.variantConfiguration.flavorName if (!flavorFolder.isEmpty()) { flavorFolder = "$FD_FLAVORS/" + flavorFolder } @@ -1141,7 +1167,7 @@ public abstract class BasePlugin { extension.testOptions.reportDir : "$project.buildDir/$FD_REPORTS/$FD_INSTRUMENT_TESTS" - String flavorFolder = variantData.flavorDirName + String flavorFolder = variantData.variantConfiguration.flavorName if (!flavorFolder.isEmpty()) { flavorFolder = "$FD_FLAVORS/" + flavorFolder } @@ -1168,7 +1194,7 @@ public abstract class BasePlugin { variantConfig.testedConfig.type != VariantConfiguration.Type.LIBRARY)) // common dex task configuration - String dexTaskName = "dex${variantData.name}" + String dexTaskName = "dex${variantData.variantConfiguration.fullName.capitalize()}" Dex dexTask = project.tasks.create(dexTaskName, Dex) variantData.dexTask = dexTask @@ -1177,7 +1203,7 @@ public abstract class BasePlugin { dexTask.conventionMapping.outputFile = { project.file( - "${project.buildDir}/libs/${project.archivesBaseName}-${variantData.baseName}.dex") + "${project.buildDir}/libs/${project.archivesBaseName}-${variantData.variantConfiguration.baseName}.dex") } dexTask.dexOptions = extension.dexOptions @@ -1198,7 +1224,7 @@ public abstract class BasePlugin { PreDex preDexTask = null; boolean runPreDex = extension.dexOptions.preDexLibraries if (runPreDex) { - def preDexTaskName = "preDex${variantData.name}" + def preDexTaskName = "preDex${variantData.variantConfiguration.fullName.capitalize()}" preDexTask = project.tasks.create(preDexTaskName, PreDex) preDexTask.dependsOn variantData.javaCompileTask @@ -1210,7 +1236,7 @@ public abstract class BasePlugin { } preDexTask.conventionMapping.outputFolder = { project.file( - "${project.buildDir}/pre-dexed/${variantData.dirName}") + "${project.buildDir}/pre-dexed/${variantData.variantConfiguration.dirName}") } } @@ -1233,7 +1259,9 @@ public abstract class BasePlugin { } // Add a task to generate application package - def packageApp = project.tasks.create("package${variantData.name}", PackageApplication) + def packageApp = project.tasks.create( + "package${variantData.variantConfiguration.fullName.capitalize()}", + PackageApplication) variantData.packageApplicationTask = packageApp packageApp.dependsOn variantData.processResourcesTask, dexTask, variantData.processJavaResourcesTask, variantData.ndkCompileTask @@ -1285,8 +1313,8 @@ public abstract class BasePlugin { def signedApk = variantData.isSigned() def apkName = signedApk ? - "${project.archivesBaseName}-${variantData.baseName}-unaligned.apk" : - "${project.archivesBaseName}-${variantData.baseName}-unsigned.apk" + "${project.archivesBaseName}-${variantData.variantConfiguration.baseName}-unaligned.apk" : + "${project.archivesBaseName}-${variantData.variantConfiguration.baseName}-unsigned.apk" packageApp.conventionMapping.outputFile = { project.file("$project.buildDir/apk/${apkName}") @@ -1298,25 +1326,29 @@ public abstract class BasePlugin { if (signedApk) { if (variantData.zipAlign) { // Add a task to zip align application package - def zipAlignTask = project.tasks.create("zipalign${variantData.name}", ZipAlign) + def zipAlignTask = project.tasks.create( + "zipalign${variantData.variantConfiguration.fullName.capitalize()}", + ZipAlign) variantData.zipAlignTask = zipAlignTask zipAlignTask.dependsOn packageApp zipAlignTask.conventionMapping.inputFile = { packageApp.outputFile } zipAlignTask.conventionMapping.outputFile = { project.file( - "$project.buildDir/apk/${project.archivesBaseName}-${variantData.baseName}.apk") + "$project.buildDir/apk/${project.archivesBaseName}-${variantData.variantConfiguration.baseName}.apk") } zipAlignTask.conventionMapping.zipAlignExe = { getSdkParser().zipAlign } appTask = zipAlignTask outputFileTask = zipAlignTask variantData.outputFile = project.file( - "$project.buildDir/apk/${project.archivesBaseName}-${variantData.baseName}.apk") + "$project.buildDir/apk/${project.archivesBaseName}-${variantData.variantConfiguration.baseName}.apk") } // Add a task to install the application package - def installTask = project.tasks.create("install${variantData.name}", InstallTask) + def installTask = project.tasks.create( + "install${variantData.variantConfiguration.fullName.capitalize()}", + InstallTask) installTask.description = "Installs the " + variantData.description installTask.group = INSTALL_GROUP installTask.dependsOn appTask @@ -1328,7 +1360,7 @@ public abstract class BasePlugin { // Add an assemble task if (assembleTask == null) { - assembleTask = project.tasks.create("assemble${variantData.name}") + assembleTask = project.tasks.create("assemble${variantData.variantConfiguration.fullName.capitalize()}") assembleTask.description = "Assembles the " + variantData.description assembleTask.group = org.gradle.api.plugins.BasePlugin.BUILD_GROUP } @@ -1338,7 +1370,9 @@ public abstract class BasePlugin { variantData.outputFile = { outputFileTask.outputFile } // add an uninstall task - def uninstallTask = project.tasks.create("uninstall${variantData.name}", UninstallTask) + def uninstallTask = project.tasks.create( + "uninstall${variantData.variantConfiguration.fullName.capitalize()}", + UninstallTask) uninstallTask.description = "Uninstalls the " + variantData.description uninstallTask.group = INSTALL_GROUP uninstallTask.variant = variantData @@ -1360,7 +1394,9 @@ public abstract class BasePlugin { @Nullable BaseVariantData testedVariantData) { VariantConfiguration variantConfig = variantData.variantConfiguration - def proguardTask = project.tasks.create("proguard${variantData.name}", ProGuardTask) + def proguardTask = project.tasks.create( + "proguard${variantData.variantConfiguration.fullName.capitalize()}", + ProGuardTask) proguardTask.dependsOn variantData.javaCompileTask if (testedVariantData != null) { proguardTask.dependsOn testedVariantData.proguardTask @@ -1373,10 +1409,10 @@ public abstract class BasePlugin { File outFile; if (variantData instanceof LibraryVariantData) { outFile = project.file( - "${project.buildDir}/$DIR_BUNDLES/${variantData.dirName}/classes.jar") + "${project.buildDir}/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/classes.jar") } else { outFile = project.file( - "${project.buildDir}/classes-proguard/${variantData.dirName}/classes.jar") + "${project.buildDir}/classes-proguard/${variantData.variantConfiguration.dirName}/classes.jar") } // --- Proguard Config --- @@ -1390,7 +1426,7 @@ public abstract class BasePlugin { "}") // input the mapping from the tested app so that we can deal with obfuscated code - proguardTask.applymapping("${project.buildDir}/proguard/${testedVariantData.dirName}/mapping.txt") + proguardTask.applymapping("${project.buildDir}/proguard/${testedVariantData.variantConfiguration.dirName}/mapping.txt") // for tested app, we only care about their aapt config since the base // configs are the same files anyway. @@ -1475,13 +1511,13 @@ public abstract class BasePlugin { proguardTask.outjars(outFile) - proguardTask.dump("${project.buildDir}/proguard/${variantData.dirName}/dump.txt") + proguardTask.dump("${project.buildDir}/proguard/${variantData.variantConfiguration.dirName}/dump.txt") proguardTask.printseeds( - "${project.buildDir}/proguard/${variantData.dirName}/seeds.txt") + "${project.buildDir}/proguard/${variantData.variantConfiguration.dirName}/seeds.txt") proguardTask.printusage( - "${project.buildDir}/proguard/${variantData.dirName}/usage.txt") + "${project.buildDir}/proguard/${variantData.variantConfiguration.dirName}/usage.txt") proguardTask.printmapping( - "${project.buildDir}/proguard/${variantData.dirName}/mapping.txt") + "${project.buildDir}/proguard/${variantData.variantConfiguration.dirName}/mapping.txt") return outFile } @@ -1499,10 +1535,12 @@ public abstract class BasePlugin { } protected void createAnchorTasks(@NonNull BaseVariantData variantData) { - variantData.preBuildTask = project.tasks.create("pre${variantData.name}Build") + variantData.preBuildTask = project.tasks.create( + "pre${variantData.variantConfiguration.fullName.capitalize()}Build") variantData.preBuildTask.dependsOn mainPreBuild - def prepareDependenciesTask = project.tasks.create("prepare${variantData.name}Dependencies", + def prepareDependenciesTask = project.tasks.create( + "prepare${variantData.variantConfiguration.fullName.capitalize()}Dependencies", PrepareDependenciesTask) variantData.prepareDependenciesTask = prepareDependenciesTask @@ -1521,7 +1559,8 @@ public abstract class BasePlugin { } // also create sourceGenTask - variantData.sourceGenTask = project.tasks.create("generate${variantData.name}Sources") + variantData.sourceGenTask = project.tasks.create( + "generate${variantData.variantConfiguration.fullName.capitalize()}Sources") } //---------------------------------------------------------------------------------------------- diff --git a/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy b/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy index ba86d35..14cce5e 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/LibraryPlugin.groovy @@ -79,9 +79,9 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { // create the source sets for the build type. // the ones for the main product flavors are handled by the base plugin. DefaultAndroidSourceSet debugSourceSet = - (DefaultAndroidSourceSet) extension.sourceSetsContainer.create(BuilderConstants.DEBUG) + (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(BuilderConstants.DEBUG) DefaultAndroidSourceSet releaseSourceSet = - (DefaultAndroidSourceSet) extension.sourceSetsContainer.create(BuilderConstants.RELEASE) + (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(BuilderConstants.RELEASE) debugBuildTypeData = new BuildTypeData(extension.debug, debugSourceSet, project) releaseBuildTypeData = new BuildTypeData(extension.release, releaseSourceSet, project) @@ -140,15 +140,15 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { debugBuildTypeData.buildType, null, VariantConfiguration.Type.TEST, - debugVariantData.variantConfiguration, - project.name) + debugVariantData.variantConfiguration) TestVariantData testVariantData = new TestVariantData(testVariantConfig, debugVariantData) // link the testVariant to the tested variant in the other direction debugVariantData.setTestVariantData(testVariantData); // dependencies for the test variant - variantDep = VariantDependencies.compute(project, testVariantData.name, + variantDep = VariantDependencies.compute(project, + testVariantData.variantConfiguration.fullName, defaultConfigData.testProvider, debugVariantData.variantDependency) testVariantData.setVariantDependency(variantDep) @@ -173,13 +173,12 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { configData.sourceSet, buildTypeData.buildType, buildTypeData.sourceSet, - VariantConfiguration.Type.LIBRARY, - project.name) + VariantConfiguration.Type.LIBRARY) LibraryVariantData variantData = new LibraryVariantData(variantConfig) VariantDependencies debugVariantDep = VariantDependencies.compute( - project, variantData.name, + project, variantData.variantConfiguration.fullName, buildTypeData, configData.mainProvider) variantData.setVariantDependency(debugVariantDep) @@ -212,13 +211,13 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { // the dependencies. This is what gets packaged in the aar. MergeResources packageRes = basicCreateMergeResourcesTask(variantData, "package", - "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/res", + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/res", false /*includeDependencies*/, false /*process9Patch*/) // Add a task to merge the assets folders createMergeAssetsTask(variantData, - "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/assets", + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/assets", false /*includeDependencies*/) // Add a task to create the BuildConfig class @@ -226,7 +225,8 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { // Add a task to generate resource source files, directing the location // of the r.txt file to be directly in the bundle. - createProcessResTask(variantData, "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}") + createProcessResTask(variantData, + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}") // process java resources createProcessJavaResTask(variantData) @@ -239,40 +239,48 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { // Add NDK tasks createNdkTasks( variantData, - { project.file("$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/jni") }); + { project.file("$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/jni") }); // package the aidl files into the bundle folder - Sync packageAidl = project.tasks.create("package${variantData.name}Aidl", Sync) + Sync packageAidl = project.tasks.create( + "package${variantData.variantConfiguration.fullName.capitalize()}Aidl", + Sync) // packageAidl from 3 sources. the order is important to make sure the override works well. packageAidl.from(variantConfig.aidlSourceList).include("**/*.aidl") packageAidl.into(project.file( - "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$SdkConstants.FD_AIDL")) + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$SdkConstants.FD_AIDL")) // package the renderscript header files files into the bundle folder - Sync packageRenderscript = project.tasks.create("package${variantData.name}Renderscript", + Sync packageRenderscript = project.tasks.create( + "package${variantData.variantConfiguration.fullName.capitalize()}Renderscript", Sync) // package from 3 sources. the order is important to make sure the override works well. packageRenderscript.from(variantConfig.renderscriptSourceList).include("**/*.rsh") packageRenderscript.into(project.file( - "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$SdkConstants.FD_RENDERSCRIPT")) + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$SdkConstants.FD_RENDERSCRIPT")) // merge consumer proguard files from different build types and flavors - MergeFileTask mergeProGuardFileTask = project.tasks.create("merge${variantData.name}ProguardFiles", + MergeFileTask mergeProGuardFileTask = project.tasks.create( + "merge${variantData.variantConfiguration.fullName.capitalize()}ProguardFiles", MergeFileTask) mergeProGuardFileTask.conventionMapping.inputFiles = { project.files(variantConfig.getConsumerProguardFiles()).files } mergeProGuardFileTask.conventionMapping.outputFile = { project.file( - "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$LibraryBundle.FN_PROGUARD_TXT") + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$LibraryBundle.FN_PROGUARD_TXT") } // copy lint.jar into the bundle folder - Copy lintCopy = project.tasks.create("copy${variantData.name}Lint", Copy) + Copy lintCopy = project.tasks.create( + "copy${variantData.variantConfiguration.fullName.capitalize()}Lint", + Copy) lintCopy.dependsOn lintCompile lintCopy.from("$project.buildDir/lint/lint.jar") - lintCopy.into("$project.buildDir/$DIR_BUNDLES/$variantData.dirName") + lintCopy.into("$project.buildDir/$DIR_BUNDLES/$variantData.variantConfiguration.dirName") - Zip bundle = project.tasks.create("bundle${variantData.name}", Zip) + Zip bundle = project.tasks.create( + "bundle${variantData.variantConfiguration.fullName.capitalize()}", + Zip) if (variantConfig.buildType.runProguard) { // run proguard on output of compile task @@ -283,10 +291,12 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { bundle.dependsOn packageRes, packageAidl, packageRenderscript, mergeProGuardFileTask, lintCopy, variantData.ndkCompileTask } else { - Sync packageLocalJar = project.tasks.create("package${variantData.name}LocalJar", Sync) + Sync packageLocalJar = project.tasks.create( + "package${variantData.variantConfiguration.fullName.capitalize()}LocalJar", + Sync) packageLocalJar.from(getLocalJarFileList(variantData.variantDependency)) packageLocalJar.into(project.file( - "$project.buildDir/$DIR_BUNDLES/${variantData.dirName}/$SdkConstants.LIBS_FOLDER")) + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$SdkConstants.LIBS_FOLDER")) // jar the classes. Jar jar = project.tasks.create("package${buildType.name.capitalize()}Jar", Jar); @@ -294,7 +304,8 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { jar.from(variantData.javaCompileTask.outputs); jar.from(variantData.processJavaResourcesTask.destinationDir) - jar.destinationDir = project.file("$project.buildDir/$DIR_BUNDLES/${variantData.dirName}") + jar.destinationDir = project.file( + "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}") jar.archiveName = "classes.jar" String packageName = variantConfig.getPackageFromManifest() @@ -313,13 +324,13 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { mergeProGuardFileTask, lintCopy, variantData.ndkCompileTask } - bundle.setDescription("Assembles a bundle containing the library in ${variantData.name}."); + bundle.setDescription("Assembles a bundle containing the library in ${variantData.variantConfiguration.fullName.capitalize()}."); bundle.destinationDir = project.file("$project.buildDir/libs") bundle.extension = BuilderConstants.EXT_LIB_ARCHIVE - if (variantData.baseName != BuilderConstants.RELEASE) { - bundle.classifier = variantData.baseName + if (variantData.variantConfiguration.baseName != BuilderConstants.RELEASE) { + bundle.classifier = variantData.variantConfiguration.baseName } - bundle.from(project.file("$project.buildDir/$DIR_BUNDLES/${variantData.dirName}")) + bundle.from(project.file("$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}")) variantData.packageLibTask = bundle variantData.outputFile = bundle.archivePath @@ -337,7 +348,7 @@ public class LibraryPlugin extends BasePlugin implements Plugin<Project> { // configure the variant to be testable. variantConfig.output = new LibraryBundle( bundle.archivePath, - project.file("$project.buildDir/$DIR_BUNDLES/${variantData.dirName}"), + project.file("$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}"), variantData.getName()) { @Nullable diff --git a/gradle/src/main/groovy/com/android/build/gradle/api/ApkVariant.java b/gradle/src/main/groovy/com/android/build/gradle/api/ApkVariant.java index d28b6dd..404625e 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/api/ApkVariant.java +++ b/gradle/src/main/groovy/com/android/build/gradle/api/ApkVariant.java @@ -21,7 +21,6 @@ import com.android.annotations.Nullable; import com.android.build.gradle.tasks.Dex; import com.android.build.gradle.tasks.PackageApplication; import com.android.build.gradle.tasks.ZipAlign; -import com.android.builder.DefaultBuildType; import com.android.builder.DefaultProductFlavor; import com.android.builder.model.SigningConfig; import org.gradle.api.DefaultTask; @@ -33,11 +32,6 @@ import java.util.List; */ public interface ApkVariant extends BaseVariant { - /** - * Returns the {@link com.android.builder.DefaultBuildType} for this build variant. - */ - @NonNull - DefaultBuildType getBuildType(); /** * Returns the list of {@link com.android.builder.DefaultProductFlavor} for this build variant. diff --git a/gradle/src/main/groovy/com/android/build/gradle/api/BaseVariant.java b/gradle/src/main/groovy/com/android/build/gradle/api/BaseVariant.java index 190bf47..297121d 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/api/BaseVariant.java +++ b/gradle/src/main/groovy/com/android/build/gradle/api/BaseVariant.java @@ -25,11 +25,14 @@ import com.android.build.gradle.tasks.MergeResources; import com.android.build.gradle.tasks.ProcessAndroidResources; import com.android.build.gradle.tasks.ProcessManifest; import com.android.build.gradle.tasks.RenderscriptCompile; +import com.android.builder.DefaultBuildType; +import com.android.builder.DefaultProductFlavor; import org.gradle.api.Task; import org.gradle.api.tasks.Copy; import org.gradle.api.tasks.compile.JavaCompile; import java.io.File; +import java.util.Collection; /** * A Build variant and all its public data. This is the base class for items common to apps, @@ -68,6 +71,19 @@ public interface BaseVariant { String getBaseName(); /** + * Returns the {@link com.android.builder.DefaultBuildType} for this build variant. + */ + @NonNull + DefaultBuildType getBuildType(); + + /** + * Returns a {@link com.android.builder.DefaultProductFlavor} that represents the merging + * of the default config and the flavors of this build variant. + */ + @NonNull + DefaultProductFlavor getConfig(); + + /** * Returns the output file for this build variants. Depending on the configuration, this could * be an apk (regular and test project) or a bundled library (library project). * @@ -137,4 +153,52 @@ public interface BaseVariant { */ @Nullable Task getAssemble(); + + /** + * Adds new Java source folders to the model. + * + * These source folders will not be used for the default build + * system, but will be passed along the default Java source folders + * to whoever queries the model. + * + * @param sourceFolders the source folders where the generated source code is. + */ + void addJavaSourceFoldersToModel(@NonNull File... sourceFolders); + + /** + * Adds new Java source folders to the model. + * + * These source folders will not be used for the default build + * system, but will be passed along the default Java source folders + * to whoever queries the model. + * + * @param sourceFolders the source folders where the generated source code is. + */ + void addJavaSourceFoldersToModel(@NonNull Collection<File> sourceFolders); + + /** + * Adds to the variant a task that generates Java source code. + * + * This will make the compileJava task depend on this task and add the + * new source folders as compilation inputs. + * + * The new source folders are also added to the model. + * + * @param task the task + * @param sourceFolders the source folders where the generated source code is. + */ + void registerJavaGeneratingTask(@NonNull Task task, @NonNull File... sourceFolders); + + /** + * Adds to the variant a task that generates Java source code. + * + * This will make the compileJava task depend on this task and add the + * new source folders as compilation inputs. + * + * The new source folders are also added to the model. + * + * @param task the task + * @param sourceFolders the source folders where the generated source code is. + */ + void registerJavaGeneratingTask(@NonNull Task task, @NonNull Collection<File> sourceFolders); } diff --git a/gradle/src/main/groovy/com/android/build/gradle/api/LibraryVariant.java b/gradle/src/main/groovy/com/android/build/gradle/api/LibraryVariant.java index 5bcfd9f..8db077d 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/api/LibraryVariant.java +++ b/gradle/src/main/groovy/com/android/build/gradle/api/LibraryVariant.java @@ -16,10 +16,7 @@ package com.android.build.gradle.api; -import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.builder.DefaultBuildType; -import com.android.builder.DefaultProductFlavor; import org.gradle.api.tasks.bundling.Zip; /** @@ -28,19 +25,6 @@ import org.gradle.api.tasks.bundling.Zip; public interface LibraryVariant extends BaseVariant { /** - * Returns the {@link com.android.builder.DefaultBuildType} for this build variant. - */ - @NonNull - DefaultBuildType getBuildType(); - - /** - * Returns a {@link com.android.builder.DefaultProductFlavor} that represents the merging - * of the default config and the flavors of this build variant. - */ - @NonNull - DefaultProductFlavor getConfig(); - - /** * Returns the build variant that will test this build variant. * * Will return null if this build variant is a test build already. diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/AndroidAsciiReportRenderer.java b/gradle/src/main/groovy/com/android/build/gradle/internal/AndroidAsciiReportRenderer.java index 2de5ad0..25ea1ca 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/AndroidAsciiReportRenderer.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/AndroidAsciiReportRenderer.java @@ -69,7 +69,8 @@ public class AndroidAsciiReportRenderer extends TextReportRenderer { renderer.visit(new Action<StyledTextOutput>() { @Override public void execute(StyledTextOutput styledTextOutput) { - getTextOutput().withStyle(Identifier).text(variantData.getName()); + getTextOutput().withStyle(Identifier).text( + variantData.getVariantConfiguration().getFullName()); getTextOutput().withStyle(Description).text(""); } }, true); diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/api/ApplicationVariantImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/api/ApplicationVariantImpl.java index ed0afe4..fcc3d0b 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/api/ApplicationVariantImpl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/api/ApplicationVariantImpl.java @@ -21,23 +21,13 @@ import com.android.annotations.Nullable; import com.android.build.gradle.api.ApplicationVariant; import com.android.build.gradle.api.TestVariant; import com.android.build.gradle.internal.variant.ApplicationVariantData; -import com.android.build.gradle.tasks.AidlCompile; +import com.android.build.gradle.internal.variant.BaseVariantData; import com.android.build.gradle.tasks.Dex; -import com.android.build.gradle.tasks.GenerateBuildConfig; -import com.android.build.gradle.tasks.MergeAssets; -import com.android.build.gradle.tasks.MergeResources; import com.android.build.gradle.tasks.PackageApplication; -import com.android.build.gradle.tasks.ProcessAndroidResources; -import com.android.build.gradle.tasks.ProcessManifest; -import com.android.build.gradle.tasks.RenderscriptCompile; import com.android.build.gradle.tasks.ZipAlign; -import com.android.builder.DefaultBuildType; import com.android.builder.DefaultProductFlavor; import com.android.builder.model.SigningConfig; import org.gradle.api.DefaultTask; -import org.gradle.api.Task; -import org.gradle.api.tasks.Copy; -import org.gradle.api.tasks.compile.JavaCompile; import java.io.File; import java.util.List; @@ -46,7 +36,7 @@ import java.util.List; * implementation of the {@link ApplicationVariant} interface around an * {@link ApplicationVariantData} object. */ -public class ApplicationVariantImpl implements ApplicationVariant { +public class ApplicationVariantImpl extends BaseVariantImpl implements ApplicationVariant { @NonNull private final ApplicationVariantData variantData; @@ -57,38 +47,13 @@ public class ApplicationVariantImpl implements ApplicationVariant { this.variantData = variantData; } - public void setTestVariant(@Nullable TestVariant testVariant) { - this.testVariant = testVariant; - } - - @Override - @NonNull - public String getName() { - return variantData.getName(); - } - @Override - @NonNull - public String getDescription() { - return variantData.getDescription(); - } - - @Override - @NonNull - public String getDirName() { - return variantData.getDirName(); + protected BaseVariantData getVariantData() { + return variantData; } - @Override - @NonNull - public String getBaseName() { - return variantData.getBaseName(); - } - - @Override - @NonNull - public DefaultBuildType getBuildType() { - return variantData.getVariantConfiguration().getBuildType(); + public void setTestVariant(@Nullable TestVariant testVariant) { + this.testVariant = testVariant; } @Override @@ -104,12 +69,6 @@ public class ApplicationVariantImpl implements ApplicationVariant { } @Override - @NonNull - public File getOutputFile() { - return variantData.getOutputFile(); - } - - @Override public void setOutputFile(@NonNull File outputFile) { if (variantData.zipAlignTask != null) { variantData.zipAlignTask.setOutputFile(outputFile); @@ -125,57 +84,6 @@ public class ApplicationVariantImpl implements ApplicationVariant { } @Override - @NonNull - public ProcessManifest getProcessManifest() { - return variantData.processManifestTask; - } - - @Override - @NonNull - public AidlCompile getAidlCompile() { - return variantData.aidlCompileTask; - } - - @Override - @NonNull - public RenderscriptCompile getRenderscriptCompile() { - return variantData.renderscriptCompileTask; - } - - @Override - public MergeResources getMergeResources() { - return variantData.mergeResourcesTask; - } - - @Override - public MergeAssets getMergeAssets() { - return variantData.mergeAssetsTask; - } - - @Override - @NonNull - public ProcessAndroidResources getProcessResources() { - return variantData.processResourcesTask; - } - - @Override - public GenerateBuildConfig getGenerateBuildConfig() { - return variantData.generateBuildConfigTask; - } - - @Override - @NonNull - public JavaCompile getJavaCompile() { - return variantData.javaCompileTask; - } - - @Override - @NonNull - public Copy getProcessJavaResources() { - return variantData.processJavaResourcesTask; - } - - @Override public Dex getDex() { return variantData.dexTask; } @@ -191,11 +99,6 @@ public class ApplicationVariantImpl implements ApplicationVariant { } @Override - public Task getAssemble() { - return variantData.assembleTask; - } - - @Override public DefaultTask getInstall() { return variantData.installTask; } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/api/BaseVariantImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/api/BaseVariantImpl.java new file mode 100644 index 0000000..1e99d91 --- /dev/null +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/api/BaseVariantImpl.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2013 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.api; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.build.gradle.api.BaseVariant; +import com.android.build.gradle.internal.variant.BaseVariantData; +import com.android.build.gradle.tasks.AidlCompile; +import com.android.build.gradle.tasks.GenerateBuildConfig; +import com.android.build.gradle.tasks.MergeAssets; +import com.android.build.gradle.tasks.MergeResources; +import com.android.build.gradle.tasks.ProcessAndroidResources; +import com.android.build.gradle.tasks.ProcessManifest; +import com.android.build.gradle.tasks.RenderscriptCompile; +import com.android.builder.DefaultBuildType; +import com.android.builder.DefaultProductFlavor; +import org.gradle.api.Task; +import org.gradle.api.tasks.Copy; +import org.gradle.api.tasks.compile.JavaCompile; + +import java.io.File; +import java.util.Collection; + +abstract class BaseVariantImpl implements BaseVariant { + + protected abstract BaseVariantData getVariantData(); + + @Override + @NonNull + public String getName() { + return getVariantData().getVariantConfiguration().getFullName(); + } + + @Override + @NonNull + public String getDescription() { + return getVariantData().getDescription(); + } + + @Override + @NonNull + public String getDirName() { + return getVariantData().getVariantConfiguration().getDirName(); + } + + @Override + @NonNull + public String getBaseName() { + return getVariantData().getVariantConfiguration().getBaseName(); + } + + @Override + @NonNull + public DefaultBuildType getBuildType() { + return getVariantData().getVariantConfiguration().getBuildType(); + } + + @NonNull + @Override + public DefaultProductFlavor getConfig() { + return getVariantData().getVariantConfiguration().getDefaultConfig(); + } + + @Override + @NonNull + public File getOutputFile() { + return getVariantData().getOutputFile(); + } + + @Override + @NonNull + public ProcessManifest getProcessManifest() { + return getVariantData().processManifestTask; + } + + @Override + @NonNull + public AidlCompile getAidlCompile() { + return getVariantData().aidlCompileTask; + } + + @Override + @NonNull + public RenderscriptCompile getRenderscriptCompile() { + return getVariantData().renderscriptCompileTask; + } + + @Override + public MergeResources getMergeResources() { + return getVariantData().mergeResourcesTask; + } + + @Override + public MergeAssets getMergeAssets() { + return getVariantData().mergeAssetsTask; + } + + @Override + @NonNull + public ProcessAndroidResources getProcessResources() { + return getVariantData().processResourcesTask; + } + + @Override + public GenerateBuildConfig getGenerateBuildConfig() { + return getVariantData().generateBuildConfigTask; + } + + @Override + @NonNull + public JavaCompile getJavaCompile() { + return getVariantData().javaCompileTask; + } + + @Override + @NonNull + public Copy getProcessJavaResources() { + return getVariantData().processJavaResourcesTask; + } + + @Override + @Nullable + public Task getAssemble() { + return getVariantData().assembleTask; + } + + @Override + public void addJavaSourceFoldersToModel(@NonNull File... generatedSourceFolders) { + getVariantData().addJavaSourceFoldersToModel(generatedSourceFolders); + } + + @Override + public void addJavaSourceFoldersToModel(@NonNull Collection<File> generatedSourceFolders) { + getVariantData().addJavaSourceFoldersToModel(generatedSourceFolders); + } + + @Override + public void registerJavaGeneratingTask(@NonNull Task task, @NonNull File... sourceFolders) { + getVariantData().registerJavaGeneratingTask(task, sourceFolders); + } + + @Override + public void registerJavaGeneratingTask(@NonNull Task task, @NonNull Collection<File> sourceFolders) { + getVariantData().registerJavaGeneratingTask(task, sourceFolders); + } +} diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/api/DefaultAndroidSourceSet.java b/gradle/src/main/groovy/com/android/build/gradle/internal/api/DefaultAndroidSourceSet.java index aab4146..0520fa5 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/api/DefaultAndroidSourceSet.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/api/DefaultAndroidSourceSet.java @@ -267,7 +267,6 @@ public class DefaultAndroidSourceSet implements AndroidSourceSet, SourceProvider // --- SourceProvider - @NonNull @Override public Set<File> getJavaDirectories() { diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/api/LibraryVariantImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/api/LibraryVariantImpl.java index 7ed4c6b..f48a529 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/api/LibraryVariantImpl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/api/LibraryVariantImpl.java @@ -20,20 +20,9 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.build.gradle.api.LibraryVariant; import com.android.build.gradle.api.TestVariant; +import com.android.build.gradle.internal.variant.BaseVariantData; import com.android.build.gradle.internal.variant.LibraryVariantData; -import com.android.build.gradle.tasks.AidlCompile; -import com.android.build.gradle.tasks.GenerateBuildConfig; -import com.android.build.gradle.tasks.MergeAssets; -import com.android.build.gradle.tasks.MergeResources; -import com.android.build.gradle.tasks.ProcessAndroidResources; -import com.android.build.gradle.tasks.ProcessManifest; -import com.android.build.gradle.tasks.RenderscriptCompile; -import com.android.builder.DefaultBuildType; -import com.android.builder.DefaultProductFlavor; -import org.gradle.api.Task; -import org.gradle.api.tasks.Copy; import org.gradle.api.tasks.bundling.Zip; -import org.gradle.api.tasks.compile.JavaCompile; import java.io.File; @@ -41,7 +30,7 @@ import java.io.File; * implementation of the {@link LibraryVariant} interface around a * {@link LibraryVariantData} object. */ -public class LibraryVariantImpl implements LibraryVariant { +public class LibraryVariantImpl extends BaseVariantImpl implements LibraryVariant { @NonNull private final LibraryVariantData variantData; @@ -52,44 +41,13 @@ public class LibraryVariantImpl implements LibraryVariant { this.variantData = variantData; } - public void setTestVariant(@Nullable TestVariant testVariant) { - this.testVariant = testVariant; - } - - @Override - @NonNull - public String getName() { - return variantData.getName(); - } - @Override - @NonNull - public String getDescription() { - return variantData.getDescription(); - } - - @Override - @NonNull - public String getDirName() { - return variantData.getDirName(); + protected BaseVariantData getVariantData() { + return variantData; } - @Override - @NonNull - public String getBaseName() { - return variantData.getBaseName(); - } - - @Override - @NonNull - public DefaultBuildType getBuildType() { - return variantData.getVariantConfiguration().getBuildType(); - } - - @NonNull - @Override - public DefaultProductFlavor getConfig() { - return variantData.getVariantConfiguration().getDefaultConfig(); + public void setTestVariant(@Nullable TestVariant testVariant) { + this.testVariant = testVariant; } @Override @@ -111,63 +69,7 @@ public class LibraryVariantImpl implements LibraryVariant { } @Override - @NonNull - public ProcessManifest getProcessManifest() { - return variantData.processManifestTask; - } - - @Override - @NonNull - public AidlCompile getAidlCompile() { - return variantData.aidlCompileTask; - } - - @Override - @NonNull - public RenderscriptCompile getRenderscriptCompile() { - return variantData.renderscriptCompileTask; - } - - @Override - public MergeResources getMergeResources() { - return variantData.mergeResourcesTask; - } - - @Override - public MergeAssets getMergeAssets() { - return variantData.mergeAssetsTask; - } - - @Override - @NonNull - public ProcessAndroidResources getProcessResources() { - return variantData.processResourcesTask; - } - - @Override - public GenerateBuildConfig getGenerateBuildConfig() { - return variantData.generateBuildConfigTask; - } - - @Override - @NonNull - public JavaCompile getJavaCompile() { - return variantData.javaCompileTask; - } - - @Override - @NonNull - public Copy getProcessJavaResources() { - return variantData.processJavaResourcesTask; - } - - @Override public Zip getPackageLibrary() { return variantData.packageLibTask; } - - @Override - public Task getAssemble() { - return variantData.assembleTask; - } } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/api/TestVariantImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/api/TestVariantImpl.java index 37eb618..073c49d 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/api/TestVariantImpl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/api/TestVariantImpl.java @@ -19,24 +19,14 @@ package com.android.build.gradle.internal.api; import com.android.annotations.NonNull; import com.android.build.gradle.api.BaseVariant; import com.android.build.gradle.api.TestVariant; +import com.android.build.gradle.internal.variant.BaseVariantData; import com.android.build.gradle.internal.variant.TestVariantData; -import com.android.build.gradle.tasks.AidlCompile; import com.android.build.gradle.tasks.Dex; -import com.android.build.gradle.tasks.GenerateBuildConfig; -import com.android.build.gradle.tasks.MergeAssets; -import com.android.build.gradle.tasks.MergeResources; import com.android.build.gradle.tasks.PackageApplication; -import com.android.build.gradle.tasks.ProcessAndroidResources; -import com.android.build.gradle.tasks.ProcessManifest; -import com.android.build.gradle.tasks.RenderscriptCompile; import com.android.build.gradle.tasks.ZipAlign; -import com.android.builder.DefaultBuildType; import com.android.builder.DefaultProductFlavor; import com.android.builder.model.SigningConfig; import org.gradle.api.DefaultTask; -import org.gradle.api.Task; -import org.gradle.api.tasks.Copy; -import org.gradle.api.tasks.compile.JavaCompile; import java.io.File; import java.util.List; @@ -44,7 +34,7 @@ import java.util.List; /** * implementation of the {@link TestVariant} interface around an {@link TestVariantData} object. */ -public class TestVariantImpl implements TestVariant { +public class TestVariantImpl extends BaseVariantImpl implements TestVariant { @NonNull private final TestVariantData variantData; @@ -56,33 +46,8 @@ public class TestVariantImpl implements TestVariant { } @Override - @NonNull - public String getName() { - return variantData.getName(); - } - - @Override - @NonNull - public String getDescription() { - return variantData.getDescription(); - } - - @Override - @NonNull - public String getDirName() { - return variantData.getDirName(); - } - - @Override - @NonNull - public String getBaseName() { - return variantData.getBaseName(); - } - - @Override - @NonNull - public DefaultBuildType getBuildType() { - return variantData.getVariantConfiguration().getBuildType(); + protected BaseVariantData getVariantData() { + return variantData; } @Override @@ -98,12 +63,6 @@ public class TestVariantImpl implements TestVariant { } @Override - @NonNull - public File getOutputFile() { - return variantData.getOutputFile(); - } - - @Override public void setOutputFile(@NonNull File outputFile) { if (variantData.zipAlignTask != null) { variantData.zipAlignTask.setOutputFile(outputFile); @@ -123,57 +82,6 @@ public class TestVariantImpl implements TestVariant { } @Override - @NonNull - public ProcessManifest getProcessManifest() { - return variantData.processManifestTask; - } - - @Override - @NonNull - public AidlCompile getAidlCompile() { - return variantData.aidlCompileTask; - } - - @Override - @NonNull - public RenderscriptCompile getRenderscriptCompile() { - return variantData.renderscriptCompileTask; - } - - @Override - public MergeResources getMergeResources() { - return variantData.mergeResourcesTask; - } - - @Override - public MergeAssets getMergeAssets() { - return variantData.mergeAssetsTask; - } - - @Override - @NonNull - public ProcessAndroidResources getProcessResources() { - return variantData.processResourcesTask; - } - - @Override - public GenerateBuildConfig getGenerateBuildConfig() { - return variantData.generateBuildConfigTask; - } - - @Override - @NonNull - public JavaCompile getJavaCompile() { - return variantData.javaCompileTask; - } - - @Override - @NonNull - public Copy getProcessJavaResources() { - return variantData.processJavaResourcesTask; - } - - @Override public Dex getDex() { return variantData.dexTask; } @@ -189,11 +97,6 @@ public class TestVariantImpl implements TestVariant { } @Override - public Task getAssemble() { - return variantData.assembleTask; - } - - @Override public DefaultTask getInstall() { return variantData.installTask; } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy index 6ca387c..a4770b6 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy @@ -18,6 +18,7 @@ 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.AndroidBuilder import com.android.builder.BuilderConstants import com.android.builder.DefaultBuildType import com.android.builder.NdkConfig @@ -25,7 +26,6 @@ import com.android.builder.model.SigningConfig import org.gradle.api.Action import org.gradle.api.internal.file.FileResolver import org.gradle.internal.reflect.Instantiator - /** * DSL overlay to make methods that accept String... work. */ @@ -82,12 +82,11 @@ public class BuildTypeDsl extends DefaultBuildType implements Serializable { // -- DSL Methods. TODO remove once the instantiator does what I expect it to do. - public void buildConfig(String... lines) { - setBuildConfig(lines) - } - - public void buildConfig(String line) { - setBuildConfig(line) + public void buildConfigField( + @NonNull String type, + @NonNull String name, + @NonNull String value) { + addBuildConfigField(AndroidBuilder.createClassField(type, name, value)); } @NonNull diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/NdkConfigDsl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/NdkConfigDsl.java index 0a5c79d..64f704a 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/NdkConfigDsl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/NdkConfigDsl.java @@ -24,6 +24,7 @@ import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Optional; import java.io.Serializable; +import java.util.Collection; import java.util.Collections; import java.util.Set; @@ -34,7 +35,7 @@ public class NdkConfigDsl implements NdkConfig, Serializable { private String moduleName; private String cFlags; - private String ldLibs; + private Set<String> ldLibs; private Set<String> abiFilters; private String stl; @@ -44,8 +45,8 @@ public class NdkConfigDsl implements NdkConfig, Serializable { public NdkConfigDsl(@NonNull NdkConfigDsl ndkConfig) { moduleName = ndkConfig.moduleName; cFlags = ndkConfig.cFlags; - ldLibs = ndkConfig.ldLibs; - setSrcDirs(ndkConfig.abiFilters); + setLdLibs(ndkConfig.ldLibs); + setAbiFilters(ndkConfig.abiFilters); } @Override @@ -70,14 +71,46 @@ public class NdkConfigDsl implements NdkConfig, Serializable { @Override @Input @Optional - public String getLdLibs() { + public Set<String> getLdLibs() { return ldLibs; } - public void setLdLibs(String ldLibs) { - this.ldLibs = ldLibs; + @NonNull + public NdkConfigDsl ldLibs(String lib) { + if (ldLibs == null) { + ldLibs = Sets.newHashSet(); + } + ldLibs.add(lib); + return this; + } + + @NonNull + public NdkConfigDsl ldLibs(String... libs) { + if (ldLibs == null) { + ldLibs = Sets.newHashSetWithExpectedSize(libs.length); + } + Collections.addAll(ldLibs, libs); + return this; + } + + @NonNull + public NdkConfigDsl setLdLibs(Collection<String> libs) { + if (libs != null) { + if (abiFilters == null) { + abiFilters = Sets.newHashSetWithExpectedSize(libs.size()); + } else { + abiFilters.clear(); + } + for (String filter : libs) { + abiFilters.add(filter); + } + } else { + abiFilters = null; + } + return this; } + @Override @Input @Optional public Set<String> getAbiFilters() { @@ -103,10 +136,10 @@ public class NdkConfigDsl implements NdkConfig, Serializable { } @NonNull - public NdkConfigDsl setSrcDirs(Iterable<String> filters) { + public NdkConfigDsl setAbiFilters(Collection<String> filters) { if (filters != null) { if (abiFilters == null) { - abiFilters = Sets.newHashSetWithExpectedSize(2); + abiFilters = Sets.newHashSetWithExpectedSize(filters.size()); } else { abiFilters.clear(); } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy index 6b78c86..1645a03 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy @@ -17,6 +17,7 @@ package com.android.build.gradle.internal.dsl import com.android.annotations.NonNull import com.android.annotations.Nullable +import com.android.builder.AndroidBuilder import com.android.builder.DefaultProductFlavor import com.android.builder.NdkConfig import org.gradle.api.Action @@ -50,12 +51,11 @@ class ProductFlavorDsl extends DefaultProductFlavor { // -- DSL Methods. TODO remove once the instantiator does what I expect it to do. - public void buildConfig(String... lines) { - setBuildConfig(lines) - } - - public void buildConfig(String line) { - setBuildConfig(line) + public void buildConfigField( + @NonNull String type, + @NonNull String name, + @NonNull String value) { + addBuildConfigField(AndroidBuilder.createClassField(type, name, value)); } @NonNull diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java index 03daa6f..ccb1e8b 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java @@ -20,6 +20,7 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.builder.NdkConfig; import com.android.builder.model.BuildType; +import com.android.builder.model.ClassField; import java.io.File; import java.io.Serializable; @@ -112,7 +113,7 @@ class BuildTypeImpl implements BuildType, Serializable { @NonNull @Override - public List<String> getBuildConfig() { + public List<ClassField> getBuildConfigFields() { return Collections.emptyList(); } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.groovy index 9edd1c0..c3ede88 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.groovy @@ -152,14 +152,20 @@ public class ModelBuilder implements ToolingModelBuilder { ArtifactInfo testArtifact = testVariantData != null ? createArtifactInfo(testVariantData, gradleProjects) : null + SourceProvider sp = variantData.variantConfiguration.getVariantSourceProvider(); + if (sp != null) { + sp = SourceProviderImpl.cloneProvider(sp); + } + VariantImpl variant = new VariantImpl( - variantData.name, - variantData.baseName, + variantData.variantConfiguration.fullName, + variantData.variantConfiguration.baseName, variantData.variantConfiguration.buildType.name, getProductFlavorNames(variantData), ProductFlavorImpl.cloneFlavor(variantData.variantConfiguration.mergedFlavor), mainArtifact, - testArtifact) + testArtifact, + sp) return variant } @@ -214,6 +220,11 @@ public class ModelBuilder implements ToolingModelBuilder { folders.add(variantData.renderscriptCompileTask.sourceOutputDir) folders.add(variantData.generateBuildConfigTask.sourceOutputDir) + List<File> extraFolders = variantData.extraGeneratedSourceFolders + if (extraFolders != null) { + folders.addAll(extraFolders) + } + return folders } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java index d03ae14..8380ae3 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java @@ -19,6 +19,7 @@ package com.android.build.gradle.internal.model; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.builder.NdkConfig; +import com.android.builder.model.ClassField; import com.android.builder.model.ProductFlavor; import java.io.File; @@ -142,7 +143,7 @@ class ProductFlavorImpl implements ProductFlavor, Serializable { @NonNull @Override - public List<String> getBuildConfig() { + public List<ClassField> getBuildConfigFields() { return Collections.emptyList(); } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/model/VariantImpl.java b/gradle/src/main/groovy/com/android/build/gradle/internal/model/VariantImpl.java index f9a5c86..2baef84 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/model/VariantImpl.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/model/VariantImpl.java @@ -19,6 +19,7 @@ package com.android.build.gradle.internal.model; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.builder.model.ArtifactInfo; +import com.android.builder.model.SourceProvider; import com.android.builder.model.Variant; import com.android.builder.model.ProductFlavor; @@ -46,6 +47,8 @@ class VariantImpl implements Variant, Serializable { private final ArtifactInfo mainArtifactInfo; @Nullable private final ArtifactInfo testArtifactInfo; + @Nullable + private final SourceProvider variantSourceProvider; VariantImpl(@NonNull String name, @NonNull String displayName, @@ -53,7 +56,8 @@ class VariantImpl implements Variant, Serializable { @NonNull List<String> productFlavorNames, @NonNull ProductFlavorImpl mergedFlavor, @NonNull ArtifactInfo mainArtifactInfo, - @Nullable ArtifactInfo testArtifactInfo) { + @Nullable ArtifactInfo testArtifactInfo, + @Nullable SourceProvider variantSourceProvider) { this.name = name; this.displayName = displayName; this.buildTypeName = buildTypeName; @@ -61,6 +65,7 @@ class VariantImpl implements Variant, Serializable { this.mergedFlavor = mergedFlavor; this.mainArtifactInfo = mainArtifactInfo; this.testArtifactInfo = testArtifactInfo; + this.variantSourceProvider = variantSourceProvider; } @Override @@ -110,4 +115,10 @@ class VariantImpl implements Variant, Serializable { public List<String> getResourceConfigurations() { return Collections.emptyList(); } + + @Override + @Nullable + public SourceProvider getSourceProvider() { + return variantSourceProvider; + } } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/tasks/NdkTask.groovy b/gradle/src/main/groovy/com/android/build/gradle/internal/tasks/NdkTask.groovy index cc5b5d2..05c56d8 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/tasks/NdkTask.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/tasks/NdkTask.groovy @@ -37,7 +37,7 @@ class NdkTask extends BaseTask { } @Input @Optional - String getLdLibs() { + Set<String> getLdLibs() { return getNdkConfig()?.ldLibs } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java index ef74235..9c1f580 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApkVariantData.java @@ -44,34 +44,12 @@ public abstract class ApkVariantData extends BaseVariantData { if (getVariantConfiguration().hasFlavors()) { return String.format("%s build for flavor %s", getCapitalizedBuildTypeName(), - getFlavoredName(true)); + getCapitalizedFlavorName()); } else { return String.format("%s build", getCapitalizedBuildTypeName()); } } - @Override - @NonNull - public String getDirName() { - if (getVariantConfiguration().hasFlavors()) { - return String.format("%s/%s", - getFlavoredName(false), getVariantConfiguration().getBuildType().getName()); - } else { - return getVariantConfiguration().getBuildType().getName(); - } - } - - @Override - @NonNull - public String getBaseName() { - if (getVariantConfiguration().hasFlavors()) { - return String.format("%s-%s", - getFlavoredName(false), getVariantConfiguration().getBuildType().getName()); - } else { - return getVariantConfiguration().getBuildType().getName(); - } - } - public boolean isSigned() { return getVariantConfiguration().isSigningReady(); } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java index a602a29..91c4d08 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java @@ -31,15 +31,6 @@ public class ApplicationVariantData extends ApkVariantData implements TestedVari super(config); } - @NonNull - @Override - protected String computeName() { - return getVariantConfiguration().hasFlavors() ? - String.format("%s%s", - getFlavoredName(true), getCapitalizedBuildTypeName()) : - getCapitalizedBuildTypeName(); - } - @Override public void setTestVariantData(@Nullable TestVariantData testVariantData) { this.testVariantData = testVariantData; diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java index 069143e..83794e8 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/BaseVariantData.java @@ -17,6 +17,7 @@ package com.android.build.gradle.internal.variant; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.annotations.VisibleForTesting; import com.android.build.gradle.internal.StringHelper; import com.android.build.gradle.internal.dependency.VariantDependencies; import com.android.build.gradle.internal.tasks.PrepareDependenciesTask; @@ -28,9 +29,8 @@ import com.android.build.gradle.tasks.NdkCompile; import com.android.build.gradle.tasks.ProcessAndroidResources; import com.android.build.gradle.tasks.ProcessManifest; import com.android.build.gradle.tasks.RenderscriptCompile; -import com.android.builder.BuilderConstants; -import com.android.builder.DefaultProductFlavor; import com.android.builder.VariantConfiguration; +import com.google.common.collect.Lists; import groovy.lang.Closure; import org.gradle.api.Task; import org.gradle.api.tasks.Copy; @@ -38,13 +38,15 @@ import org.gradle.api.tasks.compile.JavaCompile; import proguard.gradle.ProGuardTask; import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.List; /** * Base data about a variant. */ public abstract class BaseVariantData { - private String name; private final VariantConfiguration variantConfiguration; private VariantDependencies variantDependency; @@ -69,15 +71,13 @@ public abstract class BaseVariantData { public Task assembleTask; + private List<File> extraGeneratedSourceFolders; + public BaseVariantData(@NonNull VariantConfiguration variantConfiguration) { this.variantConfiguration = variantConfiguration; - this.name = computeName(); } @NonNull - protected abstract String computeName(); - - @NonNull public VariantConfiguration getVariantConfiguration() { return variantConfiguration; } @@ -92,56 +92,21 @@ public abstract class BaseVariantData { } @NonNull - public String getName() { - return name; - } - - @NonNull public abstract String getDescription(); - @NonNull - public abstract String getDirName(); - - @NonNull - public String getFlavorDirName() { - if (variantConfiguration.hasFlavors()) { - return getFlavoredName(false); - } else { - return ""; - } - } - - @NonNull - public String getFlavorName() { - if (variantConfiguration.hasFlavors()) { - return getFlavoredName(true); - } else { - return StringHelper.capitalize(BuilderConstants.MAIN); - } - } - - @NonNull - public abstract String getBaseName(); - @Nullable public String getPackageName() { return variantConfiguration.getPackageName(); } @NonNull - protected String getFlavoredName(boolean capitalized) { - StringBuilder builder = new StringBuilder(); - for (DefaultProductFlavor flavor : variantConfiguration.getFlavorConfigs()) { - String name = flavor.getName(); - builder.append(capitalized ? StringHelper.capitalize(name) : name); - } - - return builder.toString(); + protected String getCapitalizedBuildTypeName() { + return StringHelper.capitalize(variantConfiguration.getBuildType().getName()); } @NonNull - protected String getCapitalizedBuildTypeName() { - return StringHelper.capitalize(variantConfiguration.getBuildType().getName()); + protected String getCapitalizedFlavorName() { + return StringHelper.capitalize(variantConfiguration.getFlavorName()); } public void setOutputFile(Object file) { @@ -159,4 +124,51 @@ public abstract class BaseVariantData { assert false; return null; } + + @VisibleForTesting + @NonNull + String getName() { + return variantConfiguration.getFullName(); + } + + @Nullable + public List<File> getExtraGeneratedSourceFolders() { + return extraGeneratedSourceFolders; + } + + public void addJavaSourceFoldersToModel(@NonNull File... generatedSourceFolders) { + Collections.addAll(extraGeneratedSourceFolders, generatedSourceFolders); + } + + public void addJavaSourceFoldersToModel(@NonNull Collection<File> generatedSourceFolders) { + extraGeneratedSourceFolders.addAll(generatedSourceFolders); + } + + public void registerJavaGeneratingTask(@NonNull Task task, @NonNull File... generatedSourceFolders) { + if (extraGeneratedSourceFolders == null) { + extraGeneratedSourceFolders = Lists.newArrayList(); + } + + javaCompileTask.dependsOn(task); + + for (File f : generatedSourceFolders) { + javaCompileTask.source(f); + } + + addJavaSourceFoldersToModel(generatedSourceFolders); + } + + public void registerJavaGeneratingTask(@NonNull Task task, @NonNull Collection<File> generatedSourceFolders) { + if (extraGeneratedSourceFolders == null) { + extraGeneratedSourceFolders = Lists.newArrayList(); + } + + javaCompileTask.dependsOn(task); + + for (File f : generatedSourceFolders) { + javaCompileTask.source(f); + } + + addJavaSourceFoldersToModel(generatedSourceFolders); + } } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java index 852b8c5..8a86851 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java @@ -36,36 +36,17 @@ public class LibraryVariantData extends BaseVariantData implements TestedVariant @Override @NonNull - protected String computeName() { - return getVariantConfiguration().hasFlavors() ? - String.format("%s%s", - getFlavoredName(true), getCapitalizedBuildTypeName()) : - getCapitalizedBuildTypeName(); - } - - @Override - @NonNull public String getDescription() { if (getVariantConfiguration().hasFlavors()) { - return "Test build for the ${getFlavoredName(true)}${config.buildType.name.capitalize()} build"; + return String.format("%s build for flavor %s", + getCapitalizedBuildTypeName(), + getCapitalizedFlavorName()); } else { - return "Test for the ${config.buildType.name.capitalize()} build"; + return String.format("%s build", getCapitalizedBuildTypeName()); } } @Override - @NonNull - public String getDirName() { - return getVariantConfiguration().getBuildType().getName(); - } - - @Override - @NonNull - public String getBaseName() { - return getVariantConfiguration().getBuildType().getName(); - } - - @Override public void setTestVariantData(@Nullable TestVariantData testVariantData) { this.testVariantData = testVariantData; } diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java index ebd336c..b8d45ed 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/variant/TestVariantData.java @@ -43,20 +43,12 @@ public class TestVariantData extends ApkVariantData { return testedVariantData; } - @NonNull - @Override - protected String computeName() { - return getVariantConfiguration().hasFlavors() ? - String.format("%sTest", getFlavoredName(true)) : - "Test"; - } - @Override @NonNull public String getDescription() { if (getVariantConfiguration().hasFlavors()) { return String.format("Test build for the %s%s build", - getFlavoredName(true), getCapitalizedBuildTypeName()); + getCapitalizedFlavorName(), getCapitalizedBuildTypeName()); } else { return String.format("Test build for the %s build", getCapitalizedBuildTypeName()); @@ -64,26 +56,6 @@ public class TestVariantData extends ApkVariantData { } @Override - @NonNull - public String getDirName() { - if (getVariantConfiguration().hasFlavors()) { - return String.format("%s/test", getFlavoredName(false)); - } else { - return "test"; - } - } - - @Override - @NonNull - public String getBaseName() { - if (getVariantConfiguration().hasFlavors()) { - return String.format("%s-test", getFlavoredName(false)); - } else { - return "test"; - } - } - - @Override public boolean getZipAlign() { return false; } diff --git a/gradle/src/main/groovy/com/android/build/gradle/tasks/GenerateBuildConfig.groovy b/gradle/src/main/groovy/com/android/build/gradle/tasks/GenerateBuildConfig.groovy index 35bc489..cba93f0 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/tasks/GenerateBuildConfig.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/tasks/GenerateBuildConfig.groovy @@ -16,7 +16,9 @@ package com.android.build.gradle.tasks import com.android.build.gradle.internal.tasks.IncrementalTask +import com.android.builder.compiling.BuildConfigGenerator import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional import org.gradle.api.tasks.OutputDirectory public class GenerateBuildConfig extends IncrementalTask { @@ -29,13 +31,31 @@ public class GenerateBuildConfig extends IncrementalTask { // ----- PRIVATE TASK API ----- @Input - String packageName + String buildConfigPackageName + + @Input + String appPackageName @Input boolean debuggable @Input - List<String> javaLines; + String flavorName + + @Input + List<String> flavorNames + + @Input + String buildTypeName + + @Input @Optional + String versionName + + @Input + int versionCode + + @Input + List<Object> items; @Override protected void doFullTaskAction() { @@ -44,10 +64,33 @@ public class GenerateBuildConfig extends IncrementalTask { File destinationDir = getSourceOutputDir() emptyFolder(destinationDir) - getBuilder().generateBuildConfig( - getPackageName(), - isDebuggable(), - getJavaLines(), - getSourceOutputDir().absolutePath); + BuildConfigGenerator generator = new BuildConfigGenerator( + getSourceOutputDir().absolutePath, + getBuildConfigPackageName()); + + // Hack (see IDEA-100046): We want to avoid reporting "condition is always true" + // from the data flow inspection, so use a non-constant value. However, that defeats + // the purpose of this flag (when not in debug mode, if (BuildConfig.DEBUG && ...) will + // be completely removed by the compiler), so as a hack we do it only for the case + // where debug is true, which is the most likely scenario while the user is looking + // at source code. + //map.put(PH_DEBUG, Boolean.toString(mDebug)); + generator.addField("boolean", "DEBUG", getDebuggable() ? "Boolean.parseBoolean(\"true\")" : "false") + .addField("String", "PACKAGE_NAME", "\"${getAppPackageName()}\"") + .addField("String", "BUILD_TYPE", "\"${getBuildTypeName()}\"") + .addField("String", "FLAVOR", "\"${getFlavorName()}\"") + .addField("int", "VERSION_CODE", Integer.toString(getVersionCode())) + .addItems(getItems()); + + if (getVersionName() != null) { + generator.addField("String", "VERSION_NAME", "\"${getVersionName()}\"") + } + + int i = 1; + for (String name : getFlavorNames()) { + generator.addField("String", "FLAVOR${i++}", "\"$name\"") + } + + generator.generate(); } } diff --git a/gradle/src/main/groovy/com/android/build/gradle/tasks/NdkCompile.groovy b/gradle/src/main/groovy/com/android/build/gradle/tasks/NdkCompile.groovy index 45d7d99..d2a34d5 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/tasks/NdkCompile.groovy +++ b/gradle/src/main/groovy/com/android/build/gradle/tasks/NdkCompile.groovy @@ -37,7 +37,7 @@ import org.gradle.api.tasks.util.PatternSet */ class NdkCompile extends NdkTask { - Set<File> sourceFolders + List<File> sourceFolders @OutputFile File generatedMakefile @@ -54,7 +54,7 @@ class NdkCompile extends NdkTask { @InputFiles FileTree getSource() { FileTree src = null - Set<File> sources = getSourceFolders() + List<File> sources = getSourceFolders() if (!sources.isEmpty()) { src = getProject().files(new ArrayList<Object>(sources)).getAsFileTree() } @@ -127,7 +127,11 @@ class NdkCompile extends NdkTask { } if (ndk.ldLibs != null) { - sb.append("LOCAL_LDLIBS := ").append(ndk.ldLibs).append('\n') + sb.append('LOCAL_LDLIBS := \\\n') + for (String lib : ndk.ldLibs) { + sb.append('\t-l') .append(lib).append(' \\\n') + } + sb.append('\n') } sb.append("LOCAL_SRC_FILES := \\\n") @@ -136,6 +140,10 @@ class NdkCompile extends NdkTask { } sb.append('\n') + for (File sourceFolder : getSourceFolders()) { + sb.append("LOCAL_C_INCLUDES += ${sourceFolder.absolutePath}\n") + } + sb.append( "\ninclude \$(BUILD_SHARED_LIBRARY)\n") @@ -160,12 +168,6 @@ class NdkCompile extends NdkTask { } commands.add("APP_PLATFORM=" + target.hashString()) - // include paths - for (File sourceFolder : getSourceFolders()) { - commands.add("-I") - commands.add(sourceFolder.absolutePath) - } - // temp out commands.add("NDK_OUT=" + getObjFolder().absolutePath) diff --git a/gradle/src/test/groovy/com/android/build/gradle/AppPluginDslTest.groovy b/gradle/src/test/groovy/com/android/build/gradle/AppPluginDslTest.groovy index 756dfc7..bef2ec7 100644 --- a/gradle/src/test/groovy/com/android/build/gradle/AppPluginDslTest.groovy +++ b/gradle/src/test/groovy/com/android/build/gradle/AppPluginDslTest.groovy @@ -266,19 +266,17 @@ public class AppPluginDslTest extends BaseTest { @NonNull String testedVariantName, @NonNull Set<ApplicationVariant> variants, @NonNull Set<TestVariant> testVariants) { - ApplicationVariant variant = findNamedItem(variants, variantName) - assertNotNull(variant) + ApplicationVariant variant = findNamedItem(variants, variantName, "variantData") assertNotNull(variant.testVariant) assertEquals(testedVariantName, variant.testVariant.name) - assertEquals(variant.testVariant, findNamedItem(testVariants, testedVariantName)) + assertEquals(variant.testVariant, findNamedItemMaybe(testVariants, testedVariantName)) checkTasks(variant) checkTasks(variant.testVariant) } private static void checkNonTestedVariant(@NonNull String variantName, @NonNull Set<ApplicationVariant> variants) { - ApplicationVariant variant = findNamedItem(variants, variantName) - assertNotNull(variant) + ApplicationVariant variant = findNamedItem(variants, variantName, "variantData") assertNull(variant.testVariant) checkTasks(variant) } diff --git a/gradle/src/test/groovy/com/android/build/gradle/AppPluginInternalTest.groovy b/gradle/src/test/groovy/com/android/build/gradle/AppPluginInternalTest.groovy index d840272..4578945 100644 --- a/gradle/src/test/groovy/com/android/build/gradle/AppPluginInternalTest.groovy +++ b/gradle/src/test/groovy/com/android/build/gradle/AppPluginInternalTest.groovy @@ -60,14 +60,9 @@ public class AppPluginInternalTest extends BaseTest { List<BaseVariantData> variants = plugin.variantDataList assertEquals(3, variants.size()) // includes the test variant(s) - BaseVariantData debugVariant = findNamedItem(variants, "Debug") - assertNotNull(debugVariant) - - BaseVariantData release = findNamedItem(variants, "Release") - assertNotNull(release) - - BaseVariantData test = findNamedItem(variants, "Test") - assertNotNull(test) + findNamedItem(variants, "debug", "variantData") + findNamedItem(variants, "release", "variantData") + findNamedItem(variants, "debugTest", "variantData") } public void testDefaultConfig() { @@ -138,17 +133,14 @@ public class AppPluginInternalTest extends BaseTest { List<BaseVariantData> variants = plugin.variantDataList assertEquals(4, variants.size()) // includes the test variant(s) - BaseVariantData debugVariant = findNamedItem(variants, "Debug") - assertNotNull(debugVariant) + String[] variantNames = [ + "debug", "release", "staging"] - BaseVariantData releaseVariant = findNamedItem(variants, "Release") - assertNotNull(releaseVariant) - - BaseVariantData stagingVariant = findNamedItem(variants, "Staging") - assertNotNull(stagingVariant) + for (String variantName : variantNames) { + findNamedItem(variants, variantName, "variantData") + } - BaseVariantData testVariant = findNamedItem(variants, "Test") - assertNotNull(testVariant) + BaseVariantData testVariant = findNamedItem(variants, "stagingTest", "variantData") assertEquals("staging", testVariant.variantConfiguration.buildType.name) } @@ -179,12 +171,13 @@ public class AppPluginInternalTest extends BaseTest { List<BaseVariantData> variants = plugin.variantDataList assertEquals(6, variants.size()) // includes the test variant(s) - assertNotNull(findNamedItem(variants, "Flavor1Debug")) - assertNotNull(findNamedItem(variants, "Flavor1Release")) - assertNotNull(findNamedItem(variants, "Flavor1Test")) - assertNotNull(findNamedItem(variants, "Flavor2Debug")) - assertNotNull(findNamedItem(variants, "Flavor2Release")) - assertNotNull(findNamedItem(variants, "Flavor2Test")) + String[] variantNames = [ + "flavor1Debug", "flavor1Release", "flavor1DebugTest", + "flavor2Debug", "flavor2Release", "flavor2DebugTest"] + + for (String variantName : variantNames) { + findNamedItem(variants, variantName, "variantData") + } } public void testMultiFlavors() { @@ -226,24 +219,29 @@ public class AppPluginInternalTest extends BaseTest { List<BaseVariantData> variants = plugin.variantDataList assertEquals(18, variants.size()) // includes the test variant(s) - assertNotNull(findNamedItem(variants, "F1FaDebug")) - assertNotNull(findNamedItem(variants, "F1FbDebug")) - assertNotNull(findNamedItem(variants, "F1FcDebug")) - assertNotNull(findNamedItem(variants, "F2FaDebug")) - assertNotNull(findNamedItem(variants, "F2FbDebug")) - assertNotNull(findNamedItem(variants, "F2FcDebug")) - assertNotNull(findNamedItem(variants, "F1FaRelease")) - assertNotNull(findNamedItem(variants, "F1FbRelease")) - assertNotNull(findNamedItem(variants, "F1FcRelease")) - assertNotNull(findNamedItem(variants, "F2FaRelease")) - assertNotNull(findNamedItem(variants, "F2FbRelease")) - assertNotNull(findNamedItem(variants, "F2FcRelease")) - assertNotNull(findNamedItem(variants, "F1FaTest")) - assertNotNull(findNamedItem(variants, "F1FbTest")) - assertNotNull(findNamedItem(variants, "F1FcTest")) - assertNotNull(findNamedItem(variants, "F2FaTest")) - assertNotNull(findNamedItem(variants, "F2FbTest")) - assertNotNull(findNamedItem(variants, "F2FcTest")) + String[] variantNames = [ + "f1FaDebug", + "f1FbDebug", + "f1FcDebug", + "f2FaDebug", + "f2FbDebug", + "f2FcDebug", + "f1FaRelease", + "f1FbRelease", + "f1FcRelease", + "f2FaRelease", + "f2FbRelease", + "f2FcRelease", + "f1FaDebugTest", + "f1FbDebugTest", + "f1FcDebugTest", + "f2FaDebugTest", + "f2FbDebugTest", + "f2FcDebugTest"]; + + for (String variantName : variantNames) { + findNamedItem(variants, variantName, "variantData"); + } } public void testSigningConfigs() { @@ -312,37 +310,31 @@ public class AppPluginInternalTest extends BaseTest { BaseVariantData variant SigningConfig signingConfig - variant = findNamedItem(variants, "Flavor1Debug") - assertNotNull(variant) + variant = findNamedItem(variants, "flavor1Debug", "variantData") signingConfig = variant.variantConfiguration.signingConfig assertNotNull(signingConfig) assertEquals(KeystoreHelper.defaultDebugKeystoreLocation(), signingConfig.storeFile?.absolutePath) - variant = findNamedItem(variants, "Flavor1Staging") - assertNotNull(variant) + variant = findNamedItem(variants, "flavor1Staging", "variantData") signingConfig = variant.variantConfiguration.signingConfig assertNull(signingConfig) - variant = findNamedItem(variants, "Flavor1Release") - assertNotNull(variant) + variant = findNamedItem(variants, "flavor1Release", "variantData") signingConfig = variant.variantConfiguration.signingConfig assertNotNull(signingConfig) assertEquals(new File(project.projectDir, "a3"), signingConfig.storeFile) - variant = findNamedItem(variants, "Flavor2Debug") - assertNotNull(variant) + variant = findNamedItem(variants, "flavor2Debug", "variantData") signingConfig = variant.variantConfiguration.signingConfig assertNotNull(signingConfig) assertEquals(KeystoreHelper.defaultDebugKeystoreLocation(), signingConfig.storeFile?.absolutePath) - variant = findNamedItem(variants, "Flavor2Staging") - assertNotNull(variant) + variant = findNamedItem(variants, "flavor2Staging", "variantData") signingConfig = variant.variantConfiguration.signingConfig assertNotNull(signingConfig) assertEquals(new File(project.projectDir, "a1"), signingConfig.storeFile) - variant = findNamedItem(variants, "Flavor2Release") - assertNotNull(variant) + variant = findNamedItem(variants, "flavor2Release", "variantData") signingConfig = variant.variantConfiguration.signingConfig assertNotNull(signingConfig) assertEquals(new File(project.projectDir, "a3"), signingConfig.storeFile) diff --git a/gradle/src/test/groovy/com/android/build/gradle/internal/test/BaseTest.groovy b/gradle/src/test/groovy/com/android/build/gradle/internal/test/BaseTest.groovy index ac62126..269a557 100755 --- a/gradle/src/test/groovy/com/android/build/gradle/internal/test/BaseTest.groovy +++ b/gradle/src/test/groovy/com/android/build/gradle/internal/test/BaseTest.groovy @@ -183,8 +183,8 @@ public abstract class BaseTest extends TestCase { * @param name the name of the item to return * @return the found item or null */ - protected static <T> T findNamedItem(@NonNull Collection<T> items, - @NonNull String name) { + protected static <T> T findNamedItemMaybe(@NonNull Collection<T> items, + @NonNull String name) { for (T item : items) { if (name.equals(item.name)) { return item @@ -193,4 +193,18 @@ public abstract class BaseTest extends TestCase { return null } + + /** + * Returns the name item from the collection of items. The items *must* have a "name" property. + * @param items the item collection to search for a match + * @param name the name of the item to return + * @return the found item or null + */ + protected static <T> T findNamedItem(@NonNull Collection<T> items, + @NonNull String name, + @NonNull String typeName) { + T foundItem = findNamedItemMaybe(items, name); + assertNotNull("$name $typeName null-check", foundItem) + return foundItem + } } diff --git a/tests/basic/build.gradle b/tests/basic/build.gradle index b020f58..b713714 100644 --- a/tests/basic/build.gradle +++ b/tests/basic/build.gradle @@ -43,8 +43,8 @@ android { testInstrumentationRunner "android.test.InstrumentationTestRunner" testHandleProfiling false - buildConfig "private final static boolean DEFAULT = true;", \ - "private final static String FOO = \"foo\";" + buildConfigField "boolean", "DEFAULT", "true" + buildConfigField "String", "FOO", "\"foo\"" } buildTypes { @@ -52,7 +52,7 @@ android { packageNameSuffix ".debug" signingConfig signingConfigs.myConfig - buildConfig "private final static boolean DEBUG2 = false;" + buildConfigField "String", "FOO", "\"bar\"" } } diff --git a/tests/basic/src/instrumentTest/java/com/android/tests/basic/MainTest.java b/tests/basic/src/instrumentTest/java/com/android/tests/basic/MainTest.java index 7cf7329..9f4b2de 100644 --- a/tests/basic/src/instrumentTest/java/com/android/tests/basic/MainTest.java +++ b/tests/basic/src/instrumentTest/java/com/android/tests/basic/MainTest.java @@ -34,5 +34,10 @@ public class MainTest extends ActivityInstrumentationTestCase2<Main> { public void testPreconditions() { assertNotNull(mTextView); } + + @MediumTest + public void testBuildConfig() { + assertEquals("bar", BuildConfig.FOO); + } } diff --git a/tests/flavored/build.gradle b/tests/flavored/build.gradle index 61f0cea..d08c3fe 100644 --- a/tests/flavored/build.gradle +++ b/tests/flavored/build.gradle @@ -15,28 +15,23 @@ android { testBuildType = "staging" defaultConfig { - buildConfig "private final static boolean DEFAULT = true;", \ - "private final static String FOO = \"foo\";" } productFlavors { f1 { packageName = "com.android.tests.flavored.f1" versionName = "1.0.0-f1" - buildConfig "private final static String FLAVOR = \"f1\";" } f2 { packageName = "com.android.tests.flavored.f2" versionName = "1.0.0-f2" - buildConfig "private final static String FLAVOR = \"f2\";" } } - + buildTypes { debug { packageNameSuffix = ".debug" versionNameSuffix = ".D" - buildConfig "private final static boolean DEBUG2 = false;" } staging { packageNameSuffix = ".staging" diff --git a/tests/flavored/src/f1/res/values/strings.xml b/tests/flavored/src/f1/res/values/strings.xml index f081f40..7154c04 100644 --- a/tests/flavored/src/f1/res/values/strings.xml +++ b/tests/flavored/src/f1/res/values/strings.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">_Test-Flavored-f1</string> + <string name="text">F1 text</string> </resources> diff --git a/tests/flavored/src/f1Staging/res/values/strings.xml b/tests/flavored/src/f1Staging/res/values/strings.xml new file mode 100644 index 0000000..782422e --- /dev/null +++ b/tests/flavored/src/f1Staging/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="text">F1-Staging text</string> +</resources> diff --git a/tests/flavored/src/instrumentTest/java/com/android/tests/flavored/MainTest.java b/tests/flavored/src/instrumentTest/java/com/android/tests/flavored/MainTest.java index f44e0f0..b22c53d 100644 --- a/tests/flavored/src/instrumentTest/java/com/android/tests/flavored/MainTest.java +++ b/tests/flavored/src/instrumentTest/java/com/android/tests/flavored/MainTest.java @@ -34,5 +34,14 @@ public class MainTest extends ActivityInstrumentationTestCase2<Main> { public void testPreconditions() { assertNotNull(mTextView); } + + @MediumTest + public void testStagingText() { + if ("f1".equals(BuildConfig.FLAVOR)) { + assertEquals("F1-Staging text", mTextView.getText()); + } else { + assertEquals("default text", mTextView.getText()); + } + } } diff --git a/tests/flavored/src/main/res/layout/main.xml b/tests/flavored/src/main/res/layout/main.xml index 058715f..9d4e976 100644 --- a/tests/flavored/src/main/res/layout/main.xml +++ b/tests/flavored/src/main/res/layout/main.xml @@ -7,7 +7,7 @@ <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" - android:text="Test App - Flavored" + android:text="@string/text" android:id="@+id/text" /> </LinearLayout> diff --git a/tests/flavored/src/main/res/values/strings.xml b/tests/flavored/src/main/res/values/strings.xml index 24db545..46d8260 100644 --- a/tests/flavored/src/main/res/values/strings.xml +++ b/tests/flavored/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">###</string> + <string name="text">default text</string> </resources> diff --git a/tests/flavors/build.gradle b/tests/flavors/build.gradle index d3f5940..1b1c683 100644 --- a/tests/flavors/build.gradle +++ b/tests/flavors/build.gradle @@ -17,21 +17,16 @@ android { productFlavors { f1 { flavorGroup "group1" - - buildConfig "public final static String GROUP1 = \"F1\";" } f2 { flavorGroup "group1" - buildConfig "public final static String GROUP1 = \"F2\";" } fa { flavorGroup "group2" - buildConfig "public final static String GROUP2 = \"FA\";" } fb { flavorGroup "group2" - buildConfig "public final static String GROUP2 = \"FB\";" } } } diff --git a/tests/flavors/src/f1/java/com/android/tests/flavors/group1/SomeClass.java b/tests/flavors/src/f1/java/com/android/tests/flavors/group1/SomeClass.java index a5c30b2..ffbf5ab 100644 --- a/tests/flavors/src/f1/java/com/android/tests/flavors/group1/SomeClass.java +++ b/tests/flavors/src/f1/java/com/android/tests/flavors/group1/SomeClass.java @@ -2,6 +2,6 @@ package com.android.tests.flavors.group1; public class SomeClass { public static String getString() { - return "F1"; + return "f1"; } }
\ No newline at end of file diff --git a/tests/flavors/src/f1/res/values/strings.xml b/tests/flavors/src/f1/res/values/strings.xml index 73e7584..b4db3e8 100644 --- a/tests/flavors/src/f1/res/values/strings.xml +++ b/tests/flavors/src/f1/res/values/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="group1_string">F1</string> - <string name="general_string">F1</string> + <string name="group1_string">f1</string> + <string name="general_string">f1</string> </resources>
\ No newline at end of file diff --git a/tests/flavors/src/f2/java/com/android/tests/flavors/group1/SomeClass.java b/tests/flavors/src/f2/java/com/android/tests/flavors/group1/SomeClass.java index 5974587..09327a6 100644 --- a/tests/flavors/src/f2/java/com/android/tests/flavors/group1/SomeClass.java +++ b/tests/flavors/src/f2/java/com/android/tests/flavors/group1/SomeClass.java @@ -2,6 +2,6 @@ package com.android.tests.flavors.group1; public class SomeClass { public static String getString() { - return "F2"; + return "f2"; } }
\ No newline at end of file diff --git a/tests/flavors/src/f2/res/values/strings.xml b/tests/flavors/src/f2/res/values/strings.xml index 855e7f6..7a306fc 100644 --- a/tests/flavors/src/f2/res/values/strings.xml +++ b/tests/flavors/src/f2/res/values/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="group1_string">F2</string> - <string name="general_string">F2</string> + <string name="group1_string">f2</string> + <string name="general_string">f2</string> </resources>
\ No newline at end of file diff --git a/tests/flavors/src/fa/java/com/android/tests/flavors/group2/SomeClass.java b/tests/flavors/src/fa/java/com/android/tests/flavors/group2/SomeClass.java index 40a939e..ae7677b 100644 --- a/tests/flavors/src/fa/java/com/android/tests/flavors/group2/SomeClass.java +++ b/tests/flavors/src/fa/java/com/android/tests/flavors/group2/SomeClass.java @@ -2,6 +2,6 @@ package com.android.tests.flavors.group2; public class SomeClass { public static String getString() { - return "FA"; + return "fa"; } }
\ No newline at end of file diff --git a/tests/flavors/src/fa/res/values/strings.xml b/tests/flavors/src/fa/res/values/strings.xml index 331cb90..f8cefe7 100644 --- a/tests/flavors/src/fa/res/values/strings.xml +++ b/tests/flavors/src/fa/res/values/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="group2_string">FA</string> - <string name="general_string">FA</string> + <string name="group2_string">fa</string> + <string name="general_string">fa</string> </resources>
\ No newline at end of file diff --git a/tests/flavors/src/fb/java/com/android/tests/flavors/group2/SomeClass.java b/tests/flavors/src/fb/java/com/android/tests/flavors/group2/SomeClass.java index 7441b61..5768d64 100644 --- a/tests/flavors/src/fb/java/com/android/tests/flavors/group2/SomeClass.java +++ b/tests/flavors/src/fb/java/com/android/tests/flavors/group2/SomeClass.java @@ -2,6 +2,6 @@ package com.android.tests.flavors.group2; public class SomeClass { public static String getString() { - return "FB"; + return "fb"; } }
\ No newline at end of file diff --git a/tests/flavors/src/fb/res/values/strings.xml b/tests/flavors/src/fb/res/values/strings.xml index fa0733f..8fa24dc 100644 --- a/tests/flavors/src/fb/res/values/strings.xml +++ b/tests/flavors/src/fb/res/values/strings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="group2_string">FB</string> - <string name="general_string">FB</string> + <string name="group2_string">fb</string> + <string name="general_string">fb</string> </resources>
\ No newline at end of file diff --git a/tests/flavors/src/instrumentTestF1/java/com/android/tests/flavors/MainActivityGroup1Test.java b/tests/flavors/src/instrumentTestF1/java/com/android/tests/flavors/MainActivityGroup1Test.java index 2c043ef..9379d96 100644 --- a/tests/flavors/src/instrumentTestF1/java/com/android/tests/flavors/MainActivityGroup1Test.java +++ b/tests/flavors/src/instrumentTestF1/java/com/android/tests/flavors/MainActivityGroup1Test.java @@ -80,17 +80,17 @@ public class MainActivityGroup1Test extends ActivityInstrumentationTestCase2<Mai @MediumTest public void testResOverlay() { - assertEquals("F1", mResOverLay.getText()); - assertEquals("F1", mResOverLay1.getText()); + assertEquals("f1", mResOverLay.getText()); + assertEquals("f1", mResOverLay1.getText()); } @MediumTest public void testBuildConfig() { - assertEquals("F1", mBuildConfig1.getText()); + assertEquals("f1", mBuildConfig1.getText()); } @MediumTest public void testCodeOverlay() { - assertEquals("F1", mCodeOverlay1.getText()); + assertEquals("f1", mCodeOverlay1.getText()); } } diff --git a/tests/flavors/src/instrumentTestF2/java/com/android/tests/flavors/MainActivityGroup1Test.java b/tests/flavors/src/instrumentTestF2/java/com/android/tests/flavors/MainActivityGroup1Test.java index 41e9ecf..8ecd057 100644 --- a/tests/flavors/src/instrumentTestF2/java/com/android/tests/flavors/MainActivityGroup1Test.java +++ b/tests/flavors/src/instrumentTestF2/java/com/android/tests/flavors/MainActivityGroup1Test.java @@ -80,17 +80,17 @@ public class MainActivityGroup1Test extends ActivityInstrumentationTestCase2<Mai @MediumTest public void testResOverlay() { - assertEquals("F2", mResOverLay.getText()); - assertEquals("F2", mResOverLay1.getText()); + assertEquals("f2", mResOverLay.getText()); + assertEquals("f2", mResOverLay1.getText()); } @MediumTest public void testBuildConfig() { - assertEquals("F2", mBuildConfig1.getText()); + assertEquals("f2", mBuildConfig1.getText()); } @MediumTest public void testCodeOverlay() { - assertEquals("F2", mCodeOverlay1.getText()); + assertEquals("f2", mCodeOverlay1.getText()); } } diff --git a/tests/flavors/src/instrumentTestFa/java/com/android/tests/flavors/MainActivityGroup2Test.java b/tests/flavors/src/instrumentTestFa/java/com/android/tests/flavors/MainActivityGroup2Test.java index 0d0fee2..3e51225 100644 --- a/tests/flavors/src/instrumentTestFa/java/com/android/tests/flavors/MainActivityGroup2Test.java +++ b/tests/flavors/src/instrumentTestFa/java/com/android/tests/flavors/MainActivityGroup2Test.java @@ -82,17 +82,17 @@ public class MainActivityGroup2Test extends ActivityInstrumentationTestCase2<Mai public void testResOverlay() { // because this group has lower priority, we check that the resource from // this flavor is not used. - assertFalse("FA".equals(mResOverLay.getText())); - assertEquals("FA", mResOverLay2.getText()); + assertFalse("fa".equals(mResOverLay.getText())); + assertEquals("fa", mResOverLay2.getText()); } @MediumTest public void testBuildConfig() { - assertEquals("FA", mBuildConfig2.getText()); + assertEquals("fa", mBuildConfig2.getText()); } @MediumTest public void testCodeOverlay() { - assertEquals("FA", mCodeOverlay2.getText()); + assertEquals("fa", mCodeOverlay2.getText()); } } diff --git a/tests/flavors/src/instrumentTestFb/java/com/android/tests/flavors/MainActivityGroup2Test.java b/tests/flavors/src/instrumentTestFb/java/com/android/tests/flavors/MainActivityGroup2Test.java index 6f92adf..f11b5ce 100644 --- a/tests/flavors/src/instrumentTestFb/java/com/android/tests/flavors/MainActivityGroup2Test.java +++ b/tests/flavors/src/instrumentTestFb/java/com/android/tests/flavors/MainActivityGroup2Test.java @@ -82,17 +82,17 @@ public class MainActivityGroup2Test extends ActivityInstrumentationTestCase2<Mai public void testResOverlay() { // because this group has lower priority, we check that the resource from // this flavor is not used. - assertFalse("FB".equals(mResOverLay.getText())); - assertEquals("FB", mResOverLay2.getText()); + assertFalse("fb".equals(mResOverLay.getText())); + assertEquals("fb", mResOverLay2.getText()); } @MediumTest public void testBuildConfig() { - assertEquals("FB", mBuildConfig2.getText()); + assertEquals("fb", mBuildConfig2.getText()); } @MediumTest public void testCodeOverlay() { - assertEquals("FB", mCodeOverlay2.getText()); + assertEquals("fb", mCodeOverlay2.getText()); } } diff --git a/tests/flavors/src/main/java/com/android/tests/flavors/MainActivity.java b/tests/flavors/src/main/java/com/android/tests/flavors/MainActivity.java index 6968643..d768e1e 100644 --- a/tests/flavors/src/main/java/com/android/tests/flavors/MainActivity.java +++ b/tests/flavors/src/main/java/com/android/tests/flavors/MainActivity.java @@ -14,10 +14,10 @@ public class MainActivity extends Activity { TextView tv; tv = (TextView) findViewById(R.id.buildconfig1); - tv.setText(BuildConfig.GROUP1); + tv.setText(BuildConfig.FLAVOR1); tv = (TextView) findViewById(R.id.buildconfig2); - tv.setText(BuildConfig.GROUP2); + tv.setText(BuildConfig.FLAVOR2); tv = (TextView) findViewById(R.id.codeoverlay1); tv.setText(com.android.tests.flavors.group1.SomeClass.getString()); diff --git a/tests/genFolderApi/build.gradle b/tests/genFolderApi/build.gradle new file mode 100644 index 0000000..3f35366 --- /dev/null +++ b/tests/genFolderApi/build.gradle @@ -0,0 +1,45 @@ +buildscript { + repositories { + maven { url '../../../../out/host/gradle/repo' } + } + dependencies { + classpath 'com.android.tools.build:gradle:0.7.0-SNAPSHOT' + } +} +apply plugin: 'android' + +android { + compileSdkVersion 15 + buildToolsVersion "18.0.1" +} + + +public class GenerateCode extends DefaultTask { + @Input + String value + + @OutputFile + File outputFile + + @TaskAction + void taskAction() { + getOutputFile().text = + "package com.custom;\n" + + "public class Foo {\n" + + " public static String getBuildDate() { return \"${getValue()}\"; }\n" + + "}\n"; + } +} + + +android.applicationVariants.all { variant -> + + // create a task that generates a java class + File sourceFolder = file("${buildDir}/customCode/${variant.dirName}") + def javaGenerationTask = tasks.create(name: "generatedCodeFor${variant.name.capitalize()}", type: GenerateCode) { + value new Date().format("yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC")) + outputFile file("${sourceFolder.absolutePath}/com/custom/Foo.java") + } + + variant.registerJavaGeneratingTask(javaGenerationTask, sourceFolder) +}
\ No newline at end of file diff --git a/tests/genFolderApi/src/main/AndroidManifest.xml b/tests/genFolderApi/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a34d937 --- /dev/null +++ b/tests/genFolderApi/src/main/AndroidManifest.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tests.basic"> + <application android:label="@string/app_name" android:icon="@drawable/icon"> + <activity android:name=".Main" + android:label="@string/app_name"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/tests/genFolderApi/src/main/java/com/android/tests/basic/Main.java b/tests/genFolderApi/src/main/java/com/android/tests/basic/Main.java new file mode 100644 index 0000000..df05828 --- /dev/null +++ b/tests/genFolderApi/src/main/java/com/android/tests/basic/Main.java @@ -0,0 +1,19 @@ +package com.android.tests.basic; + +import android.app.Activity; +import android.os.Bundle; +import android.widget.TextView; + +public class Main extends Activity +{ + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + TextView tv = (TextView) findViewById(R.id.text); + tv.setText(com.custom.Foo.getBuildDate()); + } +} diff --git a/tests/genFolderApi/src/main/res/drawable/icon.png b/tests/genFolderApi/src/main/res/drawable/icon.png Binary files differnew file mode 100644 index 0000000..a07c69f --- /dev/null +++ b/tests/genFolderApi/src/main/res/drawable/icon.png diff --git a/tests/genFolderApi/src/main/res/layout/main.xml b/tests/genFolderApi/src/main/res/layout/main.xml new file mode 100644 index 0000000..ee817cf --- /dev/null +++ b/tests/genFolderApi/src/main/res/layout/main.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + > +<TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="Test App - GenFolderApi" + android:id="@+id/text" + /> +</LinearLayout> + diff --git a/tests/genFolderApi/src/main/res/values/strings.xml b/tests/genFolderApi/src/main/res/values/strings.xml new file mode 100644 index 0000000..64ee88e --- /dev/null +++ b/tests/genFolderApi/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string name="app_name">_Test-genFolderApi</string> +</resources> diff --git a/tests/ndkSanAngeles/build.gradle b/tests/ndkSanAngeles/build.gradle index a7ddcb9..c537e77 100644 --- a/tests/ndkSanAngeles/build.gradle +++ b/tests/ndkSanAngeles/build.gradle @@ -16,7 +16,7 @@ android { ndk { moduleName "sanangeles" cFlags "-DANDROID_NDK -DDISABLE_IMPORTGL" - ldLibs "-lGLESv1_CM -ldl -llog" + ldLibs "GLESv1_CM", "dl", "log" stl "stlport_static" } } diff --git a/tests/rsSupportMode/build.gradle b/tests/rsSupportMode/build.gradle index 96f40e4..9df3260 100644 --- a/tests/rsSupportMode/build.gradle +++ b/tests/rsSupportMode/build.gradle @@ -10,7 +10,7 @@ apply plugin: 'android' android { compileSdkVersion 18 - buildToolsVersion "18.1" + buildToolsVersion "18.1.1" defaultConfig { minSdkVersion 8 @@ -36,4 +36,4 @@ android { } } } -}
\ No newline at end of file +} |