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

Add support for experimental treatInternalAsPrivate #1248

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

rbeazleyspot
Copy link

@rbeazleyspot rbeazleyspot commented Dec 18, 2024

Adds support for experimental options when producing abi.jar, specifically KT-65690 and KT-64590 as discussed in #1245

Have added a couple of integration tests to perform basic checks of flags being applied

I expect there is more to do here and happy to work on it if its considered for merging

@rbeazleyspot rbeazleyspot changed the title Add support for experimental treatInternalAsPrivate Add support for experimental treatInternalAsPrivate #1245 Dec 18, 2024
@rbeazleyspot rbeazleyspot changed the title Add support for experimental treatInternalAsPrivate #1245 Add support for experimental treatInternalAsPrivate Dec 18, 2024
@rbeazleyspot rbeazleyspot force-pushed the issue_1245_treatInternalAsPrivate branch 2 times, most recently from 8f3b772 to 41579c0 Compare December 18, 2024 17:03
plugin:org.jetbrains.kotlin.jvm.abi:treatInternalAsPrivate=true
plugin:org.jetbrains.kotlin.jvm.abi:removePrivateClasses=true
Can be disabled for an individual target using the tag.
`kt_abi_plugin_incompatible`""",
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should probably have a tag of its own to disable this behavior at the target level so that adoption across larger projects is easier.

@Bencodes
Copy link
Collaborator

@rbeazleyspot PR looks good to me, can you take a look at the failing CI checks and regenerate the docs?

@rbeazleyspot
Copy link
Author

@rbeazleyspot PR looks good to me, can you take a look at the failing CI checks and regenerate the docs?

will do, i'm going to make the change you suggested as integrating into our codebase showed up a couple of targets with interesting (TM) issues

@rbeazleyspot
Copy link
Author

Ive pushed an update to the rule to use its own tag as suggested, regenerated the docs (there were some reformatting changes that i unstaged, not sure if that was expected or not), and updated the compilation avoidance advice.

Finally Ive since been testing this further in our app and finding i need to apply kt_public_only_in_abi_plugin_incompatible to some associate targets, so im a little concerned here.

I wondered if something in associates.bzl needs to change, but I havnt looked into this at all yet. It could be our macros are breaking things a little but the effect is certainly that internal access in an associate is not possible ie its linking against the abi jar (first?) or something.

I'll continue to investigate this.

And finally finally, due to the bug mentioned in the compilation avoidance doc i've been testing this locally with compiler 2.1 (after a few tweaks to the rules codebase)... so just a heads up 🖖

@rbeazleyspot
Copy link
Author

rbeazleyspot commented Dec 19, 2024

oh, finally finally v3 final..... i'm not sure whats going on with the CI failure, any pointers?

and FWIW this command passes locally on my machine

bazel test --cache_test_results=no -- //src/test/kotlin/io/bazel/kotlin/builder:builder_tests //src/test/kotlin/io/bazel/kotlin:KotlinJvmAssociatesBasicVisibilityTest //src/test/kotlin/io/bazel/kotlin:KotlinJvmBasicAssertionTest

@rbeazleyspot rbeazleyspot marked this pull request as ready for review December 19, 2024 12:17
@rbeazleyspot
Copy link
Author

Update on associates

KotlinJvmAssociatesBasicVisibilityTest fails when i enable these experimental flags, so something is certainly afoot... ill continue to investigate

@rbeazleyspot
Copy link
Author

rbeazleyspot commented Dec 19, 2024

So i thought the issue would be in associates.bzl where it pulls the friendly jars from the associated target and changed this to use the output jar rather than the module jar ... alas this didnt work

I was able to validate (what i thought was) the correct jar [bazel-out/darwin_arm64-fastbuild/bin/src/test/data/jvm/basic/test_associates_library.jar] was passed over as the value for --kotlin_friend_paths

so im rather stuck atm

Update:

I have something that works by pre-pending the associate targets class_jar to the compile_jars depset produced by the _jvm_deps macro... something along these lines

    associated_java_infos = [_java_info(d) for d in associated_targets]
    associated_output_jars = [info.outputs.jars for info in associated_java_infos]
    associated_targets_depset = depset([
        s[0].class_jar
        for s in associated_output_jars
    ])

and then added to the start of the transitive list

transitive = [
            associated_targets_depset,
        ] + [
            d.compile_jars
            for d in dep_infos
        ] + [
            d.transitive_compile_time_jars
            for d in dep_infos
        ]

if you think this is vaguly going down the right route I can rework this so its not using deprecated methods

@rbeazleyspot
Copy link
Author

It occurred to me last night that the problem with associates this change has shown is maybe an issue in its own right.... should I open one for this @Bencodes ? ie compilation with associates use compile_jars rather than output jars

I guess this only worked as at the time there were no ABI jars generated so it defaulted to output jars?
Then when the ABI jars were generated they were (incorrectly) including more than just public api so things still just worked ™️

@Bencodes
Copy link
Collaborator

@rbeazleyspot can you rebase this branch against HEAD, I believe the current failing REB CI job has already been fixed.

"experimental_use_public_only_abi_jars": attr.bool(
doc = """Compile using public only abi jars.
This effectively applies the following two compiler plugin options:
plugin:org.jetbrains.kotlin.jvm.abi:treatInternalAsPrivate=true
Copy link
Collaborator

