This introduces a rule that const properties cannot use the `this` type if that referenced type exceeds the scope.
This code is an error:
```pkl
const foo: this
```
This is not:
```pkl
const foo = new {
local myself: this
}
```
Additionally, this fixes:
* const depth logic to account for eager scopes
* behavior of `this` type inside custom this scopes
We reject any filepath that contains a `\` character;
all Pkl code must use `/` as the path separator.
So, we don't need to normalize `%5c` as a path sep on Windows.
This changes type argument syntax to "standard" style, and away from turbofish.
The motivation here is that turbofish-style type arguments are hard to read, and developers who are not already deeply knowledgeable about Pkl might struggle to understand such code.
In most languages, the grammar for "method call with type args" don't introduce any additional symbols between the identifier and the type argument list (e.g. C++, TypeScript, C#, Scala, Go).
This adds changes such that URIs like `file:///path/to/%2E%2E/bar.txt`
are considered path traversal sequences.
These URIs are treated as dot segments, and normalized prior to calling
into security checks.
For package URIs, the same treatment is applied to the
URI fragment.
jar-file URIs are special-cased and normalized as well.
Additionally, `%2f` is treated as `/` for file, jar-file and asset path segments.
However, these are left alone for other URIs (RFC-3986 treats `%2e` as identical to `.`, but `%2f` as distinct from `/`)..
* VmObject.getRootFirstObject() is a recursive call, which sometimes
fails with "too deep inlining"
* Incorrect loop condition profile usage in some places
* Need to mark `checkedReturnTypeNode` final so that GraalVM knows
that it is PE constant
Sometimes we see a thrown IllegalStateException when CPU profiling,
where the underlying cause is a ConcurrentModificationException in
the underlying GraalVM internals.
This attempts to minimize the chances of this exception being thrown
by starting proiling after the evaluator and its context have been
created.
Motivation:
- VmObjectLike.iterateMemberValues() is an internal iterator whose loop body is a Java lambda.
It suffers from the following limitations:
- `continue` and `break` cannot be used.
- `return` becomes an (awkward) replacement for `continue` and `break`.
It cannot be used to return from the enclosing method.
- Mutating variables requires hoisting them (MutableBoolean, etc.).
- Node.execute() calls are very slow because they are behind a Truffle boundary.
- Callers of iterateMemberValues() do not specify what and how they want to iterate.
This obscures the iteration code and makes it difficult (often impossible) to optimize.
Changes:
- Add interface VmObjectCursor, an external iterator that iterates over VmObject members.
Its design is inspired by org.graalvm.collections.MapCursor.
- Add VmObjectCursor implementations specialized for different members, VmObject subclasses, and cursor options.
- Replace VmObjectLike.iterateMemberValues() with the following methods that return VmObjectCursor:
- properties()
- properties(CursorOption)
- elements()
- elements(CursorOption)
- entries()
- entries(CursorOption)
- members
- members(CursorOption)
- Replace all usages of iterateMemberValues() with one of the above methods.
Before: object.iterateMembersValues((key, member, value) -> { if (member.isProp()) {...} });
After : for (var cursor = object.properties(); cursor.advance(); ) {...}
Result:
- Iteration code is much simpler and clearer.
- Iteration code that calls Node.execute() is much faster because it is no longer behind a Truffle boundary.
- Other iteration code is potentially faster and can be better optimized in the future.
Co-authored-by: translatenix <119817707+translatenix@users.noreply.github.com>
Co-authored-by: Jen Basch <jbasch94@gmail.com>
This introduces a way to run CPU profiling.
The profiler produces output in pprof format.
CLI users can enable CPU profiling via command line flags.
Profiling is otherwise not offered as an API.
Co-authored-by: Jen Basch <jbasch94@gmail.com>
Co-authored-by: Islon Scherer <islonscherer@gmail.com>
* Add tasks to generate source jars for java executables
* native source bundles
* source bundles in separate plugin
* Wire up sourceBundle task
* Produce bundles on a per-variant basis (Java fat jar, each native variant)
* Introduce `pklNativeSourceBundle` and `pklJvmSourceBundle` plugins for handling fat jar vs. GraalVM bits
* Download compiled classes list, and exclude Java sources for executable stuff specifically
* Include native sources when appropriate (GraalVM, JDK, zlib, musl, libpkl)
---------
Co-authored-by: Jen Basch <jbasch@apple.com>
This adds an option which allows users to control exactly how
`@ConfigurationProperties` annotations are attached to classes.
This helps when:
* Spring Boot users don't have a single root class, but multiple
classes that are injected in disparate places
* Pkl's module structure doesn't match the resulting `.properties`
layout
This changes it to render the qualified name instead of the simple name.
* Module classes render the module name
* Classes within module render the module name and the class name joined by `#`
* Rendering of members of `pkl:base` does not change
For example:
* `new k8s.core.v1.Service {}` instead of `new ModuleClass {}`.
* `new k8s.core.v1.Service#ServiceSpec {}` instead of `new ServiceSpec {}`
* `new pkl.Project {}` instead of `new ModuleClass {}`
This affects the following:
* `toString()`
* `trace()`
* Error messages
* REPL
Currently the module cache directory in CLI commands (and thus in Gradle tasks, since they use CLI commands under the hood) is only used for the "primary" task. For example, for an eval command, the module cache directory will be used for the evaluation of the target module.
However, most commands also work with projects, and for projects the `PklProject` file must be evaluated. This is done via `Project.loadFromPath`, which internally builds an evaluator with the default module cache path. Therefore, all evaluations of project manifests always use default cache path instead of whatever is configured through the CLI option/Gradle task property. This, in turn, may result in unexpected behavior: in general, the user would expect that if they specify the cache directory, it will be used for all evaluations (e.g. when they pre-populate the cache and expect evaluations to work offline).
The same is true for settings evaluation, although for settings it is significantly less important since settings scripts can't have remote dependencies.
This PR propagates cache path into the project evaluator (as well as the settings evaluator, for consistency). This will result in the user-specified cache directory being used for `PklProject` evaluations as well.
Patterns that originate from the language runtime will add
`Pattern.UNICODE_CHARACTER_CLASS | Pattern.UNICODE_CASE` as implicit
regex flags, so we need to do the same on the binary decoding side.
* Compute a derived regex expression with `\z` anchor
* Ensure derived regex can't be messed up with comments (in extended mode) or quote start
Follow up to #1880
This adds logic to UnresolvedTypeNode to create a `UnionOfStringLiterals`
type node if a member is a typealias who is a string or a string literal union.
Also, this fixes an issue where marking a duplicate string literal with the
default marker throws an index out of bounds exception.
This makes various improvements to help truffle do partial
evaluation of code related to typechecking.
* Split `UnionTypeNode` into `UnionTypeNodeExploded` and
`UnionTypeNodeLooped` to avoid gigantic graphs. This especially helps
in the case of typealiases, because they are inlined into their usage
sites.
* Move constraint-failure exception construction in
`TypeConstraintNode` behind `@TruffleBoundary` helper methods
instead of `transferToInterpreterAndInvalidate`, since building the
exception is a rare, off-hot-path operation.
* Move `ClassNode`'s one-time class-initialization logic behind a
`@TruffleBoundary` method (`initClass`), store `VmLanguage` as a
field instead of recomputing it via `VmLanguage.get(this)`, and use
`transferToInterpreterAndInvalidate` since class init never needs to
re-run on the compiled path.
* Pass `VmLanguage` explicitly into `TypeTestNode` and `ClassNode`
(via `AstBuilder`) rather than resolving it with
`VmLanguage.get(this)` on a hot path.
* Fix various issues where the partial evaluator determines that a frame
should have been materialized but was not.
* Pre-initialize call targets in `ObjectMember.setMemberNode()` and
`FunctionLiteralNode` so the first invocation doesn't trigger a
compilation invalidation.
* Fix truffle node tree issues (don't mark `@RootNode` as child,
deepCopy instead of passing an already adopted node).
* Remove unnecessary interpreter transfers when throwing type mismatch exceptions
This changes the `join` method in `List`/`Set`/`Listing` to
call the overridden `toString()` method.
This is a breaking change, but is considered a bugfix.
Fix this printed warning during java compilation:
"Note: Some input files use unchecked or unsafe operations. Recompile with -Xlint:unchecked for details"
* Add `-Xlint:unchecked` as a javac flag
* Fix the various warnings
This changes the logic for inferring `new {}` expressions in method
arguments to using regular frame slots, instead of auxiliary slots.
Overall, this is a performance improvement: no looking up auxiliary slot
numbers, which makes this code much more PE friendly.
* At parse time, get or create a frame slot that holds the method
* Introduce `ArgInfo` record (preserve primitive int) over using `Pair`
* Remove unneeded `isImplicitNewExpr` method; this is not needed because
we can just keep track of the method slot on the frame descriptor
builder.
This changes code so that the in-language `toString()` doesn't use
Java's `Object.toString()`.
Additionally, the existing `toString()` implementation is switched over
to using `VmValueRenderer`, which does not force (leaves `?` in place of
unforced values).
This helps improve ergonomics when working on the language (can enable
automatically calling `toString()` on debug values).
Additionally, external tools might call toString(); for example,
Truffle's compiler sometimes will stringify node fields (e.g.
when -Dengine.CompilationFailureAction=Throw) is set.
Fix invalid prefix when generating spring boot config
In Spring Boot, the prefix passed to `@ConfigurationProperties` must
be in "canonical form".
The presence of this annotation allows spring boot to directly inject
properties into a class, but is not actually needed.
The correct behavior here is to omit this annotation if the property
name does not match Spring Boot's canonical form.
* In GeneratorWhenNode, need to move individual iterations into their
own methods so that the @ExplodeLoop sees a constant number of
iterations whenever that method is called.
* In the other nodes, the lambda passed to
`forceAndIterateMemberValues` needs to capture the materialized frame,
not the virtual frame.
YamlEmitter only routed a string into YamlEscaper when it held a
character below 0x20, so 0x7F, the C1 block, U+2028 and U+2029 went out
as plain scalars. They are not `c-printable` (YAML 1.2 spec 5.1), and
NEL, LS and PS are line breaks in YAML 1.1, so the rendered document is
either rejected or silently split by a reader.
The escapes added in #1165 for 0x85, 0xA0, U+2028, and U+2029 could only
fire when some other character happened to open that gate. Share one
predicate between the two sites that decide, and give 0x7F-0x9F the
8-bit escape they lack.
This skips some unnecessary steps when evaluating annotations that
have no attached object bodies by returning an EmptyObjectLiteralNode
instead of a PropertiesLiteralNode
GraalVM's partial evaulator can't handle recursive calls into the same
node.
The current implementation around evaluating `VmNull` as a parent causes
the partial evaluator to bail out, leaving Pkl stuck in interpreter
mode.
This rewrites the various object literals to add individual
specializations for each type of default value we can see from a VmNull
parent.
Also:
* Fix `isTypeObjectClass` impl
* Fix bug when amending with generator object literal node with object params
The truffle compiler currently _always_ bails out of compilation for
`VmUtils.getFrame()` calls, because it determines that some branch
of this code can possibly return a materialized frame.
This adjusts the code so that the hot path (levelsUp == 0)
does not touch `VmUtils.getFrame()`, and avoids unnecessarily
materializing the frame.
This rewrites the listing/mapping typecast nodes to be more friendly
to partial-evaluation.
This is because the compiler bails out of deeply recursive calls.
This moves the protobuf module from experimental to deprecated
Rationale:
* This is very seldom used, if used at all
* Not fully fleshed out (this really should be paired with a protoc-gen-pkl, which doesn't exist)
* There is a ProtoJSON wire format that we can already render to
This changes logic that previously read/wrote from `~/.pkl` to use
XDG base directories (all OSes), and Known Folders locations on Windows.
For example, Pkl will look for `settings.pkl` in:
1. `$XDG_CONFIG_HOME/pkl/settings.pkl`
2. `%APPDATA/pkl/settings.pkl`
3. `~/.pkl/settings.pkl`
4. Path pkl/settings/pkl within `$XDG_CONFIG_DIRS`
5. `/etc/xdg/pkl/settings.pkl`
---------
Co-authored-by: Florin Ungur <florin@florinungur.com>
This adds a check that abstract members must be implemented.
If any members lack an implementation, an error is thrown describing
the missing members.
Co-authored-by: Dan Chao <dan.chao@apple.com>
This adds a `libpkl-static.pc` so pkg-config users can link either
statically or dynamically via `pkg-config --libs libpkl`, or
`pkg-config --libs libpkl-static`.
Additionally, this fixes an issue where the replace tokens wasn't
doing anything, leaving the `@version@` token intact in the archive.
Additionally, this adds an `-install_name` when building the dylib for macOS.
Co-authored-by: Islon Scherer <islonscherer@gmail.com>
* Fix possible SIGSEGV from host process.
- Require that the same `pkl_exec_t` be used in the same OS thread; returning meaningful error if this fails
* Remove `System.exitProcess(1)` logic in NativeTransport; this would kill the host process too and isn't an appropriate action for a received ProtocolException
* Allow multiple calls to pkl_init without pkl_close; this limitation doesn't really make any sense
* Prefer calling methods defined in graal_isolate.h, instead of creating the same method via CEntryPoint
* Add a CMakeLists.txt so that CLion can follow the code and provide proper diagnostics
* Improve doc comments; describe params as either in or out
This adds a new Antora module for libpkl, and updates the language
bindings documentation.
Co-authored-by: Jen Basch <jbasch94@gmail.com>
Co-authored-by: Islon Scherer <islonscherer@gmail.com>
This simplifies the resolution of names in typealias constraints.
This removes the existing logic around swapping out the frame's
owner/receiver, and instead favors resolving the variable at parse time.
* During variable resolution, create read variable nodes that read off of
a receiver node
* Introduce `GetTypeAliasModuleNode` that provides the typealias's
enclosing module
* Inject the enclosing module during typealias instantiation
The java-gradle-plugin already creates the pluginMaven publication. Applying the library publishing convention creates another publication with the same coordinates, causing an overwrite warning during Sonatype publishing.
Configure the shared POM metadata, validation, signing, and archive artifacts directly so pkl-gradle retains the convention behavior without creating the duplicate library publication.
Fixes#1742
* Fix issue where the DeployJob and GithubRelease jobs download
artifacts using a glob that only matches one artifact
* Make NativeImageBuild task only produce outputs as declared by build;
ensure there's no build_artifacts.txt, sources/ dir, etc.
This uses native-image to generate a C library for Pkl.
This generated library from native-image is wrapped with our own library,
in `pkl.h`.
This produces a static and a dynamic library for each os/arch variant
that Pkl currently supports.
Co-authored-by: Kushal Pisavadia <kushal.p@apple.com>
Co-authored-by: Jen Basch <jbasch94@gmail.com>
Co-authored-by: Islon Scherer <i_desouzascherer@apple.com>
The expression preamble length was subtracted from endColumn even
when endColumn came from the already-stripped sourceLine.length(),
so multi-line frames got a negative caret width and String.repeat
threw. Apply the offset only to the frame-derived columns.
---------
Co-authored-by: Dan Chao <dan.chao@apple.com>
When following redirects, `RequestRewritingClient` discarded each 3xx
response without closing its body, leaking the underlying connection.
Close the body as soon as we know the status is a redirect and won't
be returned, so the too-many-redirects, missing-`Location`,
invalid-URI and downgrade error paths all release the connection too.
This prevents leaking one `BodyHandlers.ofInputStream()` connection
per hop. Now the code closes the body before following the redirect.
This fixes a regression where local members cannot be seen by the
expression evaluator.
Because variable are now parse-time resolved, this builds a truffle node
by first constructing a synthetic module of all defined local members,
and calls AstBuilder on this synthetic module first.
This changes local asset path resolution so that `..` segments at the
dependency root just resolves to the dependency root.
This makes import resolution work the same between local and remote dependencies.
This changes the following:
1. If given a union type, the member must exist on each member of that type
2. If accessing a member off `Reference<D, Null>`, give a `Reference<D, Null>`
Also:
* Improve error messages thrown during member access.
* Add test around accessing members off of a function type
Stdlib modules are singletons that are shared across multiple evaluators.
This improves thread safety by evaluating its `output.bytes` during
initialization, which initializes truffle nodes (e.g. TypeTestNode),
and also initializes the member cache of the module output of `pkl:base`
This addresses many IDE warnings resulting from the switch to JSpecify.
Also, this changes the behavior of exporting VmObject; there's no place
in our code that does not force a VmObject prior to export, so
the existing logic around handling nullable values has been removed.
This adjusts the doc comments in ref.pkl
* Fix incorrect code snippets
* Clean up examples
* Remove some sections
* Make phrasing consistent with the rest of the stdlib
## What changed
This updates the GraalVM install task so Windows installs use ZIP extraction instead of the Unix tar path. Windows now publishes the extracted directory by moving it into place, while macOS and Linux keep the existing tar extraction and symlink-based install flow.
## Why
BuildInfo.GraalVm downloads .zip archives on Windows, but InstallGraalVm always ran tar --strip-components=1 -xzf and then tried to install by creating a symbolic link. That combination is fragile on Windows: the archive format does not match the extraction command, and symlink creation can require special privileges.
The changes made in this commit are good, but we're going to kick this out
to the next release.
This is because:
1. There's a couple more issues around the `abstract` modifier that is not
implemented yet, and need design considerations
2. These are breaking changes, and we want to minimize the amount of breakages
for users.
3. The main branch is still the develop branch for Pkl 0.32
We will apply a re-revert of this commit after Pkl 0.32 is released.
The eval task, unlike other tasks, creates the evaluator when the property is evaluated, not just when the task is executed (in the `getEffective*` properties). The problem here is that property evaluation can and will happen before the task is executed, because Gradle needs property values for caching and sometimes task dependency information.
Therefore, if due to misconfiguration or due to intentional configuration the evaluator cannot be created - for example, when the `PklProject` module doesn't exist, but the project directory is configured - then the task will fail with an exception which looks _very_ similar to a regular execution exception, but which actually is not, because it is thrown not during task execution, but during preparation for the execution.
This distinction matters a lot when you rely on conditional task execution. If you use the `onlyIf` predicate on tasks to define a condition for the task execution, this predicate will be evaluated before the task actions are run, but *after* properties are evaluated. Thus, if property evaluation fails with an exception, it will *look* as if the `onlyIf` predicate is completely ignored and not even evaluated, and the task action is run regardless of the predicate.
This error mode is extremely confusing and is actually wrong: if I use `onlyIf` to gate the task execution, I don't want *any* of its logic to run. In fact, in my case I specifically use `onlyIf` on the evaluation task to only execute it if a prerequisite is met, and the same predicate guards a bunch of other tasks which prepare the Pkl project, so my Pkl project isn't even generated if the predicate fails. But due to this behavior of properties evaluation which are not controlled by `onlyIf`, the project is still attempted to be evaluated, and this results in a very unexpected build failure.
The solution is to ignore the evaluation exception, because for all intents and purposes, if the project can't be properly evaluated, it will fail during the task execution as it should, so the values of output properties don't really matter as the task will never be run.
These methods aren't implemented in `Set`, and don't really make sense because `Set` types can't be accessed by index.
Note: although this removes methods, this actually isn't a breaking change:
1. Calling `Set.findIndex()` currently throws an error around "cannot invoke abstract method"
2. `List` and `Set` are the only subclasses of `Collection`.
The following code isn't breaking at runtime, although static analysis tooling (like our IDE plugins) will now flag this as an error:
```pkl
myCollection: Collection
idx = myCollection.indexOf(1)
```
Several `Facts:` examples in the `pkl:base` standard library docs assert
statements that are false when evaluated. Since these examples are not
run by any test, the mistakes went unnoticed and are rendered verbatim
into the generated API docs, where they mislead readers.
The corrected examples:
- `String.isNotBlank`: `"\t\n\r".isNotBlank` was listed as holding, but
a string of only whitespace is blank, so it is false. Negated it to
match the neighboring `!"".isNotBlank` and `!" ".isNotBlank` examples.
- `DataSize.toBinaryUnit` / `toDecimalUnit`: the `mb`/`mib` lines
mirrored the `kb`/`kib` lines, but the identity only holds for adjacent
units. `1024.kb == 1000.kib` (both 1,024,000 b), whereas `1024.mb` is
1,024,000,000 b and `1000.mib` is 1,048,576,000 b, so they are not
equal. There is no clean round-number equivalent at this magnitude, so I
removed the two false lines; the remaining examples still demonstrate
the conversion.
- `Collection.any`: `!List(1, 2, 3).any((n) -> n.isEven)` is false
because 2 is even. Changed the list to `List(1, 3, 5)` so the negation
holds.
- `IntSeq.end`: the example read `IntSeq(2, 5).start == 5`, which
documents the wrong property and is false (`start` is 2). Corrected it
to `IntSeq(2, 5).end == 5`.
- `List.isDistinctBy` / `distinctBy`: `List("a", "b", "abc")` is not
distinct by length, since `"a"` and `"b"` both have length 1. Switched
to `List("a", "bb", "ccc")` so the distinctness examples hold.
- `Map`: `Map(...).values` returns a `List`, not a `Set`. Corrected the
expected type.
I verified that each corrected example evaluates to `true`, and that the
neighboring examples I kept still pass, using the released Pkl 0.31.1
binary. The changes are confined to doc-comment text, so formatting is
unaffected.
---------
Signed-off-by: Aditya Singh <adisin650@gmail.com>
This makes various improvements to the handling of frame slot vars, and
includes some bug fixes introduced by
https://github.com/apple/pkl/pull/1622
* Refactor SymbolTable to track for-generator and parameter slots in
each scope
* Execute let expressions in their own root node in some places
* Unify how frame slots are managed; they are all represented as
`FrameSlotVariable`, created in `AstBuilder`, and passed into
`SymbolTable`.
* Fix how let expressions are executed in custom this scopes (introduce
a new root node when needed)
Fixes#1614.
## Context
A non-abstract `class` (or `module`) was allowed to declare `abstract`
properties and methods.
Because such an enclosing type is instantiable, an `abstract` member
there can never be guaranteed
an implementation — so the contradiction surfaced only as a runtime
error when the member was
accessed (`Cannot invoke abstract method`), or not at all.
This makes it a compile-time error to declare an `abstract` member
unless its enclosing class or
module is also `abstract`. This is consistent with how Pkl already
rejects instantiating an abstract
class, and mirrors how Java and Kotlin treat abstract members.
## Before
```pkl
class Foo {
abstract bar: Int
}
res = new Foo { bar = 5 } // evaluated successfully (should fail)
```
```pkl
class Foo {
abstract function bar(): Int
}
res = new Foo {} // evaluated successfully; res.bar() failed only at runtime
```
## After
```
–– Pkl Error ––
Cannot define an abstract member in a non-abstract class.
2 | abstract bar: Int
^^^^^^^^
at Foo
A member can only be `abstract` if its enclosing class is also `abstract`.
```
## Implementation
- `AstBuilder` now validates, while building the AST, that a
non-abstract class/module declares no
`abstract` members. The check runs in both `visitClass` and
`visitModule`, and the error points at
the `abstract` keyword.
- Adds the `abstractMemberInNonAbstractClass` error message.
## Scope: classes and modules
The issue describes classes; I applied the same rule to modules as well,
since a module is a class
in Pkl and a non-abstract module is likewise directly evaluatable. Happy
to narrow this to classes
only if you'd prefer — it's a one-line change either way.
The `moduleMethodModifiers` pkl-doc test fixture declared an abstract
method at non-abstract module
level (relying on the old behavior); it's updated to an `abstract
module`, and its expected
documentation output is regenerated.
## Tests
- New `LanguageSnippetTests` error cases: abstract property in a class,
abstract method in a class,
and abstract member in a module.
- `./gradlew build` passes (`pkl-core` and `pkl-doc` included).
---------
Co-authored-by: Vinayak <vinayak@vama.app>
Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
This implements HTTP redirect following ourselves.
The goal is:
1. All I/O is checked against `--allowed-resources` and
`--allowed-modules`, including HTTP redirects
2. HTTP rewrite rules can affect redirect following
3. HTTP headers can affect redirect following
---------
Co-authored-by: Islon Scherer <islonscherer@gmail.com>
This reverts the commits that enabled Gradle's configuration cache
feature.
IMO: this feature is too hard to use. We don't know if a task is valid
for the configuration cache until it runs, and it's very hard to tell if
something is safe when authoring Gradle code.
For example, our publish tasks are currently failing; I don't know how I
would fix this without running the publish task again on my dev machine.
Also, some of our build scripts become more brittle because of this; for
example, see
https://github.com/apple/pkl/blob/bb07589eae0b3195a589559a3245cbc12c29b394/build-logic/src/main/kotlin/BuildInfo.kt#L291-L296
The added snippet test originally produced error "A value of type
`Function2` cannot be exported."
This PR actually fixes the bug twice:
* By marking `ConvertProperty.render` as `hidden` so that it is skipped
when the enclosing object is exported. This broke any attempts to obtain
the module schema because this requires exporting all annotations on all
class properties.
* By changing the way that `VmUndefinedValueException.fillInHint()`
obtains the module URI to avoid obtaining the module schema (and
triggering the more expensive module schema generation process).
It also makes function-typed annotation properties in `pkl:Command` hidden to avoid similar issues there.
Bumps `shadowPlugin` from 9.4.1 to 9.4.2.
Updates `com.gradleup.shadow:com.gradleup.shadow.gradle.plugin` from
9.4.1 to 9.4.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/GradleUp/shadow/releases">com.gradleup.shadow:com.gradleup.shadow.gradle.plugin's
releases</a>.</em></p>
<blockquote>
<h2>9.4.2</h2>
<h3>Changed</h3>
<ul>
<li>Update jdependency to support Java 27. (<a
href="https://redirect.github.com/GradleUp/shadow/pull/2033">#2033</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/GradleUp/shadow/commit/29c432a7b6824b6fef23d46dc067e5c14112ff90"><code>29c432a</code></a>
Prepare version 9.4.2</li>
<li><a
href="https://github.com/GradleUp/shadow/commit/8aa8e6c1fb2ac0c17f0ff77e521cbe599cf64245"><code>8aa8e6c</code></a>
Update dependency org.vafer:jdependency to v2.16 (<a
href="https://redirect.github.com/GradleUp/shadow/issues/2033">#2033</a>)</li>
<li>See full diff in <a
href="https://github.com/GradleUp/shadow/compare/9.4.1...9.4.2">compare
view</a></li>
</ul>
</details>
<br />
Updates `com.gradleup.shadow` from 9.4.1 to 9.4.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/GradleUp/shadow/releases">com.gradleup.shadow's
releases</a>.</em></p>
<blockquote>
<h2>9.4.2</h2>
<h3>Changed</h3>
<ul>
<li>Update jdependency to support Java 27. (<a
href="https://redirect.github.com/GradleUp/shadow/pull/2033">#2033</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/GradleUp/shadow/commit/29c432a7b6824b6fef23d46dc067e5c14112ff90"><code>29c432a</code></a>
Prepare version 9.4.2</li>
<li><a
href="https://github.com/GradleUp/shadow/commit/8aa8e6c1fb2ac0c17f0ff77e521cbe599cf64245"><code>8aa8e6c</code></a>
Update dependency org.vafer:jdependency to v2.16 (<a
href="https://redirect.github.com/GradleUp/shadow/issues/2033">#2033</a>)</li>
<li>See full diff in <a
href="https://github.com/GradleUp/shadow/compare/9.4.1...9.4.2">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This introduces breaking changes for external readers are loaded:
1. In PklProject, relative paths are resolved relative to the enclosing
PklProject file (make behavior consistent with how other settings work)
2. Make CLI flags blow away any settings set on a PklProject
3. Introduce a new `workingDir` property, which defaults to the
PklProject dir
The overall goal is to make this behavior consistent with how other
settings work.
For example, relative paths for other evaluator settings are already
relative to the project directory.
Additionally, in every other case, CLI flags will overwrite any setting
set within PklProject.
Previously, `VmDynamic.isHiddenOrLocalProperty` didn't correctly
identify locals whose cache key is an `ObjectMember` instead of an
`Identifier`, causing `VmDynamic. getRegularMemberCount` to return an
incorrect value. This caused some renderers to produce incorrect output.
Resolves#1631
This introduces an optimization to write let expressions to frame slots
of the current frame, rather than transforming them into lambdas. As a
result, let expressions are _much_ faster to execute.
Fixes the following error:
```
A problem was found with the configuration of task ':pkl-core:sourcesJar' (type 'Jar').
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.
- Gradle detected a problem with the following location: '/home/runner/work/pkl/pkl/pkl-core/build/generated/sources/baseModuleMembers'.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
Reason: Task ':pkl-core:sourcesJar' uses this output of task ':pkl-core:generateBaseModuleMembers' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
For more on this, please refer to https://docs.gradle.org/9.5.1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
Possible solutions:
94 actionable tasks: 76 executed, 18 from cache
1. Declare task ':pkl-core:generateBaseModuleMembers' as an input of ':pkl-core:sourcesJar'.
2. Declare an explicit dependency on ':pkl-core:generateBaseModuleMembers' from ':pkl-core:sourcesJar' using Task#dependsOn.
3. Declare an explicit dependency on ':pkl-core:generateBaseModuleMembers' from ':pkl-core:sourcesJar' using Task#mustRunAfter.
```
This replaces `ResolveVariableNode` and `ResolveMethodNode` with their resolution.
When we build the truffle node tree, we determine whether names resolve to:
* lexical scope
* base module
* implicit this
Then, we use this information to directly construct the underlying nodes (`ReadPropertyNode`, `ReadLocalPropertyNode`, etc).
Additionally, `AstBuilder` determines whether the property access must be const or not.
This introduces a `BaseModuleMembers` registry, which gets generated as part of Java compilation.
Use Locale.ROOT to apply the lowecase format. For URI scheme and host
locale-neutral casing is the semantically the correct choice. Added a
unit test that sets the default locale to tr-TR and that would fail
without the fix.
- Remove single usage of @immutable without replacement
- Remove HttpClient's usages of @threadsafe without replacement
- Replace javax.annotation.concurrent.GuardedBy
with com.google.errorprone.annotations.concurrent.GuardedBy
Also:
- Remove redundant final modifiers from members of a final class
---------
Co-authored-by: odenix <self@odenix.org>
With JSpecify now a dependency of pkl-config-java, this moves the
non-null annotation to jspecify's.
This makes it simpler for users to do nullness checks, as tooling
already understands JSpecify nullness annotations.
* Relax forbidden headers constraints
- remove restriction on browser-related headers
- allow any glob pattern (no need to end with `/` or `*`, because glob
patterns already require users to explicitly declare prefix matches if
that's the intention)
* Replace `List<Pair<, ...>>`; use `Map<String, ...>` instead
* Use glob pattern strings as an API throughout, instead of `Pattern`
(e.g. in `HttpClientBuilder`)
* Add HTTP headers to message passing API
* Add HTTP headers to executor API (introduces `ExecutorSpiOptions4`)
* Add tests for Gradle, CLI, and pkl-executor invocations
* Improve documentation
* Add `isGlobPattern` API to class `String` for in-language validation
of http headers
* Behavior change: make sure explicitly configured `User-Agent` in
`HttpClientBuilder` can be shadowed by headers (allows users to set
`--http-header "**=User-Agent: My User Agent"` and for this to be the
only user agent).
CC @kyokuping
IntelliJ can understand that some annotations on fields mean that they
are implicitly initialized, which means we don't get the "field XXX is
not initialized" warning for `@LateInit` fields.
This setting, unfortunately, is recorded into `.idea/misc.xml`, which
contains a bunch of arbitrary stuff that we don't want to check into
source control
This adds some logic to touch up that file to mark `@LateInit` as
implicitly initialized fields, so we don't get any editor warnings.
Also, suppress some warnings.
Replace pkl-core's local nullness annotations with JSpecify annotations.
Enable NullAway checking for pkl-core packages except org.pkl.core.ast
and org.pkl.core.stdlib.
Notable code changes:
- Add a dedicated late-init constructor to VmTyped
- Move VmExceptionBuilder's fallback message derivation from withCause()
to build()
- Split VmException rendering between builder-provided messages and
string-backed messages
- Initialize MessageTransport handlers with default throwing handlers
- Update JSON helper collection types to allow nullable values JSON
arrays and objects can contain JSON null,
so the Java Map/List element types need to model nullable elements
explicitly
- Make public command transform APIs accept nullable transformed values
Command transforms can produce null for optional/default handling,
so the BiFunction and options-map element types now model that
explicitly
- Make ExecutorSpiException accept nullable message and cause
Existing call sites can pass nullable causes from Throwable.getCause()
- Remove JSR-305 semantics from `@LateInit`
JSpecify does not support the same type-qualifier-nickname pattern,
so `@LateInit` is now documentation plus a NullAway
constructor-initialization exemption
Out of scope:
- NullAway checking of org.pkl.core.ast and org.pkl.core.stdlib
- IntelliJ warnings related to `@LateInit` fields
- Removing the JSR-305 dependency, since concurrency annotations are
still in use
Motivation:
Config.as() causes nullness warnings when its result is intentionally assigned
to a non-null variable
Changes:
* Introduce Config.asNullable(Class<T>), asNullable(JavaType<T>), and
asNullable(Type) to explicitly opt into nullable values
* Keep the signatures of Config.as(Class<T>) and Config.as(JavaType<T>)
unchanged from 0.31 by adding @NullUnmarked
* This gives users time to migrate from as() to asNullable() where appropriate
* Avoids introducing new spurious warnings
* Change `<T> T Config.as(Type)` to `<T extends @nullable Object> T Config.as(Type)`
* This overload is typically used by reflective code such as
pkl-config-kotlin's Config.to() rather than directly by user code
* Clarify that JavaType<T> represents a non-null top-level type whose type arguments may be nullable
* Restricting <T> to non-null keeps method signatures understandable for humans and tools
* Enables full symmetry between Class<T> and JavaType<T> overloads in Config and JavaType
* Enables future non-null runtime checks in both Config.as() overloads
* Simplify construction of `JavaType`s with nullable type arguments
* Add ofNullable() variants for most factory methods, e.g., JavaType.listOfNullable()
* Overhaul Javadoc of Config and JavaType
Result:
* Clear separation between accessing nullable and non-null values
* Config.as() is used for the common non-null case
* Config.as() can perform non-null runtime checks in a future release (breaking change)
* More ergonomic construction of types with nullable type arguments
* More detailed and consistent documentation
* Fix error message when an invalid test reporter is supplied in Gradle
* Fix Gradle property name in docs
* Fix Gradle property name in tasks
* Introduce `TestReporter.default`, and use it in places where default
is applied
* Remove calls to `convention()`; this is not required because the input
is optional anyways.
When a docsite has only one package name and no DocsiteInfo.overview,
treat it like Javadoc's single-module output: redirect the top-level
index to the package page and omit the site-title breadcrumb segment
from generated pages.
Add src/test/files/SinglePackageTest fixtures to cover multiple package
versions, redirect behavior, breadcrumb behavior, and unchanged site
structure.
Also:
- Shut down Executor used in test.
- Declare expected output fixtures of DocGenerator as test inputs, not
outputs.
- Fix IntelliJ warning by using a Set for the right-hand side of
collection subtraction.
The version of local project dependencies should _always_ exactly match
up with what's declared in a PklProject.deps.json; any package in the
transitive dependency tree should always be delcaring the same import
too.
Closes#1591
run() now creates and closes a default Executor per call. This is fine
because there is no good reason to call this method multiple times.
run(Executor) now lets callers provide their own Executor, which is
customary for a well-behaved library.
Also: Fix IntelliJ warning by calling toSet()
Closes#1583
This omission, in particular, prevents Gradle plugins (which rely on CLI
classes) from adding custom resource readers via the service loading
mechanism. This change seems benign, especially since this is already
done for module key factories.
Power assertions only work when the source section is available. If it
is unavailable, power assertions throw a ParserError (unexpected EOF on
an empty input) when re-parsing the expression for presentation.
This change allows `PklProject` files, usually loaded via the `Project`
static methods, to have references to external packages via `package://`
URIs.
This is helpful for centralizing and sharing common package
configuration via packages.
ktfmt has much improved how it formats Kotlin code. Unfortunately, this
means that whenever we touch a single line in a Kotlin file, we get a
_lot_ more changes thanks to ratcheting now picking up this file for
formatting.
This PR just reformats every single Kotlin file so we don't have to deal
with this churn in future PRs that touch Kotlin code.
This is a quality-of-life improvement; make our build logs more easy to
read through for the default case.
If we need more information, we can click on the "Enable debug logging"
checkbox when re-running a job, which then populates the `runner.debug`
context variable.
Modern versions of Gradle support configuration caching
to prevent the gradual increase of project size to affect
the overall developer experience of Gradle builds. To
prepare the PKL project, and specificall pkl-gradle, for
configuration support, we introduce an integration test to
vet configuration cache rules, and then perform the necessary
updates to provide configuration cache support.
Motivation:
- `Config` mixes configuration representation with decoding logic
- `Config.fromPklBinary()` does not scale as decoding gains options
(e.g., binary versions or formats)
- The decoding API is inconsistent with `ConfigEvaluator`
Changes:
- Introduce `ConfigDecoder` (with builder) and move
`Config.fromPklBinary()` logic into it
- Deprecate `Config.fromPklBinary()` methods for removal
- Add `ConfigDecoder.forKotlin()` extension function
- Update and improve tests
Result:
- Decoding is separated from `Config` and exposed via a dedicated API
- Decoding can evolve independently (e.g., adding options such as binary
versions or supporting new formats)
- Evaluation and decoding APIs follow a consistent design
Dependabot currently does not update lockfiles in multi-module projects
(see https://github.com/dependabot/dependabot-core/issues/14633)
To work around this issue, we will simply remove our lockfiles, and
change our version catalog to use fully specified versions.
The removal of lockfiles introduces two issues:
1. It is less visible what our dependency graph is
2. Our builds are potentially non-reproducible
To work around this, two mitigations are in place:
1. Enable `failOnDynamicVersions()`, which causes Gradle to fail the
build if any dependencies declare a version range
2. Enable GitHub dependency submission, which provides insight into the
project SBOM
Fixes the following pom.xml issues:
1. pkl-doc and pkl-codegen-java sets the wrong dependency scopes for
pkl-commons-cli/pkl-base
2. pkl-config-kotlin sets the wrong dependency scope for
pkl-config-java-all
Closes#1293Closes#1517
This doesn't really make sense as part of the `Config` API.
We can maybe make class `ConfigUtils` public, but, I don't know how useful it
is anyways; it's more of an implementation detail.
Motivation:
buildSrc is a special-case legacy mechanism.
Gradle recommends using an included build named build-logic instead:
https://docs.gradle.org/current/userguide/best_practices_structuring_builds.html#favor_composite_builds
Changes:
- Rename buildSrc/ to build-logic/
- triggers reformatting
- Replace occurrences of "buildSrc" with "build-logic"
- Include the build-logic build in the main build (via
settings.gradle.kts)
- Apply convention plugins via plugin IDs instead of type-safe accessors
- small tradeoff compared to buildSrc
Result:
- Faster and more isolated builds
- Build logic behaves like a normal build, making it easier to evolve
and reason about
---------
Co-authored-by: Daniel Chao <dan.chao@apple.com>
- Enforce Kotlin version via resolution rule (replaces BOM)
- fail if kotlin-stdlib/kotlin-reflect exceed target version
- Replace kotlin-stdlib-jdk8 with kotlin-stdlib (jdk7/8 are now shims)
- Port pkl-core annotation processor to Java (with Codex)
- removes kotlin-stdlib from its compile classpath for better dependency
hygiene (Java module)
- Downgrade clikt for Kotlin 2.2 compatibility
- Upgrade kotlinx-serialization
---------
Co-authored-by: Daniel Chao <dan.chao@apple.com>
2026-04-15 09:02:42 -07:00
1739 changed files with 66360 additions and 19612 deletions
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
@@ -96,6 +93,14 @@ There is an IntelliJ plugin meant for development on the Pkl project itself loca
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/.github/[GitHub Actions] jobs like our https://github.com/apple/pkl/blob/main/.github/jobs/BuildNativeJob.pkl[BuildNativeJob.pkl], where we build Pkl automatically.
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
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.
@@ -46,7 +46,7 @@ The first slot of the array designates the value's type.
The remaining slots have fixed meanings depending on the type.
Additional slots may be added to types in future Pkl releases. Decoders *must* be designed to defensively discard values beyond the number of known slots for a type or provide meaningful error messages.
The array's length is the number of slots that are filled. For example, xref:{uri-stdlib-List}[List] is encoded as an MessagePack array with two elements.
The array's length is the number of slots that are filled. For example, link:{uri-stdlib-List}[List] is encoded as an MessagePack array with two elements.
|===
|Pkl type |Slot 1 2+|Slot 2 2+|Slot 3 2+|Slot 4
@@ -187,6 +187,15 @@ The array's length is the number of slots that are filled. For example, xref:{ur
|
|
|
|link:{uri-stdlib-ref-Reference}[Reference]
|`0x20`
|`<value>` (Typed)
|Domain
|`<value>`
|Data
|link:{uri-messagepack-array}[array]
|Array of link:{uri-stdlib-ref-Access}[`pkl.ref#Access`] values
@@ -7,7 +7,10 @@ Pkl can be embedded within any host application.
The host application has access to low level controls.
It is able to manage the lifecycle of evaluators, as well as provide custom modules and resources to Pkl.
Currently, Pkl must be embedded as a child process, by shelling out to the CLI using the xref:pkl-cli:index.adoc#command-server[`pkl server`] command. In the future, a C library will also be provided.
Pkl can be embedded in one of two ways:
. By spawning xref:pkl-cli:index.adoc#command-server[`pkl server`] as a subprocess, and communicating with it via STDIN/STDOUT.
. By linking to the xref:libpkl:index.adoc[libpkl library].
When embedded, communication between a host application and Pkl happens via message passing.
The message passing specification can be found in xref:message-passing-api.adoc[].
@@ -20,7 +23,7 @@ NOTE: Pkl's Java and Kotlin libraries binds to Pkl directly, and do not use mess
A language binding for Pkl should generally have the following components:
. A client that spawns `pkl server`, and talks to it using message passing.
. A client that either spawns `pkl server` or links to `libpkl`, and talks to it using message passing.
. A deserializer that turns xref:binary-encoding.adoc[pkl binary encoding] into a structure in the host language.
. A code generator that transforms Pkl schemas into schemas written in the host language.
The code generator is mostly written in Pkl, with a lightweight executable that acts as the glue layer.
Flag that indicates to generate config classes for use with Spring Boot.
====
.--spring-boot-configuration-properties
[%collapsible]
====
Default: (none) +
Example: `my.mod#Server=server` +
Explicitly configures which generated classes receive the Spring Boot `@ConfigurationProperties` annotation, and with what prefix.
Only applies if `--generate-spring-boot` is set.
The key is the Pkl class name (for example, `my.mod` for a module class, or `my.mod#Server` for a class within a module), and the value is the annotation's prefix.
An empty value generates a bare `@ConfigurationProperties` annotation.
If this option is omitted, the annotations are inferred from the structure of the input modules.
If this option is set, no annotations are inferred, and only the specified classes are annotated.
Repeat this option to define multiple mappings.
Values must be valid Spring Boot configuration properties prefixes.
@@ -360,7 +360,7 @@ at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/e4d8c882d/stdl
<6> What Pkl evaluated to discover the error.
When Pkl prints source locations, it also prints clickable links for easy access.
For local files, it generates a link for your development environment (https://pkl-lang.org/main/current/pkl-cli/index.html#settings-file[configurable in `+~/.pkl/settings.pkl+`]).
For local files, it generates a link for your development environment (https://pkl-lang.org/main/current/pkl-cli/index.html#settings-file[configurable in `+~/.config/pkl/settings.pkl+`]).
For packages imported from elsewhere, if available, Pkl produces `https://` links to their repository.
It is designed to be a low-level API that interacts with Pkl via the xref:bindings-specification:message-passing-api.adoc[message passing API].
It is meant to be paired with higher level logic written in a host language within the context of a Pkl language binding library.
The higher level logic deals with implementing the evaluator API, and serializing/deserializing messages according to the message passing API.
== Installing libpkl
Currently, we do not publish libpkl.
Therefore, libpkl needs to be built from source, by cloning this repository and running the steps laid out in <<build-from-source>>.
Once built, it can be <<linking-to-libpkl,linked against>>, either statically or dynamically.
[[linking-to-libpkl]]
== Linking to libpkl
It is possible to link to libpkl either as a static library or a dynamic library.
Statically linking to libpkl means that it is possible to copy libpkl's library code directly into your own library or executable at compile time, meaning that it is self-contained.
However, this impacts the binary size of your application, as libpkl's library files are around 100MB.
On the other hand, dynamically linking to libpkl has negligible impact on binary size, but requires that end users have libpkl installed on their OS.
=== Linking to the static vs. shared library
The simplest way to configure your compiler to link to either the static or the shared library is to use https://en.wikipedia.org/wiki/Pkg-config[pkg-config].
The libpkl library ships with two pkg-config files: `libpkl.pc`, and `libpkl-static.pc`.
The normal `libpkl.pc` links to the shared library.
To unambiguously link to the static library, use `libpkl-static.pc`.
For example, when using `cc`:
[source,shell]
----
# Link against the shared library
cc -o myprogram myprogram.c $(pkg-config --libs --cflags libpkl)
# Link against the static library
cc -o myprogram myprogram.c $(pkg-config --static --libs --cflags libpkl-static)
----
If libpkl is installed in a non-system directory, set `PKG_CONFIG_PATH` to the subpath `lib/pkgconfig` within the directory that contains libpkl. For example, given libpkl directory `/path/to/libpkl`, the environment variable should have `/path/to/libpkl/lib/pkgconfig`.
NOTE: Windows can use pkg-config through the https://www.msys2.org/docs/pkgconfig/[MSYS2 toolchain]. Using pkg-config on Windows implies compiling with gcc-style compiler like https://code.visualstudio.com/docs/cpp/config-mingw[MinGW], instead of MSVC.
[NOTE]
====
It's also possible to link to the static library with the normal `libpkl.pc`.
For example:
[source,shell]
----
cc -Wl,-Bstatic $(pkg-config --libs --cflags libpkl)
----
====
[[build-from-source]]
== Building libpkl from source
To build libpkl from source, the apple/pkl repository first must be cloned down to a host OS.
Build machine requirements:
* Java 21 or higher
* zlib
* C compiler
** `cc` (gcc, clang) toolchain on Unix
** MSVC toolchain on Windows
Example:
[source,shell]
----
git clone git@github.com:apple/pkl.git
cd pkl/
./gradlew libpkl:buildNative
----
This results in two directories of interest:
* `libpkl/build/distributions/`: directory containing archives (`.zip` on Windows, `.tar.gz` on macOS/Linux) of C libraries.
* `libpkl/build/native-libs/<os>-<arch>`: directory containing the built library files (the inner structure of the archive).
Cross-compilation is not supported.
=== Distribution layout
The built distribution archive contains both statically linked and dynamically linked binaries for each OS.
@@ -36,7 +34,7 @@ For interactive development, the CLI includes a Read-Eval-Print Loop (REPL).
The CLI comes in multiple flavors:
* Native macOS executable for amd64 (tested on macOS 10.15)
* Native macOS executable for aarch64 (tested on macOS 10.15)
* Native Linux executable for amd64
* Native Linux executable for aarch64
* Native Alpine Linux executable for amd64 (cross-compiled and tested on Oracle Linux 8)
@@ -140,8 +138,6 @@ Development and release versions can be downloaded and installed manually.
=== macOS Executable
On aarch64:
[source,shell]
[subs="+attributes"]
----
@@ -150,16 +146,6 @@ chmod +x pkl
./pkl --version
----
On amd64:
[source,shell]
[subs="+attributes"]
----
curl -L -o pkl '{uri-pkl-macos-amd64-download}'
chmod +x pkl
./pkl --version
----
This should print something similar to:
[source]
@@ -321,7 +307,7 @@ The default output renderer for a module supports the following formats:
* `pcf`
* `plist`
* `properties`
* `textproto`
* `textproto` (deprecated in Pkl 0.33)
* `xml`
* `yaml`
@@ -464,6 +450,24 @@ When enabled, type constraint failures will show intermediate values in the asse
Use `--no-power-assertions` to disable this feature if you prefer simpler output or better performance.
====
[[profile-cpu-output]]
.--profile-cpu-output
[%collapsible]
====
Default: (none) +
The file to write profiler output to. Omitting this option disables CPU profiling entirely. +
The CPU profiler writes output in https://github.com/google/pprof[pprof] format.
====
[[profile-cpu-sample-period]]
.--profile-cpu-sample-period
[%collapsible]
====
Default: 10 +
The sampling duration for the CPU sampler, in milliseconds.
====
This command also takes <<common-options, common options>>.
[[command-server]]
@@ -546,6 +550,15 @@ When enabled, test failures will show intermediate values in the assertion expre
Use `--no-power-assertions` to disable this feature if you prefer simpler output.
====
[[test-reporter]]
.--test-reporter
[%collapsible]
====
Default: `spec` +
Example: `--test-reporter minimal` +
Which test reporter to use for CLI output. Possible values are `spec` and `minimal`.
====
This command also takes <<common-options, common options>>.
[[command-run]]
@@ -667,6 +680,20 @@ Force generation of expected examples. +
The old expected files will be deleted if present.
====
.--test-reporter
[%collapsible]
====
Default: `spec` +
Example: `--test-reporter minimal` +
Which test reporter to use for CLI output. Possible values are `spec` and `minimal`.
====
.--install
[%collapsible]
====
Install the built package into the module cache dir.
====
This command also takes <<common-options,common options>>.
[[command-project-resolve]]
@@ -1368,14 +1395,24 @@ it works as follows:
The Pkl settings file allows to customize the CLI experience.
A settings file is a Pkl module amending the `pkl.settings` standard library module.
Its default location is `~/.pkl/settings.pkl`.
Unless configured explicitly, Pkl will look in the following locations:
. `$XDG_CONFIG_HOME/pkl/settings.pkl`
. `%APPDATA%/pkl/settings.pkl` (on Windows only)
. `~/.config/pkl/settings.pkl`
. Subdirectory `pkl/settings.pkl` within one of the paths described by `$XDG_CONFIG_DIRS`
. `/etc/xdg/pkl/settings.pkl`
. `~/.pkl/settings.pkl` (legacy location used by Pkl 0.32 and lower)
To use a different settings file, set the `--settings` command line option, for example `--settings mysettings.pkl`.
To enforce default settings, use `--settings pkl:settings`.
The settings file is also honored by (and configurable through) the Gradle plugin and `CliEvaluator` API.
Here is a typical settings file:
.~/.pkl/settings.pkl
.~/.config/pkl/settings.pkl
[source%parsed,{pkl}]
----
amends "pkl:settings" // <1>
@@ -1397,10 +1434,19 @@ When making TLS requests, Pkl comes with its own set of {uri-certificates}[CA ce
These certificates can be overridden via either of the two options:
- Set them directly via the CLI option `--ca-certificates <path>`.
- Add them to a directory at path `~/.pkl/cacerts/`.
- Add them to a user directory.
If CA certificates are not explicitly configured, Pkl will look in the following locations:
. `$XDG_CONFIG_HOME/pkl/cacerts`
. `%APPDATA%/pkl/cacerts` (on Windows only)
. `~/.config/pkl/cacerts`
. Subdirectory `pkl/cacerts` within one of the paths described by `$XDG_CONFIG_DIRS`
. `/etc/xdg/pkl/cacerts`
. `~/.pkl/cacerts` (legacy location used by Pkl 0.32 and lower)
Both these options will *replace* the default CA certificates bundled with Pkl. +
The CLI option takes precedence over the certificates in `~/.pkl/cacerts/`. +
The CLI option takes precedence over the certificates in the cacerts directory. +
Certificates need to be X.509 certificates in PEM format.
[[http-proxy]]
Loaded 100 of 1739 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.