From 0410e2b1f1bb2cfc8a10db2c6fe21dc1a3c1a691 Mon Sep 17 00:00:00 2001 From: Gunnar Wagenknecht Date: Wed, 16 Aug 2023 14:02:07 +0200 Subject: [PATCH] New option '-Xecj_collect_used_deps' which allows to control jdeps file -Xecj_collect_used_deps=all (default) collect information about direct as well as transitive dependencies into jdeps -Xecj_collect_used_deps=direct_only collect only information about direct dependencies into jdeps -Xecj_collect_used_deps=none don't collect any used dependency information into jdeps --- .../build/buildjar/javac/BlazeEcjMain.java | 93 +++++++++++++------ 1 file changed, 65 insertions(+), 28 deletions(-) diff --git a/compiler/src/main/buildjar/com/google/devtools/build/buildjar/javac/BlazeEcjMain.java b/compiler/src/main/buildjar/com/google/devtools/build/buildjar/javac/BlazeEcjMain.java index 70c14b6..01beb63 100644 --- a/compiler/src/main/buildjar/com/google/devtools/build/buildjar/javac/BlazeEcjMain.java +++ b/compiler/src/main/buildjar/com/google/devtools/build/buildjar/javac/BlazeEcjMain.java @@ -66,6 +66,25 @@ */ public class BlazeEcjMain { + static enum UsedDependencyCollectionMode { All, DirectOnly, None; + + static UsedDependencyCollectionMode fromOptionValue(String value) { + if (value != null) { + switch (value) { + case "all": + return All; + case "direct_only": + return DirectOnly; + case "none": + return None; + default: + throw new IllegalArgumentException("Unknown option value for -Xecj_collect_used_deps: " + value); + } + } + return All; // default to all + } + } + static class BlazeEclipseBatchCompiler extends Main { final AnnotationProcessingModule processingModule; @@ -76,11 +95,13 @@ static class BlazeEclipseBatchCompiler extends Main { final ImmutableSet directJars; final Map directDependenciesMap; final Map noneDirectDependenciesMap; + final UsedDependencyCollectionMode usedDependencyCollectionMode; public BlazeEclipseBatchCompiler(PrintWriter outWriter, PrintWriter errWriter, - ImmutableList plugins, String sandboxPathPrefix, Map sourceFilesByAbsoluteOrCanonicalPath) { + ImmutableList plugins, String sandboxPathPrefix, Map sourceFilesByAbsoluteOrCanonicalPath, UsedDependencyCollectionMode usedDependencyCollectionMode) { super(outWriter, errWriter, false /* systemExitWhenFinished */, null /* customDefaultOptions */, null /* compilationProgress */); + this.usedDependencyCollectionMode = usedDependencyCollectionMode; this.sandboxPathPrefix = Path.of(sandboxPathPrefix); this.sourceFilesByAbsoluteOrCanonicalPath = sourceFilesByAbsoluteOrCanonicalPath; this.processingModule = ((AnnotationProcessingPlugin) plugins.stream() @@ -181,31 +202,33 @@ protected void recordNameEnvironmentAnswer(ClasspathAnswer classpathAnswer) { jarPath = sandboxPathPrefix.relativize(jarPath); // update the dependency proto - if(directJars.contains(jarPath)) { - if (!directDependenciesMap.containsKey(jarPath)) { - Dependency dep = - Dependency.newBuilder() - // Path.toString uses the platform separator (`\` on Windows) which may not - // match the format in params files (which currently always use `/`, see - // bazelbuild/bazel#4108). JavaBuilder should always parse Path strings into - // java.nio.file.Paths before comparing them. - .setPath(jarPath.toString()) - .setKind(Dependency.Kind.EXPLICIT) - .build(); - directDependenciesMap.put(jarPath, dep); - } - } else { - if (!noneDirectDependenciesMap.containsKey(jarPath)) { - Dependency dep = - Dependency.newBuilder() - // Path.toString uses the platform separator (`\` on Windows) which may not - // match the format in params files (which currently always use `/`, see - // bazelbuild/bazel#4108). JavaBuilder should always parse Path strings into - // java.nio.file.Paths before comparing them. - .setPath(jarPath.toString()) - .setKind(Dependency.Kind.IMPLICIT) - .build(); - noneDirectDependenciesMap.put(jarPath, dep); + if(usedDependencyCollectionMode != UsedDependencyCollectionMode.None) { + if(directJars.contains(jarPath)) { + if ((usedDependencyCollectionMode == UsedDependencyCollectionMode.All || usedDependencyCollectionMode == UsedDependencyCollectionMode.DirectOnly) && !directDependenciesMap.containsKey(jarPath)) { + Dependency dep = + Dependency.newBuilder() + // Path.toString uses the platform separator (`\` on Windows) which may not + // match the format in params files (which currently always use `/`, see + // bazelbuild/bazel#4108). JavaBuilder should always parse Path strings into + // java.nio.file.Paths before comparing them. + .setPath(jarPath.toString()) + .setKind(Dependency.Kind.EXPLICIT) + .build(); + directDependenciesMap.put(jarPath, dep); + } + } else { + if (usedDependencyCollectionMode == UsedDependencyCollectionMode.All && !noneDirectDependenciesMap.containsKey(jarPath)) { + Dependency dep = + Dependency.newBuilder() + // Path.toString uses the platform separator (`\` on Windows) which may not + // match the format in params files (which currently always use `/`, see + // bazelbuild/bazel#4108). JavaBuilder should always parse Path strings into + // java.nio.file.Paths before comparing them. + .setPath(jarPath.toString()) + .setKind(Dependency.Kind.IMPLICIT) + .build(); + noneDirectDependenciesMap.put(jarPath, dep); + } } } } @@ -258,8 +281,7 @@ public static BlazeJavacResult compile(BlazeJavacArguments arguments) { StringWriter errOutput = new StringWriter(); PrintWriter errWriter = new PrintWriter(errOutput); - - BlazeEclipseBatchCompiler compiler = new BlazeEclipseBatchCompiler(errWriter, errWriter, arguments.plugins(), sandboxPathPrefix, sourceFilesByAbsoluteOrCanonicalPath); + BlazeEclipseBatchCompiler compiler = new BlazeEclipseBatchCompiler(errWriter, errWriter, arguments.plugins(), sandboxPathPrefix, sourceFilesByAbsoluteOrCanonicalPath, UsedDependencyCollectionMode.fromOptionValue(getJavacOptionValue(arguments.javacOptions(), "-Xecj_collect_used_deps"))); List ecjArguments = new ArrayList<>(); setLocations(ecjArguments, arguments, compiler.dependencyModule); @@ -328,6 +350,21 @@ public static BlazeJavacResult compile(BlazeJavacArguments arguments) { builder.build()); } +private static String getJavacOptionValue(List javacOptions, String optionName) { + for (int i = 0; i < javacOptions.size(); i++) { + String option = javacOptions.get(i); + if(option.startsWith(optionName)) { + int separatorPos = option.indexOf('='); + if(separatorPos == -1 && javacOptions.size() > i+1) { + return javacOptions.get(i+1); + } else { + return option.substring(separatorPos+1).trim(); + } + } + } + return null; +} + private static String detectWorkingDirPathPrefix(BlazeJavacArguments arguments) throws IOException { // since the JDT compiler is executed from within the sandbox, the absolute path will be resolved to the working directory // we simple remove the working directory