@Bencodes Bencodes Dec 20, 2024

Choose a reason for hiding this comment

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

Do these flags need to be paired together to work? If not splitting these up into two individual flags could help further ease the migration over to this.

Copy link
Author

Choose a reason for hiding this comment

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

in my (limited) experience yes, they only appear to work together... however i will split them, maybe there are variations in compiler versions....

Copy link
Author

Choose a reason for hiding this comment

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

maybe it would be better if we pivoted on this idea; if we keep down this road there will be a parallel release train with the kotlin compiler. Each option added for the abi plugin will be mirrored in a similar commit/release here. Could we instead have some experimental_abi_plugin_flags dictionary or similar that is unpacked when configuring the plugin in KotlinJvmTaskExecutor ?

On the other hand i quite like the idea of restricting what options are available such that these rules can be opinionated about how to build abi jars and increase compilation avoidance :D

Copy link
Author

Choose a reason for hiding this comment

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

it looks like this conditional means both flags are needed as its gated behind removePrivateClasses...

private fun shouldRemoveFromAbi(irClass: IrClass?, removePrivateClasses: Boolean, treatInternalAsPrivate: Boolean): Boolean = when {
    irClass == null -> false
    irClass.isFileClass -> false
    removePrivateClasses -> irClass.isVisibilityStrippedFromAbi(stripInternal = treatInternalAsPrivate)
    else -> false
}

Copy link
Author

Choose a reason for hiding this comment

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

anyway, i've pushed another commit that splits these flags... its no effort to revert that commit if we so wish

@Bencodes
Copy link
Collaborator

It occurred to me last night that the problem with associates this change has shown is maybe an issue in its own right....

A new issue would be good for this just to track it. There are a few known edge cases with associates, some of which you've called out here. The ones that I'm aware of are:

  1. Associate dep collection brings the entire classpath along with each associate target. This unintentionally leaks some transitive classpath internals beyond the direct associate dependency. I filed an issue for this one a while back Associates or friends leak the internals of their compile classpath #1021
  2. As you mentioned associates uses the compile jar instead of the output/runtime jar. This one is worth fixing inside the master branch.
  3. There are some additional edge cases that will need to be looked at around ensuring that if we collect an output jar for an associate dependency, it's ABI doesn't make it into the list of standard classpath jars. It's been a while since i've looked into this, but I remember finding that if you pass both the ABI and runtime jars to kotlinc you get into some weird territory where one may get picked over the other, produced an unexpected error (maybe this has improved in 2.x).

I hacked together a not-so-amazing solution to all of these issues a while back since we had been testing out these abi-gen-compiler changes internally to see what kind incremental compilation improvements we could expect here. To do this I had to chop up associates.bzl quite heavily so that I could build a relationship between the compile and output jars up front, and then swap jars in and out accordingly when constructing that final classpath for the KotlinCompile action.

@rbeazleyspot rbeazleyspot force-pushed the issue_1245_treatInternalAsPrivate branch from 217a3c2 to 48db5df Compare December 23, 2024 09:00
@rbeazleyspot
Copy link
Author

It occurred to me last night that the problem with associates this change has shown is maybe an issue in its own right....

A new issue would be good for this just to track it. There are a few known edge cases with associates, some of which you've called out here. The ones that I'm aware of are:

#1250

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.

2 participants