configme is a centrally-installed Python package that configures the build of
the yelmox / climber-x model stacks and their component packages from a single
source of machine- and compiler-specific information.
It replaces the per-repository config.py and the orchestrator-specific
install.py with one tool: detect the netCDF installation automatically, build
the Makefile for each component from its template using shared machine/compiler
fragments, and clone/link a whole stack with one command.
configme install yelmox # clone + configure + link (+ build) a whole stack
configme upgrade yelmox # git pull the stack + reconfigure (+ rebuild if changed)
configme config yelmox # (re)generate Makefiles for an already-present stack
configme status yelmox # report what is present and what is still pending (read-only)
configme # (re)configure the current directory (orchestrator or package)
configme show macbook # print a machine (or compiler) fragment to copy/edit
configme new machine mybox # scaffold a new machine fragment from linux, to edit
configme netcdf # detect & print NC_FROOT / NC_CROOTconfigme is installed once, globally, and provides the configme command on
your PATH:
pip install git+https://github.com/fesmc/configmeTo upgrade later, add --upgrade (or --force-reinstall) to the same command.
The only runtime dependency is tomli on Python < 3.11 (tomllib is used on
3.11+); it is installed automatically. configme invokes nf-config /
nc-config, git, and make as external commands when needed.
If the configme command is not found after installing, the Python user bin
directory is probably not on your PATH. Add it to your ~/.bashrc /
~/.zshrc:
export PATH="${PATH}:${HOME}/.local/bin"The most common workflow is a one-shot install: clone a whole stack,
configure every package for your machine/compiler, link the orchestrator, and
build what needs building — all in one command.
configme install yelmox # clone + configure + link (+ build) the whole stack
configme install yelmox -m dkrz_levante -c ifx # pick the machine + compiler explicitly
configme install yelmox -d https # clone over HTTPS (no GitHub SSH key needed)
configme install yelmox --dir ~/models/yelmox # put the checkout here instead of ./yelmox
configme install yelmox --build-deps # rebuild dependency packages without prompting
configme install yelmo # just yelmo + the sub-packages it needs
configme install yelmo --only # only yelmo, nothing pulled in
configme install yelmox:dev # orchestrator on its `dev` branch (its manifest then drives components)
configme install climber-x:alex-dev # same for climber-x
configme install yelmox+yelmo:mybranch # pin one component; CLI ref overrides the manifest
configme install yelmox --link fesm-utils=/abs/path # symlink an existing checkout instead of cloning
configme install yelmox --dry-run # preview what would be cloned/configuredIf you omit -m/-c, configme detects the machine from the hostname where it
can and otherwise prompts you. Options combine freely, e.g.:
configme install yelmox -m dkrz_levante -c ifx -d httpsBy default configme install clones over SSH (git@github.com:...), which
needs a GitHub SSH key. On a machine where you haven't set one up (e.g. a fresh
HPC account), -d https clones over HTTPS instead. Use --overwrite to
re-clone over an existing checkout, or -d no to skip cloning entirely and
configure whatever is already on disk.
Run configme --help for the full command surface and configme list to see
the supported orchestrators, packages, machines, and compilers.
If you already have an orchestrator checkout on disk (cloned by hand, or one you are developing in), run configme from inside it to configure the stack without cloning anything:
cd yelmox # an existing orchestrator checkout
configme init # optional — only needed if the dir name is different than the package name
configme -m macbook -c gfortran # configure every package in the stackconfigme init scaffolds .configme/ (a committable manifest.toml plus a
config.toml template). It is optional: a checkout whose directory name matches
its package name (e.g. yelmox) is recognised without it, and the bare command
above creates .configme/config.toml for you on first run. Use init when the
directory name is different than the package name (the manifest makes it
recognisable regardless of directory name) or when you want the manifest tracked
in git.
configme config shares its target grammar with configme install, so the
same names work for both:
configme config yelmo -m macbook -c gfortran # yelmo + the sub-packages it needs
configme config yelmox+yelmo # exactly those two, no expansion
configme config yelmo --only # just yelmo, nothing pulled in
cd yelmo && configme -m macbook -c gfortran # bare = `configme config` on this dirconfigme config only (re)generates Makefiles — it never clones, links, or
builds. Add --dry-run to preview which Makefiles would change.
If a package is already cloned somewhere else on disk (e.g. a shared
fesm-utils build on an HPC filesystem, or a development checkout you maintain
by hand), point configme at it instead of cloning a duplicate:
configme install yelmox --link fesm-utils=/work/shared/fesm-utils
configme install yelmox --link fesm-utils=/abs/a --link coordinates=/abs/bconfigme symlinks the package's slot inside the install root (yelmox/fesm-utils -> /work/shared/fesm-utils) and skips its clone, configure, and build steps —
the linked checkout is treated as user-managed. Inter-package links (e.g.
yelmox/yelmo/fesm-utils -> ../fesm-utils) still work because they chain through
the symlink. The primary package itself cannot be linked — use --dir for that.
A non-existent link target is a hard error: configme will not fall back to cloning, since silent fallback would defeat the point of the flag.
Frequently-reused mappings can live in TOML instead:
# ~/.configme/links.toml — applies to every install
# <root>/.configme/links.toml — overrides global per-package
[links]
"fesm-utils" = "/work/shared/fesm-utils"
"coordinates" = "/work/shared/coordinates"Precedence: --link (CLI) overrides <root>/.configme/links.toml (project)
overrides ~/.configme/links.toml (global). CLI links are applied silently;
file-supplied links are confirmed one at a time at install time (the file may
carry stale entries — better to ask than silently link a wrong path).
configme upgrade honors links too: a linked package's pull and rebuild are
skipped because the external checkout is the user's to manage. Pass --link
again at upgrade time to (re)point a link at a different target.
After each successful build, configme writes a small .configme-build.toml
into the package's checkout recording the machine and compiler it was built
for. When a later install links that same checkout into a project with a
different (machine, compiler), the link line gets a (! …) warning so a
toolchain mismatch is visible before it confuses the consumer's build.
configme upgrade pulls new versions of already-installed checkouts and
reconfigures them with the same machine/compiler you installed with (read from
.configme/config.toml; override with -m/-c). It shares the target grammar
with install/config:
configme upgrade # the current checkout's primary + its deps
configme upgrade yelmox # the whole yelmox stack
configme upgrade yelmo # yelmo + the sub-packages it needs
configme upgrade yelmo --only # just yelmo, nothing pulled inEach checkout is updated in place with git pull --ff-only on whatever branch
is checked out. A checkout that is missing, has uncommitted changes, or whose
branch has diverged from upstream is skipped with a warning and never
touched — resolve those by hand (anything beyond a clean fast-forward is left
to you). Every package is then reconfigured; a package whose pull brought in new
commits is also rebuilt when it is a build-it package (e.g. fesm-utils), gated
exactly like install — --build-deps rebuilds without asking, otherwise you
are prompted. Add --dry-run to preview the pulls and reconfigures.
The orchestrator's data repos are refreshed alongside the components. These
are auxiliary, clone-only checkouts — for CLIMBER-X, the large input/ data repo
on GitLab — declared in the orchestrator's data_packages list. Upgrade pulls
one that is already on disk, but never clones a missing one: upgrade only
ever refreshes what you already have. If a data repo (or an optional private
component) was never installed, the run ends with a reminder naming it and
the configme install command to fetch it — so the big input repo is surfaced
without forcing a multi-GB download.
The pip_package/runme_config post-config extras (e.g. the runme tool) are
offered a re-run, each a y/N prompt (default no). To run the whole upgrade
unattended, pass -y — it answers yes to every prompt (ref switches, rebuilds,
data-repo pulls), so configme upgrade -y needs no input.
To touch only specific checkouts, use --repos with a comma-separated list —
components and/or data repos. Each entry is either a package name or a
path to where the checkout already lives (handy when you don't recall the
package name): a path is matched against the managed checkouts, --link targets
and symlinks included, and resolved back to the package name.
configme upgrade -y # pull/refresh everything, no prompts
configme upgrade --repos climber-x-input # by package name
configme upgrade --repos ./input # by path — resolves to climber-x-input
configme upgrade --repos yelmo,./input # mix names and pathsThe same --repos (name or path) applies to configme git.
configme status is a read-only report of what is actually on disk versus
what the plan expects — it never clones, configures, links, or builds. It shares
the target grammar with install/config and answers the questions you have
after a partial install: are all the repositories there (including optional and
data ones that may have been skipped)? Are the inter-component links in place?
Is fesm-utils built for every variant?
configme status # the current checkout's primary + its deps
configme status yelmox # the whole yelmox stack
configme status -v # show every check, including the ones already okIt groups checks into repos, links, builds, and extras, hides everything that is already in order, and ends with the exact commands to run by hand for whatever is left:
Builds:
[partial] fesm-utils (omp) (missing fftw-omp/lib/libfftw3.a) -> configme install fesm-utils --build-deps
Run these when ready:
configme install fesm-utils --build-deps
The exit status is non-zero only for a genuine problem (a required repo missing,
a symlink broken, a half-finished build); intentionally deferred items (a
skipped optional repo, a data clone you postponed, an unbuilt variant) are shown
as pending but do not fail. The same "still pending" block is appended to the
install and config summaries, so a normal run also reminds you of anything
outstanding.
On a new machine or cluster, give it any name you like. configme new machine
scaffolds a starter fragment (seeded from linux) into both the project's
.configme/machines/ and your ~/.configme/machines/, ready to edit:
configme new machine mybox # creates mybox.mk in project + user tiers
configme show macbook # print an existing one as a reference to copy
configme config yelmox -m mybox -c gfortranYou don't even have to run new first: if you pass an unknown machine to
config/install at the interactive prompt, configme offers to create it from
linux on the spot. Once your fragment works well, please consider
contributing it back to configme so others can reuse it.
The .mk fragment above configures the libraries configme builds itself. One
dependency — fesm-utils — builds its bundled fftw/lis with its own
build.py, which reads a separate machine file in its own schema (compiler
vars, module loads, and per-component overrides configme deliberately doesn't
model). So configme new machine <name> (and the unknown-machine prompt above)
writes two stubs per tier: the <name>.mk fragment and a <name>.toml in
fesm-utils' build.py schema, seeded from a bundled template with the machine name
filled in. Edit the .toml's compilers/modules for your cluster (an HPC machine
like chinook+ifx needs an [compilers.ifx] table and the right [modules]).
When configme drives build.py, it copies your <name>.toml into the
fesm-utils checkout's machines/ so build.py -m <name> resolves it — you
never edit the checkout directly. If a same-named file already exists there and
differs, configme asks before overwriting (default no), so a checked-in machine
file is never clobbered.
A few standalone fesmc tools that aren't model packages can still be installed
through configme install as a convenience — currently just
runme:
configme install runme # pip install -U git+https://github.com/fesmc/runme
configme install runme --dry-run # print the pip command without running itThis is exactly the same install the pip_package orchestrator extra does
automatically as part of configme install yelmox / climber-x; the standalone
form is handy when you want to install or update runme on its own. Other
install flags (-m/-c/--dir/-d/--build-deps) don't apply and are
ignored. configme list shows the available tools under Tools:.
To work on configme itself, clone it and install in editable mode so your changes take effect immediately, without reinstalling:
git clone git@github.com:fesmc/configme.git
cd configme
pip install -e .With an editable (pip install -e .) install, the globally-available configme
command always reflects your working tree, so you can iterate on the code and
rerun commands directly — no reinstall step between edits.
This repository is in early development. The full design is specified in
docs/DESIGN.md.