Skip to content

Commit

Permalink
fixup! continued impl work
Browse files Browse the repository at this point in the history
Signed-off-by: Sam Gammon <sam@elide.ventures>
  • Loading branch information
sgammon committed Mar 3, 2024
1 parent 58349cb commit 654a000
Show file tree
Hide file tree
Showing 22 changed files with 617 additions and 20 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,18 @@ Bazelisk, which will respect the `.bazelversion` present at the root of your pro

## Gradle Conventions

The Gradle conventions provided by this project are generic in nature and can be used in nearly any Gradle 8.x+ project.
The Gradle conventions provided by this project are generic in nature and can be used in nearly any Gradle 8+ project.
Conventions are applied in a cascading fashion, with relevant plugins being applied first, which then provide strong
baseline settings.

**Gradle infra:**

- **[Plugins](./gradle/plugins)** for common build tasks, especially around [JPMS][8]. See the plugins list below.
- **[Catalogs](./gradle/catalogs)** defining security-hardened library catalogs
- **[Platforms](./gradle/platforms)** which enforce different profiles of dependency constraints

Read more about the Gradle build infra [here](./gradle). There are [samples](./gradle/samples).

### Plugins

- **[`dev.elide.jmod`][0]:** Build [`jmod`][1] artifacts in Gradle JVM projects with Java 9+. `jmod` artifacts are
Expand Down Expand Up @@ -275,3 +283,4 @@ Elide Ventures, LLC.
[5]: ./gradle/plugins/jlink
[6]: ./gradle/plugins/graalvm
[7]: https://www.graalvm.org/latest/reference-manual/native-image/
[8]: https://www.oracle.com/corporate/features/understanding-java-9-modules.html
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# License for the specific language governing permissions and limitations under the License.
#

# build-infra
build-infra.plugins=base,graalvm,jlink,jmod,jpms,mrjar

# build conventions: jvm
conventions.jvm.target=17
conventions.jvm.toolchain=21
Expand Down
56 changes: 56 additions & 0 deletions gradle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

## Gradle Build Infra

This subdirectory provides shared Gradle build conventions, which are designed for a hardened security posture and high-
performance build experience on modern JVM toolchains. This framework of convention plugins (and other artifacts) runs
the gamut in terms of project applicability, but has a particular focus for JVM applications and library authors,
especially with Kotlin.

### What's so great about these?

Plugins are provided for integrating various Java ecosystem features with Gradle, especially around [JPMS][0]. There are
plugins which also set sensible baseline defaults, including:

- **Better reproducibility** of archives (zip, tar, jar), which improves cacheability of outputs
- **Sensible defaults for dependency security**, including [dependency locking][1] and [verification][2]
- **Strong configuration** for linting and code checking, with unopinionated configuration control
- **Testing features** like test logging and multi-module merged test + coverage reporting out of the box

> [!TIP]
> 👆 These are the features included with use of any plugin provided here.
### Available Plugins

On top of the above functionality, there are feature plugins:

- **[`dev.elide.base`][11]:** Just applies the baselines above, but can be switched off, too, to avoid interfering with
your current build settings.

- **[`dev.elide.jmod`][5]:** Build [`jmod`][3] artifacts in Gradle JVM projects with Java 9+. `jmod` artifacts are
compatible with [`jlink`][4] and make for great optimized build artifacts in modular projects.

- **[`dev.elide.jpms`][6]:** Toolkit plugin for Gradle builds enabled with modular Java (Java Platform Module System, or
JPMS). Provides a `modulepath` configuration and modular builds for Java, Kotlin, and GraalVM.

- **[`dev.elide.mrjar`][7]:** Plugin for easily building multi-target MRJAR artifacts. This plugin goes above and beyond
by **building the entire project at each bytecode tier**, so that modern Java runtimes can leverage the latest
available bytecode for your app or library.

- **[`dev.elide.jlink`][8]:** Plugin for using `jmod` and `jpms` to build optimized, self-contained modular Java apps
using [`jlink`][4].

- **[`dev.elide.graalvm`][9]:** Plugin for using `jmod` and `jpms` to build optimized, native AOT Java apps using
[`native-image`][10].

