Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions kotlin/internal/jvm/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,18 @@ def find_java_runtime_toolchain(ctx, target):
def _java_info(target):
return target[JavaInfo] if JavaInfo in target else None

def _deps_artifacts(toolchains, targets):
def _report_unused_deps(ctx, toolchains):
if "kt_experimental_report_unused_deps_off" in ctx.attr.tags:
return "off"
if "kt_experimental_report_unused_deps_warn" in ctx.attr.tags:
return "warn"
if "kt_experimental_report_unused_deps_error" in ctx.attr.tags:
return "error"
return toolchains.kt.experimental_report_unused_deps

def _deps_artifacts(ctx, toolchains, targets):
"""Collect Jdeps artifacts if required."""
if not toolchains.kt.experimental_report_unused_deps == "off":
if not _report_unused_deps(ctx, toolchains) == "off":
deps_artifacts = [t[JavaInfo].outputs.jdeps for t in targets if JavaInfo in t and t[JavaInfo].outputs.jdeps]
else:
deps_artifacts = []
Expand Down Expand Up @@ -320,7 +329,13 @@ def _run_merge_jdeps_action(ctx, toolchains, jdeps, outputs, deps):
args.add("--" + f, path)

args.add_all("--inputs", jdeps, omit_if_empty = True)
args.add("--report_unused_deps", toolchains.kt.experimental_report_unused_deps)
args.add("--report_unused_deps", _report_unused_deps(ctx, toolchains))
unused_deps_ignored_targets = [
tag.split(":", 1)[1]
for tag in ctx.attr.tags
if tag.startswith("kt_experimental_unused_deps_ignored_targets:")
]
args.add_all("--unused_deps_ignored_targets", unused_deps_ignored_targets, omit_if_empty = True)

mnemonic = "JdepsMerge"
progress_message = "%s %%{label} { jdeps: %d }" % (
Expand All @@ -329,7 +344,7 @@ def _run_merge_jdeps_action(ctx, toolchains, jdeps, outputs, deps):
)

inputs = depset(jdeps)
if not toolchains.kt.experimental_report_unused_deps == "off":
if not _report_unused_deps(ctx, toolchains) == "off":
# For sandboxing to work, and for this action to be deterministic, the compile jars need to be passed as inputs
inputs = depset(jdeps, transitive = [depset([], transitive = [dep.transitive_compile_time_jars for dep in deps])])

Expand Down Expand Up @@ -596,7 +611,7 @@ def kt_jvm_produce_jar_actions(ctx, rule_kind):
transitive_runtime_jars = _plugin_mappers.targets_to_transitive_runtime_jars(ctx.attr.plugins + ctx.attr.deps)
plugins = _new_plugins_from(ctx.attr.plugins + _exported_plugins(deps = ctx.attr.deps))

deps_artifacts = _deps_artifacts(toolchains, ctx.attr.deps + ctx.attr.associates)
deps_artifacts = _deps_artifacts(ctx, toolchains, ctx.attr.deps + ctx.attr.associates)

generated_src_jars = []
annotation_processing = None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class JdepsMerger {
OUTPUT("--output"),
TARGET_LABEL("--target_label"),
REPORT_UNUSED_DEPS("--report_unused_deps"),
UNUSED_DEPS_IGNORED_TARGETS("--unused_deps_ignored_targets"),
}

private fun readJarOwnerFromManifest(jarPath: Path): JarOwner {
Expand All @@ -63,6 +64,7 @@ class JdepsMerger {
inputs: List<String>,
output: String,
reportUnusedDeps: String,
unusedDepsIgnoredTargets: List<String>,
): Int {
val rootBuilder = Deps.Dependencies.newBuilder()
rootBuilder.success = false
Expand Down Expand Up @@ -114,6 +116,7 @@ class JdepsMerger {
.filter { it.value == Deps.Dependency.Kind.UNUSED }
.map { it.key }
.filter { it != label }
.filter { it !in unusedDepsIgnoredTargets }

if (unusedLabels.isNotEmpty()) {
ctx.info {
Expand Down Expand Up @@ -160,7 +163,9 @@ class JdepsMerger {
val output = argMap.mandatorySingle(JdepsMergerFlags.OUTPUT)
val label = argMap.mandatorySingle(JdepsMergerFlags.TARGET_LABEL)
val reportUnusedDeps = argMap.mandatorySingle(JdepsMergerFlags.REPORT_UNUSED_DEPS)
val unusedDepsIgnoredTargets =
argMap.optional(JdepsMergerFlags.UNUSED_DEPS_IGNORED_TARGETS).orEmpty()

return merge(ctx, label, inputs, output, reportUnusedDeps)
return merge(ctx, label, inputs, output, reportUnusedDeps, unusedDepsIgnoredTargets)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,67 @@ class JdepsMergerTest {
).containsExactly(unusedKotlinDep)
}

@Test
fun `unused deps report warning unless ignored`() {
val merger = DaggerJdepsMergerTestComponent.builder().build().jdepsMerger()

val unusedKotlinDep1 = ktJvmLibrary("kotlin_dep1")
val unusedKotlinDep2 = ktJvmLibrary("kotlin_dep2")
val kotlinJdeps = jdeps("kt.jdeps") {
addDependency(
with(Dependency.newBuilder()) {
kind = Dependency.Kind.UNUSED
path = unusedKotlinDep1
build()
},
)
addDependency(
with(Dependency.newBuilder()) {
kind = Dependency.Kind.UNUSED
path = unusedKotlinDep2
build()
},
)
}

val javaJdeps = jdeps("java.jdeps") {
addDependency(
with(Dependency.newBuilder()) {
kind = Dependency.Kind.EXPLICIT
path = ktJvmLibrary("java_dep")
build()
},
)
}

val mergedJdeps = out("merged.jdeps")

val result = WorkerContext.run {
doTask("jdepsmerge") { taskCtx ->
MergeJdeps(merger = merger).invoke(
taskCtx,
args {
input(kotlinJdeps)
input(javaJdeps)
flag(JdepsMergerFlags.TARGET_LABEL, "//foo/bar:baz")
flag(JdepsMergerFlags.OUTPUT, mergedJdeps)
flag(JdepsMergerFlags.REPORT_UNUSED_DEPS, "warn")
flag(JdepsMergerFlags.UNUSED_DEPS_IGNORED_TARGETS, "kotlin_dep2")
},
)
}
}
assertThat(result.status).isEqualTo(SUCCESS)
assertThat(result.log.out.toString()).contains("'remove deps kotlin_dep1' //foo/bar:baz")

val depsProto = depsProto(mergedJdeps)
assertThat(
depsProto.dependencyList
.filter { it.kind == Dependency.Kind.UNUSED }
.map { it.path },
).containsExactly(unusedKotlinDep1, unusedKotlinDep2)
}

@Test
fun `unused deps report error`() {
val merger = DaggerJdepsMergerTestComponent.builder().build().jdepsMerger()
Expand Down