Skip to content

v0.7.0

Latest

Choose a tag to compare

@m3m0r7 m3m0r7 released this 28 Jun 06:12

A large step toward 1.0: a holistic schema redesign, a full layered refactor, new runtime/tooling features, and several codegen correctness fixes surfaced by a fresh Alpine Linux sweep.

⚠️ Breaking changes (no backward-compat — still beta)

The pnlx.json / pnl.json schema was redesigned so each key's meaning is clear, separating compile-time options from runtime options. JSON Schemas are frozen and date-versioned under schemas/<name>/2026-07-01/.

  • pnl.json features (runtime): use_functionsglobal_functions, allow_cdatacdata_arguments, use_php_scalars_in_params/return/constscalar_params/scalar_returns/scalar_constants.
  • pnl.json config: self_repository/packages_repositoryrelease_repository/package_repository; load_pathslibrary_paths.
  • pnlx.json: requiresnative_libraries; new compile_options{headers, definitions} (was top-level headers + require_definitions); new setup{build_script, install} (was self_build + installation); installation.<os>.installsetup.install.<os>.commands; checkIfExistscheck_if_exists.
  • lockfile / pathmap: requiresnative_libraries.
  • CLI flags renamed to match: --enable-global-functions, --enable-cdata-arguments, --enable-scalar-returns / --enable-scalar-constants.

Features

  • pnl doctor — diagnoses the toolchain: libclang (required), a C compiler, pkg-config, PHP + the FFI extension, and the workspace; exits non-zero on a required-check failure.
  • ftps native-library fetching — via suppaftp with native-tls (Security.framework on macOS, schannel on Windows, vendored OpenSSL on Linux, shared with git2).
  • Pnlx\FFI\Allocator + AllocationScope — allocate inside the extension's own FFI scope and pin allocations against premature GC (the common use-after-free), with a use-after-release guard.
  • Constraint-aware dependency resolution — a version a dependency pins that conflicts with an already-installed version is now reported, not silently mis-resolved.

Codegen correctness fixes

All four were surfaced by a fresh Alpine Linux (musl) docker sweep and verified there:

  • Case-colliding type files. A C struct tag and its typedef differing only in case (e.g. Argon2_Context / argon2_context) generated two PHP files declaring the same (case-insensitive) class — fatal on a case-sensitive filesystem, while on macOS the field-less wrapper silently won. They are now deduplicated, keeping the field-carrying wrapper.
  • Quoted-include sibling headers. A library whose API lives in headers included by the entry header (z3's z3_api.h, hdf5's H5public.h) was generating a silently empty binding. Headers pulled in via #include "..." are now treated as package-owned.
  • Typedef names eaten by macro neutralization. An all-uppercase typedef (gdbm's GDBM_FILE) matched the ABI-attribute-macro heuristic and was stubbed empty, truncating the pointer to int (a segfault at call time). Typedef names are now excluded from neutralization.
  • Struct-by-value arguments and returns. Structs passed or returned by value (quickjs's JSValue, gdbm's datum) were marshalled as pointers; the generated marshaller now passes and receives them by value.

Refactor & internals

  • Full layered module reorganization: util ← model ← {native, sources} ← codegen ← app (plus embed), with the largest god-files split apart.
  • Lints codified in Cargo.toml (-D warnings, clippy::all).
  • New conventions document at docs/{en,ja}/conventions.md.

Verification

Alpine 3.21 docker sweep across all packages: 172/180 install, 171/172 installed-package examples pass. The remainder are packages genuinely absent from Alpine repos, plus one macOS-only exported symbol (p11_kit_check_version).