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

Kotlin: build extractor with bazel #16117

Merged
merged 111 commits into from
Jun 4, 2024
Merged

Kotlin: build extractor with bazel #16117

merged 111 commits into from
Jun 4, 2024

Conversation

redsun82
Copy link
Contributor

@redsun82 redsun82 commented Apr 4, 2024

Usage overview

Building the extractor can be done via

bazel build //java/kotlin-extractor:codeql-extractor-kotlin-<variant>-<version>

where <variant> is either standalone or embeddable, and <version> is one of the supported versions.

For the moment both variants where tested by replacing them into target/intree/codeql-java and running one relevant integration test.

bazel build //java/kotlin-extractor

will build a default variant:

  • standalone, unless CODEQL_KOTLIN_SINGLE_VERSION_EMBEDDABLE is set to true, in which case it will go for embeddable
  • the version will be taken as the last supported version less than the version of the currently installed kotlinc
    • if CODEQL_KOTLIN_SINGLE_VERSION is set, that will be used instead
    • if kotlinc is not installed, 1.9.20-Beta will be used (the current kotlin toolchain downloaded by rules_kotlin is 1.9.23).

If using the provided kotlinc wrapper (see section below), bazel will be aware of versions selected by it and change the default //java/kotlinc-extractor accordingly.

kotlinc wrapper

A cross-platform kotlinc wrapper is provided in java/kotlinc-extractor/deps/dev. If this path is added to the PATH environment variable, one can call kotlinc and have the wrapper take care of downloading the appropriate Kotlin compiler under the hood. The desired version can be selected with kotlinc --select x.y.z, or left to the current default of 1.9.0.

Selected and installed version data is stored in .gitignored files in the same directory, and can be cleared with kotlinc --clear.

These -- options cannot conflict with normal kotlinc options, which uses single - options instead.

If ripunzip is installed, or in any case on windows from within semmle-code where ripunzip.exe is provided, that will be used, which results in faster kotlin installations.

Interactions with the existing build

For the moment nothing changes on the internal build, which will still call build.py. After we integrate this into the internal build system we can come back here and clean up obsolete files.

Implementation notes

Version variants

rules_kotlin does not seem to really support building with different -language-version settings in the same workspace, so I ended up patching it to allow specifying that at a kt_jvm_library level via kt_kotlinc_options. This allows defining the different extractor versions in the same build file using a standard [...] comprehension.

Standalone / embeddable

Embeddable requires not only changing one dependency, but also some imports in the source code itself. This is achieved by reexporting and patching the code in the @codeql_kotlin_embeddable external repository. The java/kotlin-extractor/BUILD.bazel file is shared with that repository, and behaves slightly differently depending on that (based on repo_name()).

External dependencies

The kotlin dependencies are given as LFS files in java/kotlin-extractor/deps. However normal codeql users won't have those files downloaded, whether they have git lfs installed or not, as fetching those files are excluded by the repo's .lfsconfig. Additionally, those LFS files won't count towards users' quotas on forks, and users not having write permissions on github/codeql won't be able to push new LFS files there (so we can't be "LFS bombed").

