Merge remote branch 'origin/master'

This commit is contained in:
irengrig
2012-02-09 20:06:06 +04:00
25 changed files with 844 additions and 120 deletions
+1
View File
@@ -11,6 +11,7 @@
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/android/android.iml" filepath="$PROJECT_DIR$/plugins/android/android.iml" group="plugins/Android" />
<module fileurl="file://$PROJECT_DIR$/plugins/android/rt/android-rt.iml" filepath="$PROJECT_DIR$/plugins/android/rt/android-rt.iml" group="plugins/Android" />
<module fileurl="file://$PROJECT_DIR$/plugins/android/jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/android/jps-plugin/android-jps-plugin.iml" group="plugins/Android"/>
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" />
+4
View File
@@ -366,6 +366,10 @@ public def layoutCommunityPlugins(String home) {
}
jar("android_rt.jar") {module("android-rt")}
dir("jps") {
jar("android-jps-plugin.jar") { module("android-jps-plugin") }
}
}
}
}
+5 -15
View File
@@ -1,21 +1,11 @@
package org.jetbrains.jps
/**
* @author nik
* @author Eugene.Kudelevsky
*/
class JavaSdk extends Sdk {
String jdkPath
public interface JavaSdk {
def JavaSdk(Project project, String name, String jdkPath, Closure initializer) {
super(project, name, initializer)
this.jdkPath = jdkPath
}
String getJavacExecutable();
String getJavacExecutable() {
return jdkPath + File.separator + "bin" + File.separator + "javac";
}
String getJavaExecutable() {
return jdkPath + File.separator + "bin" + File.separator + "java";
}
}
String getJavaExecutable();
}
@@ -0,0 +1,21 @@
package org.jetbrains.jps
/**
* @author nik
*/
class JavaSdkImpl extends Sdk implements JavaSdk {
String jdkPath
def JavaSdkImpl(Project project, String name, String jdkPath, Closure initializer) {
super(project, name, initializer)
this.jdkPath = jdkPath
}
String getJavacExecutable() {
return jdkPath + File.separator + "bin" + File.separator + "javac";
}
String getJavaExecutable() {
return jdkPath + File.separator + "bin" + File.separator + "java";
}
}
@@ -43,7 +43,7 @@ class Project {
}
def JavaSdk createJavaSdk(String name, String path, Closure initializer) {
def sdk = new JavaSdk(this, name, path, initializer)
def sdk = new JavaSdkImpl(this, name, path, initializer)
sdks[name] = sdk
return sdk
}
@@ -1,8 +1,8 @@
package org.jetbrains.jps.idea
import org.jetbrains.jps.JavaSdkImpl
import org.jetbrains.jps.Project
import org.jetbrains.jps.Sdk
import org.jetbrains.jps.JavaSdk
/**
* @author nik
@@ -14,6 +14,6 @@ class JavaSdkType extends SdkTypeService {
@Override
Sdk createSdk(Project project, String name, String homePath, Node additionalData) {
return new JavaSdk(project, name, homePath, {})
return new JavaSdkImpl(project, name, homePath, {})
}
}
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="module" module-name="jps-model" />
<orderEntry type="module" module-name="android-rt" />
<orderEntry type="module" module-name="jps-builders" />
<orderEntry type="module" module-name="util" />
</component>
</module>
@@ -0,0 +1 @@
org.jetbrains.jps.android.AndroidFacetType
@@ -0,0 +1 @@
org.jetbrains.jps.android.AndroidSdkType
@@ -0,0 +1 @@
org.jetbrains.jps.android.AndroidBuilderService
@@ -0,0 +1,20 @@
package org.jetbrains.jps.android;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.incremental.BuilderService;
import org.jetbrains.jps.incremental.ModuleLevelBuilder;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidBuilderService extends BuilderService {
@NotNull
@Override
public List<? extends ModuleLevelBuilder> createModuleLevelBuilders(ExecutorService executorService) {
return Arrays.asList(new AndroidSourceGeneratingBuilder());
}
}
@@ -0,0 +1,46 @@
package org.jetbrains.jps.android
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jps.Module
import org.jetbrains.jps.idea.Facet
/**
* @author nik
*/
class AndroidFacet extends Facet {
final Module module
final String resFolderRelativePath
AndroidFacet(Module module, String name, String resFolderRelativePath) {
this.module = module
this.name = name;
this.resFolderRelativePath = resFolderRelativePath
}
File getResourceDir() {
return findFileByRelativeModulePath(resFolderRelativePath, true)
}
private File findFileByRelativeModulePath(String relativePath, boolean lookInContentRoot) {
if (module.basePath != null) {
def absPath = FileUtil.toSystemIndependentName(module.basePath + relativePath)
def f = new File(absPath)
if (f.exists()) {
return f
}
}
if (lookInContentRoot) {
module.contentRoots.each {
def absPath = FileUtil.toSystemIndependentName(contentRoot + relativePath)
def f = new File(absPath)
if (f.exists()) {
return f
}
}
}
return null;
}
}
@@ -0,0 +1,22 @@
package org.jetbrains.jps.android
import org.jetbrains.jps.MacroExpander
import org.jetbrains.jps.Module
import org.jetbrains.jps.idea.Facet
import org.jetbrains.jps.idea.FacetTypeService
/**
* @author Eugene.Kudelevsky
*/
class AndroidFacetType extends FacetTypeService {
public static final String ID = "android"
AndroidFacetType() {
super(ID)
}
@Override
Facet createFacet(Module module, String name, Node facetConfiguration, MacroExpander macroExpander) {
return new AndroidFacet(module, name, "");
}
}
@@ -0,0 +1,34 @@
package org.jetbrains.jps.android
import org.jetbrains.jps.JavaSdk
import org.jetbrains.jps.Project
import org.jetbrains.jps.Sdk
import org.jetbrains.jps.JavaSdkImpl
/**
* @author Eugene.Kudelevsky
*/
class AndroidSdk extends Sdk implements JavaSdk {
final String sdkPath;
final String buildTargetHashString;
final String javaSdkName;
AndroidSdk(Project project, String name, String sdkPath, String javaSdkName, String buildTargetHashString) {
super(project, name, {})
this.sdkPath = sdkPath
this.buildTargetHashString = buildTargetHashString
this.javaSdkName = javaSdkName;
}
@Override
String getJavacExecutable() {
def javaSdk = project.sdks[javaSdkName]
return javaSdk instanceof JavaSdkImpl ? javaSdk.getJavacExecutable() : null
}
@Override
String getJavaExecutable() {
def javaSdk = project.sdks[javaSdkName]
return javaSdk instanceof JavaSdkImpl ? javaSdk.getJavaExecutable() : null
}
}
@@ -0,0 +1,30 @@
package org.jetbrains.jps.android
import org.jetbrains.jps.idea.SdkTypeService
import org.jetbrains.jps.Sdk
import org.jetbrains.jps.Project
/**
* @author Eugene.Kudelevsky
*/
class AndroidSdkType extends SdkTypeService {
AndroidSdkType() {
super("Android SDK");
}
@Override
Sdk createSdk(Project project, String name, String homePath, Node additionalData) {
def attributes = additionalData.attributes()
if (attributes == null) {
return null;
}
def buildTargetHashString = (String)attributes.get("sdk")
def internalJdkName = (String)attributes.get("jdk")
if (internalJdkName == null || buildTargetHashString == null) {
return null;
}
return new AndroidSdk(project, name, homePath, internalJdkName, buildTargetHashString)
}
}
@@ -0,0 +1,498 @@
package org.jetbrains.jps.android;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.compiler.tools.AndroidIdl;
import org.jetbrains.android.compiler.tools.AndroidRenderscript;
import org.jetbrains.android.sdk.MessageBuildingSdkLog;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.*;
import org.jetbrains.jps.idea.Facet;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.*;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.android.AndroidSourceGeneratingBuilder");
@NonNls private static final String BUILDER_NAME = "android-source-generator";
@NonNls private static final String AIDL_EXTENSION = "aidl";
@NonNls private static final String RENDERSCRIPT_EXTENSION = "rs";
public AndroidSourceGeneratingBuilder() {
super(BuilderCategory.SOURCE_GENERATOR);
}
@Override
public String getName() {
return BUILDER_NAME;
}
@Override
public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
if (context.isCompilingTests()) {
return ModuleLevelBuilder.ExitCode.OK;
}
try {
return doBuild(context, chunk);
}
catch (ProjectBuildException e) {
throw e;
}
catch (Exception e) {
String message = e.getMessage();
if (message == null) {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
//noinspection IOResourceOpenedButNotSafelyClosed
e.printStackTrace(new PrintStream(out));
message = "Internal error: \n" + out.toString();
}
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message));
throw new ProjectBuildException(message, e);
}
}
private static ModuleLevelBuilder.ExitCode doBuild(CompileContext context, ModuleChunk chunk) throws Exception {
final Map<File, AndroidFacet> idlFilesToCompile = new HashMap<File, AndroidFacet>();
final Map<File, AndroidFacet> rsFilesToCompile = new HashMap<File, AndroidFacet>();
final Set<Module> modules = new HashSet<Module>();
context.processFilesToRecompile(chunk, new FileProcessor() {
@Override
public boolean apply(Module module, File file, String sourceRoot) throws IOException {
final AndroidFacet facet = getFacet(module);
if (facet == null) {
return true;
}
final String ext = FileUtil.getExtension(file.getName());
if (AIDL_EXTENSION.equals(ext)) {
idlFilesToCompile.put(file, facet);
modules.add(facet.getModule());
}
else if (RENDERSCRIPT_EXTENSION.equals(ext)) {
rsFilesToCompile.put(file, facet);
modules.add(facet.getModule());
}
return true;
}
});
final Map<Module, MyModuleData> moduleDataMap = computeModuleDatas(modules, context);
if (moduleDataMap == null) {
return ExitCode.OK;
}
if (!runAidlCompiler(context, idlFilesToCompile, moduleDataMap)) {
return ExitCode.OK;
}
if (!runRenderscriptCompiler(context, rsFilesToCompile, moduleDataMap)) {
return ExitCode.OK;
}
return ExitCode.OK;
}
private static boolean runAidlCompiler(@NotNull final CompileContext context,
@NotNull Map<File, AndroidFacet> files,
@NotNull Map<Module, MyModuleData> moduleDataMap) {
context.processMessage(new ProgressMessage("Processing AIDL files..."));
boolean success = true;
for (Map.Entry<File, AndroidFacet> entry : files.entrySet()) {
final File file = entry.getKey();
final Module module = entry.getValue().getModule();
final String filePath = file.getPath();
final MyModuleData moduleData = moduleDataMap.get(module);
if (!LOG.assertTrue(moduleData != null)) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Internal error"));
success = false;
continue;
}
final File outputDirectory = moduleData.getOutputDirectory();
final File aidlOutputDirectory = new File(outputDirectory, "generated-aidl");
final IAndroidTarget target = moduleData.getAndroidTarget();
try {
final File[] sourceRoots = getSourceRootsForModuleAndDependencies(module);
final String[] sourceRootPaths = toPaths(sourceRoots);
final String packageName = computePackageForFile(context, file);
if (packageName == null) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot compute package for file",
filePath));
success = false;
continue;
}
final File outputFile = new File(aidlOutputDirectory, packageName.replace('.', File.separatorChar) +
File.separator + FileUtil.getNameWithoutExtension(file) + ".java");
final String outputFilePath = outputFile.getPath();
final Map<AndroidCompilerMessageKind, List<String>> messages =
AndroidIdl.execute(target, filePath, outputFilePath, sourceRootPaths);
addMessages(context, messages, filePath);
if (messages.get(AndroidCompilerMessageKind.ERROR).size() > 0) {
success = false;
continue;
}
final String moduleName = getCannonicalModuleName(module);
final SourceToOutputMapping sourceToOutputMap = context.getDataManager().getSourceToOutputMap(moduleName, false);
sourceToOutputMap.update(filePath, outputFilePath);
}
catch (final IOException e) {
reportExceptionError(context, filePath, e);
success = false;
}
}
return success;
}
private static boolean runRenderscriptCompiler(@NotNull final CompileContext context,
@NotNull Map<File, AndroidFacet> files,
@NotNull Map<Module, MyModuleData> moduleDataMap) {
context.processMessage(new ProgressMessage("Processing Renderscript files..."));
boolean success = true;
for (Map.Entry<File, AndroidFacet> entry : files.entrySet()) {
final File file = entry.getKey();
final Module module = entry.getValue().getModule();
final MyModuleData moduleData = moduleDataMap.get(module);
if (!LOG.assertTrue(moduleData != null)) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Internal error"));
success = false;
continue;
}
final File outputDirectory = moduleData.getOutputDirectory();
final File rsOutputDirectory = new File(outputDirectory, "generated-rs");
final File generatedResourcesDir = new File(outputDirectory, "generated-resources");
final IAndroidTarget target = moduleData.getAndroidTarget();
final String sdkLocation = moduleData.getSdkLocation();
final String filePath = file.getPath();
File tmpOutputDirectory = null;
try {
tmpOutputDirectory = FileUtil.createTempDirectory("generated-rs-temp", null);
final String depFolderPath = getDependencyFolder(context, file, tmpOutputDirectory);
final File rawDir = new File(generatedResourcesDir, "raw");
final Map<AndroidCompilerMessageKind, List<String>> messages =
AndroidRenderscript.execute(sdkLocation, target, filePath, tmpOutputDirectory.getPath(), depFolderPath, rawDir.getPath());
addMessages(context, messages, filePath);
if (messages.get(AndroidCompilerMessageKind.ERROR).size() > 0) {
success = false;
}
else {
final List<File> newFiles = new ArrayList<File>();
AndroidCommonUtils.moveAllFiles(tmpOutputDirectory, rsOutputDirectory, newFiles);
final File bcFile = new File(rawDir, FileUtil.getNameWithoutExtension(file) + ".bc");
if (bcFile.exists()) {
newFiles.add(bcFile);
}
final List<String> newFilePaths = Arrays.asList(toPaths(newFiles.toArray(new File[newFiles.size()])));
final String moduleName = getCannonicalModuleName(module);
final SourceToOutputMapping sourceToOutputMap = context.getDataManager().getSourceToOutputMap(moduleName, false);
sourceToOutputMap.update(filePath, newFilePaths);
}
}
catch (IOException e) {
reportExceptionError(context, filePath, e);
success = false;
}
finally {
if (tmpOutputDirectory != null) {
FileUtil.delete(tmpOutputDirectory);
}
}
}
return success;
}
private static void reportExceptionError(@NotNull CompileContext context, @NotNull String filePath, @NotNull Exception exception) {
final String message = exception.getMessage();
if (message != null) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, message, filePath));
LOG.debug(exception);
}
else {
context.processMessage(new CompilerMessage(BUILDER_NAME, exception));
}
}
@NotNull
private static String getCannonicalModuleName(@NotNull Module module) {
return module.getName().toLowerCase(Locale.US);
}
@Nullable
private static String getDependencyFolder(@NotNull CompileContext context, @NotNull File sourceFile, @NotNull File genFolder) {
final RootDescriptor descriptor = context.getRootsIndex().getModuleAndRoot(sourceFile);
if (descriptor == null) {
return null;
}
final File sourceRoot = descriptor.root;
final File parent = FileUtil.getParentFile(sourceFile);
if (parent == null) {
return null;
}
if (parent.equals(sourceRoot)) {
return genFolder.getPath();
}
final String relativePath = FileUtil.getRelativePath(sourceRoot, parent);
assert relativePath != null;
return genFolder.getPath() + '/' + relativePath;
}
@Nullable
private static Map<Module, MyModuleData> computeModuleDatas(@NotNull Collection<Module> modules, @NotNull CompileContext context)
throws Exception {
final Map<Module, MyModuleData> moduleDataMap = new HashMap<Module, MyModuleData>();
boolean success = true;
for (Module module : modules) {
final Sdk sdk = module.getSdk();
if (!(sdk instanceof AndroidSdk)) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
"Android SDK is not specified for module " + module.getName()));
success = false;
continue;
}
final AndroidSdk androidSdk = (AndroidSdk)sdk;
final IAndroidTarget target = parseAndroidTarget(androidSdk, context);
if (target == null) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
"Android SDK is invalid or not specified for module " + module.getName()));
success = false;
continue;
}
final File outputDir = context.getProjectPaths().getModuleOutputDir(module, false);
if (outputDir == null) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
"Cannot find output directory for module " + module.getName()));
success = false;
continue;
}
moduleDataMap.put(module, new MyModuleData(outputDir, androidSdk.getSdkPath(), target));
}
return success ? moduleDataMap : null;
}
private static void addMessages(@NotNull CompileContext context,
@NotNull Map<AndroidCompilerMessageKind, List<String>> messages,
@Nullable String sourcePath) {
for (Map.Entry<AndroidCompilerMessageKind, List<String>> entry : messages.entrySet()) {
final AndroidCompilerMessageKind kind = entry.getKey();
final BuildMessage.Kind buildMessageKind = toBuildMessageKind(kind);
if (buildMessageKind == null) {
continue;
}
for (String message : entry.getValue()) {
context.processMessage(new CompilerMessage(BUILDER_NAME, buildMessageKind, message, sourcePath));
}
}
}
@Nullable
private static BuildMessage.Kind toBuildMessageKind(@NotNull AndroidCompilerMessageKind kind) {
switch (kind) {
case ERROR:
return BuildMessage.Kind.ERROR;
case INFORMATION:
return BuildMessage.Kind.INFO;
case WARNING:
return BuildMessage.Kind.WARNING;
default:
LOG.error("unknown AndroidCompilerMessageKind object " + kind);
return null;
}
}
@Nullable
private static String computePackageForFile(@NotNull CompileContext context, @NotNull File file) throws IOException {
final RootDescriptor descriptor = context.getRootsIndex().getModuleAndRoot(file);
if (descriptor == null) {
return null;
}
final String relPath = FileUtil.getRelativePath(descriptor.root, FileUtil.getParentFile(file));
if (relPath == null) {
return null;
}
return FileUtil.toSystemIndependentName(relPath).replace('/', '.');
}
@Nullable
private static IAndroidTarget parseAndroidTarget(@NotNull AndroidSdk sdk, @NotNull CompileContext context) {
final String targetHashString = sdk.getBuildTargetHashString();
if (targetHashString == null) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
"Cannot parse SDK " + sdk.getName() + ": build target is not specified"));
return null;
}
final MessageBuildingSdkLog log = new MessageBuildingSdkLog();
final SdkManager manager = AndroidCommonUtils.createSdkManager(sdk.getSdkPath(), log);
if (manager == null) {
final String message = log.getErrorMessage();
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
"Android SDK is parsed incorrectly." +
(message.length() > 0 ? " Parsing log:\n" + message : "")));
return null;
}
final IAndroidTarget target = manager.getTargetFromHashString(targetHashString);
if (target == null) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR,
"Cannot parse SDK '" + sdk.getName() + "': unknown target " + targetHashString));
return null;
}
return target;
}
private static void fillSourceRoots(@NotNull Module module, @NotNull Set<Module> visited, @NotNull Set<File> result)
throws IOException {
visited.add(module);
final AndroidFacet facet = getFacet(module);
File resDir = null;
if (facet != null) {
resDir = facet.getResourceDir();
if (resDir != null) {
resDir = resDir.getCanonicalFile();
}
}
for (String sourceRootPath : module.getSourceRoots()) {
final File sourceRoot = new File(sourceRootPath).getCanonicalFile();
if (!sourceRoot.equals(resDir)) {
result.add(sourceRoot);
}
}
for (ClasspathItem classpathItem : module.getClasspath(ClasspathKind.PRODUCTION_COMPILE)) {
if (classpathItem instanceof Module) {
final Module depModule = (Module)classpathItem;
if (!visited.contains(depModule)) {
fillSourceRoots(depModule, visited, result);
}
}
}
}
@NotNull
public static File[] getSourceRootsForModuleAndDependencies(@NotNull Module module) throws IOException {
Set<File> result = new HashSet<File>();
fillSourceRoots(module, new HashSet<Module>(), result);
return result.toArray(new File[result.size()]);
}
@Override
public String getDescription() {
return "Android Builder";
}
@Nullable
private static AndroidFacet getFacet(@NotNull Module module) {
AndroidFacet androidFacet = null;
for (Facet facet : module.getFacets().values()) {
if (facet instanceof AndroidFacet) {
androidFacet = (AndroidFacet)facet;
}
}
return androidFacet;
}
@NotNull
private static String[] toPaths(@NotNull File[] files) {
final String[] result = new String[files.length];
for (int i = 0; i < result.length; i++) {
result[i] = files[i].getPath();
}
return result;
}
private static class MyModuleData {
private final File myOutputDirectory;
private final String mySdkLocation;
private final IAndroidTarget myAndroidTarget;
private MyModuleData(@NotNull File outputDirectory,
@NotNull String sdkLocation,
@NotNull IAndroidTarget androidTarget) {
myOutputDirectory = outputDirectory;
mySdkLocation = sdkLocation;
myAndroidTarget = androidTarget;
}
@NotNull
public File getOutputDirectory() {
return myOutputDirectory;
}
@NotNull
public IAndroidTarget getAndroidTarget() {
return myAndroidTarget;
}
@NotNull
public String getSdkLocation() {
return mySdkLocation;
}
}
}
@@ -16,7 +16,9 @@
package org.jetbrains.android.compiler.tools;
import com.android.sdklib.IAndroidTarget;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.annotations.NotNull;
@@ -32,6 +34,8 @@ import java.util.Map;
* @author Alexey Efimov
*/
public final class AndroidIdl {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.tools.AndroidIdl");
private AndroidIdl() {
}
@@ -51,6 +55,8 @@ public final class AndroidIdl {
}
commands.add(file);
commands.add(outFile);
LOG.info(AndroidCommonUtils.command2string(commands));
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(commands));
}
@@ -0,0 +1,58 @@
package org.jetbrains.android.compiler.tools;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidCompilerMessageKind;
import org.jetbrains.android.util.ExecutionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author Eugene.Kudelevsky
*/
public class AndroidRenderscript {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidRenderscriptCompiler");
public static Map<AndroidCompilerMessageKind, List<String>> execute(@NotNull final String sdkLocation,
@NotNull IAndroidTarget target,
@NotNull String sourceFilePath,
@NotNull final String genFolderPath,
@Nullable String depFolderPath,
@NotNull final String rawDirPath)
throws IOException {
final List<String> command = new ArrayList<String>();
command.add(
FileUtil.toSystemDependentName(sdkLocation + '/' + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER + SdkConstants.FN_RENDERSCRIPT));
command.add("-I");
command.add(target.getPath(IAndroidTarget.ANDROID_RS_CLANG));
command.add("-I");
command.add(target.getPath(IAndroidTarget.ANDROID_RS));
command.add("-p");
command.add(FileUtil.toSystemDependentName(genFolderPath));
command.add("-o");
command.add(FileUtil.toSystemDependentName(rawDirPath));
command.add("-target-api");
command.add(Integer.toString(target.getVersion().getApiLevel()));
if (depFolderPath != null) {
command.add("-d");
command.add(FileUtil.toSystemDependentName(depFolderPath));
}
command.add("-MD");
command.add(FileUtil.toSystemDependentName(sourceFilePath));
LOG.info(AndroidCommonUtils.command2string(command));
return ExecutionUtil.doExecute(ArrayUtil.toStringArray(command));
}
}
@@ -21,11 +21,7 @@ import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
/**
* Created by IntelliJ IDEA.
* User: Eugene.Kudelevsky
* Date: Aug 25, 2009
* Time: 5:54:47 PM
* To change this template use File | Settings | File Templates.
* @author Eugene.Kudelevsky
*/
public class MessageBuildingSdkLog implements ISdkLog {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.sdk.MessageBuildingSdkLog");
@@ -1,8 +1,15 @@
package org.jetbrains.android.util;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
@@ -11,7 +18,7 @@ import java.util.Iterator;
*/
public class AndroidCommonUtils {
@NonNls public static final Object MANIFEST_JAVA_FILE_NAME = "Manifest.java";
public static final String R_JAVA_FILENAME = "R.java";
@NonNls public static final String R_JAVA_FILENAME = "R.java";
private AndroidCommonUtils() {
}
@@ -29,4 +36,37 @@ public class AndroidCommonUtils {
}
return builder.toString();
}
@Nullable
public static SdkManager createSdkManager(@NotNull String path, @NotNull ISdkLog log) {
path = FileUtil.toSystemDependentName(path);
final File f = new File(path);
if (!f.exists() || !f.isDirectory()) {
return null;
}
final File platformsDir = new File(f, SdkConstants.FD_PLATFORMS);
if (!platformsDir.exists() || !platformsDir.isDirectory()) {
return null;
}
return SdkManager.createManager(path + File.separatorChar, log);
}
public static void moveAllFiles(@NotNull File from, @NotNull File to, @NotNull Collection<File> newFiles) throws IOException {
if (from.isFile()) {
FileUtil.rename(from, to);
newFiles.add(to);
}
else {
final File[] children = from.listFiles();
if (children != null) {
for (File child : children) {
moveAllFiles(child, new File(to, child.getName()), newFiles);
}
}
}
}
}
+6
View File
@@ -189,6 +189,12 @@
<externalAnnotator language="JAVA" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
<externalAnnotator language="XML" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
<externalAnnotator language="TEXT" implementationClass="org.jetbrains.android.inspections.lint.AndroidLintExternalAnnotator"/>
<compileServer.plugin jar-path="jps/android-jps-plugin.jar"/>
<compileServer.plugin jar-path="android-rt.jar"/>
<compileServer.plugin jar-path="sdklib.jar"/>
<compileServer.plugin jar-path="../../../../../community/plugins/android/lib/sdklib.jar"/>
</extensions>
<extensionPoints>
@@ -20,6 +20,7 @@ import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.compiler.tools.AndroidApt;
import org.jetbrains.android.compiler.tools.AndroidIdl;
import org.jetbrains.android.compiler.tools.AndroidRenderscript;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
@@ -448,13 +449,19 @@ public class AndroidAutogenerator {
try {
tempOutDir = FileUtil.createTempDirectory("android_renderscript_autogeneration", "tmp");
final VirtualFile vTempOutDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempOutDir);
final Map<CompilerMessageCategory, List<String>> messages = AndroidRenderscriptCompiler.
launchRenderscriptCompiler(module.getProject(), item.mySdkLocation, item.myTarget, file, tempOutDir.getPath(), item.myRawDirPath);
final String depFolderPath =
vTempOutDir != null ? AndroidRenderscriptCompiler.getDependencyFolder(context.getProject(), file, vTempOutDir) : null;
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidRenderscript
.execute(item.mySdkLocation, item.myTarget, file.getPath(), tempOutDir.getPath(), depFolderPath,
item.myRawDirPath));
if (messages.get(CompilerMessageCategory.ERROR).size() == 0) {
final List<File> newFiles = new ArrayList<File>();
moveAllFiles(tempOutDir, new File(item.myGenDirPath), newFiles);
AndroidCommonUtils.moveAllFiles(tempOutDir, new File(item.myGenDirPath), newFiles);
for (File newFile : newFiles) {
final VirtualFile newVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(newFile);
@@ -502,22 +509,6 @@ public class AndroidAutogenerator {
}
}
private static void moveAllFiles(@NotNull File from, @NotNull File to, @NotNull Collection<File> newFiles) throws IOException {
if (from.isFile()) {
FileUtil.rename(from, to);
newFiles.add(to);
}
else {
final File[] children = from.listFiles();
if (children != null) {
for (File child : children) {
moveAllFiles(child, new File(to, child.getName()), newFiles);
}
}
}
}
private static boolean ensureFilesWritable(@NotNull final Project project, @NotNull final Collection<VirtualFile> filesToCheck) {
if (filesToCheck.size() == 0) {
return true;
@@ -2,31 +2,26 @@ package org.jetbrains.android.compiler;
import com.android.AndroidConstants;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.intellij.facet.FacetManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.compiler.tools.AndroidRenderscript;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,8 +35,7 @@ import java.util.*;
* @author Eugene.Kudelevsky
*/
public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidRenderscriptCompiler");
private static final GenerationItem[] EMPTY_GENERATION_ITEM_ARRAY = {};
@Nullable
@@ -190,13 +184,15 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
}
for (final VirtualFile sourceFile : genItem.myFiles) {
final String depFolderOsPath = getDependencyFolder(context.getProject(), sourceFile, outputRootDirectory);
try {
final Map<CompilerMessageCategory, List<String>> messages = launchRenderscriptCompiler(context.getProject(),
genItem.mySdkLocation,
genItem.myAndroidTarget,
sourceFile,
genRootPath,
genItem.myRawDirPath);
final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys(
AndroidRenderscript
.execute(genItem.mySdkLocation, genItem.myAndroidTarget, sourceFile.getPath(), genRootPath,
depFolderOsPath,
genItem.myRawDirPath));
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (context.getProject().isDisposed()) {
@@ -235,47 +231,10 @@ public class AndroidRenderscriptCompiler implements SourceGeneratingCompiler {
}
}
static Map<CompilerMessageCategory, List<String>> launchRenderscriptCompiler(@NotNull Project project,
@NotNull final String sdkLocation,
@NotNull IAndroidTarget target,
@NotNull final VirtualFile sourceFile,
@NotNull final String genFolderPath,
@NotNull final String rawDirPath)
throws IOException {
final List<String> command = new ArrayList<String>();
command.add(
FileUtil.toSystemDependentName(sdkLocation + '/' + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER + SdkConstants.FN_RENDERSCRIPT));
command.add("-I");
command.add(target.getPath(IAndroidTarget.ANDROID_RS_CLANG));
command.add("-I");
command.add(target.getPath(IAndroidTarget.ANDROID_RS));
command.add("-p");
command.add(FileUtil.toSystemDependentName(genFolderPath));
command.add("-o");
command.add(FileUtil.toSystemDependentName(rawDirPath));
final String sourceFilePath = FileUtil.toSystemDependentName(sourceFile.getPath());
final VirtualFile genFolder = LocalFileSystem.getInstance().refreshAndFindFileByPath(FileUtil.toSystemIndependentName(genFolderPath));
if (genFolder != null) {
final String dependencyFolderPath = getDependencyFolder(project, sourceFile, genFolder);
if (dependencyFolderPath != null) {
command.add("-d");
command.add(FileUtil.toSystemDependentName(dependencyFolderPath));
}
}
command.add("-MD");
command.add(sourceFilePath);
LOG.info(AndroidCommonUtils.command2string(command));
return AndroidCompileUtil.execute(ArrayUtil.toStringArray(command));
}
@Nullable
private static String getDependencyFolder(@NotNull final Project project,
@NotNull final VirtualFile sourceFile,
@NotNull final VirtualFile genFolder) {
static String getDependencyFolder(@NotNull final Project project,
@NotNull final VirtualFile sourceFile,
@NotNull final VirtualFile genFolder) {
final ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
final VirtualFile sourceRoot = index.getSourceRootForFile(sourceFile);
@@ -33,6 +33,7 @@ import com.intellij.reference.SoftReference;
import com.intellij.util.containers.HashMap;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.android.actions.AndroidEnableDdmsAction;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.BufferingFileWrapper;
import org.jetbrains.annotations.NotNull;
@@ -152,7 +153,7 @@ public class AndroidSdk {
@Nullable
public static AndroidSdk parse(@NotNull String path, @NotNull ISdkLog log) {
final SdkManager manager = AndroidSdkUtils.createSdkManager(path, log);
final SdkManager manager = AndroidCommonUtils.createSdkManager(path, log);
return manager != null ? new AndroidSdk(manager, path) : null;
}
@@ -17,9 +17,7 @@
package org.jetbrains.android.sdk;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
@@ -36,12 +34,12 @@ import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import org.jetbrains.android.util.AndroidCommonUtils;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
/**
@@ -55,7 +53,7 @@ public class AndroidSdkUtils {
}
public static boolean isAndroidSdk(@NotNull String path) {
return createSdkManager(path, new EmptySdkLog()) != null;
return AndroidCommonUtils.createSdkManager(path, new EmptySdkLog()) != null;
}
@Nullable
@@ -370,21 +368,4 @@ public class AndroidSdkUtils {
public static void openModuleDependenciesConfigurable(final Module module) {
ProjectSettingsService.getInstance(module.getProject()).openModuleDependenciesSettings(module, null);
}
@Nullable
public static SdkManager createSdkManager(@NotNull String path, @NotNull ISdkLog log) {
path = FileUtil.toSystemDependentName(path);
final File f = new File(path);
if (!f.exists() || !f.isDirectory()) {
return null;
}
final File platformsDir = new File(f, SdkConstants.FD_PLATFORMS);
if (!platformsDir.exists() || !platformsDir.isDirectory()) {
return null;
}
return SdkManager.createManager(path + File.separatorChar, log);
}
}