summaryrefslogtreecommitdiff
path: root/android-gradle-jps
diff options
context:
space:
mode:
authorAlex Ruiz <alruiz@google.com>2013-10-31 21:10:20 -0700
committerAlex Ruiz <alruiz@google.com>2013-11-03 15:18:22 -0800
commit056d3d90715dedea0c7bd00eb098cf3e22c43e3e (patch)
treed849f84f61ec4b4569a7524731c7871358dbdeb0 /android-gradle-jps
parent87c21cd3efa570921995cbaa2d59df501ccbb562 (diff)
downloadidea-056d3d90715dedea0c7bd00eb098cf3e22c43e3e.tar.gz
Enabled building selected modules.
(By "building" we mean "making" and "compiling.") Currently, Android Studio builds all the modules in the project. Users have reported that they only want to build certain modules. This CL enables that. The main issue with JPS is that it is impossible to have a 'target builder' (in JPS terminology) that knows about all the selected modules in the IDE (JPS has no notion of an IDE.) The most that we can get from JPS is to have one 'target builder' per module, and these target builders won't know about each other, making it impossible to have a single call to Gradle passing the tasks to execute per selected module (we would end with a call to Gradle per module.) To work around this, we have a back door: we have an extension point in JPS where we can pass JVM args to the JPS process (we requested that some time ago.) In this CL we pass the names of the selected modules (if any) to as JVM parameters to the JPS process. On the other hand, it is really easy to implement building selected modules in the new build strategy. In addition, this CL: - Fixes the "update" mechanism of the "Make Module(s)" and "Compile Module(s)". - Makes it possible to compile a module if any of its files is selected. - Unifies the way Gradle tasks to execute are calculated (for both JPS and direct Gradle invocation,) fixing bugs in both build approaches. - Does not call "assemble" on pure Java libraries when generating sources. - Cleans up code. - Adds more tests. Fixes https://code.google.com/p/android/issues/detail?id=59915 Change-Id: I4f24fbfd4773d37c0276ee7b6815d85f6b312fa0
Diffstat (limited to 'android-gradle-jps')
-rw-r--r--android-gradle-jps/src/com/android/tools/idea/jps/builder/AndroidGradleTargetBuilder.java80
-rw-r--r--android-gradle-jps/src/com/android/tools/idea/jps/builder/BuilderExecutionSettings.java74
-rw-r--r--android-gradle-jps/testSrc/com/android/tools/idea/jps/builder/BuilderExecutionSettingsTest.java11
3 files changed, 86 insertions, 79 deletions
diff --git a/android-gradle-jps/src/com/android/tools/idea/jps/builder/AndroidGradleTargetBuilder.java b/android-gradle-jps/src/com/android/tools/idea/jps/builder/AndroidGradleTargetBuilder.java
index e4f296d0ba6..a9edea63bbc 100644
--- a/android-gradle-jps/src/com/android/tools/idea/jps/builder/AndroidGradleTargetBuilder.java
+++ b/android-gradle-jps/src/com/android/tools/idea/jps/builder/AndroidGradleTargetBuilder.java
@@ -15,13 +15,12 @@
*/
package com.android.tools.idea.jps.builder;
-import com.android.SdkConstants;
import com.android.tools.idea.gradle.output.GradleMessage;
+import com.android.tools.idea.gradle.output.parser.GradleErrorOutputParser;
import com.android.tools.idea.gradle.util.AndroidGradleSettings;
-import com.android.tools.idea.gradle.util.BuildMode;
+import com.android.tools.idea.gradle.util.GradleBuilds;
import com.android.tools.idea.jps.AndroidGradleJps;
import com.android.tools.idea.jps.model.JpsAndroidGradleModuleExtension;
-import com.android.tools.idea.gradle.output.parser.GradleErrorOutputParser;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.io.Closeables;
@@ -59,10 +58,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@@ -73,10 +69,11 @@ public class AndroidGradleTargetBuilder extends TargetBuilder<AndroidGradleBuild
private static final GradleErrorOutputParser ERROR_OUTPUT_PARSER = new GradleErrorOutputParser();
@NonNls private static final String CLEAN_TASK_NAME = "clean";
- @NonNls private static final String DEFAULT_ASSEMBLE_TASK_NAME = "assemble";
@NonNls private static final String BUILDER_NAME = "Android Gradle Target Builder";
+ private static final int BUFFER_SIZE = 2048;
+
public AndroidGradleTargetBuilder() {
super(Collections.singletonList(AndroidGradleBuildTarget.TargetType.INSTANCE));
}
@@ -131,7 +128,7 @@ public class AndroidGradleTargetBuilder extends TargetBuilder<AndroidGradleBuild
@NotNull BuilderExecutionSettings executionSettings) {
boolean buildTests = AndroidJpsUtil.isInstrumentationTestContext(context);
List<String> tasks = Lists.newArrayList();
- for (JpsModule module : project.getModules()) {
+ for (JpsModule module : getModulesToBuild(project, executionSettings)) {
populateBuildTasks(module, executionSettings, tasks, buildTests);
}
if (!tasks.isEmpty()) {
@@ -143,6 +140,22 @@ public class AndroidGradleTargetBuilder extends TargetBuilder<AndroidGradleBuild
return tasks.toArray(new String[tasks.size()]);
}
+ @NotNull
+ private static List<JpsModule> getModulesToBuild(@NotNull JpsProject project, @NotNull BuilderExecutionSettings executionSettings) {
+ List<JpsModule> modules = project.getModules();
+ Set<String> moduleNames = executionSettings.getModulesToBuildNames();
+ if (moduleNames.isEmpty()) {
+ return modules;
+ }
+ List<JpsModule> modulesToBuild = Lists.newArrayList();
+ for (JpsModule module : modules) {
+ if (moduleNames.contains(module.getName())) {
+ modulesToBuild.add(module);
+ }
+ }
+ return modulesToBuild;
+ }
+
private static void populateBuildTasks(@NotNull JpsModule module,
@NotNull BuilderExecutionSettings executionSettings,
@NotNull List<String> tasks,
@@ -152,49 +165,10 @@ public class AndroidGradleTargetBuilder extends TargetBuilder<AndroidGradleBuild
return;
}
String gradleProjectPath = androidGradleFacet.getProperties().GRADLE_PROJECT_PATH;
- if (gradleProjectPath == null) {
- // Gradle project path is never, ever null. If the path is empty, it shows as ":". We had reports of this happening. It is likely that
- // users manually added the Android-Gradle facet to a project. After all it is likely not to be a Gradle module. Better quit and not
- // build the module.
- String format = "Module '%1$s' does not have a Gradle path. It is likely that this module was manually added by the user.";
- String msg = String.format(format, module.getName());
- LOG.warn(msg);
- return;
- }
- String assembleTaskName = null;
JpsAndroidModuleExtensionImpl androidFacet = (JpsAndroidModuleExtensionImpl)AndroidJpsUtil.getExtension(module);
- if (androidFacet != null) {
- JpsAndroidModuleProperties properties = androidFacet.getProperties();
- BuildMode buildMode = executionSettings.getBuildMode();
- switch (buildMode) {
- case SOURCE_GEN:
- assembleTaskName = properties.SOURCE_GEN_TASK_NAME;
- break;
- case COMPILE_JAVA:
- assembleTaskName = properties.COMPILE_JAVA_TASK_NAME;
- break;
- default:
- assembleTaskName = properties.ASSEMBLE_TASK_NAME;
- }
- }
- if (Strings.isNullOrEmpty(assembleTaskName)) {
- assembleTaskName = DEFAULT_ASSEMBLE_TASK_NAME;
- }
- assert assembleTaskName != null;
- tasks.add(createBuildTask(gradleProjectPath, assembleTaskName));
-
- if (buildTests && androidFacet != null) {
- JpsAndroidModuleProperties properties = androidFacet.getProperties();
- String assembleTestTaskName = properties.ASSEMBLE_TEST_TASK_NAME;
- if (!Strings.isNullOrEmpty(assembleTestTaskName)) {
- tasks.add(createBuildTask(gradleProjectPath, assembleTestTaskName));
- }
- }
- }
+ JpsAndroidModuleProperties properties = androidFacet != null ? androidFacet.getProperties() : null;
- @NotNull
- private static String createBuildTask(@NotNull String gradleProjectPath, @NotNull String taskName) {
- return gradleProjectPath + SdkConstants.GRADLE_PATH_SEPARATOR + taskName;
+ GradleBuilds.findAndAddBuildTask(module.getName(), executionSettings.getBuildMode(), gradleProjectPath, properties, tasks, buildTests);
}
private static void ensureTempDirExists() {
@@ -247,8 +221,8 @@ public class AndroidGradleTargetBuilder extends TargetBuilder<AndroidGradleBuild
GradleConnector connector = getGradleConnector(executionSettings);
ProjectConnection connection = connector.connect();
- ByteArrayOutputStream stdout = new ByteArrayOutputStream();
- ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+ ByteArrayOutputStream stdout = new ByteArrayOutputStream(BUFFER_SIZE);
+ ByteArrayOutputStream stderr = new ByteArrayOutputStream(BUFFER_SIZE);
try {
BuildLauncher launcher = connection.newBuild();
@@ -348,7 +322,7 @@ public class AndroidGradleTargetBuilder extends TargetBuilder<AndroidGradleBuild
}
else {
// Since we have nothing else to show, just print the stack trace of the caught exception.
- ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
try {
//noinspection IOResourceOpenedButNotSafelyClosed
e.printStackTrace(new PrintStream(out));
diff --git a/android-gradle-jps/src/com/android/tools/idea/jps/builder/BuilderExecutionSettings.java b/android-gradle-jps/src/com/android/tools/idea/jps/builder/BuilderExecutionSettings.java
index 68e2bf0a168..db6cb6e5787 100644
--- a/android-gradle-jps/src/com/android/tools/idea/jps/builder/BuilderExecutionSettings.java
+++ b/android-gradle-jps/src/com/android/tools/idea/jps/builder/BuilderExecutionSettings.java
@@ -20,6 +20,7 @@ import com.android.tools.idea.gradle.util.AndroidGradleSettings;
import com.android.tools.idea.gradle.util.BuildMode;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.intellij.util.SystemProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,6 +28,7 @@ import org.jetbrains.jps.api.GlobalOptions;
import java.io.File;
import java.util.List;
+import java.util.Set;
/**
* Settings used to build a Gradle project.
@@ -34,7 +36,10 @@ import java.util.List;
class BuilderExecutionSettings {
private final boolean myEmbeddedGradleDaemonEnabled;
private final int myGradleDaemonMaxIdleTimeInMs;
+
@NotNull private final List<String> myGradleDaemonJvmOptions = Lists.newArrayList();
+ @NotNull private final Set<String> myModulesToBuildNames = Sets.newHashSet();
+
@Nullable private final File myGradleHomeDir;
@Nullable private final File myGradleServiceDir;
@Nullable private final File myJavaHomeDir;
@@ -54,36 +59,11 @@ class BuilderExecutionSettings {
myBuildMode = Strings.isNullOrEmpty(buildActionName) ? BuildMode.DEFAULT_BUILD_MODE : BuildMode.valueOf(buildActionName);
myVerboseLoggingEnabled = SystemProperties.getBooleanProperty(BuildProcessJvmArgs.USE_GRADLE_VERBOSE_LOGGING, false);
myParallelBuild = SystemProperties.getBooleanProperty(GlobalOptions.COMPILE_PARALLEL_OPTION, false);
+ populateModulesToBuild();
populateGradleDaemonJvmOptions();
populateHttpProxyJvmOptions();
}
- private void populateGradleDaemonJvmOptions() {
- int vmOptionCount = SystemProperties.getIntProperty(BuildProcessJvmArgs.GRADLE_DAEMON_JVM_OPTION_COUNT, 0);
- for (int i = 0; i < vmOptionCount; i++) {
- String jvmOption = System.getProperty(BuildProcessJvmArgs.GRADLE_DAEMON_JVM_OPTION_PREFIX + i);
- if (!Strings.isNullOrEmpty(jvmOption)) {
- myGradleDaemonJvmOptions.add(jvmOption);
- }
- }
- }
-
- private void populateHttpProxyJvmOptions() {
- int vmOptionCount = SystemProperties.getIntProperty(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_COUNT, 0);
- for (int i = 0; i < vmOptionCount; i++) {
- String jvmOption = System.getProperty(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_PREFIX + i);
- if (!Strings.isNullOrEmpty(jvmOption)) {
- int indexOfSeparator = jvmOption.indexOf(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_SEPARATOR);
- if (indexOfSeparator < 0 || indexOfSeparator >= jvmOption.length() -1) {
- continue;
- }
- String name = jvmOption.substring(0, indexOfSeparator);
- String value = jvmOption.substring(indexOfSeparator + 1);
- myGradleDaemonJvmOptions.add(AndroidGradleSettings.createJvmArg(name, value));
- }
- }
- }
-
@Nullable
private static File findDir(@NotNull String jvmArgName, @NotNull String dirType) {
File gradleServiceDir = createFile(jvmArgName);
@@ -118,6 +98,42 @@ class BuilderExecutionSettings {
return path != null && !path.isEmpty() ? new File(path) : null;
}
+ private void populateModulesToBuild() {
+ int moduleCount = SystemProperties.getIntProperty(BuildProcessJvmArgs.MODULES_TO_BUILD_PROPERTY_COUNT, 0);
+ for (int i = 0; i < moduleCount; i++) {
+ String module = System.getProperty(BuildProcessJvmArgs.MODULES_TO_BUILD_PROPERTY_PREFIX + i);
+ if (!Strings.isNullOrEmpty(module)) {
+ myModulesToBuildNames.add(module);
+ }
+ }
+ }
+
+ private void populateGradleDaemonJvmOptions() {
+ int vmOptionCount = SystemProperties.getIntProperty(BuildProcessJvmArgs.GRADLE_DAEMON_JVM_OPTION_COUNT, 0);
+ for (int i = 0; i < vmOptionCount; i++) {
+ String jvmOption = System.getProperty(BuildProcessJvmArgs.GRADLE_DAEMON_JVM_OPTION_PREFIX + i);
+ if (!Strings.isNullOrEmpty(jvmOption)) {
+ myGradleDaemonJvmOptions.add(jvmOption);
+ }
+ }
+ }
+
+ private void populateHttpProxyJvmOptions() {
+ int vmOptionCount = SystemProperties.getIntProperty(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_COUNT, 0);
+ for (int i = 0; i < vmOptionCount; i++) {
+ String jvmOption = System.getProperty(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_PREFIX + i);
+ if (!Strings.isNullOrEmpty(jvmOption)) {
+ int indexOfSeparator = jvmOption.indexOf(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_SEPARATOR);
+ if (indexOfSeparator < 0 || indexOfSeparator >= jvmOption.length() -1) {
+ continue;
+ }
+ String name = jvmOption.substring(0, indexOfSeparator);
+ String value = jvmOption.substring(indexOfSeparator + 1);
+ myGradleDaemonJvmOptions.add(AndroidGradleSettings.createJvmArg(name, value));
+ }
+ }
+ }
+
boolean isEmbeddedGradleDaemonEnabled() {
return myEmbeddedGradleDaemonEnabled;
}
@@ -164,6 +180,11 @@ class BuilderExecutionSettings {
return myParallelBuild;
}
+ @NotNull
+ Set<String> getModulesToBuildNames() {
+ return myModulesToBuildNames;
+ }
+
@Override
public String toString() {
return "BuilderExecutionSettings[" +
@@ -177,6 +198,7 @@ class BuilderExecutionSettings {
", parallelBuild=" + myParallelBuild +
", projectDir=" + myProjectDir +
", verboseLoggingEnabled=" + myVerboseLoggingEnabled +
+ ", modulesToBuildNames=" + myModulesToBuildNames +
']';
}
}
diff --git a/android-gradle-jps/testSrc/com/android/tools/idea/jps/builder/BuilderExecutionSettingsTest.java b/android-gradle-jps/testSrc/com/android/tools/idea/jps/builder/BuilderExecutionSettingsTest.java
index 9f9757876f9..e9e24e3d3d8 100644
--- a/android-gradle-jps/testSrc/com/android/tools/idea/jps/builder/BuilderExecutionSettingsTest.java
+++ b/android-gradle-jps/testSrc/com/android/tools/idea/jps/builder/BuilderExecutionSettingsTest.java
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
+import java.util.Set;
/**
* Tests for {@link BuilderExecutionSettings}.
@@ -62,6 +63,7 @@ public class BuilderExecutionSettingsTest extends TestCase {
private static void delete(@Nullable File dir) {
if (dir != null) {
+ //noinspection ResultOfMethodCallIgnored
dir.delete();
}
}
@@ -104,6 +106,10 @@ public class BuilderExecutionSettingsTest extends TestCase {
System.setProperty(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_PREFIX + 2, "randomText");
System.setProperty(BuildProcessJvmArgs.HTTP_PROXY_PROPERTY_PREFIX + 3, "randomText:");
+ System.setProperty(BuildProcessJvmArgs.MODULES_TO_BUILD_PROPERTY_COUNT, "2");
+ System.setProperty(BuildProcessJvmArgs.MODULES_TO_BUILD_PROPERTY_PREFIX + 0, "main");
+ System.setProperty(BuildProcessJvmArgs.MODULES_TO_BUILD_PROPERTY_PREFIX + 1, "lib");
+
BuilderExecutionSettings settings = new BuilderExecutionSettings();
assertEquals(55, settings.getGradleDaemonMaxIdleTimeInMs());
assertEquals(gradleHomeDirPath, pathOf(settings.getGradleHomeDir()));
@@ -119,6 +125,11 @@ public class BuilderExecutionSettingsTest extends TestCase {
assertEquals(maxPermSize, vmOptions.get(1));
assertEquals("-Dhttp.proxyHost=" + httpProxyHost, vmOptions.get(2));
assertEquals("-Dhttp.proxyPort=" + httpProxyPort, vmOptions.get(3));
+
+ Set<String> modulesToBuildNames = settings.getModulesToBuildNames();
+ assertEquals(2, modulesToBuildNames.size());
+ assertTrue(modulesToBuildNames.contains("main"));
+ assertTrue(modulesToBuildNames.contains("lib"));
}
private static String pathOf(@Nullable File dir) {