Building the extractor will require git lfs to be installed on the system, but will then work and checkout those dependencies lazily on demand within the bazel cache. This means a bazel clean will clear those files out. However if those files are present in the checkout and not just LFS pointers (as happens for example when updating/adding dependencies, or if git config lfs.fetchinclude java/kotlin-extractor/deps/* is specified followed by a git lfs checkout), then bazel will symlink them as they are, without incurring in any LFS download overhead, including after bazel clean.

Updating the dependencies doesn't require any special actions: when added and pushed the files will be uploaded as LFS files, and locally they will be picked up by bazel without any problem.

rules_kotlin patching

We do need to patch rules_kotlin to provide different -language-version values for different bazel targets. After some discussion we decided to to that with a local bazel registry rather than an override, because that will make sharing with the internal semmle-code repo easier.

@github-actions github-actions bot added the Kotlin label Apr 4, 2024
@redsun82 redsun82 marked this pull request as ready for review April 8, 2024 10:42
@redsun82 redsun82 requested review from a team as code owners April 8, 2024 10:42
@redsun82 redsun82 requested review from igfoo and criemen April 8, 2024 10:45
@redsun82 redsun82 requested a review from a team as a code owner April 9, 2024 11:27
@github-actions github-actions bot added the Java label Apr 9, 2024
Copy link
Collaborator

@criemen criemen left a comment

Choose a reason for hiding this comment

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

Not a full review yet, but this is far as I got for now. Thanks a lot for working on this!

.bazelrc Outdated Show resolved Hide resolved
.bazelrc Outdated Show resolved Hide resolved
.lfsconfig Show resolved Hide resolved
MODULE.bazel Outdated Show resolved Hide resolved
java/kotlin-extractor/BUILD.bazel Outdated Show resolved Hide resolved
java/kotlin-extractor/BUILD.bazel Outdated Show resolved Hide resolved
java/kotlin-extractor/BUILD.bazel Outdated Show resolved Hide resolved
java/kotlin-extractor/deps.bzl Show resolved Hide resolved
java/kotlin-extractor/deps.bzl Outdated Show resolved Hide resolved
java/kotlin-extractor/deps.bzl Show resolved Hide resolved
java/kotlin-extractor/deps.bzl Show resolved Hide resolved
.github/workflows/kotlin-build.yml Show resolved Hide resolved
Building the extractor can be done via
```
bazel build //java/kotlin-extractor:codeql-extractor-kotlin-<variant>-<version>
```
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like this can't be done from <root>, but can be done from <root>/ql or <root>/ql/java/kotlin-extractor. Is that expected?

Also, I think that this should mention that you needs tools/bazel to be the bazel on your path.

Copy link
Contributor 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 can't be done from , but can be done from /ql or /ql/java/kotlin-extractor. Is that expected?

I can add a note about building from the internal repo (bazel build @codeql//java/kotlin-extractor:etc is what works from there)

Also, I think that this should mention that you needs tools/bazel to be the bazel on your path.

Actually, any installed bazel or bazelisk will do (bar http fetching problems 😅). On codeql, if it's bazelisk (which is now the recommended bazel executable to have and is what bazel is on github actions) it will pick up the correct bazel version. If it's a fixed bazel version, it will exit any way with a helpful error on a version mismatch.

Furthermore, on semmle-code, any installed bazel will actually auto-pick tools/bazel.

Copy link
Contributor

Choose a reason for hiding this comment

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

The helpful error will have the user install bazel, though, and they will have to update their installation when we bump our bazel version. Wouldn't it be better to just tell them to use the tools/bazel they already have?

Copy link
Collaborator

@criemen criemen left a comment

Choose a reason for hiding this comment

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

I resurrected some threads that imo still need addressing.

I'm also interested in the future of the hand-written build system: Do we plan to delete this as soon as we've moved the internal build off it? Do we plan to keep it around?

If `kotlinc` is updated, bazel won't be aware of it and will therefore keep the same default version. Possible workarounds for that:
* `bazel clean`
* `bazel fetch --force @codeql_kotlin_defaults\\:all`
* `CODEQL_KOTLIN_SINGLE_VERSION= bazel build //java/kotlin-extractor`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add a note about this then, and/or drop this workaround?
Or maybe shell out to a source of randomness to set the variable content :D

"echo %s-%s > $(RULEDIR)/%s/com/github/codeql/extractor.name" % (_extractor_name_prefix, v, v),
] + [
"cp $(execpath %s) $(RULEDIR)/%s/%s" % (src, v, tgt)
for src, tgt in _resources
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit doesn't seem to have been addressed, despite a thumbs-up emoji

@@ -0,0 +1,31 @@
module(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure where these ended up.

java/kotlin-extractor/dev/kotlinc Outdated Show resolved Hide resolved
@@ -0,0 +1,163 @@
#!/usr/bin/env python3
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't there be a java/kotlin-extractor/dev/kotlin as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess? I did not have to call that, but my interaction with kotlin was not that deep. I've added both that and kapt. I'm guessing kolinc-* variants are not really needed directly? But those could be added too if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

or would you just add kotlin?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think that kotlin is worthwhile, so people can easily run Kotlin programs while working on things. I don't think anything else is likely to be necessary, and we can always add more things later if it turns out to be useful.

@redsun82
Copy link
Contributor Author

redsun82 commented Jun 4, 2024

I resurrected some threads that imo still need addressing.

I'm also interested in the future of the hand-written build system: Do we plan to delete this as soon as we've moved the internal build off it? Do we plan to keep it around?

My idea would be to remove all unneeded scripts after the internal repo change is merged.

criemen
criemen previously approved these changes Jun 4, 2024
Copy link
Collaborator

@criemen criemen left a comment

Choose a reason for hiding this comment

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

LGTM, but please wait with merging for approval from @igfoo.

igfoo
igfoo previously approved these changes Jun 4, 2024
Copy link
Collaborator

@criemen criemen left a comment

Choose a reason for hiding this comment

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

re-stamping, assuming CI turns green

@redsun82 redsun82 merged commit ad2eacf into main Jun 4, 2024
24 checks passed
@redsun82 redsun82 deleted the redsun82/kotlin branch June 4, 2024 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants