Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d097341abd | ||
|
|
0eab5fb552 | ||
|
|
7c3787396e | ||
|
|
57df7995fd | ||
|
|
6c97b09c29 | ||
|
|
da19c3971e | ||
|
|
efad356b7b | ||
|
|
261a2260a1 | ||
|
|
204c6b16c3 | ||
|
|
f91f91fd30 | ||
|
|
309fb49fa1 |
No files matched your search
@@ -0,0 +1,165 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
// File gets rendered to .circleci/config.yml via git hook.
|
||||
amends "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.circleci@1.1.1#/PklCI.pkl"
|
||||
|
||||
import "jobs/BuildNativeJob.pkl"
|
||||
import "jobs/GradleCheckJob.pkl"
|
||||
import "jobs/DeployJob.pkl"
|
||||
import "jobs/SimpleGradleJob.pkl"
|
||||
|
||||
local prbJobs: Listing<String> = gradleCheckJobs.keys.toListing()
|
||||
|
||||
local buildAndTestJobs = (prbJobs) {
|
||||
"bench"
|
||||
"gradle-compatibility"
|
||||
...buildNativeJobs.keys.filter((it) -> it.endsWith("snapshot"))
|
||||
}
|
||||
|
||||
local releaseJobs = (prbJobs) {
|
||||
"bench"
|
||||
"gradle-compatibility"
|
||||
...buildNativeJobs.keys.filter((it) -> it.endsWith("release"))
|
||||
}
|
||||
|
||||
prb {
|
||||
jobs = prbJobs
|
||||
}
|
||||
|
||||
main {
|
||||
jobs {
|
||||
...buildAndTestJobs
|
||||
new {
|
||||
["deploy-snapshot"] {
|
||||
requires = buildAndTestJobs
|
||||
context = "pkl-maven-release"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
release {
|
||||
jobs {
|
||||
...releaseJobs
|
||||
// do GitHub release first because we can overwrite the tag.
|
||||
// publishing to Maven Central is final.
|
||||
new {
|
||||
["github-release"] {
|
||||
requires = releaseJobs
|
||||
context = "pkl-github-release"
|
||||
}
|
||||
}
|
||||
new {
|
||||
["deploy-release"] {
|
||||
requires { "github-release" }
|
||||
context = "pkl-maven-release"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
releaseBranch {
|
||||
jobs = releaseJobs
|
||||
}
|
||||
|
||||
triggerDocsBuild = "both"
|
||||
|
||||
triggerPackageDocsBuild = "release"
|
||||
|
||||
local buildNativeJobs: Mapping<String, BuildNativeJob> = new {
|
||||
for (_dist in List("release", "snapshot")) {
|
||||
for (_arch in List("amd64", "aarch64")) {
|
||||
for (_os in List("macOS", "linux")) {
|
||||
["pkl-cli-\(_os)-\(_arch)-\(_dist)"] {
|
||||
arch = _arch
|
||||
os = _os
|
||||
isRelease = _dist == "release"
|
||||
}
|
||||
}
|
||||
}
|
||||
["pkl-cli-linux-alpine-amd64-\(_dist)"] {
|
||||
arch = "amd64"
|
||||
os = "linux"
|
||||
musl = true
|
||||
isRelease = _dist == "release"
|
||||
}
|
||||
["pkl-cli-windows-amd64-\(_dist)"] {
|
||||
arch = "amd64"
|
||||
os = "windows"
|
||||
isRelease = _dist == "release"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local gradleCheckJobs: Mapping<String, GradleCheckJob> = new {
|
||||
["gradle-check-jdk17"] {
|
||||
javaVersion = "17.0"
|
||||
isRelease = false
|
||||
}
|
||||
["gradle-check-jdk21"] {
|
||||
javaVersion = "21.0"
|
||||
isRelease = false
|
||||
}
|
||||
["gradle-check-jdk17-windows"] {
|
||||
javaVersion = "17.0"
|
||||
isRelease = false
|
||||
os = "windows"
|
||||
}
|
||||
}
|
||||
|
||||
jobs {
|
||||
for (jobName, job in buildNativeJobs) {
|
||||
[jobName] = job.job
|
||||
}
|
||||
for (jobName, job in gradleCheckJobs) {
|
||||
[jobName] = job.job
|
||||
}
|
||||
["bench"] = new SimpleGradleJob { command = "bench:jmh" }.job
|
||||
["gradle-compatibility"] = new SimpleGradleJob {
|
||||
name = "gradle compatibility"
|
||||
command = #"""
|
||||
:pkl-gradle:build \
|
||||
:pkl-gradle:compatibilityTestReleases
|
||||
"""#
|
||||
}.job
|
||||
["deploy-snapshot"] = new DeployJob { command = "publishToSonatype" }.job
|
||||
["deploy-release"] = new DeployJob {
|
||||
isRelease = true
|
||||
command = "publishToSonatype closeAndReleaseSonatypeStagingRepository"
|
||||
}.job
|
||||
["github-release"] {
|
||||
docker {
|
||||
new { image = "maniator/gh:v2.40.1" }
|
||||
}
|
||||
steps {
|
||||
new AttachWorkspaceStep { at = "." }
|
||||
new RunStep {
|
||||
name = "Publish release on GitHub"
|
||||
command = #"""
|
||||
# exclude build_artifacts.txt from publish
|
||||
rm -f pkl-cli/build/executable/*.build_artifacts.txt
|
||||
gh release create "${CIRCLE_TAG}" \
|
||||
--title "${CIRCLE_TAG}" \
|
||||
--target "${CIRCLE_SHA1}" \
|
||||
--verify-tag \
|
||||
--notes "Release notes: https://pkl-lang.org/main/current/release-notes/changelog.html#release-${CIRCLE_TAG}" \
|
||||
--repo "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" \
|
||||
pkl-cli/build/executable/*
|
||||
"""#
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,877 @@
|
||||
# Generated from CircleCI.pkl. DO NOT EDIT.
|
||||
version: '2.1'
|
||||
orbs:
|
||||
pr-approval: apple/pr-approval@0.1.0
|
||||
jobs:
|
||||
pkl-cli-macOS-amd64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: /usr/sbin/softwareupdate --install-rosetta --agree-to-license
|
||||
name: Installing Rosetta 2
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: macos.m1.large.gen1
|
||||
macos:
|
||||
xcode: 15.3.0
|
||||
pkl-cli-linux-amd64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: staticdeps-amd64
|
||||
name: Restore static deps from cache
|
||||
- run:
|
||||
command: |-
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/x86_64-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-1.2.13: configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-1.2.13: make..." && make -s -j4 \
|
||||
&& echo "zlib-1.2.13: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-1.2.13
|
||||
fi
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
&& cat /tmp/musl.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "musl-1.2.2: configure..." && ./configure --disable-shared --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "musl-1.2.2: make..." && make -s -j4 \
|
||||
&& echo "musl-1.2.2: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_musl-1.2.2
|
||||
|
||||
# native-image expects to find an executable at this path.
|
||||
ln -s ~/staticdeps/bin/musl-gcc ~/staticdeps/bin/x86_64-linux-musl-gcc
|
||||
fi
|
||||
name: Set up environment
|
||||
shell: '#!/bin/bash -exo pipefail'
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/staticdeps
|
||||
key: staticdeps-amd64
|
||||
name: Save statics deps to cache
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: oraclelinux:8-slim
|
||||
pkl-cli-macOS-aarch64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: macos.m1.large.gen1
|
||||
macos:
|
||||
xcode: 15.3.0
|
||||
pkl-cli-linux-aarch64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: staticdeps-aarch64
|
||||
name: Restore static deps from cache
|
||||
- run:
|
||||
command: |-
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/aarch64-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-1.2.13: configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-1.2.13: make..." && make -s -j4 \
|
||||
&& echo "zlib-1.2.13: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-1.2.13
|
||||
fi
|
||||
name: Set up environment
|
||||
shell: '#!/bin/bash -exo pipefail'
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/staticdeps
|
||||
key: staticdeps-aarch64
|
||||
name: Save statics deps to cache
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: arm.xlarge
|
||||
docker:
|
||||
- image: arm64v8/oraclelinux:8-slim
|
||||
pkl-cli-linux-alpine-amd64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: staticdeps-amd64
|
||||
name: Restore static deps from cache
|
||||
- run:
|
||||
command: |-
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/x86_64-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-1.2.13: configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-1.2.13: make..." && make -s -j4 \
|
||||
&& echo "zlib-1.2.13: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-1.2.13
|
||||
fi
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
&& cat /tmp/musl.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "musl-1.2.2: configure..." && ./configure --disable-shared --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "musl-1.2.2: make..." && make -s -j4 \
|
||||
&& echo "musl-1.2.2: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_musl-1.2.2
|
||||
|
||||
# native-image expects to find an executable at this path.
|
||||
ln -s ~/staticdeps/bin/musl-gcc ~/staticdeps/bin/x86_64-linux-musl-gcc
|
||||
fi
|
||||
name: Set up environment
|
||||
shell: '#!/bin/bash -exo pipefail'
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/staticdeps
|
||||
key: staticdeps-amd64
|
||||
name: Save statics deps to cache
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: oraclelinux:8-slim
|
||||
pkl-cli-windows-amd64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64
|
||||
name: gradle buildNative
|
||||
shell: bash.exe
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: windows.large
|
||||
machine:
|
||||
image: windows-server-2022-gui:current
|
||||
pkl-cli-macOS-amd64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: /usr/sbin/softwareupdate --install-rosetta --agree-to-license
|
||||
name: Installing Rosetta 2
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:macExecutableAmd64 pkl-core:testMacExecutableAmd64 pkl-server:testMacExecutableAmd64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: macos.m1.large.gen1
|
||||
macos:
|
||||
xcode: 15.3.0
|
||||
pkl-cli-linux-amd64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: staticdeps-amd64
|
||||
name: Restore static deps from cache
|
||||
- run:
|
||||
command: |-
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/x86_64-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-1.2.13: configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-1.2.13: make..." && make -s -j4 \
|
||||
&& echo "zlib-1.2.13: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-1.2.13
|
||||
fi
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
&& cat /tmp/musl.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "musl-1.2.2: configure..." && ./configure --disable-shared --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "musl-1.2.2: make..." && make -s -j4 \
|
||||
&& echo "musl-1.2.2: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_musl-1.2.2
|
||||
|
||||
# native-image expects to find an executable at this path.
|
||||
ln -s ~/staticdeps/bin/musl-gcc ~/staticdeps/bin/x86_64-linux-musl-gcc
|
||||
fi
|
||||
name: Set up environment
|
||||
shell: '#!/bin/bash -exo pipefail'
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/staticdeps
|
||||
key: staticdeps-amd64
|
||||
name: Save statics deps to cache
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:linuxExecutableAmd64 pkl-core:testLinuxExecutableAmd64 pkl-server:testLinuxExecutableAmd64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: oraclelinux:8-slim
|
||||
pkl-cli-macOS-aarch64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:macExecutableAarch64 pkl-core:testMacExecutableAarch64 pkl-server:testMacExecutableAarch64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: macos.m1.large.gen1
|
||||
macos:
|
||||
xcode: 15.3.0
|
||||
pkl-cli-linux-aarch64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: staticdeps-aarch64
|
||||
name: Restore static deps from cache
|
||||
- run:
|
||||
command: |-
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/aarch64-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-1.2.13: configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-1.2.13: make..." && make -s -j4 \
|
||||
&& echo "zlib-1.2.13: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-1.2.13
|
||||
fi
|
||||
name: Set up environment
|
||||
shell: '#!/bin/bash -exo pipefail'
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/staticdeps
|
||||
key: staticdeps-aarch64
|
||||
name: Save statics deps to cache
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:linuxExecutableAarch64 pkl-core:testLinuxExecutableAarch64 pkl-server:testLinuxExecutableAarch64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: arm.xlarge
|
||||
docker:
|
||||
- image: arm64v8/oraclelinux:8-slim
|
||||
pkl-cli-linux-alpine-amd64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: staticdeps-amd64
|
||||
name: Restore static deps from cache
|
||||
- run:
|
||||
command: |-
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/x86_64-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-1.2.13: configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-1.2.13: make..." && make -s -j4 \
|
||||
&& echo "zlib-1.2.13: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-1.2.13
|
||||
fi
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
&& cat /tmp/musl.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "musl-1.2.2: configure..." && ./configure --disable-shared --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "musl-1.2.2: make..." && make -s -j4 \
|
||||
&& echo "musl-1.2.2: make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_musl-1.2.2
|
||||
|
||||
# native-image expects to find an executable at this path.
|
||||
ln -s ~/staticdeps/bin/musl-gcc ~/staticdeps/bin/x86_64-linux-musl-gcc
|
||||
fi
|
||||
name: Set up environment
|
||||
shell: '#!/bin/bash -exo pipefail'
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/staticdeps
|
||||
key: staticdeps-amd64
|
||||
name: Save statics deps to cache
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:alpineExecutableAmd64 pkl-core:testAlpineExecutableAmd64 pkl-server:testAlpineExecutableAmd64
|
||||
name: gradle buildNative
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
- image: oraclelinux:8-slim
|
||||
pkl-cli-windows-amd64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results pkl-cli:windowsExecutableAmd64 pkl-core:testWindowsExecutableAmd64 pkl-server:testWindowsExecutableAmd64
|
||||
name: gradle buildNative
|
||||
shell: bash.exe
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: windows.large
|
||||
machine:
|
||||
image: windows-server-2022-gui:current
|
||||
gradle-check-jdk17:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
|
||||
name: gradle check
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
docker:
|
||||
- image: cimg/openjdk:17.0
|
||||
gradle-check-jdk21:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
|
||||
name: gradle check
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
docker:
|
||||
- image: cimg/openjdk:21.0
|
||||
gradle-check-jdk17-windows:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
|
||||
name: gradle check
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
resource_class: windows.large
|
||||
machine:
|
||||
image: windows-server-2022-gui:current
|
||||
bench:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results bench:jmh
|
||||
name: bench:jmh
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
docker:
|
||||
- image: cimg/openjdk:17.0
|
||||
gradle-compatibility:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results :pkl-gradle:build \
|
||||
:pkl-gradle:compatibilityTestReleases
|
||||
name: gradle compatibility
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
docker:
|
||||
- image: cimg/openjdk:17.0
|
||||
deploy-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: '.'
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results publishToSonatype
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
docker:
|
||||
- image: cimg/openjdk:17.0
|
||||
deploy-release:
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: '.'
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results -DreleaseBuild=true publishToSonatype closeAndReleaseSonatypeStagingRepository
|
||||
- persist_to_workspace:
|
||||
root: '.'
|
||||
paths:
|
||||
- pkl-cli/build/executable/
|
||||
- store_test_results:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
docker:
|
||||
- image: cimg/openjdk:17.0
|
||||
github-release:
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: '.'
|
||||
- run:
|
||||
command: |-
|
||||
# exclude build_artifacts.txt from publish
|
||||
rm -f pkl-cli/build/executable/*.build_artifacts.txt
|
||||
gh release create "${CIRCLE_TAG}" \
|
||||
--title "${CIRCLE_TAG}" \
|
||||
--target "${CIRCLE_SHA1}" \
|
||||
--verify-tag \
|
||||
--notes "Release notes: https://pkl-lang.org/main/current/release-notes/changelog.html#release-${CIRCLE_TAG}" \
|
||||
--repo "${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}" \
|
||||
pkl-cli/build/executable/*
|
||||
name: Publish release on GitHub
|
||||
docker:
|
||||
- image: maniator/gh:v2.40.1
|
||||
trigger-docsite-build:
|
||||
steps:
|
||||
- run:
|
||||
command: |-
|
||||
curl --location \
|
||||
--request POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-u "${CIRCLE_TOKEN}:" \
|
||||
--data '{ "branch": "main" }' \
|
||||
"https://circleci.com/api/v2/project/github/apple/pkl-lang.org/pipeline"
|
||||
name: Triggering docsite build
|
||||
docker:
|
||||
- image: cimg/base:current
|
||||
trigger-package-docs-build:
|
||||
steps:
|
||||
- run:
|
||||
command: |-
|
||||
curl --location \
|
||||
--request POST \
|
||||
--header "Content-Type: application/json" \
|
||||
-u "${CIRCLE_TOKEN}:" \
|
||||
--data '{ "branch": "main" }' \
|
||||
"https://circleci.com/api/v2/project/github/apple/pkl-package-docs/pipeline"
|
||||
name: Triggering docsite build
|
||||
docker:
|
||||
- image: cimg/base:current
|
||||
workflows:
|
||||
prb:
|
||||
jobs:
|
||||
- hold:
|
||||
type: approval
|
||||
- pr-approval/authenticate:
|
||||
context: pkl-pr-approval
|
||||
- gradle-check-jdk17:
|
||||
requires:
|
||||
- hold
|
||||
- gradle-check-jdk21:
|
||||
requires:
|
||||
- hold
|
||||
- gradle-check-jdk17-windows:
|
||||
requires:
|
||||
- hold
|
||||
when:
|
||||
matches:
|
||||
value: << pipeline.git.branch >>
|
||||
pattern: ^pull/\d+(/head)?$
|
||||
main:
|
||||
jobs:
|
||||
- gradle-check-jdk17
|
||||
- gradle-check-jdk21
|
||||
- gradle-check-jdk17-windows
|
||||
- bench
|
||||
- gradle-compatibility
|
||||
- pkl-cli-macOS-amd64-snapshot
|
||||
- pkl-cli-linux-amd64-snapshot
|
||||
- pkl-cli-macOS-aarch64-snapshot
|
||||
- pkl-cli-linux-aarch64-snapshot
|
||||
- pkl-cli-linux-alpine-amd64-snapshot
|
||||
- pkl-cli-windows-amd64-snapshot
|
||||
- deploy-snapshot:
|
||||
requires:
|
||||
- gradle-check-jdk17
|
||||
- gradle-check-jdk21
|
||||
- gradle-check-jdk17-windows
|
||||
- bench
|
||||
- gradle-compatibility
|
||||
- pkl-cli-macOS-amd64-snapshot
|
||||
- pkl-cli-linux-amd64-snapshot
|
||||
- pkl-cli-macOS-aarch64-snapshot
|
||||
- pkl-cli-linux-aarch64-snapshot
|
||||
- pkl-cli-linux-alpine-amd64-snapshot
|
||||
- pkl-cli-windows-amd64-snapshot
|
||||
context: pkl-maven-release
|
||||
- trigger-docsite-build:
|
||||
requires:
|
||||
- deploy-snapshot
|
||||
context:
|
||||
- pkl-pr-approval
|
||||
when:
|
||||
equal:
|
||||
- main
|
||||
- << pipeline.git.branch >>
|
||||
release:
|
||||
jobs:
|
||||
- gradle-check-jdk17:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- gradle-check-jdk21:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- gradle-check-jdk17-windows:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- bench:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- gradle-compatibility:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-cli-macOS-amd64-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-cli-linux-amd64-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-cli-macOS-aarch64-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-cli-linux-aarch64-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-cli-linux-alpine-amd64-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- pkl-cli-windows-amd64-release:
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- github-release:
|
||||
requires:
|
||||
- gradle-check-jdk17
|
||||
- gradle-check-jdk21
|
||||
- gradle-check-jdk17-windows
|
||||
- bench
|
||||
- gradle-compatibility
|
||||
- pkl-cli-macOS-amd64-release
|
||||
- pkl-cli-linux-amd64-release
|
||||
- pkl-cli-macOS-aarch64-release
|
||||
- pkl-cli-linux-aarch64-release
|
||||
- pkl-cli-linux-alpine-amd64-release
|
||||
- pkl-cli-windows-amd64-release
|
||||
context: pkl-github-release
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- deploy-release:
|
||||
requires:
|
||||
- github-release
|
||||
context: pkl-maven-release
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
- trigger-package-docs-build:
|
||||
requires:
|
||||
- deploy-release
|
||||
context:
|
||||
- pkl-pr-approval
|
||||
filters:
|
||||
branches:
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^v?\d+\.\d+\.\d+$/
|
||||
release-branch:
|
||||
jobs:
|
||||
- gradle-check-jdk17
|
||||
- gradle-check-jdk21
|
||||
- gradle-check-jdk17-windows
|
||||
- bench
|
||||
- gradle-compatibility
|
||||
- pkl-cli-macOS-amd64-release
|
||||
- pkl-cli-linux-amd64-release
|
||||
- pkl-cli-macOS-aarch64-release
|
||||
- pkl-cli-linux-aarch64-release
|
||||
- pkl-cli-linux-alpine-amd64-release
|
||||
- pkl-cli-windows-amd64-release
|
||||
when:
|
||||
matches:
|
||||
value: << pipeline.git.branch >>
|
||||
pattern: ^release/\d+\.\d+$
|
||||
@@ -0,0 +1,164 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Builds the native `pkl` CLI
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.uri@1.0.0#/URI.pkl"
|
||||
|
||||
/// The architecture to use
|
||||
arch: "amd64"|"aarch64"
|
||||
|
||||
/// Whether to link to musl. Otherwise, links to glibc.
|
||||
musl: Boolean = false
|
||||
|
||||
local setupLinuxEnvironment: Config.RunStep =
|
||||
let (jdkVersion = "17.0.9+9")
|
||||
let (muslVersion = "1.2.2")
|
||||
let (zlibVersion = "1.2.13")
|
||||
let (jdkVersionEncoded = URI.encodeComponent(jdkVersion))
|
||||
let (jdkVersionAlt = jdkVersion.replaceLast("+", "_"))
|
||||
let (majorJdkVersion = jdkVersion.split(".").first)
|
||||
new {
|
||||
name = "Set up environment"
|
||||
shell = "#!/bin/bash -exo pipefail"
|
||||
command = new Listing {
|
||||
#"""
|
||||
sed -ie '/\[ol8_codeready_builder\]/,/^$/s/enabled=0/enabled=1/g' /etc/yum.repos.d/oracle-linux-ol8.repo \
|
||||
&& microdnf -y install util-linux tree coreutils-single findutils curl tar gzip git zlib-devel gcc-c++ make openssl glibc-langpack-en libstdc++-static \
|
||||
&& microdnf clean all \
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin\#(majorJdkVersion)-binaries/releases/download/jdk-\#(jdkVersionEncoded)/OpenJDK\#(majorJdkVersion)U-jdk_\#(if (arch == "amd64") "x64" else "aarch64")_linux_hotspot_\#(jdkVersionAlt).tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
&& cat /tmp/jdk.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
mkdir -p ~/staticdeps/bin
|
||||
|
||||
cp /usr/lib/gcc/\#(if (arch == "amd64") "x86_64" else "aarch64")-redhat-linux/8/libstdc++.a ~/staticdeps
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v\#(zlibVersion)/zlib-\#(zlibVersion).tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-\#(zlibVersion) \
|
||||
&& cd /tmp/dep_zlib-\#(zlibVersion) \
|
||||
&& cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "zlib-\#(zlibVersion): configure..." && ./configure --static --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "zlib-\#(zlibVersion): make..." && make -s -j4 \
|
||||
&& echo "zlib-\#(zlibVersion): make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_zlib-\#(zlibVersion)
|
||||
fi
|
||||
"""#
|
||||
// don't need musl on aarch because GraalVM only supports musl builds on x86
|
||||
when (arch == "amd64") {
|
||||
#"""
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-\#(muslVersion).tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-\#(muslVersion) \
|
||||
&& cd /tmp/dep_musl-\#(muslVersion) \
|
||||
&& cat /tmp/musl.tar.gz | tar --strip-components=1 -xzC . \
|
||||
&& echo "musl-\#(muslVersion): configure..." && ./configure --disable-shared --prefix="$HOME"/staticdeps > /dev/null \
|
||||
&& echo "musl-\#(muslVersion): make..." && make -s -j4 \
|
||||
&& echo "musl-\#(muslVersion): make install..." && make -s install \
|
||||
&& rm -rf /tmp/dep_musl-\#(muslVersion)
|
||||
|
||||
# native-image expects to find an executable at this path.
|
||||
ln -s ~/staticdeps/bin/musl-gcc ~/staticdeps/bin/x86_64-linux-musl-gcc
|
||||
fi
|
||||
"""#
|
||||
}
|
||||
}.join("\n\n")
|
||||
}
|
||||
|
||||
steps {
|
||||
when (os == "linux") {
|
||||
new Config.RestoreCacheStep {
|
||||
name = "Restore static deps from cache"
|
||||
key = "staticdeps-\(arch)"
|
||||
}
|
||||
setupLinuxEnvironment
|
||||
new Config.SaveCacheStep {
|
||||
name = "Save statics deps to cache"
|
||||
key = "staticdeps-\(arch)"
|
||||
paths {
|
||||
"~/staticdeps"
|
||||
}
|
||||
}
|
||||
}
|
||||
when (os == "macOS" && arch == "amd64") {
|
||||
new Config.RunStep {
|
||||
name = "Installing Rosetta 2"
|
||||
command = """
|
||||
/usr/sbin/softwareupdate --install-rosetta --agree-to-license
|
||||
"""
|
||||
}
|
||||
}
|
||||
new Config.RunStep {
|
||||
name = "gradle buildNative"
|
||||
local _os =
|
||||
if (module.os == "macOS") "mac"
|
||||
else if (musl) "alpine"
|
||||
else if (module.os == "windows") "windows"
|
||||
else "linux"
|
||||
local jobName = "\(_os)Executable\(arch.capitalize())"
|
||||
when (module.os == "windows") {
|
||||
shell = "bash.exe"
|
||||
}
|
||||
command = #"""
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
./gradlew \#(module.gradleArgs) pkl-cli:\#(jobName) pkl-core:test\#(jobName.capitalize()) pkl-server:test\#(jobName.capitalize())
|
||||
"""#
|
||||
}
|
||||
new Config.PersistToWorkspaceStep {
|
||||
root = "."
|
||||
paths {
|
||||
"pkl-cli/build/executable/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
job {
|
||||
when (os == "macOS") {
|
||||
macos {
|
||||
xcode = "15.3.0"
|
||||
}
|
||||
resource_class = "macos.m1.large.gen1"
|
||||
}
|
||||
when (os == "linux") {
|
||||
docker {
|
||||
new {
|
||||
image = if (arch == "aarch64") "arm64v8/oraclelinux:8-slim" else "oraclelinux:8-slim"
|
||||
}
|
||||
}
|
||||
environment {
|
||||
["JAVA_HOME"] = "/jdk"
|
||||
}
|
||||
resource_class = if (arch == "aarch64") "arm.xlarge" else "xlarge"
|
||||
}
|
||||
when (os == "windows") {
|
||||
machine {
|
||||
image = "windows-server-2022-gui:current"
|
||||
}
|
||||
resource_class = "windows.large"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
|
||||
local self = this
|
||||
|
||||
command: String
|
||||
|
||||
job {
|
||||
docker {
|
||||
new { image = "cimg/openjdk:17.0" }
|
||||
}
|
||||
}
|
||||
|
||||
os = "linux"
|
||||
|
||||
steps {
|
||||
new Config.AttachWorkspaceStep { at = "." }
|
||||
new Config.RunStep {
|
||||
command = "./gradlew \(self.gradleArgs) \(module.command)"
|
||||
}
|
||||
// add jpkl to workspace so it gets published as a GitHub release
|
||||
new Config.PersistToWorkspaceStep {
|
||||
root = "."
|
||||
paths {
|
||||
"pkl-cli/build/executable/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
|
||||
javaVersion: "17.0"|"21.0"
|
||||
|
||||
os = "linux"
|
||||
|
||||
steps {
|
||||
new Config.RunStep {
|
||||
name = "gradle check"
|
||||
command = "./gradlew \(module.gradleArgs) check"
|
||||
}
|
||||
}
|
||||
|
||||
job {
|
||||
when (os == "linux") {
|
||||
docker {
|
||||
new {
|
||||
image = "cimg/openjdk:\(javaVersion)"
|
||||
}
|
||||
}
|
||||
}
|
||||
when (os == "windows") {
|
||||
machine {
|
||||
image = "windows-server-2022-gui:current"
|
||||
}
|
||||
resource_class = "windows.large"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
abstract module GradleJob
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
|
||||
/// Whether this is a release build or not.
|
||||
isRelease: Boolean = false
|
||||
|
||||
/// The OS to run on
|
||||
os: "macOS"|"linux"|"windows"
|
||||
|
||||
fixed gradleArgs = new Listing {
|
||||
"--info"
|
||||
"--stacktrace"
|
||||
"-DtestReportsDir=${HOME}/test-results"
|
||||
when (isRelease) {
|
||||
"-DreleaseBuild=true"
|
||||
}
|
||||
}.join(" ")
|
||||
|
||||
steps: Listing<Config.Step>
|
||||
|
||||
job: Config.Job = new {
|
||||
environment {
|
||||
["LANG"] = "en_US.UTF-8"
|
||||
}
|
||||
steps {
|
||||
"checkout"
|
||||
...module.steps
|
||||
new Config.StoreTestResults {
|
||||
path = "~/test-results"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
|
||||
name: String = command
|
||||
|
||||
command: String
|
||||
|
||||
os = "linux"
|
||||
|
||||
steps {
|
||||
new Config.RunStep {
|
||||
name = module.name
|
||||
command = """
|
||||
./gradlew \(module.gradleArgs) \(module.command)
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
job {
|
||||
docker {
|
||||
new { image = "cimg/openjdk:17.0" }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
# Auto-format Kotlin code
|
||||
816cd483c8adf4c04e14236c173a1dc6bd2579ea
|
||||
# Format Kotlin code again
|
||||
2b3603b544bae2ad87374b65afaf8ac018216261
|
||||
@@ -1,6 +1,5 @@
|
||||
# linguist-generated would suppress files in diffs
|
||||
**/src/test/files/** linguist-vendored
|
||||
.github/workflows/* linguist-generated
|
||||
|
||||
/docs/** linguist-documentation
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
files=`git diff --cached --name-status`
|
||||
|
||||
if [[ $files =~ .github/* ]]; then
|
||||
pkl eval --project-dir .github/ -m .github .github/index.pkl
|
||||
git add .github/workflows/
|
||||
if [[ $files =~ .circleci/config.pkl ]]; then
|
||||
pkl eval .circleci/config.pkl -o .circleci/config.yml
|
||||
git add .circleci/config.yml
|
||||
fi
|
||||
@@ -1,10 +0,0 @@
|
||||
amends "pkl:Project"
|
||||
|
||||
dependencies {
|
||||
["pkl.impl.ghactions"] {
|
||||
uri = "package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.8.2"
|
||||
}
|
||||
["gha"] {
|
||||
uri = "package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.4.0"
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"resolvedDependencies": {
|
||||
"package://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1": {
|
||||
"type": "remote",
|
||||
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.actions@1.9.0",
|
||||
"checksums": {
|
||||
"sha256": "5947924cf94fae9d8cdca42ade3f86db2675842cab7254214e7c0e281ddb6908"
|
||||
}
|
||||
},
|
||||
"package://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1": {
|
||||
"type": "remote",
|
||||
"uri": "projectpackage://pkg.pkl-lang.org/pkl-project-commons/pkl.impl.ghactions@1.8.2",
|
||||
"checksums": {
|
||||
"sha256": "12cca6326806ec37abc790a6707b6d907b4f8ba97628f2bc7fb327b5a6f68b49"
|
||||
}
|
||||
},
|
||||
"package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.deepToTyped@1": {
|
||||
"type": "remote",
|
||||
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.deepToTyped@1.2.1",
|
||||
"checksums": {
|
||||
"sha256": "6e752d1e84aff24c3a1801658f27f12af70840c39b3fe7bac509c8178d566d25"
|
||||
}
|
||||
},
|
||||
"package://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1": {
|
||||
"type": "remote",
|
||||
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/pkl.github.dependabotManagedActions@1.1.9",
|
||||
"checksums": {
|
||||
"sha256": "467b91559f31ad7401c78d3df9569b5ec7aa4e1b49209f9f22d02bd72971e0bd"
|
||||
}
|
||||
},
|
||||
"package://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1": {
|
||||
"type": "remote",
|
||||
"uri": "projectpackage://pkg.pkl-lang.org/pkl-pantry/com.github.dependabot@1.0.4",
|
||||
"checksums": {
|
||||
"sha256": "c7391119f946d7761d0ca0cc358ed8fe2bdfc691411087ccac89637bd96fec4a"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: gradle
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: /
|
||||
schedule:
|
||||
interval: quarterly
|
||||
- package-ecosystem: github-actions
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: /
|
||||
groups:
|
||||
first-party:
|
||||
patterns:
|
||||
- actions/*
|
||||
codeql:
|
||||
patterns:
|
||||
- github/codeql-action/*
|
||||
ignore:
|
||||
- dependency-name: '*'
|
||||
update-types:
|
||||
- version-update:semver-major
|
||||
schedule:
|
||||
interval: quarterly
|
||||
@@ -1,261 +0,0 @@
|
||||
amends "@pkl.impl.ghactions/PklCI.pkl"
|
||||
|
||||
import "@gha/Workflow.pkl"
|
||||
|
||||
import "jobs/BuildJavaExecutableJob.pkl"
|
||||
import "jobs/BuildNativeJob.pkl"
|
||||
import "jobs/DeployJob.pkl"
|
||||
import "jobs/GithubRelease.pkl"
|
||||
import "jobs/GradleJob.pkl"
|
||||
import "jobs/PklJob.pkl"
|
||||
import "jobs/SimpleGradleJob.pkl"
|
||||
|
||||
triggerDocsBuild = "both"
|
||||
|
||||
testReports {
|
||||
junit {
|
||||
"**/build/test-results/**/*.xml"
|
||||
}
|
||||
html {
|
||||
"**/build/reports/tests/**/*"
|
||||
}
|
||||
excludeJobs {
|
||||
"bench"
|
||||
"github-release"
|
||||
"dependency-submission"
|
||||
"dependency-review"
|
||||
Regex("deploy-.*")
|
||||
}
|
||||
}
|
||||
|
||||
local baseGradleCheck: SimpleGradleJob = new {
|
||||
isRelease = false
|
||||
command = "check"
|
||||
fetchDepth = 0
|
||||
}
|
||||
|
||||
local gradleCheck = (baseGradleCheck) {
|
||||
os = "linux"
|
||||
}
|
||||
|
||||
local gradleCheckWindows = (baseGradleCheck) {
|
||||
os = "windows"
|
||||
}
|
||||
|
||||
local typealias PklJobs = Mapping<String, PklJob | *Workflow.Job>
|
||||
|
||||
local toWorkflowJobs: (PklJobs) -> Workflow.Jobs = (it) -> new Workflow.Jobs {
|
||||
for (k, v in it) {
|
||||
when (v is PklJob) {
|
||||
[k] = v.job
|
||||
} else {
|
||||
[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local gradleCheckJobs: PklJobs = new {
|
||||
["gradle-check"] = gradleCheck
|
||||
["gradle-check-windows"] = gradleCheckWindows
|
||||
}
|
||||
|
||||
local buildNativeJobs: Mapping<String, BuildNativeJob> = new {
|
||||
for (_dist in List("release", "snapshot")) {
|
||||
for (_project in List("pkl-cli", "pkl-doc", "libpkl")) {
|
||||
for (_arch in List("amd64", "aarch64")) {
|
||||
["\(_project)-linux-\(_arch)-\(_dist)"] {
|
||||
arch = _arch
|
||||
os = "linux"
|
||||
isRelease = _dist == "release"
|
||||
project = _project
|
||||
buildDir = if (_project == "libpkl") "libpkl/build/native-libs/**/*" else "\(_project)*/build/executable/**/*"
|
||||
}
|
||||
}
|
||||
["\(_project)-macOS-aarch64-\(_dist)"] {
|
||||
arch = "aarch64"
|
||||
os = "macOS"
|
||||
isRelease = _dist == "release"
|
||||
project = _project
|
||||
}
|
||||
["\(_project)-alpine-linux-amd64-\(_dist)"] {
|
||||
arch = "amd64"
|
||||
os = "linux"
|
||||
musl = true
|
||||
isRelease = _dist == "release"
|
||||
project = _project
|
||||
buildDir = if (_project == "libpkl") "libpkl*/build/distributions/**/*" else "\(_project)*/build/executable/**/*"
|
||||
}
|
||||
["\(_project)-windows-amd64-\(_dist)"] {
|
||||
arch = "amd64"
|
||||
os = "windows"
|
||||
isRelease = _dist == "release"
|
||||
project = _project
|
||||
buildDir = if (_project == "libpkl") "libpkl*/build/distributions/**/*" else "\(_project)*/build/executable/**/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local buildNativeSnapshots = buildNativeJobs.toMap().filter((key, _) -> key.endsWith("snapshot"))
|
||||
|
||||
local buildNativeReleases = buildNativeJobs.toMap().filter((key, _) -> key.endsWith("release"))
|
||||
|
||||
local benchmarkJob: SimpleGradleJob = new { command = "bench:jmh" }
|
||||
|
||||
local gradleCompatibilityJob: SimpleGradleJob = new {
|
||||
command = ":pkl-gradle:build :pkl-gradle:compatibilityTestReleases"
|
||||
fetchDepth = 0
|
||||
}
|
||||
|
||||
local buildJavaExecutableJob: BuildJavaExecutableJob = new {
|
||||
fetchDepth = 0
|
||||
}
|
||||
|
||||
local buildAndTestJobs: PklJobs = new {
|
||||
...gradleCheckJobs
|
||||
["bench"] = benchmarkJob
|
||||
["gradle-compatibility"] = gradleCompatibilityJob
|
||||
["java-executables-snapshot"] = (buildJavaExecutableJob) { isRelease = false }
|
||||
...buildNativeSnapshots
|
||||
}
|
||||
|
||||
local releaseJobs: PklJobs = new {
|
||||
...gradleCheckJobs
|
||||
["bench"] = benchmarkJob
|
||||
["gradle-compatibility"] = gradleCompatibilityJob
|
||||
["java-executables-release"] = (buildJavaExecutableJob) { isRelease = true }
|
||||
...buildNativeReleases
|
||||
}
|
||||
|
||||
// By default, just run ./gradlew check on linux.
|
||||
// Trigger other checks based on GitHub PR description. Examples:
|
||||
//
|
||||
// * [windows] -- Test on Windows
|
||||
// * [native] -- Test all native builds
|
||||
// * [native-pkl-cli] -- Test all pkl-cli os/arch pairs
|
||||
// * [native-pkl-cli-macos] -- Test pkl-cli on macOS
|
||||
prb {
|
||||
local prbJobs: Mapping<String, GradleJob> = new {
|
||||
["gradle-check"] = gradleCheck
|
||||
["gradle-check-windows"] = (gradleCheckWindows) {
|
||||
`if` = "contains(github.event.pull_request.body, '[windows]')"
|
||||
}
|
||||
for (jobName, job in buildNativeSnapshots) {
|
||||
[jobName] = (job) {
|
||||
local tags = new Listing {
|
||||
"[native]"
|
||||
"[native-\(job.project)]"
|
||||
"[native-\(job.project)-\(job.os)]"
|
||||
"[native-\(job.project)-\(job.os)-\(job.arch)]"
|
||||
"[native-\(job.project)-\(job.os)-\(job.arch)]"
|
||||
when (job.musl) {
|
||||
"[native-\(job.project)-alpine-\(job.os)-\(job.arch)]"
|
||||
}
|
||||
}
|
||||
`if` =
|
||||
tags
|
||||
.toList()
|
||||
.map((it) -> "contains(github.event.pull_request.body, '\(it)')")
|
||||
.join(" || ")
|
||||
}
|
||||
}
|
||||
}
|
||||
local prbJobs2 = (prbJobs) {
|
||||
[[true]] {
|
||||
// better SLA when not running on nightly
|
||||
nightlyMacOS = false
|
||||
}
|
||||
}
|
||||
jobs = prbJobs2 |> toWorkflowJobs
|
||||
}
|
||||
|
||||
build {
|
||||
jobs = buildAndTestJobs |> toWorkflowJobs
|
||||
}
|
||||
|
||||
main {
|
||||
jobs =
|
||||
(buildAndTestJobs) {
|
||||
["deploy-snapshot"] = (
|
||||
new DeployJob {
|
||||
extraGradleArgs {
|
||||
"--no-parallel"
|
||||
}
|
||||
command = "publishToSonatype"
|
||||
}
|
||||
) {
|
||||
needs = buildAndTestJobs.keys.toListing()
|
||||
}
|
||||
["dependency-submission"] {
|
||||
`runs-on` = "ubuntu-latest"
|
||||
permissions {
|
||||
contents = "write"
|
||||
}
|
||||
steps {
|
||||
module.catalog.`actions/checkout@v6`
|
||||
(module.catalog.`actions/setup-java@v5`) {
|
||||
with {
|
||||
`java-version` = "25"
|
||||
distribution = "temurin"
|
||||
}
|
||||
}
|
||||
(module.catalog.`gradle/actions/dependency-submission@v6`) {
|
||||
with {
|
||||
// language=regexp
|
||||
`dependency-graph-include-configurations` =
|
||||
".*[rR]untimeClasspath|.*[cC]ompileClasspath"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} |> toWorkflowJobs
|
||||
}
|
||||
|
||||
releaseBranch {
|
||||
jobs = releaseJobs |> toWorkflowJobs
|
||||
}
|
||||
|
||||
release {
|
||||
jobs =
|
||||
(releaseJobs) {
|
||||
["deploy-release"] = (
|
||||
new DeployJob {
|
||||
isRelease = true
|
||||
command = "publishToSonatype closeAndReleaseSonatypeStagingRepository"
|
||||
}
|
||||
) {
|
||||
needs = releaseJobs.keys.toListing()
|
||||
}
|
||||
["github-release"] = new GithubRelease {
|
||||
needs = releaseJobs.keys.toListing()
|
||||
}
|
||||
} |> toWorkflowJobs
|
||||
}
|
||||
|
||||
dependabot {
|
||||
updates {
|
||||
new {
|
||||
`package-ecosystem` = "gradle"
|
||||
schedule {
|
||||
interval = "quarterly"
|
||||
}
|
||||
cooldown {
|
||||
`default-days` = 7
|
||||
}
|
||||
directory = "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codeql {
|
||||
scans {
|
||||
new {
|
||||
language = "java-kotlin"
|
||||
buildMode = "autobuild"
|
||||
}
|
||||
new {
|
||||
language = "javascript-typescript"
|
||||
buildMode = "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "@gha/catalog.pkl"
|
||||
|
||||
// Keep this in sync with projects that build java executables
|
||||
local projects: List<String> = List("pkl-doc", "pkl-cli", "pkl-codegen-java", "pkl-codegen-kotlin")
|
||||
|
||||
local command =
|
||||
new Listing<String> {
|
||||
"./gradlew"
|
||||
module.gradleArgs
|
||||
for (project in projects) {
|
||||
// NOTE: `build` doesn't build native executables
|
||||
"\(project):build"
|
||||
}
|
||||
}.join(" ")
|
||||
|
||||
steps {
|
||||
new {
|
||||
name = "gradle build java executables"
|
||||
shell = "bash"
|
||||
run = command
|
||||
}
|
||||
(catalog.`actions/upload-artifact@v5`) {
|
||||
name = "Upload executable artifacts"
|
||||
with {
|
||||
name = "deploy-artifacts-java-executables"
|
||||
path = "*/build/executable/**/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "@gha/catalog.pkl"
|
||||
|
||||
/// Whether to link to musl. Otherwise, links to glibc.
|
||||
musl: Boolean(implies(module.os == "linux")) = false
|
||||
|
||||
/// The Gradle project under which to generate the executable
|
||||
project: String
|
||||
|
||||
/// Path pattern for artifact uploads (glob passed to actions/upload-artifact)
|
||||
buildDir: String = "\(project)*/build/executable/**/*"
|
||||
|
||||
local needsCCompiler = project == "libpkl"
|
||||
|
||||
extraGradleArgs {
|
||||
when (musl) {
|
||||
"-Dpkl.musl=true"
|
||||
}
|
||||
}
|
||||
|
||||
preSteps {
|
||||
when (os == "linux" && !musl) {
|
||||
new {
|
||||
name = "Install deps"
|
||||
run =
|
||||
"dnf install -y git binutils gcc glibc-devel zlib-devel libstdc++-static glibc-langpack-en"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
steps {
|
||||
when (musl) {
|
||||
new {
|
||||
name = "Install musl and zlib"
|
||||
run = read("../scripts/install_musl.sh").text
|
||||
}
|
||||
}
|
||||
// workaround for https://github.com/actions/checkout/issues/1048
|
||||
when (os == "linux" && !musl) {
|
||||
new {
|
||||
name = "Fix git ownership"
|
||||
// language=bash
|
||||
run = #"git status || git config --system --add safe.directory "$GITHUB_WORKSPACE""#
|
||||
}
|
||||
}
|
||||
when (needsCCompiler && os == "windows") {
|
||||
new {
|
||||
name = "Set up MSVC"
|
||||
uses = "ilammy/msvc-dev-cmd@v1"
|
||||
}
|
||||
}
|
||||
new {
|
||||
name = "gradle buildNative"
|
||||
shell = "bash"
|
||||
run = "./gradlew \(module.gradleArgs) \(project):buildNative"
|
||||
}
|
||||
(catalog.`actions/upload-artifact@v5`) {
|
||||
name = "Upload built artifacts"
|
||||
with {
|
||||
name =
|
||||
if (musl)
|
||||
"deploy-artifacts-\(project)-alpine-\(module.os)-\(module.arch)"
|
||||
else
|
||||
"deploy-artifacts-\(project)-\(module.os)-\(module.arch)"
|
||||
// Need to insert a wildcard to make actions/upload-artifact preserve the folder hierarchy.
|
||||
// See https://github.com/actions/upload-artifact/issues/206
|
||||
path = module.buildDir
|
||||
}
|
||||
}
|
||||
(catalog.`actions/upload-artifact@v5`) {
|
||||
name = "Upload compiled classes list"
|
||||
with {
|
||||
name =
|
||||
if (musl)
|
||||
"compiled-classes-\(project)-alpine-\(module.os)-\(module.arch)"
|
||||
else
|
||||
"compiled-classes-\(project)-\(module.os)-\(module.arch)"
|
||||
// Need to insert a wildcard to make actions/upload-artifact preserve the folder hierarchy.
|
||||
// See https://github.com/actions/upload-artifact/issues/206
|
||||
path = "\(project)*/build/compiled-classes/**/*"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fixed job {
|
||||
when (os == "linux" && !musl) {
|
||||
container {
|
||||
image = "redhat/ubi8:8.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "@gha/catalog.pkl"
|
||||
import "@gha/Workflow.pkl"
|
||||
import "@pkl.impl.ghactions/helpers.pkl"
|
||||
|
||||
local self = this
|
||||
|
||||
command: String
|
||||
|
||||
arch = "amd64"
|
||||
|
||||
os = "linux"
|
||||
|
||||
steps {
|
||||
catalog.`actions/checkout@v6`
|
||||
(catalog.`actions/download-artifact@v6`) {
|
||||
with {
|
||||
pattern = "deploy-artifacts-**"
|
||||
`merge-multiple` = true
|
||||
}
|
||||
}
|
||||
new Workflow.Step {
|
||||
run = "./gradlew \(self.gradleArgs) \(module.command)"
|
||||
}
|
||||
|> helpers.withMavenPublishSecrets
|
||||
}
|
||||
|
||||
fixed job {
|
||||
environment = "maven-release"
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
module GithubRelease
|
||||
|
||||
extends "PklJob.pkl"
|
||||
|
||||
import "@gha/catalog.pkl"
|
||||
import "@gha/context.pkl"
|
||||
|
||||
fixed job {
|
||||
`runs-on` = "ubuntu-latest"
|
||||
permissions {
|
||||
contents = "write"
|
||||
}
|
||||
needs = module.needs
|
||||
steps {
|
||||
(catalog.`actions/download-artifact@v6`) {
|
||||
with {
|
||||
pattern = "deploy-artifacts-**"
|
||||
`merge-multiple` = true
|
||||
}
|
||||
}
|
||||
new {
|
||||
name = "Publish release on GitHub"
|
||||
env {
|
||||
["GH_TOKEN"] = context.github.token
|
||||
["TAG_NAME"] = context.github.refName
|
||||
["GIT_SHA"] = context.github.sha
|
||||
["GH_REPO"] = context.github.repository
|
||||
}
|
||||
// language=bash
|
||||
run =
|
||||
#"""
|
||||
gh release create ${TAG_NAME} \
|
||||
--draft \
|
||||
--title "${TAG_NAME}" \
|
||||
--target "${GIT_SHA}" \
|
||||
--verify-tag \
|
||||
--notes "Release notes: https://pkl-lang.org/main/current/release-notes/changelog.html#release-${TAG_NAME}" \
|
||||
*/build/executable/*
|
||||
"""#
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
abstract module GradleJob
|
||||
|
||||
extends "PklJob.pkl"
|
||||
|
||||
import "@gha/Workflow.pkl"
|
||||
import "@gha/context.pkl"
|
||||
import "@pkl.impl.ghactions/catalog.pkl"
|
||||
|
||||
/// Whether this is a release build or not.
|
||||
isRelease: Boolean = false
|
||||
|
||||
/// The architecture to use
|
||||
arch: "amd64" | "aarch64" = "amd64"
|
||||
|
||||
/// The OS to run on.
|
||||
os: "macOS" | "linux" | "windows" = "linux"
|
||||
|
||||
// TODO flip this to `true` when nightly macOS is available
|
||||
/// Whether to run on nightly macOS.
|
||||
nightlyMacOS: Boolean(implies(os == "macOS")) = false
|
||||
|
||||
extraGradleArgs: Listing<String>
|
||||
|
||||
steps: Listing<Workflow.Step>
|
||||
|
||||
preSteps: Listing<Workflow.Step>
|
||||
|
||||
/// The fetch depth to use when doing a git checkout.
|
||||
fetchDepth: Int?
|
||||
|
||||
fixed gradleArgs =
|
||||
new Listing {
|
||||
"$DEBUG_ARGS"
|
||||
"--no-daemon"
|
||||
"-DpklMultiJdkTesting=true"
|
||||
when (isRelease) {
|
||||
"-DreleaseBuild=true"
|
||||
}
|
||||
...extraGradleArgs
|
||||
}.join(" ")
|
||||
|
||||
fixed job {
|
||||
env {
|
||||
["LANG"] = "en_US.UTF-8"
|
||||
when (os == "windows") {
|
||||
["JAVA_HOME"] = "/jdk"
|
||||
}
|
||||
}
|
||||
when (os == "macOS") {
|
||||
`if` =
|
||||
let (cond = "github.repository_owner == 'apple'")
|
||||
if (super.`if` != null)
|
||||
"(\(super.`if`)) && \(cond)"
|
||||
else
|
||||
cond
|
||||
}
|
||||
`runs-on` =
|
||||
if (os == "linux" && arch == "amd64")
|
||||
"ubuntu-latest"
|
||||
else if (os == "linux" && arch == "aarch64")
|
||||
"ubuntu-24.04-arm"
|
||||
else if (os == "windows")
|
||||
"windows-latest"
|
||||
else
|
||||
new Listing {
|
||||
"self-hosted"
|
||||
"macos"
|
||||
// Currently have a bug where macOS runners have `cc` from XCode 26 toolchain but have
|
||||
// default SDK set to 27.
|
||||
// TODO remove me once this issue is fixed.
|
||||
"tahoe"
|
||||
when (nightlyMacOS) {
|
||||
"nightly"
|
||||
}
|
||||
}
|
||||
steps {
|
||||
...preSteps
|
||||
// full checkout (needed for spotless)
|
||||
(catalog.`actions/checkout@v6`) {
|
||||
when (fetchDepth != null) {
|
||||
with {
|
||||
`fetch-depth` = fetchDepth
|
||||
}
|
||||
}
|
||||
}
|
||||
(catalog.`actions/setup-java@v5`) {
|
||||
with {
|
||||
`java-version` = "25"
|
||||
distribution = "temurin"
|
||||
architecture =
|
||||
if (arch == "amd64")
|
||||
"x64"
|
||||
else
|
||||
"aarch64"
|
||||
}
|
||||
}
|
||||
(catalog.`gradle/actions/setup-gradle@v5`) {
|
||||
when (isRelease) {
|
||||
with {
|
||||
`cache-disabled` = true
|
||||
}
|
||||
}
|
||||
}
|
||||
new {
|
||||
name = "Set DEBUG_ARGS env var"
|
||||
env {
|
||||
["RUNNER_DEBUG"] = context.runner.debug
|
||||
}
|
||||
shell = "bash"
|
||||
// language=bash
|
||||
run =
|
||||
"""
|
||||
if [[ "$RUNNER_DEBUG" -eq 1 ]]; then
|
||||
echo "DEBUG_ARGS=--info --stacktrace" >> $GITHUB_ENV
|
||||
fi
|
||||
"""
|
||||
}
|
||||
...module.steps
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
abstract module PklJob
|
||||
|
||||
extends "@pkl.impl.ghactions/jobs/PklJob.pkl"
|
||||
|
||||
/// Identify any jobs that must complete successfully before this job will run.
|
||||
///
|
||||
/// It can be a string or array of strings.
|
||||
/// If a job fails or is skipped, all jobs that need it are skipped unless the jobs use a conditional expression that
|
||||
/// causes the job to continue.
|
||||
/// If a run contains a series of jobs that need each other, a failure or skip applies to all jobs in the dependency
|
||||
/// chain from the point of failure or skip onwards. If you would like a job to run even if a job it is dependent on
|
||||
/// did not succeed, use the `always()` conditional expression in `jobs.<job_id>.if`.
|
||||
///
|
||||
/// See: <https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idneeds>
|
||||
needs: (String | *Listing<String>)?
|
||||
|
||||
/// A conditional to prevent a job from running unless a condition is met.
|
||||
///
|
||||
/// You can use any supported context and expression to create a conditional.
|
||||
/// For more information on which contexts are supported in this key, see
|
||||
/// [Contexts reference](https://docs.github.com/en/actions/reference/workflows-and-actions/contexts#context-availability).
|
||||
@SourceCode { language = "GithubExpressionLanguage" }
|
||||
`if`: String?
|
||||
|
||||
/// The underlying workflow job
|
||||
fixed job {
|
||||
`if` = module.`if`
|
||||
needs = module.needs
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
name: String = command
|
||||
|
||||
command: String
|
||||
|
||||
os = "linux"
|
||||
|
||||
steps {
|
||||
new {
|
||||
name = module.name
|
||||
shell = "bash"
|
||||
run =
|
||||
"""
|
||||
./gradlew \(module.gradleArgs) \(module.command)
|
||||
"""
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
set -e
|
||||
mkdir -p ~/staticdeps/
|
||||
|
||||
ZLIB_VERSION="1.2.13"
|
||||
MUSL_VERSION="9fa28ece75d8a2191de7c5bb53bed224c5947417" # v1.2.6
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
# Download zlib tarball and signature
|
||||
curl -Lf "https://github.com/madler/zlib/releases/download/v${ZLIB_VERSION}/zlib-${ZLIB_VERSION}.tar.gz" -o /tmp/zlib.tar.gz
|
||||
curl -Lf "https://github.com/madler/zlib/releases/download/v${ZLIB_VERSION}/zlib-${ZLIB_VERSION}.tar.gz.asc" -o /tmp/zlib.tar.gz.asc
|
||||
|
||||
# Import zlib GPG key
|
||||
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 5ED46A6721D365587791E2AA783FCD8E58BCAFBA
|
||||
|
||||
# Verify GPG signature
|
||||
echo "Verifying zlib GPG signature..."
|
||||
gpg --verify /tmp/zlib.tar.gz.asc /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p "/tmp/dep_zlib-${ZLIB_VERSION}"
|
||||
cd "/tmp/dep_zlib-${ZLIB_VERSION}"
|
||||
# shellcheck disable=SC2002
|
||||
cat /tmp/zlib.tar.gz | tar --strip-components=1 -xzC .
|
||||
|
||||
echo "zlib-${ZLIB_VERSION}: configure..."
|
||||
./configure --static --prefix="$HOME"/staticdeps > /dev/null
|
||||
|
||||
echo "zlib-${ZLIB_VERSION}: make..."
|
||||
make -s -j4
|
||||
|
||||
echo "zlib-${ZLIB_VERSION}: make install..."
|
||||
make -s install
|
||||
|
||||
rm -rf /tmp/dep_zlib-${ZLIB_VERSION}
|
||||
fi
|
||||
|
||||
declare -a MUSL_REPOS=(
|
||||
https://git.musl-libc.org/git/musl
|
||||
https://gogs.librecmc.org/OWEALS/musl.git
|
||||
)
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
# Download musl git repo
|
||||
cd /tmp
|
||||
for repo in "${MUSL_REPOS[@]}"; do
|
||||
if git clone --depth 1 --revision "$MUSL_VERSION" "$repo" /tmp/musl; then
|
||||
break
|
||||
else
|
||||
rm -rf /tmp/musl
|
||||
fi
|
||||
done
|
||||
cd /tmp/musl
|
||||
|
||||
for patch in $GITHUB_WORKSPACE/.github/scripts/musl-*.patch; do
|
||||
echo "musl-${MUSL_VERSION}: applying $patch..."
|
||||
cat "$patch" | git apply
|
||||
done
|
||||
|
||||
echo "musl-${MUSL_VERSION}: configure..."
|
||||
./configure --disable-shared --prefix="$HOME"/staticdeps > /dev/null
|
||||
|
||||
echo "musl-${MUSL_VERSION}: make..."
|
||||
make -s -j4
|
||||
|
||||
echo "musl-${MUSL_VERSION}: make install..."
|
||||
make -s install
|
||||
|
||||
rm -rf "/tmp/dep_musl-${MUSL_VERSION}"
|
||||
|
||||
# native-image expects to find an executable at this path.
|
||||
ln -s ~/staticdeps/bin/musl-gcc ~/staticdeps/bin/x86_64-linux-musl-gcc
|
||||
fi
|
||||
|
||||
echo "${HOME}/staticdeps/bin" >> "$GITHUB_PATH"
|
||||
@@ -1,166 +0,0 @@
|
||||
>From 7813e9119eb5fe681b6750b8a033a0490bca0941 Mon Sep 17 00:00:00 2001
|
||||
From: Szabolcs Nagy <nsz@port70.net>
|
||||
Date: Thu, 23 Apr 2026 21:22:18 +0000
|
||||
Subject: [PATCH] regex: avoid int overflow in regcomp
|
||||
|
||||
regcomp has many int arith ops that may overflow. before tre_expand_ast
|
||||
int values are limited by 2x the input length n, e.g.:
|
||||
|
||||
input ERE int field max value
|
||||
aaaaaaaaaaaa... position n
|
||||
()()()()()()... submatch_id n/2+1
|
||||
()||||||||||... num_tags 2n-3
|
||||
|
||||
so overflow before expand requires large n (and a lot of memory). later
|
||||
some values can become big due to repetitions:
|
||||
|
||||
input ERE int field that overflows
|
||||
(((a{255}){255}){255}){255} position
|
||||
((a|b*){255,}){255,} num_transitions
|
||||
|
||||
num_transitions and memory use can be big without {k,} repetitions too:
|
||||
|
||||
input ERE what max value
|
||||
(a|a|a|a...|a)* num_transitions n^2/4
|
||||
(()|a|a|...|a)* sum tnfa tags > n^3/16 - n^2
|
||||
|
||||
so memory can run out quickly as n grows (with 31bit va space 1700 long
|
||||
input is enough even without {k,}) about half is tnfa and half is ast
|
||||
firstpos/lastpos data. but overflow can happen before allocations fail.
|
||||
|
||||
fix early overflow by limiting n. the stack usage is in [n,11n] without
|
||||
repetitions, usually 7n, so the stack limit got adjusted too. the limit
|
||||
is such that almost all inputs that worked before still work.
|
||||
|
||||
overflows during and after expand are fixed by explicit checks via a
|
||||
check_add helper and xcalloc instead of xmalloc.
|
||||
---
|
||||
src/regex/regcomp.c | 41 +++++++++++++++++++++++++++++++++++------
|
||||
1 file changed, 35 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/regex/regcomp.c b/src/regex/regcomp.c
|
||||
index b4b81968..a7115b12 100644
|
||||
--- a/src/regex/regcomp.c
|
||||
+++ b/src/regex/regcomp.c
|
||||
@@ -1680,6 +1680,12 @@ tre_add_tags(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *tree,
|
||||
AST to TNFA compilation routines.
|
||||
*/
|
||||
|
||||
+/* check if a+b overflows for a,b in [0,INT_MAX] */
|
||||
+static int check_add(unsigned a, unsigned b)
|
||||
+{
|
||||
+ return a + b > INT_MAX;
|
||||
+}
|
||||
+
|
||||
typedef enum {
|
||||
COPY_RECURSE,
|
||||
COPY_SET_RESULT_PTR
|
||||
@@ -1731,6 +1737,8 @@ tre_copy_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
|
||||
/* XXX - e.g. [ab] has only one position but two
|
||||
nodes, so we are creating holes in the state space
|
||||
here. Not fatal, just wastes memory. */
|
||||
+ if (check_add(pos, *pos_add))
|
||||
+ return REG_ESPACE;
|
||||
pos += *pos_add;
|
||||
num_copied++;
|
||||
}
|
||||
@@ -1826,6 +1834,8 @@ tre_copy_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
|
||||
break;
|
||||
}
|
||||
}
|
||||
+ if (check_add(*pos_add, num_copied))
|
||||
+ return REG_ESPACE;
|
||||
*pos_add += num_copied;
|
||||
return status;
|
||||
}
|
||||
@@ -1870,6 +1880,8 @@ tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
|
||||
tre_literal_t *lit= node->obj;
|
||||
if (!IS_SPECIAL(lit) || IS_BACKREF(lit))
|
||||
{
|
||||
+ if (check_add(lit->position, pos_add))
|
||||
+ return REG_ESPACE;
|
||||
lit->position += pos_add;
|
||||
if (lit->position > max_pos)
|
||||
max_pos = lit->position;
|
||||
@@ -1998,6 +2010,8 @@ tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
|
||||
}
|
||||
|
||||
iter_depth--;
|
||||
+ if (check_add(pos_add_total, pos_add - pos_add_last))
|
||||
+ return REG_ESPACE;
|
||||
pos_add_total += pos_add - pos_add_last;
|
||||
if (iter_depth == 0)
|
||||
pos_add = pos_add_total;
|
||||
@@ -2010,6 +2024,8 @@ tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (check_add(*position, pos_add_total))
|
||||
+ return REG_ESPACE;
|
||||
*position += pos_add_total;
|
||||
|
||||
/* `max_pos' should never be larger than `*position' if the above
|
||||
@@ -2711,9 +2727,19 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags)
|
||||
/* Parse context. */
|
||||
tre_parse_ctx_t parse_ctx;
|
||||
|
||||
+ /* Limits: before tre_expand_ast, int values like position, subid or
|
||||
+ * num_tags are bounded by 2x input length, used stack entries are
|
||||
+ * bounded by 16x input length. input length is checked upfront to
|
||||
+ * avoid overflows before expand. later, values that can grow big are
|
||||
+ * bounds checked via check_add and xcalloc. */
|
||||
+ const int input_limit = 1024000;
|
||||
+ const int stack_limit = 8*input_limit;
|
||||
+ if (strnlen(regex, input_limit) >= input_limit)
|
||||
+ return REG_ESPACE;
|
||||
+
|
||||
/* Allocate a stack used throughout the compilation process for various
|
||||
purposes. */
|
||||
- stack = tre_stack_new(512, 1024000, 128);
|
||||
+ stack = tre_stack_new(512, stack_limit, 128);
|
||||
if (!stack)
|
||||
return REG_ESPACE;
|
||||
/* Allocate a fast memory allocator. */
|
||||
@@ -2801,9 +2827,12 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags)
|
||||
for example "a*" or "ab*". Figure out a simple way to detect
|
||||
this possibility. */
|
||||
tmp_ast_l = tree;
|
||||
- tmp_ast_r = tre_ast_new_literal(mem, 0, 0, parse_ctx.position++);
|
||||
+ tmp_ast_r = tre_ast_new_literal(mem, 0, 0, parse_ctx.position);
|
||||
if (tmp_ast_r == NULL)
|
||||
ERROR_EXIT(REG_ESPACE);
|
||||
+ if (check_add(parse_ctx.position, 1))
|
||||
+ ERROR_EXIT(REG_ESPACE);
|
||||
+ parse_ctx.position++;
|
||||
|
||||
tree = tre_ast_new_catenation(mem, tmp_ast_l, tmp_ast_r);
|
||||
if (tree == NULL)
|
||||
@@ -2813,22 +2842,22 @@ regcomp(regex_t *restrict preg, const char *restrict regex, int cflags)
|
||||
if (errcode != REG_OK)
|
||||
ERROR_EXIT(errcode);
|
||||
|
||||
- counts = xmalloc(sizeof(int) * parse_ctx.position);
|
||||
+ counts = xcalloc(sizeof(int), parse_ctx.position);
|
||||
if (counts == NULL)
|
||||
ERROR_EXIT(REG_ESPACE);
|
||||
|
||||
- offs = xmalloc(sizeof(int) * parse_ctx.position);
|
||||
+ offs = xcalloc(sizeof(int), parse_ctx.position);
|
||||
if (offs == NULL)
|
||||
ERROR_EXIT(REG_ESPACE);
|
||||
|
||||
- for (i = 0; i < parse_ctx.position; i++)
|
||||
- counts[i] = 0;
|
||||
tre_ast_to_tnfa(tree, NULL, counts, NULL);
|
||||
|
||||
add = 0;
|
||||
for (i = 0; i < parse_ctx.position; i++)
|
||||
{
|
||||
offs[i] = add;
|
||||
+ if (check_add(add, counts[i] + 1))
|
||||
+ ERROR_EXIT(REG_ESPACE);
|
||||
add += counts[i] + 1;
|
||||
counts[i] = 0;
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
@@ -1,177 +0,0 @@
|
||||
>From 228da39e38c1cae13cbe637e771412c1984dba5d Mon Sep 17 00:00:00 2001
|
||||
From: Rich Felker <dalias@aerifal.cx>
|
||||
Date: Thu, 9 Apr 2026 22:51:30 -0400
|
||||
Subject: [PATCH 1/3] qsort: fix leonardo heap corruption from bug in
|
||||
doubleword ctz primitive
|
||||
|
||||
the pntz function, implementing a "count trailing zeros" variant for a
|
||||
bit vector consisting of two size_t words, erroneously returned zero
|
||||
rather than the number of bits in the low word when the first bit set
|
||||
was the low bit of the high word.
|
||||
|
||||
as a result, a loop in the trinkle function which should have a
|
||||
guaranteed small bound on the number of iterations, could run
|
||||
unboundedly, thereby overflowing a stack-based working-space array
|
||||
which was sized for the bound.
|
||||
|
||||
CVE-2026-40200 has been assigned for this issue.
|
||||
---
|
||||
src/stdlib/qsort.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
|
||||
index ab79dc6f..13219ab3 100644
|
||||
--- a/src/stdlib/qsort.c
|
||||
+++ b/src/stdlib/qsort.c
|
||||
@@ -34,11 +34,11 @@
|
||||
|
||||
typedef int (*cmpfun)(const void *, const void *, void *);
|
||||
|
||||
+/* returns index of first bit set, excluding the low bit assumed to always
|
||||
+ * be set, starting from low bit of p[0] up through high bit of p[1] */
|
||||
static inline int pntz(size_t p[2]) {
|
||||
- int r = ntz(p[0] - 1);
|
||||
- if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
|
||||
- return r;
|
||||
- }
|
||||
+ if (p[0] != 1) return ntz(p[0] - 1);
|
||||
+ if (p[1]) return 8*sizeof(size_t) + ntz(p[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
>From b3291b9a9f77f1f993d2b4f8c68a26cf09221ae7 Mon Sep 17 00:00:00 2001
|
||||
From: Rich Felker <dalias@aerifal.cx>
|
||||
Date: Thu, 9 Apr 2026 23:40:53 -0400
|
||||
Subject: [PATCH 2/3] qsort: hard-preclude oob array writes independent of any
|
||||
invariants
|
||||
|
||||
while the root cause of CVE-2026-40200 was a faulty ctz primitive, the
|
||||
fallout of the bug would have been limited to erroneous sorting or
|
||||
infinite loop if not for the stores to a stack-based array that
|
||||
depended on trusting invariants in order not to go out of bounds.
|
||||
|
||||
increase the size of the array to a power of two so that we can mask
|
||||
indices into it to force them into range. in the absence of any
|
||||
further bug, the masking is a no-op, but it does not have any
|
||||
measurable performance cost, and it makes spatial memory safety
|
||||
trivial to prove (and for readers not familiar with the algorithms to
|
||||
trust).
|
||||
---
|
||||
src/stdlib/qsort.c | 20 +++++++++++++-------
|
||||
1 file changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
|
||||
index 13219ab3..e4bce9f7 100644
|
||||
--- a/src/stdlib/qsort.c
|
||||
+++ b/src/stdlib/qsort.c
|
||||
@@ -89,10 +89,16 @@ static inline void shr(size_t p[2], int n)
|
||||
p[1] >>= n;
|
||||
}
|
||||
|
||||
+/* power-of-two length for working array so that we can mask indices and
|
||||
+ * not depend on any invariant of the algorithm for spatial memory safety.
|
||||
+ * the original size was just 14*sizeof(size_t)+1 */
|
||||
+#define AR_LEN (16 * sizeof(size_t))
|
||||
+#define AR_MASK (AR_LEN - 1)
|
||||
+
|
||||
static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int pshift, size_t lp[])
|
||||
{
|
||||
unsigned char *rt, *lf;
|
||||
- unsigned char *ar[14 * sizeof(size_t) + 1];
|
||||
+ unsigned char *ar[AR_LEN];
|
||||
int i = 1;
|
||||
|
||||
ar[0] = head;
|
||||
@@ -104,16 +110,16 @@ static void sift(unsigned char *head, size_t width, cmpfun cmp, void *arg, int p
|
||||
break;
|
||||
}
|
||||
if(cmp(lf, rt, arg) >= 0) {
|
||||
- ar[i++] = lf;
|
||||
+ ar[i++ & AR_MASK] = lf;
|
||||
head = lf;
|
||||
pshift -= 1;
|
||||
} else {
|
||||
- ar[i++] = rt;
|
||||
+ ar[i++ & AR_MASK] = rt;
|
||||
head = rt;
|
||||
pshift -= 2;
|
||||
}
|
||||
}
|
||||
- cycle(width, ar, i);
|
||||
+ cycle(width, ar, i & AR_MASK);
|
||||
}
|
||||
|
||||
static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, size_t pp[2], int pshift, int trusty, size_t lp[])
|
||||
@@ -121,7 +127,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
|
||||
unsigned char *stepson,
|
||||
*rt, *lf;
|
||||
size_t p[2];
|
||||
- unsigned char *ar[14 * sizeof(size_t) + 1];
|
||||
+ unsigned char *ar[AR_LEN];
|
||||
int i = 1;
|
||||
int trail;
|
||||
|
||||
@@ -142,7 +148,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
|
||||
}
|
||||
}
|
||||
|
||||
- ar[i++] = stepson;
|
||||
+ ar[i++ & AR_MASK] = stepson;
|
||||
head = stepson;
|
||||
trail = pntz(p);
|
||||
shr(p, trail);
|
||||
@@ -150,7 +156,7 @@ static void trinkle(unsigned char *head, size_t width, cmpfun cmp, void *arg, si
|
||||
trusty = 0;
|
||||
}
|
||||
if(!trusty) {
|
||||
- cycle(width, ar, i);
|
||||
+ cycle(width, ar, i & AR_MASK);
|
||||
sift(head, width, cmp, arg, pshift, lp);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
||||
>From 5122f9f3c99fee366167c5de98b31546312921ab Mon Sep 17 00:00:00 2001
|
||||
From: Luca Kellermann <mailto.luca.kellermann@gmail.com>
|
||||
Date: Fri, 10 Apr 2026 03:03:22 +0200
|
||||
Subject: [PATCH 3/3] qsort: fix shift UB in shl and shr
|
||||
|
||||
if shl() or shr() are called with n==8*sizeof(size_t), n is adjusted
|
||||
to 0. the shift by (sizeof(size_t) * 8 - n) that then follows will
|
||||
consequently shift by the width of size_t, which is UB and in practice
|
||||
produces an incorrect result.
|
||||
|
||||
return early in this case. the bitvector p was already shifted by the
|
||||
required amount.
|
||||
---
|
||||
src/stdlib/qsort.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/src/stdlib/qsort.c b/src/stdlib/qsort.c
|
||||
index e4bce9f7..28607450 100644
|
||||
--- a/src/stdlib/qsort.c
|
||||
+++ b/src/stdlib/qsort.c
|
||||
@@ -71,6 +71,7 @@ static inline void shl(size_t p[2], int n)
|
||||
n -= 8 * sizeof(size_t);
|
||||
p[1] = p[0];
|
||||
p[0] = 0;
|
||||
+ if (!n) return;
|
||||
}
|
||||
p[1] <<= n;
|
||||
p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
|
||||
@@ -83,6 +84,7 @@ static inline void shr(size_t p[2], int n)
|
||||
n -= 8 * sizeof(size_t);
|
||||
p[0] = p[1];
|
||||
p[1] = 0;
|
||||
+ if (!n) return;
|
||||
}
|
||||
p[0] >>= n;
|
||||
p[0] |= p[1] << (sizeof(size_t) * 8 - n);
|
||||
--
|
||||
2.21.0
|
||||
@@ -1,319 +0,0 @@
|
||||
>From 67219f0130ec7c876ac0b299046460fad31caabf Mon Sep 17 00:00:00 2001
|
||||
From: Rich Felker <dalias@aerifal.cx>
|
||||
Date: Mon, 30 Mar 2026 16:00:50 -0400
|
||||
Subject: [PATCH] fix pathological slowness & incorrect mappings in iconv
|
||||
gb18030 decoder
|
||||
|
||||
in order to implement the "UTF" aspect of gb18030 (ability to
|
||||
represent arbitrary unicode characters not present in the 2-byte
|
||||
mapping), we have to apply the index obtained from the encoded 4-byte
|
||||
sequence into the set of unmapped characters. this was done by
|
||||
scanning repeatedly over the table of mapped characters and counting
|
||||
off mapped characters below a running index by which to adjust the
|
||||
running index by on each iteration. this iterative process eventually
|
||||
leaves us with the value of the Nth unmapped character replacing the
|
||||
index, but depending on which particular character that is, the number
|
||||
of iterations needed to find it can be in the tens of thousands, and
|
||||
each iteration traverses the whole 126x190 table in the inner loop.
|
||||
this can lead to run times exceeding an entire second per character on
|
||||
moderate-speed machines.
|
||||
|
||||
on top of that, the transformation logic produced wrong results for
|
||||
BMP characters above the the surrogate range, as a result of not
|
||||
correctly accounting for it being excluded, and for characters outside
|
||||
the BMP, as a result of a misunderstanding of how gb18030 encodes
|
||||
them.
|
||||
|
||||
this patch replaces the unmapped character lookup with a single linear
|
||||
search of a list of unmapped ranges. there are only 206 such ranges,
|
||||
and these are permanently assigned and unchangeable as a consequence
|
||||
of the character encoding having to be stable, so a simple array of
|
||||
16-bit start/length values for each range consumes only 824 bytes, a
|
||||
very reasonable size cost here.
|
||||
|
||||
this new table accounts for the previously-incorrect surrogate
|
||||
handling, and non-BMP characters are handled correctly by a single
|
||||
offset, without the need for any unmapped-range search.
|
||||
|
||||
there are still a small number of mappings that are incorrect due to
|
||||
late changes made in the definition of gb18030, swapping PUA
|
||||
codepoints with proper Unicode characters. correcting these requires a
|
||||
postprocessing step that will be added later.
|
||||
---
|
||||
src/locale/gb18030utf.h | 206 ++++++++++++++++++++++++++++++++++++++++
|
||||
src/locale/iconv.c | 33 +++++--
|
||||
2 files changed, 230 insertions(+), 9 deletions(-)
|
||||
create mode 100644 src/locale/gb18030utf.h
|
||||
|
||||
diff --git a/src/locale/gb18030utf.h b/src/locale/gb18030utf.h
|
||||
new file mode 100644
|
||||
index 00000000..322a2440
|
||||
--- /dev/null
|
||||
+++ b/src/locale/gb18030utf.h
|
||||
@@ -0,0 +1,206 @@
|
||||
+{ 0x80, 36 },
|
||||
+{ 0xa5, 2 },
|
||||
+{ 0xa9, 7 },
|
||||
+{ 0xb2, 5 },
|
||||
+{ 0xb8, 31 },
|
||||
+{ 0xd8, 8 },
|
||||
+{ 0xe2, 6 },
|
||||
+{ 0xeb, 1 },
|
||||
+{ 0xee, 4 },
|
||||
+{ 0xf4, 3 },
|
||||
+{ 0xf8, 1 },
|
||||
+{ 0xfb, 1 },
|
||||
+{ 0xfd, 4 },
|
||||
+{ 0x102, 17 },
|
||||
+{ 0x114, 7 },
|
||||
+{ 0x11c, 15 },
|
||||
+{ 0x12c, 24 },
|
||||
+{ 0x145, 3 },
|
||||
+{ 0x149, 4 },
|
||||
+{ 0x14e, 29 },
|
||||
+{ 0x16c, 98 },
|
||||
+{ 0x1cf, 1 },
|
||||
+{ 0x1d1, 1 },
|
||||
+{ 0x1d3, 1 },
|
||||
+{ 0x1d5, 1 },
|
||||
+{ 0x1d7, 1 },
|
||||
+{ 0x1d9, 1 },
|
||||
+{ 0x1db, 1 },
|
||||
+{ 0x1dd, 28 },
|
||||
+{ 0x1fa, 87 },
|
||||
+{ 0x252, 15 },
|
||||
+{ 0x262, 101 },
|
||||
+{ 0x2c8, 1 },
|
||||
+{ 0x2cc, 13 },
|
||||
+{ 0x2da, 183 },
|
||||
+{ 0x3a2, 1 },
|
||||
+{ 0x3aa, 7 },
|
||||
+{ 0x3c2, 1 },
|
||||
+{ 0x3ca, 55 },
|
||||
+{ 0x402, 14 },
|
||||
+{ 0x450, 1 },
|
||||
+{ 0x452, 7102 },
|
||||
+{ 0x2011, 2 },
|
||||
+{ 0x2017, 1 },
|
||||
+{ 0x201a, 2 },
|
||||
+{ 0x201e, 7 },
|
||||
+{ 0x2027, 9 },
|
||||
+{ 0x2031, 1 },
|
||||
+{ 0x2034, 1 },
|
||||
+{ 0x2036, 5 },
|
||||
+{ 0x203c, 112 },
|
||||
+{ 0x20ad, 86 },
|
||||
+{ 0x2104, 1 },
|
||||
+{ 0x2106, 3 },
|
||||
+{ 0x210a, 12 },
|
||||
+{ 0x2117, 10 },
|
||||
+{ 0x2122, 62 },
|
||||
+{ 0x216c, 4 },
|
||||
+{ 0x217a, 22 },
|
||||
+{ 0x2194, 2 },
|
||||
+{ 0x219a, 110 },
|
||||
+{ 0x2209, 6 },
|
||||
+{ 0x2210, 1 },
|
||||
+{ 0x2212, 3 },
|
||||
+{ 0x2216, 4 },
|
||||
+{ 0x221b, 2 },
|
||||
+{ 0x2221, 2 },
|
||||
+{ 0x2224, 1 },
|
||||
+{ 0x2226, 1 },
|
||||
+{ 0x222c, 2 },
|
||||
+{ 0x222f, 5 },
|
||||
+{ 0x2238, 5 },
|
||||
+{ 0x223e, 10 },
|
||||
+{ 0x2249, 3 },
|
||||
+{ 0x224d, 5 },
|
||||
+{ 0x2253, 13 },
|
||||
+{ 0x2262, 2 },
|
||||
+{ 0x2268, 6 },
|
||||
+{ 0x2270, 37 },
|
||||
+{ 0x2296, 3 },
|
||||
+{ 0x229a, 11 },
|
||||
+{ 0x22a6, 25 },
|
||||
+{ 0x22c0, 82 },
|
||||
+{ 0x2313, 333 },
|
||||
+{ 0x246a, 10 },
|
||||
+{ 0x249c, 100 },
|
||||
+{ 0x254c, 4 },
|
||||
+{ 0x2574, 13 },
|
||||
+{ 0x2590, 3 },
|
||||
+{ 0x2596, 10 },
|
||||
+{ 0x25a2, 16 },
|
||||
+{ 0x25b4, 8 },
|
||||
+{ 0x25be, 8 },
|
||||
+{ 0x25c8, 3 },
|
||||
+{ 0x25cc, 2 },
|
||||
+{ 0x25d0, 18 },
|
||||
+{ 0x25e6, 31 },
|
||||
+{ 0x2607, 2 },
|
||||
+{ 0x260a, 54 },
|
||||
+{ 0x2641, 1 },
|
||||
+{ 0x2643, 2110 },
|
||||
+{ 0x2e82, 2 },
|
||||
+{ 0x2e85, 3 },
|
||||
+{ 0x2e89, 2 },
|
||||
+{ 0x2e8d, 10 },
|
||||
+{ 0x2e98, 15 },
|
||||
+{ 0x2ea8, 2 },
|
||||
+{ 0x2eab, 3 },
|
||||
+{ 0x2eaf, 4 },
|
||||
+{ 0x2eb4, 2 },
|
||||
+{ 0x2eb8, 3 },
|
||||
+{ 0x2ebc, 14 },
|
||||
+{ 0x2ecb, 293 },
|
||||
+{ 0x2ffc, 4 },
|
||||
+{ 0x3004, 1 },
|
||||
+{ 0x3018, 5 },
|
||||
+{ 0x301f, 2 },
|
||||
+{ 0x302a, 20 },
|
||||
+{ 0x303f, 2 },
|
||||
+{ 0x3094, 7 },
|
||||
+{ 0x309f, 2 },
|
||||
+{ 0x30f7, 5 },
|
||||
+{ 0x30ff, 6 },
|
||||
+{ 0x312a, 246 },
|
||||
+{ 0x322a, 7 },
|
||||
+{ 0x3232, 113 },
|
||||
+{ 0x32a4, 234 },
|
||||
+{ 0x3390, 12 },
|
||||
+{ 0x339f, 2 },
|
||||
+{ 0x33a2, 34 },
|
||||
+{ 0x33c5, 9 },
|
||||
+{ 0x33cf, 2 },
|
||||
+{ 0x33d3, 2 },
|
||||
+{ 0x33d6, 113 },
|
||||
+{ 0x3448, 43 },
|
||||
+{ 0x3474, 298 },
|
||||
+{ 0x359f, 111 },
|
||||
+{ 0x360f, 11 },
|
||||
+{ 0x361b, 765 },
|
||||
+{ 0x3919, 85 },
|
||||
+{ 0x396f, 96 },
|
||||
+{ 0x39d1, 14 },
|
||||
+{ 0x39e0, 147 },
|
||||
+{ 0x3a74, 218 },
|
||||
+{ 0x3b4f, 287 },
|
||||
+{ 0x3c6f, 113 },
|
||||
+{ 0x3ce1, 885 },
|
||||
+{ 0x4057, 264 },
|
||||
+{ 0x4160, 471 },
|
||||
+{ 0x4338, 116 },
|
||||
+{ 0x43ad, 4 },
|
||||
+{ 0x43b2, 43 },
|
||||
+{ 0x43de, 248 },
|
||||
+{ 0x44d7, 373 },
|
||||
+{ 0x464d, 20 },
|
||||
+{ 0x4662, 193 },
|
||||
+{ 0x4724, 5 },
|
||||
+{ 0x472a, 82 },
|
||||
+{ 0x477d, 16 },
|
||||
+{ 0x478e, 441 },
|
||||
+{ 0x4948, 50 },
|
||||
+{ 0x497b, 2 },
|
||||
+{ 0x497e, 4 },
|
||||
+{ 0x4984, 1 },
|
||||
+{ 0x4987, 20 },
|
||||
+{ 0x499c, 3 },
|
||||
+{ 0x49a0, 22 },
|
||||
+{ 0x49b8, 703 },
|
||||
+{ 0x4c78, 39 },
|
||||
+{ 0x4ca4, 111 },
|
||||
+{ 0x4d1a, 148 },
|
||||
+{ 0x4daf, 81 },
|
||||
+{ 0x9fa6, 14426 },
|
||||
+{ 0xe76c, 1 },
|
||||
+{ 0xe7c8, 1 },
|
||||
+{ 0xe7e7, 13 },
|
||||
+{ 0xe815, 1 },
|
||||
+{ 0xe819, 5 },
|
||||
+{ 0xe81f, 7 },
|
||||
+{ 0xe827, 4 },
|
||||
+{ 0xe82d, 4 },
|
||||
+{ 0xe833, 8 },
|
||||
+{ 0xe83c, 7 },
|
||||
+{ 0xe844, 16 },
|
||||
+{ 0xe856, 14 },
|
||||
+{ 0xe865, 4295 },
|
||||
+{ 0xf92d, 76 },
|
||||
+{ 0xf97a, 27 },
|
||||
+{ 0xf996, 81 },
|
||||
+{ 0xf9e8, 9 },
|
||||
+{ 0xf9f2, 26 },
|
||||
+{ 0xfa10, 1 },
|
||||
+{ 0xfa12, 1 },
|
||||
+{ 0xfa15, 3 },
|
||||
+{ 0xfa19, 6 },
|
||||
+{ 0xfa22, 1 },
|
||||
+{ 0xfa25, 2 },
|
||||
+{ 0xfa2a, 1030 },
|
||||
+{ 0xfe32, 1 },
|
||||
+{ 0xfe45, 4 },
|
||||
+{ 0xfe53, 1 },
|
||||
+{ 0xfe58, 1 },
|
||||
+{ 0xfe67, 1 },
|
||||
+{ 0xfe6c, 149 },
|
||||
+{ 0xff5f, 129 },
|
||||
+{ 0xffe6, 26 },
|
||||
diff --git a/src/locale/iconv.c b/src/locale/iconv.c
|
||||
index 52178950..4151411d 100644
|
||||
--- a/src/locale/iconv.c
|
||||
+++ b/src/locale/iconv.c
|
||||
@@ -74,6 +74,10 @@ static const unsigned short gb18030[126][190] = {
|
||||
#include "gb18030.h"
|
||||
};
|
||||
|
||||
+static const unsigned short gb18030utf[][2] = {
|
||||
+#include "gb18030utf.h"
|
||||
+};
|
||||
+
|
||||
static const unsigned short big5[89][157] = {
|
||||
#include "big5.h"
|
||||
};
|
||||
@@ -224,6 +228,8 @@ static unsigned uni_to_jis(unsigned c)
|
||||
}
|
||||
}
|
||||
|
||||
+#define countof(a) (sizeof (a) / sizeof *(a))
|
||||
+
|
||||
size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
|
||||
{
|
||||
size_t x=0;
|
||||
@@ -430,15 +436,24 @@ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restri
|
||||
d = *((unsigned char *)*in + 3);
|
||||
if (d-'0'>9) goto ilseq;
|
||||
c += d-'0';
|
||||
- c += 128;
|
||||
- for (d=0; d<=c; ) {
|
||||
- k = 0;
|
||||
- for (int i=0; i<126; i++)
|
||||
- for (int j=0; j<190; j++)
|
||||
- if (gb18030[i][j]-d <= c-d)
|
||||
- k++;
|
||||
- d = c+1;
|
||||
- c += k;
|
||||
+ /* Starting at 90 30 81 30 (189000), mapping is
|
||||
+ * linear without gaps, to U+10000 and up. */
|
||||
+ if (c >= 189000) {
|
||||
+ c -= 189000;
|
||||
+ c += 0x10000;
|
||||
+ if (c >= 0x110000) goto ilseq;
|
||||
+ break;
|
||||
+ }
|
||||
+ /* Otherwise we must process an index into set
|
||||
+ * of characters unmapped by 2-byte table. */
|
||||
+ for (int i=0; ; i++) {
|
||||
+ if (i==countof(gb18030utf))
|
||||
+ goto ilseq;
|
||||
+ if (c<gb18030utf[i][1]) {
|
||||
+ c += gb18030utf[i][0];
|
||||
+ break;
|
||||
+ }
|
||||
+ c -= gb18030utf[i][1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
@@ -1,42 +0,0 @@
|
||||
#file: noinspection MandatoryParamsAbsent,UndefinedAction
|
||||
# This is a fake workflow that never runs.
|
||||
# It's used to pin actions to specific git SHAs when generating actual workflows.
|
||||
# It also gets updated by dependabot (see .github/dependabot.yml).
|
||||
# Generated from Workflow.pkl. DO NOT EDIT.
|
||||
name: __lockfile__
|
||||
'on':
|
||||
push:
|
||||
branches-ignore:
|
||||
- '**'
|
||||
tags-ignore:
|
||||
- '**'
|
||||
permissions: {}
|
||||
jobs:
|
||||
locks:
|
||||
if: 'false'
|
||||
runs-on: nothing
|
||||
steps:
|
||||
- name: EnricoMi/publish-unit-test-result-action@v2
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
- name: actions/checkout@v6
|
||||
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
- name: actions/create-github-app-token@v2
|
||||
uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
|
||||
- name: actions/download-artifact@v6
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
|
||||
- name: actions/setup-java@v5
|
||||
uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5
|
||||
- name: actions/upload-artifact@v5
|
||||
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
|
||||
- name: dawidd6/action-download-artifact@v11
|
||||
uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
|
||||
- name: github/codeql-action/analyze@v4
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
- name: github/codeql-action/init@v4
|
||||
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
- name: gradle/actions/dependency-submission@v6
|
||||
uses: gradle/actions/dependency-submission@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6
|
||||
- name: gradle/actions/setup-gradle@v5
|
||||
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
|
||||
- name: ilammy/msvc-dev-cmd@v1
|
||||
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,62 +0,0 @@
|
||||
# Generated from Workflow.pkl. DO NOT EDIT.
|
||||
'on':
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
- cron: 29 17 * * 4
|
||||
jobs:
|
||||
analyze-actions:
|
||||
name: Analyze (actions)
|
||||
permissions:
|
||||
security-events: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
with:
|
||||
languages: actions
|
||||
build-mode: none
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
with:
|
||||
category: /language:actions
|
||||
analyze-java-kotlin:
|
||||
name: Analyze (java-kotlin)
|
||||
permissions:
|
||||
security-events: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
with:
|
||||
languages: java-kotlin
|
||||
build-mode: autobuild
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
with:
|
||||
category: /language:java-kotlin
|
||||
analyze-javascript-typescript:
|
||||
name: Analyze (javascript-typescript)
|
||||
permissions:
|
||||
security-events: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
with:
|
||||
languages: javascript-typescript
|
||||
build-mode: none
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
||||
with:
|
||||
category: /language:javascript-typescript
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,34 +0,0 @@
|
||||
# Generated from Workflow.pkl. DO NOT EDIT.
|
||||
name: PR Test Reports
|
||||
'on':
|
||||
workflow_run:
|
||||
types:
|
||||
- completed
|
||||
workflows:
|
||||
- Pull Request
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
test-results:
|
||||
name: Test Results
|
||||
if: github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure'
|
||||
permissions:
|
||||
actions: read
|
||||
checks: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11
|
||||
with:
|
||||
path: artifacts
|
||||
name: test-results-.*
|
||||
name_is_regexp: true
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
- name: Publish test results
|
||||
uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2
|
||||
with:
|
||||
commit: ${{ github.event.workflow_run.head_sha }}
|
||||
comment_mode: 'off'
|
||||
files: artifacts/**/*.xml
|
||||
event_file: artifacts/test-results-event-file/event.json
|
||||
event_name: ${{ github.event.workflow_run.event }}
|
||||
+3
-7
@@ -5,7 +5,6 @@
|
||||
.gradle/
|
||||
build/
|
||||
generated/
|
||||
testgenerated/
|
||||
|
||||
# IntelliJ
|
||||
.idea/
|
||||
@@ -15,10 +14,7 @@ testgenerated/
|
||||
!.idea/runConfigurations/
|
||||
!.idea/scopes/
|
||||
!.idea/vcs.xml
|
||||
.intellijPlatform/
|
||||
|
||||
.vscode/
|
||||
|
||||
.pkl-lsp/
|
||||
|
||||
.kotlin/
|
||||
# :pkl-core:makeIntelliJAntlrPluginHappy
|
||||
gen/
|
||||
PklLexer.tokens
|
||||
Generated
+10
-1
@@ -10,6 +10,16 @@
|
||||
<option name="INSERT_INNER_CLASS_IMPORTS" value="true" />
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
|
||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
|
||||
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||
<value />
|
||||
</option>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
|
||||
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
|
||||
@@ -53,7 +63,6 @@
|
||||
</option>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="" withSubpackages="true" static="false" module="true" />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
|
||||
-34
@@ -12,35 +12,6 @@
|
||||
<option name="REPORT_FIELDS" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="ClassCanBeRecord" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ClassEscapesItsScope" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="CustomRegExpInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="myConfigurations">
|
||||
<list>
|
||||
<RegExpInspectionConfiguration>
|
||||
<option name="name" value="PklCliDirectProjectEvaluatorSettingsAccess" />
|
||||
<option name="suppressId" value="PklCliDirectProjectEvaluatorSettingsAccess" />
|
||||
<option name="uuid" value="dd497f47-d38f-3fab-9ed7-eabe699620c8" />
|
||||
<option name="patterns">
|
||||
<list>
|
||||
<InspectionPattern>
|
||||
<option name="regExp" value="project\?\.evaluatorSettings" />
|
||||
<option name="_fileType" value="Kotlin" />
|
||||
<option name="searchContext" value="ANY" />
|
||||
<option name="replacement" value="evaluatorSettings" />
|
||||
</InspectionPattern>
|
||||
<InspectionPattern>
|
||||
<option name="regExp" value="project\?\.resolvedEvaluatorSettings" />
|
||||
<option name="_fileType" value="Kotlin" />
|
||||
<option name="searchContext" value="ANY" />
|
||||
<option name="replacement" value="evaluatorSettings" />
|
||||
</InspectionPattern>
|
||||
</list>
|
||||
</option>
|
||||
</RegExpInspectionConfiguration>
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="FieldAccessNotGuarded" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="FieldMayBeFinal" enabled="true" level="INFORMATION" enabled_by_default="true">
|
||||
<scope name="AllExceptTruffleAst" level="WARNING" enabled="true" />
|
||||
</inspection_tool>
|
||||
@@ -97,15 +68,10 @@
|
||||
<option name="REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SameParameterValue" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ShellCheck" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<shellcheck_settings value="SC2129" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="StringToUpperWithoutLocale" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" />
|
||||
<inspection_tool class="dd497f47-d38f-3fab-9ed7-eabe699620c8" enabled="true" level="ERROR" enabled_by_default="true" editorAttributes="ERRORS_ATTRIBUTES" />
|
||||
</profile>
|
||||
</component>
|
||||
+1
-1
@@ -1 +1 @@
|
||||
21
|
||||
17.0
|
||||
@@ -1,2 +0,0 @@
|
||||
Jen Basch <421772+HT154@users.noreply.github.com>
|
||||
Jen Basch <jbasch@apple.com>
|
||||
@@ -1,24 +0,0 @@
|
||||
# This file is only used to configure CLion with proper include paths.
|
||||
# Pkl builds everything through Gradle, not CMake.
|
||||
cmake_minimum_required(VERSION 4.2)
|
||||
project(pkl C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
file(GLOB NATIVE_LIB_INCLUDE_DIRS CONFIGURE_DEPENDS
|
||||
libpkl/build/native-libs/*/include)
|
||||
file(GLOB NATIVE_IMAGE_BUILD_DIRS CONFIGURE_DEPENDS
|
||||
libpkl/build/tmp/native-image-build/*)
|
||||
|
||||
include_directories(${NATIVE_LIB_INCLUDE_DIRS})
|
||||
include_directories(${NATIVE_IMAGE_BUILD_DIRS})
|
||||
include_directories(libpkl/src/main/c/include)
|
||||
|
||||
file(GLOB_RECURSE GENERATED_HEADER_FILES CONFIGURE_DEPENDS
|
||||
libpkl/build/tmp/native-libs/*/*.h)
|
||||
|
||||
add_executable(pkl
|
||||
${GENERATED_HEADER_FILES}
|
||||
libpkl/src/main/c/include/pkl.h
|
||||
libpkl/src/main/c/pkl.c
|
||||
libpkl/src/nativeTest/c/test_pkl.c)
|
||||
@@ -0,0 +1,77 @@
|
||||
## Code of Conduct
|
||||
|
||||
### Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our
|
||||
project and our community a harassment-free experience for everyone,
|
||||
regardless of age, body size, disability, ethnicity, sex
|
||||
characteristics, gender identity and expression, level of experience,
|
||||
education, socio-economic status, nationality, personal appearance,
|
||||
race, religion, or sexual identity and orientation.
|
||||
|
||||
### Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual
|
||||
attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political
|
||||
attacks
|
||||
* Public or private harassment
|
||||
* Publishing others’ private information, such as a physical or
|
||||
electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
### Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of
|
||||
acceptable behavior and are expected to take appropriate and fair
|
||||
corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit,
|
||||
or reject comments, commits, code, wiki edits, issues, and other
|
||||
contributions that are not aligned to this Code of Conduct, or to ban
|
||||
temporarily or permanently any contributor for other behaviors that they
|
||||
deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
### Scope
|
||||
|
||||
This Code of Conduct applies within all project spaces, and it also
|
||||
applies when an individual is representing the project or its community
|
||||
in public spaces. Examples of representing a project or community
|
||||
include using an official project e-mail address, posting via an
|
||||
official social media account, or acting as an appointed representative
|
||||
at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
### Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may
|
||||
be reported by contacting the open source team at
|
||||
opensource-conduct@group.apple.com. All complaints will be reviewed and
|
||||
investigated and will result in a response that is deemed necessary and
|
||||
appropriate to the circumstances. The project team is obligated to
|
||||
maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted
|
||||
separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in
|
||||
good faith may face temporary or permanent repercussions as determined
|
||||
by other members of the project’s leadership.
|
||||
|
||||
### Attribution
|
||||
|
||||
This Code of Conduct is adapted from the
|
||||
[Contributor Covenant](https://www.contributor-covenant.org), version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
+25
-45
@@ -2,22 +2,19 @@
|
||||
:uri-gng: https://gng.dsun.org
|
||||
:uri-jenv: https://www.jenv.be
|
||||
:uri-intellij: https://www.jetbrains.com/idea/download/
|
||||
:uri-native-prerequisites-linux: https://www.graalvm.org/latest/getting-started/linux/#prerequisites-for-native-image-on-linux
|
||||
:uri-native-prerequisites-windows: https://www.graalvm.org/latest/getting-started/windows/#prerequisites-for-native-image-on-windows
|
||||
:uri-jdk: https://adoptopenjdk.net/releases.html?variant=openjdk17
|
||||
|
||||
== Setup
|
||||
|
||||
. (mandatory) Install a JDK (JDK 21+ required).
|
||||
. (recommended) Install {uri-intellij}[IntelliJ IDEA] +
|
||||
. (mandatory) Install {uri-jdk}[OpenJDK 17] or higher
|
||||
. (recommended) Install {uri-intellij}[IntelliJ IDEA 2023.x] +
|
||||
To import the project into IntelliJ, go to File->Open and select the project's root directory.
|
||||
If the project is opened but not imported, look for a popup in the lower right corner
|
||||
and click its "Import Gradle Project" link.
|
||||
. (recommended) Install {uri-gng}[gng] +
|
||||
_gng_ enables you to run Gradle commands with `gw` (instead of `./gradlew`) from any subdirectory.
|
||||
. (recommended) Set up Git ignore-revs +
|
||||
`git config blame.ignoreRevsFile .git-blame-ignore-revs`
|
||||
_gng_ enables to run Gradle commands with `gw` (instead of `./gradlew`) from any subdirectory.
|
||||
. (recommended) Install {uri-jenv}[jenv] and plugins +
|
||||
_jenv_ uses specific JDK versions in certain subdirectories. _Pkl_ comes with a `.java-version` file specifying JDK 21. +
|
||||
_jenv_ use specific JDK versions in certain subdirectories. _Pkl_ comes with a `.java-version` file specifying JDK 17. +
|
||||
Enable _jenv_ plugins for better handling by `gradle`:
|
||||
+
|
||||
[source,shell]
|
||||
@@ -25,34 +22,22 @@ Enable _jenv_ plugins for better handling by `gradle`:
|
||||
jenv enable-plugin gradle
|
||||
jenv enable-plugin export
|
||||
----
|
||||
. (optional) If you've named the original apple/pkl git repository something other than `origin`, set env var `PKL_ORIGINAL_REMOTE_NAME` to that name in your `.bashrc`, `.zshrc`, `config.fish` or however you manage your local environment.
|
||||
+
|
||||
This will allow spotless to pick the correct starting branch when formatting source code files.
|
||||
Otherwise, you might see that _every_ file has its copyright year updated.
|
||||
|
||||
=== Additional Linux Setup
|
||||
. (optional) To build the native executable (`./gradlew buildNative`),
|
||||
install {uri-native-prerequisites-linux}[Prerequisites For Native Image on Linux].
|
||||
|
||||
=== Additional Windows Setup
|
||||
. (optional) Go to `System->For developers` and enable `Developer Mode`.
|
||||
Otherwise, some tests may fail due to insufficient file system privileges.
|
||||
. (optional) To build the native executable (`./gradlew buildNative`),
|
||||
install {uri-native-prerequisites-windows}[Prerequisites For Native Image on Windows].
|
||||
|
||||
== Common Build Commands
|
||||
|
||||
[source,shell]
|
||||
----
|
||||
gw clean
|
||||
gw test # run all tests except native executable tests
|
||||
gw spotlessApply # fix code formatting
|
||||
gw build # build everything except native executables
|
||||
gw pkl-cli:testNative # run native executable tests
|
||||
gw pkl-cli:buildNative # build native executable for current platform
|
||||
gw test # run all tests except native executable tests
|
||||
gw testNative # run native executable tests
|
||||
gw spotlessApply # fix code formatting
|
||||
gw build # build everything except native executables
|
||||
gw buildNative # build macOS executable on macOS,
|
||||
# Linux and Alpine executables on Linux
|
||||
# (Alpine executable is only built if ~/staticdeps/bin/musl-gcc exists)
|
||||
|
||||
pkl-cli/build/executable/jpkl # run Java executable
|
||||
pkl-cli/build/executable/pkl-macos-aarch64 # run Mac executable
|
||||
pkl-cli/build/executable/pkl-macos-amd64 # run Mac executable
|
||||
pkl-cli/build/executable/pkl-linux-amd64 # run Linux executable
|
||||
pkl-cli/build/executable/pkl-alpine-linux-amd64 # run Alpine Linux executable
|
||||
pkl-cli/build/executable/pkl-windows-amd64.exe # run Windows executable
|
||||
@@ -73,12 +58,16 @@ gw wrapper --gradle-version [version] --gradle-distribution-sha256-sum [sha]
|
||||
|
||||
. (optional) Update _gradle/libs.version.toml_
|
||||
based on version information from https://search.maven.org, https://plugins.gradle.org, and GitHub repos
|
||||
. Run `gw updateDependencyLocks`
|
||||
. Validate changes with `gw build buildNative`
|
||||
. Review and commit the updated dependency lock files
|
||||
|
||||
== Code Generation
|
||||
|
||||
* Truffle code generation is performed by Truffle's annotation processor, which runs as part of task `:pkl-core:compileJava`
|
||||
** Output dir is `generated/truffle/`
|
||||
* ANTLR code generation is performed by task `:pkl-core:generateGrammarSource`
|
||||
** Output dir is `generated/antlr/`
|
||||
|
||||
== Remote JVM Debugging
|
||||
|
||||
@@ -87,35 +76,26 @@ This will listen on port 5005.
|
||||
|
||||
Example: `./gradlew test -Djvmdebug=true`
|
||||
|
||||
== Snippet Test Plugin
|
||||
|
||||
There is an IntelliJ plugin meant for development on the Pkl project itself located in https://github.com/apple/pkl-project-commons[pkl-project-commons].
|
||||
|
||||
See https://github.com/apple/pkl-project-commons?tab=readme-ov-file#internal-intellij-plugin[its readme] for instructions on how to set it up.
|
||||
|
||||
== Working on libpkl
|
||||
|
||||
libpkl is a native library written in C, and is best written in CLion, or VSCode.
|
||||
|
||||
IntelliJ has limited support for editing C sources.
|
||||
|
||||
There is a CMakeLists.txt file whose only job is to configure CLion with proper include paths.
|
||||
|
||||
== Resources
|
||||
For automated build setup examples see our https://github.com/apple/pkl/blob/main/.circleci/[CircleCI] jobs like our https://github.com/apple/pkl/blob/main/.circleci/jobs/BuildNativeJob.pkl[BuildNativeJob.pkl], where we build Pkl automatically.
|
||||
|
||||
For automated build setup examples see our https://github.com/apple/pkl/blob/main/.github/[GitHub Actions] jobs like our https://github.com/apple/pkl/blob/main/.github/jobs/BuildNativeJob.pkl[BuildNativeJob.pkl], where we build Pkl automatically.
|
||||
=== ANTLR
|
||||
|
||||
* https://github.com/antlr/antlr4/blob/main/doc/index.md[Documentation]
|
||||
* https://groups.google.com/forum/#!forum/antlr-discussion[Forums]
|
||||
* https://github.com/mobileink/lab.clj.antlr/tree/main/doc[Some third-party docs]
|
||||
|
||||
=== Truffle
|
||||
|
||||
* http://ssw.jku.at/Research/Projects/JVM/Truffle.html[Homepage]
|
||||
* https://github.com/graalvm/truffle[GitHub]
|
||||
* http://lafo.ssw.uni-linz.ac.at/javadoc/truffle/latest/[Javadoc]
|
||||
* https://mail.openjdk.org/pipermail/graal-dev/[Mailing List]
|
||||
* http://mail.openjdk.java.net/pipermail/graal-dev/[Mailing List]
|
||||
* https://medium.com/@octskyward/graal-truffle-134d8f28fb69#.2db370y2g[Graal & Truffle (Article)]
|
||||
* https://comserv.cs.ut.ee/home/files/Pool_ComputerScience_2016.pdf?study=ATILoputoo&reference=6319668E7151D556131810BC3F4A627D7FEF5F3B[Truffle Overview (see chapter 1)]
|
||||
* https://gist.github.com/smarr/d1f8f2101b5cc8e14e12[Truffle: Languages and Material]
|
||||
* https://github.com/smarr/truffle-notes[Truffle Notes]
|
||||
* https://www.graalvm.org/latest/graalvm-as-a-platform/language-implementation-framework/[Truffle Language Implementation Framework]
|
||||
* https://wiki.openjdk.java.net/display/Graal/Truffle+FAQ+and+Guidelines[Truffle FAQ]
|
||||
|
||||
=== Other Config Languages
|
||||
|
||||
|
||||
@@ -8,5 +8,4 @@ See link:CONTRIBUTING.adoc[] for general contribution guidelines.
|
||||
|
||||
* https://github.com/bioball[Daniel Chao]
|
||||
* https://github.com/stackoverflow[Islon Scherer]
|
||||
* https://github.com/HT154[Jen Basch]
|
||||
* https://github.com/holzensp[Philip Hölzenspies]
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright © 2024-2026 Apple Inc. and the Pkl project authors
|
||||
Copyright © 2024 Apple Inc. and the Pkl project authors
|
||||
|
||||
|
||||
Portions of this software were originally based on 'SnakeYAML' developed by Andrey Somov.
|
||||
|
||||
+2
-81
@@ -12,7 +12,7 @@
|
||||
:uri-installation: https://pkl-lang.org/main/current/pkl-cli/index.html#installation
|
||||
:uri-lang-reference: https://pkl-lang.org/main/current/language-reference/index.html
|
||||
:uri-ci-artifacts: https://s01.oss.sonatype.org/content/groups/public/org/pkl-lang/
|
||||
:uri-ci-pipeline: https://github.com/apple/pkl/actions
|
||||
:uri-ci-pipeline: https://app.circleci.com/pipelines/github/apple/pkl
|
||||
|
||||
A configuration as code language with rich validation and tooling.
|
||||
|
||||
@@ -37,86 +37,7 @@ We'd love to hear from you!
|
||||
* Create an {uri-github-issue}[issue]
|
||||
* Ask a question on {uri-github-discussions}[GitHub Discussions]
|
||||
|
||||
== Development
|
||||
|
||||
image:https://github.com/apple/pkl/actions/workflows/main.yml/badge.svg?style=svg["Build (main)", link="https://github.com/apple/pkl/actions/workflows/main.yml"]
|
||||
|
||||
== Development image:https://circleci.com/gh/apple/pkl.svg?style=svg["Apple", link="https://app.circleci.com/pipelines/github/apple/pkl"]
|
||||
* link:CONTRIBUTING.adoc[] for tips on pull requests and filing issues
|
||||
* link:DEVELOPMENT.adoc[] for build instructions
|
||||
* {uri-ci-artifacts}[Sonatype Repository] for the artifacts/binaries built by our {uri-ci-pipeline}[CI pipelines] (and those of our other tools and packages repositories).
|
||||
|
||||
== Pkl GitHub Repositories
|
||||
|
||||
[%autowidth]
|
||||
|===
|
||||
|Name |Description
|
||||
|
||||
|`apple/pkl`
|
||||
|A configuration as code language with rich validation and tooling.
|
||||
|
||||
|https://github.com/apple/pkl-evolution[`apple/pkl-evolution`]
|
||||
|Suggested Pkl Improvements, Changes, or Enhancements (SPICEs)
|
||||
|
||||
|https://github.com/apple/pkl-go[`apple/pkl-go`]
|
||||
|Pkl bindings for the Go programming language
|
||||
|
||||
|https://github.com/apple/pkl-go-examples[`apple/pkl-go-examples`]
|
||||
|Examples for using Pkl within Go applications
|
||||
|
||||
|https://github.com/apple/highlightjs-pkl[`apple/highlightjs-pkl`]
|
||||
|Highlight.js syntax highlighting for Pkl
|
||||
|
||||
|https://github.com/apple/pkl-intellij[`apple/pkl-intellij`]
|
||||
|JetBrains editor plugins providing Pkl language support
|
||||
|
||||
|https://github.com/apple/pkl-jvm-examples[`apple/pkl-jvm-examples`]
|
||||
|Examples for using Pkl within JVM applications
|
||||
|
||||
|https://github.com/apple/pkl-k8s[`apple/pkl-k8s`]
|
||||
|Templates for using Pkl with Kubernetes
|
||||
|
||||
|https://github.com/apple/pkl-k8s-examples[`apple/pkl-k8s-examples`]
|
||||
|Examples for using Pkl with Kubernetes
|
||||
|
||||
|https://github.com/apple/pkl-lang.org[`apple/pkl-lang.org`]
|
||||
|The pkl-lang.org website
|
||||
|
||||
|https://github.com/apple/pkl-lsp[`apple/pkl-lsp`]
|
||||
|Language server for Pkl, implementing the server-side of the Language Server Protocol
|
||||
|
||||
|https://github.com/apple/pkl-neovim[`apple/pkl-neovim`]
|
||||
|Pkl language support for Neovim
|
||||
|
||||
|https://github.com/apple/pkl-package-docs[`apple/pkl-package-docs`]
|
||||
|Documentation for Pkl packages
|
||||
|
||||
|https://github.com/apple/pkl-pantry[`apple/pkl-pantry`]
|
||||
|Shared Pkl packages
|
||||
|
||||
|https://github.com/apple/pkl-project-commons[`apple/pkl-project-commons`]
|
||||
|Utility libraries for Pkl
|
||||
|
||||
|https://github.com/apple/pkl-readers[`apple/pkl-readers`]
|
||||
|Shared Pkl https://pkl-lang.org/main/current/language-reference/index.html#external-readers[external reader] tools
|
||||
|
||||
|https://github.com/apple/pkl-spring[`apple/pkl-spring`]
|
||||
|Spring Boot extension for configuring Boot apps with Pkl
|
||||
|
||||
|https://github.com/apple/pkl-swift[`apple/pkl-swift`]
|
||||
|Pkl bindings for the Swift programming language
|
||||
|
||||
|https://github.com/apple/pkl-swift-examples[`apple/pkl-swift-examples`]
|
||||
|Examples for using Pkl within Swift applications
|
||||
|
||||
|https://github.com/apple/pkl-vscode[`apple/pkl-vscode`]
|
||||
|Pkl language support for VS Code
|
||||
|
||||
|https://github.com/apple/pkl.tmbundle[`apple/pkl.tmbundle`]
|
||||
|TextMate bundle for Pkl
|
||||
|
||||
|https://github.com/apple/tree-sitter-pkl[`apple/tree-sitter-pkl`]
|
||||
|Tree-sitter parser for Pkl
|
||||
|
||||
|https://github.com/apple/rules_pkl[`apple/rules_pkl`]
|
||||
|Bazel build rules for Pkl
|
||||
|===
|
||||
+32
-119
@@ -26,7 +26,18 @@ Copyright © 2017 Square, Inc.
|
||||
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 http://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.
|
||||
|
||||
4) GeantyRef (https://github.com/leangen/geantyref)
|
||||
4) ANTLR 4 Runtime (Optimized) (http://tunnelvisionlabs.com)
|
||||
POM License: The BSD License - http://www.antlr.org/license.html
|
||||
|
||||
Copyright (c) 2012 Terence Parr and Sam Harwell
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
5) GeantyRef (https://github.com/leangen/geantyref)
|
||||
Manifest license URL: https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
@@ -36,7 +47,7 @@ Copyright © 2017 Kaqqao
|
||||
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 http://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.
|
||||
|
||||
5) commonmark-java core
|
||||
6) commonmark-java core
|
||||
POM License: The 2-Clause BSD License - https://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
Embedded license:
|
||||
@@ -67,7 +78,7 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
6) commonmark-java extension for tables
|
||||
7) commonmark-java extension for tables
|
||||
POM License: The 2-Clause BSD License - https://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
Embedded license:
|
||||
@@ -98,7 +109,7 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
7) jansi (http://fusesource.com/)
|
||||
8) jansi (http://fusesource.com/)
|
||||
Manifest license URL: https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
@@ -108,13 +119,13 @@ Copyright © Fusesource 2023
|
||||
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 http://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.
|
||||
|
||||
8) Graal Sdk (https://github.com/oracle/graal)
|
||||
9) Graal Sdk (https://github.com/oracle/graal)
|
||||
POM License: Universal Permissive License, Version 1.0 - http://opensource.org/licenses/UPL
|
||||
|
||||
9) Truffle API (http://openjdk.java.net/projects/graal)
|
||||
10) Truffle API (http://openjdk.java.net/projects/graal)
|
||||
POM License: Universal Permissive License, Version 1.0 - http://opensource.org/licenses/UPL
|
||||
|
||||
10) IntelliJ IDEA Annotations (http://www.jetbrains.org)
|
||||
11) IntelliJ IDEA Annotations (http://www.jetbrains.org)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -122,7 +133,7 @@ Copyright © Jetbrains 2023
|
||||
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 http://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.
|
||||
|
||||
11) kotlin-reflect (https://kotlinlang.org/)
|
||||
12) kotlin-reflect (https://kotlinlang.org/)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -130,7 +141,7 @@ Copyright © Wuseal 2018
|
||||
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 http://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.
|
||||
|
||||
12) kotlin-stdlib (https://kotlinlang.org/)
|
||||
13) kotlin-stdlib (https://kotlinlang.org/)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -138,7 +149,7 @@ Copyright © 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contribu
|
||||
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 http://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.
|
||||
|
||||
13) kotlin-stdlib-common (https://kotlinlang.org/)
|
||||
14) kotlin-stdlib-common (https://kotlinlang.org/)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -146,7 +157,7 @@ Copyright © 2023 Kotlin Team
|
||||
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 http://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.
|
||||
|
||||
14) kotlin-stdlib-jdk7 (https://kotlinlang.org/)
|
||||
15) kotlin-stdlib-jdk7 (https://kotlinlang.org/)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -154,7 +165,7 @@ Copyright © 2023 Kotlin Team
|
||||
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 http://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.
|
||||
|
||||
15) kotlin-stdlib-jdk8 (https://kotlinlang.org/)
|
||||
16) kotlin-stdlib-jdk8 (https://kotlinlang.org/)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -162,7 +173,7 @@ Copyright © 2023 Kotlin Team
|
||||
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 http://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.
|
||||
|
||||
16) kotlinx.html (https://github.com/Kotlin/kotlinx.html)
|
||||
17) kotlinx.html (https://github.com/Kotlin/kotlinx.html)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -170,7 +181,7 @@ Copyright © 2017 Yole
|
||||
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 http://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.
|
||||
|
||||
17) kotlinx-serialization-core (https://github.com/Kotlin/kotlinx.serialization)
|
||||
18) kotlinx-serialization-core (https://github.com/Kotlin/kotlinx.serialization)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -178,7 +189,7 @@ The Apache License
|
||||
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 http://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.
|
||||
|
||||
18) kotlinx-serialization-json (https://github.com/Kotlin/kotlinx.serialization)
|
||||
19) kotlinx-serialization-json (https://github.com/Kotlin/kotlinx.serialization)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -186,7 +197,7 @@ The Apache License
|
||||
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 http://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.
|
||||
|
||||
19) JLine Reader
|
||||
20) JLine Reader
|
||||
Manifest license URL: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
POM License: The 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause
|
||||
@@ -205,7 +216,7 @@ software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
20) JLine Terminal
|
||||
21) JLine Terminal
|
||||
Manifest license URL: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
POM License: The 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause
|
||||
@@ -224,7 +235,7 @@ software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
21) JLine JANSI Terminal
|
||||
22) JLine JANSI Terminal
|
||||
Manifest license URL: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
POM License: The 3-Clause BSD License - https://opensource.org/licenses/BSD-3-Clause
|
||||
@@ -243,7 +254,7 @@ software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
22) msgpack-core (https://msgpack.org/)
|
||||
23) msgpack-core (https://msgpack.org/)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -251,7 +262,7 @@ Copyright © 2016 Sadayuki Furuhashi, Muga Nishizawa, Taro L. Saito, Mitsunori K
|
||||
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 http://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.
|
||||
|
||||
23) Paguro (https://github.com/GlenKPeterson/Paguro)
|
||||
24) Paguro (https://github.com/GlenKPeterson/Paguro)
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
The Apache License
|
||||
@@ -353,7 +364,7 @@ Everyone is permitted to copy and distribute copies of this Agreement, but in or
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
|
||||
|
||||
24) SnakeYAML Engine (http://www.snakeyaml.org)
|
||||
25) SnakeYAML Engine (http://www.snakeyaml.org)
|
||||
Manifest license URL: https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
@@ -363,101 +374,3 @@ Copyright © 2008-2010 Andrey Somov
|
||||
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 http://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.
|
||||
|
||||
25) JSpecify (https://jspecify.dev)
|
||||
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Copyright 2022 The JSpecify Authors.
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
||||
|
||||
26) mordant
|
||||
POM License: Apache License, Version 2.0 - https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Copyright 2018 AJ Alt
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
||||
|
||||
27) colormath
|
||||
License URL: https://github.com/ajalt/colormath/blob/master/LICENSE
|
||||
|
||||
Copyright 2021 AJ Alt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
28) protobuf-java
|
||||
License URL: https://github.com/protocolbuffers/protobuf/blob/main/LICENSE
|
||||
|
||||
Copyright 2008 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Code generated by the Protocol Buffer compiler is owned by the owner
|
||||
of the input file used when generating it. This code is not
|
||||
standalone and requires a support library to be linked with it. This
|
||||
support library is itself covered by the above license.
|
||||
|
||||
29) pprof
|
||||
License URL: https://github.com/google/pprof/blob/main/LICENSE
|
||||
|
||||
Copyright 2016 Google Inc. 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
|
||||
|
||||
http://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.
|
||||
+19
-40
@@ -1,49 +1,31 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
plugins {
|
||||
id("pklAllProjects")
|
||||
id("pklJavaLibrary")
|
||||
pklAllProjects
|
||||
pklJavaLibrary
|
||||
pklGraalVm
|
||||
id("me.champeau.jmh")
|
||||
}
|
||||
|
||||
val truffle: Configuration = configurations.create("truffle")
|
||||
val graal: Configuration = configurations.create("graal")
|
||||
val truffle: Configuration by configurations.creating
|
||||
val graal: Configuration by configurations.creating
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
dependencies {
|
||||
jmh(projects.pklCore)
|
||||
jmh(projects.pklCommonsTest)
|
||||
jmh(projects.pklParser)
|
||||
// necessary because antlr4-runtime is declared as implementation dependency in pkl-core.gradle
|
||||
jmh(libs.antlrRuntime)
|
||||
truffle(libs.truffleApi)
|
||||
graal(libs.graalCompiler)
|
||||
}
|
||||
|
||||
jmh {
|
||||
// includes = listOf("ParserBenchmark")
|
||||
//include = ["fib_class_java"]
|
||||
//include = ["fib_class_constrained1", "fib_class_constrained2"]
|
||||
jmhVersion.set(libs.versions.jmh)
|
||||
// jvmArgsAppend = "-Dgraal.TruffleCompilationExceptionsAreFatal=true " +
|
||||
// "-Dgraal.Dump=Truffle,TruffleTree -Dgraal.TraceTruffleCompilation=true " +
|
||||
// "-Dgraal.TruffleFunctionInlining=false"
|
||||
val graalVm =
|
||||
when (buildInfo.arch) {
|
||||
Target.Arch.AARCH64 -> buildInfo.graalVmAarch64
|
||||
Target.Arch.AMD64 -> buildInfo.graalVmAmd64
|
||||
}
|
||||
jvm.set("${graalVm.baseDir}/bin/java")
|
||||
// see:
|
||||
// https://docs.oracle.com/en/graalvm/enterprise/20/docs/graalvm-as-a-platform/implement-language/#disable-class-path-separation
|
||||
jvm.set("${buildInfo.graalVmAmd64.baseDir}/bin/java")
|
||||
// see: https://docs.oracle.com/en/graalvm/enterprise/20/docs/graalvm-as-a-platform/implement-language/#disable-class-path-separation
|
||||
jvmArgs.set(
|
||||
listOf(
|
||||
// one JVM arg per list element doesn't work, but the following does
|
||||
@@ -51,19 +33,16 @@ jmh {
|
||||
)
|
||||
)
|
||||
includeTests.set(false)
|
||||
// threads = Runtime.runtime.availableProcessors() / 2 + 1
|
||||
// synchronizeIterations = false
|
||||
//threads = Runtime.runtime.availableProcessors() / 2 + 1
|
||||
//synchronizeIterations = false
|
||||
}
|
||||
|
||||
tasks.named("jmh") {
|
||||
if (buildInfo.arch == Target.Arch.AARCH64) {
|
||||
dependsOn(":installGraalVmAarch64")
|
||||
} else if (buildInfo.arch == Target.Arch.AMD64) {
|
||||
dependsOn(":installGraalVmAmd64")
|
||||
}
|
||||
dependsOn(":installGraalVmAmd64")
|
||||
}
|
||||
|
||||
// Prevent this error which occurs when building in IntelliJ:
|
||||
// "Entry org/pkl/core/fib_class_typed.pkl is a duplicate but no duplicate handling strategy has
|
||||
// been set."
|
||||
tasks.processJmhResources { duplicatesStrategy = DuplicatesStrategy.EXCLUDE }
|
||||
// "Entry org/pkl/core/fib_class_typed.pkl is a duplicate but no duplicate handling strategy has been set."
|
||||
tasks.processJmhResources {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# This is a Gradle generated file for dependency locking.
|
||||
# Manual edits can break the build and are not advised.
|
||||
# This file is expected to be part of source control.
|
||||
com.tunnelvisionlabs:antlr4-runtime:4.9.0=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
net.bytebuddy:byte-buddy:1.14.16=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
net.java.dev.jna:jna:5.6.0=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
|
||||
net.sf.jopt-simple:jopt-simple:5.0.4=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.apache.commons:commons-math3:3.6.1=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeOnlyDependenciesMetadata
|
||||
org.assertj:assertj-core:3.26.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.graalvm.compiler:compiler:23.0.2=graal
|
||||
org.graalvm.sdk:graal-sdk:23.0.2=graal,jmh,jmhRuntimeClasspath,truffle
|
||||
org.graalvm.truffle:truffle-api:23.0.2=graal,jmh,jmhRuntimeClasspath,truffle
|
||||
org.jetbrains.intellij.deps:trove4j:1.0.20200330=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-daemon-embeddable:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:1.7.10=kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-reflect:1.7.10=kotlinCompilerClasspath,kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-script-runtime:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath
|
||||
org.jetbrains.kotlin:kotlin-scripting-common:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-scripting-jvm:1.7.10=kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest
|
||||
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.jetbrains:annotations:13.0=kotlinCompilerClasspath,kotlinCompilerPluginClasspathJmh,kotlinCompilerPluginClasspathMain,kotlinCompilerPluginClasspathTest,kotlinKlibCommonizerClasspath,testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.junit.jupiter:junit-jupiter-api:5.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
|
||||
org.junit.jupiter:junit-jupiter-engine:5.10.2=testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
|
||||
org.junit.jupiter:junit-jupiter-params:5.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath
|
||||
org.junit.platform:junit-platform-commons:1.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
|
||||
org.junit.platform:junit-platform-engine:1.10.2=testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
|
||||
org.junit:junit-bom:5.10.2=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
|
||||
org.openjdk.jmh:jmh-core:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.openjdk.jmh:jmh-generator-asm:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.openjdk.jmh:jmh-generator-bytecode:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.openjdk.jmh:jmh-generator-reflection:1.37=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testImplementationDependenciesMetadata,testRuntimeClasspath,testRuntimeOnlyDependenciesMetadata
|
||||
org.organicdesign:Paguro:3.10.3=jmh,jmhRuntimeClasspath
|
||||
org.ow2.asm:asm:9.0=jmh,jmhCompileClasspath,jmhImplementationDependenciesMetadata,jmhRuntimeClasspath
|
||||
org.snakeyaml:snakeyaml-engine:2.5=jmh,jmhRuntimeClasspath
|
||||
empty=annotationProcessor,apiDependenciesMetadata,archives,compile,compileClasspath,compileOnly,compileOnlyDependenciesMetadata,default,implementationDependenciesMetadata,intransitiveDependenciesMetadata,jmhAnnotationProcessor,jmhApiDependenciesMetadata,jmhCompile,jmhCompileOnly,jmhCompileOnlyDependenciesMetadata,jmhIntransitiveDependenciesMetadata,jmhKotlinScriptDef,jmhKotlinScriptDefExtensions,jmhRuntime,jmhRuntimeOnlyDependenciesMetadata,kotlinCompilerPluginClasspath,kotlinNativeCompilerPluginClasspath,kotlinScriptDef,kotlinScriptDefExtensions,runtime,runtimeClasspath,runtimeOnlyDependenciesMetadata,sourcesJar,testAnnotationProcessor,testApiDependenciesMetadata,testCompile,testCompileOnly,testCompileOnlyDependenciesMetadata,testIntransitiveDependenciesMetadata,testKotlinScriptDef,testKotlinScriptDefExtensions,testRuntime
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/**
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
/**
|
||||
* Copyright © 2024 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.
|
||||
@@ -23,7 +23,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.util.TempFile;
|
||||
import org.openjdk.jmh.util.TempFileManager;
|
||||
import org.pkl.core.evaluatorSettings.TraceMode;
|
||||
import org.pkl.core.http.HttpClient;
|
||||
import org.pkl.core.module.ModuleKeyFactories;
|
||||
import org.pkl.core.repl.ReplRequest;
|
||||
@@ -51,9 +50,7 @@ public class ListSort {
|
||||
null,
|
||||
null,
|
||||
IoUtils.getCurrentWorkingDir(),
|
||||
StackFrameTransformers.defaultTransformer,
|
||||
false,
|
||||
TraceMode.COMPACT);
|
||||
StackFrameTransformers.defaultTransformer);
|
||||
private static final List<Object> list = new ArrayList<>(100000);
|
||||
|
||||
static {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
/**
|
||||
* Copyright © 2024 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.
|
||||
@@ -15,17 +15,8 @@
|
||||
*/
|
||||
package org.pkl.core.parser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.pkl.commons.test.FileTestUtils;
|
||||
import org.pkl.commons.test.FileTestUtilsKt;
|
||||
import org.pkl.core.Release;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.parser.Parser;
|
||||
import org.pkl.parser.ParserError;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Warmup(iterations = 5, time = 2)
|
||||
@@ -33,33 +24,37 @@ import org.pkl.parser.ParserError;
|
||||
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||
@Fork(1)
|
||||
public class ParserBenchmark {
|
||||
// One-time execution of this code took ~10s until moving rule alternative
|
||||
// for parenthesized expression after alternative for anonymous function.
|
||||
@Benchmark
|
||||
public void parseStdlib() {
|
||||
for (var stdlibModule : Release.current().standardLibrary().modules()) {
|
||||
try {
|
||||
var moduleSource =
|
||||
IoUtils.readClassPathResourceAsString(
|
||||
getClass(), "/org/pkl/core/stdlib/%s.pkl".formatted(stdlibModule.substring(4)));
|
||||
new Parser().parseModule(moduleSource);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void parseSnippetTests() {
|
||||
var snippetTestDir =
|
||||
FileTestUtils.getRootProjectDir()
|
||||
.resolve("pkl-core/src/test/files/LanguageSnippetTests/input");
|
||||
for (var snippet : FileTestUtilsKt.listFilesRecursively(snippetTestDir)) {
|
||||
try {
|
||||
var moduleSource = Files.readString(snippet);
|
||||
new Parser().parseModule(moduleSource);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} catch (ParserError ignore) {
|
||||
}
|
||||
}
|
||||
public void run() {
|
||||
new Parser()
|
||||
.parseModule(
|
||||
"""
|
||||
a1 {
|
||||
a2 {
|
||||
a3 {
|
||||
a4 {
|
||||
a5 {
|
||||
a6 {
|
||||
a7 {
|
||||
a8 {
|
||||
a9 {
|
||||
a10 {
|
||||
a11 {
|
||||
a12 {
|
||||
a13 = map(map(map((x) -> 1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}""");
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
`jvm-toolchains`
|
||||
}
|
||||
|
||||
/**
|
||||
* To avoid the provisioning of multiple JDKs and other build issues, keep this value in sync with
|
||||
* the JVM toolchain versions in `BuildInfo.kt` and `gradle-daemon-jvm.properties`.
|
||||
*/
|
||||
val toolchainVersion = 25
|
||||
|
||||
dependencies {
|
||||
implementation(libs.downloadTaskPlugin)
|
||||
implementation(libs.errorPronePlugin)
|
||||
implementation(libs.nullawayPlugin)
|
||||
implementation(libs.spotlessPlugin)
|
||||
implementation(libs.kotlinPlugin) { exclude(module = "kotlin-android-extensions") }
|
||||
implementation(libs.shadowPlugin)
|
||||
|
||||
// fix from the Gradle team: makes version catalog symbols available in build scripts
|
||||
// see here for more: https://github.com/gradle/gradle/issues/15383
|
||||
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(toolchainVersion)
|
||||
vendor = JvmVendorSpec.ADOPTIUM
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach { options.release = toolchainVersion }
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(toolchainVersion)
|
||||
compilerOptions {
|
||||
jvmTarget = JvmTarget.fromTarget(toolchainVersion.toString())
|
||||
freeCompilerArgs.add("-Xjdk-release=$toolchainVersion")
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
rootProject.name = "build-logic"
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" }
|
||||
|
||||
// makes ~/.gradle/init.gradle unnecessary and ~/.gradle/gradle.properties optional
|
||||
dependencyResolutionManagement {
|
||||
// use same version catalog as main build
|
||||
versionCatalogs { register("libs") { from(files("../gradle/libs.versions.toml")) } }
|
||||
|
||||
repositories {
|
||||
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
@@ -1,466 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
import Target.Arch
|
||||
import Target.OS
|
||||
import java.io.File
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.VersionCatalog
|
||||
import org.gradle.api.artifacts.VersionCatalogsExtension
|
||||
import org.gradle.api.attributes.Category
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.internal.extensions.stdlib.capitalized
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
import org.gradle.jvm.toolchain.*
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
import org.gradle.process.CommandLineArgumentProvider
|
||||
|
||||
/**
|
||||
* JVM bytecode target; this is pinned at a reasonable version, because downstream JVM projects
|
||||
* which consume Pkl will need a minimum bytecode level at or above this one.
|
||||
*
|
||||
* Kotlin and Java need matching bytecode targets, so this is expressed as a build setting and
|
||||
* constant default. To override, pass `-DpklJdkToolchain=X` to the Gradle command line, where X is
|
||||
* a major Java version.
|
||||
*/
|
||||
const val PKL_JVM_TARGET_DEFAULT_MAXIMUM = 17
|
||||
|
||||
/**
|
||||
* The Pkl build requires JDK 25+; otherwise, NullAway will not work correctly.
|
||||
*
|
||||
* This is a build-time requirement, not a runtime requirement. To avoid the provisioning of
|
||||
* multiple JDKs and other build issues, keep this value in sync with the JVM toolchain versions in
|
||||
* `build-logic/build.gradle.kts` and `gradle-daemon-jvm.properties`.
|
||||
*/
|
||||
const val PKL_JDK_VERSION_MIN = 25
|
||||
|
||||
/**
|
||||
* The JDK minimum is set to match the bytecode minimum, to guarantee that fat JARs work against the
|
||||
* earliest supported bytecode target.
|
||||
*/
|
||||
const val PKL_TEST_JDK_MINIMUM = PKL_JVM_TARGET_DEFAULT_MAXIMUM
|
||||
|
||||
/**
|
||||
* Maximum JDK version which Pkl is tested with; this should be bumped when new JDK releases are
|
||||
* issued.
|
||||
*/
|
||||
const val PKL_TEST_JDK_MAXIMUM = 26
|
||||
|
||||
/**
|
||||
* If `true`, all JDK releases between [PKL_TEST_JDK_MINIMUM] and [PKL_TEST_JDK_MAXIMUM] are tested.
|
||||
* If `false`, only LTS releases within that range are tested. To override, pass
|
||||
* `-DpklTestAllJdks=true` on the Gradle command line.
|
||||
*/
|
||||
const val PKL_TEST_ALL_JDKS = false
|
||||
|
||||
// `buildInfo` in main build scripts
|
||||
// `project.extensions.getByType<BuildInfo>()` in precompiled script plugins
|
||||
open class BuildInfo(private val project: Project) {
|
||||
inner class GraalVm(
|
||||
val osName: String,
|
||||
val arch: String,
|
||||
val version: String,
|
||||
val graalJdkVersion: String,
|
||||
) {
|
||||
val homeDir: String by lazy {
|
||||
System.getenv("GRAALVM_HOME") ?: "${System.getProperty("user.home")}/.graalvm"
|
||||
}
|
||||
val graalVmJdkVersion: String by lazy { libs.findVersion("graalVmJdkVersion").get().toString() }
|
||||
val graalVmInnovation: String by lazy { libs.findVersion("graalVmInnovation").get().toString() }
|
||||
|
||||
val baseName: String by lazy {
|
||||
"graalvm-community-jdk-${graalVmJdkVersion}_${osName}-${arch}_bin"
|
||||
}
|
||||
|
||||
val graalMajorVersion: String = graalJdkVersion.split(".").first()
|
||||
|
||||
val downloadUrl: String by lazy {
|
||||
val ext = if (os.isWindows) "zip" else "tar.gz"
|
||||
val platformArch = if (arch == "amd64") "x64" else arch
|
||||
"https://github.com/graalvm/graalvm-ce-builds/releases/download/graal-$version/graalvm-community-jdk-${graalMajorVersion}i${graalVmInnovation}-${graalJdkVersion}_${osName}-${platformArch}_bin.$ext"
|
||||
}
|
||||
|
||||
val downloadFile: File by lazy {
|
||||
val extension = if (os.isWindows) "zip" else "tar.gz"
|
||||
File(homeDir, "${baseName}.$extension")
|
||||
}
|
||||
|
||||
val installDir: File by lazy { File(homeDir, baseName) }
|
||||
|
||||
val baseDir: String by lazy {
|
||||
if (os.isMacOS) "$installDir/Contents/Home" else installDir.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/** The target machine to build, defaulting to the host system machine. */
|
||||
val targetMachine: Target by lazy { Target.from(os = os, arch = targetArch, musl = musl) }
|
||||
|
||||
/** The target architecture to build, defaulting to the system architecture. */
|
||||
val targetArch: Arch by lazy { System.getProperty("pkl.targetArch")?.let(Arch::fromName) ?: arch }
|
||||
|
||||
/** Tells if this is a cross-arch build (e.g. targeting amd64 when on an aarch64 machine). */
|
||||
val isCrossArch by lazy { arch != targetArch }
|
||||
|
||||
/** Tells if cross-arch builds are supported on this machine. */
|
||||
val isCrossArchSupported by lazy { os.isMacOS }
|
||||
|
||||
/** Whether to build native executables using the musl toolchain or not. */
|
||||
val musl: Boolean by lazy { java.lang.Boolean.getBoolean("pkl.musl") }
|
||||
|
||||
val arch: Arch by lazy {
|
||||
when (val arch = System.getProperty("os.arch")) {
|
||||
"x86_64",
|
||||
"amd64" -> Arch.AMD64
|
||||
"aarch64" -> Arch.AARCH64
|
||||
else -> throw GradleException("Cannot build Pkl on arch: $arch")
|
||||
}
|
||||
}
|
||||
|
||||
val graalVmAarch64: GraalVm by lazy { createGraalVm("aarch64") }
|
||||
|
||||
val graalVmAmd64: GraalVm by lazy { createGraalVm("x64") }
|
||||
|
||||
private fun createGraalVm(arch: String): GraalVm {
|
||||
val osName =
|
||||
when {
|
||||
os.isMacOS -> "macos"
|
||||
os.isLinux -> "linux"
|
||||
os.isWindows -> "windows"
|
||||
else -> throw RuntimeException("Unsupported OS for GraalVM: ${os.name}")
|
||||
}
|
||||
val version = libs.findVersion("graalVm").get().toString()
|
||||
val graalJdkVersion = libs.findVersion("graalVmJdkVersion").get().toString()
|
||||
return GraalVm(osName, arch, version, graalJdkVersion)
|
||||
}
|
||||
|
||||
val isCiBuild: Boolean by lazy { System.getenv("CI") != null }
|
||||
|
||||
val isReleaseBuild: Boolean by lazy { java.lang.Boolean.getBoolean("releaseBuild") }
|
||||
|
||||
val isNativeArch: Boolean by lazy { java.lang.Boolean.getBoolean("nativeArch") }
|
||||
|
||||
val jvmTarget: Int by lazy {
|
||||
System.getProperty("pklJvmTarget")?.toInt() ?: PKL_JVM_TARGET_DEFAULT_MAXIMUM
|
||||
}
|
||||
|
||||
// JPMS exports for Truffle; needed on some versions of Java, and transitively within some JARs.
|
||||
private val jpmsExports =
|
||||
arrayOf(
|
||||
"org.graalvm.truffle/com.oracle.truffle.api.exception=ALL-UNNAMED",
|
||||
"org.graalvm.truffle/com.oracle.truffle.api=ALL-UNNAMED",
|
||||
"org.graalvm.truffle/com.oracle.truffle.api.nodes=ALL-UNNAMED",
|
||||
"org.graalvm.truffle/com.oracle.truffle.api.source=ALL-UNNAMED",
|
||||
)
|
||||
|
||||
// Extra JPMS modules forced onto the module path via `--add-modules` in some cases.
|
||||
private val jpmsAddModules = arrayOf("jdk.unsupported")
|
||||
|
||||
// Formats `jpmsExports` for use in JAR manifest attributes.
|
||||
val jpmsExportsForJarManifest: String by lazy {
|
||||
jpmsExports.joinToString(" ") { it.substringBefore("=") }
|
||||
}
|
||||
|
||||
// Formats `jpmsExports` for use on the command line with `--add-exports`.
|
||||
val jpmsExportsForAddExportsFlags: Collection<String> by lazy {
|
||||
jpmsExports.map { "--add-exports=$it" }
|
||||
}
|
||||
|
||||
// Formats `jpmsAddModules` for use on the command line with `--add-modules`.
|
||||
val jpmsAddModulesFlags: Collection<String> by lazy { jpmsAddModules.map { "--add-modules=$it" } }
|
||||
|
||||
// JVM properties to set during testing.
|
||||
val testProperties =
|
||||
mapOf<String, Any>(
|
||||
// @TODO: this should be removed once pkl supports JPMS as a true Java Module.
|
||||
"polyglotimpl.DisableClassPathIsolation" to true
|
||||
)
|
||||
|
||||
val jdkVendor: JvmVendorSpec = JvmVendorSpec.ADOPTIUM
|
||||
|
||||
val jdkToolchainVersion: JavaLanguageVersion by lazy {
|
||||
JavaLanguageVersion.of(System.getProperty("pklJdkToolchain")?.toInt() ?: PKL_JDK_VERSION_MIN)
|
||||
}
|
||||
|
||||
val jdkTestFloor: JavaLanguageVersion by lazy { JavaLanguageVersion.of(PKL_TEST_JDK_MINIMUM) }
|
||||
|
||||
val jdkTestCeiling: JavaLanguageVersion by lazy { JavaLanguageVersion.of(PKL_TEST_JDK_MAXIMUM) }
|
||||
|
||||
val testAllJdks: Boolean by lazy {
|
||||
// By default, Pkl is tested against LTS JDK releases within the bounds of `PKL_TEST_JDK_TARGET`
|
||||
// and `PKL_TEST_JDK_MAXIMUM`. To test against the full suite of JDK versions, past and present,
|
||||
// set `-DpklTestAllJdks=true` on the Gradle command line. This results in non-LTS releases, old
|
||||
// releases, and "experimental releases" (newer than the toolchain version) being included in
|
||||
// the default `check` suite.
|
||||
System.getProperty("pklTestAllJdks")?.toBoolean() ?: PKL_TEST_ALL_JDKS
|
||||
}
|
||||
|
||||
val testExperimentalJdks: Boolean by lazy {
|
||||
System.getProperty("pklTestFutureJdks")?.toBoolean() ?: false
|
||||
}
|
||||
|
||||
val testJdkVendors: Sequence<JvmVendorSpec> by lazy {
|
||||
// By default, only Adoptium is tested during multi-JDK testing. Flip `-DpklTestAllVendors=true`
|
||||
// to additionally test against GraalVM and Oracle.
|
||||
when (System.getProperty("pklTestAllVendors")?.toBoolean()) {
|
||||
true -> sequenceOf(JvmVendorSpec.ADOPTIUM, JvmVendorSpec.GRAAL_VM, JvmVendorSpec.ORACLE)
|
||||
else -> sequenceOf(JvmVendorSpec.ADOPTIUM)
|
||||
}
|
||||
}
|
||||
|
||||
private val isArmWindows: Boolean
|
||||
get() {
|
||||
if (!os.isWindows) {
|
||||
return false
|
||||
}
|
||||
// System.getProperty("os.arch") returns the architecture of the JVM, not the host OS.
|
||||
val procArch = System.getenv("PROCESSOR_ARCHITECTURE")
|
||||
return "ARM64".equals(procArch, ignoreCase = true)
|
||||
}
|
||||
|
||||
// Assembles a collection of JDK versions which tests can be run against, considering ancillary
|
||||
// parameters like `testAllJdks` and `testExperimentalJdks`.
|
||||
val jdkTestRange: Collection<JavaLanguageVersion> by lazy {
|
||||
if (isArmWindows) {
|
||||
// Java toolchains does not work on ARM windows: https://github.com/gradle/gradle/issues/29807
|
||||
// prevent creating tasks to test different JDKs if developing on a Windows ARM machine.
|
||||
return@lazy listOf()
|
||||
}
|
||||
JavaVersionRange.inclusive(jdkTestFloor, jdkTestCeiling).toList()
|
||||
}
|
||||
|
||||
val JavaLanguageVersion.isEnabled: Boolean
|
||||
get() = isVersionEnabled(this)
|
||||
|
||||
fun isVersionEnabled(version: JavaLanguageVersion): Boolean {
|
||||
return when {
|
||||
testAllJdks -> true
|
||||
multiJdkTesting -> JavaVersionRange.isLTS(version)
|
||||
testExperimentalJdks -> version > jdkToolchainVersion
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun JavaToolchainSpec.pklJdkToolchain() {
|
||||
languageVersion.set(jdkToolchainVersion)
|
||||
vendor.set(jdkVendor)
|
||||
}
|
||||
|
||||
private fun labelForVendor(vendor: JvmVendorSpec): String =
|
||||
when (vendor) {
|
||||
JvmVendorSpec.AZUL -> "Zulu"
|
||||
JvmVendorSpec.GRAAL_VM -> "GraalVm"
|
||||
JvmVendorSpec.ORACLE -> "Oracle"
|
||||
JvmVendorSpec.ADOPTIUM -> "Adoptium"
|
||||
else -> error("Unrecognized JDK vendor: $vendor")
|
||||
}
|
||||
|
||||
private fun testNamer(baseName: () -> String): (JavaLanguageVersion, JvmVendorSpec?) -> String =
|
||||
{ jdkTarget, vendor ->
|
||||
val targetToken =
|
||||
when (vendor) {
|
||||
null -> "Jdk${jdkTarget.asInt()}"
|
||||
else -> "Jdk${jdkTarget.asInt()}${labelForVendor(vendor).capitalized()}"
|
||||
}
|
||||
if (jdkTarget > jdkToolchainVersion) {
|
||||
// test targets above the toolchain target are considered "experimental".
|
||||
"${baseName()}${targetToken}Experimental"
|
||||
} else {
|
||||
"${baseName()}${targetToken}"
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
fun multiJdkTestingWith(
|
||||
templateTask: TaskProvider<out Test>,
|
||||
configurator: MultiJdkTestConfigurator = {},
|
||||
): Iterable<Provider<out Any>> =
|
||||
with(project) {
|
||||
val isMultiVendor = testJdkVendors.count() > 1
|
||||
val baseNameProvider = { templateTask.get().name }
|
||||
val namer = testNamer(baseNameProvider)
|
||||
val applyConfig: MultiJdkTestConfigurator = { (version, jdk) ->
|
||||
// 1) copy configurations from the template task
|
||||
templateTask.get().let { template ->
|
||||
// copy explicit dependencies not inferred from task inputs
|
||||
dependsOn(template.dependsOn)
|
||||
classpath = template.classpath
|
||||
testClassesDirs = template.testClassesDirs
|
||||
jvmArgs.addAll(template.jvmArgs)
|
||||
jvmArgumentProviders.addAll(
|
||||
template.jvmArgumentProviders.map { provider ->
|
||||
// Gradle injects this arg, which is not compatible across JDK versions
|
||||
// other JDK versions (see https://github.com/gradle/gradle/issues/39442)
|
||||
CommandLineArgumentProvider {
|
||||
provider.asArguments().filter { !it.startsWith("--sun-misc-unsafe-memory-access") }
|
||||
}
|
||||
}
|
||||
)
|
||||
forkEvery = template.forkEvery
|
||||
maxParallelForks = template.maxParallelForks
|
||||
minHeapSize = template.minHeapSize
|
||||
maxHeapSize = template.maxHeapSize
|
||||
exclude(template.excludes)
|
||||
template.systemProperties.forEach { prop -> systemProperty(prop.key, prop.value) }
|
||||
}
|
||||
|
||||
// 2) assign launcher
|
||||
javaLauncher = jdk
|
||||
|
||||
// 3) dispatch the user's configurator
|
||||
configurator(version to jdk)
|
||||
}
|
||||
|
||||
serviceOf<JavaToolchainService>().let { toolchains ->
|
||||
jdkTestRange
|
||||
.flatMap { targetVersion ->
|
||||
// multiply out by jdk vendor
|
||||
testJdkVendors.map { vendor -> (targetVersion to vendor) }
|
||||
}
|
||||
.mapNotNull { (jdkTarget, vendor) ->
|
||||
if (jdkToolchainVersion == jdkTarget) {
|
||||
tasks.register(namer(jdkTarget, vendor)) {
|
||||
// alias to `test`
|
||||
dependsOn(templateTask)
|
||||
group = Category.VERIFICATION
|
||||
description =
|
||||
"Alias for regular '${baseNameProvider()}' task, on JDK ${jdkTarget.asInt()}"
|
||||
}
|
||||
} else {
|
||||
// Always register and enable the task so it can be run explicitly,
|
||||
// but only return it if it should be included in "check".
|
||||
val task =
|
||||
tasks.register(namer(jdkTarget, vendor.takeIf { isMultiVendor }), Test::class) {
|
||||
group = Category.VERIFICATION
|
||||
description = "Run tests against JDK ${jdkTarget.asInt()}"
|
||||
applyConfig(jdkTarget to toolchains.launcherFor { languageVersion = jdkTarget })
|
||||
// fix: on jdk17, we must force the polyglot module on to the modulepath
|
||||
if (jdkTarget.asInt() == 17)
|
||||
jvmArgumentProviders.add(
|
||||
CommandLineArgumentProvider {
|
||||
buildList { listOf("--add-modules=org.graalvm.polyglot") }
|
||||
}
|
||||
)
|
||||
}
|
||||
task.takeIf { jdkTarget.isEnabled }
|
||||
}
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
val javaCompiler: Provider<JavaCompiler> by lazy {
|
||||
project.serviceOf<JavaToolchainService>().let { toolchainService ->
|
||||
toolchainService.compilerFor { pklJdkToolchain() }
|
||||
}
|
||||
}
|
||||
|
||||
val javaTestLauncher: Provider<JavaLauncher> by lazy {
|
||||
project.serviceOf<JavaToolchainService>().let { toolchainService ->
|
||||
toolchainService.launcherFor { pklJdkToolchain() }
|
||||
}
|
||||
}
|
||||
|
||||
val multiJdkTesting: Boolean by lazy {
|
||||
// Test Pkl against a full range of JDK versions, past and present, within the
|
||||
// supported bounds of `PKL_TEST_JDK_TARGET` and `PKL_TEST_JDK_MAXIMUM`.
|
||||
//
|
||||
// In CI, this defaults to `true` to catch potential cross-JDK compat regressions or other bugs.
|
||||
// In local dev, this defaults to `false` to speed up the build and reduce contributor load.
|
||||
System.getProperty("pklMultiJdkTesting")?.toBoolean() ?: isCiBuild
|
||||
}
|
||||
|
||||
val hasMuslToolchain: Boolean by lazy {
|
||||
// see .github/scripts/install_musl.sh
|
||||
File(System.getProperty("user.home"), "staticdeps/bin/x86_64-linux-musl-gcc").exists()
|
||||
}
|
||||
|
||||
val os: OS by lazy {
|
||||
val currentOs = OperatingSystem.current()
|
||||
when {
|
||||
currentOs.isMacOsX -> OS.MacOS
|
||||
currentOs.isLinux -> OS.Linux
|
||||
currentOs.isWindows -> OS.Windows
|
||||
else -> throw GradleException("Cannot build on ${currentOs.name}")
|
||||
}
|
||||
}
|
||||
|
||||
// could be `commitId: Provider<String> = project.provider { ... }`
|
||||
val commitId: String by lazy {
|
||||
// allow -DcommitId=abc123 for build environments that don't have git.
|
||||
System.getProperty("commitId").let { if (it != null) return@lazy it }
|
||||
// only run command once per build invocation
|
||||
if (project.path == project.rootProject.path) {
|
||||
val process =
|
||||
ProcessBuilder()
|
||||
.command("git", "rev-parse", "--short", "HEAD")
|
||||
.directory(project.rootDir)
|
||||
.start()
|
||||
process.waitFor().also { exitCode ->
|
||||
if (exitCode == -1) throw RuntimeException(process.errorStream.reader().readText())
|
||||
}
|
||||
process.inputStream.reader().readText().trim()
|
||||
} else {
|
||||
project.rootProject.extensions.getByType(BuildInfo::class.java).commitId
|
||||
}
|
||||
}
|
||||
|
||||
val commitish: String by lazy { if (isReleaseBuild) project.version.toString() else commitId }
|
||||
|
||||
val pklVersion: String by lazy {
|
||||
if (isReleaseBuild) {
|
||||
project.version.toString()
|
||||
} else {
|
||||
project.version.toString().replace("-SNAPSHOT", "-dev+$commitId")
|
||||
}
|
||||
}
|
||||
|
||||
val pklVersionNonUnique: String by lazy {
|
||||
if (isReleaseBuild) {
|
||||
project.version.toString()
|
||||
} else {
|
||||
project.version.toString().replace("-SNAPSHOT", "-dev")
|
||||
}
|
||||
}
|
||||
|
||||
// https://melix.github.io/blog/2021/03/version-catalogs-faq.html#_but_how_can_i_use_the_catalog_in_em_plugins_em_defined_in_code_buildsrc_code
|
||||
val libs: VersionCatalog by lazy {
|
||||
project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||
}
|
||||
|
||||
init {
|
||||
if (!isReleaseBuild) {
|
||||
project.version = "${project.version}-SNAPSHOT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shape of a function which is applied to configure multi-JDK testing.
|
||||
private typealias MultiJdkTestConfigurator =
|
||||
Test.(Pair<JavaLanguageVersion, Provider<JavaLauncher>>) -> Unit
|
||||
|
||||
private val OperatingSystem.canonicalName
|
||||
get() =
|
||||
when {
|
||||
isMacOsX -> "macos"
|
||||
isWindows -> "windows"
|
||||
isLinux -> "linux"
|
||||
else -> throw RuntimeException("Unsupported OS: $name")
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* 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+/")
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* 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 Target.OS
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
/**
|
||||
* Task for creating static libraries from object files.
|
||||
*
|
||||
* Supports both Unix `ar` and Windows `lib.exe`.
|
||||
*/
|
||||
abstract class CArchive : DefaultTask() {
|
||||
/** The object files to archive. */
|
||||
@get:InputFiles abstract val objectFiles: ConfigurableFileCollection
|
||||
|
||||
/** The output static library file. */
|
||||
@get:OutputFile abstract val outputFile: RegularFileProperty
|
||||
|
||||
@get:Inject protected abstract val execOperations: ExecOperations
|
||||
|
||||
private val buildInfo: BuildInfo = project.extensions.getByType(BuildInfo::class.java)
|
||||
|
||||
init {
|
||||
group = "build"
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun archive() {
|
||||
outputFile.get().asFile.delete()
|
||||
when (buildInfo.os) {
|
||||
OS.Linux,
|
||||
OS.MacOS -> archiveWithAr()
|
||||
OS.Windows -> archiveWithLib()
|
||||
}
|
||||
logger.info("Created static library -> ${outputFile.get().asFile.name}")
|
||||
}
|
||||
|
||||
private fun archiveWithAr() {
|
||||
val output = outputFile.get().asFile
|
||||
output.parentFile.mkdirs()
|
||||
|
||||
val args = buildList {
|
||||
add("ar")
|
||||
add("-rcs")
|
||||
add(output.absolutePath)
|
||||
objectFiles.files.forEach { file -> add(file.absolutePath) }
|
||||
}
|
||||
|
||||
execOperations.exec {
|
||||
workingDir = project.projectDir
|
||||
commandLine(args)
|
||||
}
|
||||
}
|
||||
|
||||
private fun archiveWithLib() {
|
||||
val output = outputFile.get().asFile
|
||||
output.parentFile.mkdirs()
|
||||
|
||||
val args = buildList {
|
||||
add("lib.exe")
|
||||
add("/OUT:${output.absolutePath}")
|
||||
objectFiles.files.forEach { file -> add(file.absolutePath) }
|
||||
}
|
||||
|
||||
execOperations.exec {
|
||||
workingDir = project.projectDir
|
||||
commandLine(args)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,410 +0,0 @@
|
||||
/*
|
||||
* 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 Target.OS
|
||||
import javax.inject.Inject
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
/**
|
||||
* Task for compiling C source files to object files or executables. Supports both GCC/Clang and
|
||||
* MSVC compilers.
|
||||
*/
|
||||
abstract class CCompile : DefaultTask() {
|
||||
/** The C source files to compile. */
|
||||
@get:InputFiles abstract val sourceFiles: ConfigurableFileCollection
|
||||
|
||||
/** The include directories for compilation. */
|
||||
@get:InputFiles abstract val includeDirs: ConfigurableFileCollection
|
||||
|
||||
/** Preprocessor definitions. */
|
||||
@get:Input @get:Optional abstract val defines: MapProperty<String, String>
|
||||
|
||||
/** C standard version (e.g., "c11", "c17", "gnu11"). */
|
||||
@get:Input @get:Optional abstract val cStandard: Property<String>
|
||||
|
||||
/** Optimization level (e.g., "0", "1", "2", "3", "s", "fast"). */
|
||||
@get:Input @get:Optional abstract val optimizationLevel: Property<String>
|
||||
|
||||
/** Whether to include debug symbols. */
|
||||
@get:Input abstract val debugSymbols: Property<Boolean>
|
||||
|
||||
/** Whether to generate position-independent code (GCC/Clang only). */
|
||||
@get:Input abstract val positionIndependentCode: Property<Boolean>
|
||||
|
||||
/** Warning flags (GCC/Clang: prefixed with -W, e.g., "all", "extra"). */
|
||||
@get:Input abstract val warningFlags: ListProperty<String>
|
||||
|
||||
/** Warning level for MSVC (0-4). */
|
||||
@get:Input @get:Optional abstract val warningLevel: Property<Int>
|
||||
|
||||
/** Feature flags (GCC/Clang only, prefixed with -f). */
|
||||
@get:Input abstract val featureFlags: ListProperty<String>
|
||||
|
||||
/** Machine-specific flags (GCC/Clang only, prefixed with -m). */
|
||||
@get:Input abstract val machineFlags: ListProperty<String>
|
||||
|
||||
/** Runtime library for MSVC (e.g., "MT", "MD", "MTd", "MDd"). */
|
||||
@get:Input @get:Optional abstract val runtimeLibrary: Property<String>
|
||||
|
||||
/** Additional compiler arguments. */
|
||||
@get:Input abstract val compilerArgs: ListProperty<String>
|
||||
|
||||
/** The architecture to compile for (macOS only). */
|
||||
@get:Input @get:Optional abstract val arch: Property<Target.Arch>
|
||||
|
||||
// ===== Linking properties =====
|
||||
|
||||
/** Whether to link into an executable (true) or just compile to object files (false). */
|
||||
@get:Input abstract val link: Property<Boolean>
|
||||
|
||||
/** Library search paths. */
|
||||
@get:InputFiles @get:Optional abstract val libraryPaths: ConfigurableFileCollection
|
||||
|
||||
/** Libraries to link by name. */
|
||||
@get:Input @get:Optional abstract val libraries: ListProperty<String>
|
||||
|
||||
/** Direct library files to link. */
|
||||
@get:InputFiles @get:Optional abstract val libraryFiles: ConfigurableFileCollection
|
||||
|
||||
/** Linker flags. */
|
||||
@get:Input @get:Optional abstract val linkerFlags: ListProperty<String>
|
||||
|
||||
/** macOS frameworks to link (GCC/Clang only). */
|
||||
@get:Input @get:Optional abstract val frameworks: ListProperty<String>
|
||||
|
||||
/** Output file when linking (executable name). */
|
||||
@get:OutputFile @get:Optional abstract val outputFile: RegularFileProperty
|
||||
|
||||
/** Create a shared library (dll, dylib, so). */
|
||||
@get:Input abstract val sharedLibrary: Property<Boolean>
|
||||
|
||||
/** The output directory for object files (when not linking). */
|
||||
@get:OutputDirectory @get:Optional abstract val outputDir: DirectoryProperty
|
||||
|
||||
@get:Inject protected abstract val execOperations: ExecOperations
|
||||
|
||||
private val buildInfo: BuildInfo = project.extensions.getByType(BuildInfo::class.java)
|
||||
|
||||
init {
|
||||
group = "build"
|
||||
// Defaults
|
||||
link.convention(false)
|
||||
debugSymbols.convention(false)
|
||||
positionIndependentCode.convention(false)
|
||||
sharedLibrary.convention(false)
|
||||
warningFlags.convention(listOf("all", "extra"))
|
||||
warningLevel.convention(3)
|
||||
featureFlags.convention(emptyList())
|
||||
machineFlags.convention(emptyList())
|
||||
compilerArgs.convention(emptyList())
|
||||
defines.convention(emptyMap())
|
||||
libraries.convention(emptyList())
|
||||
linkerFlags.convention(emptyList())
|
||||
frameworks.convention(emptyList())
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun compile() {
|
||||
if (link.get()) {
|
||||
compileAndLink()
|
||||
} else {
|
||||
compileOnly()
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileOnly() {
|
||||
val outputDirectory = outputDir.get().asFile
|
||||
outputDirectory.mkdirs()
|
||||
|
||||
val cFiles = sourceFiles.files.filter { it.extension == "c" }
|
||||
|
||||
if (cFiles.isEmpty()) {
|
||||
logger.info("No C files to compile")
|
||||
return
|
||||
}
|
||||
|
||||
cFiles.forEach { cFile ->
|
||||
when (buildInfo.targetMachine.os) {
|
||||
OS.Linux,
|
||||
OS.MacOS -> compileFileGCC(cFile, outputDirectory)
|
||||
OS.Windows -> compileFileMSVC(cFile, outputDirectory)
|
||||
}
|
||||
}
|
||||
cFiles.forEach { cFile ->
|
||||
val objectFile = outputDirectory.resolve("${cFile.nameWithoutExtension}.o")
|
||||
logger.info("Compiled ${cFile.name} -> ${objectFile.name}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileFileGCC(cFile: java.io.File, outputDirectory: java.io.File) {
|
||||
val objectFile = outputDirectory.resolve("${cFile.nameWithoutExtension}.o")
|
||||
|
||||
val args = buildList {
|
||||
add("cc")
|
||||
add("-c")
|
||||
addAll(buildCompilerFlagsGCC())
|
||||
add(cFile.absolutePath)
|
||||
add("-o")
|
||||
add(objectFile.absolutePath)
|
||||
}
|
||||
|
||||
execOperations.exec {
|
||||
workingDir = project.projectDir
|
||||
commandLine(args)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileFileMSVC(cFile: java.io.File, outputDirectory: java.io.File) {
|
||||
val objectFile = outputDirectory.resolve("${cFile.nameWithoutExtension}.obj")
|
||||
|
||||
val args = buildList {
|
||||
add("cl.exe")
|
||||
add("/c")
|
||||
addAll(buildCompilerFlagsMSVC())
|
||||
add("/Fo${objectFile.absolutePath}")
|
||||
add(cFile.absolutePath)
|
||||
}
|
||||
|
||||
execOperations.exec {
|
||||
workingDir = project.projectDir
|
||||
commandLine(args)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileAndLink() {
|
||||
when (buildInfo.targetMachine.os) {
|
||||
OS.Linux,
|
||||
OS.MacOS -> compileAndLinkGCC()
|
||||
OS.Windows -> compileAndLinkMSVC()
|
||||
}
|
||||
|
||||
logger.info("Compiled and linked -> ${outputFile.get().asFile.name}")
|
||||
}
|
||||
|
||||
private fun compileAndLinkGCC() {
|
||||
val output = outputFile.get().asFile
|
||||
|
||||
val args = buildList {
|
||||
add("cc")
|
||||
addAll(buildCompilerFlagsGCC())
|
||||
|
||||
// Add source/object files
|
||||
sourceFiles.files.forEach { file -> add(file.absolutePath) }
|
||||
|
||||
// Library search paths
|
||||
libraryPaths.files.forEach { dir -> add("-L${dir.absolutePath}") }
|
||||
|
||||
// Direct library files. These must come before `-l` libraries below: GNU ld resolves
|
||||
// symbols in a single left-to-right pass, so a static `-lz` etc. must appear after the
|
||||
// archives (e.g. libpkl.a) whose undefined symbols it resolves, or those symbols are
|
||||
// never pulled in.
|
||||
libraryFiles.files.forEach { file -> add(file.absolutePath) }
|
||||
|
||||
// Libraries by name
|
||||
libraries.get().forEach { lib -> add("-l${lib}") }
|
||||
|
||||
// Linker flags
|
||||
if (linkerFlags.get().isNotEmpty()) {
|
||||
add("-Wl,${linkerFlags.get().joinToString(",")}")
|
||||
}
|
||||
|
||||
// macOS frameworks
|
||||
if (buildInfo.os.isMacOS) {
|
||||
frameworks.get().forEach { framework ->
|
||||
add("-framework")
|
||||
add(framework)
|
||||
}
|
||||
}
|
||||
|
||||
if (sharedLibrary.get()) {
|
||||
add("-shared")
|
||||
}
|
||||
|
||||
// Output file
|
||||
add("-o")
|
||||
add(output.absolutePath)
|
||||
}
|
||||
|
||||
output.parentFile.mkdirs()
|
||||
|
||||
execOperations.exec {
|
||||
workingDir = project.projectDir
|
||||
commandLine(args)
|
||||
}
|
||||
}
|
||||
|
||||
private fun compileAndLinkMSVC() {
|
||||
val output = outputFile.get().asFile
|
||||
output.parentFile.mkdirs()
|
||||
|
||||
val args = buildList {
|
||||
add("cl.exe")
|
||||
addAll(buildCompilerFlagsMSVC())
|
||||
|
||||
// Output executable
|
||||
add("/Fe${output.absolutePath}")
|
||||
|
||||
// Add source/object files
|
||||
sourceFiles.files.forEach { file -> add(file.absolutePath) }
|
||||
|
||||
// Linker section
|
||||
if (
|
||||
libraryPaths.files.isNotEmpty() ||
|
||||
libraries.get().isNotEmpty() ||
|
||||
libraryFiles.files.isNotEmpty() ||
|
||||
linkerFlags.get().isNotEmpty()
|
||||
) {
|
||||
add("/link")
|
||||
|
||||
if (sharedLibrary.get()) {
|
||||
add("/DLL")
|
||||
}
|
||||
|
||||
// Library search paths
|
||||
libraryPaths.files.forEach { dir -> add("/LIBPATH:${dir.absolutePath}") }
|
||||
|
||||
// Library files by name
|
||||
libraries.get().forEach { lib -> add("lib${lib}.lib") }
|
||||
|
||||
// Direct library files
|
||||
libraryFiles.files.forEach { file -> add(file.absolutePath) }
|
||||
|
||||
// Additional linker flags
|
||||
addAll(linkerFlags.get())
|
||||
}
|
||||
}
|
||||
|
||||
execOperations.exec {
|
||||
workingDir = project.projectDir
|
||||
commandLine(args)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildCompilerFlagsGCC(): List<String> = buildList {
|
||||
// Warning flags
|
||||
warningFlags.get().forEach { flag -> add("-W${flag}") }
|
||||
|
||||
// Include directories
|
||||
includeDirs.files.forEach { dir -> add("-I${dir.absolutePath}") }
|
||||
|
||||
// Preprocessor definitions
|
||||
defines.get().forEach { (key, value) ->
|
||||
if (value.isEmpty()) {
|
||||
add("-D${key}")
|
||||
} else {
|
||||
add("-D${key}=${value}")
|
||||
}
|
||||
}
|
||||
|
||||
// C standard
|
||||
if (cStandard.isPresent) {
|
||||
add("-std=${cStandard.get()}")
|
||||
}
|
||||
|
||||
// Optimization level
|
||||
if (optimizationLevel.isPresent) {
|
||||
add("-O${optimizationLevel.get()}")
|
||||
}
|
||||
|
||||
// Debug symbols
|
||||
if (debugSymbols.get()) {
|
||||
add("-g")
|
||||
}
|
||||
|
||||
// Position-independent code
|
||||
if (positionIndependentCode.get()) {
|
||||
add("-fPIC")
|
||||
}
|
||||
|
||||
// Feature flags
|
||||
featureFlags.get().forEach { flag -> add("-f${flag}") }
|
||||
|
||||
// Machine flags
|
||||
machineFlags.get().forEach { flag -> add("-m${flag}") }
|
||||
|
||||
// Platform-specific flags
|
||||
if (buildInfo.os.isMacOS && arch.isPresent) {
|
||||
add("-arch")
|
||||
add(arch.get().cCompilerName)
|
||||
}
|
||||
|
||||
// Additional compiler arguments
|
||||
addAll(compilerArgs.get())
|
||||
}
|
||||
|
||||
private fun buildCompilerFlagsMSVC(): List<String> = buildList {
|
||||
// Warning level
|
||||
if (warningLevel.isPresent) {
|
||||
add("/W${warningLevel.get()}")
|
||||
}
|
||||
|
||||
// Include directories
|
||||
includeDirs.files.forEach { dir -> add("/I${dir.absolutePath}") }
|
||||
|
||||
// Preprocessor definitions
|
||||
defines.get().forEach { (key, value) ->
|
||||
if (value.isEmpty()) {
|
||||
add("/D${key}")
|
||||
} else {
|
||||
add("/D${key}=${value}")
|
||||
}
|
||||
}
|
||||
|
||||
// C standard
|
||||
if (cStandard.isPresent) {
|
||||
add("/std:${cStandard.get()}")
|
||||
}
|
||||
|
||||
// Optimization level
|
||||
if (optimizationLevel.isPresent) {
|
||||
when (optimizationLevel.get().lowercase()) {
|
||||
"0",
|
||||
"d" -> add("/Od")
|
||||
"1" -> add("/O1")
|
||||
"2" -> add("/O2")
|
||||
"x",
|
||||
"fast" -> add("/Ox")
|
||||
"s" -> add("/Os")
|
||||
"t" -> add("/Ot")
|
||||
}
|
||||
}
|
||||
|
||||
// Debug symbols
|
||||
if (debugSymbols.get()) {
|
||||
add("/Zi")
|
||||
}
|
||||
|
||||
// Runtime library
|
||||
if (runtimeLibrary.isPresent) {
|
||||
add("/${runtimeLibrary.get()}")
|
||||
}
|
||||
|
||||
// Additional compiler arguments
|
||||
addAll(compilerArgs.get())
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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 groovy.util.Node
|
||||
import groovy.xml.XmlParser
|
||||
import groovy.xml.XmlUtil
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class ConfigureLateInitAnnotation : DefaultTask() {
|
||||
private val miscXmlFile = project.rootProject.file(".idea/misc.xml")
|
||||
|
||||
init {
|
||||
inputs.file(miscXmlFile)
|
||||
outputs.file(miscXmlFile)
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
fun run() {
|
||||
val annotationName = "org.pkl.core.util.LateInit"
|
||||
|
||||
if (!miscXmlFile.exists()) {
|
||||
miscXmlFile.writeText(
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
</project>
|
||||
"""
|
||||
.trimIndent()
|
||||
.trim()
|
||||
)
|
||||
}
|
||||
|
||||
val root = XmlParser().parse(miscXmlFile)
|
||||
|
||||
fun Node.childNodes() = children().filterIsInstance<Node>()
|
||||
|
||||
var entryPointsManager =
|
||||
root.childNodes().find {
|
||||
it.name() == "component" && it.attribute("name") == "EntryPointsManager"
|
||||
}
|
||||
if (entryPointsManager == null) {
|
||||
entryPointsManager = root.appendNode("component", mapOf("name" to "EntryPointsManager"))
|
||||
}
|
||||
|
||||
var writeAnnotations = entryPointsManager.childNodes().find { it.name() == "writeAnnotations" }
|
||||
if (writeAnnotations == null) {
|
||||
writeAnnotations = entryPointsManager.appendNode("writeAnnotations")
|
||||
}
|
||||
|
||||
val alreadyExists =
|
||||
writeAnnotations.childNodes().any {
|
||||
it.name() == "writeAnnotation" && it.attribute("name") == annotationName
|
||||
}
|
||||
|
||||
if (!alreadyExists) {
|
||||
writeAnnotations.appendNode("writeAnnotation", mapOf("name" to annotationName))
|
||||
miscXmlFile.writeText(XmlUtil.serialize(root))
|
||||
logger.lifecycle("Updated .idea/misc.xml")
|
||||
} else {
|
||||
logger.info("$annotationName is already configured in .idea/misc.xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
/**
|
||||
* Builds a self-contained Pkl CLI Jar that is directly executable on Windows, macOS, and Linux.
|
||||
*
|
||||
* For direct execution, the `java` command must be on the PATH.
|
||||
*
|
||||
* Technique borrowed from [Mill](https://mill-build.org/blog/5-executable-jars.html).
|
||||
*/
|
||||
abstract class ExecutableJar : DefaultTask() {
|
||||
@get:InputFile abstract val inJar: RegularFileProperty
|
||||
|
||||
@get:OutputFile abstract val outJar: RegularFileProperty
|
||||
|
||||
@get:Input abstract val jvmArgs: ListProperty<String>
|
||||
|
||||
@TaskAction
|
||||
@Suppress("unused")
|
||||
fun buildJar() {
|
||||
val inFile = inJar.get().asFile
|
||||
val outFile = outJar.get().asFile
|
||||
val escapedJvmArgs = jvmArgs.get().joinToString(separator = " ") { "\"$it\"" }
|
||||
val unixStartScript =
|
||||
"""
|
||||
@ 2>/dev/null # 2>nul & echo off & goto BOF
|
||||
:
|
||||
exec java $escapedJvmArgs -jar "$0" "$@"
|
||||
exit
|
||||
"""
|
||||
.trimIndent()
|
||||
val windowsStartScript =
|
||||
"""
|
||||
:BOF
|
||||
setlocal
|
||||
@echo off
|
||||
java $escapedJvmArgs -jar "%~dpnx0" %*
|
||||
endlocal
|
||||
exit /B %errorlevel%
|
||||
"""
|
||||
.trimIndent()
|
||||
// need crlf endings for Windows portion of script
|
||||
.replace("\n", "\r\n")
|
||||
val startScript = unixStartScript + "\r\n" + windowsStartScript + "\r\n".repeat(3)
|
||||
outFile.outputStream().use { outStream ->
|
||||
startScript.byteInputStream().use { it.copyTo(outStream) }
|
||||
inFile.inputStream().use { it.copyTo(outStream) }
|
||||
}
|
||||
|
||||
// chmod a+x
|
||||
outFile.setExecutable(true, false)
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.api.provider.Property
|
||||
|
||||
abstract class ExecutableSpec {
|
||||
/** The main entrypoint Java class of the executable. */
|
||||
abstract val mainClass: Property<String>
|
||||
|
||||
/**
|
||||
* The name of the native executable.
|
||||
*
|
||||
* Not required if not building a native executable.
|
||||
*/
|
||||
abstract val name: Property<String>
|
||||
|
||||
/** The name of the Java executable. */
|
||||
abstract val javaName: Property<String>
|
||||
|
||||
/** The name of the executable that shows in the description when published to Maven. */
|
||||
abstract val documentationName: Property<String>
|
||||
|
||||
/**
|
||||
* The base name of the Maven publication.
|
||||
*
|
||||
* This becomes the base name of the Artifact ID, with the os and arch suffixed.
|
||||
*
|
||||
* For example, `pkl` becomes `pkl-macos-aarch` for the macOS/aarch64 variant.
|
||||
*/
|
||||
abstract val publicationName: Property<String>
|
||||
|
||||
/** The name of the artifact ID for the Java executable. */
|
||||
abstract val javaPublicationName: Property<String>
|
||||
|
||||
/** The website for this executable. */
|
||||
abstract val website: Property<String>
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.util.GradleVersion
|
||||
|
||||
open class GradlePluginTests {
|
||||
lateinit var minGradleVersion: GradleVersion
|
||||
lateinit var maxGradleVersion: GradleVersion
|
||||
var skippedGradleVersions: List<GradleVersion> = listOf()
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
|
||||
open class HtmlValidator(project: Project) {
|
||||
var sources: FileCollection = project.files()
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* 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.nio.file.AtomicMoveNotSupportedException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.*
|
||||
import java.util.zip.ZipInputStream
|
||||
import javax.inject.Inject
|
||||
import kotlin.io.path.createDirectories
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.internal.file.FileOperations
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
abstract class InstallGraalVm
|
||||
@Inject
|
||||
constructor(
|
||||
private val fileOperations: FileOperations,
|
||||
private val execOperations: ExecOperations,
|
||||
) : DefaultTask() {
|
||||
@get:Input abstract val graalVm: Property<BuildInfo.GraalVm>
|
||||
|
||||
init {
|
||||
@Suppress("LeakingThis") onlyIf("GraalVM not installed") { !graalVm.get().installDir.exists() }
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
@Suppress("unused")
|
||||
fun run() {
|
||||
// minimize chance of corruption by extract-to-random-dir-and-publish
|
||||
val distroDir = Paths.get(graalVm.get().homeDir, UUID.randomUUID().toString())
|
||||
try {
|
||||
distroDir.createDirectories()
|
||||
println("Extracting ${graalVm.get().downloadFile} into $distroDir")
|
||||
val os = org.gradle.internal.os.OperatingSystem.current()
|
||||
if (os.isWindows) extractZip(distroDir) else extractTarGz(distroDir)
|
||||
|
||||
val distroBinDir =
|
||||
if (os.isMacOsX) distroDir.resolve("Contents/Home/bin") else distroDir.resolve("bin")
|
||||
|
||||
println("Installing native-image into $distroDir")
|
||||
val gvmVersionMajor =
|
||||
requireNotNull(graalVm.get().version.split(".").first().toIntOrNull()) {
|
||||
"Invalid GraalVM JDK version: ${graalVm.get().graalVmJdkVersion}"
|
||||
}
|
||||
if (gvmVersionMajor < 24) {
|
||||
execOperations.exec {
|
||||
val executableName = if (os.isWindows) "gu.cmd" else "gu"
|
||||
executable = distroBinDir.resolve(executableName).toString()
|
||||
args("install", "--no-progress", "native-image")
|
||||
}
|
||||
}
|
||||
|
||||
publishInstallDir(distroDir, os)
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
fileOperations.delete(distroDir)
|
||||
} catch (ignored: Exception) {}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractTarGz(distroDir: Path) {
|
||||
// faster and more reliable than Gradle's `copy { from tarTree() }`
|
||||
execOperations.exec {
|
||||
workingDir = distroDir.toFile()
|
||||
executable = "tar"
|
||||
args("--strip-components=1", "-xzf", graalVm.get().downloadFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractZip(distroDir: Path) {
|
||||
val targetDir = distroDir.toAbsolutePath().normalize()
|
||||
ZipInputStream(graalVm.get().downloadFile.inputStream().buffered()).use { zipInput ->
|
||||
var entry = zipInput.nextEntry
|
||||
while (entry != null) {
|
||||
try {
|
||||
val strippedPath = stripFirstPathComponent(entry.name)
|
||||
if (strippedPath != null) {
|
||||
val target = targetDir.resolve(strippedPath).normalize()
|
||||
require(target.startsWith(targetDir)) {
|
||||
"GraalVM archive entry escapes destination directory: ${entry.name}"
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
target.createDirectories()
|
||||
} else {
|
||||
target.parent?.createDirectories()
|
||||
Files.copy(zipInput, target)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
zipInput.closeEntry()
|
||||
}
|
||||
entry = zipInput.nextEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stripFirstPathComponent(path: String): String? {
|
||||
val normalizedPath = path.replace('\\', '/').trimStart('/')
|
||||
val separatorIndex = normalizedPath.indexOf('/')
|
||||
if (separatorIndex == -1) return null
|
||||
return normalizedPath.substring(separatorIndex + 1).takeIf { it.isNotEmpty() }
|
||||
}
|
||||
|
||||
private fun publishInstallDir(distroDir: Path, os: org.gradle.internal.os.OperatingSystem) {
|
||||
if (os.isWindows) {
|
||||
println("Installing ${graalVm.get().installDir} from $distroDir")
|
||||
moveAtomicallyOrRegularly(distroDir, graalVm.get().installDir.toPath())
|
||||
return
|
||||
}
|
||||
|
||||
println("Creating symlink ${graalVm.get().installDir} for $distroDir")
|
||||
val tempLink = Paths.get(graalVm.get().homeDir, UUID.randomUUID().toString())
|
||||
Files.createSymbolicLink(tempLink, distroDir)
|
||||
try {
|
||||
moveAtomicallyOrRegularly(tempLink, graalVm.get().installDir.toPath())
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
fileOperations.delete(tempLink.toFile())
|
||||
} catch (ignored: Exception) {}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun moveAtomicallyOrRegularly(source: Path, target: Path) {
|
||||
try {
|
||||
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE)
|
||||
} catch (e: AtomicMoveNotSupportedException) {
|
||||
Files.move(source, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
import java.util.*
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
|
||||
typealias JavaVersionPair = Pair<JavaLanguageVersion, JavaLanguageVersion>
|
||||
|
||||
// All LTS releases.
|
||||
private val ltsReleases =
|
||||
sortedSetOf(
|
||||
JavaLanguageVersion.of(8),
|
||||
JavaLanguageVersion.of(11),
|
||||
JavaLanguageVersion.of(17),
|
||||
JavaLanguageVersion.of(21),
|
||||
JavaLanguageVersion.of(25),
|
||||
)
|
||||
|
||||
/** Describes an inclusive range of JVM versions, based on the [JavaLanguageVersion] type. */
|
||||
@JvmInline
|
||||
value class JavaVersionRange private constructor(private val bounds: JavaVersionPair) :
|
||||
Iterable<JavaLanguageVersion> {
|
||||
@Suppress("unused")
|
||||
companion object {
|
||||
fun isLTS(version: JavaLanguageVersion): Boolean = version in ltsReleases
|
||||
|
||||
fun inclusive(floor: JavaLanguageVersion, ceiling: JavaLanguageVersion): JavaVersionRange =
|
||||
JavaVersionRange(floor to ceiling)
|
||||
|
||||
fun startingAt(floor: JavaLanguageVersion): JavaVersionRange =
|
||||
inclusive(floor, JavaLanguageVersion.of(PKL_TEST_JDK_MAXIMUM))
|
||||
|
||||
fun upTo(ceiling: JavaLanguageVersion): JavaVersionRange =
|
||||
inclusive(JavaLanguageVersion.of(PKL_TEST_JDK_MINIMUM), ceiling)
|
||||
}
|
||||
|
||||
operator fun contains(version: JavaLanguageVersion): Boolean =
|
||||
version >= bounds.first && version <= bounds.second
|
||||
|
||||
fun asSequence(): Sequence<JavaLanguageVersion> = sequence {
|
||||
var current = bounds.first
|
||||
while (current <= bounds.second) {
|
||||
yield(current)
|
||||
current = JavaLanguageVersion.of(current.asInt() + 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun asSortedSet(): SortedSet<JavaLanguageVersion> = asSequence().toSortedSet()
|
||||
|
||||
override fun iterator(): Iterator<JavaLanguageVersion> = asSortedSet().iterator()
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
/*
|
||||
* 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.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import javax.inject.Inject
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.exists
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.MapProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.services.BuildService
|
||||
import org.gradle.api.services.BuildServiceParameters
|
||||
import org.gradle.api.tasks.ClasspathNormalizer
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputDirectories
|
||||
import org.gradle.api.tasks.OutputFiles
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.registerIfAbsent
|
||||
import org.gradle.kotlin.dsl.withNormalizer
|
||||
import org.gradle.process.ExecOperations
|
||||
|
||||
abstract class NativeImageBuildService : BuildService<BuildServiceParameters.None>
|
||||
|
||||
abstract class NativeImageBuild : DefaultTask() {
|
||||
@get:Input abstract val outputName: Property<String>
|
||||
|
||||
@get:Input abstract val extraNativeImageArgs: ListProperty<String>
|
||||
|
||||
@get:Input abstract val arch: Property<Target.Arch>
|
||||
|
||||
/**
|
||||
* Names of extra directories, relative to the native-image working directory, that should be
|
||||
* copied into [outputDir] after a successful build.
|
||||
*/
|
||||
@get:Input abstract val additionalOutputDirectoryNames: SetProperty<String>
|
||||
|
||||
/**
|
||||
* The main class entrypoint for the executable.
|
||||
*
|
||||
* This option is not necessary if [sharedLibrary] is true.
|
||||
*/
|
||||
@get:Optional @get:Input abstract val mainClass: Property<String>
|
||||
|
||||
/** Create a shared library, instead of an executable. */
|
||||
@get:Input abstract val sharedLibrary: Property<Boolean>
|
||||
|
||||
@get:InputFiles abstract val classpath: ConfigurableFileCollection
|
||||
|
||||
@get:Input abstract val envVars: MapProperty<String, String>
|
||||
|
||||
@get:InputFile @get:Optional abstract val nativeCompilerPath: RegularFileProperty
|
||||
|
||||
@get:Internal abstract val compiledClassesFile: RegularFileProperty
|
||||
|
||||
@get:Internal abstract val outputDir: DirectoryProperty
|
||||
|
||||
@get:Inject protected abstract val execOperations: ExecOperations
|
||||
|
||||
@get:Inject protected abstract val objectFactory: ObjectFactory
|
||||
|
||||
private val graalVm: Provider<BuildInfo.GraalVm> = arch.map { a ->
|
||||
when (a) {
|
||||
Target.Arch.AMD64 -> buildInfo.graalVmAmd64
|
||||
Target.Arch.AARCH64 -> buildInfo.graalVmAarch64
|
||||
}
|
||||
}
|
||||
|
||||
private val buildInfo: BuildInfo = project.extensions.getByType(BuildInfo::class.java)
|
||||
|
||||
private val nativeImageCommandName =
|
||||
if (buildInfo.os.isWindows) "native-image.cmd" else "native-image"
|
||||
|
||||
private val nativeImageExecutable = graalVm.map { "${it.baseDir}/bin/$nativeImageCommandName" }
|
||||
|
||||
private val extraArgsFromProperties by lazy {
|
||||
System.getProperties()
|
||||
.filter { it.key.toString().startsWith("pkl.native") }
|
||||
.map { "${it.key}=${it.value}".substring("pkl.native".length) }
|
||||
}
|
||||
|
||||
private val buildService =
|
||||
project.gradle.sharedServices.registerIfAbsent(
|
||||
"nativeImageBuildService",
|
||||
NativeImageBuildService::class,
|
||||
) {
|
||||
maxParallelUsages.set(1)
|
||||
}
|
||||
|
||||
init {
|
||||
// ensure native-image builds run in serial (prevent `gw buildNative` from consuming all host
|
||||
// CPU resources).
|
||||
usesService(buildService)
|
||||
|
||||
sharedLibrary.convention(false)
|
||||
|
||||
outputDir.convention(project.layout.buildDirectory.dir("executable"))
|
||||
|
||||
group = "build"
|
||||
|
||||
inputs
|
||||
.files(classpath)
|
||||
.withPropertyName("runtimeClasspath")
|
||||
.withNormalizer(ClasspathNormalizer::class)
|
||||
inputs
|
||||
.files(nativeImageExecutable)
|
||||
.withPropertyName("graalVmNativeImage")
|
||||
.withPathSensitivity(PathSensitivity.ABSOLUTE)
|
||||
if (nativeCompilerPath.isPresent) {
|
||||
inputs.file(nativeCompilerPath)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@OutputFiles
|
||||
fun getEffectiveOutputFiles(): FileCollection {
|
||||
return objectFactory
|
||||
.fileCollection()
|
||||
.from(
|
||||
sharedLibrary.map { isLibrary ->
|
||||
val dir = outputDir.get()
|
||||
val libraryName = outputName.get()
|
||||
// if building a library, native-image outputs the shared library plus four headers
|
||||
// (and, on Windows, an import library); otherwise, it outputs just the one file
|
||||
if (isLibrary) {
|
||||
val sharedLibraryExtension = buildInfo.os.sharedLibraryExtension
|
||||
val staticLibraryExtension = buildInfo.os.staticLibraryExtension
|
||||
dir.files(
|
||||
buildList {
|
||||
add("$libraryName.$sharedLibraryExtension")
|
||||
if (buildInfo.os.isWindows) {
|
||||
// the DLL's import library, which consumers must link against instead of
|
||||
// the .dll itself
|
||||
add("$libraryName.$staticLibraryExtension")
|
||||
// a genuine, self-contained static archive with no runtime DLL dependency,
|
||||
// produced by build_windows.bat
|
||||
add("${libraryName}_s.$staticLibraryExtension")
|
||||
} else {
|
||||
// a genuine, self-contained static archive with no runtime dependency,
|
||||
// produced by build_unix.sh
|
||||
add("$libraryName.$staticLibraryExtension")
|
||||
}
|
||||
add("$libraryName.h")
|
||||
add("${libraryName}_dynamic.h")
|
||||
add("graal_isolate.h")
|
||||
add("graal_isolate_dynamic.h")
|
||||
}
|
||||
)
|
||||
} else {
|
||||
val executableName = if (buildInfo.os.isWindows) "${libraryName}.exe" else libraryName
|
||||
dir.file(executableName)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@OutputDirectories
|
||||
fun getEffectiveOutputDirectories(): FileCollection =
|
||||
objectFactory
|
||||
.fileCollection()
|
||||
.from(additionalOutputDirectoryNames.map { names -> names.map { outputDir.get().dir(it) } })
|
||||
|
||||
@TaskAction
|
||||
protected fun run() {
|
||||
val workingDir =
|
||||
project.layout.buildDirectory
|
||||
.dir("tmp/native-image-build/${name}")
|
||||
.get()
|
||||
.asFile
|
||||
.toPath()
|
||||
.also { it.createDirectories() }
|
||||
val reportsDir = workingDir.resolve("reports")
|
||||
// reports are timestamped and never cleaned up by native-image; make sure we read a fresh one
|
||||
reportsDir
|
||||
.toFile()
|
||||
.listFiles { f -> f.name.startsWith(COMPILATION_REPORT_PREFIX) }
|
||||
?.forEach { it.delete() }
|
||||
val execResult = execOperations.exec {
|
||||
val exclusions =
|
||||
listOf(buildInfo.libs.findLibrary("graalSdk").get()).map { it.get().module.name }
|
||||
|
||||
executable = nativeImageExecutable.get()
|
||||
workingDir(workingDir)
|
||||
|
||||
args = buildList {
|
||||
add("--color=always")
|
||||
// must be emitted before any experimental options are used
|
||||
add("-H:+UnlockExperimentalVMOptions")
|
||||
// emit `reports/universe_compilation_*.txt`, listing all compiled methods
|
||||
add("-H:+PrintUniverse")
|
||||
// currently gives a deprecation warning, but we've been told
|
||||
// that the "initialize everything at build time" *CLI* option is likely here to stay
|
||||
add("--initialize-at-build-time=")
|
||||
// needed for messagepack-java (see https://github.com/msgpack/msgpack-java/issues/600)
|
||||
add("--initialize-at-run-time=org.msgpack.core.buffer.DirectBufferAccess")
|
||||
// prevent storing `homeDir` in native image
|
||||
add("--initialize-at-run-time=org.pkl.core.util.BaseDirectory")
|
||||
add("--initialize-at-run-time=org.pkl.core.util.BaseDirectories")
|
||||
// prevent storing `isEnabled`
|
||||
add("--initialize-at-run-time=org.pkl.core.util.DebugLogger")
|
||||
// needed for jline-terminal-jni
|
||||
add("--initialize-at-run-time=org.jline.nativ,org.jline.terminal.impl.jni")
|
||||
// needed for protobuf-java
|
||||
add("--initialize-at-run-time=com.google.protobuf.UnsafeUtil")
|
||||
add("--no-fallback")
|
||||
add("-H:IncludeResources=org/pkl/core/stdlib/.*\\.pkl")
|
||||
add("-H:IncludeResources=org/jline/utils/.*")
|
||||
add("-H:IncludeResourceBundles=org.pkl.core.errorMessages")
|
||||
add("-H:IncludeResourceBundles=org.pkl.parser.errorMessages")
|
||||
add("-H:IncludeResources=org/pkl/commons/cli/PklCARoots.pem")
|
||||
if (mainClass.isPresent) {
|
||||
add("-H:Class=${mainClass.get()}")
|
||||
}
|
||||
if (sharedLibrary.get()) {
|
||||
add("--shared")
|
||||
}
|
||||
add("-o")
|
||||
add(outputName.get())
|
||||
// the actual limit (currently) used by native-image is this number + 1400 (idea is to
|
||||
// compensate for Truffle's own nodes)
|
||||
add("-H:MaxRuntimeCompileMethods=1800")
|
||||
add("-H:+EnforceMaxRuntimeCompileMethods")
|
||||
add("--enable-url-protocols=http,https")
|
||||
add("-H:+ReportExceptionStackTraces")
|
||||
// disable automatic support for JVM CLI options (puts our main class in full control of
|
||||
// argument parsing)
|
||||
add("-H:-ParseRuntimeOptions")
|
||||
if (!buildInfo.isReleaseBuild) {
|
||||
// disable all optimizations
|
||||
add("-O0")
|
||||
// generate debugging information
|
||||
add("-g")
|
||||
}
|
||||
if (buildInfo.isNativeArch) {
|
||||
add("-march=native")
|
||||
} else {
|
||||
add("-march=compatibility")
|
||||
}
|
||||
// native-image rejects non-existing class path entries -> filter
|
||||
add("--class-path")
|
||||
val pathInput = classpath.filter {
|
||||
it.exists() && !exclusions.any { exclude -> it.name.contains(exclude) }
|
||||
}
|
||||
add(pathInput.asPath)
|
||||
// make sure dev machine stays responsive (15% slowdown on my laptop)
|
||||
val processors =
|
||||
Runtime.getRuntime().availableProcessors() /
|
||||
if (buildInfo.os.isMacOS && !buildInfo.isCiBuild) 4 else 1
|
||||
add("-J-XX:ActiveProcessorCount=${processors}")
|
||||
addAll(envVars.get().entries.map { "-E${it.key}=${it.value}" })
|
||||
if (nativeCompilerPath.isPresent) {
|
||||
add("--native-compiler-path=${nativeCompilerPath.get().asFile}")
|
||||
}
|
||||
// Pass through all `HOMEBREW_` prefixed environment variables to allow build with shimmed
|
||||
// tools.
|
||||
addAll(environment.keys.filter { it.startsWith("HOMEBREW_") }.map { "-E$it" })
|
||||
addAll(extraNativeImageArgs.get())
|
||||
addAll(extraArgsFromProperties)
|
||||
}
|
||||
}
|
||||
|
||||
if (execResult.exitValue == 0) {
|
||||
val outputFileNames = getEffectiveOutputFiles().files.map { it.name }
|
||||
for (fileName in outputFileNames) {
|
||||
val sourceFile = workingDir.resolve(fileName)
|
||||
val targetFile = outputDir.get().asFile.toPath().resolve(fileName)
|
||||
if (!sourceFile.exists()) {
|
||||
throw GradleException("Expected to find $fileName in the working dir but didn't")
|
||||
}
|
||||
Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
for (dirName in additionalOutputDirectoryNames.get()) {
|
||||
val sourceDir = workingDir.resolve(dirName).toFile()
|
||||
if (!sourceDir.exists()) {
|
||||
throw GradleException("Expected to find directory $dirName in the working dir but didn't")
|
||||
}
|
||||
val targetDir = outputDir.get().asFile.resolve(dirName)
|
||||
targetDir.deleteRecursively()
|
||||
sourceDir.copyRecursively(targetDir, overwrite = true)
|
||||
}
|
||||
writeCompiledClasses(reportsDir.toFile())
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeCompiledClasses(reportsDir: java.io.File) {
|
||||
val report =
|
||||
reportsDir
|
||||
.listFiles { f -> f.name.startsWith(COMPILATION_REPORT_PREFIX) }
|
||||
?.maxByOrNull { it.lastModified() }
|
||||
?: throw GradleException("Expected to find $COMPILATION_REPORT_PREFIX*.txt in $reportsDir")
|
||||
// Method lines look like `336 2232 apple.security.AppleProvider$Service.newInstance(...): ...`
|
||||
// (offset, size, qualified method name, signature).
|
||||
val methodLine = Regex("""^\s*\d+\s+\d+\s+([^\s(]+)\(""")
|
||||
val classNames = sortedSetOf<String>()
|
||||
report.useLines { lines ->
|
||||
for (line in lines) {
|
||||
val method = methodLine.find(line)?.groupValues?.get(1) ?: continue
|
||||
// Nested, hidden, and lambda classes all live in their top-level class' source file.
|
||||
classNames.add(method.substringBeforeLast('.').substringBefore('$').substringBefore('/'))
|
||||
}
|
||||
}
|
||||
if (classNames.isEmpty()) {
|
||||
throw GradleException("Found no compiled methods in $report")
|
||||
}
|
||||
val file = compiledClassesFile.get().asFile
|
||||
file.parentFile.mkdirs()
|
||||
file.writeText(classNames.joinToString("\n", postfix = "\n"))
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val COMPILATION_REPORT_PREFIX = "universe_compilation_"
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* 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"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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 com.diffplug.spotless.FormatterFunc
|
||||
import com.diffplug.spotless.FormatterStep
|
||||
import java.io.Serial
|
||||
import java.io.Serializable
|
||||
import java.net.URLClassLoader
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
|
||||
class PklFormatterStep(@Transient private val configuration: Configuration) : Serializable {
|
||||
companion object {
|
||||
@Serial private const val serialVersionUID: Long = 1L
|
||||
}
|
||||
|
||||
fun create(): FormatterStep {
|
||||
return FormatterStep.createLazy(
|
||||
"pkl",
|
||||
{ PklFormatterStep(configuration) },
|
||||
{ PklFormatterFunc(configuration) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class PklFormatterFunc(@Transient private val configuration: Configuration) :
|
||||
FormatterFunc, Serializable {
|
||||
companion object {
|
||||
@Serial private const val serialVersionUID: Long = 1L
|
||||
}
|
||||
|
||||
private val classLoader by lazy {
|
||||
val urls = configuration.files.map { it.toURI().toURL() }
|
||||
// Use the platform classloader as parent to isolate from Gradle's classloader
|
||||
URLClassLoader(urls.toTypedArray(), ClassLoader.getPlatformClassLoader())
|
||||
}
|
||||
|
||||
private val formatterClass by lazy { classLoader.loadClass("org.pkl.formatter.Formatter") }
|
||||
|
||||
private val formatMethod by lazy { formatterClass.getMethod("format", String::class.java) }
|
||||
|
||||
private val formatterInstance by lazy { formatterClass.getConstructor().newInstance() }
|
||||
|
||||
override fun apply(input: String): String {
|
||||
return formatMethod(formatterInstance, input) as String
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* 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.nio.charset.StandardCharsets
|
||||
import java.util.Base64
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven
|
||||
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.plugins.signing.SigningExtension
|
||||
|
||||
/** Configures common POM metadata (licenses, developers, SCM, etc.) for all Pkl publications. */
|
||||
fun Project.configurePklPomMetadata() {
|
||||
extensions.configure<PublishingExtension> {
|
||||
publications.withType<MavenPublication>().configureEach {
|
||||
pom {
|
||||
name.set(artifactId)
|
||||
licenses {
|
||||
license {
|
||||
name.set("The Apache Software License, Version 2.0")
|
||||
url.set("https://github.com/apple/pkl/blob/main/LICENSE.txt")
|
||||
}
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
id.set("pkl-authors")
|
||||
name.set("The Pkl Authors")
|
||||
email.set("pkl-oss@group.apple.com")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
connection.set("scm:git:git://github.com/apple/pkl.git")
|
||||
developerConnection.set("scm:git:ssh://github.com/apple/pkl.git")
|
||||
val buildInfo = extensions.getByType<BuildInfo>()
|
||||
url.set("https://github.com/apple/pkl/tree/${buildInfo.commitish}")
|
||||
}
|
||||
issueManagement {
|
||||
system.set("GitHub Issues")
|
||||
url.set("https://github.com/apple/pkl/issues")
|
||||
}
|
||||
ciManagement {
|
||||
system.set("GitHub Actions")
|
||||
url.set("https://github.com/apple/pkl/actions")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures POM validation for [publicationName] to check for unresolved versions and snapshots in
|
||||
* releases.
|
||||
*/
|
||||
fun Project.configurePomValidation(publicationName: String = "library") {
|
||||
val generatePomTaskName =
|
||||
"generatePomFileFor${publicationName.replaceFirstChar { it.uppercase() }}Publication"
|
||||
val generatePomTasks =
|
||||
tasks.withType<GenerateMavenPom>().matching { it.name == generatePomTaskName }
|
||||
val pomFiles = providers.provider { generatePomTasks.map { it.destination } }
|
||||
|
||||
val validatePom =
|
||||
tasks.register("validatePom") {
|
||||
val outputFile =
|
||||
layout.buildDirectory.file("validatePom") // dummy output to satisfy up-to-date check
|
||||
|
||||
dependsOn(generatePomTasks)
|
||||
inputs.files(pomFiles)
|
||||
outputs.file(outputFile)
|
||||
onlyIf { pomFiles.get().isNotEmpty() }
|
||||
|
||||
doLast {
|
||||
outputFile.get().asFile.delete()
|
||||
|
||||
val pomFile = pomFiles.get().single()
|
||||
assert(pomFile.exists())
|
||||
|
||||
val text = pomFile.readText()
|
||||
|
||||
run {
|
||||
val unresolvedVersion = Regex("<version>.*[+,()\\[\\]].*</version>")
|
||||
val matches = unresolvedVersion.findAll(text).toList()
|
||||
if (matches.isNotEmpty()) {
|
||||
throw org.gradle.api.GradleException(
|
||||
"""
|
||||
Found unresolved version selector(s) in generated POM:
|
||||
${matches.joinToString("\n") { it.groupValues[0] }}
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
if (buildInfo.isReleaseBuild) {
|
||||
val snapshotVersion = Regex("<version>.*-SNAPSHOT</version>")
|
||||
val matches = snapshotVersion.findAll(text).toList()
|
||||
if (matches.isNotEmpty()) {
|
||||
throw org.gradle.api.GradleException(
|
||||
"""
|
||||
Found snapshot version(s) in generated POM of Pkl release version:
|
||||
${matches.joinToString("\n") { it.groupValues[0] }}
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
outputFile.get().asFile.writeText("OK")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("publish") { dependsOn(validatePom) }
|
||||
}
|
||||
|
||||
/** Configures signing for Pkl publications. */
|
||||
fun Project.configurePklSigning() {
|
||||
// Workaround for maven publish plugin not setting up dependencies correctly.
|
||||
// Taken from https://github.com/gradle/gradle/issues/26091#issuecomment-1798137734
|
||||
val dependsOnTasks = mutableListOf<String>()
|
||||
|
||||
tasks.withType<AbstractPublishToMaven>().configureEach {
|
||||
dependsOnTasks.add(name.replace("publish", "sign").replaceAfter("Publication", ""))
|
||||
dependsOn(dependsOnTasks)
|
||||
}
|
||||
|
||||
extensions.configure<SigningExtension> {
|
||||
// provided as env vars `ORG_GRADLE_PROJECT_signingKey` and
|
||||
// `ORG_GRADLE_PROJECT_signingPassword` in CI.
|
||||
val signingKey =
|
||||
(findProperty("signingKey") as String?)?.let {
|
||||
Base64.getDecoder().decode(it).toString(StandardCharsets.US_ASCII)
|
||||
}
|
||||
val signingPassword = findProperty("signingPassword") as String?
|
||||
if (signingKey != null && signingPassword != null) {
|
||||
useInMemoryPgpKeys(signingKey, signingPassword)
|
||||
}
|
||||
extensions.getByType<PublishingExtension>().publications.findByName("library")?.let { sign(it) }
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.api.DefaultTask
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.jvm.JvmLibrary
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import org.gradle.language.base.artifact.SourcesArtifact
|
||||
|
||||
open class ResolveSourcesJars : DefaultTask() {
|
||||
@get:InputFiles val configuration: Property<Configuration> = project.objects.property()
|
||||
|
||||
@get:OutputDirectory val outputDir: DirectoryProperty = project.objects.directoryProperty()
|
||||
|
||||
@TaskAction
|
||||
@Suppress("UnstableApiUsage", "unused")
|
||||
fun resolve() {
|
||||
val componentIds =
|
||||
configuration.get().incoming.resolutionResult.allDependencies.map {
|
||||
(it as ResolvedDependencyResult).selected.id
|
||||
}
|
||||
|
||||
val resolutionResult =
|
||||
project.dependencies
|
||||
.createArtifactResolutionQuery()
|
||||
.forComponents(componentIds)
|
||||
.withArtifacts(JvmLibrary::class.java, SourcesArtifact::class.java)
|
||||
.execute()
|
||||
|
||||
val resolvedJars =
|
||||
resolutionResult.resolvedComponents
|
||||
.flatMap { it.getArtifacts(SourcesArtifact::class.java) }
|
||||
.map { (it as ResolvedArtifactResult).file }
|
||||
|
||||
// copying to an output dir because I don't know how else to describe task outputs
|
||||
project.sync {
|
||||
from(resolvedJars)
|
||||
into(outputDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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 com.diffplug.spotless.FormatterFunc
|
||||
import com.diffplug.spotless.FormatterStep
|
||||
import java.io.File
|
||||
import java.io.Serial
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* A Spotless [FormatterStep] that suppresses formatting changes where the only difference between
|
||||
* the formatted output and the file's content in the upstream base ref is the license header year.
|
||||
*
|
||||
* Avoids an issue where, in the process of working on the codebase:
|
||||
* 1. A file is modified.
|
||||
* 2. Spotless formats the file, and also updates the copyright year.
|
||||
* 3. The original modification is reverted.
|
||||
* 4. Spotless formats the file again, but now the copyright year is the updated year.
|
||||
*/
|
||||
class RevertYearOnlyChangesStep(private val repoRoot: File, private val ratchetFrom: String) :
|
||||
Serializable {
|
||||
companion object {
|
||||
@Serial private const val serialVersionUID: Long = 1L
|
||||
}
|
||||
|
||||
fun create(): FormatterStep =
|
||||
FormatterStep.createLazy(
|
||||
"revertYearOnlyChanges",
|
||||
{ this },
|
||||
{ RevertYearOnlyChangesFunc(repoRoot, ratchetFrom) },
|
||||
)
|
||||
}
|
||||
|
||||
class RevertYearOnlyChangesFunc(private val repoRoot: File, private val ratchetFrom: String) :
|
||||
FormatterFunc.NeedsFile, Serializable {
|
||||
companion object {
|
||||
@Serial private const val serialVersionUID: Long = 1L
|
||||
|
||||
// Matches "Copyright © 2024" or "Copyright © 2024-2025"
|
||||
private val YEAR_REGEX = Regex("""(Copyright © )\d{4}(-\d{4})?""")
|
||||
}
|
||||
|
||||
override fun applyWithFile(unix: String, file: File): String {
|
||||
val relativePath = repoRoot.toPath().relativize(file.toPath()).toString()
|
||||
val upstreamContent = gitShow(ratchetFrom, relativePath) ?: return unix
|
||||
val normalizedRaw = YEAR_REGEX.replace(unix, "\$1YEAR")
|
||||
val normalizedUpstream = YEAR_REGEX.replace(upstreamContent, "\$1YEAR")
|
||||
return if (normalizedRaw == normalizedUpstream) {
|
||||
// Only the year changed — return the upstream content
|
||||
upstreamContent
|
||||
} else {
|
||||
unix
|
||||
}
|
||||
}
|
||||
|
||||
private fun gitShow(ref: String, path: String): String? {
|
||||
val process =
|
||||
ProcessBuilder("git", "show", "$ref:$path")
|
||||
.directory(repoRoot)
|
||||
.redirectErrorStream(true)
|
||||
.start()
|
||||
val output = process.inputStream.readBytes().toString(Charsets.UTF_8)
|
||||
return if (process.waitFor() == 0) output.replace("\r\n", "\n") else null
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
/**
|
||||
* A build target when building native libraries or executables.
|
||||
*
|
||||
* Pkl only builds for the following listed targets.
|
||||
*/
|
||||
enum class Target(val os: OS, val arch: Arch, val musl: Boolean) {
|
||||
MacosAarch64(os = OS.MacOS, arch = Arch.AARCH64, musl = false),
|
||||
LinuxAarch64(os = OS.Linux, arch = Arch.AARCH64, musl = false),
|
||||
LinuxAmd64(os = OS.Linux, arch = Arch.AMD64, musl = false),
|
||||
AlpineLinuxAmd64(os = OS.Linux, arch = Arch.AMD64, musl = true),
|
||||
WindowsAmd64(os = OS.Windows, arch = Arch.AMD64, musl = false);
|
||||
|
||||
companion object {
|
||||
fun from(os: OS, arch: Arch, musl: Boolean): Target {
|
||||
for (target in entries) {
|
||||
if (target.os == os && target.arch == arch && target.musl == musl) {
|
||||
return target
|
||||
}
|
||||
}
|
||||
throw IllegalArgumentException("Cannot build for $os-$arch with musl: $musl")
|
||||
}
|
||||
}
|
||||
|
||||
val targetName: String
|
||||
get() {
|
||||
return if (musl) {
|
||||
assert(os == OS.Linux)
|
||||
"alpine-linux-$arch"
|
||||
} else "$os-$arch"
|
||||
}
|
||||
|
||||
enum class Arch(
|
||||
/** What we call this arch */
|
||||
val simpleName: String,
|
||||
/** What the C compiler calls this arch */
|
||||
val cCompilerName: String,
|
||||
) {
|
||||
AARCH64("aarch64", "arm64"),
|
||||
AMD64("amd64", "x86_64");
|
||||
|
||||
override fun toString() = simpleName
|
||||
|
||||
companion object {
|
||||
fun fromName(name: String): Arch =
|
||||
when (name) {
|
||||
"aarch64" -> AARCH64
|
||||
"amd64" -> AMD64
|
||||
else -> throw IllegalArgumentException("Unknown arch: $name")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class OS(
|
||||
val simpleName: String,
|
||||
val sharedLibraryExtension: String,
|
||||
val staticLibraryExtension: String,
|
||||
val objectFileExtension: String,
|
||||
val displayName: String,
|
||||
) {
|
||||
MacOS(
|
||||
simpleName = "macos",
|
||||
sharedLibraryExtension = "dylib",
|
||||
staticLibraryExtension = "a",
|
||||
objectFileExtension = "o",
|
||||
displayName = "macOS",
|
||||
),
|
||||
Linux(
|
||||
simpleName = "linux",
|
||||
sharedLibraryExtension = "so",
|
||||
staticLibraryExtension = "a",
|
||||
objectFileExtension = "o",
|
||||
displayName = "Linux",
|
||||
),
|
||||
Windows(
|
||||
simpleName = "windows",
|
||||
sharedLibraryExtension = "dll",
|
||||
staticLibraryExtension = "lib",
|
||||
objectFileExtension = "obj",
|
||||
displayName = "Windows",
|
||||
);
|
||||
|
||||
override fun toString(): String = simpleName
|
||||
|
||||
val isWindows: Boolean
|
||||
get() = this == Windows
|
||||
|
||||
val isMacOS: Boolean
|
||||
get() = this == MacOS
|
||||
|
||||
val isLinux: Boolean
|
||||
get() = this == Linux
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* 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 com.diffplug.gradle.spotless.KotlinGradleExtension
|
||||
import org.gradle.accessors.dm.LibrariesForLibs
|
||||
|
||||
plugins { id("com.diffplug.spotless") }
|
||||
|
||||
val buildInfo = extensions.create<BuildInfo>("buildInfo", project)
|
||||
|
||||
configurations {
|
||||
val rejectedVersionSuffix = Regex("-alpha|-beta|-eap|-m|-rc|-snapshot", RegexOption.IGNORE_CASE)
|
||||
configureEach {
|
||||
resolutionStrategy {
|
||||
// forbid dependencies whose pom.xml's include version ranges, because this will lead to
|
||||
// unreproducible builds.
|
||||
|
||||
failOnDynamicVersions()
|
||||
componentSelection {
|
||||
all {
|
||||
if (rejectedVersionSuffix.containsMatchIn(candidate.version)) {
|
||||
reject(
|
||||
"Rejected dependency $candidate " +
|
||||
"because it has a prelease version suffix matching `$rejectedVersionSuffix`."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
javaCompiler = buildInfo.javaCompiler
|
||||
options.release = buildInfo.jvmTarget
|
||||
options.compilerArgs.add("-Xlint:unchecked")
|
||||
}
|
||||
|
||||
plugins.withType(IdeaPlugin::class).configureEach {
|
||||
val errorMessage =
|
||||
"Use IntelliJ Gradle import instead of running the `idea` task. See README for more information."
|
||||
|
||||
tasks.named("idea") { doFirst { throw GradleException(errorMessage) } }
|
||||
tasks.named("ideaModule") { doFirst { throw GradleException(errorMessage) } }
|
||||
if (project == rootProject) {
|
||||
tasks.named("ideaProject") { doFirst { throw GradleException(errorMessage) } }
|
||||
}
|
||||
}
|
||||
|
||||
plugins.withType(MavenPublishPlugin::class).configureEach {
|
||||
configure<PublishingExtension> {
|
||||
// CI builds pick up artifacts from this repo.
|
||||
// It's important that this repo is only declared once per project.
|
||||
repositories {
|
||||
maven {
|
||||
name = "projectLocal" // affects task names
|
||||
url = rootDir.resolve("build/m2").toURI()
|
||||
}
|
||||
}
|
||||
// use resolved/locked (e.g., `1.15`)
|
||||
// instead of declared (e.g., `1.+`)
|
||||
// dependency versions in generated POMs
|
||||
publications {
|
||||
withType(MavenPublication::class.java) {
|
||||
versionMapping { allVariants { fromResolutionResult() } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val allDependencies = tasks.register<DependencyReportTask>("allDependencies")
|
||||
|
||||
tasks.withType(Test::class).configureEach {
|
||||
System.getProperty("testReportsDir")?.let { reportsDir ->
|
||||
reports.junitXml.outputLocation.set(file(reportsDir).resolve(project.name).resolve(name))
|
||||
}
|
||||
debugOptions {
|
||||
enabled = System.getProperty("jvmdebug")?.toBoolean() ?: false
|
||||
host = "*"
|
||||
port = 5005
|
||||
suspend = true
|
||||
server = true
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaExec::class).configureEach {
|
||||
debugOptions {
|
||||
enabled = System.getProperty("jvmdebug")?.toBoolean() ?: false
|
||||
host = "*"
|
||||
port = 5005
|
||||
suspend = true
|
||||
server = true
|
||||
}
|
||||
}
|
||||
|
||||
// Version Catalog library symbols.
|
||||
private val libs = the<LibrariesForLibs>()
|
||||
|
||||
private val licenseHeaderFile by lazy {
|
||||
rootProject.file("build-logic/src/main/resources/license-header.star-block.txt")
|
||||
}
|
||||
|
||||
private fun KotlinGradleExtension.configureFormatter() {
|
||||
ktfmt(libs.versions.ktfmt.get()).googleStyle()
|
||||
licenseHeaderFile(licenseHeaderFile, "([a-zA-Z]|@file|//)")
|
||||
}
|
||||
|
||||
val originalRemoteName = System.getenv("PKL_ORIGINAL_REMOTE_NAME") ?: "origin"
|
||||
// if we're running against a release branch (or a PR targeted at one), use that branch for
|
||||
// ratcheting
|
||||
// these env vars are set by GitHub actions:
|
||||
// https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables
|
||||
val ratchetBranchName =
|
||||
(System.getenv("GITHUB_BASE_REF") ?: System.getenv("GITHUB_REF_NAME"))?.let {
|
||||
if (it.startsWith("release/")) it else null
|
||||
} ?: "main"
|
||||
|
||||
spotless {
|
||||
ratchetFrom = "$originalRemoteName/$ratchetBranchName"
|
||||
|
||||
val revertYearOnlyChangesStep =
|
||||
RevertYearOnlyChangesStep(rootProject.rootDir, ratchetFrom!!).create()
|
||||
|
||||
// When building root project, format build-logic files too.
|
||||
// We need this because build-logic is not a subproject of the root project, so a top-level
|
||||
// `spotlessApply` will not trigger `build-logic:spotlessApply`.
|
||||
if (project.path == rootProject.path) {
|
||||
kotlinGradle {
|
||||
configureFormatter()
|
||||
addStep(revertYearOnlyChangesStep)
|
||||
target("*.kts", "build-logic/*.kts", "build-logic/src/*/kotlin/**/*.kts")
|
||||
}
|
||||
kotlin {
|
||||
ktfmt(libs.versions.ktfmt.get()).googleStyle()
|
||||
target("build-logic/src/*/kotlin/**/*.kt")
|
||||
licenseHeaderFile(licenseHeaderFile)
|
||||
addStep(revertYearOnlyChangesStep)
|
||||
}
|
||||
} else {
|
||||
kotlinGradle {
|
||||
configureFormatter()
|
||||
addStep(revertYearOnlyChangesStep)
|
||||
target("*.kts")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.api.GradleException
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.kotlin.dsl.*
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
id("com.gradleup.shadow")
|
||||
id("pklJvmSourceBundle")
|
||||
}
|
||||
|
||||
// make fat Jar available to other subprojects
|
||||
val fatJarConfiguration: Configuration = configurations.create("fatJar")
|
||||
|
||||
val fatJarPublication: MavenPublication = publishing.publications.create<MavenPublication>("fatJar")
|
||||
|
||||
val relocations =
|
||||
mapOf(
|
||||
// pkl-core dependencies
|
||||
"org.organicdesign.fp." to "org.pkl.thirdparty.paguro.",
|
||||
"org.snakeyaml.engine." to "org.pkl.thirdparty.snakeyaml.engine.",
|
||||
"org.msgpack." to "org.pkl.thirdparty.msgpack.",
|
||||
"org.w3c.dom." to "org.pkl.thirdparty.w3c.dom.",
|
||||
"com.oracle.svm.core." to "org.pkl.thirdparty.svm.",
|
||||
|
||||
// pkl-cli dependencies
|
||||
"org.jline." to "org.pkl.thirdparty.jline.",
|
||||
"com.github.ajalt.clikt." to "org.pkl.thirdparty.clikt.",
|
||||
"com.github.ajalt.colormath." to "org.pkl.thirdparty.colormath.",
|
||||
"com.github.ajalt.mordant." to "org.pkl.thirdparty.mordant.",
|
||||
"com.sun.jna." to "org.pkl.thirdparty.jna.",
|
||||
"kotlin." to "org.pkl.thirdparty.kotlin.",
|
||||
"kotlinx." to "org.pkl.thirdparty.kotlinx.",
|
||||
"org.intellij." to "org.pkl.thirdparty.intellij.",
|
||||
"org.fusesource.jansi." to "org.pkl.thirdparty.jansi.",
|
||||
"org.fusesource.hawtjni." to "org.pkl.thirdparty.hawtjni.",
|
||||
|
||||
// pkl-doc dependencies
|
||||
"org.commonmark." to "org.pkl.thirdparty.commonmark.",
|
||||
"org.jetbrains." to "org.pkl.thirdparty.jetbrains.",
|
||||
"_COROUTINE." to "org.pkl.thirdparty.kotlinx._COROUTINE.",
|
||||
|
||||
// pkl-config-java dependencies
|
||||
"io.leangen.geantyref." to "org.pkl.thirdparty.geantyref.",
|
||||
|
||||
// pkl-codegen-java dependencies
|
||||
"com.palantir.javapoet." to "org.pkl.thirdparty.javapoet.",
|
||||
|
||||
// pkl-codegen-kotlin dependencies
|
||||
"com.squareup.kotlinpoet." to "org.pkl.thirdparty.kotlinpoet.",
|
||||
|
||||
// pkl-profiler dependencies
|
||||
"com.google.protobuf." to "org.pkl.thirdparty.com.google.protobuf.",
|
||||
"com.google.perftools." to "org.pkl.thirdparty.com.google.perftools.",
|
||||
"google.protobuf." to "org.pkl.thirdparty.google.protobuf.",
|
||||
)
|
||||
|
||||
for ((key, value) in relocations) {
|
||||
if (!key.endsWith(".")) {
|
||||
throw GradleException(
|
||||
"Invalid relocation `\"$key\" to \"$value\"`: `$key` should end with a dot"
|
||||
)
|
||||
}
|
||||
if (!value.endsWith(".")) {
|
||||
throw GradleException(
|
||||
"Invalid relocation `\"$key\" to \"$value\"`: `$value` should end with a dot"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val nonRelocations = listOf("com/oracle/truffle/", "org/graalvm/", "org/jspecify/")
|
||||
|
||||
tasks.shadowJar {
|
||||
inputs.property("relocations", relocations)
|
||||
|
||||
archiveClassifier.set(null as String?)
|
||||
|
||||
configurations = listOf(project.configurations.runtimeClasspath.get())
|
||||
|
||||
addMultiReleaseAttribute = true
|
||||
|
||||
// not required at runtime / fat JARs can't be used in native-image builds anyway
|
||||
exclude("org/pkl/cli/svm/**")
|
||||
|
||||
exclude("META-INF/maven/**")
|
||||
exclude("META-INF/upgrade/**")
|
||||
|
||||
exclude("DebugProbesKt.bin")
|
||||
|
||||
val info = project.extensions.getByType<BuildInfo>()
|
||||
val minimumJvmTarget = JavaVersion.toVersion(info.jvmTarget)
|
||||
|
||||
manifest.attributes(
|
||||
// Certain exports need to be added to the Java modulepath for Java 17 to work properly with
|
||||
// shaded JARs. See the following link for an explanation of this syntax:
|
||||
// https://bugs.openjdk.org/browse/JDK-8335225
|
||||
"Add-Exports" to info.jpmsExportsForJarManifest
|
||||
)
|
||||
|
||||
// effectively, this results in calls excluding:
|
||||
// `META-INF/versions/{18-25}/**`
|
||||
// at the time of this writing; multi-release JARs beyond JDK 21 break the current
|
||||
// version of the Shadow plugin, and aren't needed for Truffle's use by Pkl.
|
||||
JavaVersionRange.startingAt(JavaLanguageVersion.of(minimumJvmTarget.majorVersion.toInt() + 1))
|
||||
.forEach { exclude("META-INF/versions/${it.asInt()}/**") }
|
||||
|
||||
exclude("module-info.*")
|
||||
|
||||
for ((from, to) in relocations) {
|
||||
relocate(from, to)
|
||||
}
|
||||
|
||||
// necessary for service files to be adapted to relocation
|
||||
mergeServiceFiles()
|
||||
}
|
||||
|
||||
shadow { addShadowVariantIntoJavaComponent = false }
|
||||
|
||||
val testFatJar =
|
||||
tasks.register<Test>("testFatJar") {
|
||||
testClassesDirs = files(tasks.test.get().testClassesDirs)
|
||||
classpath =
|
||||
// compiled test classes
|
||||
sourceSets.test.get().output +
|
||||
// fat Jar
|
||||
tasks.shadowJar.get().outputs.files +
|
||||
// test-only dependencies
|
||||
// (test dependencies that are also main dependencies must already be contained in fat Jar;
|
||||
// to verify that, we don't want to include them here)
|
||||
(configurations.testRuntimeClasspath.get() - configurations.runtimeClasspath.get())
|
||||
}
|
||||
|
||||
tasks.check { dependsOn(testFatJar) }
|
||||
|
||||
val validateFatJar =
|
||||
tasks.register("validateFatJar") {
|
||||
val outputFile = layout.buildDirectory.file("validateFatJar/result.txt")
|
||||
inputs.files(tasks.shadowJar)
|
||||
inputs.property("nonRelocations", nonRelocations)
|
||||
outputs.file(outputFile)
|
||||
|
||||
doLast {
|
||||
val unshadowedFiles = mutableListOf<String>()
|
||||
zipTree(tasks.shadowJar.get().outputs.files.singleFile).visit {
|
||||
val fileDetails = this
|
||||
val path = fileDetails.relativePath.pathString
|
||||
if (
|
||||
!(fileDetails.isDirectory ||
|
||||
path.startsWith("org/pkl/") ||
|
||||
path.startsWith("META-INF/") ||
|
||||
nonRelocations.any { path.startsWith(it) })
|
||||
) {
|
||||
// don't throw exception inside `visit`
|
||||
// as this gives a misleading "Could not expand ZIP" error message
|
||||
unshadowedFiles.add(path)
|
||||
}
|
||||
}
|
||||
if (unshadowedFiles.isEmpty()) {
|
||||
outputFile.get().asFile.writeText("SUCCESS")
|
||||
} else {
|
||||
outputFile.get().asFile.writeText("FAILURE")
|
||||
throw GradleException("Found unshadowed files:\n" + unshadowedFiles.joinToString("\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.check { dependsOn(validateFatJar) }
|
||||
|
||||
val fatSourcesJar =
|
||||
tasks.register<MergeSourcesJars>("fatSourcesJar") {
|
||||
plugins.withId("pklJavaLibrary") { inputJars.from(tasks.named("sourcesJar")) }
|
||||
inputJars.from(configurations.named("firstPartySourcesJars"))
|
||||
inputJars.from(
|
||||
tasks.named<ResolveSourcesJars>("resolveSourcesJars").map { fileTree(it.outputDir) }
|
||||
)
|
||||
|
||||
mergedBinaryJars.from(tasks.shadowJar)
|
||||
relocatedPackages.set(relocations)
|
||||
outputJar.fileProvider(
|
||||
provider {
|
||||
file(tasks.shadowJar.get().archiveFile.get().asFile.path.replace(".jar", "-sources.jar"))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
artifacts { add("fatJar", tasks.shadowJar) }
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
named<MavenPublication>("fatJar") {
|
||||
from(components["shadow"])
|
||||
|
||||
// sources Jar is fat
|
||||
artifact(fatSourcesJar.flatMap { it.outputJar.asFile }) { classifier = "sources" }
|
||||
|
||||
plugins.withId("pklJavaLibrary") {
|
||||
val javadocJar = tasks.named<Jar>("javadocJar")
|
||||
// Javadoc Jar is not fat (didn't invest effort)
|
||||
artifact(javadocJar.flatMap { it.archiveFile }) { classifier = "javadoc" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* 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 de.undercouch.gradle.tasks.download.Download
|
||||
import de.undercouch.gradle.tasks.download.Verify
|
||||
|
||||
plugins { id("de.undercouch.download") }
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
// tries to minimize chance of corruption by download-to-temp-file-and-move
|
||||
val downloadGraalVmAarch64 =
|
||||
tasks.register<Download>("downloadGraalVmAarch64") {
|
||||
configureDownloadGraalVm(buildInfo.graalVmAarch64)
|
||||
}
|
||||
|
||||
val downloadGraalVmAmd64 =
|
||||
tasks.register<Download>("downloadGraalVmAmd64") {
|
||||
configureDownloadGraalVm(buildInfo.graalVmAmd64)
|
||||
}
|
||||
|
||||
fun Download.configureDownloadGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||
onlyIf { !graalvm.installDir.exists() }
|
||||
doLast { println("Downloaded GraalVm to ${graalvm.downloadFile}") }
|
||||
|
||||
src(graalvm.downloadUrl)
|
||||
dest(graalvm.downloadFile)
|
||||
overwrite(false)
|
||||
tempAndMove(true)
|
||||
}
|
||||
|
||||
val verifyGraalVmAarch64 =
|
||||
tasks.register<Verify>("verifyGraalVmAarch64") {
|
||||
configureVerifyGraalVm(buildInfo.graalVmAarch64)
|
||||
dependsOn(downloadGraalVmAarch64)
|
||||
}
|
||||
|
||||
val verifyGraalVmAmd64 =
|
||||
tasks.register<Verify>("verifyGraalVmAmd64") {
|
||||
configureVerifyGraalVm(buildInfo.graalVmAmd64)
|
||||
dependsOn(downloadGraalVmAmd64)
|
||||
}
|
||||
|
||||
fun Verify.configureVerifyGraalVm(graalvm: BuildInfo.GraalVm) {
|
||||
onlyIf { !graalvm.installDir.exists() }
|
||||
|
||||
src(graalvm.downloadFile)
|
||||
checksum(
|
||||
buildInfo.libs.findVersion("graalVmSha256-${graalvm.osName}-${graalvm.arch}").get().toString()
|
||||
)
|
||||
algorithm("SHA-256")
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
val installGraalVmAarch64 =
|
||||
tasks.register<InstallGraalVm>("installGraalVmAarch64") {
|
||||
dependsOn(verifyGraalVmAarch64)
|
||||
graalVm = buildInfo.graalVmAarch64
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
val installGraalVmAmd64 =
|
||||
tasks.register<InstallGraalVm>("installGraalVmAmd64") {
|
||||
dependsOn(verifyGraalVmAmd64)
|
||||
graalVm = buildInfo.graalVmAmd64
|
||||
}
|
||||
|
||||
// Picked up by GitHub Actions and uploaded as a build artifact
|
||||
tasks.withType<NativeImageBuild>().configureEach {
|
||||
compiledClassesFile =
|
||||
layout.buildDirectory.file(
|
||||
"compiled-classes/${project.name}-${project.version}-${buildInfo.targetMachine.targetName}.txt"
|
||||
)
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
plugins { base }
|
||||
|
||||
val htmlValidator = extensions.create<HtmlValidator>("htmlValidator", project)
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val validatorConfiguration: Configuration =
|
||||
configurations.create("validator") {
|
||||
resolutionStrategy.eachDependency {
|
||||
if (requested.group == "log4j" && requested.name == "log4j") {
|
||||
useTarget(buildInfo.libs.findLibrary("log4j12Api").get())
|
||||
because("mitigate critical security vulnerabilities")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
validatorConfiguration(buildInfo.libs.findLibrary("nuValidator").get()) {
|
||||
// remove unnecessary dependencies
|
||||
// (some of the requested versions don't even exist on Maven Central)
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-alpn-client")
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-continuation")
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-http")
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-security")
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-server")
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-servlets")
|
||||
exclude(group = "org.eclipse.jetty", module = "jetty-jakarta-servlet-api")
|
||||
exclude(group = "org.eclipse.jetty.toolchain")
|
||||
exclude(group = "javax.servlet")
|
||||
exclude(group = "org.apache.commons", module = "commons-fileupload2-core")
|
||||
exclude(group = "org.apache.commons", module = "commons-fileupload2-jakarta-servlet5")
|
||||
}
|
||||
}
|
||||
|
||||
val validateHtml =
|
||||
tasks.register<JavaExec>("validateHtml") {
|
||||
val resultFile = layout.buildDirectory.file("validateHtml/result.txt")
|
||||
inputs.files(htmlValidator.sources)
|
||||
outputs.file(resultFile)
|
||||
|
||||
classpath = validatorConfiguration
|
||||
mainClass.set("nu.validator.client.SimpleCommandLineValidator")
|
||||
args(
|
||||
"--skip-non-html"
|
||||
) // --also-check-css doesn't work (still checks css as html), so limit to html files
|
||||
args("--filterpattern", "(.*)Consider adding “lang=(.*)")
|
||||
args("--filterpattern", "(.*)Consider adding a “lang” attribute(.*)")
|
||||
args("--filterpattern", "(.*)unrecognized media “amzn-kf8”(.*)") // kindle
|
||||
// for debugging
|
||||
// args "--verbose"
|
||||
args(htmlValidator.sources)
|
||||
|
||||
// write a basic result file s.t. gradle can consider task up-to-date
|
||||
// writing a result file in case validation fails is not easily possible with JavaExec, but also
|
||||
// not strictly necessary
|
||||
doFirst { project.delete(resultFile) }
|
||||
doLast { resultFile.get().asFile.writeText("Success.") }
|
||||
}
|
||||
|
||||
tasks.check { dependsOn(validateHtml) }
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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 net.ltgt.gradle.errorprone.CheckSeverity
|
||||
import net.ltgt.gradle.errorprone.errorprone
|
||||
import net.ltgt.gradle.nullaway.nullaway
|
||||
import org.gradle.accessors.dm.LibrariesForLibs
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
id("net.ltgt.errorprone")
|
||||
id("net.ltgt.nullaway")
|
||||
}
|
||||
|
||||
val libs = the<LibrariesForLibs>()
|
||||
|
||||
dependencies {
|
||||
api(libs.jspecify)
|
||||
errorprone(libs.errorProne)
|
||||
errorprone(libs.nullaway)
|
||||
}
|
||||
|
||||
nullaway { onlyNullMarked = true }
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.errorprone.disableAllChecks = true
|
||||
options.errorprone.check("StringCaseLocaleUsage", CheckSeverity.ERROR)
|
||||
options.errorprone.check("GuardedBy", CheckSeverity.ERROR)
|
||||
options.errorprone.nullaway {
|
||||
error()
|
||||
onlyNullMarked = true
|
||||
jspecifyMode = true
|
||||
// honor assert x != null in addition to Objects.requireNonNull(x)
|
||||
assertsEnabled = true
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* 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 kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.writeText
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
|
||||
plugins {
|
||||
id("pklJavaLibrary")
|
||||
// id("pklPublishLibrary")
|
||||
id("com.gradleup.shadow")
|
||||
id("pklJvmSourceBundle")
|
||||
}
|
||||
|
||||
val executableSpec = project.extensions.create("executable", ExecutableSpec::class.java)
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val javaExecutable =
|
||||
tasks.register<ExecutableJar>("javaExecutable") {
|
||||
group = "build"
|
||||
dependsOn(tasks.jar)
|
||||
inJar = tasks.shadowJar.flatMap { it.archiveFile }
|
||||
val effectiveJavaName =
|
||||
executableSpec.javaName.map { name -> if (buildInfo.os.isWindows) "$name.bat" else name }
|
||||
outJar = layout.buildDirectory.dir("executable").flatMap { it.file(effectiveJavaName) }
|
||||
|
||||
// uncomment for debugging
|
||||
// jvmArgs.addAll("-ea", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")
|
||||
}
|
||||
|
||||
fun Task.setupTestStartJavaExecutable(launcher: Provider<JavaLauncher>? = null) {
|
||||
group = "verification"
|
||||
dependsOn(javaExecutable)
|
||||
|
||||
// dummy output to satisfy up-to-date check
|
||||
val outputFile = layout.buildDirectory.file("testStartJavaExecutable/$name")
|
||||
outputs.file(outputFile)
|
||||
|
||||
val execOutput = providers.exec {
|
||||
val executablePath = javaExecutable.get().outputs.files.singleFile
|
||||
if (launcher?.isPresent == true) {
|
||||
commandLine(
|
||||
launcher.get().executablePath.asFile.absolutePath,
|
||||
"-jar",
|
||||
executablePath.absolutePath,
|
||||
"--version",
|
||||
)
|
||||
} else {
|
||||
commandLine(executablePath.absolutePath, "--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 testStartJavaExecutable =
|
||||
tasks.register("testStartJavaExecutable") { setupTestStartJavaExecutable() }
|
||||
|
||||
// Setup `testStartJavaExecutable` tasks for multi-JDK testing.
|
||||
val testStartJavaExecutableOnOtherJdks =
|
||||
buildInfo.jdkTestRange.map { jdkTarget ->
|
||||
tasks.register("testStartJavaExecutableJdk${jdkTarget.asInt()}") {
|
||||
enabled = buildInfo.isVersionEnabled(jdkTarget)
|
||||
val toolChainService: JavaToolchainService = serviceOf()
|
||||
val launcher = toolChainService.launcherFor { languageVersion = jdkTarget }
|
||||
setupTestStartJavaExecutable(launcher)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.assemble { dependsOn(javaExecutable) }
|
||||
|
||||
tasks.check {
|
||||
dependsOn(testStartJavaExecutable)
|
||||
dependsOn(testStartJavaExecutableOnOtherJdks)
|
||||
}
|
||||
|
||||
// publishing {
|
||||
// publications {
|
||||
// // need to put in `afterEvaluate` because `artifactId` cannot be set lazily.
|
||||
// project.afterEvaluate {
|
||||
// register<MavenPublication>("javaExecutable") {
|
||||
// artifactId = executableSpec.javaPublicationName.get()
|
||||
//
|
||||
// artifact(javaExecutable.map { it.outputs.files.singleFile }) {
|
||||
// classifier = null
|
||||
// extension = "bin"
|
||||
// builtBy(javaExecutable)
|
||||
// }
|
||||
//
|
||||
// pom {
|
||||
// url = executableSpec.website
|
||||
// description =
|
||||
// executableSpec.documentationName.map { name ->
|
||||
// """
|
||||
// $name executable for Java.
|
||||
// Can be executed directly, or with `java -jar <path/to/jpkl>`.
|
||||
// Requires Java 17 or higher.
|
||||
// """
|
||||
// .trimIndent()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// signing { project.afterEvaluate { sign(publishing.publications["javaExecutable"]) } }
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@file:Suppress("HttpUrlsUsage", "unused")
|
||||
|
||||
import org.gradle.accessors.dm.LibrariesForLibs
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
`jvm-toolchains`
|
||||
`jvm-test-suite`
|
||||
id("pklKotlinTest")
|
||||
id("com.diffplug.spotless")
|
||||
}
|
||||
|
||||
// make sources Jar available to other subprojects
|
||||
val sourcesJarConfiguration: Provider<Configuration> = configurations.register("sourcesJar")
|
||||
|
||||
// Version Catalog library symbols.
|
||||
val libs = the<LibrariesForLibs>()
|
||||
|
||||
// Build configuration.
|
||||
val info = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
java {
|
||||
withSourcesJar() // creates `sourcesJar` task
|
||||
withJavadocJar()
|
||||
|
||||
toolchain {
|
||||
languageVersion = info.jdkToolchainVersion
|
||||
vendor = info.jdkVendor
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
// make sources Jar available to other subprojects
|
||||
add("sourcesJar", tasks["sourcesJar"])
|
||||
}
|
||||
|
||||
spotless {
|
||||
val revertYearOnlyChanges = RevertYearOnlyChangesStep(rootProject.rootDir, ratchetFrom!!).create()
|
||||
|
||||
java {
|
||||
addStep(revertYearOnlyChanges)
|
||||
googleJavaFormat(libs.versions.googleJavaFormat.get())
|
||||
target("src/*/java/**/*.java")
|
||||
licenseHeaderFile(
|
||||
rootProject.file("build-logic/src/main/resources/license-header.star-block.txt")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
manifest {
|
||||
attributes +=
|
||||
mapOf(
|
||||
"Automatic-Module-Name" to "org.${project.name.replace("-", ".")}",
|
||||
"Add-Exports" to info.jpmsExportsForJarManifest,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.javadoc {
|
||||
classpath = sourceSets.main.get().output + sourceSets.main.get().compileClasspath
|
||||
source = sourceSets.main.get().allJava
|
||||
title = "${project.name} ${project.version} API"
|
||||
(options as StandardJavadocDocletOptions).addStringOption("Xdoclint:none", "-quiet")
|
||||
}
|
||||
|
||||
val truffleJavacArgs =
|
||||
listOf(
|
||||
// TODO: determine correct limits for Truffle specializations
|
||||
// (see https://graalvm.slack.com/archives/CNQSB2DHD/p1712380902746829)
|
||||
"-Atruffle.dsl.SuppressWarnings=truffle-limit"
|
||||
)
|
||||
|
||||
tasks.compileJava {
|
||||
javaCompiler = info.javaCompiler
|
||||
options.compilerArgs.addAll(truffleJavacArgs + info.jpmsAddModulesFlags)
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
javaCompiler = info.javaCompiler
|
||||
options.release = info.jvmTarget
|
||||
}
|
||||
|
||||
tasks.withType<JavaExec>().configureEach { jvmArgs(info.jpmsAddModulesFlags) }
|
||||
|
||||
fun Test.configureJdkTestTask(launcher: Provider<JavaLauncher>) {
|
||||
useJUnitPlatform()
|
||||
javaLauncher = launcher
|
||||
systemProperties.putAll(info.testProperties)
|
||||
jvmArgs.addAll(info.jpmsAddModulesFlags)
|
||||
}
|
||||
|
||||
tasks.test { configureJdkTestTask(info.javaTestLauncher) }
|
||||
|
||||
// Prepare test tasks for each JDK version which is within the test target suite for Pkl. Each task
|
||||
// uses a pinned JDK toolchain version, and is named for the major version which is tested.
|
||||
//
|
||||
// Test tasks configured in this manner are executed manually by name, e.g. `./gradlew testJdk11`,
|
||||
// and automatically as dependencies of `check`.
|
||||
//
|
||||
// We omit the current JDK from this list because it is already tested, in effect, by the default
|
||||
// `test` task.
|
||||
//
|
||||
// Pkl subprojects may elect to further configure these tasks as needed; by default, each task
|
||||
// inherits the configuration of the default `test` task (aside from an overridden launcher).
|
||||
val jdkTestTasks = info.multiJdkTestingWith(tasks.test) { (_, jdk) -> configureJdkTestTask(jdk) }
|
||||
|
||||
tasks.check { dependsOn(jdkTestTasks) }
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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) }
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* 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.accessors.dm.LibrariesForLibs
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import org.gradle.kotlin.dsl.kotlin
|
||||
import org.gradle.kotlin.dsl.the
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
|
||||
plugins {
|
||||
java
|
||||
kotlin("jvm")
|
||||
id("com.diffplug.spotless")
|
||||
}
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val libs = the<LibrariesForLibs>()
|
||||
|
||||
kotlin {
|
||||
jvmToolchain {
|
||||
languageVersion.set(buildInfo.jdkToolchainVersion)
|
||||
vendor.set(buildInfo.jdkVendor)
|
||||
}
|
||||
compilerOptions {
|
||||
val kotlinTarget = KotlinVersion.fromVersion(libs.versions.kotlinTarget.get())
|
||||
languageVersion.set(kotlinTarget)
|
||||
apiVersion.set(kotlinTarget)
|
||||
jvmTarget = JvmTarget.fromTarget(buildInfo.jvmTarget.toString())
|
||||
freeCompilerArgs.addAll(
|
||||
"-jvm-default=no-compatibility", // was: -Xjvm-default=all
|
||||
"-Xjdk-release=${buildInfo.jvmTarget}",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
spotless {
|
||||
val revertYearOnlyChanges = RevertYearOnlyChangesStep(rootProject.rootDir, ratchetFrom!!).create()
|
||||
|
||||
kotlin {
|
||||
addStep(revertYearOnlyChanges)
|
||||
ktfmt(libs.versions.ktfmt.get()).googleStyle()
|
||||
target("src/*/kotlin/**/*.kt")
|
||||
licenseHeaderFile(
|
||||
rootProject.file("build-logic/src/main/resources/license-header.star-block.txt")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin modules to guard: fail the build if any dependency resolves to a version higher than
|
||||
* `libs.versions.kotlinTarget`. This includes versions introduced via direct declarations, BOMs,
|
||||
* version catalogs, or constraints.
|
||||
*/
|
||||
val guardedKotlinModules = setOf(libs.kotlinStdLib.get().module, libs.kotlinReflect.get().module)
|
||||
|
||||
/**
|
||||
* Classpath configurations where the above rule applies. Kept narrow to avoid interfering with
|
||||
* Gradle/Kotlin plugin internal configurations.
|
||||
*/
|
||||
val guardedConfigurations =
|
||||
setOf(
|
||||
configurations.compileClasspath,
|
||||
configurations.runtimeClasspath,
|
||||
configurations.testCompileClasspath,
|
||||
configurations.testRuntimeClasspath,
|
||||
)
|
||||
|
||||
guardedConfigurations.forEach { configuration ->
|
||||
configuration.configure {
|
||||
incoming.afterResolve {
|
||||
resolutionResult.allComponents.forEach { component ->
|
||||
val moduleVersion = component.moduleVersion ?: return@forEach
|
||||
if (
|
||||
moduleVersion.module in guardedKotlinModules &&
|
||||
moduleVersion.version.exceedsKotlinTarget()
|
||||
) {
|
||||
throw GradleException(
|
||||
"Resolved ${moduleVersion.module}:${moduleVersion.version} on configuration $name, " +
|
||||
"which exceeds the allowed Kotlin version ($kotlinTargetVersion)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// also works for version ranges like: [2.3.0,)
|
||||
val kotlinVersionRegex = Regex("""(\d+)\.(\d+)(?:\.\d+)?""")
|
||||
val kotlinTargetVersion = libs.versions.kotlinTarget.get()
|
||||
val targetMajor = kotlinTargetVersion.substringBefore('.').toInt()
|
||||
val targetMinor = kotlinTargetVersion.substringAfter('.').toInt()
|
||||
|
||||
fun String.exceedsKotlinTarget(): Boolean {
|
||||
val version =
|
||||
kotlinVersionRegex.find(this) ?: throw GradleException("Could not parse Kotlin version: $this")
|
||||
val major = version.groupValues[1].toInt()
|
||||
val minor = version.groupValues[2].toInt()
|
||||
return major > targetMajor || (major == targetMajor && minor > targetMinor)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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 org.gradle.accessors.dm.LibrariesForLibs
|
||||
|
||||
plugins { id("pklJavaLibrary") }
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val libs = the<LibrariesForLibs>()
|
||||
|
||||
dependencies {
|
||||
// Kotlin libraries typically expose stdlib types in their public APIs.
|
||||
// Therefore, the stdlib must be available on the consumer's compile classpath,
|
||||
// and "implementation" is not sufficient.
|
||||
api(libs.kotlinStdLib)
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* 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.net.URI
|
||||
import org.gradle.accessors.dm.LibrariesForLibs
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
|
||||
|
||||
plugins {
|
||||
`jvm-test-suite`
|
||||
id("pklKotlinBase")
|
||||
}
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
val libs = the<LibrariesForLibs>()
|
||||
|
||||
dependencies {
|
||||
testImplementation(libs.kotlinStdLib)
|
||||
|
||||
testImplementation(libs.assertj)
|
||||
testImplementation(libs.junitApi)
|
||||
testImplementation(libs.junitParams)
|
||||
|
||||
testRuntimeOnly(libs.junitEngine)
|
||||
testRuntimeOnly(libs.junitLauncher)
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
val testTask = this
|
||||
|
||||
useJUnitPlatform()
|
||||
|
||||
// enable checking of stdlib return types
|
||||
systemProperty("org.pkl.testMode", "true")
|
||||
|
||||
reports.named("html") { required = true }
|
||||
|
||||
testLogging { exceptionFormat = TestExceptionFormat.FULL }
|
||||
|
||||
addTestListener(
|
||||
object : TestListener {
|
||||
override fun beforeSuite(suite: TestDescriptor) {}
|
||||
|
||||
override fun beforeTest(testDescriptor: TestDescriptor) {}
|
||||
|
||||
override fun afterTest(testDescriptor: TestDescriptor, result: TestResult) {}
|
||||
|
||||
// print report link at end of task, not just at end of build
|
||||
override fun afterSuite(descriptor: TestDescriptor, result: TestResult) {
|
||||
if (descriptor.parent != null) return // only interested in overall result
|
||||
|
||||
if (result.resultType == TestResult.ResultType.FAILURE) {
|
||||
println(
|
||||
"\nThere were failing tests. See the report at: ${fixFileUri(testTask.reports.html.entryPoint.toURI())}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// makes links clickable on macOS
|
||||
private fun fixFileUri(uri: URI): URI {
|
||||
if ("file" == uri.scheme && !uri.schemeSpecificPart.startsWith("//")) {
|
||||
return URI.create("file://" + uri.schemeSpecificPart)
|
||||
}
|
||||
return uri
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
/*
|
||||
* 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("pklNativeSourceBundle")
|
||||
id("pklPublishLibrary")
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
// assumes that `pklJavaExecutable` is also applied
|
||||
val executableSpec = project.extensions.getByType<ExecutableSpec>()
|
||||
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 stagedLinuxAmd64Executable: Configuration = configurations.create("stagedLinuxAmd64Executable")
|
||||
val stagedLinuxAarch64Executable: Configuration =
|
||||
configurations.create("stagedLinuxAarch64Executable")
|
||||
val stagedAlpineLinuxAmd64Executable: Configuration =
|
||||
configurations.create("stagedAlpineLinuxAmd64Executable")
|
||||
val stagedWindowsAmd64Executable: Configuration =
|
||||
configurations.create("stagedWindowsAmd64Executable")
|
||||
|
||||
val nativeImageClasspath =
|
||||
configurations.create("nativeImageClasspath") {
|
||||
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(target: Target) =
|
||||
files(
|
||||
layout.buildDirectory.dir("executable").map { dir ->
|
||||
dir.file(
|
||||
executableSpec.name.map { name ->
|
||||
if (target.os.isWindows) "$name-${target.targetName}.exe"
|
||||
else "$name-${target.targetName}"
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
nativeImageClasspath(libs.truffleRuntime)
|
||||
nativeImageClasspath(libs.graalSdk)
|
||||
|
||||
stagedMacAarch64Executable(executableFile(Target.MacosAarch64))
|
||||
stagedLinuxAarch64Executable(executableFile(Target.LinuxAarch64))
|
||||
stagedLinuxAmd64Executable(executableFile(Target.LinuxAmd64))
|
||||
stagedAlpineLinuxAmd64Executable(executableFile(Target.AlpineLinuxAmd64))
|
||||
stagedWindowsAmd64Executable(executableFile(Target.WindowsAmd64))
|
||||
}
|
||||
|
||||
private fun NativeImageBuild.configure(target: Target) {
|
||||
arch = target.arch
|
||||
|
||||
outputName = executableSpec.name.map { "$it-${target.targetName}" }
|
||||
mainClass = executableSpec.mainClass
|
||||
|
||||
if (target.arch == Target.Arch.AARCH64) {
|
||||
dependsOn(":installGraalVmAarch64")
|
||||
} else {
|
||||
dependsOn(":installGraalVmAmd64")
|
||||
}
|
||||
|
||||
classpath.from(sourceSets.main.map { it.output })
|
||||
classpath.from(
|
||||
project(":pkl-commons-cli").extensions.getByType(SourceSetContainer::class)["svm"].output
|
||||
)
|
||||
classpath.from(nativeImageClasspath)
|
||||
}
|
||||
|
||||
val macExecutableAarch64 =
|
||||
tasks.register<NativeImageBuild>("macExecutableAarch64") { configure(Target.MacosAarch64) }
|
||||
|
||||
val linuxExecutableAmd64 =
|
||||
tasks.register<NativeImageBuild>("linuxExecutableAmd64") { configure(Target.LinuxAmd64) }
|
||||
|
||||
val linuxExecutableAarch64 =
|
||||
tasks.register<NativeImageBuild>("linuxExecutableAarch64") {
|
||||
configure(Target.LinuxAarch64)
|
||||
// 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 =
|
||||
tasks.register<NativeImageBuild>("alpineExecutableAmd64") {
|
||||
configure(Target.AlpineLinuxAmd64)
|
||||
extraNativeImageArgs.addAll("--static", "--libc=musl")
|
||||
}
|
||||
|
||||
val windowsExecutableAmd64 =
|
||||
tasks.register<NativeImageBuild>("windowsExecutableAmd64") {
|
||||
configure(Target.WindowsAmd64)
|
||||
extraNativeImageArgs.add("-Dfile.encoding=UTF-8")
|
||||
}
|
||||
|
||||
val assembleNative = tasks.named("assembleNative")
|
||||
|
||||
val testStartNativeExecutable =
|
||||
tasks.register("testStartNativeExecutable") {
|
||||
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 =
|
||||
tasks.register("checkGlibc") {
|
||||
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 = tasks.named("testNative") { dependsOn(testStartNativeExecutable, checkGlibc) }
|
||||
|
||||
val assembleNativeMacOsAarch64 =
|
||||
tasks.named("assembleNativeMacOsAarch64") { wraps(macExecutableAarch64) }
|
||||
|
||||
val assembleNativeLinuxAarch64 =
|
||||
tasks.named("assembleNativeLinuxAarch64") { wraps(linuxExecutableAarch64) }
|
||||
|
||||
val assembleNativeLinuxAmd64 =
|
||||
tasks.named("assembleNativeLinuxAmd64") { wraps(linuxExecutableAmd64) }
|
||||
|
||||
val assembleNativeAlpineLinuxAmd64 =
|
||||
tasks.named("assembleNativeAlpineLinuxAmd64") { wraps(alpineExecutableAmd64) }
|
||||
|
||||
val assembleNativeWindowsAmd64 =
|
||||
tasks.named("assembleNativeWindowsAmd64") { wraps(windowsExecutableAmd64) }
|
||||
|
||||
private fun MavenPublication.configurePublication(target: Target, configuration: Configuration) {
|
||||
artifactId = "${executableSpec.publicationName.get()}-${target.targetName}"
|
||||
pom {
|
||||
name = "${executableSpec.publicationName.get()}-${target.targetName}"
|
||||
url = executableSpec.website
|
||||
artifact(configuration.singleFile) {
|
||||
classifier = null
|
||||
extension = if (target.os.isWindows) "exe" else "bin"
|
||||
builtBy(configuration)
|
||||
}
|
||||
description =
|
||||
executableSpec.documentationName.map { name ->
|
||||
buildString {
|
||||
append("Native $name executable for ${target.os.displayName}/${target.arch}")
|
||||
if (target.musl) {
|
||||
append(" and statically linked to musl")
|
||||
}
|
||||
append(".")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
// need to put in `afterEvaluate` because `artifactId` cannot be set lazily.
|
||||
project.afterEvaluate {
|
||||
create<MavenPublication>("macExecutableAarch64") {
|
||||
configurePublication(Target.MacosAarch64, stagedMacAarch64Executable)
|
||||
}
|
||||
|
||||
create<MavenPublication>("linuxExecutableAmd64") {
|
||||
configurePublication(Target.LinuxAmd64, stagedLinuxAmd64Executable)
|
||||
}
|
||||
|
||||
create<MavenPublication>("linuxExecutableAarch64") {
|
||||
configurePublication(Target.LinuxAarch64, stagedLinuxAarch64Executable)
|
||||
}
|
||||
|
||||
create<MavenPublication>("alpineLinuxExecutableAmd64") {
|
||||
configurePublication(Target.AlpineLinuxAmd64, stagedAlpineLinuxAmd64Executable)
|
||||
}
|
||||
|
||||
create<MavenPublication>("windowsExecutableAmd64") {
|
||||
configurePublication(Target.WindowsAmd64, stagedWindowsAmd64Executable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
signing {
|
||||
project.afterEvaluate {
|
||||
sign(publishing.publications["linuxExecutableAarch64"])
|
||||
sign(publishing.publications["linuxExecutableAmd64"])
|
||||
sign(publishing.publications["macExecutableAarch64"])
|
||||
sign(publishing.publications["alpineLinuxExecutableAmd64"])
|
||||
sign(publishing.publications["windowsExecutableAmd64"])
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
val assembleNativeMacOsAarch64 = tasks.register("assembleNativeMacOsAarch64") { group = "build" }
|
||||
|
||||
val assembleNativeLinuxAarch64 = tasks.register("assembleNativeLinuxAarch64") { group = "build" }
|
||||
|
||||
val assembleNativeLinuxAmd64 = tasks.register("assembleNativeLinuxAmd64") { group = "build" }
|
||||
|
||||
val assembleNativeAlpineLinuxAmd64 =
|
||||
tasks.register("assembleNativeAlpineLinuxAmd64") { group = "build" }
|
||||
|
||||
val assembleNativeWindowsAmd64 = tasks.register("assembleNativeWindowsAmd64") { group = "build" }
|
||||
|
||||
val testNativeMacOsAarch64 = tasks.register("testNativeMacOsAarch64") { group = "verification" }
|
||||
|
||||
val testNativeLinuxAarch64 = tasks.register("testNativeLinuxAarch64") { group = "verification" }
|
||||
|
||||
val testNativeLinuxAmd64 = tasks.register("testNativeLinuxAmd64") { group = "verification" }
|
||||
|
||||
val testNativeAlpineLinuxAmd64 =
|
||||
tasks.register("testNativeAlpineLinuxAmd64") { group = "verification" }
|
||||
|
||||
val testNativeWindowsAmd64 = tasks.register("testNativeWindowsAmd64") { group = "verification" }
|
||||
|
||||
val buildInfo = project.extensions.getByType<BuildInfo>()
|
||||
|
||||
private fun <T : Task> Task.wraps(other: TaskProvider<T>) {
|
||||
dependsOn(other)
|
||||
outputs.files(other)
|
||||
}
|
||||
|
||||
val assembleNative =
|
||||
tasks.register("assembleNative") {
|
||||
group = "build"
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
if (!buildInfo.isCrossArchSupported && buildInfo.isCrossArch) {
|
||||
doLast {
|
||||
throw GradleException("Cross-arch builds are not supported on ${buildInfo.os.name}")
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
when (buildInfo.targetMachine) {
|
||||
Target.MacosAarch64 -> wraps(assembleNativeMacOsAarch64)
|
||||
Target.LinuxAarch64 -> wraps(assembleNativeLinuxAarch64)
|
||||
Target.LinuxAmd64 -> wraps(assembleNativeLinuxAmd64)
|
||||
Target.AlpineLinuxAmd64 -> wraps(assembleNativeAlpineLinuxAmd64)
|
||||
Target.WindowsAmd64 -> wraps(assembleNativeWindowsAmd64)
|
||||
}
|
||||
}
|
||||
|
||||
val testNative =
|
||||
tasks.register("testNative") {
|
||||
group = "verification"
|
||||
dependsOn(assembleNative)
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
if (!buildInfo.isCrossArchSupported && buildInfo.isCrossArch) {
|
||||
throw GradleException("Cross-arch builds are not supported on ${buildInfo.os.name}")
|
||||
}
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
when (buildInfo.targetMachine) {
|
||||
Target.MacosAarch64 -> wraps(testNativeMacOsAarch64)
|
||||
Target.LinuxAarch64 -> wraps(testNativeLinuxAarch64)
|
||||
Target.LinuxAmd64 -> wraps(testNativeLinuxAmd64)
|
||||
Target.AlpineLinuxAmd64 -> wraps(testNativeAlpineLinuxAmd64)
|
||||
Target.WindowsAmd64 -> wraps(testNativeWindowsAmd64)
|
||||
}
|
||||
}
|
||||
|
||||
val checkNative =
|
||||
tasks.register("checkNative") {
|
||||
group = "verification"
|
||||
dependsOn(testNative)
|
||||
}
|
||||
|
||||
val buildNative =
|
||||
tasks.register("buildNative") {
|
||||
group = "build"
|
||||
dependsOn(checkNative)
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
/*
|
||||
* 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")
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
plugins {
|
||||
`maven-publish`
|
||||
signing
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
components.findByName("java")?.let { javaComponent ->
|
||||
create<MavenPublication>("library") { from(javaComponent) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurePklPomMetadata()
|
||||
|
||||
configurePomValidation()
|
||||
|
||||
configurePklSigning()
|
||||
|
||||
artifacts {
|
||||
project.tasks.findByName("javadocJar")?.let { archives(it) }
|
||||
project.tasks.findByName("sourcesJar")?.let { archives(it) }
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* 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."
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
plugins { id("com.diffplug.spotless") }
|
||||
|
||||
val pklFormatter = configurations.create("pklFormatter")
|
||||
|
||||
dependencies { pklFormatter(rootProject.project("pkl-formatter")) }
|
||||
|
||||
spotless {
|
||||
format("pkl") {
|
||||
target("**/*.pkl")
|
||||
addStep(PklFormatterStep(pklFormatter).create())
|
||||
licenseHeaderFile(
|
||||
rootProject.file("build-logic/src/main/resources/license-header.line-comment.txt"),
|
||||
"/// ",
|
||||
)
|
||||
// disable ratcheting for Pkl sources
|
||||
// make any change to pkl-formatter reformat the stdlib
|
||||
ratchetFrom = null
|
||||
}
|
||||
}
|
||||
|
||||
for (taskName in
|
||||
listOf("spotlessPkl", "spotlessPklApply", "spotlessPklCheck", "spotlessPklDiagnose")) {
|
||||
tasks.named(taskName) { dependsOn(":pkl-formatter:assemble") }
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
::===----------------------------------------------------------------------===//
|
||||
:: Copyright © $YEAR 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.
|
||||
::===----------------------------------------------------------------------===//
|
||||
@@ -1,15 +0,0 @@
|
||||
#===----------------------------------------------------------------------===//
|
||||
# Copyright © $YEAR 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.
|
||||
#===----------------------------------------------------------------------===//
|
||||
+18
-31
@@ -1,27 +1,14 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
// https://youtrack.jetbrains.com/issue/KTIJ-19369
|
||||
@file:Suppress("DSL_SCOPE_VIOLATION")
|
||||
|
||||
import org.jetbrains.gradle.ext.ActionDelegationConfig
|
||||
import org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.PLATFORM
|
||||
import org.jetbrains.gradle.ext.ProjectSettings
|
||||
import org.jetbrains.gradle.ext.taskTriggers
|
||||
import org.jetbrains.gradle.ext.TaskTriggersConfig
|
||||
|
||||
plugins {
|
||||
id("pklAllProjects")
|
||||
id("pklGraalVm")
|
||||
pklAllProjects
|
||||
pklGraalVm
|
||||
|
||||
alias(libs.plugins.ideaExt)
|
||||
alias(libs.plugins.jmh) apply false
|
||||
@@ -31,15 +18,12 @@ plugins {
|
||||
nexusPublishing {
|
||||
repositories {
|
||||
sonatype {
|
||||
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
|
||||
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
|
||||
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
|
||||
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val configureLateInitAnnotation =
|
||||
tasks.register<ConfigureLateInitAnnotation>("configureLateInitAnnotation")
|
||||
|
||||
idea {
|
||||
project {
|
||||
this as ExtensionAware
|
||||
@@ -49,17 +33,22 @@ idea {
|
||||
delegateBuildRunToGradle = true
|
||||
testRunner = PLATFORM
|
||||
}
|
||||
taskTriggers.afterSync(configureLateInitAnnotation)
|
||||
configure<TaskTriggersConfig> {
|
||||
afterSync(provider { project(":pkl-core").tasks.named("makeIntelliJAntlrPluginHappy") })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val clean = tasks.named("clean") { delete(layout.buildDirectory) }
|
||||
val clean by tasks.registering(Delete::class) {
|
||||
delete(layout.buildDirectory)
|
||||
}
|
||||
|
||||
val printVersion = tasks.register("printVersion") { doFirst { println(buildInfo.pklVersion) } }
|
||||
val printVersion by tasks.registering {
|
||||
doFirst { println(buildInfo.pklVersion) }
|
||||
}
|
||||
|
||||
val message =
|
||||
"""
|
||||
val message = """
|
||||
====
|
||||
Gradle version : ${gradle.gradleVersion}
|
||||
Java version : ${System.getProperty("java.version")}
|
||||
@@ -74,7 +63,5 @@ Git Commit ID : ${buildInfo.commitId}
|
||||
====
|
||||
"""
|
||||
|
||||
val formattedMessage =
|
||||
message.replace("\n====", "\n" + "=".repeat(message.lines().maxByOrNull { it.length }!!.length))
|
||||
|
||||
val formattedMessage = message.replace("\n====", "\n" + "=".repeat(message.lines().maxByOrNull { it.length }!!.length))
|
||||
logger.info(formattedMessage)
|
||||
@@ -0,0 +1,33 @@
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.downloadTaskPlugin)
|
||||
implementation(libs.spotlessPlugin)
|
||||
implementation(libs.kotlinPlugin) {
|
||||
exclude(module = "kotlin-android-extensions")
|
||||
}
|
||||
implementation(libs.shadowPlugin)
|
||||
|
||||
// fix from the Gradle team: makes version catalog symbols available in build scripts
|
||||
// see here for more: https://github.com/gradle/gradle/issues/15383
|
||||
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlin {
|
||||
target {
|
||||
compilations.configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
|
||||
rootProject.name = "buildSrc"
|
||||
|
||||
pluginManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
// makes ~/.gradle/init.gradle unnecessary and ~/.gradle/gradle.properties optional
|
||||
dependencyResolutionManagement {
|
||||
// use same version catalog as main build
|
||||
versionCatalogs {
|
||||
register("libs") {
|
||||
from(files("../gradle/libs.versions.toml"))
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
import java.io.File
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.VersionCatalog
|
||||
import org.gradle.api.artifacts.VersionCatalogsExtension
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
|
||||
// `buildInfo` in main build scripts
|
||||
// `project.extensions.getByType<BuildInfo>()` in precompiled script plugins
|
||||
open class BuildInfo(project: Project) {
|
||||
inner class GraalVm(val arch: String) {
|
||||
val homeDir: String by lazy {
|
||||
System.getenv("GRAALVM_HOME") ?: "${System.getProperty("user.home")}/.graalvm"
|
||||
}
|
||||
|
||||
val version: String by lazy {
|
||||
libs.findVersion("graalVm").get().toString()
|
||||
}
|
||||
|
||||
val graalVmJdkVersion: String by lazy {
|
||||
libs.findVersion("graalVmJdkVersion").get().toString()
|
||||
}
|
||||
|
||||
val osName: String by lazy {
|
||||
when {
|
||||
os.isMacOsX -> "macos"
|
||||
os.isLinux -> "linux"
|
||||
os.isWindows -> "windows"
|
||||
else -> throw RuntimeException("${os.familyName} is not supported.")
|
||||
}
|
||||
}
|
||||
|
||||
val baseName: String by lazy {
|
||||
"graalvm-jdk-${graalVmJdkVersion}_${osName}-${arch}_bin"
|
||||
}
|
||||
|
||||
val downloadUrl: String by lazy {
|
||||
val jdkMajor = graalVmJdkVersion.takeWhile { it != '.' }
|
||||
val extension = if (os.isWindows) "zip" else "tar.gz"
|
||||
"https://download.oracle.com/graalvm/$jdkMajor/archive/$baseName.$extension"
|
||||
}
|
||||
|
||||
val installDir: File by lazy {
|
||||
File(homeDir, baseName)
|
||||
}
|
||||
|
||||
val baseDir: String by lazy {
|
||||
if (os.isMacOsX) "$installDir/Contents/Home" else installDir.toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same logic as [org.gradle.internal.os.OperatingSystem#arch], which is protected.
|
||||
*/
|
||||
val arch: String by lazy {
|
||||
when (val arch = System.getProperty("os.arch")) {
|
||||
"x86" -> "i386"
|
||||
"x86_64" -> "amd64"
|
||||
"powerpc" -> "ppc"
|
||||
else -> arch
|
||||
}
|
||||
}
|
||||
|
||||
val graalVmAarch64: GraalVm = GraalVm("aarch64")
|
||||
|
||||
val graalVmAmd64: GraalVm = GraalVm("x64")
|
||||
|
||||
val isCiBuild: Boolean by lazy {
|
||||
System.getenv("CI") != null
|
||||
}
|
||||
|
||||
val isReleaseBuild: Boolean by lazy {
|
||||
java.lang.Boolean.getBoolean("releaseBuild")
|
||||
}
|
||||
|
||||
val hasMuslToolchain: Boolean by lazy {
|
||||
// see "install musl" in .circleci/jobs/BuildNativeJob.pkl
|
||||
File(System.getProperty("user.home"), "staticdeps/bin/x86_64-linux-musl-gcc").exists()
|
||||
}
|
||||
|
||||
val os: org.gradle.internal.os.OperatingSystem by lazy {
|
||||
org.gradle.internal.os.OperatingSystem.current()
|
||||
}
|
||||
|
||||
// could be `commitId: Provider<String> = project.provider { ... }`
|
||||
val commitId: String by lazy {
|
||||
// only run command once per build invocation
|
||||
if (project === project.rootProject) {
|
||||
val process = ProcessBuilder()
|
||||
.command("git", "rev-parse", "--short", "HEAD")
|
||||
.directory(project.rootDir)
|
||||
.start()
|
||||
process.waitFor().also { exitCode ->
|
||||
if (exitCode == -1) throw RuntimeException(process.errorStream.reader().readText())
|
||||
}
|
||||
process.inputStream.reader().readText().trim()
|
||||
} else {
|
||||
project.rootProject.extensions.getByType(BuildInfo::class.java).commitId
|
||||
}
|
||||
}
|
||||
|
||||
val commitish: String by lazy {
|
||||
if (isReleaseBuild) project.version.toString() else commitId
|
||||
}
|
||||
|
||||
val pklVersion: String by lazy {
|
||||
if (isReleaseBuild) {
|
||||
project.version.toString()
|
||||
} else {
|
||||
project.version.toString().replace("-SNAPSHOT", "-dev+$commitId")
|
||||
}
|
||||
}
|
||||
|
||||
val pklVersionNonUnique: String by lazy {
|
||||
if (isReleaseBuild) {
|
||||
project.version.toString()
|
||||
} else {
|
||||
project.version.toString().replace("-SNAPSHOT", "-dev")
|
||||
}
|
||||
}
|
||||
|
||||
// https://melix.github.io/blog/2021/03/version-catalogs-faq.html#_but_how_can_i_use_the_catalog_in_em_plugins_em_defined_in_code_buildsrc_code
|
||||
val libs: VersionCatalog by lazy {
|
||||
project.extensions.getByType<VersionCatalogsExtension>().named("libs")
|
||||
}
|
||||
|
||||
init {
|
||||
if (!isReleaseBuild) {
|
||||
project.version = "${project.version}-SNAPSHOT"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
/**
|
||||
* Builds a self-contained Pkl CLI Jar that is directly executable on *nix
|
||||
* and executable with `java -jar` on Windows.
|
||||
*
|
||||
* For direct execution, the `java` command must be on the PATH.
|
||||
*
|
||||
* https://skife.org/java/unix/2011/06/20/really_executable_jars.html
|
||||
*/
|
||||
abstract class ExecutableJar : DefaultTask() {
|
||||
@get:InputFile
|
||||
abstract val inJar: RegularFileProperty
|
||||
|
||||
@get:OutputFile
|
||||
abstract val outJar: RegularFileProperty
|
||||
|
||||
@get:Input
|
||||
abstract val jvmArgs: ListProperty<String>
|
||||
|
||||
@TaskAction
|
||||
fun buildJar() {
|
||||
val inFile = inJar.get().asFile
|
||||
val outFile = outJar.get().asFile
|
||||
val escapedJvmArgs = jvmArgs.get().joinToString(separator = " ") { "\"$it\"" }
|
||||
val startScript = """
|
||||
#!/bin/sh
|
||||
exec java $escapedJvmArgs -jar $0 "$@"
|
||||
""".trimIndent() + "\n\n\n"
|
||||
outFile.outputStream().use { outStream ->
|
||||
startScript.byteInputStream().use { it.copyTo(outStream) }
|
||||
inFile.inputStream().use { it.copyTo(outStream) }
|
||||
}
|
||||
|
||||
// chmod a+x
|
||||
outFile.setExecutable(true, false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
open class GradlePluginTests {
|
||||
lateinit var minGradleVersion: GradleVersion
|
||||
lateinit var maxGradleVersion: GradleVersion
|
||||
var skippedGradleVersions: List<GradleVersion> = listOf()
|
||||
}
|
||||
+7
-27
@@ -1,21 +1,6 @@
|
||||
/*
|
||||
* 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 org.gradle.util.GradleVersion
|
||||
import groovy.json.JsonSlurper
|
||||
import java.net.URI
|
||||
import org.gradle.util.GradleVersion
|
||||
|
||||
@Suppress("unused")
|
||||
class GradleVersionInfo(json: Map<String, Any>) {
|
||||
@@ -53,19 +38,15 @@ class GradleVersionInfo(json: Map<String, Any>) {
|
||||
val wrapperChecksumUrl: String by json
|
||||
|
||||
companion object {
|
||||
private fun fetchAll(): List<GradleVersionInfo> =
|
||||
fetchMultiple("https://services.gradle.org/versions/all")
|
||||
private fun fetchAll(): List<GradleVersionInfo> = fetchMultiple("https://services.gradle.org/versions/all")
|
||||
|
||||
fun fetchReleases(): List<GradleVersionInfo> = fetchAll().filter { it.isReleaseVersion }
|
||||
|
||||
fun fetchCurrent(): GradleVersionInfo =
|
||||
fetchSingle("https://services.gradle.org/versions/current")
|
||||
fun fetchCurrent(): GradleVersionInfo = fetchSingle("https://services.gradle.org/versions/current")
|
||||
|
||||
fun fetchRc(): GradleVersionInfo? =
|
||||
fetchSingleOrNull("https://services.gradle.org/versions/release-candidate")
|
||||
fun fetchRc(): GradleVersionInfo? = fetchSingleOrNull("https://services.gradle.org/versions/release-candidate")
|
||||
|
||||
fun fetchNightly(): GradleVersionInfo =
|
||||
fetchSingle("https://services.gradle.org/versions/nightly")
|
||||
fun fetchNightly(): GradleVersionInfo = fetchSingle("https://services.gradle.org/versions/nightly")
|
||||
|
||||
private fun fetchSingle(url: String): GradleVersionInfo {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -80,9 +61,8 @@ class GradleVersionInfo(json: Map<String, Any>) {
|
||||
|
||||
private fun fetchMultiple(url: String): List<GradleVersionInfo> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (JsonSlurper().parse(URI(url).toURL()) as List<Map<String, Any>>).map {
|
||||
GradleVersionInfo(it)
|
||||
}
|
||||
return (JsonSlurper().parse(URI(url).toURL()) as List<Map<String, Any>>)
|
||||
.map { GradleVersionInfo(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
|
||||
open class HtmlValidator(project: Project) {
|
||||
var sources: FileCollection = project.files()
|
||||
}
|
||||
+14
-29
@@ -1,18 +1,3 @@
|
||||
/*
|
||||
* 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.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
@@ -30,18 +15,21 @@ import org.gradle.kotlin.dsl.listProperty
|
||||
import org.gradle.kotlin.dsl.mapProperty
|
||||
|
||||
open class MergeSourcesJars : DefaultTask() {
|
||||
@get:InputFiles val inputJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||
@get:InputFiles
|
||||
val inputJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||
|
||||
@get:InputFiles
|
||||
val mergedBinaryJars: ConfigurableFileCollection = project.objects.fileCollection()
|
||||
|
||||
@get:Input val relocatedPackages: MapProperty<String, String> = project.objects.mapProperty()
|
||||
@get:Input
|
||||
val relocatedPackages: MapProperty<String, String> = project.objects.mapProperty()
|
||||
|
||||
@get:Input
|
||||
var sourceFileExtensions: ListProperty<String> =
|
||||
project.objects.listProperty<String>().convention(listOf(".java", ".kt"))
|
||||
var sourceFileExtensions: ListProperty<String> = project.objects.listProperty<String>()
|
||||
.convention(listOf(".java", ".kt"))
|
||||
|
||||
@get:OutputFile val outputJar: RegularFileProperty = project.objects.fileProperty()
|
||||
@get:OutputFile
|
||||
val outputJar: RegularFileProperty = project.objects.fileProperty()
|
||||
|
||||
@TaskAction
|
||||
@Suppress("unused")
|
||||
@@ -50,15 +38,12 @@ open class MergeSourcesJars : DefaultTask() {
|
||||
|
||||
val relocatedPkgs = relocatedPackages.get()
|
||||
|
||||
val relocatedPaths =
|
||||
relocatedPkgs.entries.associate { (key, value) -> toPath(key) to toPath(value) }
|
||||
val relocatedPaths = relocatedPkgs.entries.associate { (key, value) -> toPath(key) to toPath(value) }
|
||||
|
||||
// use negative lookbehind to match any that don't precede with
|
||||
// a word or a period character. should catch most cases.
|
||||
val importPattern =
|
||||
Pattern.compile(
|
||||
"(?<!([\\w.]))(" + relocatedPkgs.keys.joinToString("|") { it.replace(".", "\\.") } + ")"
|
||||
)
|
||||
val importPattern = Pattern.compile("(?<!(\\w|\\.))(" +
|
||||
relocatedPkgs.keys.joinToString("|") { it.replace(".", "\\.") } + ")")
|
||||
|
||||
val sourceFileExts = sourceFileExtensions.get()
|
||||
|
||||
@@ -70,7 +55,7 @@ open class MergeSourcesJars : DefaultTask() {
|
||||
val details = this
|
||||
if (details.isDirectory) return@visit
|
||||
|
||||
var path = details.relativePath.parent!!.pathString
|
||||
var path = details.relativePath.parent.pathString
|
||||
val relocatedPath = relocatedPaths.keys.find { path.startsWith(it) }
|
||||
if (relocatedPath != null) {
|
||||
path = path.replace(relocatedPath, relocatedPaths.getValue(relocatedPath))
|
||||
@@ -101,7 +86,7 @@ open class MergeSourcesJars : DefaultTask() {
|
||||
project.zipTree(jar).visit {
|
||||
val details = this
|
||||
if (details.isDirectory) return@visit // avoid adding empty dirs
|
||||
result.add(details.relativePath.parent!!.pathString)
|
||||
result.add(details.relativePath.parent.pathString)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -111,7 +96,7 @@ open class MergeSourcesJars : DefaultTask() {
|
||||
relocatedPkgs: Map<String, String>,
|
||||
details: FileVisitDetails,
|
||||
sourceText: String,
|
||||
importPattern: Pattern,
|
||||
importPattern: Pattern
|
||||
): String {
|
||||
val matcher = importPattern.matcher(sourceText)
|
||||
val buffer = StringBuffer()
|
||||
@@ -0,0 +1,43 @@
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult
|
||||
import org.gradle.api.artifacts.result.ResolvedDependencyResult
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.jvm.JvmLibrary
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import org.gradle.language.base.artifact.SourcesArtifact
|
||||
|
||||
open class ResolveSourcesJars : DefaultTask() {
|
||||
@get:InputFiles
|
||||
val configuration: Property<Configuration> = project.objects.property()
|
||||
|
||||
@get:OutputDirectory
|
||||
val outputDir: DirectoryProperty = project.objects.directoryProperty()
|
||||
|
||||
@TaskAction
|
||||
@Suppress("UnstableApiUsage", "unused")
|
||||
fun resolve() {
|
||||
val componentIds = configuration.get().incoming.resolutionResult.allDependencies.map {
|
||||
(it as ResolvedDependencyResult).selected.id
|
||||
}
|
||||
|
||||
val resolutionResult = project.dependencies.createArtifactResolutionQuery()
|
||||
.forComponents(componentIds)
|
||||
.withArtifacts(JvmLibrary::class.java, SourcesArtifact::class.java)
|
||||
.execute()
|
||||
|
||||
val resolvedJars = resolutionResult.resolvedComponents
|
||||
.flatMap { it.getArtifacts(SourcesArtifact::class.java) }
|
||||
.map { (it as ResolvedArtifactResult).file }
|
||||
|
||||
// copying to an output dir because I don't know how else to describe task outputs
|
||||
project.sync {
|
||||
from(resolvedJars)
|
||||
into(outputDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 4249 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user