diff options
author | mikaelpeltier <mikaelpeltier@google.com> | 2014-07-07 15:51:38 +0200 |
---|---|---|
committer | mikaelpeltier <mikaelpeltier@google.com> | 2014-07-28 14:27:16 +0200 |
commit | 6beb3c97d7c5602f8a6a339fc6b4c4b53e3d816a (patch) | |
tree | a6ce4dddfaedd80d658b7559b289ce09ddd558d8 | |
parent | f03975dc15719d32dd4476df3d6ea7cf64d5e145 (diff) | |
download | toolchain_jack-6beb3c97d7c5602f8a6a339fc6b4c4b53e3d816a.tar.gz toolchain_jack-6beb3c97d7c5602f8a6a339fc6b4c4b53e3d816a.tar.bz2 toolchain_jack-6beb3c97d7c5602f8a6a339fc6b4c4b53e3d816a.zip |
Merge dex files even if there is only deleted files
(cherry picked from commit 95394e27321fa11b3a934357df8601abbc28909c)
Change-Id: Icee73f5dfce755785ea0e2c6fe22097e4e99e541
7 files changed, 205 insertions, 46 deletions
diff --git a/jack/src/com/android/jack/Jack.java b/jack/src/com/android/jack/Jack.java index b96c1ee0..51d0b95e 100644 --- a/jack/src/com/android/jack/Jack.java +++ b/jack/src/com/android/jack/Jack.java @@ -44,6 +44,7 @@ import com.android.jack.backend.dex.annotations.ClassAnnotationSchedulingSeparat import com.android.jack.backend.dex.annotations.DefaultValueAnnotationAdder; import com.android.jack.backend.dex.annotations.ReflectAnnotationsAdder; import com.android.jack.backend.dex.rop.CodeItemBuilder; +import com.android.jack.backend.jayce.ImportConflictException; import com.android.jack.backend.jayce.JackFormatProduct; import com.android.jack.backend.jayce.JayceFileImporter; import com.android.jack.backend.jayce.JayceSingleTypeWriter; @@ -69,8 +70,10 @@ import com.android.jack.ir.ast.JDefinedClassOrInterface; import com.android.jack.ir.ast.JField; import com.android.jack.ir.ast.JMethod; import com.android.jack.ir.ast.JPackage; +import com.android.jack.ir.ast.JPackageLookupException; import com.android.jack.ir.ast.JSession; import com.android.jack.ir.ast.JType; +import com.android.jack.ir.ast.JTypeLookupException; import com.android.jack.ir.ast.JVisitor; import com.android.jack.ir.formatter.InternalFormatter; import com.android.jack.ir.formatter.TypePackageAndMethodFormatter; @@ -345,6 +348,26 @@ public abstract class Jack { NothingToDoException, ConfigurationException, JackUserException { + run(options, false); + } + + /** + * Runs the jack compiler on source files and generates a dex file. + * + * @param options options for the compiler. + * @throws ConfigurationException + * @throws IllegalOptionsException + * @throws NothingToDoException + * @throws ImportConflictException + * @throws JackIOException + * @throws JPackageLookupException + * @throws JTypeLookupException + */ + public static void run(@Nonnull Options options, boolean skipEcj) + throws IllegalOptionsException, + NothingToDoException, + ConfigurationException, + JackUserException { boolean assertEnable = false; // assertEnable = true if assertion is already enable assert true == (assertEnable = true); @@ -367,7 +390,7 @@ public abstract class Jack { RunnableHooks hooks = new RunnableHooks(); try { - options.checkValidity(hooks); + options.checkValidity(hooks, skipEcj); Config config = options.getConfig(); ThreadConfig.setConfig(config); @@ -384,7 +407,7 @@ public abstract class Jack { logger.log(Level.INFO, "Jack sanity checks {0}", (options.hasSanityChecks() ? "enabled" : "disabled")); - JSession session = buildSession(options, hooks); + JSession session = skipEcj ? getSession() : buildSession(options, hooks); Request request = createInitialRequest(); request.addFeature(Resources.class); diff --git a/jack/src/com/android/jack/Options.java b/jack/src/com/android/jack/Options.java index b4ae1360..6deefc95 100644 --- a/jack/src/com/android/jack/Options.java +++ b/jack/src/com/android/jack/Options.java @@ -616,6 +616,11 @@ public class Options { public void checkValidity(@Nonnull RunnableHooks hooks) throws IllegalOptionsException, NothingToDoException, ConfigurationException { + checkValidity(hooks, false); + } + + public void checkValidity(@Nonnull RunnableHooks hooks, boolean skipEcj) + throws IllegalOptionsException, NothingToDoException, ConfigurationException { config = getConfigBuilder().setHooks(hooks).build(); LoggerFactory.loadLoggerConfiguration( @@ -636,11 +641,13 @@ public class Options { ); try { - compiler.configure(ecjArguments.toArray(new String[ecjArguments.size()])); - if (!compiler.proceed) { - throw new NothingToDoException(); + if (!skipEcj) { + compiler.configure(ecjArguments.toArray(new String[ecjArguments.size()])); + if (!compiler.proceed) { + throw new NothingToDoException(); + } + compiler.getLibraryAccess().cleanup(); } - compiler.getLibraryAccess().cleanup(); } catch (IllegalArgumentException e) { throw new IllegalOptionsException(e.getMessage(), e); } diff --git a/jack/src/com/android/jack/experimental/incremental/CompilerState.java b/jack/src/com/android/jack/experimental/incremental/CompilerState.java index f2229f81..03d5d9ab 100644 --- a/jack/src/com/android/jack/experimental/incremental/CompilerState.java +++ b/jack/src/com/android/jack/experimental/incremental/CompilerState.java @@ -83,7 +83,16 @@ public final class CompilerState { return compilerStateFile; } - public void updateCompilerState(@Nonnull Set<String> filesToRecompile) { + public void updateCompilerState(@Nonnull Set<String> filesToRecompile, + @Nonnull Set<String> filesToDelete) { + + for (String javaFileToDelete : filesToDelete) { + javaFileToTypeNamePath.remove(javaFileToDelete); + codeFileToUsedFiles.remove(javaFileToDelete); + structFileToUsedFiles.remove(javaFileToDelete); + cstFileToUsedFiles.remove(javaFileToDelete); + } + for (String javaFileToRecompile : filesToRecompile) { javaFileToTypeNamePath.remove(javaFileToRecompile); codeFileToUsedFiles.remove(javaFileToRecompile); diff --git a/jack/src/com/android/jack/experimental/incremental/JackIncremental.java b/jack/src/com/android/jack/experimental/incremental/JackIncremental.java index e13e35e6..1ecec7b1 100644 --- a/jack/src/com/android/jack/experimental/incremental/JackIncremental.java +++ b/jack/src/com/android/jack/experimental/incremental/JackIncremental.java @@ -50,7 +50,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -189,18 +188,21 @@ public class JackIncremental extends CommandLine { logger.log(Level.FINE, "Compiler state {0}", getCompilerState()); logger.log(Level.FINE, "File dependencies {0}", dependenciesToString(fileDependencies)); - Set<String> filesToRecompile = getFilesToRecompile(fileDependencies, javaFilesNames); + Set<String> deletedFiles = getDeletedFiles(javaFilesNames); + Set<String> filesToRecompile = + getFilesToRecompile(fileDependencies, javaFilesNames, deletedFiles); - if (!filesToRecompile.isEmpty()) { + if (!filesToRecompile.isEmpty() || !deletedFiles.isEmpty()) { logger.log(Level.INFO, "{0} Files to recompile {1}", new Object[] {Integer.valueOf(filesToRecompile.size()), filesToRecompile}); updateOptions(options, filesToRecompile); - getCompilerState().updateCompilerState(filesToRecompile); + // Compiler state update can be done here, if there is compilation error, modification + // will not be write on the disk + getCompilerState().updateCompilerState(filesToRecompile, deletedFiles); - logger.log(Level.INFO, "Ecj options {0}", options.getEcjArguments()); - - Jack.run(options); + logger.log(Level.FINE, "Ecj options {0}", options.getEcjArguments()); + Jack.run(options, filesToRecompile.isEmpty()); } else { logger.log(Level.INFO, "No files to recompile"); } @@ -301,33 +303,44 @@ public class JackIncremental extends CommandLine { @Nonnull private static Set<String> getFilesToRecompile( - @Nonnull Map<String, Set<String>> fileDependencies, @Nonnull List<String> javaFileNames) - throws JackUserException { + @Nonnull Map<String, Set<String>> fileDependencies, @Nonnull List<String> javaFileNames, + Set<String> deletedFiles) throws JackUserException { Set<String> filesToRecompile = new HashSet<String>(); - filesToRecompile.addAll(getModifiedFiles(fileDependencies, javaFileNames)); + filesToRecompile.addAll(getModifiedFiles(fileDependencies, javaFileNames, deletedFiles)); filesToRecompile.addAll(getAddedFiles(fileDependencies, javaFileNames)); - filesToRecompile.addAll(getDeletedFiles(fileDependencies, javaFileNames)); + + for (String deletedFile : deletedFiles) { + deleteOldFilesFromJavaFiles(deletedFile); + addNotModifiedDependencies(fileDependencies, deletedFiles, filesToRecompile, deletedFile); + } + + for (String fileToRecompile : filesToRecompile) { + deleteOldFilesFromJavaFiles(fileToRecompile); + } return filesToRecompile; } + private static void addNotModifiedDependencies( + @Nonnull Map<String, Set<String>> fileDependencies, @Nonnull Set<String> deletedFiles, + @Nonnull Set<String> filesToRecompile, @Nonnull String fileName) { + for (String dependency : fileDependencies.get(fileName)) { + if (!deletedFiles.contains(dependency)) { + filesToRecompile.add(dependency); + } + } + } + @Nonnull - private static Set<String> getDeletedFiles(@Nonnull Map<String, Set<String>> fileDependencies, - @Nonnull List<String> javaFileNames) throws JackUserException { + private static Set<String> getDeletedFiles(@Nonnull List<String> javaFileNames) + throws JackUserException { Set<String> deletedFiles = new HashSet<String>(); - Iterator<String> previousFilesIt = getCompilerState().getJavaFilename().iterator(); - - while (previousFilesIt.hasNext()) { - String previousFileName = previousFilesIt.next(); - if (!javaFileNames.contains(previousFileName)) { - logger.log(Level.INFO, "{0} was deleted", previousFileName); - deletedFiles.addAll(fileDependencies.get(previousFileName)); - deleteOldFilesFromJavaFiles(previousFileName); - for (String dependencyFile : fileDependencies.get(previousFileName)) { - deleteOldFilesFromJavaFiles(dependencyFile); - } - previousFilesIt.remove(); + + for (String javaFileName : getCompilerState().getJavaFilename()) { + if (!javaFileNames.contains(javaFileName)) { + logger.log(Level.INFO, "{0} was deleted", javaFileName); + deletedFiles.add(javaFileName); } } @@ -367,24 +380,25 @@ public class JackIncremental extends CommandLine { @Nonnull private static Set<String> getModifiedFiles(@Nonnull Map<String, Set<String>> fileDependencies, - @Nonnull List<String> javaFileNames) throws JackUserException { + @Nonnull List<String> javaFileNames, @Nonnull Set<String> deletedFiles) + throws JackUserException { Set<String> modifiedFiles = new HashSet<String>(); for (Map.Entry<String, Set<String>> previousFileEntry : fileDependencies.entrySet()) { String javaFileName = previousFileEntry.getKey(); - for (String typeNameToCheck : getCompilerState() - .getTypeNamePathFromJavaFileName(javaFileName)) { - File javaFile = new File(javaFileName); - if (javaFileNames.contains(javaFileName) - && javaFile.lastModified() > getDexFile(typeNameToCheck).lastModified()) { - logger.log(Level.INFO, "{0} was modified", new Object[] {javaFileName}); - modifiedFiles.add(javaFileName); - modifiedFiles.addAll(previousFileEntry.getValue()); - deleteOldFilesFromJavaFiles(javaFileName); - for (String dependencyFile : previousFileEntry.getValue()) { - deleteOldFilesFromJavaFiles(dependencyFile); + if (!deletedFiles.contains(javaFileName)) { + for (String typeNameToCheck : getCompilerState().getTypeNamePathFromJavaFileName( + javaFileName)) { + File javaFile = new File(javaFileName); + File dexFile = getDexFile(typeNameToCheck); + if (!dexFile.exists() + || (javaFileNames.contains(javaFileName) && javaFile.lastModified() > dexFile + .lastModified())) { + logger.log(Level.INFO, "{0} was modified", new Object[] {javaFileName}); + modifiedFiles.add(javaFileName); + addNotModifiedDependencies(fileDependencies, deletedFiles, modifiedFiles, javaFileName); + break; } - break; } } } diff --git a/jack/tests/com/android/jack/experimental/incremental/DependenciesTest014.java b/jack/tests/com/android/jack/experimental/incremental/DependenciesTest014.java new file mode 100644 index 00000000..c73e9ab6 --- /dev/null +++ b/jack/tests/com/android/jack/experimental/incremental/DependenciesTest014.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.jack.experimental.incremental; + +import com.android.jack.Main; +import com.android.jack.TestTools; +import com.android.jack.dx.io.DexBuffer; + +import junit.framework.Assert; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.FileInputStream; + +/** + * JUnit test checking incremental support when files are deleted. + */ +public class DependenciesTest014 { + + @BeforeClass + public static void setUpClass() { + Main.class.getClassLoader().setDefaultAssertionStatus(true); + } + + /** + * Check that incremental compilation works when file without dependency is deleted. + */ + @Test + public void testDependency001() throws Exception { + IncrementalTestingEnvironment ite = + new IncrementalTestingEnvironment(TestTools.createTempDir("DependenciesTest_", "_001")); + + ite.addJavaFile("jack.incremental", "A.java", "package jack.incremental; \n" + + "public class A { \n" + "}"); + + ite.addJavaFile("jack.incremental", "B.java", "package jack.incremental; \n" + + "public class B { \n" + "}"); + + ite.incrementalBuildFromFolder(); + ite.snapshotJackFilesModificationDate(); + Assert.assertEquals(2, ite.getJackFiles().size()); + + ite.deleteJavaFile("jack.incremental", "B.java"); + ite.incrementalBuildFromFolder(); + DexBuffer db = new DexBuffer(new FileInputStream(ite.getDexFile())); + for (String typeName : db.typeNames()) { + if (typeName.equals("Ljack/incremental/B;")) { + Assert.fail(); + } + } + } + + /** + * Check that incremental compilation works when dependency file is deleted. + */ + @Test + public void testDependency002() throws Exception { + IncrementalTestingEnvironment ite = + new IncrementalTestingEnvironment(TestTools.createTempDir("DependenciesTest_", "_001")); + + ite.addJavaFile("jack.incremental", "A.java", "package jack.incremental; \n" + + "public class A { \n" + "}"); + + ite.addJavaFile("jack.incremental", "B.java", "package jack.incremental; \n" + + "public class B extends C { \n" + "}"); + + ite.addJavaFile("jack.incremental", "C.java", "package jack.incremental; \n" + + "public class C { \n" + "}"); + + ite.incrementalBuildFromFolder(); + ite.snapshotJackFilesModificationDate(); + Assert.assertEquals(3, ite.getJackFiles().size()); + + ite.deleteJavaFile("jack.incremental", "B.java"); + ite.deleteJavaFile("jack.incremental", "C.java"); + ite.incrementalBuildFromFolder(); + DexBuffer db = new DexBuffer(new FileInputStream(ite.getDexFile())); + for (String typeName : db.typeNames()) { + if (typeName.equals("Ljack/incremental/B;") || + typeName.equals("Ljack/incremental/C;")) { + Assert.fail(); + } + } + } +} + diff --git a/jack/tests/com/android/jack/experimental/incremental/DependencyAllTests.java b/jack/tests/com/android/jack/experimental/incremental/DependencyAllTests.java index f0a1a61a..458b6b52 100644 --- a/jack/tests/com/android/jack/experimental/incremental/DependencyAllTests.java +++ b/jack/tests/com/android/jack/experimental/incremental/DependencyAllTests.java @@ -9,6 +9,6 @@ import org.junit.runners.Suite.SuiteClasses; DependenciesTest003.class, DependenciesTest004.class, DependenciesTest005.class, DependenciesTest006.class, DependenciesTest007.class, DependenciesTest008.class, DependenciesTest009.class, DependenciesTest010.class, DependenciesTest011.class, - DependenciesTest012.class, DependenciesTest013.class}) + DependenciesTest012.class, DependenciesTest013.class, DependenciesTest014.class}) public class DependencyAllTests { }
\ No newline at end of file diff --git a/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java b/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java index 808307b4..24658909 100644 --- a/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java +++ b/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java @@ -219,6 +219,11 @@ public class IncrementalTestingEnvironment extends TestTools { return (jackFiles); } + @Nonnull + public File getDexFile() { + return dexFile; + } + private void startErrRedirection() { baosErr = new ByteArrayOutputStream(); errRedirectStream = new PrintStream(baosErr); |