Faster ISO builds (69 s to 9 s) and a faster write.sh check
make iso recompiled the kernel and every command each time: iso and ramroot wiped build/kernel, build/lib and build/cmd to make sure nothing was compiled for the wrong RAMROOT setting. Only kernel/proc/proc.c and kernel/dev/ramdisk.c read RAMDISK_ROOT, so only their objects go now. Even then a no-op make iso took 69 s, because sysroot.stamp lists every staged file with its mtime and two things re-copied files on every run: the plain cp in etc-install (now cp -p) and fastfetch's install (now install -C). A changed stamp rebuilds the Alpine root, the root image and its zstd -19 compression. A no-op, and a one-file kernel change, now take about 9 s. write.sh read the stick back with a buffered cmp, slowly and possibly from the page cache. It now reads 4 MB at a time with iflag=direct, which checks the stick itself; --no-verify skips the check. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015f73FesGZGYPkmDvUcj6QX
This commit is contained in:
parent
afb2e084af
commit
7d2eca8271
3 changed files with 38 additions and 16 deletions
27
Makefile
27
Makefile
|
|
@ -528,11 +528,18 @@ endif
|
||||||
#
|
#
|
||||||
# Evaluated when the Makefile is read, so the wipe happens before anything is
|
# Evaluated when the Makefile is read, so the wipe happens before anything is
|
||||||
# compiled against the wrong setting.
|
# compiled against the wrong setting.
|
||||||
|
#
|
||||||
|
# Only the two objects that read RAMDISK_ROOT are dropped: kernel/proc/proc.c
|
||||||
|
# (ROOTDEV is used nowhere else) and kernel/dev/ramdisk.c. The whole of
|
||||||
|
# build/kernel, build/lib and build/cmd used to go, which made every `make iso`
|
||||||
|
# recompile the kernel and every command, rebuild the root image from the new
|
||||||
|
# binaries and compress it again at zstd -19 -- minutes, for a one-line change.
|
||||||
|
# If another file ever starts to use ROOTDEV or RAMDISK_ROOT, add it here.
|
||||||
RAMROOT_STATE := $(if $(RAMROOT),on,off)
|
RAMROOT_STATE := $(if $(RAMROOT),on,off)
|
||||||
RAMROOT_STAMP := $(BUILD)/ramroot.state
|
RAMROOT_STAMP := $(BUILD)/ramroot.state
|
||||||
$(shell mkdir -p $(BUILD); \
|
$(shell mkdir -p $(BUILD); \
|
||||||
if [ "$$(cat $(RAMROOT_STAMP) 2>/dev/null)" != "$(RAMROOT_STATE)" ]; then \
|
if [ "$$(cat $(RAMROOT_STAMP) 2>/dev/null)" != "$(RAMROOT_STATE)" ]; then \
|
||||||
rm -rf $(BUILD)/kernel $(BUILD)/lib $(BUILD)/cmd; \
|
rm -f $(BUILD)/kernel/proc/proc.o $(BUILD)/kernel/dev/ramdisk.o; \
|
||||||
printf '%s' '$(RAMROOT_STATE)' > $(RAMROOT_STAMP); \
|
printf '%s' '$(RAMROOT_STATE)' > $(RAMROOT_STAMP); \
|
||||||
fi)
|
fi)
|
||||||
|
|
||||||
|
|
@ -738,7 +745,6 @@ qemu-uefi: esp $(BUILD)/schfs.img $(OVMF_CODE) $(OVMF_VARS)
|
||||||
# silently reused for the other, leaving ROOTDEV pointing at the wrong device.
|
# silently reused for the other, leaving ROOTDEV pointing at the wrong device.
|
||||||
# Dropping the compiled objects first makes the switch always correct.
|
# Dropping the compiled objects first makes the switch always correct.
|
||||||
ramroot:
|
ramroot:
|
||||||
rm -rf $(BUILD)/kernel $(BUILD)/lib $(BUILD)/cmd
|
|
||||||
$(MAKE) RAMROOT=1
|
$(MAKE) RAMROOT=1
|
||||||
|
|
||||||
cmd: $(CMDBINS)
|
cmd: $(CMDBINS)
|
||||||
|
|
@ -781,7 +787,6 @@ projects:
|
||||||
# CFLAGS and make cannot see that.
|
# CFLAGS and make cannot see that.
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
iso:
|
iso:
|
||||||
rm -rf $(BUILD)/kernel $(BUILD)/lib $(BUILD)/cmd
|
|
||||||
$(MAKE) RAMROOT=1 schos.iso
|
$(MAKE) RAMROOT=1 schos.iso
|
||||||
|
|
||||||
# One El Torito entry, pointing at a FAT image holding the loader and kernel.
|
# One El Torito entry, pointing at a FAT image holding the loader and kernel.
|
||||||
|
|
@ -1458,19 +1463,23 @@ LOGO_ASCII = docs/branding/Ascii/ascii_50.txt
|
||||||
# proves the same thing far less clearly.
|
# proves the same thing far less clearly.
|
||||||
SRV_FILES = $(wildcard srv/*)
|
SRV_FILES = $(wildcard srv/*)
|
||||||
|
|
||||||
|
# cp -p, not cp: sysroot.stamp lists every staged file with its mtime, and the
|
||||||
|
# Alpine root, the root image and its zstd -19 compression are all rebuilt when
|
||||||
|
# it changes. A plain cp gave every copy a new mtime, so every `make iso`
|
||||||
|
# rebuilt all of them -- over a minute of CPU for no change at all.
|
||||||
etc-install: $(SCHINIT_JOBS) $(ETC_PLAIN) $(ETC_ZSH) $(LOGO_ASCII) $(SRV_FILES)
|
etc-install: $(SCHINIT_JOBS) $(ETC_PLAIN) $(ETC_ZSH) $(LOGO_ASCII) $(SRV_FILES)
|
||||||
@mkdir -p $(SYSROOT)/etc/schinit $(SYSROOT)/etc/zsh $(SYSROOT)/usr/share/schos $(SYSROOT)/srv
|
@mkdir -p $(SYSROOT)/etc/schinit $(SYSROOT)/etc/zsh $(SYSROOT)/usr/share/schos $(SYSROOT)/srv
|
||||||
@cp $(ETC_PLAIN) $(SYSROOT)/etc/
|
@cp -p $(ETC_PLAIN) $(SYSROOT)/etc/
|
||||||
@cp $(SCHINIT_JOBS) $(SYSROOT)/etc/schinit/
|
@cp -p $(SCHINIT_JOBS) $(SYSROOT)/etc/schinit/
|
||||||
@cp $(ETC_ZSH) $(SYSROOT)/etc/zsh/
|
@cp -p $(ETC_ZSH) $(SYSROOT)/etc/zsh/
|
||||||
@cp $(LOGO_ASCII) $(SYSROOT)/usr/share/schos/logo.txt
|
@cp -p $(LOGO_ASCII) $(SYSROOT)/usr/share/schos/logo.txt
|
||||||
@cp $(SRV_FILES) $(SYSROOT)/srv/
|
@cp -p $(SRV_FILES) $(SYSROOT)/srv/
|
||||||
@# The device-name databases, where lspci and lsusb look for them: the
|
@# The device-name databases, where lspci and lsusb look for them: the
|
||||||
@# hwdata package's directory. They were at /usr/share/usb.ids, which no
|
@# hwdata package's directory. They were at /usr/share/usb.ids, which no
|
||||||
@# tool searches, so lsusb printed numbers only.
|
@# tool searches, so lsusb printed numbers only.
|
||||||
@mkdir -p $(SYSROOT)/usr/share/hwdata
|
@mkdir -p $(SYSROOT)/usr/share/hwdata
|
||||||
@rm -f $(SYSROOT)/usr/share/usb.ids
|
@rm -f $(SYSROOT)/usr/share/usb.ids
|
||||||
@for f in usb.ids pci.ids; do [ -f dist/$$f ] && cp dist/$$f $(SYSROOT)/usr/share/hwdata/; done; true
|
@for f in usb.ids pci.ids; do [ -f dist/$$f ] && cp -p dist/$$f $(SYSROOT)/usr/share/hwdata/; done; true
|
||||||
@echo "installed $(words $(ETC_PLAIN)) /etc file(s), $(words $(ETC_ZSH)) zsh file(s) and $(words $(SCHINIT_JOBS)) schinit manifest(s)"
|
@echo "installed $(words $(ETC_PLAIN)) /etc file(s), $(words $(ETC_ZSH)) zsh file(s) and $(words $(SCHINIT_JOBS)) schinit manifest(s)"
|
||||||
|
|
||||||
# The mount points. Created here rather than by init, because a mkdir on a
|
# The mount points. Created here rather than by init, because a mkdir on a
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ $(BUILDDIR)/fastfetch: $(BUILDDIR)/toolchain.cmake
|
||||||
build: $(BUILDDIR)/fastfetch
|
build: $(BUILDDIR)/fastfetch
|
||||||
|
|
||||||
install: $(BUILDDIR)/fastfetch | $(SYSROOT)/bin
|
install: $(BUILDDIR)/fastfetch | $(SYSROOT)/bin
|
||||||
install -m 0755 $(BUILDDIR)/fastfetch $(SYSROOT)/bin/fastfetch
|
install -C -m 0755 $(BUILDDIR)/fastfetch $(SYSROOT)/bin/fastfetch
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PORTDIR)
|
rm -rf $(PORTDIR)
|
||||||
|
|
|
||||||
23
write.sh
23
write.sh
|
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
# ./write.sh sdc or ./write.sh /dev/sdc
|
# ./write.sh sdc or ./write.sh /dev/sdc
|
||||||
# ./write.sh sdc other.iso to write a different image
|
# ./write.sh sdc other.iso to write a different image
|
||||||
|
# ./write.sh sdc --no-verify skip the read-back check (halves the time)
|
||||||
#
|
#
|
||||||
# Shows what is on the device, asks you to type the device's name back, then
|
# Shows what is on the device, asks you to type the device's name back, then
|
||||||
# asks for your password and writes. Everything on the device is destroyed;
|
# asks for your password and writes. Everything on the device is destroyed;
|
||||||
|
|
@ -26,7 +27,7 @@ fi
|
||||||
die() { printf '%swrite.sh:%s %s\n' "$R" "$N" "$*" >&2; exit 1; }
|
die() { printf '%swrite.sh:%s %s\n' "$R" "$N" "$*" >&2; exit 1; }
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "usage: ./write.sh <device> [image.iso] [--any-disk]"
|
echo "usage: ./write.sh <device> [image.iso] [--any-disk] [--no-verify]"
|
||||||
echo " ./write.sh sdc writes schos.iso to /dev/sdc"
|
echo " ./write.sh sdc writes schos.iso to /dev/sdc"
|
||||||
echo
|
echo
|
||||||
echo "Removable disks on this machine:"
|
echo "Removable disks on this machine:"
|
||||||
|
|
@ -36,11 +37,13 @@ usage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ANY=0
|
ANY=0
|
||||||
|
VERIFY=1
|
||||||
DEV=
|
DEV=
|
||||||
ISO=
|
ISO=
|
||||||
for a in "$@"; do
|
for a in "$@"; do
|
||||||
case "$a" in
|
case "$a" in
|
||||||
--any-disk) ANY=1 ;;
|
--any-disk) ANY=1 ;;
|
||||||
|
--no-verify) VERIFY=0 ;;
|
||||||
-h|--help) usage ;;
|
-h|--help) usage ;;
|
||||||
*) if [ -z "$DEV" ]; then DEV=$a; elif [ -z "$ISO" ]; then ISO=$a; else usage; fi ;;
|
*) if [ -z "$DEV" ]; then DEV=$a; elif [ -z "$ISO" ]; then ISO=$a; else usage; fi ;;
|
||||||
esac
|
esac
|
||||||
|
|
@ -127,12 +130,22 @@ sync
|
||||||
# --- check ------------------------------------------------------------------
|
# --- check ------------------------------------------------------------------
|
||||||
|
|
||||||
# Read it back. A stick that takes the write and keeps none of it is common
|
# Read it back. A stick that takes the write and keeps none of it is common
|
||||||
# enough among cheap ones to be worth thirty seconds.
|
# enough among cheap ones to be worth the time.
|
||||||
echo "Checking what was written..."
|
#
|
||||||
if sudo cmp -n "$ISO_BYTES" "$ISO" "$DEV"; then
|
# iflag=direct and 4 MB reads: a plain `cmp ISO /dev/sdX` reads through the page
|
||||||
|
# cache in small requests, which a USB stick serves slowly -- and may be answered
|
||||||
|
# from the cache rather than from the stick, checking nothing. Direct reads
|
||||||
|
# check the stick itself, and at the speed it can actually deliver.
|
||||||
|
if [ "$VERIFY" = 1 ]; then
|
||||||
|
echo "Checking what was written..."
|
||||||
|
BLOCKS=$(( (ISO_BYTES + 4194303) / 4194304 ))
|
||||||
|
if sudo dd if="$DEV" bs=4M count="$BLOCKS" iflag=direct status=none | cmp -n "$ISO_BYTES" - "$ISO"; then
|
||||||
echo "${G}Done.${N} $DEV holds $(basename "$ISO") and can be removed."
|
echo "${G}Done.${N} $DEV holds $(basename "$ISO") and can be removed."
|
||||||
else
|
else
|
||||||
die "the device does not read back what was written -- the stick may be failing"
|
die "the device does not read back what was written -- the stick may be failing"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "${G}Done.${N} $DEV holds $(basename "$ISO") (not verified) and can be removed."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The kernel re-reads the partition table so the new layout shows up here
|
# The kernel re-reads the partition table so the new layout shows up here
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue