aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2013-05-20 18:40:03 -0700
committerXavier Ducrohet <xav@android.com>2013-05-20 18:52:24 -0700
commitc5968ffb545c4d499388f249191372db521f9156 (patch)
tree0cdc644a1af331e30bda391999e41b37f287447f /eclipse
parentb3acb65d7f58ae2b5a1b8444341e68bbd62c6b9c (diff)
downloadsdk-c5968ffb545c4d499388f249191372db521f9156.zip
sdk-c5968ffb545c4d499388f249191372db521f9156.tar.gz
sdk-c5968ffb545c4d499388f249191372db521f9156.tar.bz2
Misc fix to the Gradle export.
Change-Id: I713b05e2ef049cf75a3a78c364f443a8e4fff33d
Diffstat (limited to 'eclipse')
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java348
1 files changed, 176 insertions, 172 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java
index 918233b..b4893e8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java
@@ -16,8 +16,25 @@
package com.android.ide.eclipse.adt.internal.wizards.exportgradle;
+import com.android.SdkConstants;
+import com.android.ide.eclipse.adt.AdtConstants;
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
+import com.android.ide.eclipse.adt.internal.sdk.ProjectState.LibraryState;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
+import com.android.ide.eclipse.adt.io.IFolderWrapper;
+import com.android.io.IAbstractFile;
+import com.android.sdklib.io.FileOp;
+import com.android.utils.Pair;
+import com.android.xml.AndroidManifest;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@@ -33,29 +50,16 @@ import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
-import com.android.SdkConstants;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
-import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.ide.eclipse.adt.io.IFolderWrapper;
-import com.android.io.IAbstractFile;
-import com.android.sdklib.io.FileOp;
-import com.android.utils.Pair;
-import com.android.xml.AndroidManifest;
-import com.google.common.base.Joiner;
-
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -64,12 +68,8 @@ import java.util.regex.Pattern;
* Based on {@link org.eclipse.ant.internal.ui.datatransfer.BuildFileCreator}
*/
public class BuildFileCreator {
- //Finds include ':module_name_1', ':module_name_2',... statements in settings.gradle files
- private static final Pattern INCLUDE_PATTERN =
- Pattern.compile("include +(':[^']+', *)*':[^']+'"); //$NON-NLS-1$
private static final String BUILD_FILE = "build.gradle"; //$NON-NLS-1$
private static final String SETTINGS_FILE = "settings.gradle"; //$NON-NLS-1$
- private static final String ANDROID_SUPPORT_JAR = "android-support-v4.jar"; //$NON-NLS-1$
private static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$
private static final String GRADLE_WRAPPER_LOCATION =
"tools/templates/gradle/wrapper"; //$NON-NLS-1$
@@ -95,9 +95,7 @@ public class BuildFileCreator {
private IJavaProject project;
private String projectName;
private String projectRoot;
- private Set<String> settingsFileEntries = new HashSet<String>();
- private boolean needsSettingsFile = false;
- private String commonRoot = null;
+ private final IPath commonRoot;
/**
* Create buildfile for the given projects.
@@ -123,34 +121,74 @@ public class BuildFileCreator {
hasGradleWrapper = false;
}
}
+
+ Set<IJavaProject> fullProjectSet = Sets.newHashSet();
+
+ // build a list of all projects that must be included. This is in case
+ // some dependencies have not been included in the selected projects. We also include
+ // parent projects so that the full multi-project setup is correct.
+ // Note that if two projects are selected that are not related, both will be added
+ // in the same multi-project anyway.
+ for (IJavaProject javaProject : projects) {
+ fullProjectSet.add(javaProject);
+ ProjectState projectState = Sdk.getProjectState(javaProject.getProject());
+
+ // add dependencies
+ List<IProject> dependencies = projectState.getFullLibraryProjects();
+ for (IProject dependency : dependencies) {
+ fullProjectSet.add(JavaCore.create(dependency));
+ }
+
+ Collection<ProjectState> parents = projectState.getFullParentProjects();
+ for (ProjectState parent : parents) {
+ fullProjectSet.add(JavaCore.create(parent.getProject()));
+ }
+ }
+
// determine files to create/change
List<IFile> files = new ArrayList<IFile>();
- for (IJavaProject project : projects) {
+
+ // add the build.gradle file for all projects.
+ for (IJavaProject project : fullProjectSet) {
// build.gradle file
IFile file = project.getProject().getFile(BuildFileCreator.BUILD_FILE);
files.add(file);
}
- // Locate the settings.gradle file and add it to the changed files list
- for (IJavaProject project : projects) {
- BuildFileCreator instance = new BuildFileCreator(project, shell);
- instance.determineCommonRoot();
- IPath path = Path.fromOSString(instance.getGradleSettingsFile().getAbsolutePath());
- IFile file = project.getProject().getWorkspace().getRoot().getFile(path);
- if (file != null) {
- files.add(file);
+ // get the commonRoot for all projects. If only one project, this returns the path
+ // of the project.
+ IPath commonRoot = determineCommonRoot(fullProjectSet);
+
+ IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+ IPath workspaceLocation = workspaceRoot.getLocation();
+
+ IPath relativePath = commonRoot.makeRelativeTo(workspaceLocation);
+ boolean rootInWorkspace = !relativePath.equals(commonRoot);
+
+ File settingsFile = new File(commonRoot.toFile(), SETTINGS_FILE);
+
+ // more than one project -> generate settings.gradle
+ if (fullProjectSet.size() > 1 && rootInWorkspace) {
+ // Locate the settings.gradle file and add it to the changed files list
+ IPath settingsGradle = Path.fromOSString(settingsFile.getAbsolutePath());
+
+ // different path, means commonRoot is inside the workspace, which means we have
+ // to add settings.gradle and wrapper files to the list of files to add.
+ IFile iFile = workspaceRoot.getFile(settingsGradle);
+ if (iFile != null) {
+ files.add(iFile);
}
- // Gradle wrapper files
- if (hasGradleWrapper) {
- // See if there already wrapper files there and only mark nonexistent ones for
- // creation.
- for (File wrapperFile : getGradleWrapperFiles(
- new File(project.getResource().getLocation().toString()))) {
- if (!wrapperFile.exists()) {
- path = Path.fromOSString(wrapperFile.getAbsolutePath());
- file = project.getProject().getWorkspace().getRoot().getFile(path);
- files.add(file);
- }
+ }
+
+ // Gradle wrapper files
+ if (hasGradleWrapper && rootInWorkspace) {
+ // See if there already wrapper files there and only mark nonexistent ones for
+ // creation.
+ for (File wrapperFile : getGradleWrapperFiles(commonRoot.toFile())) {
+ if (!wrapperFile.exists()) {
+ IPath path = Path.fromOSString(wrapperFile.getAbsolutePath());
+ IFile file = workspaceRoot.getFile(path);
+ files.add(file);
}
}
}
@@ -161,7 +199,8 @@ public class BuildFileCreator {
// Now iterate over all the projects and generate the build files.
localmonitor = SubMonitor.convert(pm, ExportMessages.PageTitle,
confirmedFiles.size());
- for (IJavaProject currentProject : projects) {
+ List<String> projectSettingsPath = Lists.newArrayList();
+ for (IJavaProject currentProject : fullProjectSet) {
IFile file = currentProject.getProject().getFile(BuildFileCreator.BUILD_FILE);
if (!confirmedFiles.contains(file)) {
continue;
@@ -171,22 +210,15 @@ public class BuildFileCreator {
currentProject.getProject().getName()));
ProjectState projectState = Sdk.getProjectState(currentProject.getProject());
- BuildFileCreator instance = new BuildFileCreator(currentProject, shell);
- instance.determineCommonRoot();
+ BuildFileCreator instance = new BuildFileCreator(currentProject, commonRoot, shell);
if (projectState != null) {
// This is an Android project
instance.appendHeader(projectState.isLibrary());
instance.appendDependencies();
instance.startAndroidTask(projectState);
- instance.appendDefaultConfig();
+ //instance.appendDefaultConfig();
instance.createAndroidSourceSets();
instance.finishAndroidTask();
- if (instance.needsSettingsFile) {
- instance.mergeGradleSettingsFile();
- if (hasGradleWrapper) {
- copyGradleWrapper(gradleLocation, new File(instance.commonRoot));
- }
- }
} else {
// This is a plain Java project
instance.appendJavaHeader();
@@ -207,7 +239,23 @@ public class BuildFileCreator {
}
localmonitor.worked(1);
res.add(instance.projectName);
+
+ // get the project path to add it to the settings.gradle.
+ projectSettingsPath.add(instance.getRelativeGradleProjectPath());
+ }
+
+ // write the settings file.
+ if (fullProjectSet.size() > 1) {
+ writeGradleSettingsFile(settingsFile, projectSettingsPath);
+ writeRootBuildGradle(new File(commonRoot.toFile(), BUILD_FILE));
+ }
+
+ // finally write the wrapper
+ // TODO check we can based on where it is
+ if (hasGradleWrapper) {
+ copyGradleWrapper(gradleLocation, commonRoot.toFile());
}
+
} finally {
if (localmonitor != null && !localmonitor.isCanceled()) {
localmonitor.done();
@@ -223,11 +271,12 @@ public class BuildFileCreator {
* @param project create buildfile for this project
* @param shell parent instance for dialogs
*/
- private BuildFileCreator(IJavaProject project, Shell shell) {
+ private BuildFileCreator(IJavaProject project, IPath commonRoot, Shell shell) {
this.project = project;
this.projectName = project.getProject().getName();
this.buildfile = new StringBuilder();
this.projectRoot = project.getResource().getLocation().toString();
+ this.commonRoot = commonRoot;
}
/**
@@ -262,22 +311,19 @@ public class BuildFileCreator {
/**
* Finds the common parent directory shared by this project and all its dependencies.
+ * If there's only one project, returns the single project's folder.
*/
- private void determineCommonRoot() {
- String currentProjectRoot = project.getResource().getLocation().toString();
-
- if (commonRoot == null) {
- commonRoot = new Path(currentProjectRoot).removeLastSegments(1).toString();
- }
-
- for (IClasspathEntry entry : project.readRawClasspath()) {
- if (entry.getEntryKind() != IClasspathEntry.CPE_PROJECT) {
- continue;
+ private static IPath determineCommonRoot(Collection<IJavaProject> projects) {
+ IPath commonRoot = null;
+ for (IJavaProject javaProject : projects) {
+ if (commonRoot == null) {
+ commonRoot = javaProject.getProject().getLocation();
+ } else {
+ commonRoot = findCommonRoot(commonRoot, javaProject.getProject().getLocation());
}
- IJavaProject referencedProject = getJavaProjectByName(entry.getPath().toString());
- String referencedProjectRoot = referencedProject.getResource().getLocation().toString();
- commonRoot = findCommonRoot(commonRoot, referencedProjectRoot);
}
+
+ return commonRoot;
}
/**
@@ -310,105 +356,79 @@ public class BuildFileCreator {
}
buildfile.append("dependencies {\n"); //$NON-NLS-1$
- // We'll have to do a preliminary pass and pull out any projects that have or are
- // dependencies. Then we need to identify the common parent of all of those projects,
- // and merge all those projects into a settings.gradle file there. Then we need to build
- // relative gradle paths to each library and populate those into the compile
- // project(':a:b:library') entries output below.
+ // first the local jars.
+ buildfile.append(" compile fileTree(dir: 'libs', include: '*.jar')\n");
+
+ // then the project dependencies.
+ // First the Android libraries.
+ ProjectState state = Sdk.getProjectState(project.getProject());
- String currentProjectRoot = project.getResource().getLocation().toString();
- String path = getRelativeGradleProjectPath(currentProjectRoot, commonRoot);
- settingsFileEntries.add("'" + path + "'"); //$NON-NLS-1$
+ for (LibraryState libState : state.getLibraries()) {
+ String path = getRelativeGradleProjectPath(
+ libState.getProjectState().getProject().getLocation(), commonRoot);
+ buildfile.append(" compile project('" + path + "')\n"); //$NON-NLS-1$
+ }
+
+ // Next, the other non-Android projects.
for (IClasspathEntry entry : project.readRawClasspath()) {
- String entryPath = entry.getPath().makeAbsolute().toString();
- switch(entry.getEntryKind()) {
- case IClasspathEntry.CPE_PROJECT:
- IJavaProject cpProject = getJavaProjectByName(entry.getPath().toString());
- String cpProjectRoot = cpProject.getResource().getLocation().toString();
- path = getRelativeGradleProjectPath(cpProjectRoot, commonRoot);
- settingsFileEntries.add("'" + path + "'"); //$NON-NLS-1$
- needsSettingsFile = true;
+ if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
+ IProject cpProject = getNonAndroidProjectByName(entry.getPath().toString());
+ if (cpProject != null) {
+ String path = getRelativeGradleProjectPath(
+ cpProject.getLocation(), commonRoot);
+
buildfile.append(" compile project('" + path + "')\n"); //$NON-NLS-1$
- break;
- case IClasspathEntry.CPE_LIBRARY:
- if (entry.getPath().lastSegment().equals(ANDROID_SUPPORT_JAR)) {
- // This jar gets added automatically by the Android Gradle plugin
- continue;
- }
- path = getRelativePath(entryPath, projectRoot);
- buildfile.append(" compile files('" + path + "')\n"); //$NON-NLS-1$
- break;
- default:
- break;
+ }
}
}
+
buildfile.append("}\n"); //$NON-NLS-1$
buildfile.append("\n"); //$NON-NLS-1$
}
/**
- * Given two filesystem paths, finds the parent directory of both of them.
+ * Given two IPaths, finds the parent directory of both of them.
*/
- private String findCommonRoot(String path1, String path2) {
- IPath f1 = new Path(path1);
- IPath f2 = new Path(path2);
+ private static IPath findCommonRoot(IPath path1, IPath path2) {
+ // TODO: detect paths on different disk drive on Windows!
IPath result = (IPath) Path.ROOT.clone();
- for (int i = 0; i < Math.min(f1.segmentCount(), f2.segmentCount()); i++) {
- if (f1.segment(i).equals(f2.segment(i))) {
- result = result.append(Path.SEPARATOR + f1.segment(i));
+ final int count = Math.min(path1.segmentCount(), path2.segmentCount());
+ for (int i = 0; i < count; i++) {
+ if (path1.segment(i).equals(path2.segment(i))) {
+ result = result.append(Path.SEPARATOR + path2.segment(i));
}
}
- return result.toString();
+ return result;
}
- /**
- * Converts the given path to be relative to the given root path, and converts it to
- * Gradle project notation, such as is used in the settings.gradle file.
- */
- private String getRelativeGradleProjectPath(String path, String root) {
- String relativePath = getRelativePath(path, root);
- return ":" + relativePath.replaceAll("\\" + Path.SEPARATOR, ":"); //$NON-NLS-1$
+ private String getRelativeGradleProjectPath() {
+ return getRelativeGradleProjectPath(project.getProject().getLocation(), commonRoot);
}
/**
- * Returns a path which is equivalent to the given location relative to the
- * specified base path.
+ * Converts the given path to be relative to the given root path, and converts it to
+ * Gradle project notation, such as is used in the settings.gradle file.
*/
- private static String getRelativePath(String otherLocation, String basePath) {
-
- IPath location = new Path(otherLocation);
- IPath base = new Path(basePath);
- if ((location.getDevice() != null && !location.getDevice()
- .equalsIgnoreCase(base.getDevice())) || !location.isAbsolute()) {
- return otherLocation;
- }
- int baseCount = base.segmentCount();
- int count = base.matchingFirstSegments(location);
- String temp = ""; //$NON-NLS-1$
- for (int j = 0; j < baseCount - count; j++) {
- temp += "../"; //$NON-NLS-1$
- }
- String relative = new Path(temp).append(
- location.removeFirstSegments(count)).toString();
- if (relative.length() == 0) {
- relative = "."; //$NON-NLS-1$
- }
-
- return relative;
+ private String getRelativeGradleProjectPath(IPath path, IPath root) {
+ IPath relativePath = path.makeRelativeTo(root);
+ String relativeString = relativePath.toOSString();
+ return ":" + relativeString.replaceAll(Pattern.quote(File.separator), ":"); //$NON-NLS-1$
}
/**
* Finds the workspace project with the given name
*/
- private static IJavaProject getJavaProjectByName(String name) {
+ private static IProject getNonAndroidProjectByName(String name) {
try {
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
- if (project.exists()) {
- return JavaCore.create(project);
+ if (project.exists() && !project.hasNature(AdtConstants.NATURE_DEFAULT)) {
+ return project;
}
} catch (IllegalArgumentException iae) {
+ } catch (CoreException e) {
}
+
return null;
}
@@ -417,9 +437,10 @@ public class BuildFileCreator {
*/
private void startAndroidTask(ProjectState projectState) {
int buildApi = projectState.getTarget().getVersion().getApiLevel();
+ String toolsVersion = projectState.getTarget().getBuildToolInfo().getRevision().toString();
buildfile.append("android {\n"); //$NON-NLS-1$
buildfile.append(" compileSdkVersion " + buildApi + "\n"); //$NON-NLS-1$
- buildfile.append(" buildToolsVersion \"" + buildApi + "\"\n"); //$NON-NLS-1$
+ buildfile.append(" buildToolsVersion \"" + toolsVersion + "\"\n"); //$NON-NLS-1$
buildfile.append("\n"); //$NON-NLS-1$
}
@@ -457,17 +478,15 @@ public class BuildFileCreator {
srcDirs.add("'" + path.toOSString() + "'"); //$NON-NLS-1$
}
+ String srcPaths = Joiner.on(",").join(srcDirs);
+
buildfile.append(" sourceSets {\n"); //$NON-NLS-1$
buildfile.append(" main {\n"); //$NON-NLS-1$
- buildfile.append(" manifest.srcFile '"
- + getRelativePath(mManifestFile.getOsLocation(), projectRoot)
- + "'\n"); //$NON-NLS-1$
- buildfile.append(" java.srcDirs = ["
- + Joiner.on(",").join(srcDirs)
- + "]\n"); //$NON-NLS-1$
- buildfile.append(" resources.srcDirs = ['src']\n"); //$NON-NLS-1$
- buildfile.append(" aidl.srcDirs = ['src']\n"); //$NON-NLS-1$
- buildfile.append(" renderscript.srcDirs = ['src']\n"); //$NON-NLS-1$
+ buildfile.append(" manifest.srcFile '" + SdkConstants.FN_ANDROID_MANIFEST_XML + "'\n"); //$NON-NLS-1$
+ buildfile.append(" java.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ buildfile.append(" resources.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ buildfile.append(" aidl.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ buildfile.append(" renderscript.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
buildfile.append(" res.srcDirs = ['res']\n"); //$NON-NLS-1$
buildfile.append(" assets.srcDirs = ['assets']\n"); //$NON-NLS-1$
buildfile.append(" }\n"); //$NON-NLS-1$
@@ -502,10 +521,14 @@ public class BuildFileCreator {
IPath path = entry.getPath().removeFirstSegments(1);
dirs.add("'" + path.toOSString() + "'"); //$NON-NLS-1$
}
+
+ String srcPaths = Joiner.on(",").join(dirs);
+
buildfile.append("sourceSets {\n"); //$NON-NLS-1$
- buildfile.append(" main.java.srcDirs = ["); //$NON-NLS-1$
- buildfile.append(Joiner.on(",").join(dirs)); //$NON-NLS-1$
- buildfile.append("]\n"); //$NON-NLS-1$
+ buildfile.append(" main.java.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ buildfile.append(" main.resources.srcDirs = [" + srcPaths + "]\n"); //$NON-NLS-1$
+ buildfile.append(" test.java.srcDirs = ['tests/java']\n"); //$NON-NLS-1$
+ buildfile.append(" test.resources.srcDirs = ['tests/resources']\n"); //$NON-NLS-1$
buildfile.append("}\n"); //$NON-NLS-1$
}
@@ -513,37 +536,18 @@ public class BuildFileCreator {
* Merges the new subproject dependencies into the settings.gradle file if it already exists,
* and creates one if it does not.
*/
- private void mergeGradleSettingsFile() {
- File file = getGradleSettingsFile();
+ private static void writeGradleSettingsFile(File settingsFile, List<String> projectPaths) {
StringBuilder contents = new StringBuilder();
- if (file.exists()) {
- contents.append(AdtPlugin.readFile(file));
-
- for (String entry : settingsFileEntries) {
- if (contents.indexOf(entry) != -1) {
- continue;
- }
- Matcher matcher = INCLUDE_PATTERN.matcher(contents);
- if (matcher.find()) {
- contents.insert(matcher.end(), ", " + entry); //$NON-NLS-1$
- } else {
- contents.insert(0, "include " + entry + "\n"); //$NON-NLS-1$
- }
- }
- } else {
- contents.append("include ");
- contents.append(Joiner.on(",").join(settingsFileEntries));
- contents.append("\n"); //$NON-NLS-1$
+ for (String path : projectPaths) {
+ contents.append("include '").append(path).append("'\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
- AdtPlugin.writeFile(file, contents.toString());
+ AdtPlugin.writeFile(settingsFile, contents.toString());
}
- /**
- * Returns the settings.gradle file (which may not exist yet).
- */
- private File getGradleSettingsFile() {
- return new File(commonRoot, SETTINGS_FILE);
+ private static void writeRootBuildGradle(File buildFile) {
+ AdtPlugin.writeFile(buildFile,
+ "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n");
}
/**