private static void doCollectResourceDirs( AndroidFacet facet, boolean collectResCacheDirs, List<String> result, CompileContext context) { final Module module = facet.getModule(); if (collectResCacheDirs) { final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform(); final int platformToolsRevision = platform != null ? platform.getSdk().getPlatformToolsRevision() : -1; if (platformToolsRevision < 0 || platformToolsRevision > 7) { // png cache is supported since platform-tools-r8 final String resCacheDirOsPath = findResourcesCacheDirectory(module, false, context); if (resCacheDirOsPath != null) { result.add(resCacheDirOsPath); } else { LOG.info("PNG cache not found for module " + module.getName()); } } } final VirtualFile resourcesDir = AndroidAptCompiler.getResourceDirForApkCompiler(module, facet); if (resourcesDir != null) { result.add(resourcesDir.getPath()); } }
private static void addItem( @NotNull final Collection<VirtualFile> sourceFiles, @NotNull final AndroidFacet facet, @NotNull final String resourceDirPath, @NotNull String sdkLocation, @NotNull final IAndroidTarget target, @NotNull final List<GenerationItem> items) { final String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(facet); if (sourceRootPath == null) { return; } final String rawDirPath = resourceDirPath + '/' + AndroidConstants.FD_RES_RAW; items.add( new MyGenerationItem(facet.getModule(), sourceFiles, rawDirPath, sdkLocation, target)); }
private static VirtualFile[] getFilesToCheckReadonlyStatus( GeneratingCompiler.GenerationItem[] items) { List<VirtualFile> filesToCheck = new ArrayList<VirtualFile>(); for (GeneratingCompiler.GenerationItem item : items) { if (item instanceof AndroidAptCompiler.AptGenerationItem) { final Set<File> generatedFiles = ((AndroidAptCompiler.AptGenerationItem) item).getGeneratedFiles().keySet(); for (File generatedFile : generatedFiles) { if (generatedFile.exists()) { VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(generatedFile); if (generatedVFile != null) { filesToCheck.add(generatedVFile); } } } } } return VfsUtil.toVirtualFileArray(filesToCheck); }
@Nullable private File getOutputDirsToCompileTo(ModuleChunk chunk, final List<OutputDir> dirs) throws IOException { File fileToDelete = null; if (chunk.getModuleCount() == 1) { // optimization final Module module = chunk.getModules()[0]; ApplicationManager.getApplication() .runReadAction( new Runnable() { public void run() { final String sourcesOutputDir = getOutputDir(module); if (shouldCompileTestsSeparately(module)) { if (sourcesOutputDir != null) { dirs.add(new OutputDir(sourcesOutputDir, ModuleChunk.SOURCES)); } final String testsOutputDir = getTestsOutputDir(module); if (testsOutputDir == null) { LOG.error("Tests output dir is null for module \"" + module.getName() + "\""); } else { dirs.add(new OutputDir(testsOutputDir, ModuleChunk.TEST_SOURCES)); } } else { // both sources and test sources go into the same output if (sourcesOutputDir == null) { LOG.error( "Sources output dir is null for module \"" + module.getName() + "\""); } else { dirs.add(new OutputDir(sourcesOutputDir, ModuleChunk.ALL_SOURCES)); } } } }); } else { // chunk has several modules final File outputDir = FileUtil.createTempDirectory("compile", "output"); fileToDelete = outputDir; dirs.add(new OutputDir(outputDir.getPath(), ModuleChunk.ALL_SOURCES)); } return fileToDelete; }
@Nullable private Pair<String, String> moveToRealLocation( String tempOutputDir, String pathToClass, VirtualFile sourceFile, final List<File> filesToRefresh) { final Module module = myCompileContext.getModuleByFile(sourceFile); if (module == null) { final String message = "Cannot determine module for source file: " + sourceFile.getPresentableUrl() + ";\nCorresponding output file: " + pathToClass; LOG.info(message); myCompileContext.addMessage( CompilerMessageCategory.WARNING, message, sourceFile.getUrl(), -1, -1); // do not move: looks like source file has been invalidated, need recompilation return new Pair<String, String>(tempOutputDir, pathToClass); } final String realOutputDir; if (myCompileContext.isInTestSourceContent(sourceFile)) { realOutputDir = getTestsOutputDir(module); LOG.assertTrue(realOutputDir != null); } else { realOutputDir = getOutputDir(module); LOG.assertTrue(realOutputDir != null); } if (FileUtil.pathsEqual(tempOutputDir, realOutputDir)) { // no need to move filesToRefresh.add(new File(pathToClass)); return new Pair<String, String>(realOutputDir, pathToClass); } final String realPathToClass = realOutputDir + pathToClass.substring(tempOutputDir.length()); final File fromFile = new File(pathToClass); final File toFile = new File(realPathToClass); boolean success = fromFile.renameTo(toFile); if (!success) { // assuming cause of the fail: intermediate dirs do not exist FileUtil.createParentDirs(toFile); // retry after making non-existent dirs success = fromFile.renameTo(toFile); } if (!success) { // failed to move the file: e.g. because source and destination reside on // different mountpoints. try { FileUtil.copy(fromFile, toFile); FileUtil.delete(fromFile); success = true; } catch (IOException e) { LOG.info(e); success = false; } } if (success) { filesToRefresh.add(toFile); return new Pair<String, String>(realOutputDir, realPathToClass); } return null; }
private static GenerationItem[] doGenerate( @NotNull final CompileContext context, @NotNull final GenerationItem[] items, VirtualFile outputRootDirectory) { if (context.getProject().isDisposed()) { return EMPTY_GENERATION_ITEM_ARRAY; } // we have one item per module there, so clear output directory final String genRootPath = FileUtil.toSystemDependentName(outputRootDirectory.getPath()); final File genRootDir = new File(genRootPath); if (genRootDir.exists()) { if (!FileUtil.delete(genRootDir)) { context.addMessage( CompilerMessageCategory.ERROR, "Cannot delete directory " + genRootPath, null, -1, -1); return EMPTY_GENERATION_ITEM_ARRAY; } if (!genRootDir.mkdir()) { context.addMessage( CompilerMessageCategory.ERROR, "Cannot create directory " + genRootPath, null, -1, -1); return EMPTY_GENERATION_ITEM_ARRAY; } } final List<GenerationItem> results = new ArrayList<GenerationItem>(items.length); for (final GenerationItem item : items) { if (item instanceof MyGenerationItem) { final MyGenerationItem genItem = (MyGenerationItem) item; if (!AndroidCompileUtil.isModuleAffected(context, genItem.myModule)) { continue; } boolean success = true; for (final VirtualFile sourceFile : genItem.myFiles) { final String depFolderOsPath = getDependencyFolder(context.getProject(), sourceFile, outputRootDirectory); try { 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()) { return; } addMessages(context, messages, sourceFile.getUrl()); } }); if (messages.get(CompilerMessageCategory.ERROR).size() > 0) { success = false; } } catch (final IOException e) { ApplicationManager.getApplication() .runReadAction( new Runnable() { public void run() { if (context.getProject().isDisposed()) return; context.addMessage( CompilerMessageCategory.ERROR, e.getMessage(), sourceFile.getUrl(), -1, -1); } }); success = false; } } if (success) { results.add(genItem); } } } outputRootDirectory.refresh(false, true); return results.toArray(new GenerationItem[results.size()]); }
public static void generate(GeneratingCompiler compiler, final CompileContext context) { if (context == null) { return; } final Set<Module> affectedModules = new HashSet<Module>(); Collections.addAll(affectedModules, context.getCompileScope().getAffectedModules()); ApplicationManager.getApplication() .invokeAndWait( new Runnable() { @Override public void run() { for (Module module : affectedModules) { if (module.isDisposed() || module.getProject().isDisposed()) { continue; } final AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null) { AndroidCompileUtil.createGenModulesAndSourceRoots(facet); } } } }, ModalityState.defaultModalityState()); List<GeneratingCompiler.GenerationItem> itemsToGenerate = new ArrayList<GeneratingCompiler.GenerationItem>(); for (GeneratingCompiler.GenerationItem item : compiler.getGenerationItems(context)) { if (affectedModules.contains(item.getModule())) { itemsToGenerate.add(item); } } GeneratingCompiler.GenerationItem[] items = itemsToGenerate.toArray(new GeneratingCompiler.GenerationItem[itemsToGenerate.size()]); final boolean[] run = {true}; final VirtualFile[] files = getFilesToCheckReadonlyStatus(items); if (files.length > 0) { ApplicationManager.getApplication() .invokeAndWait( new Runnable() { @Override public void run() { ApplicationManager.getApplication() .runReadAction( new Runnable() { @Override public void run() { final Project project = context.getProject(); run[0] = !project.isDisposed() && ReadonlyStatusHandler.ensureFilesWritable(project, files); } }); } }, ModalityState.defaultModalityState()); } if (run[0]) { compiler.generate(context, items, null); } }