hx uses lockfiles to ensure reproducible builds across machines and over time.
Why Lockfiles?
The Problem
Without lockfiles:
hx buildon Monday might useaeson-2.1.0hx buildon Tuesday might useaeson-2.2.0(newly released)- Builds break unexpectedly
- CI builds differ from local builds
The Solution
With lockfiles:
- All dependencies are pinned to exact versions
- Builds are reproducible indefinitely
- Updates are explicit and intentional
Creating a Lockfile
Generate hx.lock:
hx lockThis:
- Reads dependencies from your
.cabalfile - Resolves all transitive dependencies
- Pins to specific versions
- Records checksums for verification
- Writes
hx.lock
Lockfile Contents
hx.lock contains:
# Auto-generated by hx. Do not edit manually.
version = 1
generated = "2024-01-15T10:30:00Z"
hx_version = "0.4.0"
[toolchain]
ghc = "9.8.2"
cabal = "3.10.3.0"
[index]
hackage = "2024-01-15T00:00:00Z"
[[package]]
name = "aeson"
version = "2.1.2.1"
sha256 = "abc123..."
source = "hackage"
dependencies = ["base", "text", "containers"]
[[package]]
name = "text"
version = "2.0.2"
sha256 = "def456..."
source = "hackage"
dependencies = ["base", "bytestring"]Using the Lockfile
Sync Dependencies
Install the locked versions:
hx syncBuild with Locked Versions
Regular build commands use the lockfile automatically:
hx build # Uses versions from hx.lockUpdating Dependencies
Update All
hx lock --updateOr:
hx update
hx lockUpdate Specific Package
hx update aeson
hx lockCheck for Updates
hx outdatedLockfile Workflow
New Project
hx new my-project
cd my-project
hx lock # Create initial lockfile
git add hx.lock
git commit -m "Initial lockfile"Adding Dependencies
hx add text containers
hx lock # Update lockfile
git add hx.lock *.cabal
git commit -m "Add text and containers"Updating Dependencies
hx outdated # See what's outdated
hx update # Update to latest compatible
hx test # Verify everything works
git add hx.lock
git commit -m "Update dependencies"Cloning a Project
git clone https://github.com/example/project
cd project
hx sync # Install locked versions
hx buildVersion Control
Commit hx.lock
Always commit hx.lock:
git add hx.lock
git commit -m "Update dependencies"Never Gitignore
Do NOT add to .gitignore:
# Bad - don't do this!
hx.lockMerge Conflicts
If conflicts occur:
# Accept one version
git checkout --ours hx.lock
# Regenerate
hx lock
# Commit
git add hx.lock
git commitCI Integration
Verify Lockfile
Ensure lockfile is up-to-date:
- name: Verify lockfile
run: hx lock --checkFrozen Builds
Fail if lockfile would change:
- name: Build (frozen)
run: |
hx lock --frozen
hx buildComplete CI Example
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup hx
run: curl -fsSL https://get.arcanist.sh/hx | sh
- name: Verify lockfile
run: hx lock --frozen
- name: Sync dependencies
run: hx sync
- name: Build
run: hx build
- name: Test
run: hx testLockfile Strategies
Configure in hx.toml:
[dependencies]
lock-strategy = "hx" # or "cabal-freeze"hx (Default)
Uses hx’s TOML lockfile format.
Advantages:
- Human-readable
- Includes checksums
- Toolchain pinning
- Better merge conflict handling
cabal-freeze
Uses cabal.project.freeze for compatibility.
Advantages:
- Works with plain Cabal
- No hx dependency in CI
- Familiar to Cabal users
Index State
Pin the Hackage index state for extra reproducibility:
[dependencies]
index-state = "2024-01-15T00:00:00Z"This ensures the same packages are available even if newer ones are uploaded.
Offline Builds
With a lockfile, build offline:
# First, download all dependencies
hx sync
# Later, build offline
hx build --offlineTroubleshooting
Lockfile Out of Sync
error: hx.lock is out of sync with hx.toml
fix: Run `hx lock` to updateMissing Lockfile
warning: No hx.lock found. Builds may not be reproducible.
hint: Run `hx lock` to create a lockfileChecksum Mismatch
error: Package 'aeson-2.1.2.1' checksum mismatch
expected: abc123...
got: def456...
This may indicate:
- Corrupted download
- Package replaced on Hackage (rare)
fix: Run `hx lock --force` to regenerateBest Practices
- Always commit hx.lock
- Run
hx lock --checkin CI - Review lockfile changes in PRs
- Update dependencies regularly
- Use
hx syncwhen cloning
See Also
- hx lock — Generate lockfile
- hx sync — Install from lockfile
- hx outdated — Check for updates
- Lockfile Reference — File format