summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikaelpeltier <mikaelpeltier@google.com>2014-07-07 15:51:38 +0200
committermikaelpeltier <mikaelpeltier@google.com>2014-07-28 14:27:16 +0200
commit6beb3c97d7c5602f8a6a339fc6b4c4b53e3d816a (patch)
treea6ce4dddfaedd80d658b7559b289ce09ddd558d8
parentf03975dc15719d32dd4476df3d6ea7cf64d5e145 (diff)
downloadtoolchain_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
-rw-r--r--jack/src/com/android/jack/Jack.java27
-rw-r--r--jack/src/com/android/jack/Options.java15
-rw-r--r--jack/src/com/android/jack/experimental/incremental/CompilerState.java11
-rw-r--r--jack/src/com/android/jack/experimental/incremental/JackIncremental.java90
-rw-r--r--jack/tests/com/android/jack/experimental/incremental/DependenciesTest014.java101
-rw-r--r--jack/tests/com/android/jack/experimental/incremental/DependencyAllTests.java2
-rw-r--r--jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java5
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);