Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enables compiling against direct dependencies only - kotlin #842

Merged

Conversation

nkoroste
Copy link
Collaborator

@nkoroste nkoroste commented Oct 7, 2022

Defines --@io_bazel_rules_kotlin//kotlin/settings:experimental_prune_transitive_deps=True that will allow you to make java and android to only use direct dependancies when compiling a given target. This significantly speeds up incremental compilations at the cost of adding explicit deps to all targets.

Relates to bazelbuild/bazel#16426

Can be tested with #840 which will produce the following expected output:

cd examples/deps && ./run.sh --@io_bazel_rules_kotlin//kotlin/settings:experimental_prune_transitive_deps=True

Rebuilt libjava targets: 4
Rebuilt libandroid targets: 4
Rebuilt libkt targets: 2
Rebuilt libktandroid targets: 2
Rebuilt libandroid res-only targets: 4
Rebuilt libktandroid res-only targets: 4

@@ -101,16 +102,26 @@ def _jvm_deps(toolchains, associated_targets, deps, runtime_deps = []):
",\n ".join([" %s" % x for x in list(diff)]),
)
dep_infos = [_java_info(d) for d in associated_targets + deps] + [toolchains.kt.jvm_stdlibs]

# Reduced classpath, exclude transitive deps from compilation
if (ctx.attr._experimental_prune_transitive_deps[BuildSettingInfo].value):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it be better to expose this at the toolchains.kt level so that there's a unified place to look up these high level build settings?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You're talking about kotlin/internal/toolchains.bzl right? defining this in toolchains will prevent you from passing this flag on CLI, no?
Right now you're able to do something like this:

bazel build --@io_bazel_rules_kotlin//kotlin/internal/jvm:experimental_prune_transitive_deps=True //foo

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah yes you are actually right.

Copy link
Contributor

Choose a reason for hiding this comment

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

That isn't strictly true right? You can always have a config setting that enables the feature in the tool chain.

We do this for conditional multiplex workers

config_setting( 
     name = "kotlinc_multiplex_workers", 
     define_values = { 
         "kotlinc_multiplex_workers": "enabled", 
     }, 
 ) 
  
 define_kt_toolchain( 
     name = "toolchain", 
     api_version = "1.7", 
     experimental_multiplex_workers = select({ 
         ":kotlinc_multiplex_workers": True, 
         "//conditions:default": False, 
     }),

Then enable it via --define=kotlinc_multiplex_workers=enabled one could also do this as a proper flag. The benefits of this is that we don't need to ship skylib in the release archive and downstream users get full control over how it's toggled and set.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You're right, but that requires a lot of setup on the user side that can potentially be error prone. I personally think that having it via skylib is more user friendly and aligns with all other first class citizen flags we support. Though I don't have super strong feeling either way.

Copy link
Contributor

@chancila chancila Nov 23, 2022

Choose a reason for hiding this comment

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

you can attach the build flag on the toolchain rule, there's no need for this build flag to be an attr for pretty much every kotlin rule...

rules_rust pulls the config settings in the toolchain, rules_go has a config rule that reads the flags and generates a config provider that is then consumed by other rules

either way the flags in these rules need to be better located and integrated, they are in an internal jvm package, they should be moved out to something like //kotlin/config:* so they easier to reason about

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As Cris recommended, I've moved the flag under kotlin/settings and attached it to the toolchain as it's cleaner that way.
I'll do the same for the jdeps, kotlin_deps flag for consistency in a follow up pr.

@@ -33,3 +33,13 @@ bzl_library(
"@build_bazel_rules_android//android",
],
)

load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
Copy link
Collaborator

Choose a reason for hiding this comment

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

@nkoroste I think we need to include bazel_skylib in the release archive as a release dependency.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure how releases work to be honest so I would differ to your expertise

@nkoroste nkoroste marked this pull request as ready for review October 13, 2022 00:08
@nkoroste nkoroste force-pushed the nk-compilationAvoidanceKotlin_upstream branch from e8fdb31 to 7ec08e4 Compare October 13, 2022 00:11
@lukaciko
Copy link
Contributor

@nkoroste does this replace experimental_reduce_classpath_mode? What is the difference between the two?

@rockwotj
Copy link
Contributor

@nkoroste does this replace experimental_reduce_classpath_mode? What is the difference between the two?

@lukaciko the difference with this PR is that the transitive jars aren't even passed into the action, so you get caching benefits instead of just giving kotlinc a smaller classpath. As far as I can tell, this PR should make experimental_reduce_classpath_mode obsolete. Please someone correct me if I'm wrong

See:

inputs.directDependenciesList + transitiveDepsForCompile

@arunkumar9t2
Copy link
Contributor

arunkumar9t2 commented Oct 19, 2022

I would not say this makes the reduced claspath mode redundant yet since this forces every target to list their deps which can be problematic for many @maven targets which do not define their impl vs api correctly. Eg. Room uses LiveData but does not declare it. Fixing this manually is lot of pain.

It is true that not passing jars as inputs is the best option since we get caching benefits. To do that in starlark for rules_kotlin however we need few changes from Bazel.

Bazel already has experimental class path mode called bazel which prunes transitive classpath based on jdeps before action registration. But this is not exposed to starlark yet. Rules kotlin already has jdeps and if this function is available via java_common like

