public static int parseAndWriteBuckCompatibleDepfile( ExecutionContext context, ProjectFilesystem filesystem, HeaderPathNormalizer headerPathNormalizer, HeaderVerification headerVerification, Path sourceDepFile, Path destDepFile, Path inputPath, Path outputPath) throws IOException { // Process the dependency file, fixing up the paths, and write it out to it's final location. // The paths of the headers written out to the depfile are the paths to the symlinks from the // root of the repo if the compilation included them from the header search paths pointing to // the symlink trees, or paths to headers relative to the source file if the compilation // included them using source relative include paths. To handle both cases we check for the // prerequisites both in the values and the keys of the replacement map. Logger.get(Depfiles.class).debug("Processing dependency file %s as Makefile", sourceDepFile); ImmutableMap<String, Object> params = ImmutableMap.<String, Object>of("input", inputPath, "output", outputPath); try (InputStream input = filesystem.newFileInputStream(sourceDepFile); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); OutputStream output = filesystem.newFileOutputStream(destDepFile); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output)); SimplePerfEvent.Scope perfEvent = SimplePerfEvent.scope( context.getBuckEventBus(), PerfEventId.of("depfile-parse"), params)) { ImmutableList<String> prereqs = Depfiles.parseDepfile(reader).getPrereqs(); // Skip the first prereq, as it's the input source file. Preconditions.checkState(inputPath.toString().equals(prereqs.get(0))); ImmutableList<String> headers = prereqs.subList(1, prereqs.size()); for (String rawHeader : headers) { Path header = Paths.get(rawHeader).normalize(); Optional<Path> absolutePath = headerPathNormalizer.getAbsolutePathForUnnormalizedPath(header); if (absolutePath.isPresent()) { Preconditions.checkState(absolutePath.get().isAbsolute()); writer.write(absolutePath.get().toString()); writer.newLine(); } else if (headerVerification.getMode() != HeaderVerification.Mode.IGNORE && !headerVerification.isWhitelisted(header.toString())) { context .getBuckEventBus() .post( ConsoleEvent.create( headerVerification.getMode() == HeaderVerification.Mode.ERROR ? Level.SEVERE : Level.WARNING, "%s: included an untracked header \"%s\"", inputPath, header)); if (headerVerification.getMode() == HeaderVerification.Mode.ERROR) { return 1; } } } } return 0; }