diff options
author | Alex Ruiz <alruiz@google.com> | 2013-10-31 21:10:20 -0700 |
---|---|---|
committer | Alex Ruiz <alruiz@google.com> | 2013-11-03 15:18:22 -0800 |
commit | 056d3d90715dedea0c7bd00eb098cf3e22c43e3e (patch) | |
tree | d849f84f61ec4b4569a7524731c7871358dbdeb0 /android-gradle-jps | |
parent | 87c21cd3efa570921995cbaa2d59df501ccbb562 (diff) | |
download | idea-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')
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) { |