From 70f834ea5c2dcd4a62904e7cab067106e07c11dc Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 10:43:41 +0200 Subject: [PATCH 01/15] Migrate build to Gradle --- .github/workflows/ci.yml | 16 +- .github/workflows/release-cli.yml | 2 +- .github/workflows/release-maven.yml | 16 +- .gitignore | 10 +- CONTRIBUTING.md | 56 +- Dockerfile | 2 +- bin/docker-setup.sh | 4 +- build.gradle.kts | 582 ++++++++++++++++++ build.sbt | 463 -------------- docs/getting-started.md | 12 +- flake.nix | 1 - gradle.properties | 3 + gradle/libs.versions.toml | 48 ++ project/build.properties | 1 - project/plugins.sbt | 6 - .../com/sourcegraph/scip_java/BuildInfo.kt | 9 +- .../scip_java/buildtools/ScipBuildTool.kt | 2 +- scip-snapshots/README.md | 4 +- .../tests/MinimizedSnapshotScipGenerator.java | 7 +- .../src/main/java/tests/SaveSnapshots.java | 6 +- .../java/tests/AssertSnapshotHandler.java | 3 +- settings.gradle.kts | 32 + 22 files changed, 741 insertions(+), 544 deletions(-) create mode 100644 build.gradle.kts delete mode 100644 build.sbt create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml delete mode 100644 project/build.properties delete mode 100644 project/plugins.sbt create mode 100644 settings.gradle.kts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 245f8ab97..640bfdb79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: - uses: DeterminateSystems/magic-nix-cache-action@v13 - name: Main project tests - run: nix develop .#jdk${{ matrix.java }} --command sbt test + run: nix develop .#jdk${{ matrix.java }} --command gradle test --no-daemon docker_test: runs-on: ubuntu-latest @@ -83,8 +83,8 @@ jobs: - uses: DeterminateSystems/magic-nix-cache-action@v13 - - run: nix develop --command sbt cli/pack - - run: echo "$PWD/scip-java/target/pack/bin" >> "$GITHUB_PATH" + - run: nix develop --command gradle :scip-java:installDist --no-daemon + - run: echo "$PWD/scip-java/build/install/scip-java/bin" >> "$GITHUB_PATH" - name: Auto-index scip-java codebase run: | # shellcheck disable=SC2016 @@ -113,10 +113,10 @@ jobs: - uses: DeterminateSystems/magic-nix-cache-action@v13 - name: scip-kotlinc tests - run: nix develop --command sbt scipKotlinc/test + run: nix develop --command gradle :scip-kotlinc:test --no-daemon - name: Regenerate snapshots - run: nix develop --command sbt scipSnapshots/run + run: nix develop --command gradle :scip-snapshots:saveSnapshots --no-daemon - name: Check snapshot drift run: | @@ -141,13 +141,13 @@ jobs: - run: | nix develop .#jdk${{ matrix.java }} --command \ - sbt --error cli/pack publishM2 publishLocal + gradle --no-daemon :scip-java:installDist publishToMavenLocal SCIP_JAVA_VERSION="$( - sed -n 's/^version:=//p' scip-java/target/pack/VERSION + sed -n 's/^version:=//p' scip-java/build/install/scip-java/VERSION )" test -n "$SCIP_JAVA_VERSION" printf 'SCIP_JAVA_VERSION=%s\n' "$SCIP_JAVA_VERSION" >> "$GITHUB_ENV" - printf 'SCIP_JAVA_CLI=%s\n' "$PWD/scip-java/target/pack/bin/scip-java" >> "$GITHUB_ENV" + printf 'SCIP_JAVA_CLI=%s\n' "$PWD/scip-java/build/install/scip-java/bin/scip-java" >> "$GITHUB_ENV" - run: | nix develop "$GITHUB_WORKSPACE#jdk${{ matrix.java }}" --command \ diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml index 4e6c6bb4a..c33e896a6 100644 --- a/.github/workflows/release-cli.yml +++ b/.github/workflows/release-cli.yml @@ -37,7 +37,7 @@ jobs: cd "$OUT_DIR" VERSION=${VERSION#v} - ARTIFACT="com.sourcegraph:scip-java_2.13:${VERSION}" + ARTIFACT="com.sourcegraph:scip-java:${VERSION}" for attempt in {1..10}; do if cs resolve "$ARTIFACT" >/dev/null 2>&1; then diff --git a/.github/workflows/release-maven.yml b/.github/workflows/release-maven.yml index e3f38ff45..b082060b5 100644 --- a/.github/workflows/release-maven.yml +++ b/.github/workflows/release-maven.yml @@ -15,8 +15,20 @@ jobs: with: summarize: false - uses: DeterminateSystems/magic-nix-cache-action@v13 - - name: Publish ${{ github.ref }} - run: nix develop --command sbt ci-release + - name: Publish snapshot ${{ github.ref }} + if: ${{ !startsWith(github.ref, 'refs/tags/') }} + run: nix develop --command gradle --no-daemon publishToSonatype + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + - name: Publish release ${{ github.ref }} + if: ${{ startsWith(github.ref, 'refs/tags/') }} + run: | + version="${GITHUB_REF_NAME#v}" + nix develop --command env VERSION="$version" \ + gradle --no-daemon publishToSonatype closeAndReleaseSonatypeStagingRepository env: PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} PGP_SECRET: ${{ secrets.PGP_SECRET }} diff --git a/.gitignore b/.gitignore index 97484a25c..ce6f3c1a3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,9 @@ result result-* -# sbt specific +# build tool output +.gradle/ +build/ .cache .history .lib/ @@ -13,8 +15,6 @@ dist/* target/ lib_managed/ src_managed/ -project/boot/ -project/plugins/project/ .bloop _site/ @@ -79,7 +79,3 @@ scip-snapshots/META-INF/ # writes META-INF/scip/sources/Test.kt.scip relative to the test # cwd. scip-kotlinc/META-INF/ - -# Standard sbt project metadata directories. -project/target/ -project/project/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 018188df7..20b6d5f27 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,8 +14,8 @@ nix develop .#jdk17 # JDK 17 nix develop .#jdk21 # JDK 21 ``` -This drops you into a shell with `sbt`, `maven`, `gradle`, `bazelisk`, -`nodejs`, `yarn`, `git`, `jq`, etc. all pinned to the versions used in CI. +This drops you into a shell with `gradle`, `maven`, `bazelisk`, `nodejs`, +`yarn`, `git`, `jq`, etc. all pinned to the versions used in CI. If you'd rather install tools manually, you'll need at least: @@ -43,25 +43,23 @@ These are the main components of the project. interface. - `scip-java/src/test`: build-tool integration tests and fixtures for the `scip-java` command-line interface. -- `build.sbt`: the sbt build definition. -- `project/plugins.sbt`: plugins for the sbt build. +- `settings.gradle.kts`: Gradle project layout. +- `build.gradle.kts`: Gradle build definition. +- `gradle/libs.versions.toml`: dependency and plugin versions. ## Helpful commands -| Command | Where | Description | -| ------------------------------------------------------------------- | -------- | ----------------------------------------------------------------------------------- | -| `sbt` | terminal | Start interactive sbt shell with Java 11 (run from `nix develop`). Takes a while to load on the first run. | -| `unit/test` | sbt | Run fast unit tests. | -| `~unit/test` | sbt | Start watch mode to run tests on file save, good for local edit-and-test workflows. | -| `cli/test` | sbt | Run slow build tool tests (Gradle, Maven). | -| `snapshots/testOnly tests.MinimizedSnapshotScipTest` | sbt | Runs fast snapshot tests. Indexes a small set of files under `tests/minimized`. | -| `snapshots/test` | sbt | Runs all snapshot tests. | -| `snapshots/run` | sbt | Update only the Java snapshot goldens under `tests/snapshots`. | -| `scipKotlincMinimized/kotlincSnapshots` | sbt | Update only the Kotlin snapshot goldens under `scip-kotlinc/minimized`. | -| `regenerateSnapshots` | sbt | Regenerate ALL snapshot goldens (Java + Kotlin). Run after fixing a bug. | -| `cli/run --cwd DIRECTORY` | sbt | Run `scip-java` command-line tool against a given Gradle/Maven build. | -| `google-java-format --replace $(git ls-files '*.java')` | terminal | Format Java sources (from `nix develop`). Enforced by `nix flake check`. | -| `ktfmt --kotlinlang-style $(git ls-files '*.kt')` | terminal | Format Kotlin sources (from `nix develop`). Enforced by `nix flake check`. | +| Command | Where | Description | +| ------------------------------------------------------- | -------- | ----------------------------------------------------------------------- | +| `gradle test --no-daemon` | terminal | Run all Gradle tests. | +| `gradle :scip-java:test --no-daemon` | terminal | Run CLI build-tool integration tests (Gradle, Maven, SCIP config). | +| `gradle :scip-kotlinc:test --no-daemon` | terminal | Run Kotlin compiler-plugin tests. | +| `gradle :scip-snapshots:test --no-daemon` | terminal | Compare Java and Kotlin snapshot goldens. | +| `gradle :scip-snapshots:saveSnapshots --no-daemon` | terminal | Regenerate Java and Kotlin snapshot goldens. | +| `gradle :scip-java:installDist --no-daemon` | terminal | Build a local `scip-java` distribution under `scip-java/build/install/`. | +| `gradle :scip-java:run --args='--cwd DIRECTORY'` | terminal | Run `scip-java` against a given Gradle/Maven build. | +| `google-java-format --replace $(git ls-files '*.java')` | terminal | Format Java sources (from `nix develop`). Enforced by `nix flake check`. | +| `ktfmt --kotlinlang-style $(git ls-files '*.kt')` | terminal | Format Kotlin sources (from `nix develop`). Enforced by `nix flake check`. | ## Import the project into IntelliJ @@ -80,20 +78,16 @@ Next, follow [these instructions](https://github.com/HPI-Information-Systems/Metanome/wiki/Installing-the-google-styleguide-settings-in-intellij-and-eclipse) here to configure the Google Java formatter. -Finally, run "File > Project From Existing Sources" to import the sbt build into -IntelliJ. Select the "sbt" option if it asks you to choose between -sbt/BSP/Bloop. +Finally, run "File > Project From Existing Sources" to import the Gradle build +into IntelliJ. Select the "Gradle" option if it asks you to choose a build +model. -It's best to run tests from the sbt shell, not from the IntelliJ UI. +It's best to run tests from Gradle, not from the IntelliJ UI. ## Tests are written in Java with JUnit 5 -The unit tests (`tests/unit`) and snapshot tests (`tests/snapshots`) are plain -Java using [JUnit 5](https://junit.org/junit5/), wired into sbt via -[sbt-jupiter-interface](https://github.com/sbt/sbt-jupiter-interface). The -snapshot suite is a JUnit `@TestFactory` that emits one dynamic test per -generated document, comparing it against the committed goldens under -`tests/snapshots/src/main/generated` -([snapshot testing](https://jestjs.io/docs/en/snapshot-testing) is heavily used -in this codebase). Build-tool tests (`scip-java/src/test`) are written in -Kotlin. +The Java tests use [JUnit 5](https://junit.org/junit5/) through Gradle's JUnit +Platform support. The snapshot suite is a JUnit `@TestFactory` that emits one +dynamic test per generated document, comparing it against the committed goldens +under `scip-snapshots/expected`. Build-tool tests (`scip-java/src/test`) are +written in Kotlin. diff --git a/Dockerfile b/Dockerfile index 5af452423..45ae2c6b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ RUN git config --global --add safe.directory * COPY . . -RUN sbt cli/pack && mkdir -p /app/scip-java && cp -R scip-java/target/pack/. /app/scip-java/ +RUN gradle --no-daemon :scip-java:installDist && mkdir -p /app/scip-java && cp -R scip-java/build/install/scip-java/. /app/scip-java/ COPY ./bin/scip-java-docker-script.sh /usr/bin/scip-java diff --git a/bin/docker-setup.sh b/bin/docker-setup.sh index b472e11b4..6e4f72165 100755 --- a/bin/docker-setup.sh +++ b/bin/docker-setup.sh @@ -3,14 +3,14 @@ set -eux curl -fLo /usr/local/bin/cs https://github.com/coursier/coursier/releases/download/v2.1.5/coursier chmod +x /usr/local/bin/cs ln -sf /usr/local/bin/cs /usr/local/bin/coursier -cs setup --yes --apps cs,coursier,sbt +cs setup --yes --apps cs,coursier curl -fLo maven.zip https://archive.apache.org/dist/maven/maven-3/3.9.1/binaries/apache-maven-3.9.1-bin.zip unzip -d /opt/maven maven.zip rm maven.zip mv /opt/maven/*/* /opt/maven -curl -fLo gradle.zip https://services.gradle.org/distributions/gradle-7.6.1-bin.zip +curl -fLo gradle.zip https://services.gradle.org/distributions/gradle-8.10-bin.zip unzip -d /opt/gradle gradle.zip rm gradle.zip mv /opt/gradle/*/* /opt/gradle diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..828e38697 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,582 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.google.protobuf.gradle.ProtobufExtension +import com.google.protobuf.gradle.proto +import java.nio.charset.StandardCharsets +import java.util.Base64 +import org.gradle.api.JavaVersion +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.distribution.DistributionContainer +import org.gradle.api.plugins.BasePluginExtension +import org.gradle.api.plugins.JavaApplication +import org.gradle.api.plugins.JavaPlugin +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.Copy +import org.gradle.api.tasks.JavaExec +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.Sync +import org.gradle.api.tasks.compile.JavaCompile +import org.gradle.api.tasks.javadoc.Javadoc +import org.gradle.api.tasks.testing.Test +import org.gradle.external.javadoc.StandardJavadocDocletOptions +import org.gradle.plugins.signing.SigningExtension +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + id("io.github.gradle-nexus.publish-plugin") version "2.0.0" + alias(libs.plugins.kotlin.jvm) apply false + alias(libs.plugins.protobuf) apply false + alias(libs.plugins.shadow) apply false +} + +fun decodePgpSecret(raw: String): String = + if (raw.contains("BEGIN PGP")) { + raw + } else { + runCatching { String(Base64.getDecoder().decode(raw), StandardCharsets.UTF_8) }.getOrElse { raw } + } + +val computedVersion = + providers + .gradleProperty("releaseVersion") + .orElse(providers.environmentVariable("VERSION").map { it.removePrefix("v") }) + .orElse( + providers.provider { + rootProject.file("VERSION").takeIf { it.isFile }?.readText()?.trim()?.takeIf { + it.isNotEmpty() + } ?: "0.0.0-SNAPSHOT" + } + ) + +group = "com.sourcegraph" +version = computedVersion.get() + +val javacModuleOptions = + listOf( + "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ) +val javacTestJvmOptions = javacModuleOptions.map { it.removePrefix("-J") } +val versionCatalog = extensions.getByType().named("libs") +val protobufVersion = versionCatalog.findVersion("protobuf").get().requiredVersion +fun library(alias: String) = versionCatalog.findLibrary(alias).get() + +allprojects { + group = rootProject.group + version = rootProject.version +} + +subprojects { + // Several modules also have Bazel `BUILD` files. On the default macOS + // case-insensitive filesystem, Gradle's default `build/` directory collides + // with those files, so keep Gradle outputs under the already-ignored target/. + if (file("BUILD").isFile) { + layout.buildDirectory.set(layout.projectDirectory.dir("target/gradle")) + } + + plugins.withType { + extensions.configure { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + withSourcesJar() + withJavadocJar() + } + + tasks.withType().configureEach { + options.encoding = "UTF-8" + options.release.set(11) + } + + tasks.withType().configureEach { + options.encoding = "UTF-8" + (options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet") + } + + tasks.withType().configureEach { + useJUnitPlatform() + testLogging { + events("failed", "skipped") + } + } + } +} + +fun Project.configureMavenPublishing(displayName: String, descriptionText: String) { + apply(plugin = "maven-publish") + apply(plugin = "signing") + + extensions.configure { + publications { + create("mavenJava") { + from(components["java"]) + pom { + name.set(displayName) + description.set(descriptionText) + url.set("https://github.com/sourcegraph/scip-java") + licenses { + license { + name.set("Apache-2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0") + } + } + developers { + developer { + id.set("sourcegraph") + name.set("Sourcegraph") + } + } + scm { + connection.set("scm:git:https://github.com/sourcegraph/scip-java.git") + developerConnection.set("scm:git:ssh://git@github.com/sourcegraph/scip-java.git") + url.set("https://github.com/sourcegraph/scip-java") + } + } + } + } + } + + val publishing = extensions.getByType() + val signingKey = providers.environmentVariable("PGP_SECRET").map(::decodePgpSecret) + val signingPassword = providers.environmentVariable("PGP_PASSPHRASE") + extensions.configure { + isRequired = signingKey.isPresent && !project.version.toString().endsWith("SNAPSHOT") + if (signingKey.isPresent) { + useInMemoryPgpKeys(signingKey.get(), signingPassword.orNull) + sign(publishing.publications) + } + } +} + +nexusPublishing { + repositories { + sonatype { + username.set(providers.environmentVariable("SONATYPE_USERNAME")) + password.set(providers.environmentVariable("SONATYPE_PASSWORD")) + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} + +project(":scip-shared") { + apply(plugin = "java-library") + + extensions.configure { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + dependencies { + "api"(library("scip-java-bindings")) + } + + tasks.withType().configureEach { + options.release.set(8) + } + + configureMavenPublishing( + displayName = "scip-shared", + descriptionText = "Shared SCIP utilities used by scip-java compiler plugins", + ) +} + +project(":scip-javac") { + apply(plugin = "java-library") + apply(plugin = "com.github.johnrengelman.shadow") + + dependencies { + "api"(project(":scip-shared")) + "testImplementation"(library("junit-jupiter-api")) + "testRuntimeOnly"(library("junit-jupiter-engine")) + "testRuntimeOnly"(library("junit-platform-launcher")) + } + + tasks.named("compileJava") { + options.isDebug = true + val emptyProcessorPath = layout.buildDirectory.dir("empty-processorpath") + options.annotationProcessorPath = files(emptyProcessorPath) + doFirst { + emptyProcessorPath.get().asFile.mkdirs() + } + } + + tasks.named("test") { + jvmArgs(javacTestJvmOptions) + } + + tasks.named("shadowJar") { + archiveClassifier.set("all") + mergeServiceFiles() + exclude("javax/**", "com/sun/**", "sun/**", "META-INF/versions/9/module-info.class") + relocate("com.google", "com.sourcegraph.shaded.com.google") + relocate("google", "com.sourcegraph.shaded.google") + relocate("org.relaxng", "com.sourcegraph.shaded.relaxng") + relocate("com.sourcegraph", "com.sourcegraph.shaded.com.sourcegraph") { + exclude("com.sourcegraph.scip_javac.ScipPlugin") + exclude("com.sourcegraph.scip_javac.InjectScipOptions") + } + } + + configureMavenPublishing( + displayName = "scip-javac", + descriptionText = "A javac plugin to emit SCIP information", + ) +} + +project(":scip-kotlinc") { + apply(plugin = "java-library") + apply(plugin = "org.jetbrains.kotlin.jvm") + apply(plugin = "com.github.johnrengelman.shadow") + + extensions.configure { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + dependencies { + "implementation"(project(":scip-shared")) + "implementation"(library("scip-kotlin-bindings")) + "compileOnly"(library("kotlin-stdlib")) + "compileOnly"(library("kotlin-compiler-embeddable")) + + "testImplementation"(library("kotlin-compiler-embeddable")) + "testImplementation"(library("kotlin-test")) + "testImplementation"(library("kotlin-test-junit5")) + "testImplementation"(library("kotlin-reflect")) + "testImplementation"(library("kotest-assertions-core")) + "testImplementation"(library("kctfork-core")) + "testRuntimeOnly"(library("junit-jupiter-engine")) + "testRuntimeOnly"(library("junit-platform-launcher")) + } + + tasks.withType().configureEach { + compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8) + compilerOptions.freeCompilerArgs.addAll("-Xinline-classes", "-Xcontext-parameters") + } + + tasks.withType().configureEach { + options.release.set(8) + } + + tasks.named("test") { + jvmArgs("-Xmx2g") + } + + tasks.named("shadowJar") { + archiveClassifier.set("all") + mergeServiceFiles() + relocate("com.intellij", "org.jetbrains.kotlin.com.intellij") + } + + configureMavenPublishing( + displayName = "scip-kotlinc", + descriptionText = "A kotlinc plugin to emit SCIP information", + ) +} + +project(":scip-gradle-plugin") { + apply(plugin = "java-library") + apply(plugin = "com.github.johnrengelman.shadow") + + extensions.configure { + archivesName.set("scip-gradle") + } + + dependencies { + "compileOnly"(library("gradle-api")) + "compileOnly"(library("gradle-test-kit")) + } + + tasks.named("shadowJar") { + archiveClassifier.set("all") + } +} + +project(":scip-maven-plugin") { + apply(plugin = "java-library") + + dependencies { + "implementation"(library("maven-plugin-api")) + "implementation"(library("maven-project")) + "compileOnly"(library("maven-plugin-annotations")) + } + + val generatePluginXml = tasks.register("generatePluginXml") { + from("src/main/resources/META-INF/maven/plugin.template.xml") { + rename { "plugin.xml" } + filter { line: String -> line.replace("@VERSION@", project.version.toString()) } + } + into(layout.buildDirectory.dir("generated/resources/pluginXml/META-INF/maven")) + inputs.property("version", project.version.toString()) + } + + extensions.configure { + named("main") { + resources.srcDir(generatePluginXml) + } + } + + configureMavenPublishing( + displayName = "scip-maven-plugin", + descriptionText = "A Maven plugin that exports dependency metadata for scip-java", + ) +} + +project(":scip-aggregator") { + apply(plugin = "java-library") + apply(plugin = "com.google.protobuf") + + dependencies { + "api"(library("scip-java-bindings")) + "implementation"(project(":scip-shared")) + "testImplementation"(library("junit-jupiter-api")) + "testRuntimeOnly"(library("junit-jupiter-engine")) + "testRuntimeOnly"(library("junit-platform-launcher")) + } + + extensions.configure("protobuf") { + protoc { + artifact = "com.google.protobuf:protoc:$protobufVersion" + } + } + + extensions.configure { + named("main") { + proto { + srcDir("src/main/protobuf") + } + } + } + + configureMavenPublishing( + displayName = "scip-aggregator", + descriptionText = "Aggregates compiler-plugin SCIP shards into a single SCIP index", + ) +} + +project(":scip-java") { + apply(plugin = "org.jetbrains.kotlin.jvm") + apply(plugin = "application") + + dependencies { + "implementation"(project(":scip-aggregator")) + "implementation"(library("clikt-jvm")) + "implementation"(library("kotlin-stdlib")) + "implementation"(library("kotlin-compiler-embeddable")) + "implementation"(library("kotlin-scripting-common")) + "implementation"(library("kotlin-scripting-jvm")) + "implementation"(library("kotlin-scripting-dependencies")) + "implementation"(library("kotlin-scripting-dependencies-maven")) + "implementation"(library("kotlinx-serialization-json-jvm")) + + "testImplementation"(library("kotlin-test")) + "testImplementation"(library("kotlin-test-junit5")) + "testRuntimeOnly"(library("junit-jupiter-engine")) + "testRuntimeOnly"(library("junit-platform-launcher")) + } + + tasks.withType().configureEach { + compilerOptions.jvmTarget.set(JvmTarget.JVM_11) + } + + tasks.named("test") { + jvmArgs(javacTestJvmOptions) + systemProperty("scip.jdk.version", "11") + } + + extensions.configure { + mainClass.set("com.sourcegraph.scip_java.ScipJava") + } + + val generateEmbeddedResources = tasks.register("generateEmbeddedResources") { + val javacShadow = project(":scip-javac").tasks.named("shadowJar") + val gradleShadow = project(":scip-gradle-plugin").tasks.named("shadowJar") + val kotlincShadow = project(":scip-kotlinc").tasks.named("shadowJar") + + from(javacShadow.flatMap { it.archiveFile }) { + rename { "scip-plugin.jar" } + } + from(gradleShadow.flatMap { it.archiveFile }) { + rename { "gradle-plugin.jar" } + } + from(kotlincShadow.flatMap { it.archiveFile }) { + rename { "scip-kotlinc.jar" } + } + into(layout.buildDirectory.dir("generated/resources/embedded")) + inputs.property("version", project.version.toString()) + doLast { + destinationDir.resolve("scip-java.properties").writeText("version=${project.version}\n") + } + } + + extensions.configure { + named("main") { + resources.srcDir(generateEmbeddedResources) + } + } + + val generateDistributionVersion = tasks.register("generateDistributionVersion") { + val output = layout.buildDirectory.file("generated/distribution/VERSION") + inputs.property("version", project.version.toString()) + outputs.file(output) + doLast { + val file = output.get().asFile + file.parentFile.mkdirs() + file.writeText("version:=${project.version}\n") + } + } + + extensions.configure { + named("main") { + contents { + from(generateDistributionVersion) + } + } + } + + configureMavenPublishing( + displayName = "scip-java", + descriptionText = "Java and Kotlin indexer for SCIP", + ) +} + +project(":scip-snapshots-java-common") { + apply(plugin = "java-library") + + dependencies { + "compileOnly"(library("lombok")) + "annotationProcessor"(library("lombok")) + } + + val annotationProcessorClasspath = configurations.named("annotationProcessor") + + tasks.named("compileJava") { + val javacShadow = project(":scip-javac").tasks.named("shadowJar") + val scipTargetroot = layout.buildDirectory.dir("scip-targetroot") + dependsOn(javacShadow) + classpath = classpath.plus(files(javacShadow.flatMap { it.archiveFile })) + options.annotationProcessorPath = + annotationProcessorClasspath.get().plus(files(javacShadow.flatMap { it.archiveFile })) + outputs.dir(scipTargetroot) + options.isFork = true + options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacTestJvmOptions + options.compilerArgs.add( + "-Xplugin:scip -text:on -verbose -sourceroot:${rootProject.rootDir.absolutePath} " + + "-targetroot:${scipTargetroot.get().asFile.absolutePath} -randomtimestamp=${System.nanoTime()}" + ) + doFirst { + scipTargetroot.get().asFile.deleteRecursively() + scipTargetroot.get().asFile.mkdirs() + } + } +} + +project(":scip-snapshots-kotlin-common") { + apply(plugin = "java-library") + apply(plugin = "org.jetbrains.kotlin.jvm") + + extensions.configure { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + dependencies { + "implementation"(library("kotlin-stdlib")) + } + + val scipTargetroot = layout.buildDirectory.dir("scip-targetroot") + val javacShadow = project(":scip-javac").tasks.named("shadowJar") + val kotlincShadow = project(":scip-kotlinc").tasks.named("shadowJar") + + tasks.named("compileKotlin") { + dependsOn(kotlincShadow) + inputs.file(kotlincShadow.flatMap { it.archiveFile }) + outputs.dir(scipTargetroot) + compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8) + compilerOptions.freeCompilerArgs.addAll( + "-Xplugin=${kotlincShadow.flatMap { it.archiveFile }.get().asFile.absolutePath}", + "-P", + "plugin:scip-kotlinc:sourceroot=${rootProject.rootDir.absolutePath}", + "-P", + "plugin:scip-kotlinc:targetroot=${scipTargetroot.get().asFile.absolutePath}", + ) + doFirst { + scipTargetroot.get().asFile.deleteRecursively() + scipTargetroot.get().asFile.mkdirs() + } + } + + tasks.named("compileJava") { + dependsOn(javacShadow) + classpath = classpath.plus(files(javacShadow.flatMap { it.archiveFile })) + options.annotationProcessorPath = files(javacShadow.flatMap { it.archiveFile }) + outputs.dir(scipTargetroot) + options.isFork = true + options.release.set(8) + options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacTestJvmOptions + options.compilerArgs.add( + "-Xplugin:scip -sourceroot:${rootProject.rootDir.absolutePath} " + + "-targetroot:${scipTargetroot.get().asFile.absolutePath}" + ) + } +} + +project(":scip-snapshots") { + apply(plugin = "java-library") + + dependencies { + "implementation"(project(":scip-java")) + "implementation"(library("scip-java-bindings")) + "testImplementation"(library("junit-jupiter-api")) + "testRuntimeOnly"(library("junit-jupiter-engine")) + "testRuntimeOnly"(library("junit-platform-launcher")) + } + + val javaCase = project(":scip-snapshots-java-common") + val kotlinCase = project(":scip-snapshots-kotlin-common") + val javaCaseClasses = javaCase.tasks.named("classes") + val kotlinCaseClasses = kotlinCase.tasks.named("classes") + val javaTargetroot = javaCase.layout.buildDirectory.dir("scip-targetroot") + val kotlinTargetroot = kotlinCase.layout.buildDirectory.dir("scip-targetroot") + val snapshotProperties = + mapOf( + "snapshot.sourceroot" to rootProject.rootDir.absolutePath, + "snapshot.cases" to "java-common,kotlin-common", + "snapshot.case.java-common.expectDir" to + rootProject.layout.projectDirectory.dir("scip-snapshots/expected/java/common").asFile.absolutePath, + "snapshot.case.java-common.targetroot" to javaTargetroot.get().asFile.absolutePath, + "snapshot.case.kotlin-common.expectDir" to + rootProject.layout.projectDirectory.dir("scip-snapshots/expected/kotlin/common").asFile.absolutePath, + "snapshot.case.kotlin-common.targetroot" to kotlinTargetroot.get().asFile.absolutePath, + "snapshot.case.kotlin-common.aggregateNoEmitInverseRelationships" to "true", + "scip.jdk.version" to "11", + ) + + tasks.named("test") { + dependsOn(javaCaseClasses, kotlinCaseClasses) + jvmArgs(javacTestJvmOptions) + systemProperties(snapshotProperties) + } + + tasks.register("saveSnapshots") { + group = "verification" + description = "Regenerates Java and Kotlin SCIP snapshot goldens." + dependsOn(tasks.named("classes"), javaCaseClasses, kotlinCaseClasses) + val sourceSets = project.extensions.getByType() + classpath = sourceSets.named("main").get().runtimeClasspath + mainClass.set("tests.SaveSnapshots") + jvmArgs(javacTestJvmOptions) + systemProperties(snapshotProperties) + } +} + +tasks.register("saveSnapshots") { + group = "verification" + description = "Regenerates all SCIP snapshot goldens." + dependsOn(":scip-snapshots:saveSnapshots") +} diff --git a/build.sbt b/build.sbt deleted file mode 100644 index 3dd9bcf23..000000000 --- a/build.sbt +++ /dev/null @@ -1,463 +0,0 @@ -import _root_.kotlin.Keys._ - -lazy val V = - new { - val protobuf = "4.34.2" - val scipBindings = "0.8.0" - val gradle = "8.10" - val kotlinVersion = "2.2.0" - val kotest = "4.6.3" - val kctfork = "0.7.1" - val clikt = "5.0.3" - val kotlinxSerialization = "1.9.0" - } - -// sbt-git's bundled JGit can't read linked worktrees; shell out to -// git CLI there. See https://github.com/sbt/sbt-git/issues/264. -if (file(".git").isFile) - Seq(useReadableConsoleGit) -else - Nil - -inThisBuild( - List( - organization := "com.sourcegraph", - homepage := Some(url("https://github.com/sourcegraph/scip-java")), - dynverSeparator := "-", - PB.protocVersion := V.protobuf, - autoScalaLibrary := false, - crossPaths := false, - // Pin bytecode to major 55 so compiler plugins can run on Java 11. - Compile / javacOptions ++= Seq("--release", "11"), - incOptions ~= { old => - old.withEnabled(false).withApiDebug(true) - }, - licenses := - List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")) - ) -) - -name := "root" -(publish / skip) := true - -// Shared module with the SCIP shard utilities (symbol encoder, document -// builder, on-disk writer) consumed by both the Java compiler plugin -// (scip-javac) and the Kotlin compiler plugin (scip-kotlinc). -lazy val scipShared = project - .in(file("scip-shared")) - .settings( - moduleName := "scip-shared", - libraryDependencies += - "org.scip-code" % "scip-java-bindings" % V.scipBindings - ) - -lazy val javacPlugin = project - .in(file("scip-javac")) - .settings( - moduleName := "scip-javac", - // Scoped to compile so doc tasks (which reject -g) are unaffected. - Compile / compile / javacOptions += "-g", - // JDK 14+ ServiceLoader-scans the classpath for Plugin providers; our - // own META-INF/services entry points at ScipPlugin before it's - // built. Force an empty processor path so javac skips the scan. - Compile / compile / javacOptions ++= { - val empty = target.value / "empty-processorpath" - IO.createDirectory(empty) - Seq("-processorpath", empty.getAbsolutePath) - }, - (assembly / assemblyMergeStrategy) := { - case PathList("javax", _ @_*) => - MergeStrategy.discard - case PathList("com", "sun", _ @_*) => - MergeStrategy.discard - case PathList("sun", _ @_*) => - MergeStrategy.discard - case PathList("META-INF", "versions", "9", "module-info.class") => - MergeStrategy.discard - case x => - val oldStrategy = (assembly / assemblyMergeStrategy).value - oldStrategy(x) - }, - (assembly / assemblyShadeRules) := - Seq( - ShadeRule - .rename( - // Don't rename ScipPlugin since the fully-qualified name is - // referenced from META-INF/services/com.sun.source.util.Plugin - "com.sourcegraph.scip_javac.ScipPlugin" -> - "com.sourcegraph.scip_javac.ScipPlugin", - // Don't rename InjectScipOptions because we load it via FQN to - // process a list of Java compiler options. - "com.sourcegraph.scip_javac.InjectScipOptions" -> - "com.sourcegraph.scip_javac.InjectScipOptions", - "com.google.**" -> "com.sourcegraph.shaded.com.google.@1", - // Shade everything else in the scip-javac compiler plugin in - // order to be able to index the plugin code itself. Without this step, - // we can't add the plugin to the classpath while compiling the source - // code of the plugin itself because it results in cryptic compile errors. - "com.sourcegraph.**" -> "com.sourcegraph.shaded.com.sourcegraph.@1", - "google.**" -> "com.sourcegraph.shaded.google.@1", - "org.relaxng.**" -> "com.sourcegraph.shaded.relaxng.@1" - ) - .inAll - ), - // JUnit 5 for the colocated in-process javac tests (test scope only, so it - // stays out of the published scip-javac POM). - libraryDependencies += "com.github.sbt.junit" % "jupiter-interface" % - JupiterKeys.jupiterVersion.value % Test, - Test / fork := true, - // The tests drive javac in-process via ScipPlugin; on JDK 17+ this requires - // the JDK-internal javac packages to be opened. - Test / javaOptions ++= javacModuleOptions.map(_.stripPrefix("-J")) - ) - .dependsOn(scipShared) - -// The scip-kotlinc compiler plugin. Built as a fat-jar that is later -// embedded into the scip-java CLI distribution (see cli's resourceGenerators) -// so the runtime no longer needs to fetch a published scip-kotlinc -// artifact from Maven. -lazy val scipKotlinc = project - .in(file("scip-kotlinc")) - .enablePlugins(KotlinPlugin) - .settings( - name := "scip-kotlinc", - moduleName := "scip-kotlinc", - description := "A kotlinc plugin to emit SCIP information", - kotlinVersion := V.kotlinVersion, - kotlincJvmTarget := "1.8", - kotlincOptions ++= Seq("-Xinline-classes", "-Xcontext-parameters"), - // sbt-kotlin-plugin defaults to adding `kotlin-scripting-compiler-embeddable` - // (and its transitive kotlin-stdlib) as a regular dependency. Mark them - // Provided — kotlinc supplies them at runtime, and we don't want them - // bundled into the fat-jar. - kotlinRuntimeProvided := true, - // kotlin-stdlib is supplied by kotlinc at runtime — keep on compile - // classpath via Provided so the assembled fat-jar does not bundle it. - libraryDependencies += - "org.jetbrains.kotlin" % "kotlin-stdlib" % V.kotlinVersion % Provided, - // SCIP message classes come from scipShared (which depends on - // scip-java-bindings); this adds the Kotlin DSL extensions on top. - libraryDependencies += - "org.scip-code" % "scip-kotlin-bindings" % V.scipBindings, - // kotlin-compiler-embeddable is supplied by kotlinc at runtime - libraryDependencies += "org.jetbrains.kotlin" % - "kotlin-compiler-embeddable" % V.kotlinVersion % Provided, - // ---- sbt-assembly fat-jar --------------------------------------------- - // Produces a shaded jar for consumers that need a self-contained compiler - // plugin, such as the CLI resource embedding and minimized fixture build. - assembly / assemblyShadeRules := - Seq( - // Relocate any IntelliJ classes the same way kotlin-compiler-embeddable - // does internally. Do NOT rename `com.sourcegraph.**` — the - // META-INF/services files reference those FQNs. - ShadeRule - .rename("com.intellij.**" -> "org.jetbrains.kotlin.com.intellij.@1") - .inAll - ), - // tests - libraryDependencies ++= - Seq( - "org.jetbrains.kotlin" % "kotlin-compiler-embeddable" % - V.kotlinVersion % Test, - "org.jetbrains.kotlin" % "kotlin-test" % V.kotlinVersion % Test, - "org.jetbrains.kotlin" % "kotlin-test-junit5" % V.kotlinVersion % Test, - "org.jetbrains.kotlin" % "kotlin-reflect" % V.kotlinVersion % Test, - "io.kotest" % "kotest-assertions-core-jvm" % V.kotest % Test, - "dev.zacsweers.kctfork" % "core" % V.kctfork % Test, - "com.github.sbt.junit" % "jupiter-interface" % - JupiterKeys.jupiterVersion.value % Test - ), - Test / fork := true, - Test / javaOptions += "-Xmx2g", - // sbt-kotlin-plugin 3.1.6 inspects every jar on the kotlinc classpath and - // moves any jar containing META-INF/services/org.jetbrains.kotlin.compiler.plugin.* - // entries into the compiler-plugin classpath, removing it from the regular - // classpath. kctfork ships such service files for its own internal use as a - // KAPT/registrar shim, which makes its public API (com.tschuchort.compiletesting.*) - // invisible to our test sources. Workaround: pre-extract kctfork to a - // directory and add that directory to the test classpath — sbt-kotlin-plugin - // only inspects .jar files, so directories pass through unmodified. - Test / unmanagedJars += { - val report = update.value - val files = report.allFiles - val jar = files - .find(_.getName == s"core-${V.kctfork}.jar") - .getOrElse( - sys.error(s"kctfork core-${V.kctfork}.jar not found in update report") - ) - val dir = target.value / s"kctfork-${V.kctfork}-extracted" - val marker = dir / ".extracted" - if (!marker.exists()) { - IO.delete(dir) - IO.unzip(jar, dir) - IO.touch(marker) - } - Attributed.blank(dir) - } - ) - .dependsOn(scipShared) - -lazy val gradlePlugin = project - .in(file("scip-gradle-plugin")) - .settings( - name := "scip-gradle", - publish / skip := true, - libraryDependencies ++= - List( - "dev.gradleplugins" % "gradle-api" % V.gradle % Provided, - "dev.gradleplugins" % "gradle-test-kit" % V.gradle % Provided - ) - ) - -lazy val mavenPlugin = project - .in(file("scip-maven-plugin")) - .settings( - moduleName := "scip-maven-plugin", - libraryDependencies ++= - Seq( - "org.apache.maven" % "maven-plugin-api" % "3.6.3", - "org.apache.maven.plugin-tools" % "maven-plugin-annotations" % "3.6.4" % - Provided, - "org.apache.maven" % "maven-project" % "2.2.1" - ), - Compile / resourceGenerators += - Def.task { - val dir = (Compile / managedResourceDirectories).value.head / - "META-INF" / "maven" - IO.createDirectory(dir) - val file = dir / "plugin.xml" - val template = IO.read( - (Compile / resourceDirectory).value / "META-INF" / "maven" / - "plugin.template.xml" - ) - - IO.write(file, template.replace("@VERSION@", version.value)) - - Seq(file) - } - ) - -// Aggregates compiler-plugin shards into the final SCIP index consumed by the CLI. -lazy val scipAggregator = project - .in(file("scip-aggregator")) - .settings( - moduleName := "scip-aggregator", - libraryDependencies ++= - Seq( - "org.scip-code" % "scip-java-bindings" % V.scipBindings, - // JUnit 5 for the colocated Java unit tests (test scope only, so it is - // excluded from the published POM and keeps this a Java-only module). - "com.github.sbt.junit" % "jupiter-interface" % - JupiterKeys.jupiterVersion.value % Test - ), - (Compile / PB.targets) := - Seq(PB.gens.java(V.protobuf) -> (Compile / sourceManaged).value) - ) - .dependsOn(scipShared) - -lazy val cli = project - .in(file("scip-java")) - .enablePlugins(KotlinPlugin, PackPlugin) - .settings( - moduleName := "scip-java", - kotlinVersion := V.kotlinVersion, - kotlincJvmTarget := "11", - (Compile / mainClass) := Some("com.sourcegraph.scip_java.ScipJava"), - (run / baseDirectory) := (ThisBuild / baseDirectory).value, - // ScipJava.main can call System.exit, so we always fork the JVM when - // sbt invokes it directly so it cannot kill the surrounding sbt process. - Compile / run / fork := true, - Test / fork := true, - // Our CI set up is a couple of measly vCPUs so parallelising tests there makes - // everything worse. - Test / testForkedParallel := !sys.env.contains("CI"), - // The SCIP build tool drives javac in-process; on JDK 17+ this requires - // opening the JDK-internal javac packages. - Test / javaOptions ++= javacModuleOptions.map(_.stripPrefix("-J")), - // Pin the JDK version embedded in stdlib SCIP symbols so output is stable. - Test / javaOptions += "-Dscip.jdk.version=11", - libraryDependencies ++= - List( - "com.github.ajalt.clikt" % "clikt-jvm" % V.clikt, - "org.jetbrains.kotlinx" % "kotlinx-serialization-json-jvm" % - V.kotlinxSerialization, - "org.jetbrains.kotlin" % "kotlin-compiler-embeddable" % V.kotlinVersion, - "org.jetbrains.kotlin" % "kotlin-scripting-common" % V.kotlinVersion, - "org.jetbrains.kotlin" % "kotlin-scripting-jvm" % V.kotlinVersion, - "org.jetbrains.kotlin" % "kotlin-scripting-dependencies" % - V.kotlinVersion, - "org.jetbrains.kotlin" % "kotlin-scripting-dependencies-maven" % - V.kotlinVersion - ), - libraryDependencies ++= - Seq( - "org.jetbrains.kotlin" % "kotlin-test" % V.kotlinVersion % Test, - "org.jetbrains.kotlin" % "kotlin-test-junit5" % V.kotlinVersion % Test, - "com.github.sbt.junit" % "jupiter-interface" % - JupiterKeys.jupiterVersion.value % Test - ), - (Compile / resourceGenerators) += - Def - .task { - val out = (Compile / resourceManaged).value.toPath - IO.delete(out.toFile) - - val outs = Seq( - (javacPlugin / Compile / assembly).value -> - out.resolve("scip-plugin.jar").toFile, - (gradlePlugin / Compile / assembly).value -> - out.resolve("gradle-plugin.jar").toFile, - (scipKotlinc / Compile / assembly).value -> - out.resolve("scip-kotlinc.jar").toFile - ) - - IO.copy( - outs, - overwrite = true, - preserveLastModified = false, - preserveExecutable = true - ) - val propsFile = out.resolve("scip-java.properties").toFile - // Build version consumed at runtime by BuildInfo.version (Kotlin). - IO.write(propsFile, s"version=${version.value}\n") - - propsFile +: outs.map(_._2) - } - .taskValue - ) - .dependsOn(scipAggregator) - -// Kotlin snapshot case. The fixture includes Java sources as interop -// consumers, but the case is still keyed by the Kotlin compiler/plugin version -// axis. It writes *.scip shards under target/scip-targetroot/ for the central -// scipSnapshots project to aggregate and compare with goldens. -lazy val scipSnapshotsKotlinCommon = project - .in(file("scip-snapshots/cases/kotlin/common")) - .enablePlugins(KotlinPlugin) - .settings( - publish / skip := true, - kotlinVersion := V.kotlinVersion, - kotlincJvmTarget := "1.8", - kotlinLib("stdlib"), - // Force javac to fork. Two reasons: - // 1. JDK 9+ strongly encapsulates jdk.compiler internals; scip-javac - // reflectively touches them and needs --add-exports flags. With a - // forked javac we can pass `-J--add-exports=...` (mirrors scip-java). - // 2. sbt's in-process javac receives `vf://` virtual-file URIs from the - // MappedFileConverter, which scip-javac cannot resolve via - // java.nio.file.Path.of. Forked javac is invoked with absolute file - // paths instead, so the plugin sees real paths. - // Setting javaHome to Some() flips - // ZincUtil.compilers/JavaTools.directOrFork from direct → fork. - javaHome := Some(file(System.getProperty("java.home"))), - Compile / javacOptions ++= javacModuleOptions, - // Attach the assembled kotlinc fat-jar to the compile classpath. - // sbt-kotlin-plugin's AnalyzingKotlinCompiler partitions the classpath: - // any jar containing META-INF/services/org.jetbrains.kotlin.compiler.plugin* - // entries (which our fat-jar does, for both CommandLineProcessor and - // CompilerPluginRegistrar) is moved into args.pluginClasspaths and removed - // from the regular classpath. So no `-Xplugin=` is needed and we - // don't have to predict the assembled jar's filename. The .value reference - // also gives us the right task ordering — assembly runs before compile. - Compile / unmanagedJars += - Attributed.blank((scipKotlinc / Compile / assembly).value), - // Wire the locally-built scip-javac fat jar in place of fetching the - // published `com.sourcegraph:scip-javac` artifact at compile time. - Compile / unmanagedJars += - Attributed.blank((javacPlugin / Compile / assembly).value), - Compile / kotlincPluginOptions ++= { - val srcRoot = (ThisBuild / baseDirectory).value.getAbsolutePath - val tgtRoot = (target.value / "scip-targetroot").getAbsolutePath - Seq( - s"plugin:scip-kotlinc:sourceroot=$srcRoot", - s"plugin:scip-kotlinc:targetroot=$tgtRoot" - ) - }, - // The scip javac plugin parses its own argument string, so - // `-Xplugin:scip -sourceroot:<...> -targetroot:<...>` MUST be passed - // as a single javac argument (matches the existing Gradle behavior). - Compile / javacOptions += { - val srcRoot = (ThisBuild / baseDirectory).value - val tgtRoot = target.value / "scip-targetroot" - s"-Xplugin:scip -sourceroot:${srcRoot.getAbsolutePath} " + - s"-targetroot:${tgtRoot.getAbsolutePath}" - } - ) - -lazy val scipSnapshotsJavaCommon = project - .in(file("scip-snapshots/cases/java/common")) - .settings( - publish / skip := true, - run / fork := true, - libraryDependencies += "org.projectlombok" % "lombok" % "1.18.22", - // Fork javac so it receives real file paths instead of sbt's `vf://` virtual-file URIs - // (see the comment on `scipSnapshotsKotlinCommon` for the long story). - javaHome := Some(file(System.getProperty("java.home"))), - // Keep minimized snapshots stable across JDK 11/17/21. - Compile / javacOptions ++= Seq("--release", "11"), - Compile / javacOptions ++= javacModuleOptions, - javacOptions += - List( - s"-Xplugin:scip", - s"-text:on", - s"-verbose", - s"-sourceroot:${(ThisBuild / baseDirectory).value}", - s"-targetroot:${(Compile / semanticdbTargetRoot).value}", - s"-randomtimestamp=${System.nanoTime()}" - ).mkString(" ") - ) - .dependsOn(javacPlugin) - -def javacModuleOptions = List( - "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" -) - -lazy val scipSnapshots = project - .in(file("scip-snapshots")) - .settings( - publish / skip := true, - Test / fork := true, - // Open the JDK-internal javac packages to the in-process javac the tests - // drive; on JDK 17+ this is required or the reflective access fails. - Test / javaOptions ++= javacModuleOptions.map(_.stripPrefix("-J")), - // Pin the JDK version embedded in stdlib SCIP symbols (e.g. `jdk 11 - // java/lang/String#`) so snapshots are stable across JDK 11/17/21. - Test / javaOptions += "-Dscip.jdk.version=11", - libraryDependencies += "com.github.sbt.junit" % "jupiter-interface" % - JupiterKeys.jupiterVersion.value % Test, - Compile / mainClass := Some("tests.SaveSnapshots"), - Compile / run / fork := true, - Test / javaOptions ++= snapshotPathOptions.value, - Compile / run / javaOptions ++= snapshotPathOptions.value - ) - .dependsOn(cli) - -// Runtime paths for the snapshot generator, passed as -D system properties. -// Depending on each snapshot case's compile task guarantees fresh targetroots -// whenever `scipSnapshots/test` or `scipSnapshots/run` evaluate javaOptions. -def snapshotPathOptions = Def.task { - val _java = (scipSnapshotsJavaCommon / Compile / compile).value - val _kotlin = (scipSnapshotsKotlinCommon / Compile / compile).value - val snapshotRoot = (ThisBuild / baseDirectory).value / "scip-snapshots" - Seq( - s"-Dsnapshot.sourceroot=${(ThisBuild / baseDirectory).value.getAbsolutePath}", - "-Dsnapshot.cases=java-common,kotlin-common", - s"-Dsnapshot.case.java-common.expectDir=${( - snapshotRoot / "expected" / "java" / "common" - ).getAbsolutePath}", - s"-Dsnapshot.case.java-common.targetroot=${( - scipSnapshotsJavaCommon / Compile / semanticdbTargetRoot - ).value.getAbsolutePath}", - s"-Dsnapshot.case.kotlin-common.expectDir=${( - snapshotRoot / "expected" / "kotlin" / "common" - ).getAbsolutePath}", - s"-Dsnapshot.case.kotlin-common.targetroot=${(( - scipSnapshotsKotlinCommon / target - ).value / "scip-targetroot").getAbsolutePath}", - "-Dsnapshot.case.kotlin-common.aggregateNoEmitInverseRelationships=true" - ) -} diff --git a/docs/getting-started.md b/docs/getting-started.md index 2707c705d..d8f5c7a8b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -66,11 +66,11 @@ Docker image with a pre-installed Java version. # macOS/Linux curl -fLo coursier https://git.io/coursier-cli \ && chmod +x coursier \ - && ./coursier launch com.sourcegraph:scip-java_2.13:@STABLE_VERSION@ -- --help + && ./coursier launch com.sourcegraph:scip-java:@STABLE_VERSION@ -- --help # macOS Homebrew brew install coursier/formulas/coursier \ - && coursier launch com.sourcegraph:scip-java_2.13:@STABLE_VERSION@ -- --help + && coursier launch com.sourcegraph:scip-java:@STABLE_VERSION@ -- --help ``` The Java launcher uses @@ -92,7 +92,7 @@ you still need a Java installation to run the `scip-java` binary. # macOS/Linux curl -fLo coursier https://git.io/coursier-cli \ && chmod +x coursier \ - && ./coursier bootstrap --standalone -o scip-java com.sourcegraph:scip-java_2.13:@STABLE_VERSION@ --main com.sourcegraph.scip_java.ScipJava + && ./coursier bootstrap --standalone -o scip-java com.sourcegraph:scip-java:@STABLE_VERSION@ --main com.sourcegraph.scip_java.ScipJava ./scip-java --help ``` @@ -107,12 +107,12 @@ The `scip-java` command-line interface is published to Maven Central. You can run the command-line interface as a library by directly invoking the `main()` method on the `com.sourcegraph.scip_java.ScipJava` class. -[![](https://img.shields.io/maven-central/v/com.sourcegraph/scip-java_2.13)](https://repo1.maven.org/maven2/com/sourcegraph/scip-java_2.13/) +[![](https://img.shields.io/maven-central/v/com.sourcegraph/scip-java)](https://repo1.maven.org/maven2/com/sourcegraph/scip-java/) If you're using Gradle. ```groovy -implementation group: 'com.sourcegraph', name: 'scip-java_2.13', version: '@STABLE_VERSION@' +implementation group: 'com.sourcegraph', name: 'scip-java', version: '@STABLE_VERSION@' ``` If you're using Maven. @@ -120,7 +120,7 @@ If you're using Maven. ```xml com.sourcegraph - scip-java_2.13 + scip-java @STABLE_VERSION@ ``` diff --git a/flake.nix b/flake.nix index bbe5eece7..53b054dc4 100644 --- a/flake.nix +++ b/flake.nix @@ -37,7 +37,6 @@ (maven.override ({ jdk_headless = jdk; })) nixfmt nodejs - (sbt.override ({ jre = jdk; })) scipCli yarn ]; diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..1eafd41ed --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 +kotlin.code.style=official +kotlin.stdlib.default.dependency=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..96e350a55 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,48 @@ +[versions] +clikt = "5.0.3" +gradle-api = "8.10" +junit-jupiter = "5.11.4" +junit-platform = "1.11.4" +kctfork = "0.7.1" +kotest = "4.6.3" +kotlin = "2.2.0" +kotlinx-serialization = "1.9.0" +lombok = "1.18.22" +maven-plugin-annotations = "3.6.4" +maven-plugin-api = "3.6.3" +maven-project = "2.2.1" +protobuf = "4.34.2" +protobuf-plugin = "0.9.4" +scip-bindings = "0.8.0" +shadow = "8.1.1" + +[libraries] +clikt-jvm = { module = "com.github.ajalt.clikt:clikt-jvm", version.ref = "clikt" } +gradle-api = { module = "dev.gradleplugins:gradle-api", version.ref = "gradle-api" } +gradle-test-kit = { module = "dev.gradleplugins:gradle-test-kit", version.ref = "gradle-api" } +junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" } +junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junit-platform" } +kctfork-core = { module = "dev.zacsweers.kctfork:core", version.ref = "kctfork" } +kotest-assertions-core = { module = "io.kotest:kotest-assertions-core-jvm", version.ref = "kotest" } +kotlin-compiler-embeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } +kotlin-scripting-common = { module = "org.jetbrains.kotlin:kotlin-scripting-common", version.ref = "kotlin" } +kotlin-scripting-dependencies = { module = "org.jetbrains.kotlin:kotlin-scripting-dependencies", version.ref = "kotlin" } +kotlin-scripting-dependencies-maven = { module = "org.jetbrains.kotlin:kotlin-scripting-dependencies-maven", version.ref = "kotlin" } +kotlin-scripting-jvm = { module = "org.jetbrains.kotlin:kotlin-scripting-jvm", version.ref = "kotlin" } +kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +kotlin-test-junit5 = { module = "org.jetbrains.kotlin:kotlin-test-junit5", version.ref = "kotlin" } +kotlinx-serialization-json-jvm = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm", version.ref = "kotlinx-serialization" } +lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" } +maven-plugin-annotations = { module = "org.apache.maven.plugin-tools:maven-plugin-annotations", version.ref = "maven-plugin-annotations" } +maven-plugin-api = { module = "org.apache.maven:maven-plugin-api", version.ref = "maven-plugin-api" } +maven-project = { module = "org.apache.maven:maven-project", version.ref = "maven-project" } +scip-java-bindings = { module = "org.scip-code:scip-java-bindings", version.ref = "scip-bindings" } +scip-kotlin-bindings = { module = "org.scip-code:scip-kotlin-bindings", version.ref = "scip-bindings" } + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" } +shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } diff --git a/project/build.properties b/project/build.properties deleted file mode 100644 index c02c575fd..000000000 --- a/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=1.11.3 diff --git a/project/plugins.sbt b/project/plugins.sbt deleted file mode 100644 index b098a7edd..000000000 --- a/project/plugins.sbt +++ /dev/null @@ -1,6 +0,0 @@ -addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.16") -addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.11.1") -addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.6") -addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") -addSbtPlugin("org.jetbrains.scala" % "sbt-kotlin-plugin" % "3.1.6") -addSbtPlugin("com.github.sbt.junit" % "sbt-jupiter-interface" % "0.15.1") diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt index 058f91489..2b5948804 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt @@ -5,9 +5,8 @@ import java.util.Properties /** * Build metadata for the scip-java CLI. * - * Replaces the previously sbt-generated `BuildInfo.java`. The static [javacModuleOptions] live here - * directly; the build-time [version] is injected by sbt into the `scip-java.properties` classpath - * resource (see the `resourceGenerators` for the `cli` project in build.sbt). + * The static [javacModuleOptions] live here directly; the build-time [version] is injected by + * Gradle into the `scip-java.properties` classpath resource. */ object BuildInfo { @@ -15,7 +14,7 @@ object BuildInfo { * `--add-exports` flags required to access internal javac APIs from the SCIP compiler plugin. * Java 11+ is the supported baseline. * - * Kept in sync with `javacModuleOptions` in build.sbt, which applies the same flags when + * Kept in sync with `javacModuleOptions` in build.gradle.kts, which applies the same flags when * compiling the plugin and the test fixtures. */ val javacModuleOptions: List = @@ -28,7 +27,7 @@ object BuildInfo { ) /** - * The scip-java release version. Read from the `scip-java.properties` resource that sbt + * The scip-java release version. Read from the `scip-java.properties` resource that Gradle * generates into the jar. Falls back to a placeholder when running without the generated * resource on the classpath. */ diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt index 7b0eef76b..e1afb95ac 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt @@ -166,7 +166,7 @@ class ScipBuildTool(index: IndexCommand) : BuildTool("SCIP", index) { // The scip-kotlinc compiler plugin is built and shipped together // with the scip-java CLI as an embedded resource (see Embedded.kt and - // the cli/resourceGenerators task in build.sbt). + // the :scip-java Gradle resources wiring). val plugin = Embedded.scipKotlincJar(tmp) val classpath = diff --git a/scip-snapshots/README.md b/scip-snapshots/README.md index 22455a71b..1da6073c1 100644 --- a/scip-snapshots/README.md +++ b/scip-snapshots/README.md @@ -20,5 +20,5 @@ expected/ version-specific cases when a fixture needs newer language features, for example `cases/java/release-17`, `cases/java/release-21`, or `cases/kotlin/kotlin-2.2`. -Run `sbt scipSnapshots/test` to compare goldens and `sbt scipSnapshots/run` to -regenerate them. +Run `gradle :scip-snapshots:test` to compare goldens and +`gradle :scip-snapshots:saveSnapshots` to regenerate them. diff --git a/scip-snapshots/src/main/java/tests/MinimizedSnapshotScipGenerator.java b/scip-snapshots/src/main/java/tests/MinimizedSnapshotScipGenerator.java index 8b61cedca..dc635c0ce 100644 --- a/scip-snapshots/src/main/java/tests/MinimizedSnapshotScipGenerator.java +++ b/scip-snapshots/src/main/java/tests/MinimizedSnapshotScipGenerator.java @@ -18,8 +18,7 @@ /** * Indexes the {@code scip-snapshots/cases} corpora and renders golden SCIP snapshots. Runtime paths - * are supplied as {@code -Dsnapshot.*} system properties by the sbt build (see build.sbt), - * replacing the former sbt-buildinfo generated values. + * are supplied as {@code -Dsnapshot.*} system properties by the Gradle build. */ public class MinimizedSnapshotScipGenerator { public static final class SnapshotCase { @@ -140,7 +139,9 @@ private static String requiredProperty(String name) { String value = System.getProperty(name); if (value == null || value.trim().isEmpty()) { throw new IllegalStateException( - "Missing -D" + name + ". Run via sbt scipSnapshots/test or scipSnapshots/run."); + "Missing -D" + + name + + ". Run via gradle :scip-snapshots:test or :scip-snapshots:saveSnapshots."); } return value; } diff --git a/scip-snapshots/src/main/java/tests/SaveSnapshots.java b/scip-snapshots/src/main/java/tests/SaveSnapshots.java index 40affa330..1180e8d6e 100644 --- a/scip-snapshots/src/main/java/tests/SaveSnapshots.java +++ b/scip-snapshots/src/main/java/tests/SaveSnapshots.java @@ -1,15 +1,15 @@ package tests; /** - * Regenerates all snapshot goldens (invoked by {@code sbt scipSnapshots/run}). Snapshot cases are - * supplied via {@code -Dsnapshot.*} system properties by the sbt build. + * Regenerates all snapshot goldens (invoked by {@code gradle :scip-snapshots:saveSnapshots}). + * Snapshot cases are supplied via {@code -Dsnapshot.*} system properties by the Gradle build. */ public final class SaveSnapshots { private SaveSnapshots() {} public static void main(String[] args) { // Keep regenerated goldens stable across JDK 11/17/21 by pinning the JDK version embedded in - // stdlib SCIP symbols. Matches the `-Dscip.jdk.version=11` set on the test JVM in build.sbt. + // stdlib SCIP symbols. Matches the `-Dscip.jdk.version=11` set on the test JVM in Gradle. System.setProperty("scip.jdk.version", "11"); MinimizedSnapshotScipGenerator generator = new MinimizedSnapshotScipGenerator(); for (MinimizedSnapshotScipGenerator.SnapshotCase snapshotCase : diff --git a/scip-snapshots/src/test/java/tests/AssertSnapshotHandler.java b/scip-snapshots/src/test/java/tests/AssertSnapshotHandler.java index 3882b626a..201ba04b3 100644 --- a/scip-snapshots/src/test/java/tests/AssertSnapshotHandler.java +++ b/scip-snapshots/src/test/java/tests/AssertSnapshotHandler.java @@ -40,7 +40,8 @@ public void onSnapshotTest( fail( "no snapshot file for " + relativePath - + ". To fix this problem, execute the command 'sbt scipSnapshots/run'"); + + ". To fix this problem, execute the command 'gradle" + + " :scip-snapshots:saveSnapshots'"); } String expected; try { diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..a0f22fcdb --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,32 @@ +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = "scip-java" + +include( + "scip-shared", + "scip-javac", + "scip-kotlinc", + "scip-aggregator", + "scip-maven-plugin", + "scip-gradle-plugin", + "scip-java", + "scip-snapshots", + "scip-snapshots-java-common", + "scip-snapshots-kotlin-common", +) + +project(":scip-snapshots-java-common").projectDir = file("scip-snapshots/cases/java/common") +project(":scip-snapshots-kotlin-common").projectDir = file("scip-snapshots/cases/kotlin/common") From 26aa5f0a04665737f52449ea2018dd7fba82f399 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 12:04:18 +0200 Subject: [PATCH 02/15] Fix Maven plugin descriptor --- build.gradle.kts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 828e38697..5f1465afb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,6 @@ import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.Copy import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.Sync @@ -20,6 +19,7 @@ import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.api.tasks.testing.Test import org.gradle.external.javadoc.StandardJavadocDocletOptions +import org.gradle.language.jvm.tasks.ProcessResources import org.gradle.plugins.signing.SigningExtension import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -306,21 +306,16 @@ project(":scip-maven-plugin") { "compileOnly"(library("maven-plugin-annotations")) } - val generatePluginXml = tasks.register("generatePluginXml") { + tasks.named("processResources") { + exclude("META-INF/maven/plugin.template.xml") from("src/main/resources/META-INF/maven/plugin.template.xml") { + into("META-INF/maven") rename { "plugin.xml" } filter { line: String -> line.replace("@VERSION@", project.version.toString()) } } - into(layout.buildDirectory.dir("generated/resources/pluginXml/META-INF/maven")) inputs.property("version", project.version.toString()) } - extensions.configure { - named("main") { - resources.srcDir(generatePluginXml) - } - } - configureMavenPublishing( displayName = "scip-maven-plugin", descriptionText = "A Maven plugin that exports dependency metadata for scip-java", From c2a793b476255a7c3ddc7922b0bca1a2a0073704 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 12:49:37 +0200 Subject: [PATCH 03/15] Simplify Gradle build --- build.gradle.kts | 46 +++++++++------------------------------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5f1465afb..f3fe722a1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -83,8 +83,6 @@ subprojects { extensions.configure { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 - withSourcesJar() - withJavadocJar() } tasks.withType().configureEach { @@ -110,6 +108,11 @@ fun Project.configureMavenPublishing(displayName: String, descriptionText: Strin apply(plugin = "maven-publish") apply(plugin = "signing") + extensions.configure { + withSourcesJar() + withJavadocJar() + } + extensions.configure { publications { create("mavenJava") { @@ -166,19 +169,10 @@ nexusPublishing { project(":scip-shared") { apply(plugin = "java-library") - extensions.configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - dependencies { "api"(library("scip-java-bindings")) } - tasks.withType().configureEach { - options.release.set(8) - } - configureMavenPublishing( displayName = "scip-shared", descriptionText = "Shared SCIP utilities used by scip-java compiler plugins", @@ -210,7 +204,6 @@ project(":scip-javac") { } tasks.named("shadowJar") { - archiveClassifier.set("all") mergeServiceFiles() exclude("javax/**", "com/sun/**", "sun/**", "META-INF/versions/9/module-info.class") relocate("com.google", "com.sourcegraph.shaded.com.google") @@ -233,11 +226,6 @@ project(":scip-kotlinc") { apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "com.github.johnrengelman.shadow") - extensions.configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - dependencies { "implementation"(project(":scip-shared")) "implementation"(library("scip-kotlin-bindings")) @@ -255,20 +243,15 @@ project(":scip-kotlinc") { } tasks.withType().configureEach { - compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8) + compilerOptions.jvmTarget.set(JvmTarget.JVM_11) compilerOptions.freeCompilerArgs.addAll("-Xinline-classes", "-Xcontext-parameters") } - tasks.withType().configureEach { - options.release.set(8) - } - tasks.named("test") { jvmArgs("-Xmx2g") } tasks.named("shadowJar") { - archiveClassifier.set("all") mergeServiceFiles() relocate("com.intellij", "org.jetbrains.kotlin.com.intellij") } @@ -292,9 +275,6 @@ project(":scip-gradle-plugin") { "compileOnly"(library("gradle-test-kit")) } - tasks.named("shadowJar") { - archiveClassifier.set("all") - } } project(":scip-maven-plugin") { @@ -409,10 +389,8 @@ project(":scip-java") { } } - extensions.configure { - named("main") { - resources.srcDir(generateEmbeddedResources) - } + tasks.named("processResources") { + from(generateEmbeddedResources) } val generateDistributionVersion = tasks.register("generateDistributionVersion") { @@ -475,11 +453,6 @@ project(":scip-snapshots-kotlin-common") { apply(plugin = "java-library") apply(plugin = "org.jetbrains.kotlin.jvm") - extensions.configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - dependencies { "implementation"(library("kotlin-stdlib")) } @@ -492,7 +465,7 @@ project(":scip-snapshots-kotlin-common") { dependsOn(kotlincShadow) inputs.file(kotlincShadow.flatMap { it.archiveFile }) outputs.dir(scipTargetroot) - compilerOptions.jvmTarget.set(JvmTarget.JVM_1_8) + compilerOptions.jvmTarget.set(JvmTarget.JVM_11) compilerOptions.freeCompilerArgs.addAll( "-Xplugin=${kotlincShadow.flatMap { it.archiveFile }.get().asFile.absolutePath}", "-P", @@ -512,7 +485,6 @@ project(":scip-snapshots-kotlin-common") { options.annotationProcessorPath = files(javacShadow.flatMap { it.archiveFile }) outputs.dir(scipTargetroot) options.isFork = true - options.release.set(8) options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacTestJvmOptions options.compilerArgs.add( "-Xplugin:scip -sourceroot:${rootProject.rootDir.absolutePath} " + From 8d3fc2a9c26bf44cbd0b4d7d9bc8a617ec90a917 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:00:39 +0200 Subject: [PATCH 04/15] Simplify Gradle configuration --- build.gradle.kts | 110 ++++++++++++++++++++++------------------------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f3fe722a1..c5fb3869b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,7 @@ import com.google.protobuf.gradle.proto import java.nio.charset.StandardCharsets import java.util.Base64 import org.gradle.api.JavaVersion -import org.gradle.api.artifacts.VersionCatalogsExtension import org.gradle.api.distribution.DistributionContainer -import org.gradle.api.plugins.BasePluginExtension import org.gradle.api.plugins.JavaApplication import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPluginExtension @@ -62,9 +60,8 @@ val javacModuleOptions = "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", ) val javacTestJvmOptions = javacModuleOptions.map { it.removePrefix("-J") } -val versionCatalog = extensions.getByType().named("libs") -val protobufVersion = versionCatalog.findVersion("protobuf").get().requiredVersion -fun library(alias: String) = versionCatalog.findLibrary(alias).get() +val catalog = libs +val protobufVersion = catalog.versions.protobuf.asProvider().get() allprojects { group = rootProject.group @@ -102,6 +99,12 @@ subprojects { } } } + + plugins.withId("org.jetbrains.kotlin.jvm") { + tasks.withType().configureEach { + compilerOptions.jvmTarget.set(JvmTarget.JVM_11) + } + } } fun Project.configureMavenPublishing(displayName: String, descriptionText: String) { @@ -170,7 +173,7 @@ project(":scip-shared") { apply(plugin = "java-library") dependencies { - "api"(library("scip-java-bindings")) + "api"(catalog.scip.java.bindings) } configureMavenPublishing( @@ -185,9 +188,9 @@ project(":scip-javac") { dependencies { "api"(project(":scip-shared")) - "testImplementation"(library("junit-jupiter-api")) - "testRuntimeOnly"(library("junit-jupiter-engine")) - "testRuntimeOnly"(library("junit-platform-launcher")) + "testImplementation"(catalog.junit.jupiter.api) + "testRuntimeOnly"(catalog.junit.jupiter.engine) + "testRuntimeOnly"(catalog.junit.platform.launcher) } tasks.named("compileJava") { @@ -228,22 +231,21 @@ project(":scip-kotlinc") { dependencies { "implementation"(project(":scip-shared")) - "implementation"(library("scip-kotlin-bindings")) - "compileOnly"(library("kotlin-stdlib")) - "compileOnly"(library("kotlin-compiler-embeddable")) + "implementation"(catalog.scip.kotlin.bindings) + "compileOnly"(catalog.kotlin.stdlib) + "compileOnly"(catalog.kotlin.compiler.embeddable) - "testImplementation"(library("kotlin-compiler-embeddable")) - "testImplementation"(library("kotlin-test")) - "testImplementation"(library("kotlin-test-junit5")) - "testImplementation"(library("kotlin-reflect")) - "testImplementation"(library("kotest-assertions-core")) - "testImplementation"(library("kctfork-core")) - "testRuntimeOnly"(library("junit-jupiter-engine")) - "testRuntimeOnly"(library("junit-platform-launcher")) + "testImplementation"(catalog.kotlin.compiler.embeddable) + "testImplementation"(catalog.kotlin.test) + "testImplementation"(catalog.kotlin.test.junit5) + "testImplementation"(catalog.kotlin.reflect) + "testImplementation"(catalog.kotest.assertions.core) + "testImplementation"(catalog.kctfork.core) + "testRuntimeOnly"(catalog.junit.jupiter.engine) + "testRuntimeOnly"(catalog.junit.platform.launcher) } tasks.withType().configureEach { - compilerOptions.jvmTarget.set(JvmTarget.JVM_11) compilerOptions.freeCompilerArgs.addAll("-Xinline-classes", "-Xcontext-parameters") } @@ -266,24 +268,19 @@ project(":scip-gradle-plugin") { apply(plugin = "java-library") apply(plugin = "com.github.johnrengelman.shadow") - extensions.configure { - archivesName.set("scip-gradle") - } - dependencies { - "compileOnly"(library("gradle-api")) - "compileOnly"(library("gradle-test-kit")) + "compileOnly"(catalog.gradle.api) + "compileOnly"(catalog.gradle.test.kit) } - } project(":scip-maven-plugin") { apply(plugin = "java-library") dependencies { - "implementation"(library("maven-plugin-api")) - "implementation"(library("maven-project")) - "compileOnly"(library("maven-plugin-annotations")) + "implementation"(catalog.maven.plugin.api) + "implementation"(catalog.maven.project) + "compileOnly"(catalog.maven.plugin.annotations) } tasks.named("processResources") { @@ -307,11 +304,11 @@ project(":scip-aggregator") { apply(plugin = "com.google.protobuf") dependencies { - "api"(library("scip-java-bindings")) + "api"(catalog.scip.java.bindings) "implementation"(project(":scip-shared")) - "testImplementation"(library("junit-jupiter-api")) - "testRuntimeOnly"(library("junit-jupiter-engine")) - "testRuntimeOnly"(library("junit-platform-launcher")) + "testImplementation"(catalog.junit.jupiter.api) + "testRuntimeOnly"(catalog.junit.jupiter.engine) + "testRuntimeOnly"(catalog.junit.platform.launcher) } extensions.configure("protobuf") { @@ -340,23 +337,19 @@ project(":scip-java") { dependencies { "implementation"(project(":scip-aggregator")) - "implementation"(library("clikt-jvm")) - "implementation"(library("kotlin-stdlib")) - "implementation"(library("kotlin-compiler-embeddable")) - "implementation"(library("kotlin-scripting-common")) - "implementation"(library("kotlin-scripting-jvm")) - "implementation"(library("kotlin-scripting-dependencies")) - "implementation"(library("kotlin-scripting-dependencies-maven")) - "implementation"(library("kotlinx-serialization-json-jvm")) - - "testImplementation"(library("kotlin-test")) - "testImplementation"(library("kotlin-test-junit5")) - "testRuntimeOnly"(library("junit-jupiter-engine")) - "testRuntimeOnly"(library("junit-platform-launcher")) - } + "implementation"(catalog.clikt.jvm) + "implementation"(catalog.kotlin.stdlib) + "implementation"(catalog.kotlin.compiler.embeddable) + "implementation"(catalog.kotlin.scripting.common) + "implementation"(catalog.kotlin.scripting.jvm) + "implementation"(catalog.kotlin.scripting.dependencies) + "implementation"(catalog.kotlin.scripting.dependencies.maven) + "implementation"(catalog.kotlinx.serialization.json.jvm) - tasks.withType().configureEach { - compilerOptions.jvmTarget.set(JvmTarget.JVM_11) + "testImplementation"(catalog.kotlin.test) + "testImplementation"(catalog.kotlin.test.junit5) + "testRuntimeOnly"(catalog.junit.jupiter.engine) + "testRuntimeOnly"(catalog.junit.platform.launcher) } tasks.named("test") { @@ -422,8 +415,8 @@ project(":scip-snapshots-java-common") { apply(plugin = "java-library") dependencies { - "compileOnly"(library("lombok")) - "annotationProcessor"(library("lombok")) + "compileOnly"(catalog.lombok) + "annotationProcessor"(catalog.lombok) } val annotationProcessorClasspath = configurations.named("annotationProcessor") @@ -454,7 +447,7 @@ project(":scip-snapshots-kotlin-common") { apply(plugin = "org.jetbrains.kotlin.jvm") dependencies { - "implementation"(library("kotlin-stdlib")) + "implementation"(catalog.kotlin.stdlib) } val scipTargetroot = layout.buildDirectory.dir("scip-targetroot") @@ -465,7 +458,6 @@ project(":scip-snapshots-kotlin-common") { dependsOn(kotlincShadow) inputs.file(kotlincShadow.flatMap { it.archiveFile }) outputs.dir(scipTargetroot) - compilerOptions.jvmTarget.set(JvmTarget.JVM_11) compilerOptions.freeCompilerArgs.addAll( "-Xplugin=${kotlincShadow.flatMap { it.archiveFile }.get().asFile.absolutePath}", "-P", @@ -498,10 +490,10 @@ project(":scip-snapshots") { dependencies { "implementation"(project(":scip-java")) - "implementation"(library("scip-java-bindings")) - "testImplementation"(library("junit-jupiter-api")) - "testRuntimeOnly"(library("junit-jupiter-engine")) - "testRuntimeOnly"(library("junit-platform-launcher")) + "implementation"(catalog.scip.java.bindings) + "testImplementation"(catalog.junit.jupiter.api) + "testRuntimeOnly"(catalog.junit.jupiter.engine) + "testRuntimeOnly"(catalog.junit.platform.launcher) } val javaCase = project(":scip-snapshots-java-common") From 8a60fcc91c2a51db0b624ac2fa144887b6c2d70a Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:06:44 +0200 Subject: [PATCH 05/15] Simplify Maven publishing config --- build.gradle.kts | 53 +++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c5fb3869b..1d34ea59b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -62,6 +62,9 @@ val javacModuleOptions = val javacTestJvmOptions = javacModuleOptions.map { it.removePrefix("-J") } val catalog = libs val protobufVersion = catalog.versions.protobuf.asProvider().get() +val repositoryUrl = "https://github.com/sourcegraph/scip-java" +val signingKey = providers.environmentVariable("PGP_SECRET").map(::decodePgpSecret) +val signingPassword = providers.environmentVariable("PGP_PASSPHRASE") allprojects { group = rootProject.group @@ -107,7 +110,7 @@ subprojects { } } -fun Project.configureMavenPublishing(displayName: String, descriptionText: String) { +fun Project.configureMavenPublishing() { apply(plugin = "maven-publish") apply(plugin = "signing") @@ -121,9 +124,9 @@ fun Project.configureMavenPublishing(displayName: String, descriptionText: Strin create("mavenJava") { from(components["java"]) pom { - name.set(displayName) - description.set(descriptionText) - url.set("https://github.com/sourcegraph/scip-java") + name.set(project.name) + description.set(project.description ?: project.name) + url.set(repositoryUrl) licenses { license { name.set("Apache-2.0") @@ -137,9 +140,9 @@ fun Project.configureMavenPublishing(displayName: String, descriptionText: Strin } } scm { - connection.set("scm:git:https://github.com/sourcegraph/scip-java.git") + connection.set("scm:git:$repositoryUrl.git") developerConnection.set("scm:git:ssh://git@github.com/sourcegraph/scip-java.git") - url.set("https://github.com/sourcegraph/scip-java") + url.set(repositoryUrl) } } } @@ -147,8 +150,6 @@ fun Project.configureMavenPublishing(displayName: String, descriptionText: Strin } val publishing = extensions.getByType() - val signingKey = providers.environmentVariable("PGP_SECRET").map(::decodePgpSecret) - val signingPassword = providers.environmentVariable("PGP_PASSPHRASE") extensions.configure { isRequired = signingKey.isPresent && !project.version.toString().endsWith("SNAPSHOT") if (signingKey.isPresent) { @@ -171,20 +172,19 @@ nexusPublishing { project(":scip-shared") { apply(plugin = "java-library") + description = "Shared SCIP utilities used by scip-java compiler plugins" dependencies { "api"(catalog.scip.java.bindings) } - configureMavenPublishing( - displayName = "scip-shared", - descriptionText = "Shared SCIP utilities used by scip-java compiler plugins", - ) + configureMavenPublishing() } project(":scip-javac") { apply(plugin = "java-library") apply(plugin = "com.github.johnrengelman.shadow") + description = "A javac plugin to emit SCIP information" dependencies { "api"(project(":scip-shared")) @@ -218,16 +218,14 @@ project(":scip-javac") { } } - configureMavenPublishing( - displayName = "scip-javac", - descriptionText = "A javac plugin to emit SCIP information", - ) + configureMavenPublishing() } project(":scip-kotlinc") { apply(plugin = "java-library") apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "com.github.johnrengelman.shadow") + description = "A kotlinc plugin to emit SCIP information" dependencies { "implementation"(project(":scip-shared")) @@ -258,10 +256,7 @@ project(":scip-kotlinc") { relocate("com.intellij", "org.jetbrains.kotlin.com.intellij") } - configureMavenPublishing( - displayName = "scip-kotlinc", - descriptionText = "A kotlinc plugin to emit SCIP information", - ) + configureMavenPublishing() } project(":scip-gradle-plugin") { @@ -276,6 +271,7 @@ project(":scip-gradle-plugin") { project(":scip-maven-plugin") { apply(plugin = "java-library") + description = "A Maven plugin that exports dependency metadata for scip-java" dependencies { "implementation"(catalog.maven.plugin.api) @@ -293,15 +289,13 @@ project(":scip-maven-plugin") { inputs.property("version", project.version.toString()) } - configureMavenPublishing( - displayName = "scip-maven-plugin", - descriptionText = "A Maven plugin that exports dependency metadata for scip-java", - ) + configureMavenPublishing() } project(":scip-aggregator") { apply(plugin = "java-library") apply(plugin = "com.google.protobuf") + description = "Aggregates compiler-plugin SCIP shards into a single SCIP index" dependencies { "api"(catalog.scip.java.bindings) @@ -325,15 +319,13 @@ project(":scip-aggregator") { } } - configureMavenPublishing( - displayName = "scip-aggregator", - descriptionText = "Aggregates compiler-plugin SCIP shards into a single SCIP index", - ) + configureMavenPublishing() } project(":scip-java") { apply(plugin = "org.jetbrains.kotlin.jvm") apply(plugin = "application") + description = "Java and Kotlin indexer for SCIP" dependencies { "implementation"(project(":scip-aggregator")) @@ -405,10 +397,7 @@ project(":scip-java") { } } - configureMavenPublishing( - displayName = "scip-java", - descriptionText = "Java and Kotlin indexer for SCIP", - ) + configureMavenPublishing() } project(":scip-snapshots-java-common") { From 48bbb3fea0cea47baf9a146737036c614d94d52b Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:11:24 +0200 Subject: [PATCH 06/15] Simplify PGP signing config --- build.gradle.kts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1d34ea59b..7a47e6385 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.google.protobuf.gradle.ProtobufExtension import com.google.protobuf.gradle.proto -import java.nio.charset.StandardCharsets -import java.util.Base64 import org.gradle.api.JavaVersion import org.gradle.api.distribution.DistributionContainer import org.gradle.api.plugins.JavaApplication @@ -29,13 +27,6 @@ plugins { alias(libs.plugins.shadow) apply false } -fun decodePgpSecret(raw: String): String = - if (raw.contains("BEGIN PGP")) { - raw - } else { - runCatching { String(Base64.getDecoder().decode(raw), StandardCharsets.UTF_8) }.getOrElse { raw } - } - val computedVersion = providers .gradleProperty("releaseVersion") @@ -63,7 +54,7 @@ val javacTestJvmOptions = javacModuleOptions.map { it.removePrefix("-J") } val catalog = libs val protobufVersion = catalog.versions.protobuf.asProvider().get() val repositoryUrl = "https://github.com/sourcegraph/scip-java" -val signingKey = providers.environmentVariable("PGP_SECRET").map(::decodePgpSecret) +val signingKey = providers.environmentVariable("PGP_SECRET") val signingPassword = providers.environmentVariable("PGP_PASSPHRASE") allprojects { From 0618f072ea1c2bfe90560bdb417b2e4551b622f7 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:22:09 +0200 Subject: [PATCH 07/15] Use Vanniktech Maven Publish --- .github/workflows/release-maven.yml | 20 +++---- build.gradle.kts | 86 +++++++++-------------------- gradle/libs.versions.toml | 2 + 3 files changed, 39 insertions(+), 69 deletions(-) diff --git a/.github/workflows/release-maven.yml b/.github/workflows/release-maven.yml index b082060b5..82e0e4f81 100644 --- a/.github/workflows/release-maven.yml +++ b/.github/workflows/release-maven.yml @@ -17,23 +17,23 @@ jobs: - uses: DeterminateSystems/magic-nix-cache-action@v13 - name: Publish snapshot ${{ github.ref }} if: ${{ !startsWith(github.ref, 'refs/tags/') }} - run: nix develop --command gradle --no-daemon publishToSonatype + run: nix develop --command gradle --no-daemon publishToMavenCentral env: - PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - PGP_SECRET: ${{ secrets.PGP_SECRET }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USERNAME }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.PGP_SECRET }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.PGP_PASSPHRASE }} - name: Publish release ${{ github.ref }} if: ${{ startsWith(github.ref, 'refs/tags/') }} run: | version="${GITHUB_REF_NAME#v}" nix develop --command env VERSION="$version" \ - gradle --no-daemon publishToSonatype closeAndReleaseSonatypeStagingRepository + gradle --no-daemon publishAndReleaseToMavenCentral env: - PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - PGP_SECRET: ${{ secrets.PGP_SECRET }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USERNAME }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.PGP_SECRET }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.PGP_PASSPHRASE }} release-cli: if: ${{ startsWith(github.ref, 'refs/tags/') }} diff --git a/build.gradle.kts b/build.gradle.kts index 7a47e6385..8b140a56c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,13 +1,12 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.google.protobuf.gradle.ProtobufExtension import com.google.protobuf.gradle.proto +import com.vanniktech.maven.publish.MavenPublishBaseExtension import org.gradle.api.JavaVersion import org.gradle.api.distribution.DistributionContainer import org.gradle.api.plugins.JavaApplication import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.Sync @@ -16,15 +15,14 @@ import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.api.tasks.testing.Test import org.gradle.external.javadoc.StandardJavadocDocletOptions import org.gradle.language.jvm.tasks.ProcessResources -import org.gradle.plugins.signing.SigningExtension import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { - id("io.github.gradle-nexus.publish-plugin") version "2.0.0" alias(libs.plugins.kotlin.jvm) apply false alias(libs.plugins.protobuf) apply false alias(libs.plugins.shadow) apply false + alias(libs.plugins.vanniktech.maven.publish) apply false } val computedVersion = @@ -54,8 +52,6 @@ val javacTestJvmOptions = javacModuleOptions.map { it.removePrefix("-J") } val catalog = libs val protobufVersion = catalog.versions.protobuf.asProvider().get() val repositoryUrl = "https://github.com/sourcegraph/scip-java" -val signingKey = providers.environmentVariable("PGP_SECRET") -val signingPassword = providers.environmentVariable("PGP_PASSPHRASE") allprojects { group = rootProject.group @@ -102,61 +98,33 @@ subprojects { } fun Project.configureMavenPublishing() { - apply(plugin = "maven-publish") - apply(plugin = "signing") - - extensions.configure { - withSourcesJar() - withJavadocJar() - } - - extensions.configure { - publications { - create("mavenJava") { - from(components["java"]) - pom { - name.set(project.name) - description.set(project.description ?: project.name) - url.set(repositoryUrl) - licenses { - license { - name.set("Apache-2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0") - } - } - developers { - developer { - id.set("sourcegraph") - name.set("Sourcegraph") - } - } - scm { - connection.set("scm:git:$repositoryUrl.git") - developerConnection.set("scm:git:ssh://git@github.com/sourcegraph/scip-java.git") - url.set(repositoryUrl) - } + apply(plugin = "com.vanniktech.maven.publish") + + extensions.configure("mavenPublishing") { + publishToMavenCentral() + signAllPublications() + + pom { + name.set(project.name) + description.set(project.description ?: project.name) + url.set(repositoryUrl) + licenses { + license { + name.set("Apache-2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0") } } - } - } - - val publishing = extensions.getByType() - extensions.configure { - isRequired = signingKey.isPresent && !project.version.toString().endsWith("SNAPSHOT") - if (signingKey.isPresent) { - useInMemoryPgpKeys(signingKey.get(), signingPassword.orNull) - sign(publishing.publications) - } - } -} - -nexusPublishing { - repositories { - sonatype { - username.set(providers.environmentVariable("SONATYPE_USERNAME")) - password.set(providers.environmentVariable("SONATYPE_PASSWORD")) - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + developers { + developer { + id.set("sourcegraph") + name.set("Sourcegraph") + } + } + scm { + connection.set("scm:git:$repositoryUrl.git") + developerConnection.set("scm:git:ssh://git@github.com/sourcegraph/scip-java.git") + url.set(repositoryUrl) + } } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 96e350a55..637001a88 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,6 +15,7 @@ protobuf = "4.34.2" protobuf-plugin = "0.9.4" scip-bindings = "0.8.0" shadow = "8.1.1" +vanniktech-maven-publish = "0.35.0" [libraries] clikt-jvm = { module = "com.github.ajalt.clikt:clikt-jvm", version.ref = "clikt" } @@ -46,3 +47,4 @@ scip-kotlin-bindings = { module = "org.scip-code:scip-kotlin-bindings", version. kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" } shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } +vanniktech-maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "vanniktech-maven-publish" } From 8e64ed8539b4bdf16f0a484f07f4427e98bbe050 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:34:08 +0200 Subject: [PATCH 08/15] Simplify Gradle versioning --- .github/workflows/release-maven.yml | 4 ++-- build.gradle.kts | 14 +------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release-maven.yml b/.github/workflows/release-maven.yml index 82e0e4f81..dd7aaf906 100644 --- a/.github/workflows/release-maven.yml +++ b/.github/workflows/release-maven.yml @@ -27,8 +27,8 @@ jobs: if: ${{ startsWith(github.ref, 'refs/tags/') }} run: | version="${GITHUB_REF_NAME#v}" - nix develop --command env VERSION="$version" \ - gradle --no-daemon publishAndReleaseToMavenCentral + nix develop --command gradle --no-daemon \ + "-PreleaseVersion=$version" publishAndReleaseToMavenCentral env: ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_PASSWORD }} ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_USERNAME }} diff --git a/build.gradle.kts b/build.gradle.kts index 8b140a56c..b0c268181 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,20 +25,8 @@ plugins { alias(libs.plugins.vanniktech.maven.publish) apply false } -val computedVersion = - providers - .gradleProperty("releaseVersion") - .orElse(providers.environmentVariable("VERSION").map { it.removePrefix("v") }) - .orElse( - providers.provider { - rootProject.file("VERSION").takeIf { it.isFile }?.readText()?.trim()?.takeIf { - it.isNotEmpty() - } ?: "0.0.0-SNAPSHOT" - } - ) - group = "com.sourcegraph" -version = computedVersion.get() +version = providers.gradleProperty("releaseVersion").orElse("0.0.0-SNAPSHOT").get() val javacModuleOptions = listOf( From fa7ff61e90af0e330e735fb17a37b7a8b92cdca8 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:39:22 +0200 Subject: [PATCH 09/15] Inline Gradle project versioning --- build.gradle.kts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b0c268181..818b02364 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,9 +25,6 @@ plugins { alias(libs.plugins.vanniktech.maven.publish) apply false } -group = "com.sourcegraph" -version = providers.gradleProperty("releaseVersion").orElse("0.0.0-SNAPSHOT").get() - val javacModuleOptions = listOf( "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", @@ -42,8 +39,8 @@ val protobufVersion = catalog.versions.protobuf.asProvider().get() val repositoryUrl = "https://github.com/sourcegraph/scip-java" allprojects { - group = rootProject.group - version = rootProject.version + group = "com.sourcegraph" + version = providers.gradleProperty("releaseVersion").orElse("0.0.0-SNAPSHOT").get() } subprojects { From 815282df75f992c74d477c4f5591d975115b1ffd Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:48:07 +0200 Subject: [PATCH 10/15] Simplify javac module options --- build.gradle.kts | 25 +++++++++---------- .../com/sourcegraph/scip_java/BuildInfo.kt | 4 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 818b02364..fe0e91dee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,15 +25,14 @@ plugins { alias(libs.plugins.vanniktech.maven.publish) apply false } -val javacModuleOptions = +val javacJvmOptions = listOf( - "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + "--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", + "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", ) -val javacTestJvmOptions = javacModuleOptions.map { it.removePrefix("-J") } val catalog = libs val protobufVersion = catalog.versions.protobuf.asProvider().get() val repositoryUrl = "https://github.com/sourcegraph/scip-java" @@ -147,7 +146,7 @@ project(":scip-javac") { } tasks.named("test") { - jvmArgs(javacTestJvmOptions) + jvmArgs(javacJvmOptions) } tasks.named("shadowJar") { @@ -289,7 +288,7 @@ project(":scip-java") { } tasks.named("test") { - jvmArgs(javacTestJvmOptions) + jvmArgs(javacJvmOptions) systemProperty("scip.jdk.version", "11") } @@ -363,7 +362,7 @@ project(":scip-snapshots-java-common") { annotationProcessorClasspath.get().plus(files(javacShadow.flatMap { it.archiveFile })) outputs.dir(scipTargetroot) options.isFork = true - options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacTestJvmOptions + options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacJvmOptions options.compilerArgs.add( "-Xplugin:scip -text:on -verbose -sourceroot:${rootProject.rootDir.absolutePath} " + "-targetroot:${scipTargetroot.get().asFile.absolutePath} -randomtimestamp=${System.nanoTime()}" @@ -410,7 +409,7 @@ project(":scip-snapshots-kotlin-common") { options.annotationProcessorPath = files(javacShadow.flatMap { it.archiveFile }) outputs.dir(scipTargetroot) options.isFork = true - options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacTestJvmOptions + options.forkOptions.jvmArgs = (options.forkOptions.jvmArgs ?: emptyList()) + javacJvmOptions options.compilerArgs.add( "-Xplugin:scip -sourceroot:${rootProject.rootDir.absolutePath} " + "-targetroot:${scipTargetroot.get().asFile.absolutePath}" @@ -451,7 +450,7 @@ project(":scip-snapshots") { tasks.named("test") { dependsOn(javaCaseClasses, kotlinCaseClasses) - jvmArgs(javacTestJvmOptions) + jvmArgs(javacJvmOptions) systemProperties(snapshotProperties) } @@ -462,7 +461,7 @@ project(":scip-snapshots") { val sourceSets = project.extensions.getByType() classpath = sourceSets.named("main").get().runtimeClasspath mainClass.set("tests.SaveSnapshots") - jvmArgs(javacTestJvmOptions) + jvmArgs(javacJvmOptions) systemProperties(snapshotProperties) } } diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt index 2b5948804..420cc0927 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt @@ -14,8 +14,8 @@ object BuildInfo { * `--add-exports` flags required to access internal javac APIs from the SCIP compiler plugin. * Java 11+ is the supported baseline. * - * Kept in sync with `javacModuleOptions` in build.gradle.kts, which applies the same flags when - * compiling the plugin and the test fixtures. + * Kept in sync with `javacJvmOptions` in build.gradle.kts, which applies the same flags without + * the `-J` prefix when running forked JVMs directly. */ val javacModuleOptions: List = listOf( From 6fd1be981e343fbd608096a05769d44dc3037a2b Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 13:52:34 +0200 Subject: [PATCH 11/15] Remove BuildInfo --- build.gradle.kts | 11 ++++-- .../com/sourcegraph/scip_java/BuildInfo.kt | 39 ------------------- .../com/sourcegraph/scip_java/Embedded.kt | 18 +++++++-- .../com/sourcegraph/scip_java/ScipJava.kt | 4 ++ .../com/sourcegraph/scip_java/ScipJavaApp.kt | 2 +- .../scip_java/buildtools/ScipBuildTool.kt | 4 +- .../scip_java/commands/AggregateRunner.kt | 4 +- 7 files changed, 30 insertions(+), 52 deletions(-) delete mode 100644 scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt diff --git a/build.gradle.kts b/build.gradle.kts index fe0e91dee..1322710d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,6 +14,7 @@ import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.javadoc.Javadoc import org.gradle.api.tasks.testing.Test import org.gradle.external.javadoc.StandardJavadocDocletOptions +import org.gradle.jvm.tasks.Jar import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -311,16 +312,18 @@ project(":scip-java") { rename { "scip-kotlinc.jar" } } into(layout.buildDirectory.dir("generated/resources/embedded")) - inputs.property("version", project.version.toString()) - doLast { - destinationDir.resolve("scip-java.properties").writeText("version=${project.version}\n") - } } tasks.named("processResources") { from(generateEmbeddedResources) } + tasks.named("jar") { + manifest { + attributes("Implementation-Version" to project.version) + } + } + val generateDistributionVersion = tasks.register("generateDistributionVersion") { val output = layout.buildDirectory.file("generated/distribution/VERSION") inputs.property("version", project.version.toString()) diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt deleted file mode 100644 index 420cc0927..000000000 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/BuildInfo.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.sourcegraph.scip_java - -import java.util.Properties - -/** - * Build metadata for the scip-java CLI. - * - * The static [javacModuleOptions] live here directly; the build-time [version] is injected by - * Gradle into the `scip-java.properties` classpath resource. - */ -object BuildInfo { - - /** - * `--add-exports` flags required to access internal javac APIs from the SCIP compiler plugin. - * Java 11+ is the supported baseline. - * - * Kept in sync with `javacJvmOptions` in build.gradle.kts, which applies the same flags without - * the `-J` prefix when running forked JVMs directly. - */ - val javacModuleOptions: List = - listOf( - "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", - ) - - /** - * The scip-java release version. Read from the `scip-java.properties` resource that Gradle - * generates into the jar. Falls back to a placeholder when running without the generated - * resource on the classpath. - */ - val version: String by lazy { - val props = Properties() - BuildInfo::class.java.getResourceAsStream("/scip-java.properties")?.use { props.load(it) } - props.getProperty("version") ?: "0.0.0-SNAPSHOT" - } -} diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt index 7fbad332b..1f48d3818 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt @@ -8,6 +8,16 @@ import java.nio.file.StandardCopyOption object Embedded { + /** `javac` launcher flags required by the SCIP plugin to access internal javac APIs. */ + val javacModuleOptions: List = + listOf( + "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ) + fun scipJar(tmpDir: Path): Path = copyFile(tmpDir, "scip-plugin.jar") fun gradlePluginJar(tmpDir: Path): Path = copyFile(tmpDir, "gradle-plugin.jar") @@ -32,7 +42,7 @@ object Embedded { val newJavacopts = tmp.resolve("javac_newarguments") // --add-exports flags required to access internal javac APIs from our // SCIP plugin. Always set; Java 11+ is the supported baseline. - val javacModuleOptions = BuildInfo.javacModuleOptions.joinToString(" ") + val javacModuleOptionsText = javacModuleOptions.joinToString(" ") val injectScipArguments = listOf( "java", @@ -59,9 +69,11 @@ object Embedded { append("done\n") append(injectScipArguments).append('\n') append("if [ \${#LAUNCHER_ARGS[@]} -eq 0 ]; then\n") - append(" javac $javacModuleOptions \"@\$NEW_JAVAC_OPTS\"\n") + append(" javac $javacModuleOptionsText \"@\$NEW_JAVAC_OPTS\"\n") append("else\n") - append(" javac $javacModuleOptions \"@\$NEW_JAVAC_OPTS\" \"\${LAUNCHER_ARGS[@]}\"\n") + append( + " javac $javacModuleOptionsText \"@\$NEW_JAVAC_OPTS\" \"\${LAUNCHER_ARGS[@]}\"\n" + ) append("fi\n") } Files.write(javac, script.toByteArray(StandardCharsets.UTF_8)) diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJava.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJava.kt index 70d2dfb3d..bd69ca9e1 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJava.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJava.kt @@ -10,6 +10,10 @@ object ScipJava { @JvmField val app: ScipJavaApp = ScipJavaApp() + val version: String by lazy { + ScipJava::class.java.`package`?.implementationVersion ?: "0.0.0-SNAPSHOT" + } + @JvmStatic fun main(args: Array) { app.runAndExitIfNonZero(args.toList()) diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJavaApp.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJavaApp.kt index a4f612e97..3e073b94d 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJavaApp.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/ScipJavaApp.kt @@ -65,7 +65,7 @@ class ScipJavaApp { reporter.reset() val processedArgs = applyGlobalCwd(rewriteNestedOptions(args)) val root = RootCommand(this) - root.versionOption(BuildInfo.version, names = setOf("--version", "-v")) + root.versionOption(ScipJava.version, names = setOf("--version", "-v")) root.subcommands(IndexCommand(), AggregateCommand(), SnapshotCommand()) return try { root.parse(processedArgs) diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt index e1afb95ac..d4af5196b 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt @@ -1,6 +1,5 @@ package com.sourcegraph.scip_java.buildtools -import com.sourcegraph.scip_java.BuildInfo import com.sourcegraph.scip_java.Embedded import com.sourcegraph.scip_java.commands.IndexCommand import java.io.File @@ -300,13 +299,12 @@ class ScipBuildTool(index: IndexCommand) : BuildTool("SCIP", index) { } val javac = javacPath(config) index.app.reporter.info("$ $javac @$argsfile") - val javacModuleOptions = BuildInfo.javacModuleOptions val jvmOptions = config.jvmOptions.map { "-J$it" } val cmd = mutableListOf() cmd += javac.toString() cmd += "@$argsfile" - cmd += javacModuleOptions + cmd += Embedded.javacModuleOptions cmd += jvmOptions val result = ProcessRunner.run( diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/commands/AggregateRunner.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/commands/AggregateRunner.kt index 730e2999e..af5404124 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/commands/AggregateRunner.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/commands/AggregateRunner.kt @@ -2,7 +2,7 @@ package com.sourcegraph.scip_java.commands import com.sourcegraph.scip_aggregator.ScipAggregator import com.sourcegraph.scip_aggregator.ScipAggregatorOptions -import com.sourcegraph.scip_java.BuildInfo +import com.sourcegraph.scip_java.ScipJava import com.sourcegraph.scip_java.ScipJavaApp import com.sourcegraph.scip_java.buildtools.ClasspathEntry import java.nio.file.Path @@ -41,7 +41,7 @@ object AggregateRunner { absoluteOutput, sourceroot, app.reporter, - ToolInfo.newBuilder().setName("scip-java").setVersion(BuildInfo.version).build(), + ToolInfo.newBuilder().setName("scip-java").setVersion(ScipJava.version).build(), parallel, packages.map { it.toPackageInformation() }, emitInverseRelationships, From b1c4282838f7d5a86a67845880b64a48efb66e8f Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 17:22:17 +0200 Subject: [PATCH 12/15] Share javac module flags --- build.gradle.kts | 19 ++++++++----- gradle/javac-internals.properties | 7 +++++ .../com/sourcegraph/scip_java/Embedded.kt | 27 ++++++++++--------- .../scip_java/buildtools/ScipBuildTool.kt | 2 +- 4 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 gradle/javac-internals.properties diff --git a/build.gradle.kts b/build.gradle.kts index 1322710d7..33791726a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import com.google.protobuf.gradle.ProtobufExtension import com.google.protobuf.gradle.proto import com.vanniktech.maven.publish.MavenPublishBaseExtension +import java.util.Properties import org.gradle.api.JavaVersion import org.gradle.api.distribution.DistributionContainer import org.gradle.api.plugins.JavaApplication @@ -26,14 +27,19 @@ plugins { alias(libs.plugins.vanniktech.maven.publish) apply false } +val javacInternalsFile = layout.projectDirectory.file("gradle/javac-internals.properties") val javacJvmOptions = - listOf( - "--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ( + Properties() + .apply { + javacInternalsFile.asFile.inputStream().use { load(it) } + } + .getProperty("javac.jvmOptions") + ?: error("Missing javac.jvmOptions in gradle/javac-internals.properties") ) + .split(',') + .map { it.trim() } + .filter { it.isNotEmpty() } val catalog = libs val protobufVersion = catalog.versions.protobuf.asProvider().get() val repositoryUrl = "https://github.com/sourcegraph/scip-java" @@ -315,6 +321,7 @@ project(":scip-java") { } tasks.named("processResources") { + from(javacInternalsFile) from(generateEmbeddedResources) } diff --git a/gradle/javac-internals.properties b/gradle/javac-internals.properties new file mode 100644 index 000000000..c1e82fca5 --- /dev/null +++ b/gradle/javac-internals.properties @@ -0,0 +1,7 @@ +# JVM flags required by scip-javac to access internal javac APIs on Java 9+. +javac.jvmOptions=\ +--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,\ +--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED,\ +--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED,\ +--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED,\ +--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt index 1f48d3818..8e315d2fc 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt @@ -5,18 +5,21 @@ import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardCopyOption +import java.util.Properties object Embedded { - /** `javac` launcher flags required by the SCIP plugin to access internal javac APIs. */ - val javacModuleOptions: List = - listOf( - "-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", - ) + val javacLauncherJvmOptions: List by lazy { + val properties = Properties() + val input = + Embedded::class.java.getResourceAsStream("/javac-internals.properties") + ?: error("missing embedded resource: /javac-internals.properties") + input.use { properties.load(it) } + val jvmOptions = + properties.getProperty("javac.jvmOptions") + ?: error("missing javac.jvmOptions in /javac-internals.properties") + jvmOptions.split(',').map { it.trim() }.filter { it.isNotEmpty() }.map { "-J$it" } + } fun scipJar(tmpDir: Path): Path = copyFile(tmpDir, "scip-plugin.jar") @@ -42,7 +45,7 @@ object Embedded { val newJavacopts = tmp.resolve("javac_newarguments") // --add-exports flags required to access internal javac APIs from our // SCIP plugin. Always set; Java 11+ is the supported baseline. - val javacModuleOptionsText = javacModuleOptions.joinToString(" ") + val javacLauncherJvmOptionsText = javacLauncherJvmOptions.joinToString(" ") val injectScipArguments = listOf( "java", @@ -69,10 +72,10 @@ object Embedded { append("done\n") append(injectScipArguments).append('\n') append("if [ \${#LAUNCHER_ARGS[@]} -eq 0 ]; then\n") - append(" javac $javacModuleOptionsText \"@\$NEW_JAVAC_OPTS\"\n") + append(" javac $javacLauncherJvmOptionsText \"@\$NEW_JAVAC_OPTS\"\n") append("else\n") append( - " javac $javacModuleOptionsText \"@\$NEW_JAVAC_OPTS\" \"\${LAUNCHER_ARGS[@]}\"\n" + " javac $javacLauncherJvmOptionsText \"@\$NEW_JAVAC_OPTS\" \"\${LAUNCHER_ARGS[@]}\"\n" ) append("fi\n") } diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt index d4af5196b..35224af3f 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/ScipBuildTool.kt @@ -304,7 +304,7 @@ class ScipBuildTool(index: IndexCommand) : BuildTool("SCIP", index) { val cmd = mutableListOf() cmd += javac.toString() cmd += "@$argsfile" - cmd += Embedded.javacModuleOptions + cmd += Embedded.javacLauncherJvmOptions cmd += jvmOptions val result = ProcessRunner.run( From 456d9b1826d6579f003d6799bae35b6382afc910 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 17:56:17 +0200 Subject: [PATCH 13/15] Move javac wrapper scripts to resources --- .../com/sourcegraph/scip_java/Embedded.kt | 73 +++++++------------ .../scip_java/buildtools/MavenBuildTool.kt | 6 +- .../main/resources/scip-java/custom-javac.sh | 38 ++++++++++ .../resources/scip-java/java-forwarder.sh | 2 + 4 files changed, 68 insertions(+), 51 deletions(-) create mode 100644 scip-java/src/main/resources/scip-java/custom-javac.sh create mode 100644 scip-java/src/main/resources/scip-java/java-forwarder.sh diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt index 8e315d2fc..d7400ac3a 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/Embedded.kt @@ -29,7 +29,9 @@ object Embedded { private fun javacErrorpath(tmp: Path): Path = tmp.resolve("errorpath.txt") - fun customJavac(sourceroot: Path, targetroot: Path, tmp: Path): Path { + data class CustomJavac(val executable: Path, val environment: Map) + + fun customJavac(sourceroot: Path, targetroot: Path, tmp: Path): CustomJavac { val bin = tmp.resolve("bin") val javac = bin.resolve("javac") val java = bin.resolve("java") @@ -38,51 +40,22 @@ object Embedded { val javacopts = targetroot.resolve("javacopts.txt") Files.createDirectories(targetroot) Files.createDirectories(bin) - Files.write( - java, - ("#!/usr/bin/env bash\n" + "java \"\$@\"\n").toByteArray(StandardCharsets.UTF_8), - ) - val newJavacopts = tmp.resolve("javac_newarguments") - // --add-exports flags required to access internal javac APIs from our - // SCIP plugin. Always set; Java 11+ is the supported baseline. - val javacLauncherJvmOptionsText = javacLauncherJvmOptions.joinToString(" ") - val injectScipArguments = - listOf( - "java", - "-Dscip.errorpath=$errorpath", - "-Dscip.pluginpath=$pluginpath", - "-Dscip.sourceroot=$sourceroot", - "-Dscip.targetroot=$targetroot", - "-Dscip.output=\$NEW_JAVAC_OPTS", - "-Dscip.old-output=$javacopts", - "-classpath $pluginpath", - "com.sourcegraph.scip_javac.InjectScipOptions", - "\"\$@\"", - ) - .joinToString(" ") - val script = buildString { - append("#!/usr/bin/env bash\n") - append("set -eu\n") - append("LAUNCHER_ARGS=()\n") - append("NEW_JAVAC_OPTS=\"$newJavacopts-\$RANDOM\"\n") - append("for arg in \"\$@\"; do\n") - append(" if [[ \$arg == -J* ]]; then\n") - append(" LAUNCHER_ARGS+=(\"\$arg\")\n") - append(" fi\n") - append("done\n") - append(injectScipArguments).append('\n') - append("if [ \${#LAUNCHER_ARGS[@]} -eq 0 ]; then\n") - append(" javac $javacLauncherJvmOptionsText \"@\$NEW_JAVAC_OPTS\"\n") - append("else\n") - append( - " javac $javacLauncherJvmOptionsText \"@\$NEW_JAVAC_OPTS\" \"\${LAUNCHER_ARGS[@]}\"\n" - ) - append("fi\n") - } - Files.write(javac, script.toByteArray(StandardCharsets.UTF_8)) + copyResource(java, "scip-java/java-forwarder.sh") + copyResource(javac, "scip-java/custom-javac.sh") javac.toFile().setExecutable(true) java.toFile().setExecutable(true) - return javac + return CustomJavac( + javac, + mapOf( + "SCIP_ERRORPATH" to errorpath.toString(), + "SCIP_JAVAC_LAUNCHER_JVM_OPTIONS" to javacLauncherJvmOptions.joinToString("\n"), + "SCIP_JAVAC_OPTIONS_PREFIX" to tmp.resolve("javac_newarguments").toString(), + "SCIP_OLD_JAVAC_OPTS" to javacopts.toString(), + "SCIP_PLUGINPATH" to pluginpath.toString(), + "SCIP_SOURCEROOT" to sourceroot.toString(), + "SCIP_TARGETROOT" to targetroot.toString(), + ), + ) } /** @@ -108,12 +81,16 @@ object Embedded { } private fun copyFile(tmpDir: Path, filename: String): Path { - val input = - Embedded::class.java.getResourceAsStream("/$filename") - ?: error("missing embedded resource: /$filename") val out = tmpDir.resolve(filename) + copyResource(out, filename) + return out + } + + private fun copyResource(out: Path, resource: String) { + val input = + Embedded::class.java.getResourceAsStream("/$resource") + ?: error("missing embedded resource: /$resource") Files.createDirectories(out.parent) input.use { Files.copy(it, out, StandardCopyOption.REPLACE_EXISTING) } - return out } } diff --git a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/MavenBuildTool.kt b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/MavenBuildTool.kt index 83e0f7ed8..be37f3f91 100644 --- a/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/MavenBuildTool.kt +++ b/scip-java/src/main/kotlin/com/sourcegraph/scip_java/buildtools/MavenBuildTool.kt @@ -24,7 +24,7 @@ class MavenBuildTool(index: IndexCommand) : BuildTool("Maven", index) { val mavenScript = if (Files.isRegularFile(mvnw) && Files.isExecutable(mvnw)) mvnw.toString() else "mvn" - val executable = + val javac = Embedded.customJavac( index.workingDirectory, index.finalTargetroot(defaultTargetroot), @@ -38,7 +38,7 @@ class MavenBuildTool(index: IndexCommand) : BuildTool("Maven", index) { // '-Dmaven.compiler.executable' setting. Forcing the compilerId to // 'javac' fixes the issue for this repo. command += "-Dmaven.compiler.compilerId=javac" - command += "-Dmaven.compiler.executable=$executable" + command += "-Dmaven.compiler.executable=${javac.executable}" command += "-Dmaven.compiler.fork=true" command += index.finalBuildCommand( @@ -52,7 +52,7 @@ class MavenBuildTool(index: IndexCommand) : BuildTool("Maven", index) { ) ) - val exit = index.app.runProcess(command) + val exit = index.app.runProcess(command, env = javac.environment) Embedded.reportUnexpectedJavacErrors(index.app.reporter, tmp) ?: exit } } diff --git a/scip-java/src/main/resources/scip-java/custom-javac.sh b/scip-java/src/main/resources/scip-java/custom-javac.sh new file mode 100644 index 000000000..f8c2e6cbb --- /dev/null +++ b/scip-java/src/main/resources/scip-java/custom-javac.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -eu + +: "${SCIP_ERRORPATH:?}" +: "${SCIP_JAVAC_LAUNCHER_JVM_OPTIONS:?}" +: "${SCIP_JAVAC_OPTIONS_PREFIX:?}" +: "${SCIP_OLD_JAVAC_OPTS:?}" +: "${SCIP_PLUGINPATH:?}" +: "${SCIP_SOURCEROOT:?}" +: "${SCIP_TARGETROOT:?}" + +LAUNCHER_ARGS=() +JAVAC_JVM_OPTIONS=() +while IFS= read -r option; do + if [[ -n "$option" ]]; then + JAVAC_JVM_OPTIONS+=("$option") + fi +done <<< "$SCIP_JAVAC_LAUNCHER_JVM_OPTIONS" +NEW_JAVAC_OPTS="$SCIP_JAVAC_OPTIONS_PREFIX-$RANDOM" + +for arg in "$@"; do + if [[ $arg == -J* ]]; then + LAUNCHER_ARGS+=("$arg") + fi +done + +java \ + "-Dscip.errorpath=$SCIP_ERRORPATH" \ + "-Dscip.pluginpath=$SCIP_PLUGINPATH" \ + "-Dscip.sourceroot=$SCIP_SOURCEROOT" \ + "-Dscip.targetroot=$SCIP_TARGETROOT" \ + -Dscip.output="$NEW_JAVAC_OPTS" \ + "-Dscip.old-output=$SCIP_OLD_JAVAC_OPTS" \ + -classpath "$SCIP_PLUGINPATH" \ + com.sourcegraph.scip_javac.InjectScipOptions \ + "$@" + +javac "${JAVAC_JVM_OPTIONS[@]}" "@$NEW_JAVAC_OPTS" "${LAUNCHER_ARGS[@]}" diff --git a/scip-java/src/main/resources/scip-java/java-forwarder.sh b/scip-java/src/main/resources/scip-java/java-forwarder.sh new file mode 100644 index 000000000..b1f148234 --- /dev/null +++ b/scip-java/src/main/resources/scip-java/java-forwarder.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +exec java "$@" From 94512555057f59c477c53b9be86d1f813923686c Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 18:22:12 +0200 Subject: [PATCH 14/15] Simplify Gradle build settings --- build.gradle.kts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 33791726a..f239681bc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,8 +41,6 @@ val javacJvmOptions = .map { it.trim() } .filter { it.isNotEmpty() } val catalog = libs -val protobufVersion = catalog.versions.protobuf.asProvider().get() -val repositoryUrl = "https://github.com/sourcegraph/scip-java" allprojects { group = "com.sourcegraph" @@ -92,6 +90,7 @@ fun Project.configureMavenPublishing() { apply(plugin = "com.vanniktech.maven.publish") extensions.configure("mavenPublishing") { + val repositoryUrl = "https://github.com/sourcegraph/scip-java" publishToMavenCentral() signAllPublications() @@ -194,11 +193,11 @@ project(":scip-kotlinc") { } tasks.withType().configureEach { - compilerOptions.freeCompilerArgs.addAll("-Xinline-classes", "-Xcontext-parameters") + compilerOptions.freeCompilerArgs.add("-Xcontext-parameters") } tasks.named("test") { - jvmArgs("-Xmx2g") + maxHeapSize = "2g" } tasks.named("shadowJar") { @@ -256,6 +255,7 @@ project(":scip-aggregator") { } extensions.configure("protobuf") { + val protobufVersion = catalog.versions.protobuf.asProvider().get() protoc { artifact = "com.google.protobuf:protoc:$protobufVersion" } From afaaf8ac8741d5c1d789bbf63954091b3b4b01e9 Mon Sep 17 00:00:00 2001 From: jupblb Date: Wed, 24 Jun 2026 18:31:33 +0200 Subject: [PATCH 15/15] Update Docker Gradle version --- bin/docker-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/docker-setup.sh b/bin/docker-setup.sh index 6e4f72165..5bee3a434 100755 --- a/bin/docker-setup.sh +++ b/bin/docker-setup.sh @@ -10,7 +10,7 @@ unzip -d /opt/maven maven.zip rm maven.zip mv /opt/maven/*/* /opt/maven -curl -fLo gradle.zip https://services.gradle.org/distributions/gradle-8.10-bin.zip +curl -fLo gradle.zip https://services.gradle.org/distributions/gradle-8.14.4-bin.zip unzip -d /opt/gradle gradle.zip rm gradle.zip mv /opt/gradle/*/* /opt/gradle