makefile package manager
mkpm shares makefile code across projects as versioned packages. A package is
a tarball of makefile code stored in a git repo (via git-lfs) and tagged
<package>/<version>. Installing a package unpacks it under .mkpm/ in your
project, where it can be included from a Mkpmfile.
Status
mkpm is in maintenance mode. It is kept clean and working for the projects that still use it, but new projects at BitSpur use plain Makefile conventions instead. Bug fixes are welcome; new features are unlikely.
Requirements
- POSIX shell and coreutils
- GNU Make >= 4.1
(on macOS install
remakeorgmake, since apple ships make 3.81) - Git and Git LFS
- jq
- curl or wget
- on macOS additionally gawk, gnu-sed and gnu-tar
mkpm checks for its requirements on first run and offers to install anything missing through the system package manager.
Install
$(curl --version >/dev/null 2>&1 && echo "curl -L" || echo "wget -O-") \ https://gitlab.com/api/v4/projects/48207162/packages/generic/mkpm/1.1.0/install.sh 2>/dev/null | sh
This installs mkpm to /usr/local/bin (override with PREFIX). A debian
package and the raw scripts are attached to each
release.
The global mkpm binary is optional. Projects initialized with a committed
./mkpm proxy binary and a committed .mkpm/cache.tar.gz bootstrap
themselves, so make works on a fresh clone without installing anything.
Quickstart
-
Initialize mkpm at the root of a git project.
This creates
mkpm.jsonand offers to add the./mkpmproxy binary, aMkpmfile, a proxyMakefile, and editor/git configuration. -
Install a package.
the
-tells mkpm the argument is a command instead of a make target (in a directory that is not yet an mkpm project, like duringinit, the-can be omitted) -
Include the package in your
Mkpmfile.include $(MKPM)/mkpm include $(MKPM)/hello .PHONY: greet greet: hello @$(ECHO) done greeting
include $(MKPM)/mkpmloads the mkpm runtime and must come first. Each installed package is included the same way by name. -
Run targets through mkpm.
mkpm greet # or ./mkpm greet make greet # via the generated proxy Makefile
Commands
mkpm [options] <TARGET> [...ARGS]
mkpm [options] - <COMMAND> [...ARGS]
options:
-h, --help show brief help
-s, --silent silent output
-d, --debug debug output
-e, --dotenv dotenv file
commands:
u|upgrade upgrade all packages from default git repo
u|upgrade <REPO> upgrade all packages from git repo
u|upgrade <REPO> <PACKAGE> upgrade a package from git repo
v|version mkpm version
i|install install all packages
i|install <PACKAGE> install a package from default git repo
i|install <REPO> <PACKAGE> install a package from git repo
rm|remove <PACKAGE> remove a package
ra|repo-add <REPO_NAME> <REPO_URI> add repo
rr|repo-remove <REPO_NAME> remove repo
reset reset mkpm
init initialize mkpm
pack pack mkpm module
publish pack and publish mkpm module
mkpm.json
All project configuration lives in mkpm.json at the project root. It is
managed by the mkpm commands, but safe to edit by hand.
{
"packages": {
"default": {
"gnu": "0.1.0"
}
},
"repos": {
"default": "https://gitlab.com/bitspur/mkpm/packages.git"
},
"binaries": {
"docker": {
"debian": "sudo apt-get install -y docker.io"
}
}
}reposmaps repo names to git uris. Packages underpackages.<repo>are installed from that repo.binaries(optional) declares system binaries the project needs. When a binary is missing, mkpm prints the matching install command (looked up by distro flavor or platform) and offers to run it.
Repos
The default package repo is https://gitlab.com/bitspur/mkpm/packages.git.
You can point the default repo at your own package repo, or add extra repos under a new name.
mkpm - repo-add howdy https://gitlab.com/example/howdy-packages.git mkpm - install howdy texas
Authoring packages
A package is a project with a main.mk entrypoint and package metadata in
mkpm.json.
{
"name": "hello",
"version": "0.1.0",
"description": "example mkpm package",
"author": "Clay Risser <email@clayrisser.com>",
"repo": "git@gitlab.com:bitspur/mkpm/packages.git",
"source": "https://gitlab.com/bitspur/mkpm/hello.git",
"files": ["extra.mk"]
}mkpm - packbuilds<name>.tar.gzcontainingmain.mk,mkpm.json,LICENSEand anything listed infiles.mkpm - publishpacks and pushes the tarball to the package repo (repo), tagging it<name>/<version>. Publishing requires write access to the package repo pluspython3andpandoc(used to update the package table in the repo readme).
How it works
- The committed
./mkpmproxy binary downloads the realmkpm.sh(pinned by version) into.mkpm/mkpm/.bin/mkpmand executes it. - Installed packages live under
.mkpm/mkpm/, which is gitignored. .mkpm/cache.tar.gzis a deterministic tarball of the bootstrap state and installed packages. Committing it (the default) makes fresh clones and CI work offline without hitting the package registry.- Useful environment variables:
MKPM_DEBUG=1for verbose output,DEFAULT_REPOto change the repoinitstarts with, andMKPM_SH_URL,MKPM_MK_URL,MKPM_PROXY_SH_URLto override where the bootstrap scripts are downloaded from.
Development
This repo self-hosts: ./mkpm <target> (or make <target>) runs the targets
in Mkpmfile using the local sources, bootstrapping from the
committed cache.
make test # bats test suite (offline, sandboxed) make lint # shfmt formatting check make format # shfmt formatting fix
Tool versions are pinned in .tool-versions (asdf format). Releases are cut by pushing a git tag, which builds the debian package and uploads the scripts to the GitLab generic package registry.
