Eagerly read the full file contents during include scanning
This is slightly more efficient than the current hand-rolled implementation, especially
the line-by-line reading of pre-grepped files.
RELNOTES: None.
PiperOrigin-RevId: 293979591
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java
index 1e674b6..11d999d 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeParser.java
@@ -59,6 +59,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -685,41 +686,65 @@
'a', Kind.NEXT_ANGLE);
/**
- * Processes the output generated by an auxiliary include-scanning binary. Closes the stream upon
- * completion.
+ * Processes the output generated by an auxiliary include-scanning binary.
*
* <p>If a source file has the following include statements:
+ *
* <pre>
* #include <string>
* #include "directory/header.h"
* </pre>
*
* <p>Then the output file has the following contents:
+ *
* <pre>
* "directory/header.h
* <string
* </pre>
+ *
* <p>Each line of the output is translated into an Inclusion object.
*/
- public static List<Inclusion> processIncludes(Object streamName, InputStream is)
- throws IOException {
+ private static List<Inclusion> processIncludes(List<String> lines) throws IOException {
List<Inclusion> inclusions = new ArrayList<>();
- try (InputStreamReader reader = new InputStreamReader(is, ISO_8859_1)) {
- for (String line : CharStreams.readLines(reader)) {
- char qchar = line.charAt(0);
- String name = line.substring(1);
- Kind kind = KIND_MAP.get(qchar);
- if (kind == null) {
- throw new IOException("Illegal inclusion kind '" + qchar + "'");
- }
- inclusions.add(new Inclusion(name, kind));
+ for (String line : lines) {
+ if (line.isEmpty()) {
+ continue;
}
- } catch (IOException e) {
- throw new IOException("Error reading include file " + streamName + ": " + e.getMessage());
+ char qchar = line.charAt(0);
+ String name = line.substring(1);
+ Kind kind = KIND_MAP.get(qchar);
+ if (kind == null) {
+ throw new IOException("Illegal inclusion kind '" + qchar + "'");
+ }
+ inclusions.add(new Inclusion(name, kind));
}
return inclusions;
}
+ /** Processes the output generated by an auxiliary include-scanning binary stored in a file. */
+ public static List<Inclusion> processIncludes(Path file) throws IOException {
+ try {
+ byte[] data = FileSystemUtils.readContent(file);
+ return IncludeParser.processIncludes(Arrays.asList(new String(data, ISO_8859_1).split("\n")));
+ } catch (IOException e) {
+ throw new IOException("Error reading include file " + file + ": " + e.getMessage());
+ }
+ }
+
+ /**
+ * Processes the output generated by an auxiliary include-scanning binary read from a stream.
+ * Closes the stream upon completion.
+ */
+ public static List<Inclusion> processIncludes(Object streamName, InputStream is)
+ throws IOException {
+ try (InputStreamReader reader = new InputStreamReader(is, ISO_8859_1)) {
+ return processIncludes(CharStreams.readLines(reader));
+ } catch (IOException e) {
+ throw new IOException("Error reading include file " + streamName + ": " + e.getMessage());
+ }
+ }
+
+
@VisibleForTesting
Inclusion extractInclusion(String line) {
return extractInclusion(line.getBytes(ISO_8859_1), 0, line.length());
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java b/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
index 6252111..c666498 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/SpawnIncludeScanner.java
@@ -312,8 +312,9 @@
actionExecutionContext,
grepIncludes,
fileType);
- return IncludeParser.processIncludes(
- output, dotIncludeStream == null ? output.getInputStream() : dotIncludeStream);
+ return dotIncludeStream == null
+ ? IncludeParser.processIncludes(output)
+ : IncludeParser.processIncludes(output, dotIncludeStream);
}
/**