Skip to content

Commit 5181cd9

Browse files
committed
Modularize build with convention plugins and per-project files
1 parent cb90147 commit 5181cd9

22 files changed

Lines changed: 552 additions & 468 deletions

build-logic/build.gradle.kts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import org.gradle.plugin.use.PluginDependency
2+
3+
plugins {
4+
`kotlin-dsl`
5+
}
6+
7+
dependencies {
8+
implementation(plugin(libs.plugins.kotlin.jvm))
9+
implementation(plugin(libs.plugins.shadow))
10+
implementation(plugin(libs.plugins.vanniktech.maven.publish))
11+
}
12+
13+
// Maps a version-catalog plugin alias to its plugin-marker dependency so the
14+
// external plugin can be applied by id from the precompiled convention plugins.
15+
fun plugin(dependency: Provider<PluginDependency>): Provider<String> =
16+
dependency.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version}" }

build-logic/settings.gradle.kts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
dependencyResolutionManagement {
2+
repositories {
3+
gradlePluginPortal()
4+
mavenCentral()
5+
}
6+
versionCatalogs {
7+
create("libs") {
8+
from(files("../gradle/libs.versions.toml"))
9+
}
10+
}
11+
}
12+
13+
rootProject.name = "build-logic"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.sourcegraph.buildlogic
2+
3+
import java.io.File
4+
import java.util.Properties
5+
6+
/**
7+
* Reads the JVM flags scip-javac needs to access internal javac APIs on Java 9+,
8+
* keeping gradle/javac-internals.properties the single source of truth.
9+
*/
10+
object JavacInternals {
11+
fun propertiesFile(rootDir: File): File = rootDir.resolve("gradle/javac-internals.properties")
12+
13+
fun jvmOptions(rootDir: File): List<String> {
14+
val file = propertiesFile(rootDir)
15+
val raw =
16+
Properties()
17+
.apply { file.inputStream().use { load(it) } }
18+
.getProperty("javac.jvmOptions")
19+
?: error("Missing javac.jvmOptions in $file")
20+
return raw.split(',').map { it.trim() }.filter { it.isNotEmpty() }
21+
}
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.sourcegraph.buildlogic
2+
3+
import org.gradle.api.Project
4+
import org.gradle.api.artifacts.Configuration
5+
6+
/**
7+
* Declares a resolvable view of another project's shaded jar, published by its
8+
* `shadowJarElements` consumable configuration (the `scip.shadow-producer`
9+
* convention plugin).
10+
*
11+
* Returns a [Configuration] (a `FileCollection`) that resolves to the single
12+
* shaded jar and carries the task dependency on the producing `shadowJar`.
13+
* Sharing the artifact this way, instead of referencing the task across
14+
* projects, keeps project evaluation order and the configuration cache intact.
15+
*/
16+
fun Project.shadowJarArtifact(producerPath: String, name: String): Configuration {
17+
val bucket = configurations.dependencyScope("${name}Classpath")
18+
dependencies.add(
19+
bucket.name,
20+
dependencies.project(mapOf("path" to producerPath, "configuration" to "shadowJarElements")),
21+
)
22+
return configurations.resolvable(name) { extendsFrom(bucket.get()) }.get()
23+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import org.gradle.api.artifacts.VersionCatalogsExtension
2+
3+
plugins {
4+
id("scip.project-base")
5+
java
6+
}
7+
8+
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
9+
10+
tasks.withType<JavaCompile>().configureEach {
11+
options.encoding = "UTF-8"
12+
options.release.set(17)
13+
}
14+
15+
tasks.withType<Javadoc>().configureEach {
16+
options.encoding = "UTF-8"
17+
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet")
18+
}
19+
20+
testing {
21+
suites {
22+
named<JvmTestSuite>("test") {
23+
useJUnitJupiter(libs.findVersion("junit-jupiter").get().requiredVersion)
24+
}
25+
}
26+
}
27+
28+
tasks.withType<Test>().configureEach {
29+
testLogging {
30+
events("failed", "skipped")
31+
}
32+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
plugins {
2+
id("scip.java-base")
3+
`java-library`
4+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
3+
4+
plugins {
5+
id("org.jetbrains.kotlin.jvm")
6+
}
7+
8+
tasks.withType<KotlinCompile>().configureEach {
9+
compilerOptions.jvmTarget.set(JvmTarget.JVM_17)
10+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import com.vanniktech.maven.publish.MavenPublishBaseExtension
2+
3+
plugins {
4+
id("com.vanniktech.maven.publish")
5+
}
6+
7+
extensions.configure<MavenPublishBaseExtension>("mavenPublishing") {
8+
val repositoryUrl = "https://github.com/sourcegraph/scip-java"
9+
publishToMavenCentral()
10+
signAllPublications()
11+
12+
pom {
13+
name.set(project.name)
14+
description.set(provider { project.description ?: project.name })
15+
url.set(repositoryUrl)
16+
licenses {
17+
license {
18+
name.set("Apache-2.0")
19+
url.set("http://www.apache.org/licenses/LICENSE-2.0")
20+
}
21+
}
22+
developers {
23+
developer {
24+
id.set("sourcegraph")
25+
name.set("Sourcegraph")
26+
}
27+
}
28+
scm {
29+
connection.set("scm:git:$repositoryUrl.git")
30+
developerConnection.set("scm:git:ssh://git@github.com/sourcegraph/scip-java.git")
31+
url.set(repositoryUrl)
32+
}
33+
}
34+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
group = "com.sourcegraph"
2+
version = providers.gradleProperty("releaseVersion").orElse("0.0.0-SNAPSHOT").get()
3+
4+
// Several modules also have Bazel `BUILD` files. On the default macOS
5+
// case-insensitive filesystem, Gradle's default `build/` directory collides
6+
// with those files, so keep Gradle outputs under the already-ignored target/.
7+
if (layout.projectDirectory.file("BUILD").asFile.isFile) {
8+
layout.buildDirectory.set(layout.projectDirectory.dir("target/gradle"))
9+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2+
3+
plugins {
4+
id("com.gradleup.shadow")
5+
}
6+
7+
// Publish the shaded jar as a consumable artifact, resolved by consumers via
8+
// `shadowJarArtifact` (see SharedArtifacts.kt).
9+
val shadowJarElements = configurations.consumable("shadowJarElements").get()
10+
artifacts.add(shadowJarElements.name, tasks.named<ShadowJar>("shadowJar"))

0 commit comments

Comments
 (0)