Add sourceBundle task to download and prepare source bundles (#1902)
* Add tasks to generate source jars for java executables * native source bundles * source bundles in separate plugin * Wire up sourceBundle task * Produce bundles on a per-variant basis (Java fat jar, each native variant) * Introduce `pklNativeSourceBundle` and `pklJvmSourceBundle` plugins for handling fat jar vs. GraalVM bits * Download compiled classes list, and exclude Java sources for executable stuff specifically * Include native sources when appropriate (GraalVM, JDK, zlib, musl, libpkl) --------- Co-authored-by: Jen Basch <jbasch@apple.com>
This commit is contained in:
1 parent
f4ad0da658
commit
d062312df9
17 files changed
+773
-19
No files matched your search
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* 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.File
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.tasks.InputFile
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.Optional
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
|
||||||
|
open class BuildSourceBundle : DefaultTask() {
|
||||||
|
/** Sources jars that are included in full. */
|
||||||
|
@get:InputFiles val inputJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sources jars that are only included in part, if [compiledClasses] is set.
|
||||||
|
*
|
||||||
|
* Only `.java` files are dropped, if their class is not in [compiledClasses]. Everything else is
|
||||||
|
* kept: other languages (e.g. Kotlin) can't be matched by name, because the classes that they
|
||||||
|
* compile to don't necessarily relate to the file name or package (e.g. with `@file:JvmName` or
|
||||||
|
* `@file:JvmPackageName`), and licenses and other metadata must be retained.
|
||||||
|
*
|
||||||
|
* If [compiledClasses] is not set, these jars are included in full.
|
||||||
|
*/
|
||||||
|
@get:InputFiles
|
||||||
|
val filteredInputJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||||
|
|
||||||
|
/** Fully qualified names of top-level classes, one per line. */
|
||||||
|
@get:[InputFile Optional]
|
||||||
|
val compiledClasses: RegularFileProperty = project.objects.fileProperty()
|
||||||
|
|
||||||
|
@get:OutputFile val outputZip: RegularFileProperty = project.objects.fileProperty()
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
@Suppress("unused")
|
||||||
|
fun merge() {
|
||||||
|
val zipFile = outputZip.asFile.get()
|
||||||
|
if (!zipFile.getParentFile().exists()) zipFile.getParentFile().mkdirs()
|
||||||
|
val classes =
|
||||||
|
if (compiledClasses.isPresent) {
|
||||||
|
compiledClasses
|
||||||
|
.get()
|
||||||
|
.asFile
|
||||||
|
.readLines()
|
||||||
|
.map { it.trim() }
|
||||||
|
.filterTo(hashSetOf()) { it.isNotEmpty() }
|
||||||
|
} else null
|
||||||
|
val packages = classes?.mapTo(hashSetOf()) { it.substringBeforeLast('.', "").replace('.', '/') }
|
||||||
|
var dropped = 0
|
||||||
|
ZipOutputStream(zipFile.outputStream()).use { zip ->
|
||||||
|
fun copyJar(jar: File, keep: (String) -> Boolean) {
|
||||||
|
val jarName = jar.toPath().fileName.toString().removeSuffix(".jar")
|
||||||
|
project.zipTree(jar).visit {
|
||||||
|
if (isDirectory) return@visit
|
||||||
|
val path = relativePath.pathString
|
||||||
|
if (!keep(path)) {
|
||||||
|
dropped++
|
||||||
|
return@visit
|
||||||
|
}
|
||||||
|
zip.putNextEntry(ZipEntry("$jarName/$path"))
|
||||||
|
copyTo(zip)
|
||||||
|
zip.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (jar in inputJars) copyJar(jar) { true }
|
||||||
|
for (jar in filteredInputJars) {
|
||||||
|
copyJar(jar) { path ->
|
||||||
|
classes == null || packages == null || isEvident(path, classes, packages)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (classes != null) {
|
||||||
|
logger.lifecycle("Dropped $dropped source files that are not in ${compiledClasses.get()}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isEvident(path: String, classes: Set<String>, packages: Set<String>): Boolean {
|
||||||
|
// sources of multi-release jars have the same classes as the unversioned ones
|
||||||
|
val sourcePath = path.replace(multiReleasePrefix, "")
|
||||||
|
val packagePath = sourcePath.substringBeforeLast('/', "")
|
||||||
|
val fileName = sourcePath.substringAfterLast('/')
|
||||||
|
return when (sourcePath.substringAfterLast('.', "")) {
|
||||||
|
"java" ->
|
||||||
|
when (fileName) {
|
||||||
|
"package-info.java" -> packagePath in packages
|
||||||
|
"module-info.java" -> true
|
||||||
|
else -> sourcePath.removeSuffix(".java").replace('/', '.') in classes
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val multiReleasePrefix = Regex("^META-INF/versions/\\d+/")
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 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.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.RegularFileProperty
|
||||||
|
import org.gradle.api.provider.SetProperty
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.InputFile
|
||||||
|
import org.gradle.api.tasks.InputFiles
|
||||||
|
import org.gradle.api.tasks.OutputFile
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects the JDK, SubstrateVM, and Graal Java sources for every class that has methods compiled
|
||||||
|
* into a native image.
|
||||||
|
*
|
||||||
|
* The classes are read from [compiledClasses], and their sources are looked up in the OpenJDK and
|
||||||
|
* Graal repositories' tagged source archives. These archives contain the sources of every platform
|
||||||
|
* and architecture, so this task does not need to run on the platform that it collects sources for.
|
||||||
|
*/
|
||||||
|
abstract class NativeImageSourcesJar : DefaultTask() {
|
||||||
|
/**
|
||||||
|
* Fully qualified top-level names of the classes compiled into the image, one per line.
|
||||||
|
*
|
||||||
|
* This is the list that native-image reports (via `-H:+PrintUniverse`) when building the image.
|
||||||
|
*/
|
||||||
|
@get:InputFile abstract val compiledClasses: RegularFileProperty
|
||||||
|
|
||||||
|
/** The gzipped tarball of the OpenJDK repository (e.g. `jdk25u`) at the JDK's release tag. */
|
||||||
|
@get:InputFiles abstract val openJdkTarball: ConfigurableFileCollection
|
||||||
|
|
||||||
|
/** The gzipped tarball of the `oracle/graal` repository at the GraalVM's release tag. */
|
||||||
|
@get:InputFiles abstract val graalTarball: ConfigurableFileCollection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The platform-specific source roots to include from OpenJDK; any of `share`, `unix`, `linux`,
|
||||||
|
* `macosx`, and `windows`.
|
||||||
|
*/
|
||||||
|
@get:Input abstract val openJdkPlatforms: SetProperty<String>
|
||||||
|
|
||||||
|
@get:OutputFile abstract val outputJar: RegularFileProperty
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
@Suppress("unused")
|
||||||
|
fun collect() {
|
||||||
|
val wanted =
|
||||||
|
compiledClasses
|
||||||
|
.get()
|
||||||
|
.asFile
|
||||||
|
.readLines()
|
||||||
|
.filter { it.isNotBlank() }
|
||||||
|
.mapTo(hashSetOf()) { it.trim().replace('.', '/') + ".java" }
|
||||||
|
if (wanted.isEmpty()) {
|
||||||
|
throw GradleException("No compiled classes found in ${compiledClasses.get()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
val platforms = openJdkPlatforms.get()
|
||||||
|
// <repo>-<tag>/src/<module>/<platform>/classes/<package path>.java
|
||||||
|
val openJdkSource = Regex("""^[^/]+/src/[^/]+/([^/]+)/classes/(.+\.java)$""")
|
||||||
|
// <repo>-<tag>/<suite>/src/<project>/src/<package path>.java
|
||||||
|
//
|
||||||
|
// Truffle sources are intentionally omitted; they are already published as sources jars.
|
||||||
|
val graalSource = Regex("""^[^/]+/(?:substratevm|compiler|sdk)/src/[^/]+/src/(.+\.java)$""")
|
||||||
|
|
||||||
|
val out = outputJar.get().asFile
|
||||||
|
out.parentFile.mkdirs()
|
||||||
|
val written = hashSetOf<String>()
|
||||||
|
ZipOutputStream(out.outputStream().buffered()).use { zip ->
|
||||||
|
fun collectFrom(tarball: java.io.File, sourcePathOf: (String) -> String?) {
|
||||||
|
project.tarTree(project.resources.gzip(tarball)).visit {
|
||||||
|
if (isDirectory) return@visit
|
||||||
|
val sourcePath = sourcePathOf(relativePath.pathString) ?: return@visit
|
||||||
|
if (sourcePath !in wanted || !written.add(sourcePath)) return@visit
|
||||||
|
zip.putNextEntry(ZipEntry(sourcePath))
|
||||||
|
copyTo(zip)
|
||||||
|
zip.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
collectFrom(openJdkTarball.singleFile) { path ->
|
||||||
|
openJdkSource
|
||||||
|
.matchEntire(path)
|
||||||
|
?.takeIf { it.groupValues[1] in platforms }
|
||||||
|
?.let { it.groupValues[2] }
|
||||||
|
}
|
||||||
|
collectFrom(graalTarball.singleFile) { path ->
|
||||||
|
graalSource.matchEntire(path)?.groupValues?.get(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.lifecycle(
|
||||||
|
"Collected sources of ${written.size} of ${wanted.size} compiled classes into $out"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 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 org.gradle.api.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The inputs that source bundles of a project are made of.
|
||||||
|
*
|
||||||
|
* This is configured by the `pklSourceBundle` plugin; the plugins that register the actual source
|
||||||
|
* bundles (`pklJvmSourceBundle` and `pklNativeSourceBundle`) consume it.
|
||||||
|
*/
|
||||||
|
abstract class SourceBundleSpec {
|
||||||
|
/** Sources jars of the project itself, and of the projects that it depends on. */
|
||||||
|
abstract val firstPartyJars: ConfigurableFileCollection
|
||||||
|
|
||||||
|
/** Sources jars of third-party dependencies, as resolved from the runtime classpath. */
|
||||||
|
abstract val dependencyJars: ConfigurableFileCollection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional sources to include in source bundles of native targets (e.g. C sources of the
|
||||||
|
* project itself).
|
||||||
|
*/
|
||||||
|
abstract val extraNativeSources: ConfigurableFileCollection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether musl and zlib are statically linked into the project's native executable for musl
|
||||||
|
* targets, in which case their sources are included in the source bundle of those targets.
|
||||||
|
*/
|
||||||
|
abstract val staticMuslLibc: Property<Boolean>
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ plugins {
|
|||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
id("com.gradleup.shadow")
|
id("com.gradleup.shadow")
|
||||||
|
id("pklJvmSourceBundle")
|
||||||
}
|
}
|
||||||
|
|
||||||
// make fat Jar available to other subprojects
|
// make fat Jar available to other subprojects
|
||||||
@@ -31,10 +32,6 @@ val fatJarConfiguration: Configuration = configurations.create("fatJar")
|
|||||||
|
|
||||||
val fatJarPublication: MavenPublication = publishing.publications.create<MavenPublication>("fatJar")
|
val fatJarPublication: MavenPublication = publishing.publications.create<MavenPublication>("fatJar")
|
||||||
|
|
||||||
// ideally we'd configure this automatically based on project dependencies
|
|
||||||
val firstPartySourcesJarsConfiguration: Configuration =
|
|
||||||
configurations.create("firstPartySourcesJars")
|
|
||||||
|
|
||||||
val relocations =
|
val relocations =
|
||||||
mapOf(
|
mapOf(
|
||||||
// pkl-core dependencies
|
// pkl-core dependencies
|
||||||
@@ -182,17 +179,13 @@ val validateFatJar =
|
|||||||
|
|
||||||
tasks.check { dependsOn(validateFatJar) }
|
tasks.check { dependsOn(validateFatJar) }
|
||||||
|
|
||||||
val resolveSourcesJars =
|
|
||||||
tasks.register<ResolveSourcesJars>("resolveSourcesJars") {
|
|
||||||
configuration.set(configurations.runtimeClasspath)
|
|
||||||
outputDir.set(layout.buildDirectory.dir("resolveSourcesJars"))
|
|
||||||
}
|
|
||||||
|
|
||||||
val fatSourcesJar =
|
val fatSourcesJar =
|
||||||
tasks.register<MergeSourcesJars>("fatSourcesJar") {
|
tasks.register<MergeSourcesJars>("fatSourcesJar") {
|
||||||
plugins.withId("pklJavaLibrary") { inputJars.from(tasks.named("sourcesJar")) }
|
plugins.withId("pklJavaLibrary") { inputJars.from(tasks.named("sourcesJar")) }
|
||||||
inputJars.from(firstPartySourcesJarsConfiguration)
|
inputJars.from(configurations.named("firstPartySourcesJars"))
|
||||||
inputJars.from(resolveSourcesJars.map { fileTree(it.outputDir) })
|
inputJars.from(
|
||||||
|
tasks.named<ResolveSourcesJars>("resolveSourcesJars").map { fileTree(it.outputDir) }
|
||||||
|
)
|
||||||
|
|
||||||
mergedBinaryJars.from(tasks.shadowJar)
|
mergedBinaryJars.from(tasks.shadowJar)
|
||||||
relocatedPackages.set(relocations)
|
relocatedPackages.set(relocations)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ plugins {
|
|||||||
id("pklJavaLibrary")
|
id("pklJavaLibrary")
|
||||||
// id("pklPublishLibrary")
|
// id("pklPublishLibrary")
|
||||||
id("com.gradleup.shadow")
|
id("com.gradleup.shadow")
|
||||||
|
id("pklJvmSourceBundle")
|
||||||
}
|
}
|
||||||
|
|
||||||
val executableSpec = project.extensions.create("executable", ExecutableSpec::class.java)
|
val executableSpec = project.extensions.create("executable", ExecutableSpec::class.java)
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 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.
|
||||||
|
*/
|
||||||
|
// Source bundle for the JVM variant of a project: its fat JAR, or its executable JAR.
|
||||||
|
//
|
||||||
|
// These contain the complete sources of all dependencies, because fat JARs contain the complete
|
||||||
|
// classes of all dependencies.
|
||||||
|
plugins { id("pklSourceBundle") }
|
||||||
|
|
||||||
|
val sourceBundleSpec = extensions.getByType<SourceBundleSpec>()
|
||||||
|
|
||||||
|
val sourceBundleJava =
|
||||||
|
tasks.register<BuildSourceBundle>("sourceBundleJava") {
|
||||||
|
group = "build"
|
||||||
|
description = "Builds the source bundle of ${project.name}'s JVM variant."
|
||||||
|
inputJars.from(sourceBundleSpec.firstPartyJars, sourceBundleSpec.dependencyJars)
|
||||||
|
outputZip =
|
||||||
|
layout.buildDirectory.file(
|
||||||
|
"sourceBundle/${project.name}-${project.version}-java-sourcebundle.zip"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("sourceBundle") { dependsOn(sourceBundleJava) }
|
||||||
@@ -22,6 +22,7 @@ plugins {
|
|||||||
id("pklGraalVm")
|
id("pklGraalVm")
|
||||||
id("pklJavaLibrary")
|
id("pklJavaLibrary")
|
||||||
id("pklNativeLifecycle")
|
id("pklNativeLifecycle")
|
||||||
|
id("pklNativeSourceBundle")
|
||||||
id("pklPublishLibrary")
|
id("pklPublishLibrary")
|
||||||
id("com.gradleup.shadow")
|
id("com.gradleup.shadow")
|
||||||
}
|
}
|
||||||
@@ -30,6 +31,9 @@ plugins {
|
|||||||
val executableSpec = project.extensions.getByType<ExecutableSpec>()
|
val executableSpec = project.extensions.getByType<ExecutableSpec>()
|
||||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||||
|
|
||||||
|
// musl executables are linked with `--static`, so musl and zlib become part of the executable
|
||||||
|
extensions.getByType<SourceBundleSpec>().staticMuslLibc = true
|
||||||
|
|
||||||
val stagedMacAarch64Executable: Configuration = configurations.create("stagedMacAarch64Executable")
|
val stagedMacAarch64Executable: Configuration = configurations.create("stagedMacAarch64Executable")
|
||||||
val stagedLinuxAmd64Executable: Configuration = configurations.create("stagedLinuxAmd64Executable")
|
val stagedLinuxAmd64Executable: Configuration = configurations.create("stagedLinuxAmd64Executable")
|
||||||
val stagedLinuxAarch64Executable: Configuration =
|
val stagedLinuxAarch64Executable: Configuration =
|
||||||
|
|||||||
@@ -0,0 +1,322 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 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 javax.inject.Inject
|
||||||
|
import org.gradle.accessors.dm.LibrariesForLibs
|
||||||
|
import org.gradle.api.tasks.options.Option
|
||||||
|
import org.gradle.process.ExecOperations
|
||||||
|
|
||||||
|
// Source bundles for the native variants of a project, one for each `Target`.
|
||||||
|
//
|
||||||
|
// Each bundle consists of the sources of everything that is compiled into the native image or
|
||||||
|
// library of that target:
|
||||||
|
// * the project's own sources, and those of its first-party dependencies;
|
||||||
|
// * the sources of third-party dependencies that have classes in the image;
|
||||||
|
// * the Java sources of the JDK, SubstrateVM, and Graal classes that are in the image;
|
||||||
|
// * the C sources of the JDK and SubstrateVM native libraries that are linked into the image;
|
||||||
|
// * for statically linked musl executables, the sources of musl and zlib.
|
||||||
|
//
|
||||||
|
// Which classes are in the image is read from the lists in `build/compiled-classes` (download them
|
||||||
|
// with the `downloadCompiledClasses` task). native-image produces these lists, and CI uploads them
|
||||||
|
// as `compiled-classes-<project>-*` artifacts. This way, the source bundle of any target can be
|
||||||
|
// built on any machine.
|
||||||
|
//
|
||||||
|
// Sources of the JDK, SubstrateVM, and Graal come from the OpenJDK and Graal repositories at the
|
||||||
|
// tags matching the GraalVM that is used to build, because GraalVM doesn't ship all of the Java
|
||||||
|
// sources (or any of the C sources).
|
||||||
|
plugins { id("pklSourceBundle") }
|
||||||
|
|
||||||
|
val libs = the<LibrariesForLibs>()
|
||||||
|
val sourceBundleSpec = extensions.getByType<SourceBundleSpec>()
|
||||||
|
|
||||||
|
val openJdkSourcesTarball: Configuration = configurations.create("openJdkSourcesTarball")
|
||||||
|
val graalSourcesTarball: Configuration = configurations.create("graalSourcesTarball")
|
||||||
|
|
||||||
|
val muslSourcesTarball: Configuration = configurations.create("muslSourcesTarball")
|
||||||
|
val zlibSourcesTarball: Configuration = configurations.create("zlibSourcesTarball")
|
||||||
|
|
||||||
|
// CI builds musl and zlib from source for statically linked executables; use the same versions.
|
||||||
|
fun muslToolchainVersion(name: String): String {
|
||||||
|
val script = rootProject.file(".github/scripts/install_musl.sh").readText()
|
||||||
|
return Regex("${name}_VERSION=\"([^\"]+)\"").find(script)?.groupValues?.get(1)
|
||||||
|
?: throw GradleException("Could not find ${name}_VERSION in .github/scripts/install_musl.sh")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The "GitHub tag archives" and "musl releases" repositories are declared in settings.gradle.kts;
|
||||||
|
// declaring repositories in a project would stop it from using the ones declared in settings.
|
||||||
|
dependencies {
|
||||||
|
val jdkVersion = libs.versions.graalVmJdkVersion.get()
|
||||||
|
openJdkSourcesTarball("openjdk:jdk${jdkVersion.substringBefore('.')}u:jdk-$jdkVersion-ga")
|
||||||
|
graalSourcesTarball("oracle:graal:vm-${libs.versions.graalVm.get()}")
|
||||||
|
muslSourcesTarball("musl:musl:${muslToolchainVersion("MUSL")}")
|
||||||
|
zlibSourcesTarball("madler:zlib:v${muslToolchainVersion("ZLIB")}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// native-image's class path can differ from the runtime class path (e.g. `nativeImageClasspath` in
|
||||||
|
// `pklNativeExecutable`), so resolve the sources of what's actually compiled in.
|
||||||
|
val resolveNativeSourcesJars =
|
||||||
|
tasks.register<ResolveSourcesJars>("resolveNativeSourcesJars") {
|
||||||
|
configuration.set(
|
||||||
|
provider {
|
||||||
|
configurations.findByName("nativeImageClasspath")
|
||||||
|
?: configurations.getByName("runtimeClasspath")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
outputDir.set(layout.buildDirectory.dir("resolveNativeSourcesJars"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// The JDK native libraries that native-image links into the image.
|
||||||
|
val openJdkNativeLibraries = listOf("java", "net", "nio", "zip", "extnet", "management_ext")
|
||||||
|
|
||||||
|
// Platform-specific directories in OpenJDK's `src/<module>/<platform>/`.
|
||||||
|
val Target.OS.openJdkPlatforms: List<String>
|
||||||
|
get() = buildList {
|
||||||
|
add("share")
|
||||||
|
if (!isWindows) add("unix")
|
||||||
|
add(
|
||||||
|
when {
|
||||||
|
isMacOS -> "macosx"
|
||||||
|
isWindows -> "windows"
|
||||||
|
else -> "linux"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The `substratevm/src/com.oracle.svm.native.*` projects that apply to the OS.
|
||||||
|
val Target.OS.svmNativeProjects: List<String>
|
||||||
|
get() = buildList {
|
||||||
|
add("libchelper")
|
||||||
|
when {
|
||||||
|
isMacOS -> {
|
||||||
|
add("darwin")
|
||||||
|
add("jvm.posix")
|
||||||
|
}
|
||||||
|
isLinux -> {
|
||||||
|
add("libcontainer")
|
||||||
|
add("jvm.posix")
|
||||||
|
}
|
||||||
|
isWindows -> add("jvm.windows")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val sourceBundleTasks =
|
||||||
|
Target.entries.map { target ->
|
||||||
|
val variant = target.name
|
||||||
|
val outputDir = layout.buildDirectory.dir("tmp/nativeImageSources/${target.targetName}")
|
||||||
|
val compiledClassesFile =
|
||||||
|
layout.buildDirectory.file("compiled-classes/${target.targetName}.txt")
|
||||||
|
|
||||||
|
val nativeImageSourcesJar =
|
||||||
|
tasks.register<NativeImageSourcesJar>("nativeImageSourcesJar$variant") {
|
||||||
|
compiledClasses = compiledClassesFile
|
||||||
|
openJdkTarball.from(openJdkSourcesTarball)
|
||||||
|
graalTarball.from(graalSourcesTarball)
|
||||||
|
openJdkPlatforms.addAll(target.os.openJdkPlatforms)
|
||||||
|
outputJar = outputDir.map { it.file("native-image-sources.jar") }
|
||||||
|
}
|
||||||
|
|
||||||
|
val openJdkNativeSourcesJar =
|
||||||
|
tasks.register<Zip>("openJdkNativeSourcesJar$variant") {
|
||||||
|
archiveFileName = "openjdk-native-sources.jar"
|
||||||
|
destinationDirectory = outputDir
|
||||||
|
includeEmptyDirs = false
|
||||||
|
|
||||||
|
from(provider { tarTree(resources.gzip(openJdkSourcesTarball.singleFile)) }) {
|
||||||
|
for (platform in target.os.openJdkPlatforms) {
|
||||||
|
include("*/src/*/$platform/native/include/**")
|
||||||
|
for (library in openJdkNativeLibraries) {
|
||||||
|
include("*/src/*/$platform/native/lib$library/**")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// drop the `<repo>-<tag>/` root directory
|
||||||
|
eachFile {
|
||||||
|
relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val graalNativeSourcesJar =
|
||||||
|
tasks.register<Zip>("graalNativeSourcesJar$variant") {
|
||||||
|
archiveFileName = "graal-native-sources.jar"
|
||||||
|
destinationDirectory = outputDir
|
||||||
|
includeEmptyDirs = false
|
||||||
|
|
||||||
|
from(provider { tarTree(resources.gzip(graalSourcesTarball.singleFile)) }) {
|
||||||
|
for (svmProject in target.os.svmNativeProjects) {
|
||||||
|
include("*/substratevm/src/com.oracle.svm.native.$svmProject/**")
|
||||||
|
}
|
||||||
|
eachFile {
|
||||||
|
relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executables for musl targets are statically linked, so musl and zlib are part of them.
|
||||||
|
val staticLibcSources =
|
||||||
|
if (target.musl) {
|
||||||
|
val muslArch =
|
||||||
|
when (target.arch) {
|
||||||
|
Target.Arch.AMD64 -> "x86_64"
|
||||||
|
Target.Arch.AARCH64 -> "aarch64"
|
||||||
|
}
|
||||||
|
|
||||||
|
val muslSourcesJar =
|
||||||
|
tasks.register<Zip>("muslSourcesJar$variant") {
|
||||||
|
archiveFileName = "musl-sources.jar"
|
||||||
|
destinationDirectory = outputDir
|
||||||
|
includeEmptyDirs = false
|
||||||
|
|
||||||
|
from(provider { tarTree(resources.gzip(muslSourcesTarball.singleFile)) }) {
|
||||||
|
// skip the other architectures
|
||||||
|
include("*/src/**", "*/include/**", "*/crt/**", "*/ldso/**", "*/compat/**")
|
||||||
|
include("*/arch/generic/**", "*/arch/$muslArch/**")
|
||||||
|
include("*/COPYRIGHT", "*/VERSION", "*/WHATSNEW")
|
||||||
|
eachFile {
|
||||||
|
relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val zlibSourcesJar =
|
||||||
|
tasks.register<Zip>("zlibSourcesJar$variant") {
|
||||||
|
archiveFileName = "zlib-sources.jar"
|
||||||
|
destinationDirectory = outputDir
|
||||||
|
includeEmptyDirs = false
|
||||||
|
|
||||||
|
from(provider { tarTree(resources.gzip(zlibSourcesTarball.singleFile)) }) {
|
||||||
|
exclude("*/.github/**")
|
||||||
|
eachFile {
|
||||||
|
relativePath = RelativePath(true, *relativePath.segments.drop(1).toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceBundleSpec.staticMuslLibc.map { isStatic ->
|
||||||
|
if (isStatic) files(muslSourcesJar, zlibSourcesJar) else files()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
provider { files() }
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<BuildSourceBundle>("sourceBundle$variant") {
|
||||||
|
group = "build"
|
||||||
|
description = "Builds the source bundle of ${project.name} for ${target.targetName}."
|
||||||
|
inputJars.from(
|
||||||
|
sourceBundleSpec.firstPartyJars,
|
||||||
|
sourceBundleSpec.extraNativeSources,
|
||||||
|
nativeImageSourcesJar,
|
||||||
|
openJdkNativeSourcesJar,
|
||||||
|
graalNativeSourcesJar,
|
||||||
|
staticLibcSources,
|
||||||
|
)
|
||||||
|
// Only include sources of dependency classes that are compiled into the image.
|
||||||
|
filteredInputJars.from(resolveNativeSourcesJars.map { fileTree(it.outputDir) })
|
||||||
|
compiledClasses = compiledClassesFile
|
||||||
|
outputZip =
|
||||||
|
layout.buildDirectory.file(
|
||||||
|
"sourceBundle/${project.name}-${project.version}-${target.targetName}-sourcebundle.zip"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("sourceBundle") { dependsOn(sourceBundleTasks) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads the lists of classes compiled into native images, which CI uploads as
|
||||||
|
* `compiled-classes-<project>-<os>-<arch>` artifacts, into `build/compiled-classes`.
|
||||||
|
*
|
||||||
|
* Requires the GitHub CLI (`gh`) to be installed and authenticated.
|
||||||
|
*/
|
||||||
|
abstract class DownloadCompiledClasses : DefaultTask() {
|
||||||
|
@get:Option(option = "run-id", description = "ID of the GitHub Actions run to download from.")
|
||||||
|
@get:Input
|
||||||
|
abstract val runId: Property<String>
|
||||||
|
|
||||||
|
@get:Option(option = "repo", description = "GitHub repository that the run belongs to.")
|
||||||
|
@get:Input
|
||||||
|
abstract val repo: Property<String>
|
||||||
|
|
||||||
|
/** The project whose artifacts to download (named `compiled-classes-<project>-*`). */
|
||||||
|
@get:Input abstract val projectName: Property<String>
|
||||||
|
|
||||||
|
@get:OutputDirectory abstract val destinationDir: DirectoryProperty
|
||||||
|
|
||||||
|
@get:Inject protected abstract val execOperations: ExecOperations
|
||||||
|
|
||||||
|
init {
|
||||||
|
group = "build"
|
||||||
|
description = "Downloads the compiled classes lists that CI produced into the build directory."
|
||||||
|
repo.convention("apple/pkl")
|
||||||
|
// always re-download; this task is meant to be run manually
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
@Suppress("unused")
|
||||||
|
fun download() {
|
||||||
|
if (!runId.isPresent) {
|
||||||
|
throw GradleException("Specify the run to download from, e.g. `--run-id=<id>`")
|
||||||
|
}
|
||||||
|
val name = projectName.get()
|
||||||
|
val downloadDir = temporaryDir.resolve("download")
|
||||||
|
downloadDir.deleteRecursively()
|
||||||
|
downloadDir.mkdirs()
|
||||||
|
|
||||||
|
execOperations.exec {
|
||||||
|
commandLine(
|
||||||
|
"gh",
|
||||||
|
"run",
|
||||||
|
"download",
|
||||||
|
runId.get(),
|
||||||
|
"--repo",
|
||||||
|
repo.get(),
|
||||||
|
"--pattern",
|
||||||
|
"compiled-classes-$name-*",
|
||||||
|
"--dir",
|
||||||
|
downloadDir.absolutePath,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Files are named `<project>-<version>-<target name>.txt`; keep only the target name.
|
||||||
|
val fileName = Regex("^${Regex.escape(name)}-\\d+(?:\\.\\d+)*(?:-SNAPSHOT)?-(.+\\.txt)$")
|
||||||
|
val downloaded =
|
||||||
|
downloadDir
|
||||||
|
.walkTopDown()
|
||||||
|
.filter { it.isFile }
|
||||||
|
.associate { file ->
|
||||||
|
val target =
|
||||||
|
fileName.matchEntire(file.name)?.groupValues?.get(1)
|
||||||
|
?: throw GradleException("Unexpected file in downloaded artifacts: $file")
|
||||||
|
target to file
|
||||||
|
}
|
||||||
|
if (downloaded.isEmpty()) {
|
||||||
|
throw GradleException("Run ${runId.get()} has no `compiled-classes-$name-*` artifacts")
|
||||||
|
}
|
||||||
|
|
||||||
|
val destination = destinationDir.get().asFile
|
||||||
|
destination.mkdirs()
|
||||||
|
// remove lists of targets that are no longer built
|
||||||
|
destination.listFiles { f -> f.extension == "txt" }?.forEach { it.delete() }
|
||||||
|
for ((target, file) in downloaded) {
|
||||||
|
file.copyTo(destination.resolve(target))
|
||||||
|
}
|
||||||
|
logger.lifecycle("Downloaded ${downloaded.keys.sorted()} into $destination")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<DownloadCompiledClasses>("downloadCompiledClasses") {
|
||||||
|
projectName = project.name
|
||||||
|
destinationDir = layout.buildDirectory.dir("compiled-classes")
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 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.
|
||||||
|
*/
|
||||||
|
plugins { id("pklAllProjects") }
|
||||||
|
|
||||||
|
// Sources jars of the first-party projects that this project depends on.
|
||||||
|
// Ideally we'd configure this automatically based on project dependencies.
|
||||||
|
val firstPartySourcesJars: Configuration = configurations.create("firstPartySourcesJars")
|
||||||
|
|
||||||
|
// Sources jars of third-party dependencies. Project dependencies are not covered by this; they
|
||||||
|
// are added to `firstPartySourcesJars` instead.
|
||||||
|
val resolveSourcesJars =
|
||||||
|
tasks.register<ResolveSourcesJars>("resolveSourcesJars") {
|
||||||
|
configuration.set(configurations.named("runtimeClasspath"))
|
||||||
|
outputDir.set(layout.buildDirectory.dir("resolveSourcesJars"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val sourceBundleSpec = extensions.create<SourceBundleSpec>("sourceBundleSpec")
|
||||||
|
|
||||||
|
sourceBundleSpec.staticMuslLibc.convention(false)
|
||||||
|
|
||||||
|
plugins.withId("pklJavaLibrary") { sourceBundleSpec.firstPartyJars.from(tasks.named("sourcesJar")) }
|
||||||
|
|
||||||
|
plugins.withId("pklKotlinLibrary") {
|
||||||
|
sourceBundleSpec.firstPartyJars.from(tasks.named("sourcesJar"))
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceBundleSpec.firstPartyJars.from(firstPartySourcesJars)
|
||||||
|
|
||||||
|
sourceBundleSpec.dependencyJars.from(resolveSourcesJars.map { fileTree(it.outputDir) })
|
||||||
|
|
||||||
|
// Builds every source bundle of this project; there is one for each variant that the project is
|
||||||
|
// distributed as. The variants are registered by `pklJvmSourceBundle` and `pklNativeSourceBundle`.
|
||||||
|
tasks.register("sourceBundle") {
|
||||||
|
group = "build"
|
||||||
|
description = "Builds the source bundles of all variants of this project."
|
||||||
|
}
|
||||||
@@ -23,6 +23,7 @@ plugins {
|
|||||||
id("pklGraalVm")
|
id("pklGraalVm")
|
||||||
id("pklJavaLibrary")
|
id("pklJavaLibrary")
|
||||||
id("pklNativeLifecycle")
|
id("pklNativeLifecycle")
|
||||||
|
id("pklNativeSourceBundle")
|
||||||
}
|
}
|
||||||
|
|
||||||
val stagedMacAarch64NativeLibrary: Configuration =
|
val stagedMacAarch64NativeLibrary: Configuration =
|
||||||
@@ -66,6 +67,11 @@ dependencies {
|
|||||||
nativeTestRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
nativeTestRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
|
||||||
externalReaderFixtureConfiguration(project(":pkl-core", "externalReaderFixture"))
|
externalReaderFixtureConfiguration(project(":pkl-core", "externalReaderFixture"))
|
||||||
|
|
||||||
|
// firstPartySourcesJars(project(":pkl-formatter", "sourcesJar")) // TODO when syntax merges
|
||||||
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-server", "sourcesJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(CCompile::class) {
|
tasks.withType(CCompile::class) {
|
||||||
@@ -146,10 +152,7 @@ val windowsNativeImageAmd64 =
|
|||||||
extraNativeImageArgs.addAll("-Dfile.encoding=UTF-8", "-H:-CheckToolchain")
|
extraNativeImageArgs.addAll("-Dfile.encoding=UTF-8", "-H:-CheckToolchain")
|
||||||
}
|
}
|
||||||
|
|
||||||
val buildNativeImageLibrary =
|
val nativeImageBuildTask =
|
||||||
tasks.register("buildNativeImageLibrary") {
|
|
||||||
group = "build"
|
|
||||||
val underlyingTask =
|
|
||||||
when (buildInfo.targetMachine) {
|
when (buildInfo.targetMachine) {
|
||||||
Target.MacosAarch64 -> macNativeImageAarch64
|
Target.MacosAarch64 -> macNativeImageAarch64
|
||||||
Target.LinuxAarch64 -> linuxNativeImageAarch64
|
Target.LinuxAarch64 -> linuxNativeImageAarch64
|
||||||
@@ -157,8 +160,12 @@ val buildNativeImageLibrary =
|
|||||||
Target.WindowsAmd64 -> windowsNativeImageAmd64
|
Target.WindowsAmd64 -> windowsNativeImageAmd64
|
||||||
Target.AlpineLinuxAmd64 -> alpineLinuxNativeImageAmd64
|
Target.AlpineLinuxAmd64 -> alpineLinuxNativeImageAmd64
|
||||||
}
|
}
|
||||||
dependsOn(underlyingTask)
|
|
||||||
outputs.files(underlyingTask)
|
val buildNativeImageLibrary =
|
||||||
|
tasks.register("buildNativeImageLibrary") {
|
||||||
|
group = "build"
|
||||||
|
dependsOn(nativeImageBuildTask)
|
||||||
|
outputs.files(nativeImageBuildTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
val buildPklObjectFile =
|
val buildPklObjectFile =
|
||||||
@@ -282,6 +289,17 @@ val buildSharedLibrary =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Source bundles for each target are registered by `pklNativeSourceBundle`. libpkl additionally
|
||||||
|
// includes its own C sources, which are the same for all targets.
|
||||||
|
val libpklNativeSourcesJar =
|
||||||
|
tasks.register<Zip>("libpklNativeSourcesJar") {
|
||||||
|
archiveFileName = "libpkl-native-sources.jar"
|
||||||
|
destinationDirectory = layout.buildDirectory.dir("tmp/nativeImageSources")
|
||||||
|
from("src/main/c")
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceBundleSpec { extraNativeSources.from(libpklNativeSourcesJar) }
|
||||||
|
|
||||||
val Target.outputDir
|
val Target.outputDir
|
||||||
get() = layout.buildDirectory.dir("native-libs/$targetName")
|
get() = layout.buildDirectory.dir("native-libs/$targetName")
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,15 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation(projects.pklCommonsTest)
|
testImplementation(projects.pklCommonsTest)
|
||||||
testImplementation(libs.wiremock)
|
testImplementation(libs.wiremock)
|
||||||
|
|
||||||
|
// used by `pklJavaExecutable` plugin (ideally this would be inferred automatically)
|
||||||
|
firstPartySourcesJars(project(":pkl-cli", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons-cli", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-formatter", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-server", "sourcesJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.jar {
|
tasks.jar {
|
||||||
|
|||||||
@@ -30,6 +30,13 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation(projects.pklConfigJava)
|
testImplementation(projects.pklConfigJava)
|
||||||
testImplementation(projects.pklCommonsTest)
|
testImplementation(projects.pklCommonsTest)
|
||||||
|
|
||||||
|
// used by `pklJavaExecutable` plugin (ideally this would be inferred automatically)
|
||||||
|
firstPartySourcesJars(project(":pkl-codegen-java", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons-cli", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
executable {
|
executable {
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ dependencies {
|
|||||||
testImplementation(projects.pklConfigKotlin)
|
testImplementation(projects.pklConfigKotlin)
|
||||||
testImplementation(projects.pklCommonsTest)
|
testImplementation(projects.pklCommonsTest)
|
||||||
testRuntimeOnly(libs.kotlinScripting)
|
testRuntimeOnly(libs.kotlinScripting)
|
||||||
|
|
||||||
|
// used by `pklJavaExecutable` plugin (ideally this would be inferred automatically)
|
||||||
|
firstPartySourcesJars(project(":pkl-codegen-kotlin", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons-cli", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
executable {
|
executable {
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation(libs.javaxInject)
|
testImplementation(libs.javaxInject)
|
||||||
|
|
||||||
|
// firstPartySourcesJars(project(":pkl-formatter", "sourcesJar")) // TODO when syntax merges
|
||||||
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
|
|
||||||
pklCodegenJava(projects.pklCodegenJava)
|
pklCodegenJava(projects.pklCodegenJava)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ dependencies {
|
|||||||
// Graal.JS
|
// Graal.JS
|
||||||
testImplementation(libs.graalSdk)
|
testImplementation(libs.graalSdk)
|
||||||
testImplementation(libs.graalJs)
|
testImplementation(libs.graalJs)
|
||||||
|
|
||||||
|
// used by `pklJavaExecutable` plugin (ideally this would be inferred automatically)
|
||||||
|
firstPartySourcesJars(project(":pkl-commons", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons-cli", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
|
|||||||
@@ -48,9 +48,14 @@ dependencies {
|
|||||||
firstPartySourcesJars(project(":pkl-cli", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-cli", "sourcesJar"))
|
||||||
firstPartySourcesJars(project(":pkl-codegen-java", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-codegen-java", "sourcesJar"))
|
||||||
firstPartySourcesJars(project(":pkl-codegen-kotlin", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-codegen-kotlin", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-commons-cli", "sourcesJar"))
|
||||||
firstPartySourcesJars(project(":pkl-config-java", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-config-java", "sourcesJar"))
|
||||||
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-core", "sourcesJar"))
|
||||||
firstPartySourcesJars(project(":pkl-doc", "sourcesJar"))
|
firstPartySourcesJars(project(":pkl-doc", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-formatter", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-parser", "sourcesJar"))
|
||||||
|
firstPartySourcesJars(project(":pkl-server", "sourcesJar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need to figure out how to properly generate javadoc here.
|
// TODO: need to figure out how to properly generate javadoc here.
|
||||||
|
|||||||
+34
-1
@@ -68,7 +68,40 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins { id("org.gradle.toolchains.foojay-resolver-convention") version ("1.0.0") }
|
plugins { id("org.gradle.toolchains.foojay-resolver-convention") version ("1.0.0") }
|
||||||
|
|
||||||
@Suppress("UnstableApiUsage") dependencyResolutionManagement { repositories { mavenCentral() } }
|
@Suppress("UnstableApiUsage")
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
// Source archives of tagged GitHub releases (used to bundle sources of native executables).
|
||||||
|
exclusiveContent {
|
||||||
|
forRepository {
|
||||||
|
ivy {
|
||||||
|
name = "GitHub tag archives"
|
||||||
|
url = uri("https://github.com/")
|
||||||
|
patternLayout { artifact("[organisation]/[module]/archive/refs/tags/[revision].tar.gz") }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter {
|
||||||
|
includeGroup("madler")
|
||||||
|
includeGroup("openjdk")
|
||||||
|
includeGroup("oracle")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// musl's release tarballs (used to bundle sources of statically linked musl executables).
|
||||||
|
exclusiveContent {
|
||||||
|
forRepository {
|
||||||
|
ivy {
|
||||||
|
name = "musl releases"
|
||||||
|
url = uri("https://musl.libc.org/releases/")
|
||||||
|
patternLayout { artifact("[module]-[revision].tar.gz") }
|
||||||
|
metadataSources { artifact() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter { includeGroup("musl") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (prj in rootProject.children) {
|
for (prj in rootProject.children) {
|
||||||
prj.buildFileName = "${prj.name}.gradle.kts"
|
prj.buildFileName = "${prj.name}.gradle.kts"
|
||||||
|
|||||||
Reference in new issue
Block a user