mxpkg is a self-hosted package manager for Modula-2, written in Modula-2 itself. It reads m2.toml manifests, resolves dependencies, and invokes mx to build projects.
# Bootstrap: build mxpkg from source using mxpkg0
cd path/to/m2
cargo build --release # build mx
cd tools/mxpkg0
cargo build --release # build bootstrapper
cargo run -- build # build mxpkg using mx
# The self-hosted binary is at tools/mxpkg/target/mxpkgCreate a new m2.toml manifest template in the current directory.
Build the package. Reads m2.toml, resolves dependencies, constructs the mx command, and compiles. Output goes to target/<name>.
--release— pass-O2to mx
Build and immediately run the package. Arguments after -- are passed to the program.
Validate dependencies and generate/update m2.lock.
Publish the package to the registry. Enforces: valid semver, no duplicates, version >= latest.
Download a package from the registry to the local cache.
Print the mxpkg version.
Remove build artifacts.
Validate the manifest and lockfile.
Verify lockfile integrity (SHA-256 hashes).
INI-like format with key=value pairs and [section] headers:
# m2.toml - package manifest
manifest_version=1
name=hello
version=0.1.0
edition=pim4
entry=src/Main.mod
m2plus=false
includes=src
[deps]
mylib=path:../mylib
otherlib=0.2.0
[cc]
cflags=-Wall
ldflags=-L/usr/local/lib
libs=m pthread
extra-c=libs/helper.c
frameworks=CoreFoundation
[test]
entry=tests/Main.mod
includes=tests
[features]
threading=false
gc=false| Key | Description | Default |
|---|---|---|
name |
Package name (required) | — |
version |
Semantic version X.Y.Z (required) | — |
entry |
Path to the main module | src/Main.mod |
m2plus |
Enable M2+ extensions | false |
edition |
Set to m2plus for extensions |
pim4 |
includes |
Space-separated include directories | — |
manifest_version |
Manifest format version | 1 |
[deps]
mylib=path:../mylib # local path dependency
otherlib=0.2.0 # registry dependency (semver)Each dependency must have its own m2.toml. Its include directories are added to the compiler's search path.
C compiler integration. All values are space-separated lists.
| Key | Description |
|---|---|
cflags |
Extra C compiler flags |
ldflags |
Linker flags |
libs |
Libraries to link (names only, not -l prefix) |
extra-c |
Extra C source files to compile and link |
frameworks |
macOS frameworks |
These are transitive — a dependency's [cc] settings propagate to dependents.
| Key | Description | Default |
|---|---|---|
entry |
Test entry point module | tests/Main.mod |
includes |
Test-only include directories | — |
Define feature gates for conditional compilation:
[features]
threading=false
gc=falseFeatures are enabled via --feature flags and control (*$IF name*) pragmas in source.
[registry]
url=https://registry.example.comGenerated by mxpkg resolve. Records the resolved dependency graph with integrity hashes:
[package]
name=hello
version=0.1.0
[dep.mylib]
version=0.1.0
source=local
sha256=abc123def456...
path=../mylibDo not edit manually. Regenerate with mxpkg resolve.
The lockfile's content hash (Lockfile::content_hash(), FNV-1a 64-bit) is used by the LSP server as a cache key — changes to m2.lock invalidate the analysis cache and trigger reindexing.
| Path | Contents |
|---|---|
~/.mxpkg/registry/ |
Package index and published packages |
~/.mxpkg/cache/ |
Downloaded package cache |
Registry dependencies use semver ranges:
^1.2.3— compatible with 1.2.3 (>=1.2.3, <2.0.0)~1.2.3— patch-level changes (>=1.2.3, <1.3.0)>=1.0.0— minimum version1.2.3— exact version
mxpkg is self-hosted: written in Modula-2, compiled by mx. The bootstrapping chain is:
cargo build— build the mx compiler (Rust)mxpkg0 build— the Rust bootstrapper compiles mxpkg using mxmxpkg build— mxpkg can now build itself and other packages
| Module | Purpose |
|---|---|
| Main | CLI entry point, command dispatch |
| Manifest | Parse and query m2.toml files |
| Builder | Construct and execute mx commands |
| Lockfile | Read and write m2.lock files |
| Resolver | Validate dependencies, generate lockfile |
| Registry | Package publishing, fetching, version lookup |
| Semver | Semantic version parsing, comparison, range matching |
| Sys | Foreign C bindings to libs/m2sys/ |
Provides capabilities not available in standard Modula-2:
- File I/O (read, write, stat, mkdir, rmdir)
- Process execution (exec, wait)
- SHA-256 hashing
- Path utilities (join, basename, dirname)
- Tar archive creation
The M2 Sys module binds to these via DEFINITION MODULE FOR "C".
bootstrap.lock contains entry_sha256 and tree_sha256 for verifying that the bootstrapped mxpkg binary matches expectations.