Skip to content

Using Native Packages

Native packages use the same @import(...) syntax as source modules, but the import resolves package metadata and a compiled shared library rather than a single .kel source file.

The math used below is the reference native package at packages/examples/math/ in the Kelvra runtime repository. ./build.sh builds it into the repository’s package output, which is why the bare "math" import can resolve when running examples from a source checkout.

const math = @import("math")
print(math.addI64(1i64, 2i64))
print(math.MEANING_OF_LIFE)
print(math.greet("Turing"))

package.api.kel is the public Kelvra-facing contract. The corresponding package.cpp implements and registers those functions and constants through the native package ABI.

Bare import names such as "math" resolve through package metadata. Canonical module paths such as "github.com/kelvralang/fs" resolve installed dependencies. Path-like imports such as "./math.kel" stay source-module imports.

The current interpreter searches for packages in:

  • build/packages relative to the interpreter binary
  • any roots passed with --package-path
  • packages/ relative to the importing source file or current working directory

You can add extra roots explicitly:

Terminal window
kelvra run --package-path /path/to/packages app.kel

Packages can expose opaque handle types through package.api.kel.

const counter = @import("counter")
const first counter.Counter = counter.create(10i64)
const second counter.Counter = counter.create(20i64)
print(counter.read(first))
print(counter.add(second, 5i64))

Those values are package-managed handles, but the type checker still tracks their package identity.

Native packages can ship package.api.kel for:

  • readable public signatures
  • editor navigation and hover docs
  • public opaque type declarations

The reference packages under packages/examples/ are the best examples in this repo.

Published native packages use the same dependency workflow as source packages, but installs may need to choose between a prebuilt artifact and a local source build.

Useful flags:

  • kelvra install --target <triple> to select a specific native target
  • kelvra install --prefer-prebuilt to stay on registry-published binaries when available
  • kelvra install --no-native-build to reject source fallback
  • kelvra install --cmake-toolchain <path> to allow non-host source-build fallback

When a registry entry only publishes source for the requested target, Kelvra records build_from_source = true and the selected target in kelvra.lock. Subsequent kelvra run --locked --target <triple> executions can reuse the cached install without rebuilding.

Validate a package directory against its manifest and compiled shared library:

Terminal window
kelvra validate-package packages/examples/math
kelvra validate-package packages/examples/counter

The current validator checks package ID syntax, reserved kelvra usage, manifest/ABI compatibility, registration metadata, and exported native signature parsing.