summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikaelpeltier <mikaelpeltier@google.com>2014-12-11 15:58:54 +0100
committermikaelpeltier <mikaelpeltier@google.com>2014-12-17 13:22:48 +0100
commite1606650fd5ffff22f1a8daed77c6539f28755ce (patch)
treec62ad7002ff8fe798cf3093241f12d4c36fa51fe
parent5dadc0fd613eef5841bf809452c9c69e41191a57 (diff)
downloadtoolchain_jack-e1606650fd5ffff22f1a8daed77c6539f28755ce.zip
toolchain_jack-e1606650fd5ffff22f1a8daed77c6539f28755ce.tar.gz
toolchain_jack-e1606650fd5ffff22f1a8daed77c6539f28755ce.tar.bz2
Remove incremental wrapper
Bug: 18425643 Change-Id: Iaad989b085f7d56952202bf6f7484380f97b60f1
-rw-r--r--jack-tests/src/com/android/jack/test/toolchain/JackApiToolchain.java29
-rw-r--r--jack-tests/src/com/android/jack/test/toolchain/JackCliToolchain.java17
-rw-r--r--jack/src/com/android/jack/Jack.java18
-rw-r--r--jack/src/com/android/jack/Options.java22
-rw-r--r--jack/src/com/android/jack/analysis/dependency/file/FileDependencies.java19
-rw-r--r--jack/src/com/android/jack/analysis/dependency/file/FileDependenciesWriter.java16
-rw-r--r--jack/src/com/android/jack/analysis/dependency/type/TypeDependencies.java35
-rw-r--r--jack/src/com/android/jack/analysis/dependency/type/TypeDependenciesWriter.java14
-rw-r--r--jack/src/com/android/jack/experimental/incremental/JackIncremental.java683
-rw-r--r--jack/src/com/android/jack/experimental/incremental/Main.java115
-rw-r--r--jack/src/com/android/jack/frontend/java/JackBatchCompiler.java3
-rw-r--r--jack/src/com/android/jack/incremental/CommonFilter.java73
-rw-r--r--jack/src/com/android/jack/incremental/IncrementalException.java (renamed from jack/src/com/android/jack/experimental/incremental/IncrementalException.java)2
-rw-r--r--jack/src/com/android/jack/incremental/IncrementalInputFilter.java415
-rw-r--r--jack/src/com/android/jack/incremental/InputFilter.java34
-rw-r--r--jack/src/com/android/jack/incremental/NoInputFilter.java60
-rw-r--r--jack/src/com/android/jack/ir/ast/JSession.java16
-rw-r--r--jack/src/com/android/jack/library/FileType.java10
-rw-r--r--jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java3
19 files changed, 701 insertions, 883 deletions
diff --git a/jack-tests/src/com/android/jack/test/toolchain/JackApiToolchain.java b/jack-tests/src/com/android/jack/test/toolchain/JackApiToolchain.java
index 4e3b167..77a6afa 100644
--- a/jack-tests/src/com/android/jack/test/toolchain/JackApiToolchain.java
+++ b/jack-tests/src/com/android/jack/test/toolchain/JackApiToolchain.java
@@ -19,7 +19,6 @@ package com.android.jack.test.toolchain;
import com.android.jack.Jack;
import com.android.jack.Options;
import com.android.jack.backend.dex.rop.CodeItemBuilder;
-import com.android.jack.experimental.incremental.JackIncremental;
import com.android.jack.shrob.spec.Flags;
import java.io.File;
@@ -58,7 +57,6 @@ public class JackApiToolchain extends JackBasedToolchain {
jackOptions.applyShrobFlags();
}
- // jackOptions.setEcjArguments(AbstractTestTools.buildEcjArgs());
jackOptions.setEcjArguments(new ArrayList<String>());
if (annotationProcessorClass != null) {
@@ -99,12 +97,7 @@ public class JackApiToolchain extends JackBasedToolchain {
System.setOut(outRedirectStream);
System.setErr(errRedirectStream);
- if (jackOptions.getIncrementalFolder() != null) {
- JackIncremental.run(jackOptions);
- } else {
- Jack.run(jackOptions);
- }
-
+ Jack.run(jackOptions);
} finally {
System.setOut(stdOut);
System.setErr(stdErr);
@@ -166,12 +159,7 @@ public class JackApiToolchain extends JackBasedToolchain {
System.setOut(outRedirectStream);
System.setErr(errRedirectStream);
- if (jackOptions.getIncrementalFolder() != null) {
- JackIncremental.run(jackOptions);
- } else {
- Jack.run(jackOptions);
- }
-
+ Jack.run(jackOptions);
} finally {
System.setOut(stdOut);
System.setErr(stdErr);
@@ -206,12 +194,7 @@ public class JackApiToolchain extends JackBasedToolchain {
jackOptions.setOutputDir(out);
}
- if (jackOptions.getIncrementalFolder() != null) {
- JackIncremental.run(jackOptions);
- } else {
- Jack.run(jackOptions);
- }
-
+ Jack.run(jackOptions);
} finally {
System.setOut(stdOut);
System.setErr(stdErr);
@@ -247,11 +230,7 @@ public class JackApiToolchain extends JackBasedToolchain {
jackOptions.setJayceOutputDir(out);
}
- if (jackOptions.getIncrementalFolder() != null) {
- JackIncremental.run(jackOptions);
- } else {
- Jack.run(jackOptions);
- }
+ Jack.run(jackOptions);
}
@Nonnull
diff --git a/jack-tests/src/com/android/jack/test/toolchain/JackCliToolchain.java b/jack-tests/src/com/android/jack/test/toolchain/JackCliToolchain.java
index 34d974f..517d955 100644
--- a/jack-tests/src/com/android/jack/test/toolchain/JackCliToolchain.java
+++ b/jack-tests/src/com/android/jack/test/toolchain/JackCliToolchain.java
@@ -55,13 +55,12 @@ public class JackCliToolchain extends JackBasedToolchain {
args.add(jackPrebuilt.getAbsolutePath());
if (incrementalFolder != null) {
- args.add(com.android.jack.experimental.incremental.Main.class.getName());
args.add("--incremental-folder");
args.add(incrementalFolder.getAbsolutePath());
- } else {
- args.add(com.android.jack.Main.class.getName());
}
+ args.add(com.android.jack.Main.class.getName());
+
addProperties(properties, args);
if (classpath != null) {
@@ -133,12 +132,10 @@ public class JackCliToolchain extends JackBasedToolchain {
args.add(jackPrebuilt.getAbsolutePath());
if (incrementalFolder != null) {
- args.add(com.android.jack.experimental.incremental.Main.class.getName());
args.add("--incremental-folder");
args.add(incrementalFolder.getAbsolutePath());
- } else {
- args.add(com.android.jack.Main.class.getName());
}
+ args.add(com.android.jack.Main.class.getName());
addProperties(properties, args);
@@ -205,12 +202,10 @@ public class JackCliToolchain extends JackBasedToolchain {
args.add(jackPrebuilt.getAbsolutePath());
if (incrementalFolder != null) {
- args.add(com.android.jack.experimental.incremental.Main.class.getName());
args.add("--incremental-folder");
args.add(incrementalFolder.getAbsolutePath());
- } else {
- args.add(com.android.jack.Main.class.getName());
}
+ args.add(com.android.jack.Main.class.getName());
if (withDebugInfos) {
args.add("-D");
@@ -257,12 +252,10 @@ public class JackCliToolchain extends JackBasedToolchain {
args.add(jackPrebuilt.getAbsolutePath());
if (incrementalFolder != null) {
- args.add(com.android.jack.experimental.incremental.Main.class.getName());
args.add("--incremental-folder");
args.add(incrementalFolder.getAbsolutePath());
- } else {
- args.add(com.android.jack.Main.class.getName());
}
+ args.add(com.android.jack.Main.class.getName());
addProperties(properties, args);
diff --git a/jack/src/com/android/jack/Jack.java b/jack/src/com/android/jack/Jack.java
index 730b11d..9f3900d 100644
--- a/jack/src/com/android/jack/Jack.java
+++ b/jack/src/com/android/jack/Jack.java
@@ -23,10 +23,8 @@ import com.android.jack.analysis.UsedVariableRemover;
import com.android.jack.analysis.defsuses.DefUsesAndUseDefsChainComputation;
import com.android.jack.analysis.defsuses.DefUsesAndUseDefsChainRemover;
import com.android.jack.analysis.defsuses.UseDefsChecker;
-import com.android.jack.analysis.dependency.file.FileDependencies;
import com.android.jack.analysis.dependency.file.FileDependenciesCollector;
import com.android.jack.analysis.dependency.file.FileDependenciesWriter;
-import com.android.jack.analysis.dependency.type.TypeDependencies;
import com.android.jack.analysis.dependency.type.TypeDependenciesCollector;
import com.android.jack.analysis.dependency.type.TypeDependenciesWriter;
import com.android.jack.analysis.dfa.reachingdefs.ReachingDefinitions;
@@ -400,11 +398,6 @@ public abstract class Jack {
return unmodifiableCollections;
}
- public static void run(@Nonnull Options options) throws ConfigurationException, JackUserException,
- IllegalOptionsException, NothingToDoException {
- Jack.run(options, new TypeDependencies(), new FileDependencies());
- }
-
/**
* Runs the jack compiler on source files and generates a dex file.
*
@@ -419,9 +412,7 @@ public abstract class Jack {
* @throws JPackageLookupException thrown when the lookup of a package failed.
* @throws JTypeLookupException thrown when the lookup of a type failed.
*/
- // TODO(jack-team): Remove typeDependencies and fileDependencies parameters
- public static void run(@Nonnull Options options, @Nonnull TypeDependencies typeDependencies,
- @Nonnull FileDependencies fileDependencies)
+ public static void run(@Nonnull Options options)
throws IllegalOptionsException,
NothingToDoException,
ConfigurationException,
@@ -475,10 +466,7 @@ public abstract class Jack {
logger.log(Level.INFO, "Jack sanity checks {0}",
(options.hasSanityChecks() ? "enabled" : "disabled"));
-
JSession session = getSession();
- session.setTypeDependencies(typeDependencies);
- session.setFileDependencies(fileDependencies);
buildSession(options, hooks);
@@ -732,12 +720,12 @@ public abstract class Jack {
@Nonnull
static JSession buildSession(@Nonnull Options options, @Nonnull RunnableHooks hooks)
throws JackUserException {
-
Tracer tracer = TracerFactory.getTracer();
List<String> ecjArguments = options.ecjArguments;
JSession session = getSession();
+ session.setInputFilter(ThreadConfig.get(Options.INPUT_FILTER).create(options));
try {
getMetaImporter(options.metaImport, hooks).doImport(session);
@@ -750,7 +738,7 @@ public abstract class Jack {
try {
jayceImporter = getJayceFileImporter(options.jayceImport, hooks, session);
putInJackClasspath(options.getBootclasspath(), hooks, session);
- putInJackClasspath(options.getClasspath(), hooks, session);
+ putInJackClasspath(session.getInputFilter().getClasspath(), hooks, session);
} catch (LibraryReadingException e) {
session.getReporter().report(Severity.FATAL, e);
throw new JackAbortException(e);
diff --git a/jack/src/com/android/jack/Options.java b/jack/src/com/android/jack/Options.java
index 6f28ddf..ea165dc 100644
--- a/jack/src/com/android/jack/Options.java
+++ b/jack/src/com/android/jack/Options.java
@@ -25,6 +25,7 @@ import com.android.jack.backend.dex.rop.CodeItemBuilder;
import com.android.jack.config.id.Arzon;
import com.android.jack.config.id.JavaVersionPropertyId;
import com.android.jack.config.id.Private;
+import com.android.jack.incremental.InputFilter;
import com.android.jack.ir.ast.JMethod;
import com.android.jack.shrob.obfuscation.MappingPrinter;
import com.android.jack.shrob.obfuscation.NameProviderFactory;
@@ -52,6 +53,7 @@ import com.android.sched.util.config.id.EnumPropertyId;
import com.android.sched.util.config.id.ImplementationPropertyId;
import com.android.sched.util.config.id.ObjectId;
import com.android.sched.util.config.id.PropertyId;
+import com.android.sched.util.config.id.ReflectFactoryPropertyId;
import com.android.sched.util.file.Directory;
import com.android.sched.util.file.FileOrDirectory.ChangePermission;
import com.android.sched.util.file.FileOrDirectory.Existence;
@@ -95,6 +97,11 @@ import javax.annotation.Nonnull;
public class Options {
@Nonnull
+ public static final ReflectFactoryPropertyId<InputFilter> INPUT_FILTER = ReflectFactoryPropertyId
+ .create("jack.input.filter", "Inputs filter", InputFilter.class)
+ .addDefaultValue("no-filter").addArgType(Options.class);
+
+ @Nonnull
public static final JavaVersionPropertyId JAVA_SOURCE_VERSION = JavaVersionPropertyId
.create("jack.java.source.version", "Java source version").addDefaultValue("1.7")
.withCategory(Arzon.get());
@@ -140,9 +147,10 @@ public class Options {
"jack.internal.library.output.dir", "Output folder for internal library",
new DirectDirInputOutputVDirCodec(Existence.MAY_EXIST))
.withCategory(Private.get()).requiredIf(GENERATE_DEX_IN_LIBRARY.getValue()
- .isTrue().and(DEX_OUTPUT_CONTAINER_TYPE.is(Container.DIR)
- .or(DEX_OUTPUT_CONTAINER_TYPE.is(Container.ZIP))
- .and(GENERATE_JACK_LIBRARY.getValue().isFalse())));
+ .isTrue().and(DEX_OUTPUT_CONTAINER_TYPE.is(Container.DIR).or(
+ DEX_OUTPUT_CONTAINER_TYPE.is(Container.ZIP)).and(GENERATE_JACK_LIBRARY.getValue()
+ .isFalse())).or(GENERATE_JACK_LIBRARY.getValue()
+ .isTrue().and(LIBRARY_OUTPUT_CONTAINER_TYPE.is(Container.DIR))));
@Nonnull
public static final PropertyId<OutputVFS> DEX_OUTPUT_DIR = PropertyId.create(
@@ -611,6 +619,8 @@ public class Options {
configBuilder.setString(LIBRARY_OUTPUT_DIR, libraryOutDir.getAbsolutePath());
configBuilder.set(LIBRARY_OUTPUT_CONTAINER_TYPE, Container.DIR);
configBuilder.set(GENERATE_JACK_LIBRARY, true);
+ configBuilder.set(GENERATE_DEX_IN_LIBRARY, true);
+ configBuilder.setString(Options.INTERNAL_LIBRARY_OUTPUT_DIR, libraryOutDir.getPath());
}
switch (multiDexKind) {
@@ -649,6 +659,10 @@ public class Options {
FieldInitializerRemover.STRING_AS_INITIALVALUE_OF_OBJECT, !runtimeLegacy);
if (incrementalFolder != null) {
+ configBuilder.setString(Options.INPUT_FILTER.getName(), "incremental");
+ configBuilder.set(Options.GENERATE_JACK_LIBRARY, true);
+ configBuilder.setString(Options.LIBRARY_OUTPUT_CONTAINER_TYPE.getName(), "dir");
+ configBuilder.setString(Options.LIBRARY_OUTPUT_DIR.getName(), incrementalFolder.getPath());
configBuilder.setString(Options.INTERNAL_LIBRARY_OUTPUT_DIR,
incrementalFolder.getAbsolutePath());
}
@@ -702,7 +716,7 @@ public class Options {
try {
compiler.configure(ecjArguments.toArray(new String[ecjArguments.size()]));
- if (!compiler.proceed) {
+ if (!compiler.proceed && incrementalFolder == null) {
throw new NothingToDoException();
}
compiler.getLibraryAccess().cleanup();
diff --git a/jack/src/com/android/jack/analysis/dependency/file/FileDependencies.java b/jack/src/com/android/jack/analysis/dependency/file/FileDependencies.java
index c7a428a..f31065d 100644
--- a/jack/src/com/android/jack/analysis/dependency/file/FileDependencies.java
+++ b/jack/src/com/android/jack/analysis/dependency/file/FileDependencies.java
@@ -70,6 +70,15 @@ public class FileDependencies extends Dependency {
types.add(typeFqn);
}
+ public void update(@Nonnull Set<String> deleteFileNames, @Nonnull Set<String> modifiedFileNames) {
+ for (String deletedJavaFileName : deleteFileNames) {
+ javaFileToTypes.remove(deletedJavaFileName);
+ }
+ for (String modifiedJavaFileName : modifiedFileNames) {
+ javaFileToTypes.remove(modifiedJavaFileName);
+ }
+ }
+
public void write(@Nonnull PrintStream ps) {
writeMapOne2Many(ps, javaFileToTypes);
ps.print(Dependency.MAP_SEPARATOR);
@@ -77,11 +86,6 @@ public class FileDependencies extends Dependency {
}
@Nonnull
- public void read(@Nonnull Readable reader) throws IOException {
- javaFileToTypes = readMapOne2Many(new LineReader(reader));
- }
-
- @Nonnull
public Set<String> getTypeNames(@Nonnull String javaFileName) {
Set<String> typeNames = javaFileToTypes.get(javaFileName);
if (typeNames == null) {
@@ -105,4 +109,9 @@ public class FileDependencies extends Dependency {
public Set<String> getCompiledJavaFiles() {
return Jack.getUnmodifiableCollections().getUnmodifiableSet(javaFileToTypes.keySet());
}
+
+ @Nonnull
+ public void read(@Nonnull Readable reader) throws IOException {
+ javaFileToTypes = readMapOne2Many(new LineReader(reader));
+ }
}
diff --git a/jack/src/com/android/jack/analysis/dependency/file/FileDependenciesWriter.java b/jack/src/com/android/jack/analysis/dependency/file/FileDependenciesWriter.java
index 5526d8b..8b87064 100644
--- a/jack/src/com/android/jack/analysis/dependency/file/FileDependenciesWriter.java
+++ b/jack/src/com/android/jack/analysis/dependency/file/FileDependenciesWriter.java
@@ -19,9 +19,10 @@ package com.android.jack.analysis.dependency.file;
import com.android.jack.Jack;
import com.android.jack.JackAbortException;
import com.android.jack.JackUserException;
-import com.android.jack.experimental.incremental.IncrementalException;
+import com.android.jack.incremental.IncrementalException;
import com.android.jack.ir.ast.JSession;
import com.android.jack.library.FileType;
+import com.android.jack.library.OutputJackLibrary;
import com.android.jack.reporting.Reporter.Severity;
import com.android.sched.item.Description;
import com.android.sched.item.Name;
@@ -44,11 +45,16 @@ public class FileDependenciesWriter implements RunnableSchedulable<JSession>{
@Override
public void run(@Nonnull JSession session) throws JackUserException {
- PrintStream ps = null;
+ write(session.getJackInternalOutputLibrary(), Jack.getSession().getFileDependencies());
+ }
+
+ public static void write(@Nonnull OutputJackLibrary ojl,
+ @Nonnull FileDependencies fileDependencies) {
+ PrintStream ps = null;
try {
- ps = new PrintStream(session.getJackInternalOutputLibrary().createFile(
- FileType.DEPENDENCIES, FileDependencies.vpath).openWrite());
- Jack.getSession().getFileDependencies().write(ps);
+ ps = new PrintStream(
+ ojl.createFile(FileType.DEPENDENCIES, FileDependencies.vpath).openWrite());
+ fileDependencies.write(ps);
} catch (CannotCreateFileException e) {
IncrementalException incrementalException = new IncrementalException(e);
Jack.getSession().getReporter().report(Severity.FATAL, incrementalException);
diff --git a/jack/src/com/android/jack/analysis/dependency/type/TypeDependencies.java b/jack/src/com/android/jack/analysis/dependency/type/TypeDependencies.java
index 428aca1..0116964 100644
--- a/jack/src/com/android/jack/analysis/dependency/type/TypeDependencies.java
+++ b/jack/src/com/android/jack/analysis/dependency/type/TypeDependencies.java
@@ -19,6 +19,7 @@ package com.android.jack.analysis.dependency.type;
import com.google.common.io.LineReader;
import com.android.jack.analysis.dependency.Dependency;
+import com.android.jack.analysis.dependency.file.FileDependencies;
import com.android.jack.ir.ast.JType;
import com.android.jack.ir.formatter.BinaryQualifiedNameFormatter;
import com.android.sched.item.Description;
@@ -89,14 +90,6 @@ public class TypeDependencies extends Dependency {
}
@Nonnull
- public void read(@Nonnull Readable readable) throws IOException {
- LineReader lr = new LineReader(readable);
- hierarchyDependencies = readMapOne2Many(lr);
- constantDependencies = readMapOne2Many(lr);
- codeDependencies = readMapOne2Many(lr);
- }
-
- @Nonnull
public Map<String, Set<String>> getRecompileDependencies() {
Map<String, Set<String>> recompileDependencies = new HashMap<String, Set<String>>();
@@ -201,4 +194,30 @@ public class TypeDependencies extends Dependency {
}
}
}
+
+ @Nonnull
+ public void read(@Nonnull Readable readable) throws IOException {
+ LineReader lr = new LineReader(readable);
+ hierarchyDependencies = readMapOne2Many(lr);
+ constantDependencies = readMapOne2Many(lr);
+ codeDependencies = readMapOne2Many(lr);
+ }
+
+ public void update(@Nonnull FileDependencies fileDependencies,
+ @Nonnull Set<String> deleteFileNames, @Nonnull Set<String> modifiedFileNames) {
+ for (String deletedJavaFileName : deleteFileNames) {
+ for (String deleteTypeName : fileDependencies.getTypeNames(deletedJavaFileName)) {
+ codeDependencies.remove(deleteTypeName);
+ constantDependencies.remove(deleteTypeName);
+ hierarchyDependencies.remove(deleteTypeName);
+ }
+ }
+ for (String modifiedJavaFileName : modifiedFileNames) {
+ for (String deleteTypeName : fileDependencies.getTypeNames(modifiedJavaFileName)) {
+ codeDependencies.remove(deleteTypeName);
+ constantDependencies.remove(deleteTypeName);
+ hierarchyDependencies.remove(deleteTypeName);
+ }
+ }
+ }
}
diff --git a/jack/src/com/android/jack/analysis/dependency/type/TypeDependenciesWriter.java b/jack/src/com/android/jack/analysis/dependency/type/TypeDependenciesWriter.java
index 68fc1c5..2229e2a 100644
--- a/jack/src/com/android/jack/analysis/dependency/type/TypeDependenciesWriter.java
+++ b/jack/src/com/android/jack/analysis/dependency/type/TypeDependenciesWriter.java
@@ -19,9 +19,10 @@ package com.android.jack.analysis.dependency.type;
import com.android.jack.Jack;
import com.android.jack.JackAbortException;
import com.android.jack.JackUserException;
-import com.android.jack.experimental.incremental.IncrementalException;
+import com.android.jack.incremental.IncrementalException;
import com.android.jack.ir.ast.JSession;
import com.android.jack.library.FileType;
+import com.android.jack.library.OutputJackLibrary;
import com.android.jack.reporting.Reporter.Severity;
import com.android.sched.item.Description;
import com.android.sched.item.Name;
@@ -44,11 +45,16 @@ public class TypeDependenciesWriter implements RunnableSchedulable<JSession>{
@Override
public void run(@Nonnull JSession session) throws JackUserException {
+ write(session.getJackInternalOutputLibrary(), Jack.getSession().getTypeDependencies());
+ }
+
+ public static void write(@Nonnull OutputJackLibrary ojl,
+ @Nonnull TypeDependencies typeDependencies) {
PrintStream ps = null;
try {
- ps = new PrintStream(session.getJackInternalOutputLibrary()
- .createFile(FileType.DEPENDENCIES, TypeDependencies.vpath).openWrite());
- Jack.getSession().getTypeDependencies().write(ps);
+ ps = new PrintStream(
+ ojl.createFile(FileType.DEPENDENCIES, TypeDependencies.vpath).openWrite());
+ typeDependencies.write(ps);
} catch (CannotCreateFileException e) {
IncrementalException incrementalException = new IncrementalException(e);
Jack.getSession().getReporter().report(Severity.FATAL, incrementalException);
diff --git a/jack/src/com/android/jack/experimental/incremental/JackIncremental.java b/jack/src/com/android/jack/experimental/incremental/JackIncremental.java
deleted file mode 100644
index 2d54632..0000000
--- a/jack/src/com/android/jack/experimental/incremental/JackIncremental.java
+++ /dev/null
@@ -1,683 +0,0 @@
-/*
- * Copyright (C) 2013 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.CommandLine;
-import com.android.jack.ExitStatus;
-import com.android.jack.IllegalOptionsException;
-import com.android.jack.Jack;
-import com.android.jack.JackUserException;
-import com.android.jack.NothingToDoException;
-import com.android.jack.Options;
-import com.android.jack.analysis.dependency.file.FileDependencies;
-import com.android.jack.analysis.dependency.file.FileDependenciesWriter;
-import com.android.jack.analysis.dependency.type.TypeDependencies;
-import com.android.jack.analysis.dependency.type.TypeDependenciesWriter;
-import com.android.jack.backend.dex.DexFileProduct;
-import com.android.jack.backend.dex.DexFileWriter;
-import com.android.jack.frontend.FrontendCompilationException;
-import com.android.jack.ir.ast.JSession;
-import com.android.jack.ir.formatter.BinaryQualifiedNameFormatter;
-import com.android.jack.ir.formatter.TypeFormatter;
-import com.android.jack.library.FileType;
-import com.android.jack.library.FileTypeDoesNotExistException;
-import com.android.jack.library.InputJackLibrary;
-import com.android.jack.library.JackLibraryFactory;
-import com.android.jack.library.LibraryFormatException;
-import com.android.jack.library.LibraryIOException;
-import com.android.jack.library.LibraryVersionException;
-import com.android.jack.library.NotJackLibraryException;
-import com.android.jack.library.OutputJackLibrary;
-import com.android.jack.load.JackLoadingException;
-import com.android.jack.scheduling.marker.ClassDefItemMarker;
-import com.android.jack.util.TextUtils;
-import com.android.sched.scheduler.IllegalRequestException;
-import com.android.sched.scheduler.PlanBuilder;
-import com.android.sched.scheduler.Request;
-import com.android.sched.util.UnrecoverableException;
-import com.android.sched.util.config.ChainedException;
-import com.android.sched.util.config.ConfigurationException;
-import com.android.sched.util.config.ThreadConfig;
-import com.android.sched.util.file.CannotCreateFileException;
-import com.android.sched.util.file.CannotDeleteFileException;
-import com.android.sched.util.file.CannotReadException;
-import com.android.sched.util.file.CannotSetPermissionException;
-import com.android.sched.util.file.Directory;
-import com.android.sched.util.file.FileAlreadyExistsException;
-import com.android.sched.util.file.FileOrDirectory.ChangePermission;
-import com.android.sched.util.file.FileOrDirectory.Existence;
-import com.android.sched.util.file.FileOrDirectory.Permission;
-import com.android.sched.util.file.NoSuchFileException;
-import com.android.sched.util.file.NotFileOrDirectoryException;
-import com.android.sched.util.file.WrongPermissionException;
-import com.android.sched.util.log.LoggerFactory;
-import com.android.sched.vfs.DirectVFS;
-import com.android.sched.vfs.InputVFile;
-import com.android.sched.vfs.VPath;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-
-/**
- * Executable class to run the jack compiler with incremental support.
- */
-public class JackIncremental extends CommandLine {
-
- @Nonnull
- private static final Logger logger = LoggerFactory.getLogger();
-
- @Nonnull
- private static List<String> deletedTypes = new ArrayList<String>();
-
- @CheckForNull
- private static File incrementalFolder;
-
- @CheckForNull
- private static InputJackLibrary incrementalInputLibrary;
-
- @CheckForNull
- private static final TypeFormatter formatter = BinaryQualifiedNameFormatter.getFormatter();
-
- @CheckForNull
- private static final char fileSeparator = '/';
-
-
- protected static void runJackAndExitOnError(@Nonnull Options options) {
- try {
- run(options);
- } catch (NothingToDoException e1) {
- // End normally since there is nothing to do
- } catch (ConfigurationException exceptions) {
- System.err.println(exceptions.getNextExceptionCount() + " error"
- + (exceptions.getNextExceptionCount() > 1 ? "s" : "")
- + " during configuration. Try --help-properties for help.");
- for (ChainedException exception : exceptions) {
- System.err.println(" " + exception.getMessage());
- }
-
- System.exit(ExitStatus.FAILURE_USAGE);
- } catch (IllegalOptionsException e) {
- System.err.println(e.getMessage());
- System.err.println("Try --help for help.");
-
- System.exit(ExitStatus.FAILURE_USAGE);
- } catch (FrontendCompilationException e) {
- // Cause exception has already been logged
- System.exit(ExitStatus.FAILURE_COMPILATION);
- } catch (JackUserException e) {
- System.err.println(e.getMessage());
- logger.log(Level.FINE, "Jack user exception:", e);
- System.exit(ExitStatus.FAILURE_COMPILATION);
- } catch (JackLoadingException e) {
- System.err.println(e.getMessage());
- logger.log(Level.FINE, "Jack loading exception:", e);
- System.exit(ExitStatus.FAILURE_COMPILATION);
- } catch (OutOfMemoryError e) {
- printExceptionMessage(e, "Out of memory error.");
- System.err.println("Try increasing heap size with java option '-Xmx<size>'");
- System.err.println(INTERRUPTED_COMPILATION_WARNING);
- logger.log(Level.FINE, "Out of memory error:", e);
- System.exit(ExitStatus.FAILURE_VM);
- } catch (StackOverflowError e) {
- printExceptionMessage(e, "Stack overflow error.");
- System.err.println("Try increasing stack size with java option '-Xss<size>'");
- System.err.println(INTERRUPTED_COMPILATION_WARNING);
- logger.log(Level.FINE, "Stack overflow error:", e);
- System.exit(ExitStatus.FAILURE_VM);
- } catch (VirtualMachineError e) {
- printExceptionMessage(e, "Virtual machine error: " + e.getClass() + ".");
- System.err.println(INTERRUPTED_COMPILATION_WARNING);
- logger.log(Level.FINE, "Virtual machine error:", e);
- System.exit(ExitStatus.FAILURE_VM);
- } catch (UnrecoverableException e) {
- System.err.println("Unrecoverable error: " + e.getMessage());
- System.err.println(INTERRUPTED_COMPILATION_WARNING);
- logger.log(Level.FINE, "Unrecoverable exception:", e);
- System.exit(ExitStatus.FAILURE_UNRECOVERABLE);
- } catch (Throwable e) {
- String info =
- "Internal incremental compiler error (version " + Jack.getVersionString() + ")";
- logger.log(Level.SEVERE, info + ':', e);
- e.printStackTrace();
- System.err.println();
- System.err.println(info + '.');
- if (e.getMessage() != null) {
- System.err.println(e.getMessage() + '.');
- }
- System.err.println(INTERRUPTED_COMPILATION_WARNING);
- System.exit(ExitStatus.FAILURE_INTERNAL);
- }
- }
-
- public static void run(@Nonnull Options options)
- throws ConfigurationException,
- IllegalOptionsException,
- NothingToDoException,
- JackUserException,
- IncrementalException {
-
- deletedTypes.clear();
- incrementalFolder = options.getIncrementalFolder();
-
- try {
- boolean firstCompilation = false;
-
- try {
- assert incrementalFolder != null;
- incrementalInputLibrary = JackLibraryFactory.getInputLibrary(new DirectVFS(new Directory(
- incrementalFolder.getPath(), null, Existence.MAY_EXIST, Permission.WRITE,
- ChangePermission.NOCHANGE)));
- } catch (NotJackLibraryException e) {
- // Nothing to do, it is the first compilation
- firstCompilation = true;
- }
-
- options.addProperty(Options.GENERATE_JACK_LIBRARY.getName(), "true");
- options.addProperty(Options.LIBRARY_OUTPUT_CONTAINER_TYPE.getName(), "dir");
- assert incrementalFolder != null;
- options.addProperty(Options.LIBRARY_OUTPUT_DIR.getName(), incrementalFolder.getPath());
-
- if (!firstCompilation && !needFullRebuild(options)) {
- assert incrementalInputLibrary != null;
- InputVFile typeDependenciesVFile = null;
- InputVFile fileDependenciesVFile = null;
- try {
- typeDependenciesVFile =
- incrementalInputLibrary.getFile(FileType.DEPENDENCIES, TypeDependencies.vpath);
- } catch (FileTypeDoesNotExistException e) {
- throw new AssertionError(e);
- }
- try {
- fileDependenciesVFile =
- incrementalInputLibrary.getFile(FileType.DEPENDENCIES, FileDependencies.vpath);
- } catch (FileTypeDoesNotExistException e) {
- throw new AssertionError(e);
- }
-
- logger.log(Level.FINE, "Incremental compilation");
-
- List<String> javaFilesNames = getJavaFilesSpecifiedOnCommandLine(options);
-
- TypeDependencies typeDependencies = new TypeDependencies();
- InputStreamReader typeReader = null;
- try {
- typeReader = new InputStreamReader(typeDependenciesVFile.openRead());
- typeDependencies.read(typeReader);
- } catch (IOException e) {
- throw new CannotReadException(typeDependenciesVFile.getLocation(), e);
- } finally {
- if (typeReader != null) {
- try {
- typeReader.close();
- } catch (IOException e) {
- }
- }
- }
-
- FileDependencies fileDependencies = new FileDependencies();
- InputStreamReader fileReader = null;
- try {
- fileReader = new InputStreamReader(fileDependenciesVFile.openRead());
- fileDependencies.read(fileReader);
- } catch (IOException e) {
- throw new CannotReadException(typeDependenciesVFile.getLocation(), e);
- } finally {
- if (fileReader != null) {
- try {
- fileReader.close();
- } catch (IOException e) {
- }
- }
- }
-
- Map<String, Set<String>> typeRecompileDependencies =
- typeDependencies.getRecompileDependencies();
- printDependencyStat(typeRecompileDependencies);
-
- Set<String> deletedFiles = getDeletedFiles(javaFilesNames, fileDependencies);
- Set<String> filesToRecompile = getFilesToRecompile(fileDependencies,
- typeRecompileDependencies, javaFilesNames, deletedFiles);
-
- if (!filesToRecompile.isEmpty() || !deletedFiles.isEmpty()) {
- logger.log(Level.FINE, "{0} Files to recompile {1}",
- new Object[] {Integer.valueOf(filesToRecompile.size()), filesToRecompile});
- updateOptions(options, filesToRecompile);
-
- logger.log(Level.FINE, "Ecj options {0}", options.getEcjArguments());
-
- try {
- Jack.run(options, typeDependencies, fileDependencies);
- } catch (NothingToDoException e) {
- // Even if there is nothing to compile, the output dex file must be rebuild from all dex
- // (one dex per types) since some dex files could be removed. To rebuild output dex
- // file, a specific plan is used.
- ThreadConfig.setConfig(options.getConfig());
-
- JSession session = Jack.getSession();
- session.setTypeDependencies(typeDependencies);
- session.setFileDependencies(fileDependencies);
-
- Request request = Jack.createInitialRequest();
- request.addProduction(DexFileProduct.class);
- request.addInitialTagOrMarker(ClassDefItemMarker.Complete.class);
- request.addInitialTagOrMarker(TypeDependencies.Collected.class);
- request.addInitialTagOrMarker(FileDependencies.Collected.class);
-
- PlanBuilder<JSession> planBuilder;
- try {
- planBuilder = request.getPlanBuilder(JSession.class);
- } catch (IllegalRequestException illegalRequest) {
- throw new AssertionError(illegalRequest);
- }
-
- planBuilder.append(TypeDependenciesWriter.class);
- planBuilder.append(FileDependenciesWriter.class);
- planBuilder.append(DexFileWriter.class);
-
- assert incrementalFolder != null;
- OutputJackLibrary incrementalOutputLibrary =
- JackLibraryFactory.getOutputLibrary(new DirectVFS(new Directory(
- incrementalFolder.getPath(), null, Existence.MAY_EXIST, Permission.WRITE,
- ChangePermission.NOCHANGE)), Jack.getEmitterId(), Jack.getVersionString());
-
- assert incrementalInputLibrary != null;
- session.setJackInternalOutputLibrary(incrementalOutputLibrary);
-
- try {
- planBuilder.getPlan().getScheduleInstance().process(Jack.getSession());
- } catch (RuntimeException runtimeExcept) {
- throw runtimeExcept;
- } catch (Exception except) {
- throw new AssertionError(except);
- } finally {
- if (incrementalOutputLibrary != null) {
- incrementalOutputLibrary.close();
- }
- }
- } finally {
- ThreadConfig.unsetConfig();
- }
-
- } else {
- logger.log(Level.FINE, "No files to recompile");
- }
- } else {
- Jack.run(options);
- }
- } catch (WrongPermissionException e) {
- throw new AssertionError(e);
- } catch (CannotSetPermissionException e) {
- throw new AssertionError(e);
- } catch (NoSuchFileException e) {
- throw new AssertionError(e);
- } catch (NotFileOrDirectoryException e) {
- throw new AssertionError(e);
- } catch (FileAlreadyExistsException e) {
- throw new AssertionError(e);
- } catch (CannotCreateFileException e) {
- throw new AssertionError(e);
- } catch (CannotReadException e) {
- throw new IncrementalException(e);
- } catch (LibraryVersionException e) {
- throw new AssertionError(e);
- } catch (LibraryFormatException e) {
- throw new AssertionError(e);
- } catch (LibraryIOException e) {
- throw new IncrementalException(e);
- }
- }
-
- /*
- * A full rebuild is needed:
- * - when a file contained inside a folder in the classpath or an archive in the classpath
- * is more recent than the generated dex file.
- * - when a file contained inside a folder in the import option or an archive in the import
- * option is more recent than the generated dex file.
- */
- private static boolean needFullRebuild(@Nonnull Options options) {
- if (!options.isAutomaticFullRebuildEnabled()) {
- return false;
- }
-
- File outputDexFile = new File(options.getOutputDir(), DexFileWriter.DEX_FILENAME);
- if (outputDexFile.exists()) {
- for (File lib : options.getBootclasspath()) {
- if (isModifiedLibrary(lib, outputDexFile.lastModified())) {
- return true;
- }
- }
- for (File lib : options.getClasspath()) {
- if (isModifiedLibrary(lib, outputDexFile.lastModified())) {
- return true;
- }
- }
- }
-
- return hasModifiedImport(options, outputDexFile.lastModified());
- }
-
- private static boolean isModifiedLibrary(@Nonnull File lib, long time) {
- if (lib.isFile() && (lib.lastModified() > time)) {
- return true;
- } else if (lib.isDirectory() && hasModifiedFile(lib, time)) {
- return true;
- }
-
- return false;
- }
-
- private static boolean hasModifiedFile(@Nonnull File file, long time) {
- assert file.isDirectory();
-
- for (File f : file.listFiles()) {
- if (f.isDirectory()) {
- if (hasModifiedFile(f, time)) {
- return true;
- }
- } else if (f.lastModified() > time) {
- return true;
- }
- }
-
- return false;
- }
-
- private static boolean hasModifiedImport(@Nonnull Options options, long time) {
- for (File importedJackFiles : options.getJayceImport()) {
- if (isModifiedLibrary(importedJackFiles, time)) {
- return true;
- }
- }
- return false;
- }
-
- @Nonnull
- private static String dependenciesToString(@Nonnull Map<String, Set<String>> fileDependencies) {
- StringBuilder builder = new StringBuilder();
- builder.append(TextUtils.LINE_SEPARATOR);
- builder.append("*Dependencies list*");
- builder.append(TextUtils.LINE_SEPARATOR);
-
- for (Map.Entry<String, Set<String>> entry : fileDependencies.entrySet()) {
- builder.append(entry.getKey());
- builder.append("->");
- builder.append(entry.getValue());
- builder.append(TextUtils.LINE_SEPARATOR);
- }
-
- return (builder.toString());
- }
-
- private static void printDependencyStat(
- @Nonnull Map<String, Set<String>> typeRecompileDependencies) {
- int dependencyNumber = 0;
- int maxDependencyNumber = -1;
- int minDependencyNumber = -1;
-
- for (Set<String> dependency : typeRecompileDependencies.values()) {
- int currentDepSize = dependency.size();
- dependencyNumber += currentDepSize;
- if (minDependencyNumber == -1 || minDependencyNumber > currentDepSize) {
- minDependencyNumber = currentDepSize;
- }
- if (maxDependencyNumber == -1 || maxDependencyNumber < currentDepSize) {
- maxDependencyNumber = currentDepSize;
- }
- }
-
- logger.log(Level.FINE,
- "There are {0} dependencies, with {1} files per dependency in average", new Object[] {
- Integer.valueOf(typeRecompileDependencies.size()),
- Double.valueOf((double) dependencyNumber / (double) typeRecompileDependencies.size())});
- logger.log(Level.FINE, "Dependencies are at minimun {0} and at maximun {1}",
- new Object[] {Integer.valueOf(minDependencyNumber), Integer.valueOf(maxDependencyNumber)});
- }
-
- private static void updateOptions(@Nonnull Options options,
- @Nonnull Set<String> javaFilesToRecompile) {
- List<String> newEcjArguments = new ArrayList<String>();
-
- for (String ecjOptions : options.getEcjArguments()) {
- if (!ecjOptions.startsWith("@") && !ecjOptions.endsWith(".java")
- && !new File(ecjOptions).isDirectory()) {
- newEcjArguments.add(ecjOptions);
- }
- }
-
- for (String fileToRecompile : javaFilesToRecompile) {
- newEcjArguments.add(fileToRecompile);
- }
-
- assert incrementalFolder != null;
- StringBuilder newClasspath = new StringBuilder(incrementalFolder.getPath());
-
- String oldClasspath = options.getClasspathAsString();
- if (oldClasspath != null) {
- newClasspath.append(File.pathSeparator);
- newClasspath.append(oldClasspath);
- }
-
- // Move imported jayce files from import to classpath option
- List<File> jayceImport = options.getJayceImport();
- if (!jayceImport.isEmpty()) {
- for (File importedJackFiles : jayceImport) {
- newClasspath.append(File.pathSeparator);
- newClasspath.append(importedJackFiles.getPath());
- }
- options.setJayceImports(Collections.<File>emptyList());
- }
-
- options.setClasspath(newClasspath.toString());
-
- if (!newEcjArguments.isEmpty()) {
- options.setEcjArguments(newEcjArguments);
- }
- }
-
- @Nonnull
- private static Set<String> getFilesToRecompile(@Nonnull FileDependencies fileDependencies,
- @Nonnull Map<String, Set<String>> typeRecompileDependencies,
- @Nonnull List<String> javaFileNames, Set<String> deletedFiles) throws IncrementalException {
- Set<String> filesToRecompile = new HashSet<String>();
-
- filesToRecompile.addAll(getModifiedFiles(fileDependencies, typeRecompileDependencies,
- javaFileNames, deletedFiles));
- filesToRecompile.addAll(getAddedFiles(fileDependencies, javaFileNames));
-
- for (String deletedFile : deletedFiles) {
- deleteOldFilesFromJavaFiles(fileDependencies, deletedFile);
- addNotModifiedDependencies(fileDependencies, typeRecompileDependencies, deletedFiles,
- filesToRecompile, deletedFile);
- }
-
- for (String fileToRecompile : filesToRecompile) {
- deleteOldFilesFromJavaFiles(fileDependencies, fileToRecompile);
- }
-
- return filesToRecompile;
- }
-
- private static void addNotModifiedDependencies(@Nonnull FileDependencies fileDependencies,
- @Nonnull Map<String, Set<String>> typeRecompileDependencies,
- @Nonnull Set<String> deletedFiles, @Nonnull Set<String> filesToRecompile,
- @Nonnull String modifiedJavaFileName) {
- for (String modifiedTypeName : fileDependencies.getTypeNames(modifiedJavaFileName)) {
- for (String typeName : typeRecompileDependencies.get(modifiedTypeName)) {
- String dependentFileName = fileDependencies.getJavaFileName(typeName);
- if (dependentFileName != null && !deletedFiles.contains(dependentFileName)) {
- filesToRecompile.add(dependentFileName);
- }
- }
- }
- }
-
- @Nonnull
- private static Set<String> getDeletedFiles(@Nonnull List<String> javaFileNames,
- @Nonnull FileDependencies fileDependencies)
- throws JackUserException {
- Set<String> deletedFiles = new HashSet<String>();
-
- for (String javaFileName : fileDependencies.getCompiledJavaFiles()) {
- if (!javaFileNames.contains(javaFileName)) {
- logger.log(Level.FINE, "{0} was deleted", javaFileName);
- deletedFiles.add(javaFileName);
- }
- }
-
- return deletedFiles;
- }
-
- private static void deleteOldFilesFromJavaFiles(
- @Nonnull FileDependencies fileDependencies, @Nonnull String javaFileName)
- throws IncrementalException {
- assert incrementalInputLibrary != null;
- for (String typeNameToRemove : fileDependencies.getTypeNames(javaFileName)) {
- if (!deletedTypes.contains(typeNameToRemove)) {
- deletedTypes.add(typeNameToRemove);
- VPath vpath = new VPath(typeNameToRemove, fileSeparator);
- deleteFile(FileType.JAYCE, vpath);
- deleteFile(FileType.DEX, vpath);
- }
- }
- }
-
- private static void deleteFile(@Nonnull FileType fileType, @Nonnull VPath vpath)
- throws IncrementalException {
- try {
- // Check that file exists
- assert incrementalInputLibrary != null;
- incrementalInputLibrary.getFile(fileType, vpath);
- incrementalInputLibrary.delete(fileType, vpath);
- } catch (FileTypeDoesNotExistException e) {
- } catch (CannotDeleteFileException e) {
- throw new IncrementalException(e);
- }
- }
-
- @Nonnull
- private static Set<String> getAddedFiles(@Nonnull FileDependencies fileDependencies,
- @Nonnull List<String> javaFileNames) {
- Set<String> addedFiles = new HashSet<String>();
- Set<String> previousFiles = fileDependencies.getCompiledJavaFiles();
-
- for (String javaFileName : javaFileNames) {
- if (!previousFiles.contains(javaFileName)) {
- logger.log(Level.FINE, "{0} was added", javaFileName);
- addedFiles.add(javaFileName);
- }
- }
-
- return addedFiles;
- }
-
- @Nonnull
- private static Set<String> getModifiedFiles(@Nonnull FileDependencies fileDependencies,
- @Nonnull Map<String, Set<String>> typeRecompileDependencies,
- @Nonnull List<String> javaFileNames, @Nonnull Set<String> deletedFiles)
- throws JackUserException {
- Set<String> modifiedFiles = new HashSet<String>();
-
- for (Map.Entry<String, Set<String>> previousFileEntry : typeRecompileDependencies.entrySet()) {
- String typeName = previousFileEntry.getKey();
- String javaFileName = fileDependencies.getJavaFileName(typeName);
- if (javaFileName != null && !deletedFiles.contains(javaFileName)) {
- File javaFile = new File(javaFileName);
- File dexFile = getDexFile(typeName);
- if (!dexFile.exists() || (javaFileNames.contains(javaFileName)
- && javaFile.lastModified() > dexFile.lastModified())) {
- logger.log(Level.FINE, "{0} was modified", new Object[] {javaFileName});
- modifiedFiles.add(javaFileName);
- addNotModifiedDependencies(fileDependencies, typeRecompileDependencies, deletedFiles,
- modifiedFiles, javaFileName);
- break;
- }
- }
- }
-
- return modifiedFiles;
- }
-
- @Nonnull
- private static List<String> getJavaFilesSpecifiedOnCommandLine(@Nonnull Options options)
- throws NothingToDoException, IllegalOptionsException {
- assert !options.getEcjArguments().isEmpty();
-
- org.eclipse.jdt.internal.compiler.batch.Main compiler =
- new org.eclipse.jdt.internal.compiler.batch.Main(new PrintWriter(System.out),
- new PrintWriter(System.err), false /* exit */, null /* options */
- , null /* compilationProgress */
- );
-
- try {
- compiler.configure(options.getEcjArguments().toArray(
- new String[options.getEcjArguments().size()]));
- if (!compiler.proceed) {
- throw new NothingToDoException();
- }
- } catch (IllegalArgumentException e) {
- throw new IllegalOptionsException(e.getMessage(), e);
- }
-
- ArrayList<String> javaFiles = new ArrayList<String>();
- for (String fileName : compiler.filenames) {
- File file = new File(fileName);
- assert file.exists();
- try {
- fileName = file.getCanonicalPath();
- } catch (IOException e) {
- // if we got exception keep the specified name
- }
- javaFiles.add(fileName);
- }
-
- return javaFiles;
- }
-
- public static TypeFormatter getFormatter() {
- return formatter;
- }
-
- @Nonnull
- protected static InputVFile getJackFile(@Nonnull String typeName) {
- try {
- assert incrementalInputLibrary != null;
- return incrementalInputLibrary.getFile(FileType.JAYCE, new VPath(typeName, fileSeparator));
- } catch (FileTypeDoesNotExistException e) {
- throw new AssertionError(e);
- }
- }
-
- @Nonnull
- protected static File getDexFile(@Nonnull String typeName) {
- assert incrementalInputLibrary != null;
- return new File(incrementalFolder, FileType.DEX.buildFileVPath(
- new VPath(typeName, fileSeparator)).getPathAsString(File.separatorChar));
- }
-}
diff --git a/jack/src/com/android/jack/experimental/incremental/Main.java b/jack/src/com/android/jack/experimental/incremental/Main.java
deleted file mode 100644
index babe775..0000000
--- a/jack/src/com/android/jack/experimental/incremental/Main.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.ExitStatus;
-import com.android.jack.Options;
-
-import org.kohsuke.args4j.CmdLineException;
-import org.kohsuke.args4j.CmdLineParser;
-
-import java.io.IOException;
-import java.io.PrintStream;
-
-import javax.annotation.Nonnull;
-
-/**
- * Command line to run the jack incremental compiler.
- */
-public abstract class Main extends JackIncremental {
- @Nonnull
- private static final String[] EXTRA_ARGS = new String[]{"-noExit"};
-
- /**
- * Runs the jack compiler from the command line
- *
- * @param args supported arguments are the same as for the ecj batch compiler.
- */
- public static void main(@Nonnull String[] args) {
- if (args.length == 0) {
- printVersion();
- System.err.println("Try --help for help.");
- System.exit(ExitStatus.SUCCESS);
- }
-
- try {
- Options options = parseCommandLine(args);
-
- if (options.askForHelp()) {
- printIncrementalUsage(System.out);
- System.exit(ExitStatus.SUCCESS);
- }
-
- if (options.askForPropertiesHelp()) {
- printHelpProperties(options);
- System.exit(ExitStatus.SUCCESS);
- }
-
- if (options.askForEcjHelp()) {
- // ECJ help was already printed by Options.checkValidity()
- System.exit(ExitStatus.SUCCESS);
- }
-
- if (options.askForVersion()) {
- printVersion();
- System.exit(ExitStatus.SUCCESS);
- }
-
- // Compile
- runJackAndExitOnError(options);
-
- System.exit(ExitStatus.SUCCESS);
- } catch (CmdLineException e) {
- System.err.println(e.getMessage());
- CmdLineParser parser = e.getParser();
- if (parser != null) {
- printIncrementalUsage(System.err);
- } else {
- System.err.println("Try --help for help.");
- }
-
- System.exit(ExitStatus.FAILURE_USAGE);
- } catch (IOException e) {
- System.err.println(e.getMessage());
-
- System.exit(ExitStatus.FAILURE_INTERNAL);
- }
- }
-
- @Nonnull
- public static Options parseCommandLine(@Nonnull String[] args)
- throws CmdLineException {
- Options options = new Options();
-
- CmdLineParser parser = new CmdLineParser(options);
- parser.setUsageWidth(100);
-
- parser.parseArgument(args);
- parser.stopOptionParsing();
- if (!options.getEcjArguments().isEmpty()) {
- parser.parseArgument(EXTRA_ARGS);
- }
-
- return options;
- }
-
- private static void printIncrementalUsage(@Nonnull PrintStream printStream) {
- printStream.println(
- " --incremental-folder FILE : Folder used for incremental data");
- printUsage(printStream);
- }
-}
diff --git a/jack/src/com/android/jack/frontend/java/JackBatchCompiler.java b/jack/src/com/android/jack/frontend/java/JackBatchCompiler.java
index a1644d3..19bcfbf 100644
--- a/jack/src/com/android/jack/frontend/java/JackBatchCompiler.java
+++ b/jack/src/com/android/jack/frontend/java/JackBatchCompiler.java
@@ -43,6 +43,7 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.logging.Level;
@@ -239,6 +240,8 @@ public class JackBatchCompiler extends Main {
super.configure(argv);
checkedClasspaths = new FileSystem.Classpath[] {
new JAstClasspath("<jack-logical-entry>", session.getLookup(), null)};
+ List<String> fileNamesToCompile = session.getInputFilter().getFileNamesToCompile();
+ filenames = fileNamesToCompile.toArray(new String[fileNamesToCompile.size()]);
}
@SuppressWarnings("rawtypes")
diff --git a/jack/src/com/android/jack/incremental/CommonFilter.java b/jack/src/com/android/jack/incremental/CommonFilter.java
new file mode 100644
index 0000000..4c0d804
--- /dev/null
+++ b/jack/src/com/android/jack/incremental/CommonFilter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.incremental;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+
+import com.android.jack.Options;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Common part of {@link InputFilter}
+ */
+public abstract class CommonFilter {
+
+ @Nonnull
+ protected List<String> getJavaFileNamesSpecifiedOnCommandLine(@Nonnull Options options) {
+ final List<File> folders = new ArrayList<File>();
+ final String extension = ".java";
+
+ List<String> javaFileNames =
+ Lists.newArrayList(Collections2.filter(options.getEcjArguments(), new Predicate<String>() {
+ @Override
+ public boolean apply(String arg) {
+ File argFile = new File(arg);
+ if (argFile.isDirectory()) {
+ folders.add(argFile);
+ }
+ return arg.endsWith(extension);
+ }
+ }));
+
+ for (File folder : folders) {
+ fillFiles(folder, extension, javaFileNames);
+ }
+
+ return (javaFileNames);
+ }
+
+ private void fillFiles(@Nonnull File folder, @Nonnull String fileExt,
+ @Nonnull List<String> fileNames) {
+ for (File subFile : folder.listFiles()) {
+ if (subFile.isDirectory()) {
+ fillFiles(subFile, fileExt, fileNames);
+ } else {
+ String path = subFile.getPath();
+ if (subFile.getName().endsWith(fileExt) && !fileNames.contains(path)) {
+ fileNames.add(path);
+ }
+ }
+ }
+ }
+}
diff --git a/jack/src/com/android/jack/experimental/incremental/IncrementalException.java b/jack/src/com/android/jack/incremental/IncrementalException.java
index 4feb3ac..5fb44c8 100644
--- a/jack/src/com/android/jack/experimental/incremental/IncrementalException.java
+++ b/jack/src/com/android/jack/incremental/IncrementalException.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.jack.experimental.incremental;
+package com.android.jack.incremental;
import com.android.jack.reporting.ReportableException;
diff --git a/jack/src/com/android/jack/incremental/IncrementalInputFilter.java b/jack/src/com/android/jack/incremental/IncrementalInputFilter.java
new file mode 100644
index 0000000..74bc20d
--- /dev/null
+++ b/jack/src/com/android/jack/incremental/IncrementalInputFilter.java
@@ -0,0 +1,415 @@
+/*
+ * 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.incremental;
+
+import com.android.jack.Jack;
+import com.android.jack.JackAbortException;
+import com.android.jack.Options;
+import com.android.jack.analysis.dependency.file.FileDependencies;
+import com.android.jack.analysis.dependency.file.FileDependenciesWriter;
+import com.android.jack.analysis.dependency.type.TypeDependencies;
+import com.android.jack.analysis.dependency.type.TypeDependenciesWriter;
+import com.android.jack.backend.dex.DexFileWriter;
+import com.android.jack.library.FileType;
+import com.android.jack.library.FileTypeDoesNotExistException;
+import com.android.jack.library.InputJackLibrary;
+import com.android.jack.library.JackLibraryFactory;
+import com.android.jack.library.LibraryFormatException;
+import com.android.jack.library.LibraryReadingException;
+import com.android.jack.library.LibraryVersionException;
+import com.android.jack.library.NotJackLibraryException;
+import com.android.jack.library.OutputJackLibrary;
+import com.android.jack.reporting.Reporter.Severity;
+import com.android.sched.util.codec.ImplementationName;
+import com.android.sched.util.config.ThreadConfig;
+import com.android.sched.util.file.CannotDeleteFileException;
+import com.android.sched.util.file.CannotReadException;
+import com.android.sched.vfs.InputVFile;
+import com.android.sched.vfs.VPath;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+
+/**
+ * {@link InputFilter} that returns filtered inputs required by incremental support.
+ */
+@ImplementationName(iface = InputFilter.class, name = "incremental")
+public class IncrementalInputFilter extends CommonFilter implements InputFilter {
+
+ @Nonnull
+ private final Options options;
+
+ @CheckForNull
+ private final InputJackLibrary incrementalInputLibrary;
+
+ @CheckForNull
+ private FileDependencies fileDependencies;
+
+ @CheckForNull
+ private TypeDependencies typeDependencies;
+
+ @Nonnull
+ private final List<String> fileNamesOnCmdLine;
+
+ public IncrementalInputFilter(@Nonnull Options options) {
+ this.options = options;
+ incrementalInputLibrary = getIncrementalInternalLibrary();
+ fileNamesOnCmdLine = getJavaFileNamesSpecifiedOnCommandLine(options);
+ if (incrementalInputLibrary != null) {
+ try {
+ fileDependencies = getFileDependencies(incrementalInputLibrary);
+ typeDependencies = getTypeDependencies(incrementalInputLibrary);
+ } catch (CannotReadException e) {
+ LibraryReadingException reportable = new LibraryReadingException(
+ new LibraryFormatException(incrementalInputLibrary.getLocation()));
+ Jack.getSession().getReporter().report(Severity.FATAL, reportable);
+ throw new JackAbortException(reportable);
+ } catch (FileTypeDoesNotExistException e) {
+ LibraryReadingException reportable = new LibraryReadingException(
+ new LibraryFormatException(incrementalInputLibrary.getLocation()));
+ Jack.getSession().getReporter().report(Severity.FATAL, reportable);
+ throw new JackAbortException(reportable);
+ }
+ }
+ }
+
+ @Override
+ @Nonnull
+ public List<File> getClasspath() {
+ InputJackLibrary incrementalInputLibrary = getIncrementalInternalLibrary();
+ List<File> classpath = options.getClasspath();
+
+ if (incrementalInputLibrary == null || needFullRebuild()) {
+ Jack.getSession().setFileDependencies(new FileDependencies());
+ Jack.getSession().setTypeDependencies(new TypeDependencies());
+ return classpath;
+ }
+
+ assert options.getIncrementalFolder() != null;
+ classpath.add(options.getIncrementalFolder());
+ classpath.addAll(options.getJayceImport());
+
+ options.setJayceImports(Collections.<File>emptyList());
+
+ try {
+ updateLibrary();
+ } catch (IncrementalException e) {
+ Jack.getSession().getReporter().report(Severity.FATAL, e);
+ throw new JackAbortException(e);
+ }
+
+ return classpath;
+ }
+
+ @Override
+ @Nonnull
+ public List<String> getFileNamesToCompile() {
+ InputJackLibrary incrementalInputLibrary = getIncrementalInternalLibrary();
+
+ if (incrementalInputLibrary == null || needFullRebuild()) {
+ return fileNamesOnCmdLine;
+ }
+
+ assert typeDependencies != null;
+
+ Map<String, Set<String>> typeRecompileDependencies =
+ typeDependencies.getRecompileDependencies();
+
+ List<String> filesToRecompile = new ArrayList<String>();
+
+ filesToRecompile.addAll(getAddedFileNames());
+
+ for (String modifiedFileName : getModifiedFileNames()) {
+ filesToRecompile.add(modifiedFileName);
+ filesToRecompile.addAll(
+ getDependencyFileNamesToRecompile(typeRecompileDependencies, modifiedFileName));
+ }
+
+ for (String deletedFileName : getDeleteFileNames()) {
+ filesToRecompile.addAll(
+ getDependencyFileNamesToRecompile(typeRecompileDependencies, deletedFileName));
+ }
+
+ return filesToRecompile;
+ }
+
+ private void updateLibrary() throws IncrementalException {
+ assert fileDependencies != null;
+ assert typeDependencies != null;
+
+ for (String fileToRecompile : getFileNamesToCompile()) {
+ deleteOldFilesFromJavaFiles(fileToRecompile);
+ }
+
+ for (String deletedFileName : getDeleteFileNames()) {
+ deleteOldFilesFromJavaFiles(deletedFileName);
+ }
+
+ fileDependencies.update(getDeleteFileNames(), getModifiedFileNames());
+ typeDependencies.update(fileDependencies, getDeleteFileNames(), getModifiedFileNames());
+
+ OutputJackLibrary outputLibrary = JackLibraryFactory.getOutputLibrary(
+ ThreadConfig.get(Options.INTERNAL_LIBRARY_OUTPUT_DIR), Jack.getEmitterId(),
+ Jack.getVersionString());
+
+ FileDependenciesWriter.write(outputLibrary, fileDependencies);
+ TypeDependenciesWriter.write(outputLibrary, typeDependencies);
+
+ Jack.getSession().setFileDependencies(fileDependencies);
+ Jack.getSession().setTypeDependencies(typeDependencies);
+ }
+
+ private void deleteOldFilesFromJavaFiles(@Nonnull String javaFileName)
+ throws IncrementalException {
+ assert fileDependencies != null;
+ List<String> deletedTypes = new ArrayList<String>();
+ for (String typeNameToRemove : fileDependencies.getTypeNames(javaFileName)) {
+ if (!deletedTypes.contains(typeNameToRemove)) {
+ deletedTypes.add(typeNameToRemove);
+ VPath vpath = new VPath(typeNameToRemove, '/');
+ deleteFile(FileType.JAYCE, vpath);
+ deleteFile(FileType.DEX, vpath);
+ }
+ }
+ }
+
+ private void deleteFile(@Nonnull FileType fileType, @Nonnull VPath vpath)
+ throws IncrementalException {
+ assert incrementalInputLibrary != null;
+ try {
+ // Check that file exists
+ incrementalInputLibrary.getFile(fileType, vpath);
+ incrementalInputLibrary.delete(fileType, vpath);
+ } catch (FileTypeDoesNotExistException e) {
+ // Nothing to do, file does no longer exists
+ } catch (CannotDeleteFileException e) {
+ throw new IncrementalException(e);
+ }
+ }
+
+ /*
+ * A full rebuild is needed when an imported library was modified or when a library from classpath
+ * was modified.
+ */
+ private boolean needFullRebuild() {
+ if (!options.isAutomaticFullRebuildEnabled()) {
+ return false;
+ }
+
+ long timestamp = new File(options.getOutputDir(), DexFileWriter.DEX_FILENAME).lastModified();
+
+ for (File lib : options.getBootclasspath()) {
+ if (isModifiedLibrary(lib, timestamp)) {
+ return true;
+ }
+ }
+
+ for (File lib : options.getClasspath()) {
+ if (isModifiedLibrary(lib, timestamp)) {
+ return true;
+ }
+ }
+
+ for (File importedJackFiles : options.getJayceImport()) {
+ if (isModifiedLibrary(importedJackFiles, timestamp)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isModifiedLibrary(@Nonnull File inputLibrary, long timestamp) {
+ if (inputLibrary.isFile() && (inputLibrary.lastModified() > timestamp)) {
+ return true;
+ } else if (inputLibrary.isDirectory() && hasModifiedFile(inputLibrary, timestamp)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean hasModifiedFile(@Nonnull File inputLibrary, long timestamp) {
+ assert inputLibrary.isDirectory();
+
+ for (File f : inputLibrary.listFiles()) {
+ if (f.isDirectory()) {
+ if (hasModifiedFile(f, timestamp)) {
+ return true;
+ }
+ } else if (f.lastModified() > timestamp) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Nonnull
+ private List<String> getDependencyFileNamesToRecompile(
+ @Nonnull Map<String, Set<String>> typeRecompileDependencies,
+ @Nonnull String modifiedJavaFileName) {
+ List<String> fileNamesToRecompile = new ArrayList<String>();
+ Set<String> deleteFileNames = getDeleteFileNames();
+
+ assert fileDependencies != null;
+ for (String modifiedTypeName : fileDependencies.getTypeNames(modifiedJavaFileName)) {
+ for (String typeName : typeRecompileDependencies.get(modifiedTypeName)) {
+ String dependentFileName = fileDependencies.getJavaFileName(typeName);
+ if (dependentFileName != null && !deleteFileNames.contains(dependentFileName)) {
+ fileNamesToRecompile.add(dependentFileName);
+ }
+ }
+ }
+
+ return fileNamesToRecompile;
+ }
+
+ @CheckForNull
+ private InputJackLibrary getIncrementalInternalLibrary() {
+ try {
+ return JackLibraryFactory.getInputLibrary(
+ ThreadConfig.get(Options.INTERNAL_LIBRARY_OUTPUT_DIR));
+ } catch (NotJackLibraryException e) {
+ // No incremental internal library, it is the first compilation
+ } catch (LibraryVersionException e) {
+ // Incremental internal library has changed, do not reuse it
+ } catch (LibraryFormatException e) {
+ // Incremental internal library has changed, do not reuse it
+ }
+ return null;
+ }
+
+ @Nonnull
+ private Set<String> getAddedFileNames() {
+ assert fileDependencies != null;
+ Set<String> addedFileNames = new HashSet<String>();
+ Set<String> previousFiles = fileDependencies.getCompiledJavaFiles();
+
+ for (String javaFileName : fileNamesOnCmdLine) {
+ if (!previousFiles.contains(javaFileName)) {
+ addedFileNames.add(javaFileName);
+ }
+ }
+
+ return addedFileNames;
+ }
+
+ @Nonnull
+ private Set<String> getModifiedFileNames() {
+ assert fileDependencies != null;
+ Set<String> modifiedFileNames = new HashSet<String>();
+
+ for (String javaFileName : fileDependencies.getCompiledJavaFiles()) {
+ if (fileNamesOnCmdLine.contains(javaFileName)) {
+ File javaFile = new File(javaFileName);
+ for (String typeName : fileDependencies.getTypeNames(javaFileName)) {
+ File dexFile = getDexFile(typeName);
+ if (!dexFile.exists() || ((javaFile.lastModified() > dexFile.lastModified()))) {
+ modifiedFileNames.add(javaFileName);
+ }
+ }
+ }
+ }
+
+ return modifiedFileNames;
+ }
+
+
+ @Nonnull
+ private Set<String> getDeleteFileNames() {
+ assert fileDependencies != null;
+ Set<String> deletedFileNames = new HashSet<String>();
+
+ for (String javaFileName : fileDependencies.getCompiledJavaFiles()) {
+ if (!fileNamesOnCmdLine.contains(javaFileName)) {
+ deletedFileNames.add(javaFileName);
+ }
+ }
+
+ return deletedFileNames;
+ }
+
+ @Nonnull
+ private File getDexFile(@Nonnull String typeName) {
+ return new File(options.getIncrementalFolder(), FileType.DEX.buildFileVPath(
+ new VPath(typeName, '/')).getPathAsString(File.separatorChar));
+ }
+
+ @Nonnull
+ private FileDependencies getFileDependencies(@Nonnull InputJackLibrary library)
+ throws CannotReadException, FileTypeDoesNotExistException {
+ InputVFile fileDependenciesVFile =
+ library.getFile(FileType.DEPENDENCIES, FileDependencies.vpath);
+
+
+ FileDependencies fileDependencies = new FileDependencies();
+ InputStreamReader fileReader = null;
+ try {
+ fileReader = new InputStreamReader(fileDependenciesVFile.openRead());
+ fileDependencies.read(fileReader);
+ } catch (IOException e) {
+ throw new CannotReadException(fileDependenciesVFile.getLocation(), e);
+ } finally {
+ if (fileReader != null) {
+ try {
+ fileReader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ return fileDependencies;
+ }
+
+ @Nonnull
+ private TypeDependencies getTypeDependencies(@Nonnull InputJackLibrary library)
+ throws CannotReadException, FileTypeDoesNotExistException {
+ InputVFile typeDependenciesVFile =
+ library.getFile(FileType.DEPENDENCIES, TypeDependencies.vpath);
+
+ TypeDependencies typeDependencies = new TypeDependencies();
+ InputStreamReader fileReader = null;
+ try {
+ fileReader = new InputStreamReader(typeDependenciesVFile.openRead());
+ typeDependencies.read(fileReader);
+ } catch (IOException e) {
+ throw new CannotReadException(typeDependenciesVFile.getLocation(), e);
+ } finally {
+ if (fileReader != null) {
+ try {
+ fileReader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ return typeDependencies;
+ }
+
+}
diff --git a/jack/src/com/android/jack/incremental/InputFilter.java b/jack/src/com/android/jack/incremental/InputFilter.java
new file mode 100644
index 0000000..c41b81e
--- /dev/null
+++ b/jack/src/com/android/jack/incremental/InputFilter.java
@@ -0,0 +1,34 @@
+/*
+ * 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.incremental;
+
+import java.io.File;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Interface that filter some inputs of Jack.
+ */
+public interface InputFilter {
+
+ @Nonnull
+ public List<String> getFileNamesToCompile();
+
+ @Nonnull
+ public List<File> getClasspath();
+}
diff --git a/jack/src/com/android/jack/incremental/NoInputFilter.java b/jack/src/com/android/jack/incremental/NoInputFilter.java
new file mode 100644
index 0000000..d8203a3
--- /dev/null
+++ b/jack/src/com/android/jack/incremental/NoInputFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.incremental;
+
+import com.android.jack.Jack;
+import com.android.jack.Options;
+import com.android.jack.analysis.dependency.file.FileDependencies;
+import com.android.jack.analysis.dependency.type.TypeDependencies;
+import com.android.sched.util.codec.ImplementationName;
+
+import java.io.File;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+/**
+ * {@link InputFilter} that returns unfiltered inputs.
+ */
+@ImplementationName(iface = InputFilter.class, name = "no-filter")
+public class NoInputFilter extends CommonFilter implements InputFilter {
+
+ @Nonnull
+ private final List<String> fileNamesToCompile;
+
+ @Nonnull
+ private final Options options;
+
+ public NoInputFilter(@Nonnull Options options) {
+ this.options = options;
+ this.fileNamesToCompile = getJavaFileNamesSpecifiedOnCommandLine(options);
+ }
+
+ @Override
+ @Nonnull
+ public List<String> getFileNamesToCompile() {
+ return fileNamesToCompile;
+ }
+
+ @Override
+ @Nonnull
+ public List<File> getClasspath() {
+ Jack.getSession().setFileDependencies(new FileDependencies());
+ Jack.getSession().setTypeDependencies(new TypeDependencies());
+ return options.getClasspath();
+ }
+}
diff --git a/jack/src/com/android/jack/ir/ast/JSession.java b/jack/src/com/android/jack/ir/ast/JSession.java
index 83abb3b..0032093 100644
--- a/jack/src/com/android/jack/ir/ast/JSession.java
+++ b/jack/src/com/android/jack/ir/ast/JSession.java
@@ -21,6 +21,7 @@ import com.google.common.collect.Iterators;
import com.android.jack.Jack;
import com.android.jack.analysis.dependency.file.FileDependencies;
import com.android.jack.analysis.dependency.type.TypeDependencies;
+import com.android.jack.incremental.InputFilter;
import com.android.jack.ir.JNodeInternalError;
import com.android.jack.ir.ast.JPrimitiveType.JPrimitiveTypeEnum;
import com.android.jack.ir.sourceinfo.SourceInfo;
@@ -112,6 +113,9 @@ public class JSession extends JNode {
@CheckForNull
private FileDependencies fileDependencies;
+ @CheckForNull
+ private InputFilter inputFilter;
+
public JSession() {
super(SourceInfo.UNKNOWN);
topLevelPackage = new JPackage("", this, null);
@@ -121,6 +125,18 @@ public class JSession extends JNode {
}
@Nonnull
+ public InputFilter getInputFilter() {
+ assert inputFilter != null;
+ return inputFilter;
+ }
+
+ @Nonnull
+ public void setInputFilter(@Nonnull InputFilter inputFilter) {
+ this.inputFilter = inputFilter;
+ }
+
+
+ @Nonnull
public JNodeLookup getLookup() {
return lookup;
}
diff --git a/jack/src/com/android/jack/library/FileType.java b/jack/src/com/android/jack/library/FileType.java
index 7d62ec2..0bd0578 100644
--- a/jack/src/com/android/jack/library/FileType.java
+++ b/jack/src/com/android/jack/library/FileType.java
@@ -29,22 +29,22 @@ import javax.annotation.Nonnull;
public enum FileType {
DEX("dex", "dex", ".dex", "dex") {
@Override
- public void check() throws LibraryFormatException {
+ public void check() {
}
},
JAYCE("jayce", "jayce", ".jayce", "jayce") {
@Override
- public void check() throws LibraryFormatException {
+ public void check() {
}
},
JPP("jpp", "jpp", ".jpp", "java pre-processor") {
@Override
- public void check() throws LibraryFormatException {
+ public void check() {
}
},
RSC("rsc", "rsc", "", "resource") {
@Override
- public void check() throws LibraryFormatException {
+ public void check() {
}
},
DEPENDENCIES("dependencies", "dependencies", ".dep", "dependencies") {
@@ -53,7 +53,7 @@ public enum FileType {
return "dependencies";
}
@Override
- public void check() throws LibraryFormatException {
+ public void check() {
}
};
diff --git a/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java b/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java
index e704a86..3c740a9 100644
--- a/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java
+++ b/jack/tests/com/android/jack/experimental/incremental/IncrementalTestingEnvironment.java
@@ -16,6 +16,7 @@
package com.android.jack.experimental.incremental;
+import com.android.jack.Jack;
import com.android.jack.Options;
import com.android.jack.TestTools;
import com.android.jack.backend.dex.DexFileWriter;
@@ -275,6 +276,6 @@ public class IncrementalTestingEnvironment extends TestTools {
addFile(sourceFolderOrSourceList, options.getEcjArguments());
options.setClasspath(classpath);
options.setOutputDir(out);
- JackIncremental.run(options);
+ Jack.run(options);
}
}