jars = java_common.reduce_classpath(transitive_classpath, jdeps)

Then we can also do classpath reduction before action registration which will help with compile avoidance.

Lastly bazel has automatic recovery in default java_builder classpath mode. It attempts compilation with direct jars first and if it fails it falls back to full transitive classpath.

Side note:

What we are doing internally is we filter classpath only for project targets and for external targets like @maven we don't filter and pass as it is. This for now keeps build.bazel not too verbose. We pass this information to bazel and rules_kotlin via tags.

@nkoroste
Copy link
Collaborator Author

As far as I can tell, this PR should make experimental_reduce_classpath_mode obsolete. Please someone correct me if I'm wrong

I agree with @arunkumar9t2, it doesn't make it obsolete as we can do reduction on both the class level (bazelbuild/bazel#16457) and on the jar/deps level which is what this PR is trying to achieve.

It is true that not passing jars as inputs is the best option since we get caching benefits. To do that in starlark for rules_kotlin however we need few changes from Bazel.

Are you talking about this bazelbuild/bazel#16426?

Side note:
What we are doing internally is we filter classpath only for project targets and for external targets like @maven we don't filter and pass as it is. This for now keeps build.bazel not too verbose. We pass this information to bazel and rules_kotlin via tags.

Do you mind sharing what you have? I guess my PR will take care of both which does have pretty large performance gain for us

@nkoroste nkoroste force-pushed the nk-compilationAvoidanceKotlin_upstream branch from 377c9a7 to f11d238 Compare November 1, 2022 19:56
@nkoroste nkoroste force-pushed the nk-compilationAvoidanceKotlin_upstream branch from 091dc74 to 2b4cbe8 Compare December 14, 2022 19:49
nkoroste and others added 6 commits December 14, 2022 12:03
…idanceKotlin_upstream

* upstream/master: (51 commits)
  Expose ksp_version (bazelbuild#989)
  Bump quick guide to use v1.8 (bazelbuild#987)
  Fail CI if the docs are outdated (bazelbuild#961)
  Rename dev_io_bazel_rules_kotlin -> io_bazel_rules_kotlin (bazelbuild#973)
  update stardoc to 0.5.6 (bazelbuild#986)
  fix readme about kotlinc_opts and javac_opts (bazelbuild#984)
  Update README with KSP support (bazelbuild#983)
  Regenerate the docs (bazelbuild#980)
  Update the README.md with the latest dev override config (bazelbuild#981)
  Remove opts.release.bzl which is no longer being used (bazelbuild#982)
  Remove print warning from kt_download_local_dev_dependencies (bazelbuild#974)
  Avoid creating duplicate android_sdk_repositories (bazelbuild#978)
  Normalize label (bazelbuild#968)
  Generate koltinc options (bazelbuild#962)
  Restore neverlink on compiler. (bazelbuild#977)
  Use the mnemonic for worker keys (bazelbuild#976)
  Update KtLint to 0.49.1 (bazelbuild#970)
  Add support for -Xuse-fir-lt (bazelbuild#972)
  Support -Xenable-incremental-compilation (bazelbuild#971)
  Update to Kotlin 1.8.21 (bazelbuild#969)
  ...
…idanceKotlin_upstream

* upstream/master:
  Move the KSP and compiler target definitions into rules_kotlin (bazelbuild#1014)
  Avoid running java_common#compile against KSP generated outputs (bazelbuild#990)
  Update kt_java_stub_template to 6.2.1 (bazelbuild#992)
  Disable strict deps for Android example (bazelbuild#1013)
  Group the all_tests jobs together in presubmit.yml (bazelbuild#1008)
  Add rules_java 6.4.0 (bazelbuild#1010)
  Update Bazel to 6.3.2 (bazelbuild#1007)
  Update rules_jvm_external to 5.3 (bazelbuild#1009)
  Migrate usages of deprecated `JavaInfo` fields (bazelbuild#1005)
  Remove unnecessary Java runtime dependencies (bazelbuild#1000)
**kwargs
)
exported_target_labels.append(base_name)
elif resource_files:
Copy link
Collaborator

Choose a reason for hiding this comment

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

This conditional also needs to check if there is a manifest, otherwise manifests might get left behind.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@nkoroste nkoroste merged commit 004189e into bazelbuild:master Sep 29, 2023
1 check passed
pswaminathan added a commit to pswaminathan/rules_kotlin that referenced this pull request Feb 13, 2024
Prior to bazelbuild#842, kwargs were sent to the base android library rule. In that PR, one of the branches no longer contained it. This causes any target with resources/manifest not to send kwargs, which means that e.g. `assets` don't get passed down.
Bencodes added a commit that referenced this pull request Mar 1, 2024
Bencodes added a commit that referenced this pull request Mar 1, 2024
* Revert android.bzl changes introduced by #842

* Formatting
oliviernotteghem pushed a commit to uber-common/rules_kotlin that referenced this pull request Aug 2, 2024
)

* Revert android.bzl changes introduced by bazelbuild#842

* Formatting
oliviernotteghem pushed a commit to uber-common/rules_kotlin that referenced this pull request Aug 2, 2024
)

* Revert android.bzl changes introduced by bazelbuild#842

* Formatting
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants