Skip to content
Merged
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
23 changes: 20 additions & 3 deletions kotlin/internal/jvm/associates.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,28 @@ load(
_utils = "utils",
)

def _get_associates(ctx, associates):
def _collect_associates(ctx, toolchains, associate):
"""Collects the associate jars from the provided dependency and returns
them as a depset.

There are two outcomes for this marco:
1. When `experimental_strict_associate_dependencies` is enabled and the tag override has not been provided, only the
direct java_output compile jars will be collected for each associate target.
2. When `experimental_strict_associate_dependencies` is disabled, the complete transitive set of compile jars will
be collected for each assoicate target.
"""
jars_depset = None
if (toolchains.kt.experimental_strict_associate_dependencies and
"kt_experimental_strict_associate_dependencies_incompatible" not in ctx.attr.tags):
jars_depset = depset(direct = [a.compile_jar for a in associate[JavaInfo].java_outputs])
else:
jars_depset = depset(transitive = [associate[JavaInfo].compile_jars])
return jars_depset

def _get_associates(ctx, toolchains, associates):
"""Creates a struct of associates meta data"""
if not associates:
return struct(
targets = [],
module_name = _utils.derive_module_name(ctx),
jars = depset(),
)
Expand All @@ -39,7 +56,7 @@ def _get_associates(ctx, associates):
jars = []
module_names = []
for a in associates:
jars.append(depset(transitive = [a[JavaInfo].compile_jars, a[_KtJvmInfo].module_jars]))
jars.append(_collect_associates(ctx = ctx, toolchains = toolchains, associate = a))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear if the a[_KtJvmInfo].module_jars still needs to be included here. We don't hit this case in our codebase and I don't have enough historical context around why we need this here.

module_names.append(a[_KtJvmInfo].module_name)
module_names = list(_sets.copy_of(module_names))

Expand Down
2 changes: 1 addition & 1 deletion kotlin/internal/jvm/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _jvm_deps(ctx, toolchains, associate_deps, deps, exports = [], runtime_deps
)
dep_infos = [_java_info(d) for d in associate_deps + deps] + [toolchains.kt.jvm_stdlibs]

associates = _associate_utils.get_associates(ctx, associates = associate_deps)
associates = _associate_utils.get_associates(ctx, toolchains = toolchains, associates = associate_deps)

# Reduced classpath, exclude transitive deps from compilation
if (toolchains.kt.experimental_prune_transitive_deps and
Expand Down
9 changes: 9 additions & 0 deletions kotlin/internal/toolchains.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def _kotlin_toolchain_impl(ctx):
empty_jdeps = ctx.file._empty_jdeps,
jacocorunner = ctx.attr.jacocorunner,
experimental_prune_transitive_deps = ctx.attr._experimental_prune_transitive_deps[BuildSettingInfo].value,
experimental_strict_associate_dependencies = ctx.attr._experimental_strict_associate_dependencies[BuildSettingInfo].value,
)

return [
Expand Down Expand Up @@ -259,6 +260,14 @@ _kt_toolchain = rule(
kt_experimental_prune_transitive_deps_incompatible tag allows to exclude specific targets""",
default = Label("//kotlin/settings:experimental_prune_transitive_deps"),
),
"_experimental_strict_associate_dependencies": attr.label(
doc = """
If enabled, only the direct compile jars will be collected for each listed associate target
instead of the compelte transitive set of jars. This helps prevent Kotlin internals from leaking beyond
their intended exposure by only exposing the direct java outputs. Using
kt_experimental_prune_transitive_deps_incompatible tag allows to exclude specific targets""",
default = Label("//kotlin/settings:experimental_strict_associate_dependencies"),
),
"_jvm_emit_jdeps": attr.label(default = "//kotlin/settings:jvm_emit_jdeps"),
},
implementation = _kotlin_toolchain_impl,
Expand Down
10 changes: 8 additions & 2 deletions kotlin/settings/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,20 @@ release_archive(
# Flag that controls the emission of jdeps files during kotlin jvm compilation.
bool_flag(
name = "jvm_emit_jdeps",
build_setting_default = True,
build_setting_default = True, # Upstream default behavior
visibility = ["//visibility:public"],
)

# Kotlin strict deps can be enabled by setting the following value on the command line
# --@rules_kotlin//kotlin/settings:experimental_prune_transitive_deps=True
bool_flag(
name = "experimental_prune_transitive_deps",
build_setting_default = False,
visibility = ["//visibility:public"],
)

# --@rules_kotlin//kotlin/settings:experimental_strict_associate_dependencies=True
bool_flag(
name = "experimental_strict_associate_dependencies",
build_setting_default = False,
visibility = ["//visibility:public"],
)
8 changes: 7 additions & 1 deletion kotlin/settings/BUILD.release.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@ bool_flag(
visibility = ["//visibility:public"],
)

# Kotlin strict deps can be enabled by setting the following value on the command line
# --@rules_kotlin//kotlin/settings:experimental_prune_transitive_deps=True
bool_flag(
name = "experimental_prune_transitive_deps",
build_setting_default = False,
visibility = ["//visibility:public"],
)

# --@rules_kotlin//kotlin/settings:experimental_strict_associate_dependencies=True
bool_flag(
name = "experimental_strict_associate_dependencies",
build_setting_default = False,
visibility = ["//visibility:public"],
)