Packagemanager-LFS-PackageUser-System git · main
Package-user based package manager for LFS/BLFS
Shell 63.7% Markdown 35.8%git clone https://git.christianimmanuel.de/linux-from-scratch/Packagemanager-LFS-PackageUser-System.gitwget https://git.christianimmanuel.de/linux-from-scratch/Packagemanager-LFS-PackageUser-System/archive/Packagemanager-LFS-PackageUser-System.tar.gzMakefile raw
# lfs-pkgusr -- install the package-user toolchain.
#
# make install -> /usr
# make install PREFIX=/usr/local -> /usr/local
# make uninstall
# make clean -> scratch files, not installed ones
# make check -> run the regression tests
#
# DESTDIR is honoured, so this works for staged installs and for installing
# into a tree that is not the running system:
# make install DESTDIR=/mnt/lfs PREFIX=/usr
# /usr, not /usr/local: these tools ARE the system's package management -- the
# chroot invokes them by name, and packagemanager runs lfs-helper pm-install
# off $PATH, which does not include /usr/local everywhere.
PREFIX ?= /usr
DESTDIR ?=
BINDIR := $(DESTDIR)$(PREFIX)/bin
SHAREDIR := $(DESTDIR)$(PREFIX)/share/lfs-pkgusr
COMPDIR := $(DESTDIR)$(PREFIX)/share/bash-completion/completions
SYSCONFDIR ?= $(DESTDIR)/etc
# The four tools, the book merger, and the phase runner every generated
# install script sources (it goes in bin so `. lfs-phases` finds it on PATH,
# on the host, in the chroot and on the built system alike).
TOOLS := lfs lfs-helper packagemanager blfs lfs-sysvbook lfs-phases lfs-kernel lfs-backup
COMPLETION := lfs-completion.bash
TESTS := test_lfs_crosschain.sh
INSTALL ?= install
# Directories are created with mkdir -p, NEVER `install -d`.
#
# `install -d` applies its mode to a directory that ALREADY EXISTS, so
# installing the tools re-moded /usr/bin from 775 to 755 and silently broke
# the package-user system: package users are in group install and need
# group-write on the install directories. The next build then failed with
# permission errors that had nothing to do with the package.
# mkdir -p leaves an existing directory exactly as it is.
MKDIR ?= mkdir -p
.PHONY: all install uninstall check stamp clean help
all: help
help:
@echo "make install [PREFIX=...] [DESTDIR=...] install the tools"
@echo "make uninstall [PREFIX=...] remove them"
@echo "make check run the tests"
@echo "make stamp stamp the stack files with the tools' version"
@echo "make clean remove scratch files"
@echo ""
@echo "installs into: $(PREFIX)/bin"
install:
@echo "==> tools -> $(BINDIR)"
$(MKDIR) $(BINDIR)
@# packagemanager_install is retired (1.12.0, folded into lfs-helper
@# pm-install) -- sweep a previously installed copy off the system.
@if [ -e "$(BINDIR)/packagemanager_install" ]; then \
rm -f "$(BINDIR)/packagemanager_install" \
&& echo " removed retired packagemanager_install"; \
fi
@# lfs-config is retired (1.14.291): lfs-backup replaces it.
@if [ -e "$(BINDIR)/lfs-config" ]; then \
rm -f "$(BINDIR)/lfs-config" && echo " removed retired lfs-config (now lfs-backup)"; \
fi
@for t in $(TOOLS); do \
if [ -f "$$t" ]; then \
$(INSTALL) -m 755 "$$t" "$(BINDIR)/$$t" && echo " $$t"; \
else \
echo " !! missing: $$t" >&2; exit 1; \
fi; \
done
@# THE STAMP RECORDS WHAT IS INSTALLED, so whoever installs writes it.
@# It was written only by `lfs build-system install-tools`, which runs
@# on a host against a chroot -- so on a BOOTED system every later
@# `make install` left the stamp describing the old copies, and
@# packagemanager announced "these tools differ from the copies on the
@# host" and told the reader to run sync-tools on a host that no longer
@# exists.
@$(MKDIR) $(DESTDIR)/usr/share/lfs
@{ echo '{'; first=1; for t in $(TOOLS); do [ -f "$$t" ] || continue; m=$$(md5sum "$$t" | cut -d' ' -f1); [ $$first = 1 ] || echo ','; first=0; printf ' "%s": "%s"' "$$t" "$$m"; done; echo; echo '}'; } > $(DESTDIR)/usr/share/lfs/tool-stamps.json
@echo " recorded $(DESTDIR)/usr/share/lfs/tool-stamps.json"
@echo "==> stacks -> $(DESTDIR)/etc/pkgusr/stacks"
$(MKDIR) $(DESTDIR)/etc/pkgusr/stacks
@# A STACK FILE IS THE USER'S. This overwrote it unconditionally, so
@# `make install` silently undid every edit -- and the edits are the
@# point of the file: which packages to avoid, which refs to pin. A
@# user who had just removed `avoid ruby` would have had it back, and
@# the build would have failed the same way again with no explanation.
@# Install it when it is missing; otherwise keep theirs and leave the
@# new one alongside for comparison.
@# ...but only a file the user has ACTUALLY edited. Keeping every
@# installed stack forever meant a shipped fix -- new entries, a
@# corrected have= -- waited in a .new file for a manual merge, even
@# when the user had never touched the file. `packagemanager stack
@# services` then ran three entries while the new one had six, and
@# nothing said why. So record what we shipped: if the installed copy
@# still matches the last shipped copy, it is ours to update.
@$(MKDIR) $(DESTDIR)/etc/pkgusr/stacks/.shipped
@for f in stacks/*; do \
[ -f "$$f" ] || continue; \
b="$$(basename $$f)"; \
d="$(DESTDIR)/etc/pkgusr/stacks/$$b"; \
r="$(DESTDIR)/etc/pkgusr/stacks/.shipped/$$b"; \
if [ ! -e "$$d" ]; then \
$(INSTALL) -m 644 "$$f" "$$d" && cp -f "$$f" "$$r" \
&& echo " $$f"; \
elif cmp -s "$$f" "$$d"; then \
cp -f "$$f" "$$r"; echo " $$b (unchanged)"; \
elif [ -f "$$r" ] && cmp -s "$$r" "$$d"; then \
$(INSTALL) -m 644 "$$f" "$$d" && cp -f "$$f" "$$r" \
&& rm -f "$$d.new" \
&& echo " $$b (updated -- you had not edited it)"; \
else \
$(INSTALL) -m 644 "$$f" "$$d.new" \
&& echo " $$b -> KEPT YOURS; new version saved as $$d.new"; \
fi; \
done; true
@# kernel.conf is a file to EDIT BEFORE building, so it is installed
@# rather than written on first run -- and, like a stack file, an
@# edited one is kept and the new one lands beside it.
@# backup.conf: what lfs-backup carries. Yours is kept, like kernel.conf.
@if [ -f backup.conf ]; then \
$(MKDIR) "$(DESTDIR)/etc/pkgusr"; \
d="$(DESTDIR)/etc/pkgusr/backup.conf"; \
if [ ! -e "$$d" ] || cmp -s backup.conf "$$d"; then \
$(INSTALL) -m 644 backup.conf "$$d" && echo " backup.conf"; \
else \
$(INSTALL) -m 644 backup.conf "$$d.new" \
&& echo " backup.conf -> KEPT YOURS ($$d.new)"; \
fi; \
fi
@if [ -f kernel.conf ]; then \
d="$(DESTDIR)/etc/pkgusr/kernel.conf"; \
if [ ! -e "$$d" ] || cmp -s kernel.conf "$$d"; then \
$(INSTALL) -m 644 kernel.conf "$$d" && echo " kernel.conf"; \
else \
$(INSTALL) -m 644 kernel.conf "$$d.new" \
&& echo " kernel.conf -> KEPT YOURS ($$d.new)"; \
fi; \
fi
@# A STACK ENTRY MAY HAVE A DIRECTORY. The loop above takes files
@# only, so stacks/mytools/install_mytools -- the package-user script
@# the mytools step runs -- was never installed, and the step would
@# have failed with "missing .../mytools/install_mytools". Copy the
@# subdirectories too, without clobbering a script the user edited.
@for d in stacks/*/; do \
[ -d "$$d" ] || continue; \
b="$$(basename $$d)"; \
$(MKDIR) "$(DESTDIR)/etc/pkgusr/stacks/$$b"; \
for f in "$$d"*; do \
[ -f "$$f" ] || continue; \
t="$(DESTDIR)/etc/pkgusr/stacks/$$b/$$(basename $$f)"; \
if [ ! -e "$$t" ] || cmp -s "$$f" "$$t"; then \
$(INSTALL) -m 755 "$$f" "$$t"; \
else \
$(INSTALL) -m 755 "$$f" "$$t.new" \
&& echo " $$b/$$(basename $$f) -> KEPT YOURS ($$t.new)"; \
fi; \
done; \
echo " $$b/ ($$(ls -1 $$d | wc -l) file(s))"; \
done; true
@chmod 755 $(DESTDIR)/etc/pkgusr/stacks/*.sh 2>/dev/null || true
@echo "==> bash completion -> $(COMPDIR)"
@# Optional, and a missing one must not take the tools down with it:
@# `install: cannot stat 'lfs-completion.bash'` aborted the whole target
@# after the tools were already in place, so the run looked failed while
@# most of it had succeeded.
@if [ -f "$(COMPLETION)" ]; then \
$(MKDIR) $(COMPDIR); \
$(INSTALL) -m 644 $(COMPLETION) $(COMPDIR)/lfs; \
for t in blfs packagemanager lfs-helper; do \
ln -sf lfs "$(COMPDIR)/$$t"; \
done; \
else \
echo " skipped: $(COMPLETION) is not in this checkout"; \
fi
@echo "==> XDG profile for shared users -> $(SYSCONFDIR)/pkgusr/skel-u_xdg"
$(MKDIR) $(SYSCONFDIR)/pkgusr/skel-u_xdg
@if [ -f "$(SYSCONFDIR)/pkgusr/skel-u_xdg/.bash_profile" ]; then \
echo " kept your existing .bash_profile"; \
else \
$(INSTALL) -m 644 skel-u_xdg/.bash_profile \
"$(SYSCONFDIR)/pkgusr/skel-u_xdg/.bash_profile"; \
echo " installed (XDG_RUNTIME_DIR is filled in on first use)"; \
fi
@echo "==> tests -> $(SHAREDIR)"
$(MKDIR) $(SHAREDIR)
# The tests are optional -- say so when they are absent, rather than hiding a
# real failure. `2>/dev/null || true` hid both cases alike.
@if [ -f "$(TESTS)" ]; then \
$(INSTALL) -m 644 $(TESTS) $(SHAREDIR)/ && echo " $(TESTS)"; \
else \
echo " (not shipped: $(TESTS))"; \
fi
@echo ""
@echo "Installed. Check with:"
@echo " $(PREFIX)/bin/lfs --version"
@echo " $(PREFIX)/bin/lfs --help"
uninstall:
@for t in $(TOOLS); do rm -fv "$(BINDIR)/$$t"; done
@for t in lfs blfs packagemanager lfs-helper; do \
rm -fv "$(COMPDIR)/$$t"; \
done
rm -rfv $(SHAREDIR)
@echo ""
@echo "Left alone (they are yours):"
@echo " $(SYSCONFDIR)/pkgusr/skel-u_xdg/.bash_profile"
@echo " /usr/share/lfs books, settings, snapshots"
@echo " /etc/pkgusr packagemanager settings, kernel.conf, backup.conf"
check:
@bash $(TESTS) ./lfs
# ONE ARTIFACT, ONE NUMBER -- and a rule a human has to remember is a rule
# that drifts. The stack files each carry `# stack-version:`, the suite
# asserts it equals the tools' version, and it was ten releases stale before
# anyone ran the suite. This stamps them from `lfs --version`, so cutting a
# release is `make stamp` rather than seven sed commands.
stamp:
@v=$$(./lfs --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1); \
[ -n "$$v" ] || { echo "cannot read a version from ./lfs"; exit 1; }; \
for f in stacks/*.stack; do \
grep -q '^# stack-version:' "$$f" \
|| { echo "$$f has no stack-version line -- add one"; exit 1; }; \
sed -i "s/^# stack-version: .*/# stack-version: $$v/" "$$f"; \
done; \
echo "stamped $$(ls stacks/*.stack | wc -l) stack file(s) with $$v"
# Nothing here is compiled, so clean removes only what running the tools here
# leaves behind: Python bytecode and the test suite's scratch directories.
# It never touches an installed tree -- that is what uninstall is for.
clean:
rm -rf __pycache__ *.pyc
rm -rf /tmp/lfstest.* /tmp/lfstest-count.*
@echo "clean. (installed files are untouched -- use 'make uninstall')"