[0]: https://www.oracle.com/corporate/features/understanding-java-9-modules.html
[1]: https://docs.gradle.org/current/userguide/dependency_locking.html
[2]: https://docs.gradle.org/current/userguide/dependency_verification.html
[3]: https://docs.oracle.com/en/java/javase/11/tools/jmod.html
[4]: https://docs.oracle.com/en/java/javase/11/tools/jlink.html
[5]: ./plugins/jmod
[6]: ./plugins/jpms
[7]: ./plugins/mrjar
[8]: ./plugins/jlink
[9]: ./plugins/graalvm
[10]: https://www.graalvm.org/latest/reference-manual/native-image/
[11]: ./plugins/base
4 changes: 4 additions & 0 deletions gradle/build-infra/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

## Gradle Conventions: Meta-Infrastructure

Coming soon.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import org.gradle.api.Plugin
import org.gradle.api.initialization.Settings

private fun settingsPlugins(): List<String> = listOf(
"build.less",
"com.gradle.enterprise",
"com.gradle.common-custom-user-data-gradle-plugin",
"org.gradle.toolchains.foojay-resolver-convention",
BuildConstants.KnownPlugins.SETTINGS_BUILDLESS,
BuildConstants.KnownPlugins.SETTINGS_GRADLE_ENTERPRISE,
BuildConstants.KnownPlugins.SETTINGS_GRADLE_COMMON,
BuildConstants.KnownPlugins.SETTINGS_FOOJAY_TOOLCHAINS,
)

