Report errors for non-existant flag files correctly.
Additionally, fix the contents of the flags file for the tests.
This worked by accident on Linux but is incorrect and doesn't
work on Windows.
R=sgjesse@google.com, zerny@google.com
Change-Id: I1e67db038d65c739808daff927a13aabdbba32d0
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 250f2e9..1db187e 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.ExceptionUtils;
-import com.android.tools.r8.utils.FlagFile;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
@@ -94,9 +93,8 @@
});
}
- private static void run(String[] args) throws CompilationFailedException, IOException {
- String[] expandedArgs = FlagFile.expandFlagFiles(args);
- D8Command command = D8Command.parse(expandedArgs, CommandLineOrigin.INSTANCE).build();
+ private static void run(String[] args) throws CompilationFailedException {
+ D8Command command = D8Command.parse(args, CommandLineOrigin.INSTANCE).build();
if (command.isPrintHelp()) {
System.out.println(USAGE_MESSAGE);
return;
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 4c65134..6f956db 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.FlagFile;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
@@ -215,9 +216,10 @@
Path outputPath = null;
OutputMode outputMode = null;
boolean hasDefinedApiLevel = false;
+ String[] expandedArgs = FlagFile.expandFlagFiles(args, builder.getReporter());
try {
- for (int i = 0; i < args.length; i++) {
- String arg = args[i].trim();
+ for (int i = 0; i < expandedArgs.length; i++) {
+ String arg = expandedArgs[i].trim();
if (arg.length() == 0) {
continue;
} else if (arg.equals("--help")) {
@@ -243,7 +245,7 @@
} else if (arg.equals("--file-per-class")) {
outputMode = OutputMode.DexFilePerClassFile;
} else if (arg.equals("--output")) {
- String output = args[++i];
+ String output = expandedArgs[++i];
if (outputPath != null) {
builder.getReporter().error(new StringDiagnostic(
"Cannot output both to '" + outputPath.toString() + "' and '" + output + "'",
@@ -252,15 +254,15 @@
}
outputPath = Paths.get(output);
} else if (arg.equals("--lib")) {
- builder.addLibraryFiles(Paths.get(args[++i]));
+ builder.addLibraryFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--classpath")) {
- builder.addClasspathFiles(Paths.get(args[++i]));
+ builder.addClasspathFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--main-dex-list")) {
- builder.addMainDexListFiles(Paths.get(args[++i]));
+ builder.addMainDexListFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--optimize-multidex-for-linearalloc")) {
builder.setOptimizeMultidexForLinearAlloc(true);
} else if (arg.equals("--min-api")) {
- hasDefinedApiLevel = parseMinApi(builder, args[++i], hasDefinedApiLevel, origin);
+ hasDefinedApiLevel = parseMinApi(builder, expandedArgs[++i], hasDefinedApiLevel, origin);
} else if (arg.equals("--intermediate")) {
builder.setIntermediate(true);
} else if (arg.equals("--no-desugaring")) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 8e1722e..16c9de8 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -51,7 +51,6 @@
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.FileUtils;
-import com.android.tools.r8.utils.FlagFile;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.android.tools.r8.utils.LineNumberOptimizer;
@@ -534,9 +533,8 @@
}
}
- private static void run(String[] args) throws CompilationFailedException, IOException {
- String[] expandedArgs = FlagFile.expandFlagFiles(args);
- R8Command command = R8Command.parse(expandedArgs, CommandLineOrigin.INSTANCE).build();
+ private static void run(String[] args) throws CompilationFailedException {
+ R8Command command = R8Command.parse(args, CommandLineOrigin.INSTANCE).build();
if (command.isPrintHelp()) {
System.out.println(USAGE_MESSAGE);
return;
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index ced17d4..4fc0590 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.FlagFile;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.android.tools.r8.utils.Reporter;
@@ -513,8 +514,9 @@
Origin argsOrigin,
Builder builder,
ParseState state) {
- for (int i = 0; i < args.length; i++) {
- String arg = args[i].trim();
+ String[] expandedArgs = FlagFile.expandFlagFiles(args, builder.getReporter());
+ for (int i = 0; i < expandedArgs.length; i++) {
+ String arg = expandedArgs[i].trim();
if (arg.length() == 0) {
continue;
} else if (arg.equals("--help")) {
@@ -546,7 +548,7 @@
}
state.outputMode = OutputMode.ClassFile;
} else if (arg.equals("--output")) {
- String outputPath = args[++i];
+ String outputPath = expandedArgs[++i];
if (state.outputPath != null) {
builder.getReporter().error(new StringDiagnostic(
"Cannot output both to '"
@@ -558,10 +560,10 @@
}
state.outputPath = Paths.get(outputPath);
} else if (arg.equals("--lib")) {
- builder.addLibraryFiles(Paths.get(args[++i]));
+ builder.addLibraryFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--min-api")) {
state.hasDefinedApiLevel =
- parseMinApi(builder, args[++i], state.hasDefinedApiLevel, argsOrigin);
+ parseMinApi(builder, expandedArgs[++i], state.hasDefinedApiLevel, argsOrigin);
} else if (arg.equals("--no-tree-shaking")) {
builder.setDisableTreeShaking(true);
} else if (arg.equals("--no-minification")) {
@@ -569,17 +571,17 @@
} else if (arg.equals("--no-desugaring")) {
builder.setDisableDesugaring(true);
} else if (arg.equals("--main-dex-rules")) {
- builder.addMainDexRulesFiles(Paths.get(args[++i]));
+ builder.addMainDexRulesFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--main-dex-list")) {
- builder.addMainDexListFiles(Paths.get(args[++i]));
+ builder.addMainDexListFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--main-dex-list-output")) {
- builder.setMainDexListOutputPath(Paths.get(args[++i]));
+ builder.setMainDexListOutputPath(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--optimize-multidex-for-linearalloc")) {
builder.setOptimizeMultidexForLinearAlloc(true);
} else if (arg.equals("--pg-conf")) {
- builder.addProguardConfigurationFiles(Paths.get(args[++i]));
+ builder.addProguardConfigurationFiles(Paths.get(expandedArgs[++i]));
} else if (arg.equals("--pg-map-output")) {
- builder.setProguardMapOutputPath(Paths.get(args[++i]));
+ builder.setProguardMapOutputPath(Paths.get(expandedArgs[++i]));
} else {
if (arg.startsWith("--")) {
builder.getReporter().error(new StringDiagnostic("Unknown option: " + arg, argsOrigin));
diff --git a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
index 577632a..9c7f525 100644
--- a/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ExceptionUtils.java
@@ -74,7 +74,7 @@
}
public interface MainAction {
- void run() throws CompilationFailedException, IOException;
+ void run() throws CompilationFailedException;
}
public static void withMainProgramHandler(MainAction action) {
@@ -84,7 +84,7 @@
// Detail of the errors were already reported
System.err.println("Compilation failed");
System.exit(STATUS_ERROR);
- } catch (RuntimeException | IOException e) {
+ } catch (RuntimeException e) {
System.err.println("Compilation failed with an internal error.");
Throwable cause = e.getCause() == null ? e : e.getCause();
cause.printStackTrace();
diff --git a/src/main/java/com/android/tools/r8/utils/FlagFile.java b/src/main/java/com/android/tools/r8/utils/FlagFile.java
index 2354066..4791217 100644
--- a/src/main/java/com/android/tools/r8/utils/FlagFile.java
+++ b/src/main/java/com/android/tools/r8/utils/FlagFile.java
@@ -4,18 +4,41 @@
package com.android.tools.r8.utils;
+import com.android.tools.r8.origin.Origin;
import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class FlagFile {
- public static String[] expandFlagFiles(String[] args) throws IOException {
+
+ private static class FlagFileOrigin extends Origin {
+ private final Path path;
+
+ protected FlagFileOrigin(Path path) {
+ super(Origin.root());
+ this.path = path;
+ }
+
+ @Override
+ public String part() {
+ return "flag file argument: '@" + path + "'";
+ }
+ }
+
+ public static String[] expandFlagFiles(String[] args, Reporter reporter) {
List<String> flags = new ArrayList<>(args.length);
for (String arg : args) {
if (arg.startsWith("@")) {
- flags.addAll(Files.readAllLines(Paths.get(arg.substring(1))));
+ Path flagFilePath = Paths.get(arg.substring(1));
+ try {
+ flags.addAll(Files.readAllLines(flagFilePath));
+ } catch (IOException e) {
+ Origin origin = new FlagFileOrigin(flagFilePath);
+ reporter.error(new ExceptionDiagnostic(e, origin));
+ }
} else {
flags.add(arg);
}
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 5576058..1b846a5 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -9,6 +9,7 @@
import static java.nio.file.StandardOpenOption.CREATE_NEW;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import com.android.sdklib.AndroidVersion;
@@ -99,7 +100,7 @@
FileUtils.writeTextFile(
flagsFile,
"--output",
- output.toString(),
+ "output.zip",
"--min-api",
"24",
input.toString());
@@ -110,6 +111,19 @@
assertEquals(Tool.D8, marker.getTool());
}
+ @Test(expected=CompilationFailedException.class)
+ public void nonExistingFlagsFile() throws Throwable {
+ Path working = temp.getRoot().toPath();
+ Path flags = working.resolve("flags.txt").toAbsolutePath();
+ assertNotEquals(0, ToolHelper.forkR8(working, "@flags.txt").exitCode);
+ DiagnosticsChecker.checkErrorsContains("File not found", handler ->
+ D8.run(
+ D8Command.parse(
+ new String[] { "@" + flags.toString() },
+ EmbeddedOrigin.INSTANCE,
+ handler).build()));
+ }
+
@Test
public void printsHelpOnNoInput() throws Throwable {
ProcessResult result = ToolHelper.forkD8(temp.getRoot().toPath());
diff --git a/src/test/java/com/android/tools/r8/DiagnosticsChecker.java b/src/test/java/com/android/tools/r8/DiagnosticsChecker.java
index 2265c3e..2f45ae2 100644
--- a/src/test/java/com/android/tools/r8/DiagnosticsChecker.java
+++ b/src/test/java/com/android/tools/r8/DiagnosticsChecker.java
@@ -49,13 +49,14 @@
try {
runner.run(handler);
} catch (CompilationFailedException e) {
+ List<String> messages = ListUtils.map(handler.errors, Diagnostic::getDiagnosticMessage);
System.out.println("Expecting match for '" + snippet + "'");
- System.out.println("StdErr:\n" + handler.errors);
+ System.out.println("StdErr:\n" + messages);
assertTrue(
"Expected to find snippet '"
+ snippet
+ "' in error messages:\n"
- + String.join("\n", ListUtils.map(handler.errors, Diagnostic::getDiagnosticMessage)),
+ + String.join("\n", messages),
handler.errors.stream().anyMatch(d -> d.getDiagnosticMessage().contains(snippet)));
throw e;
}
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index c1072bd..fbd88be 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -101,7 +101,7 @@
FileUtils.writeTextFile(
flagsFile,
"--output",
- output.toString(),
+ "output.zip",
"--min-api",
"24",
"--lib",
@@ -114,6 +114,20 @@
assertEquals(Tool.R8, marker.getTool());
}
+
+ @Test(expected=CompilationFailedException.class)
+ public void nonExistingFlagsFile() throws Throwable {
+ Path working = temp.getRoot().toPath();
+ Path flags = working.resolve("flags.txt").toAbsolutePath();
+ assertNotEquals(0, ToolHelper.forkR8(working, "@flags.txt").exitCode);
+ DiagnosticsChecker.checkErrorsContains("File not found", handler ->
+ R8.run(
+ R8Command.parse(
+ new String[] { "@" + flags.toString() },
+ EmbeddedOrigin.INSTANCE,
+ handler).build()));
+ }
+
@Test
public void printsHelpOnNoInput() throws Throwable {
ProcessResult result = ToolHelper.forkR8(temp.getRoot().toPath());