packages
α1○ package-declaration○ project-structure◌ deps-fe (α2)◌ build-fe (α2)◌ content-addressing (β)◌ ferrule-lock (β)
packages
Package Declaration
In .fe source files, declare the package name only (no version):
package net.http;The content address (hash of source + derivation) is computed by build tools, not written in source.
project structure
| file | purpose |
|---|---|
deps.fe | dependencies (cli-editable, restricted format) |
build.fe | build configuration (full ferrule code, optional) |
ferrule.lock | locked content addresses |
src/main.fe | application entrypoint |
deps.fe (Dependency Declaration)
A restricted format that CLI tools can read and modify:
.{
.name = "my-app",
.version = "0.1.0",
.dependencies = .{
// registry shorthand
.http = .{ .pkg = "net/http", .version = "~> 1.2" },
.json = .{ .pkg = "data/json", .version = "^2.0" },
// direct URL with hash
.crypto = .{
.url = "https://github.com/ferrule/crypto/archive/v1.0.0.tar.gz",
.hash = "sha256:abc123..."
},
},
.dev_dependencies = .{
.testing = .{ .pkg = "std/testing", .version = "~> 1.0" },
},
}Version Specifiers
| Syntax | Meaning |
|---|---|
"1.2.3" | Exact version |
"~> 1.2" | Compatible with 1.2.x |
"^1.2" | Compatible with 1.x.x |
">= 1.0, < 2.0" | Range |
Dependency Sources
| Source | Syntax |
|---|---|
| Registry | .pkg = "namespace/name" |
| URL | .url = "https://...", .hash = "sha256:..." |
| Git | .git = "https://...", .rev = "..." |
| Local | .path = "../local-dep" |
build.fe (Build Configuration)
For complex builds, use full Ferrule code:
const build = @import("std/build");
const deps = @import("deps.fe");
pub function configure(b: build.Builder) -> Unit {
const exe = b.addExecutable(.{
.name = "my-app",
.root = "src/main.fe",
});
// add dependencies
exe.addDependency(deps.http);
exe.addDependency(deps.json);
// configure target
exe.setTarget(b.standardTargetOptions());
exe.setOptimize(b.standardOptimizeOption());
// custom build steps
if b.option("with-debug") {
exe.addDefine("DEBUG", "1");
}
}Most projects only need deps.fe. Use build.fe when you need:
- Custom build logic
- Conditional compilation
- Code generation
- Multiple build targets
Content Addressing
A package's content address is:
hash(source_tree + derivation)Properties:
- Computed automatically by
ferrule build - Stored in
ferrule.lock - Changing source, derivation, or dependencies produces a new address
- Artifacts embed provenance capsules (full derivation + dependency addresses)
Lockfile (ferrule.lock)
Pins exact content addresses:
# ferrule.lock — auto-generated, do not edit manually
[[package]]
name = "net/http"
version = "1.2.3"
hash = "sha256:2f7c84a93fb..."
source = "registry"
dependencies = ["sha256:a1b2c3..."]
[[package]]
name = "crypto"
version = "1.0.0"
hash = "sha256:def456..."
source = "https://github.com/ferrule/crypto/archive/v1.0.0.tar.gz"
dependencies = []Properties:
- Generated by
ferrule buildandferrule add - Committed to version control
- Human-readable but managed by tooling
- Ensures reproducible builds
Package Capabilities
Packages declare required capabilities:
// in deps.fe
.{
.name = "my-server",
.capabilities = .{ .fs, .net, .time },
.dependencies = .{
.http = .{
.pkg = "net/http",
.version = "~> 1.2",
.capabilities = .{ .net } // this dep needs net
},
},
}Build tool enforces capability requirements:
$ ferrule build
error: dependency 'net/http' requires capability [net]
Your project has not declared this capability.
Add to deps.fe:
.capabilities = .{ .net },Registry vs Direct URLs
Both are supported:
.dependencies = .{
// registry (convenient)
.http = .{ .pkg = "net/http", .version = "~> 1.2" },
// direct URL (no registry dependency)
.crypto = .{
.url = "https://...",
.hash = "sha256:..."
},
}Registry is a convenience layer; direct URLs always work.
Provenance
Build artifacts embed provenance information:
- Content address of the package
- Full dependency tree addresses
- Build tool versions
- Optional signatures
This enables verification of how any artifact was built.
CLI Commands
# create new project
ferrule new my-app
# add dependency (updates deps.fe and ferrule.lock)
ferrule add net/http
# add specific version
ferrule add net/http@1.2.3
# add from URL
ferrule add --url https://... --hash sha256:...
# update dependencies
ferrule update
# build
ferrule build
# run
ferrule runSummary
| File | Purpose | Editable |
|---|---|---|
deps.fe | Dependencies (restricted format) | CLI + manual |
build.fe | Build logic (full code) | Manual only |
ferrule.lock | Locked hashes | CLI only |