mirror of
https://github.com/apple/pkl.git
synced 2026-04-27 10:47:12 +02:00
Motivation: buildSrc is a special-case legacy mechanism. Gradle recommends using an included build named build-logic instead: https://docs.gradle.org/current/userguide/best_practices_structuring_builds.html#favor_composite_builds Changes: - Rename buildSrc/ to build-logic/ - triggers reformatting - Replace occurrences of "buildSrc" with "build-logic" - Include the build-logic build in the main build (via settings.gradle.kts) - Apply convention plugins via plugin IDs instead of type-safe accessors - small tradeoff compared to buildSrc Result: - Faster and more isolated builds - Build logic behaves like a normal build, making it easier to evolve and reason about --------- Co-authored-by: Daniel Chao <dan.chao@apple.com>
191 lines
5.7 KiB
Kotlin
191 lines
5.7 KiB
Kotlin
/*
|
|
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* 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.
|
|
*/
|
|
import java.io.ByteArrayOutputStream
|
|
import java.io.OutputStream
|
|
import org.gradle.kotlin.dsl.support.serviceOf
|
|
|
|
plugins {
|
|
id("pklAllProjects")
|
|
id("pklKotlinLibrary")
|
|
id("pklPublishLibrary")
|
|
id("pklJavaExecutable")
|
|
id("pklNativeExecutable")
|
|
`maven-publish`
|
|
|
|
// already on build script class path (see build-logic/build.gradle.kts),
|
|
// hence must only specify plugin ID here
|
|
id(libs.plugins.shadow.get().pluginId)
|
|
|
|
alias(libs.plugins.checksum)
|
|
}
|
|
|
|
// make Java executable available to other subprojects
|
|
val javaExecutableConfiguration: Configuration = configurations.create("javaExecutable")
|
|
|
|
publishing {
|
|
publications {
|
|
named<MavenPublication>("library") {
|
|
pom {
|
|
url.set("https://github.com/apple/pkl/tree/main/pkl-cli")
|
|
description.set("Pkl CLI Java library.")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
implementation(libs.truffleRuntime)
|
|
compileOnly(libs.graalSdk)
|
|
|
|
// CliEvaluator exposes PClass
|
|
api(projects.pklCore)
|
|
// CliEvaluatorOptions exposes CliBaseOptions
|
|
api(projects.pklCommonsCli)
|
|
|
|
implementation(projects.pklCommons)
|
|
implementation(libs.jlineReader)
|
|
implementation(libs.jlineTerminal)
|
|
implementation(libs.jlineTerminalJni)
|
|
implementation(projects.pklServer)
|
|
implementation(projects.pklFormatter)
|
|
implementation(libs.clikt)
|
|
|
|
testImplementation(projects.pklCommonsTest)
|
|
testImplementation(libs.wiremock)
|
|
}
|
|
|
|
tasks.jar {
|
|
manifest.attributes +=
|
|
mapOf("Main-Class" to "org.pkl.cli.Main", "Add-Exports" to buildInfo.jpmsExportsForJarManifest)
|
|
}
|
|
|
|
tasks.javadoc { enabled = false }
|
|
|
|
tasks.shadowJar {
|
|
archiveFileName.set("jpkl")
|
|
|
|
exclude("META-INF/maven/**")
|
|
exclude("META-INF/upgrade/**")
|
|
|
|
exclude("module-info.*")
|
|
}
|
|
|
|
val testJavaExecutable by
|
|
tasks.registering(Test::class) {
|
|
testClassesDirs = tasks.test.get().testClassesDirs
|
|
classpath =
|
|
// compiled test classes
|
|
sourceSets.test.get().output +
|
|
// java executable
|
|
tasks.javaExecutable.get().outputs.files +
|
|
// test-only dependencies
|
|
// (test dependencies that are also main dependencies must already be contained in java
|
|
// executable;
|
|
// to verify that, we don't want to include them here)
|
|
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
|
}
|
|
|
|
// Setup `testJavaExecutable` tasks for multi-JDK testing.
|
|
val testJavaExecutableOnOtherJdks = buildInfo.multiJdkTestingWith(testJavaExecutable)
|
|
|
|
// Prepare a run of the fat JAR, optionally with a specific Java launcher.
|
|
private fun setupJavaExecutableRun(
|
|
name: String,
|
|
args: Array<String>,
|
|
launcher: Provider<JavaLauncher>? = null,
|
|
configurator: Exec.() -> Unit = {},
|
|
) =
|
|
tasks.register(name, Exec::class) {
|
|
dependsOn(tasks.javaExecutable)
|
|
val outputFile = layout.buildDirectory.file(name) // dummy output to satisfy up-to-date check
|
|
outputs.file(outputFile)
|
|
|
|
executable =
|
|
when (launcher) {
|
|
null -> "java"
|
|
else -> launcher.get().executablePath.asFile.absolutePath
|
|
}
|
|
standardOutput = OutputStream.nullOutputStream()
|
|
|
|
args("-jar", tasks.javaExecutable.get().outputs.files.singleFile.toString(), *args)
|
|
|
|
doFirst { outputFile.get().asFile.delete() }
|
|
|
|
doLast { outputFile.get().asFile.writeText("OK") }
|
|
|
|
configurator()
|
|
}
|
|
|
|
val evalTestFlags = arrayOf("eval", "-x", "1 + 1", "pkl:base")
|
|
|
|
fun Exec.useRootDirAndSuppressOutput() {
|
|
workingDir = rootProject.layout.projectDirectory.asFile
|
|
standardOutput = ByteArrayOutputStream() // we only care that this exec doesn't fail
|
|
}
|
|
|
|
// 0.28 Preparing for JDK21 toolchains revealed that `testStartJavaExecutable` may pass, even though
|
|
// the evaluator fails. To catch this, we eval a simple expression using the fat jar.
|
|
val testEvalJavaExecutable by
|
|
setupJavaExecutableRun("testEvalJavaExecutable", evalTestFlags) { useRootDirAndSuppressOutput() }
|
|
|
|
// Run the same evaluator tests on all configured JDK test versions.
|
|
val testEvalJavaExecutableOnOtherJdks =
|
|
buildInfo.jdkTestRange.map { jdkTarget ->
|
|
setupJavaExecutableRun(
|
|
"testEvalJavaExecutableJdk${jdkTarget.asInt()}",
|
|
evalTestFlags,
|
|
serviceOf<JavaToolchainService>().launcherFor { languageVersion = jdkTarget },
|
|
) {
|
|
useRootDirAndSuppressOutput()
|
|
}
|
|
}
|
|
|
|
tasks.check {
|
|
dependsOn(
|
|
testJavaExecutable,
|
|
testJavaExecutableOnOtherJdks,
|
|
testEvalJavaExecutable,
|
|
testEvalJavaExecutableOnOtherJdks,
|
|
)
|
|
}
|
|
|
|
tasks.checkNative {
|
|
dependsOn(":pkl-core:checkNative")
|
|
dependsOn(":pkl-server:checkNative")
|
|
}
|
|
|
|
executable {
|
|
name = "pkl"
|
|
javaName = "jpkl"
|
|
documentationName = "Pkl CLI"
|
|
publicationName = "pkl-cli"
|
|
javaPublicationName = "pkl-cli-java"
|
|
mainClass = "org.pkl.cli.Main"
|
|
website = "https://pkl-lang.org/main/current/pkl-cli/index.html"
|
|
}
|
|
|
|
// make Java executable available to other subprojects
|
|
// (we don't do the same for native executables because we don't want tasks assemble/build to build
|
|
// them)
|
|
artifacts {
|
|
add("javaExecutable", tasks.javaExecutable.map { it.outputs.files.singleFile }) {
|
|
name = "pkl-cli-java"
|
|
classifier = null
|
|
extension = "jar"
|
|
builtBy(tasks.javaExecutable)
|
|
}
|
|
}
|