Packaging and Language Wrappers
Copperlace is implemented in Rust and exposed through native and language wrapper packages.
For the release operator checklist, see Copperlace release process.
Build Workflows
Use the root Makefile for normal development workflows:
make check
make package
make clean
make check runs Rust formatting checks plus Rust, Python, and Java tests.
make package builds distributable CLI/native, Python, JS/TS, and Java
artifacts for the current platform.
make clean removes generated Rust, Python, JS/TS, and Java build output.
Release Automation
GitHub Actions builds and smoke-tests packages for pull requests and pushes to
main. Version tags matching v* build the same package set, generate
SHA256SUMS, and publish assets to the GitHub Release for that tag.
The first-class native release targets are:
-
linux-x86_64 -
linux-aarch64 -
macos-x86_64 -
macos-aarch64 -
windows-x86_64
Windows aarch64 is not part of the first release matrix. Other platforms may still work from source when Rust, Python, Java, or Node tooling is available, but packaged native artifacts are not promised for them.
Release assets include:
-
platform CLI archives containing the
copperlacebinary and native library; -
Python wheels with the platform native library bundled under
copperlace/native/, plus a source distribution that can build the bundled Rust core from source; -
Java API, all-platform, and platform native JARs;
-
a JS/WASM package tarball generated from
wasm-pack --target bundler; -
SHA256SUMSfor uploaded release assets.
Use make release-check locally to verify Cargo, Python, and Maven versions
match before creating a release tag. Release tags should use the package version
prefixed with v, such as v0.1.1.
Rust Artifacts
The Rust package in rust-core/ builds:
-
an
rlibRust library; -
a
cdylibnative dynamic library; -
the
copperlaceCLI binary. -
a WebAssembly package when built with
wasm-pack.
make cli-archive builds the current-platform CLI release archive under
target/release-artifacts/.
The CLI supports:
copperlace render --config <path>
copperlace render -c <path> -r <name> --count <n> --set name=Mia
copperlace render -c <path> -r <object-rule> --compact-json
CLI rendering uses the builtin processor registry. If --rule is omitted, the
CLI renders origin. --count renders multiple outputs from one loaded config.
--set key=value provides initial context values for each render and may be
repeated; duplicate keys use the last value.
The CLI infers output mode from the selected rule shape. String-valued and
list-valued rules render as text. Object-valued rules render as structured JSON,
formatted with tabs by default. Use --compact-json for compact JSON; with
--count --compact-json, the CLI writes one compact JSON value per line.
C ABI
The native dynamic library exposes an opaque ruleset handle API:
-
copperlace_ruleset_from_file -
copperlace_ruleset_from_file_with_processors -
copperlace_ruleset_from_string -
copperlace_ruleset_from_string_with_processors -
copperlace_ruleset_render -
copperlace_ruleset_render_with_context -
copperlace_ruleset_render_structured_json -
copperlace_ruleset_render_structured_json_with_context -
copperlace_processor_result_set_output -
copperlace_processor_result_set_error -
copperlace_ruleset_free -
copperlace_string_free
Returned strings are allocated by Copperlace and must be released with
copperlace_string_free. Ruleset handles must be released with
copperlace_ruleset_free.
Custom processor callbacks must remain valid until the ruleset handle is freed.
Python Wrapper
The Python package in python/ uses ctypes over the C ABI. Public entry
points are:
-
Copperlace.from_string(config, processors=None) -
Copperlace.from_file(path, processors=None) -
Copperlace.render(rule, context=None) -
Copperlace.render_inferred(rule, context=None) -
Copperlace.render_structured(rule, context=None) -
RuleSet.from_string(config, processors=None) -
RuleSet.from_file(path, processors=None) -
RuleSet.render(rule, context=None) -
RuleSet.render_inferred(rule, context=None) -
RuleSet.render_structured(rule, context=None) -
render_str(config, rule, context=None, processors=None) -
render_file(path, rule, context=None, processors=None) -
render_str_inferred(config, rule, context=None, processors=None) -
render_file_inferred(path, rule, context=None, processors=None) -
render_str_structured(config, rule, context=None, processors=None) -
render_file_structured(path, rule, context=None, processors=None)
Copperlace is the recommended load-once API for repeated renders. Copperlace
and RuleSet are context managers and release the native handle when closed.
Wrapper failures are raised as CopperlaceError.
The wheel build compiles rust-core and bundles the platform native library
under copperlace/native/. Linux wheels are repaired with auditwheel before
publication so they use PyPI-compatible platform tags. The source distribution
includes the Rust sources needed to build the native library from source.
PyPI releases publish:
-
platform wheels for Linux x86_64/aarch64, macOS x86_64/aarch64, and Windows x86_64;
-
one source distribution;
-
the same package version as Cargo, Java, and GitHub Release artifacts.
Python rendering uses the builtin processor registry plus any custom processor callbacks provided at construction time.
Python structured rendering is intentionally string-based. The wrapper keeps the Rust-to-Python boundary as rendering to text or structured JSON text instead of exposing a second structured value model. Inferred rendering also returns strings: normal text for string-valued and list-valued rules, or formatted JSON text for object-valued rules.
JS/TS WebAssembly Package
The JS/TS package in js/ is generated by wasm-pack from rust-core/.
Public entry points are:
-
new Copperlace(config) -
Copperlace.withProcessors(config, processors) -
Copperlace.render(rule) -
Copperlace.renderWithContext(rule, context) -
renderString(config, rule) -
renderStringWithContext(config, rule, context) -
renderStringWithProcessors(config, rule, processors) -
renderStringWithProcessorsAndContext(config, rule, processors, context)
Copperlace is the recommended load-once API for repeated renders in browser
apps. Browser callers should load rule text themselves, usually with fetch,
and pass the config string into Copperlace; file-path APIs are not exported to
WebAssembly.
Build the bundler-oriented package with:
make js-package
Build a direct browser ES module package with:
make js-web
Both commands write generated output to js/pkg/, which is a build artifact.
JS/TS rendering uses the builtin processor registry plus any custom processor
functions provided at construction time.
Java Wrapper
The Java module in java/ uses Java FFM over the C ABI. The simplest Maven
Central dependency is dev.mahe.copperlace:copperlace, which depends on the
Java API plus all first-class supported native platform artifacts.
<dependency>
<groupId>dev.mahe.copperlace</groupId>
<artifactId>copperlace</artifactId>
<version>0.1.1</version>
</dependency>
Gradle Kotlin DSL:
implementation("dev.mahe.copperlace:copperlace:0.1.1")
Applications that only want one runtime platform can depend on one platform artifact instead. Choose the runtime platform, not necessarily the build platform:
-
dev.mahe.copperlace:copperlace-linux-x86_64 -
dev.mahe.copperlace:copperlace-linux-aarch64 -
dev.mahe.copperlace:copperlace-macos-x86_64 -
dev.mahe.copperlace:copperlace-macos-aarch64 -
dev.mahe.copperlace:copperlace-windows-x86_64
Each platform artifact depends on dev.mahe.copperlace:copperlace-api
transitively. Advanced users can depend on copperlace-api directly when they
provide the native library through COPPERLACE_LIBRARY_PATH or source-tree
build output.
Public entry points are:
-
Copperlace.fromString(config) -
Copperlace.fromStringWithProcessors(config, processors) -
Copperlace.fromFile(path) -
Copperlace.fromFileWithProcessors(path, processors) -
Copperlace.render(rule) -
Copperlace.render(rule, context) -
Copperlace.renderInferred(rule) -
Copperlace.renderInferred(rule, context) -
Copperlace.renderStructuredJson(rule) -
Copperlace.renderStructuredJson(rule, formatJson) -
Copperlace.renderStructuredJson(rule, context) -
Copperlace.renderStructuredJson(rule, context, formatJson) -
Copperlace.renderString(config, rule) -
Copperlace.renderString(config, rule, context) -
Copperlace.renderStringInferred(config, rule) -
Copperlace.renderStringInferred(config, rule, context) -
Copperlace.renderStringStructuredJson(config, rule) -
Copperlace.renderStringStructuredJson(config, rule, formatJson) -
Copperlace.renderStringStructuredJson(config, rule, context) -
Copperlace.renderStringStructuredJson(config, rule, context, formatJson) -
Copperlace.renderStringWithProcessors(config, rule, processors) -
Copperlace.renderStringWithProcessors(config, rule, context, processors) -
Copperlace.renderFile(path, rule) -
Copperlace.renderFile(path, rule, context) -
Copperlace.renderFileInferred(path, rule) -
Copperlace.renderFileInferred(path, rule, context) -
Copperlace.renderFileStructuredJson(path, rule) -
Copperlace.renderFileStructuredJson(path, rule, formatJson) -
Copperlace.renderFileStructuredJson(path, rule, context) -
Copperlace.renderFileStructuredJson(path, rule, context, formatJson) -
Copperlace.renderFileWithProcessors(path, rule, processors) -
Copperlace.renderFileWithProcessors(path, rule, context, processors) -
RuleSet.fromString(config) -
RuleSet.fromStringWithProcessors(config, processors) -
RuleSet.fromFile(path) -
RuleSet.fromFileWithProcessors(path, processors) -
RuleSet.render(rule) -
RuleSet.render(rule, context) -
RuleSet.renderInferred(rule) -
RuleSet.renderInferred(rule, context) -
RuleSet.renderStructuredJson(rule) -
RuleSet.renderStructuredJson(rule, formatJson) -
RuleSet.renderStructuredJson(rule, context) -
RuleSet.renderStructuredJson(rule, context, formatJson)
Copperlace is the recommended load-once API for repeated renders. Copperlace
and RuleSet implement AutoCloseable; callers should use try-with-resources
or call close.
The Java API JAR contains only Java classes. Native binaries are packaged in
platform artifacts for linux-x86_64, linux-aarch64, macos-x86_64,
macos-aarch64, and windows-x86_64.
Plain Maven builds include the current-system native Java package by default
when the staged native library exists under
java/native-artifacts/<classifier>/. Maven does not compile the native
library; use make java-package to build Rust, stage the current native
library, and package the Java API plus current-platform native JAR. To build
only the Java API, run Maven with -pl api.
At runtime, the Java wrapper loads the native library in this order:
-
COPPERLACE_LIBRARY_PATH -
packaged classifier resource
-
local Rust build output for source-tree development
Java rendering uses the builtin processor registry plus any custom processor callbacks provided at construction time.
Java structured rendering is intentionally string-based. The Java wrapper keeps
the Rust-to-Java boundary as rendering to text or structured JSON text instead
of exposing a second structured value model. No-argument structured JSON
overloads return formatted JSON using tabs for indentation. The formatJson
parameter controls serialization: false returns compact JSON and true
returns formatted JSON. renderInferred also returns strings: normal text for
string-valued and list-valued rules, or formatted JSON text for object-valued
rules.