Skip to content

Commit 3dd5d81

Browse files
authored
Create jdeps output from classpath entries (#1376)
* Create jdeps output from classpath entries Motivation: jdeps output is used by Intellij Bazel plugin to construct project model. Current implementation adds all entries as explicit source deps, does not do distinguish between implicit or unused deps.
1 parent d789f0a commit 3dd5d81

File tree

13 files changed

+144
-7
lines changed

13 files changed

+144
-7
lines changed

scala/private/common_outputs.bzl

+1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ common_outputs = {
66
"manifest": "%{name}_MANIFEST.MF",
77
"statsfile": "%{name}.statsfile",
88
"diagnosticsfile": "%{name}.diagnosticsproto",
9+
"jdeps": "%{name}.jdep",
910
}

scala/private/phases/phase_compile.bzl

+5-1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ def _compile_or_empty(
193193
manifest,
194194
ctx.outputs.statsfile,
195195
ctx.outputs.diagnosticsfile,
196+
ctx.outputs.jdeps,
196197
sources,
197198
jars,
198199
all_srcjars,
@@ -269,6 +270,7 @@ rm -f {jar_output}
269270
# ensures that empty src targets still emit a statsfile and a diagnosticsfile
270271
touch {statsfile}
271272
touch {diagnosticsfile}
273+
touch {jdepsfile}
272274
""" + ijar_cmd
273275

274276
cmd = cmd.format(
@@ -277,9 +279,10 @@ touch {diagnosticsfile}
277279
zipper = ctx.executable._zipper.path,
278280
statsfile = ctx.outputs.statsfile.path,
279281
diagnosticsfile = ctx.outputs.diagnosticsfile.path,
282+
jdepsfile = ctx.outputs.jdeps.path,
280283
)
281284

282-
outs = [ctx.outputs.jar, ctx.outputs.statsfile, ctx.outputs.diagnosticsfile]
285+
outs = [ctx.outputs.jar, ctx.outputs.statsfile, ctx.outputs.diagnosticsfile, ctx.outputs.jdeps]
283286
inputs = ctx.files.resources + [ctx.outputs.manifest]
284287

285288
ctx.actions.run_shell(
@@ -303,6 +306,7 @@ def _create_scala_compilation_provider(ctx, ijar, source_jar, deps_providers):
303306
compile_jar = ijar,
304307
source_jar = source_jar,
305308
deps = deps_providers,
309+
jdeps = ctx.outputs.jdeps,
306310
exports = exports,
307311
runtime_deps = runtime_deps,
308312
neverlink = ctx.attr.neverlink,

scala/private/rule_impls.bzl

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def compile_scala(
3939
manifest,
4040
statsfile,
4141
diagnosticsfile,
42+
jdepsPath,
4243
sources,
4344
cjars,
4445
all_srcjars,
@@ -79,6 +80,7 @@ def compile_scala(
7980
args.add("--Manifest", manifest)
8081
args.add("--PrintCompileTime", print_compile_time)
8182
args.add("--ExpectJavaOutput", expect_java_output)
83+
args.add("--JDepsFilePath", jdepsPath)
8284
args.add("--StrictDepsMode", dependency_info.strict_deps_mode)
8385
args.add("--UnusedDependencyCheckerMode", dependency_info.unused_deps_mode)
8486
args.add("--DependencyTrackingMethod", dependency_info.dependency_tracking_method)
@@ -109,7 +111,7 @@ def compile_scala(
109111
if dependency_info.unused_deps_mode != "off":
110112
args.add_all("--UnusedDepsIgnoredTargets", unused_dependency_checker_ignored_targets)
111113

112-
outs = [output, statsfile, diagnosticsfile]
114+
outs = [output, statsfile, diagnosticsfile, jdepsPath]
113115

114116
ins = depset(
115117
direct = [manifest] + sources + classpath_resources + resources + resource_jars,

scala_proto/private/scala_proto_aspect.bzl

+3
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def _compile_sources(ctx, toolchain, proto, src_jars, deps, stamp_label):
8989
write_manifest_file(ctx.actions, manifest, None)
9090
statsfile = ctx.actions.declare_file(ctx.label.name + "_scalac.statsfile")
9191
diagnosticsfile = ctx.actions.declare_file(ctx.label.name + "_scalac.diagnosticsproto")
92+
jdepsfile = ctx.actions.declare_file(ctx.label.name + ".jdeps")
9293
compile_deps = deps + _compile_deps(ctx, toolchain)
9394
merged_deps = java_common.merge(compile_deps)
9495

@@ -103,6 +104,7 @@ def _compile_sources(ctx, toolchain, proto, src_jars, deps, stamp_label):
103104
manifest,
104105
statsfile,
105106
diagnosticsfile,
107+
jdepsfile,
106108
sources = [],
107109
cjars = merged_deps.compile_jars,
108110
all_srcjars = depset(src_jars),
@@ -127,6 +129,7 @@ def _compile_sources(ctx, toolchain, proto, src_jars, deps, stamp_label):
127129
output_jar = output,
128130
compile_jar = output,
129131
deps = compile_deps,
132+
jdeps = jdepsfile,
130133
exports = compile_deps,
131134
runtime_deps = compile_deps,
132135
)
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
load("@rules_java//java:defs.bzl", "java_library")
2+
3+
java_library(
4+
name = "jdeps",
5+
srcs = ["JdepsWriter.java"],
6+
visibility = ["//visibility:public"],
7+
deps = [
8+
"@bazel_tools//src/main/protobuf:deps_java_proto",
9+
"@com_google_protobuf//:protobuf_java",
10+
],
11+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package io.bazel.rulesscala.jdeps;
2+
3+
import com.google.devtools.build.lib.view.proto.Deps;
4+
import java.io.BufferedOutputStream;
5+
import java.io.FileOutputStream;
6+
import java.io.IOException;
7+
import java.io.OutputStream;
8+
9+
public final class JdepsWriter {
10+
11+
private JdepsWriter() {
12+
}
13+
14+
public static void write(String jdpesPath, String currentTarget, String[] classpath)
15+
throws IOException {
16+
17+
Deps.Dependencies.Builder builder = Deps.Dependencies.newBuilder();
18+
builder.setSuccess(true);
19+
builder.setRuleLabel(currentTarget);
20+
21+
for (String jar : classpath) {
22+
Deps.Dependency.Builder dependencyBuilder = Deps.Dependency.newBuilder();
23+
dependencyBuilder.setKind(Deps.Dependency.Kind.EXPLICIT);
24+
dependencyBuilder.setPath(jar);
25+
builder.addDependency(dependencyBuilder.build());
26+
}
27+
28+
try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(jdpesPath))) {
29+
builder.build().writeTo(outputStream);
30+
}
31+
}
32+
33+
}

src/java/io/bazel/rulesscala/scalac/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ java_binary(
1515
deps = [
1616
"//scala/private/toolchain_deps:scala_compile_classpath",
1717
"//src/java/io/bazel/rulesscala/io_utils",
18+
"//src/java/io/bazel/rulesscala/jdeps",
1819
"//third_party/bazel/src/main/protobuf:worker_protocol_java_proto",
1920
"@io_bazel_rules_scala//src/java/io/bazel/rulesscala/jar",
2021
"@io_bazel_rules_scala//src/java/io/bazel/rulesscala/worker",

src/java/io/bazel/rulesscala/scalac/CompileOptions.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public class CompileOptions {
2424
public final String[] unusedDepsIgnoredTargets;
2525
public final String[] indirectJars;
2626
public final String[] indirectTargets;
27+
public final String jdepsFilePath;
2728
public final String strictDepsMode;
2829
public final String unusedDependencyCheckerMode;
2930
public final String currentTarget;
@@ -60,6 +61,7 @@ public CompileOptions(String[] lines) {
6061
indirectJars = args.getOrEmpty("IndirectJars");
6162
indirectTargets = args.getOrEmpty("IndirectTargets");
6263

64+
jdepsFilePath = args.getSingleOrError("JDepsFilePath");
6365
strictDepsMode = args.getSingleOrError("StrictDepsMode");
6466
unusedDependencyCheckerMode = args.getSingleOrError("UnusedDependencyCheckerMode");
6567
currentTarget = args.getSingleOrError("CurrentTarget");
@@ -75,7 +77,7 @@ public CompileOptions(String[] lines) {
7577

7678
static final class Args {
7779

78-
private static final String[] EMPTY = new String[] {};
80+
private static final String[] EMPTY = new String[]{};
7981
private final Map<String, String[]> index = new LinkedHashMap<>();
8082

8183
Args(String[] lines) {

src/java/io/bazel/rulesscala/scalac/ScalacWorker.java

+15-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,18 @@
44

55
import io.bazel.rulesscala.io_utils.StreamCopy;
66
import io.bazel.rulesscala.jar.JarCreator;
7+
import io.bazel.rulesscala.jdeps.JdepsWriter;
78
import io.bazel.rulesscala.worker.Worker;
8-
import java.io.*;
9-
import java.nio.file.*;
9+
import java.io.File;
10+
import java.io.FileOutputStream;
11+
import java.io.IOException;
12+
import java.io.InputStream;
13+
import java.io.OutputStream;
14+
import java.nio.file.FileVisitResult;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.nio.file.Paths;
18+
import java.nio.file.SimpleFileVisitor;
1019
import java.nio.file.attribute.BasicFileAttributes;
1120
import java.util.ArrayList;
1221
import java.util.Arrays;
@@ -61,6 +70,8 @@ public void work(String[] args) throws Exception {
6170
compileScalaSources(ops, scalaSources, classes);
6271
}
6372

73+
JdepsWriter.write(ops.jdepsFilePath, ops.currentTarget, ops.classpath);
74+
6475
/** Copy the resources */
6576
copyResources(ops.resourceSources, ops.resourceTargets, classes);
6677

@@ -95,7 +106,7 @@ private static String[] collectSrcJarSources(
95106
}
96107

97108
private static List<File> filterFilesByExtension(List<File> files, String extension) {
98-
List<File> filtered = new ArrayList<File>();
109+
List<File> filtered = new ArrayList<>();
99110
for (File f : files) {
100111
if (f.toString().endsWith(extension)) {
101112
filtered.add(f);
@@ -238,7 +249,7 @@ private static String[] getPluginParamsFrom(CompileOptions ops) {
238249
}
239250

240251
private static void compileScalaSources(CompileOptions ops, String[] scalaSources, Path classes)
241-
throws IllegalAccessException, IOException {
252+
throws IOException {
242253

243254
String[] pluginArgs = buildPluginArgs(ops.plugins);
244255
String[] pluginParams = getPluginParamsFrom(ops);

src/java/io/bazel/rulesscala/scalac/ScalacWorker3.java

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.bazel.rulesscala.scalac;
22

33
import static java.io.File.pathSeparator;
4+
5+
import io.bazel.rulesscala.jdeps.JdepsWriter;
46
import scala.Tuple2;
57
import io.bazel.rulesscala.io_utils.StreamCopy;
68
import io.bazel.rulesscala.jar.JarCreator;
@@ -76,6 +78,8 @@ public void work(String[] args) throws Exception {
7678
compileScalaSources(ops, scalaSources, tmpPath);
7779
}
7880

81+
JdepsWriter.write(ops.jdepsFilePath, ops.currentTarget, ops.classpath);
82+
7983
/** Copy the resources */
8084
copyResources(ops.resourceSources, ops.resourceTargets, tmpPath);
8185

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
load("@rules_java//java:defs.bzl", "java_test")
2+
3+
java_test(
4+
name = "jdeps",
5+
srcs = ["JdepsWriterTest.java"],
6+
test_class = "jdeps.JdepsWriterTest",
7+
deps = [
8+
"//src/java/io/bazel/rulesscala/jdeps",
9+
"@bazel_tools//src/main/protobuf:deps_java_proto",
10+
"@com_google_protobuf//:protobuf_java",
11+
"@io_bazel_rules_scala_junit_junit",
12+
],
13+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package jdeps;
2+
3+
import static org.junit.Assert.assertArrayEquals;
4+
5+
import com.google.devtools.build.lib.view.proto.Deps;
6+
import com.google.devtools.build.lib.view.proto.Deps.Dependency;
7+
import io.bazel.rulesscala.jdeps.JdepsWriter;
8+
import java.io.BufferedInputStream;
9+
import java.io.File;
10+
import java.io.FileInputStream;
11+
import java.io.IOException;
12+
import java.nio.file.Files;
13+
import org.junit.Test;
14+
15+
public class JdepsWriterTest {
16+
17+
@Test
18+
public void writesJarListToJdepsFile() throws IOException {
19+
File jdepsPath = Files
20+
.createTempDirectory("jdeps-test-tempdir-")
21+
.resolve("some-target.jdeps")
22+
.toFile();
23+
24+
String[] classpath = {"foo.jar", "baz/zoo.class"};
25+
26+
JdepsWriter.write(
27+
jdepsPath.getPath(),
28+
"some-target",
29+
classpath
30+
);
31+
32+
assertArrayEquals(readJarsFromJdepsFile(jdepsPath), classpath);
33+
}
34+
35+
private String[] readJarsFromJdepsFile(File jdepsPath) throws IOException {
36+
Deps.Dependencies dependencies = Deps.Dependencies
37+
.parseFrom(new BufferedInputStream(new FileInputStream(jdepsPath)));
38+
39+
return dependencies
40+
.getDependencyList()
41+
.stream()
42+
.map(Dependency::getPath)
43+
.toArray(String[]::new);
44+
}
45+
}

twitter_scrooge/twitter_scrooge.bzl

+7
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ def _compile_generated_scala(
248248
label.name + "_scalac.diagnosticsproto",
249249
sibling = scrooge_jar,
250250
)
251+
252+
jdepsFile = ctx.actions.declare_file(
253+
label.name + ".jdeps",
254+
sibling = scrooge_jar,
255+
)
256+
251257
all_deps = _concat_lists(deps_java_info, implicit_deps)
252258
merged_deps = java_common.merge(all_deps)
253259

@@ -262,6 +268,7 @@ def _compile_generated_scala(
262268
manifest,
263269
statsfile,
264270
diagnosticsfile,
271+
jdepsFile,
265272
sources = [],
266273
cjars = merged_deps.transitive_compile_time_jars,
267274
all_srcjars = depset([scrooge_jar]),

0 commit comments

Comments
 (0)