/**
Expand All @@ -43,9 +43,17 @@ public class BaselineBuildSettings : Plugin<Settings> {
buildCaching.local.enabled.convention(true)
}

val pathString = target.rootDir.toPath().toString()
val catalogPath = when {
target.rootDir.toPath().toString().contains("gradle/plugins/") -> "../../catalogs"
target.rootDir.toPath().toString().contains("samples") -> "../catalogs"
// plugins folder is double-nested
pathString.contains("gradle/plugins/") -> "../../catalogs"

// samples, libs, and platforms are top-level
pathString.contains("samples") ||
pathString.contains("libs") ||
pathString.contains("platforms") -> "../catalogs"

// otherwise, it's the root project
else -> "gradle/catalogs"
}

Expand Down
5 changes: 5 additions & 0 deletions gradle/catalogs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

## Gradle Conventions: Catalogs

This directory defines Gradle version catalogs which are provided via the [supplemental libraries](../libs). The docs
there and in the [Gradle `build-infra` README](../..) explain more about how these all work.
66 changes: 66 additions & 0 deletions gradle/libs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

## Gradle Conventions: Supplemental Libraries

Provides supplemental **Maven libraries**, and **[version catalogs][0]**, for the `build-infra` project. These libraries
and catalogs are used under the hood by these plugins, and can be re-used for other projects.

### Why ship some catalogs?

Firstly, we want to align our own versions internally; but secondly, there are often _very sensible_ constraints that
can be placed on JVM builds in order to **harden security** and **improve build performance**. These catalogs define the
latest versions of tools like [Kotlin][1], [Guava][2], [Apache Commons][3], and more, which are used most often in
projects targeting JVM.

If you are using Gradle, Version Catalogs are a good alternative to [Maven BOMs][4], because:

- You can pick from them like a menu; only the dependencies you pick are downloaded
- You can access the version string, dependency coordinates, and even bundles of like dependencies
- Gradle generates accessors for you, that look like this: `libs.guava`, or `libs.kotlin.stdlib`
- Maven BOMs will often cause all sorts of unrelated metadata crawling; version catalogs don't have this problem

### Available Catalogs

There are three available catalogs: `core`, `infra`, and `libs`. Each targets a different use case and level of
opinionation.

#### `core`

The `core` catalog is unopinionated and focuses on critical JVM tooling, like **Kotlin**, **IDEA**, and plugins from the
Gradle team. Plugins are declared both as **plugins** and **libraries**, allowing these artifacts to be used in
`buildSrc` or `build-logic` projects as well as regular Gradle projects.

**The `core` catalog contains tools which are:**

1) Used by the `build-infra` project itself
2) Vetted for dependency security and liveness
3) Very un-opinionated, other than declaring the latest stable versions

#### `infra`

The `infra` catalog focuses on build tooling with a particular focus on the Gradle plug-in ecosystem. The best and most
popular Gradle plugins are declared with their latest versions, as both **plugins** and **libraries**, allowing these
artifacts to be used in `buildSrc` or `build-logic`-style projects as well as regular Gradle projects.

**The `infra` catalog contains tools which are:**

1) Used for builds, either by `build-infra` or downstream consumers
2) Vetted for dependency security and liveness
3) Slightly opinionated, in the sense that some plugins and features won't apply to some users

#### `libs`

The `libs` catalog focuses on compile-time and run-time libraries which might be useful within the broader JVM
ecosystem. This includes things like **Guava**, **Apache Commons**, compression libraries, and so on. Plugins provided
in this catalog focus on cosmetic/optional build improvements.

**The `libs` catalog contains libraries which are:**

1) Used anywhere, generally, for a lot of things
2) Vetted for dependency security and liveness
3) Strongly opinionated, in the sense that the latest stable version is always declared

[0]: https://docs.gradle.org/current/userguide/platforms.html#sec:sharing-catalogs
[1]: https://kotlinlang.org
[2]: https://github.com/google/guava
[3]: https://commons.apache.org/
[4]: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#bill-of-materials-bom-poms
36 changes: 36 additions & 0 deletions gradle/libs/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/

plugins {
id("infra.root")
}

description = "Supplemental version catalogs and libraries for Gradle build infra"
group = "dev.elide.infra"

evaluationDependsOnChildren()

private fun Task.taskInAllLibs(task: String): Unit = listOf(
projects.catalogCore,
projects.catalogInfra,
projects.catalogLibs,
).forEach {
dependsOn(project(":${it.name}").tasks.named(task))
}

// Top-level tasks.

val clean by tasks.registering { taskInAllLibs("clean") }
val test by tasks.registering { taskInAllLibs("test") }
val check by tasks.registering { taskInAllLibs("check") }
val build by tasks.registering { taskInAllLibs("build") }
38 changes: 38 additions & 0 deletions gradle/libs/catalog-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/

plugins {
base
`version-catalog`
`maven-publish`

id("infra.root")
id("infra.library")
}

description = "Core version catalog"
group = "dev.elide.infra"

catalog {
versionCatalog {
from(files("../../catalogs/core.versions.toml"))
}
}

publishing {
publications {
create<MavenPublication>("maven") {
from(components["versionCatalog"])
}
}
}
38 changes: 38 additions & 0 deletions gradle/libs/catalog-infra/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/

plugins {
base
`version-catalog`
`maven-publish`

id("infra.root")
id("infra.library")
}

description = "Infra version catalog"
group = "dev.elide.infra"

catalog {
versionCatalog {
from(files("../../catalogs/infra.versions.toml"))
}
}

publishing {
publications {
create<MavenPublication>("maven") {
from(components["versionCatalog"])
}
}
}
38 changes: 38 additions & 0 deletions gradle/libs/catalog-libs/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/

plugins {
base
`version-catalog`
`maven-publish`

id("infra.root")
id("infra.library")
}

description = "General library version catalog"
group = "dev.elide.infra"

catalog {
versionCatalog {
from(files("../../catalogs/libs.versions.toml"))
}
}

publishing {
publications {
create<MavenPublication>("maven") {
from(components["versionCatalog"])
}
}
}
34 changes: 34 additions & 0 deletions gradle/libs/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/

pluginManagement {
includeBuild("../build-infra")
}

plugins {
`jvm-toolchain-management`
id("infra.settings")
}

// All plain JVM libraries provided by this project.
val allLibraries = listOf(
"catalog-core",
"catalog-infra",
"catalog-libs",
)

allLibraries.forEach {
include(":$it")
}

rootProject.name = "libs"
Loading

0 comments on commit 654a000

Please sign in to comment.