mirror of
https://github.com/apple/pkl.git
synced 2026-06-11 08:12:50 +02:00
1cc20b611f
This reverts the commits that enabled Gradle's configuration cache feature. IMO: this feature is too hard to use. We don't know if a task is valid for the configuration cache until it runs, and it's very hard to tell if something is safe when authoring Gradle code. For example, our publish tasks are currently failing; I don't know how I would fix this without running the publish task again on my dev machine. Also, some of our build scripts become more brittle because of this; for example, see https://github.com/apple/pkl/blob/bb07589eae0b3195a589559a3245cbc12c29b394/build-logic/src/main/kotlin/BuildInfo.kt#L291-L296
339 lines
11 KiB
Kotlin
339 lines
11 KiB
Kotlin
/*
|
|
* Copyright © 2025-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.lang.Runtime.Version
|
|
import kotlin.io.path.createDirectories
|
|
import kotlin.io.path.writeText
|
|
import org.gradle.accessors.dm.LibrariesForLibs
|
|
|
|
plugins {
|
|
id("pklGraalVm")
|
|
id("pklJavaLibrary")
|
|
id("pklNativeLifecycle")
|
|
id("pklPublishLibrary")
|
|
id("com.gradleup.shadow")
|
|
}
|
|
|
|
// assumes that `pklJavaExecutable` is also applied
|
|
val executableSpec = project.extensions.getByType<ExecutableSpec>()
|
|
val buildInfo = project.extensions.getByType<BuildInfo>()
|
|
|
|
val stagedMacAmd64Executable: Configuration by configurations.creating
|
|
val stagedMacAarch64Executable: Configuration by configurations.creating
|
|
val stagedLinuxAmd64Executable: Configuration by configurations.creating
|
|
val stagedLinuxAarch64Executable: Configuration by configurations.creating
|
|
val stagedAlpineLinuxAmd64Executable: Configuration by configurations.creating
|
|
val stagedWindowsAmd64Executable: Configuration by configurations.creating
|
|
|
|
val nativeImageClasspath by configurations.creating {
|
|
extendsFrom(configurations.runtimeClasspath.get())
|
|
// Ensure native-image version uses GraalVM C SDKs instead of Java FFI or JNA
|
|
// (comes from artifact `mordant-jvm-graal-ffi`).
|
|
exclude("com.github.ajalt.mordant", "mordant-jvm-ffm")
|
|
exclude("com.github.ajalt.mordant", "mordant-jvm-ffm-jvm")
|
|
exclude("com.github.ajalt.mordant", "mordant-jvm-jna")
|
|
exclude("com.github.ajalt.mordant", "mordant-jvm-jna-jvm")
|
|
}
|
|
|
|
val libs = the<LibrariesForLibs>()
|
|
|
|
dependencies {
|
|
fun executableFile(suffix: String) =
|
|
files(
|
|
layout.buildDirectory.dir("executable").map { dir ->
|
|
dir.file(executableSpec.name.map { "$it-$suffix" })
|
|
}
|
|
)
|
|
nativeImageClasspath(libs.truffleRuntime)
|
|
nativeImageClasspath(libs.graalSdk)
|
|
|
|
stagedMacAarch64Executable(executableFile("macos-aarch64"))
|
|
stagedMacAmd64Executable(executableFile("macos-amd64"))
|
|
stagedLinuxAmd64Executable(executableFile("linux-amd64"))
|
|
stagedLinuxAarch64Executable(executableFile("linux-aarch64"))
|
|
stagedAlpineLinuxAmd64Executable(executableFile("alpine-linux-amd64"))
|
|
stagedWindowsAmd64Executable(executableFile("windows-amd64.exe"))
|
|
}
|
|
|
|
private fun NativeImageBuild.amd64() {
|
|
arch = Architecture.AMD64
|
|
dependsOn(":installGraalVmAmd64")
|
|
}
|
|
|
|
private fun NativeImageBuild.aarch64() {
|
|
arch = Architecture.AARCH64
|
|
dependsOn(":installGraalVmAarch64")
|
|
}
|
|
|
|
private fun NativeImageBuild.setClasspath() {
|
|
classpath.from(sourceSets.main.map { it.output })
|
|
classpath.from(
|
|
project(":pkl-commons-cli").extensions.getByType(SourceSetContainer::class)["svm"].output
|
|
)
|
|
classpath.from(nativeImageClasspath)
|
|
}
|
|
|
|
val macExecutableAmd64 by
|
|
tasks.registering(NativeImageBuild::class) {
|
|
imageName = executableSpec.name.map { "$it-macos-amd64" }
|
|
mainClass = executableSpec.mainClass
|
|
amd64()
|
|
setClasspath()
|
|
}
|
|
|
|
val macExecutableAarch64 by
|
|
tasks.registering(NativeImageBuild::class) {
|
|
imageName = executableSpec.name.map { "$it-macos-aarch64" }
|
|
mainClass = executableSpec.mainClass
|
|
aarch64()
|
|
setClasspath()
|
|
}
|
|
|
|
val linuxExecutableAmd64 by
|
|
tasks.registering(NativeImageBuild::class) {
|
|
imageName = executableSpec.name.map { "$it-linux-amd64" }
|
|
mainClass = executableSpec.mainClass
|
|
amd64()
|
|
setClasspath()
|
|
}
|
|
|
|
val linuxExecutableAarch64 by
|
|
tasks.registering(NativeImageBuild::class) {
|
|
imageName = executableSpec.name.map { "$it-linux-aarch64" }
|
|
mainClass = executableSpec.mainClass
|
|
aarch64()
|
|
setClasspath()
|
|
// Ensure compatibility for kernels with page size set to 4k, 16k and 64k
|
|
// (e.g. Raspberry Pi 5, Asahi Linux)
|
|
extraNativeImageArgs.add("-H:PageSize=65536")
|
|
}
|
|
|
|
val alpineExecutableAmd64 by
|
|
tasks.registering(NativeImageBuild::class) {
|
|
imageName = executableSpec.name.map { "$it-alpine-linux-amd64" }
|
|
mainClass = executableSpec.mainClass
|
|
amd64()
|
|
setClasspath()
|
|
extraNativeImageArgs.addAll(listOf("--static", "--libc=musl"))
|
|
}
|
|
|
|
val windowsExecutableAmd64 by
|
|
tasks.registering(NativeImageBuild::class) {
|
|
imageName = executableSpec.name.map { "$it-windows-amd64" }
|
|
mainClass = executableSpec.mainClass
|
|
amd64()
|
|
setClasspath()
|
|
}
|
|
|
|
val assembleNative by tasks.existing
|
|
|
|
val testStartNativeExecutable by tasks.registering {
|
|
dependsOn(assembleNative)
|
|
|
|
// dummy file for up-to-date checking
|
|
val outputFile = project.layout.buildDirectory.file("testStartNativeExecutable/output.txt")
|
|
outputs.file(outputFile)
|
|
|
|
val execOutput = providers.exec {
|
|
commandLine(assembleNative.get().outputs.files.singleFile, "--version")
|
|
}
|
|
|
|
doLast {
|
|
val outputText = execOutput.standardOutput.asText.get()
|
|
if (!outputText.contains(buildInfo.pklVersionNonUnique)) {
|
|
throw GradleException(
|
|
"Expected version output to contain current version (${buildInfo.pklVersionNonUnique}), but got '$outputText'"
|
|
)
|
|
}
|
|
outputFile.get().asFile.toPath().apply {
|
|
try {
|
|
parent.createDirectories()
|
|
} catch (_: java.nio.file.FileAlreadyExistsException) {}
|
|
writeText("OK")
|
|
}
|
|
}
|
|
}
|
|
|
|
val requiredGlibcVersion: Version = Version.parse("2.17")
|
|
|
|
val checkGlibc by tasks.registering {
|
|
enabled = buildInfo.os.isLinux && !buildInfo.musl
|
|
dependsOn(assembleNative)
|
|
doLast {
|
|
val exec = providers.exec {
|
|
commandLine("objdump", "-T", assembleNative.get().outputs.files.singleFile)
|
|
}
|
|
val output = exec.standardOutput.asText.get()
|
|
val minimumGlibcVersion =
|
|
output
|
|
.split("\n")
|
|
.mapNotNull { line ->
|
|
val match = Regex("GLIBC_([.0-9]*)").find(line)
|
|
match?.groups[1]?.let { Version.parse(it.value) }
|
|
}
|
|
.maxOrNull()
|
|
if (minimumGlibcVersion == null) {
|
|
throw GradleException(
|
|
"Could not determine glibc version from executable. objdump output: $output"
|
|
)
|
|
}
|
|
if (minimumGlibcVersion > requiredGlibcVersion) {
|
|
throw GradleException(
|
|
"Incorrect glibc version. Found: $minimumGlibcVersion, required: $requiredGlibcVersion"
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Expose underlying task's outputs
|
|
private fun <T : Task> Task.wraps(other: TaskProvider<T>) {
|
|
dependsOn(other)
|
|
outputs.files(other)
|
|
}
|
|
|
|
val testNative by tasks.existing { dependsOn(testStartNativeExecutable, checkGlibc) }
|
|
|
|
val assembleNativeMacOsAarch64 by tasks.existing { wraps(macExecutableAarch64) }
|
|
|
|
val assembleNativeMacOsAmd64 by tasks.existing { wraps(macExecutableAmd64) }
|
|
|
|
val assembleNativeLinuxAarch64 by tasks.existing { wraps(linuxExecutableAarch64) }
|
|
|
|
val assembleNativeLinuxAmd64 by tasks.existing { wraps(linuxExecutableAmd64) }
|
|
|
|
val assembleNativeAlpineLinuxAmd64 by tasks.existing { wraps(alpineExecutableAmd64) }
|
|
|
|
val assembleNativeWindowsAmd64 by tasks.existing { wraps(windowsExecutableAmd64) }
|
|
|
|
publishing {
|
|
publications {
|
|
// need to put in `afterEvaluate` because `artifactId` cannot be set lazily.
|
|
project.afterEvaluate {
|
|
create<MavenPublication>("macExecutableAmd64") {
|
|
artifactId = "${executableSpec.publicationName.get()}-macos-amd64"
|
|
artifact(stagedMacAmd64Executable.singleFile) {
|
|
classifier = null
|
|
extension = "bin"
|
|
builtBy(stagedMacAmd64Executable)
|
|
}
|
|
pom {
|
|
name = "${executableSpec.publicationName.get()}-macos-amd64"
|
|
url = executableSpec.website
|
|
description =
|
|
executableSpec.documentationName.map { name ->
|
|
"Native $name executable for macOS/amd64."
|
|
}
|
|
}
|
|
}
|
|
|
|
create<MavenPublication>("macExecutableAarch64") {
|
|
artifactId = "${executableSpec.publicationName.get()}-macos-aarch64"
|
|
artifact(stagedMacAarch64Executable.singleFile) {
|
|
classifier = null
|
|
extension = "bin"
|
|
builtBy(stagedMacAarch64Executable)
|
|
}
|
|
pom {
|
|
name = "${executableSpec.publicationName.get()}-macos-aarch64"
|
|
url = executableSpec.website
|
|
description =
|
|
executableSpec.documentationName.map { name ->
|
|
"Native $name executable for macOS/aarch64."
|
|
}
|
|
}
|
|
}
|
|
|
|
create<MavenPublication>("linuxExecutableAmd64") {
|
|
artifactId = "${executableSpec.publicationName.get()}-linux-amd64"
|
|
artifact(stagedLinuxAmd64Executable.singleFile) {
|
|
classifier = null
|
|
extension = "bin"
|
|
builtBy(stagedLinuxAmd64Executable)
|
|
}
|
|
pom {
|
|
name = "${executableSpec.publicationName.get()}-linux-amd64"
|
|
url = executableSpec.website
|
|
description =
|
|
executableSpec.documentationName.map { name ->
|
|
"Native $name executable for linux/amd64."
|
|
}
|
|
}
|
|
}
|
|
|
|
create<MavenPublication>("linuxExecutableAarch64") {
|
|
artifactId = "${executableSpec.publicationName.get()}-linux-aarch64"
|
|
artifact(stagedLinuxAarch64Executable.singleFile) {
|
|
classifier = null
|
|
extension = "bin"
|
|
builtBy(stagedLinuxAarch64Executable)
|
|
}
|
|
pom {
|
|
name = "${executableSpec.publicationName.get()}-linux-aarch64"
|
|
url = executableSpec.website
|
|
description =
|
|
executableSpec.documentationName.map { name ->
|
|
"Native $name executable for linux/aarch64."
|
|
}
|
|
}
|
|
}
|
|
|
|
create<MavenPublication>("alpineLinuxExecutableAmd64") {
|
|
artifactId = "${executableSpec.publicationName.get()}-alpine-linux-amd64"
|
|
artifact(stagedAlpineLinuxAmd64Executable.singleFile) {
|
|
classifier = null
|
|
extension = "bin"
|
|
builtBy(stagedAlpineLinuxAmd64Executable)
|
|
}
|
|
pom {
|
|
name = "${executableSpec.publicationName.get()}-alpine-linux-amd64"
|
|
url = executableSpec.website
|
|
description =
|
|
executableSpec.documentationName.map { name ->
|
|
"Native $name executable for linux/amd64 and statically linked to musl."
|
|
}
|
|
}
|
|
}
|
|
|
|
create<MavenPublication>("windowsExecutableAmd64") {
|
|
artifactId = "${executableSpec.publicationName.get()}-windows-amd64"
|
|
artifact(stagedWindowsAmd64Executable.singleFile) {
|
|
classifier = null
|
|
extension = "exe"
|
|
builtBy(stagedWindowsAmd64Executable)
|
|
}
|
|
pom {
|
|
name = "${executableSpec.publicationName.get()}-windows-amd64"
|
|
url = executableSpec.website
|
|
description =
|
|
executableSpec.documentationName.map { name ->
|
|
"Native $name executable for windows/amd64."
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
signing {
|
|
project.afterEvaluate {
|
|
sign(publishing.publications["linuxExecutableAarch64"])
|
|
sign(publishing.publications["linuxExecutableAmd64"])
|
|
sign(publishing.publications["macExecutableAarch64"])
|
|
sign(publishing.publications["macExecutableAmd64"])
|
|
sign(publishing.publications["alpineLinuxExecutableAmd64"])
|
|
sign(publishing.publications["windowsExecutableAmd64"])
|
|
}
|
|
}
|