bbolt-cli-package¶
Packages
Package one CLI out of a larger Go repository with buildGoModule, instead
of building every command the upstream module ships.
Problem¶
Many Go projects are primarily libraries but also ship one or more commands
under cmd/. etcd-io/bbolt is the embedded BoltDB key/value store used by
countless Go services, and it happens to include a handy bbolt CLI for
inspecting and surgically editing those .db files on disk.
If you point buildGoModule at such a repo with no further hints, it will try
to build all main packages it finds — pulling in commands you do not want,
extra build time, and sometimes extra dependencies. You wanted one tool.
Key insight / trap¶
Two lines do the work:
subPackages = [ "cmd/bbolt" ]; # build only this one command
ldflags = [ "-s" "-w" ]; # strip symbol table + DWARF debug info
subPackagesis the important one. It restricts the build to the given import paths (relative to the module root, i.e. the directory withgo.mod). With it,buildGoModulecompiles and installs exactlycmd/bboltand nothing else. Without it, everypackage mainin the tree becomes an output binary.ldflags = [ "-s" "-w" ]is the standard Go binary-slimming pair:-sdrops the symbol table,-wdrops DWARF debug info. Useful for an ops tool you just want to drop on a box.- Set
mainPrograminmetasolib.getExe/nix runresolve tobbolteven thoughpnameisbbolt-cli.
Trap when adapting to another repo: vendorHash must match the vendored
dependency set. Start with lib.fakeHash, build once, and paste the hash Nix
reports. Same for the src hash.
Usage¶
# In an overlay or flake:
final: prev: {
bbolt-cli = prev.callPackage ./packages/bbolt-cli-package { };
}
or directly:
Then bbolt is on PATH (add the package to environment.systemPackages,
home.packages, or a nix shell).
Adapting to a different tool¶
To extract a different command from a different repo, change four things:
src(owner/repo/rev/hash),vendorHash,subPackagesto thecmd/<name>path you actually want,mainProgram/metato match.
Everything else — the subPackages + ldflags pattern — carries over
unchanged.
Source¶
packages/bbolt-cli-package/default.nix
# Extract ONE command from a multi-command Go module.
#
# etcd-io/bbolt is a library repo that also ships several commands under cmd/.
# We only want the `bbolt` CLI (inspect/edit BoltDB files), not the whole tree.
#
# The reusable trick: `subPackages = [ "cmd/bbolt" ]` tells buildGoModule to
# compile and install exactly that one package instead of every main package in
# the module. `ldflags = [ "-s" "-w" ]` strips the symbol table and DWARF debug
# info from the resulting binary.
#
# Build with, e.g.:
# pkgs.callPackage ./default.nix { }
{
lib,
buildGoModule,
fetchFromGitHub,
}:
buildGoModule rec {
pname = "bbolt-cli";
version = "1.4.3";
src = fetchFromGitHub {
owner = "etcd-io";
repo = "bbolt";
rev = "v${version}";
# nix-prefetch or the first failing build prints the correct hash.
hash = "sha256-awBkr2ObRxPQkMlfVFZxEbQ9JQJsFrJvSBHtqP4Hb3I=";
};
# Hash of the vendored Go dependencies. Set to lib.fakeHash on first build,
# then paste the value Nix reports.
vendorHash = "sha256-TzVmAMrNrNkFE9jQ+SILJXvbhBK1WenNPqA0FfuDU+M=";
# THE KEY LINE: build only cmd/bbolt, not every command in the repo.
# Paths are relative to the module root (where go.mod lives).
subPackages = [ "cmd/bbolt" ];
# -s strips the symbol table, -w drops DWARF debug info: smaller binary.
ldflags = [
"-s"
"-w"
];
meta = {
description = "BoltDB CLI tool for inspecting and manipulating bbolt databases";
homepage = "https://github.com/etcd-io/bbolt";
license = lib.licenses.mit;
mainProgram = "bbolt";
};
}