aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@google.com>2013-11-25 21:48:15 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2013-11-25 21:48:15 +0000
commit6a39b03bb738ea32426b98de64ca171ebefa50a4 (patch)
tree5e70a57799c1632381df5c976c6a3a5f4d631476
parent60aa3e26bfb1d3c263e6789446df7a9526ac1603 (diff)
parent6e00045fd570c43f8e37109e9bc8b32b1a6cb510 (diff)
downloadbuild-6a39b03bb738ea32426b98de64ca171ebefa50a4.tar.gz
Merge "Improved BuildConfig."
-rw-r--r--builder-model/src/main/java/com/android/builder/model/BaseConfig.java6
-rw-r--r--builder-model/src/main/java/com/android/builder/model/ClassField.java33
-rw-r--r--builder/build.gradle1
-rw-r--r--builder/src/main/java/com/android/builder/AndroidBuilder.java25
-rw-r--r--builder/src/main/java/com/android/builder/DefaultManifestParser.java21
-rw-r--r--builder/src/main/java/com/android/builder/ManifestParser.java42
-rw-r--r--builder/src/main/java/com/android/builder/VariantConfiguration.java105
-rw-r--r--builder/src/main/java/com/android/builder/compiling/BuildConfigGenerator.java135
-rw-r--r--builder/src/main/java/com/android/builder/internal/BaseConfigImpl.java31
-rw-r--r--builder/src/main/java/com/android/builder/internal/BuildConfigGenerator.java111
-rw-r--r--builder/src/main/java/com/android/builder/internal/ClassFieldImpl.java86
-rw-r--r--builder/src/main/resources/com/android/builder/internal/BuildConfig.template7
-rw-r--r--builder/src/test/java/com/android/builder/VariantConfigurationTest.java5
-rw-r--r--builder/src/test/java/com/android/builder/compiling/BuildConfigGeneratorTest.java102
-rw-r--r--builder/src/test/java/com/android/builder/internal/BuildConfigGeneratorTest.java75
-rw-r--r--changelog.txt10
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy32
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/dsl/BuildTypeDsl.groovy13
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/dsl/ProductFlavorDsl.groovy12
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/model/BuildTypeImpl.java3
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/internal/model/ProductFlavorImpl.java3
-rw-r--r--gradle/src/main/groovy/com/android/build/gradle/tasks/GenerateBuildConfig.groovy57
-rw-r--r--tests/basic/build.gradle6
-rw-r--r--tests/basic/src/instrumentTest/java/com/android/tests/basic/MainTest.java5
-rw-r--r--tests/flavored/build.gradle7
-rw-r--r--tests/flavors/build.gradle5
-rw-r--r--tests/flavors/src/f1/java/com/android/tests/flavors/group1/SomeClass.java2
-rw-r--r--tests/flavors/src/f1/res/values/strings.xml4
-rw-r--r--tests/flavors/src/f2/java/com/android/tests/flavors/group1/SomeClass.java2
-rw-r--r--tests/flavors/src/f2/res/values/strings.xml4
-rw-r--r--tests/flavors/src/fa/java/com/android/tests/flavors/group2/SomeClass.java2
-rw-r--r--tests/flavors/src/fa/res/values/strings.xml4
-rw-r--r--tests/flavors/src/fb/java/com/android/tests/flavors/group2/SomeClass.java2
-rw-r--r--tests/flavors/src/fb/res/values/strings.xml4
-rw-r--r--tests/flavors/src/instrumentTestF1/java/com/android/tests/flavors/MainActivityGroup1Test.java8
-rw-r--r--tests/flavors/src/instrumentTestF2/java/com/android/tests/flavors/MainActivityGroup1Test.java8
-rw-r--r--tests/flavors/src/instrumentTestFa/java/com/android/tests/flavors/MainActivityGroup2Test.java8
-rw-r--r--tests/flavors/src/instrumentTestFb/java/com/android/tests/flavors/MainActivityGroup2Test.java8
-rw-r--r--tests/flavors/src/main/java/com/android/tests/flavors/MainActivity.java4
39 files changed, 684 insertions, 314 deletions
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/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 d21a795..7c5f6b1 100644
--- a/builder/src/main/java/com/android/builder/VariantConfiguration.java
+++ b/builder/src/main/java/com/android/builder/VariantConfiguration.java
@@ -24,6 +24,7 @@ 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;
@@ -35,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;
@@ -323,6 +325,26 @@ public class VariantConfiguration implements TestData {
}
/**
+ * 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
@@ -640,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;
@@ -649,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;
@@ -721,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
@@ -1115,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/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 424a5f3..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
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 70ed31e..6525120 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -3,10 +3,18 @@
- 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 compoenents (res, manifest, etc...) have higher priority than components from build type
+ 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 s 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.
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 d442514..ab56022 100644
--- a/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
+++ b/gradle/src/main/groovy/com/android/build/gradle/BasePlugin.groovy
@@ -374,7 +374,7 @@ public abstract class BasePlugin {
getManifestDependencies(config.directLibraries)
}
processManifestTask.conventionMapping.versionCode = {
- mergedFlavor.versionCode
+ config.versionCode
}
processManifestTask.conventionMapping.minSdkVersion = {
mergedFlavor.minSdkVersion
@@ -549,16 +549,40 @@ 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 = {
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/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/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/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/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 41e50d9..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 "public final static String FLAVOR = \"f1\";"
}
f2 {
packageName = "com.android.tests.flavored.f2"
versionName = "1.0.0-f2"
- buildConfig "public 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/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());