Compare commits

...

26 Commits

Author SHA1 Message Date
MJ Pooladkhay
3fe8be59b6 download cloud-hypervisor and firmware binaries
Signed-off-by: MJ Pooladkhay <mj@pooladkhay.com>
2026-11-03 11:05:39 +00:00
MJ Pooladkhay
43b564f9e9 add the ability to have read-only virtio-fs shares
Signed-off-by: MJ Pooladkhay <mj@pooladkhay.com>
2026-11-03 11:05:39 +00:00
MJ Pooladkhay
412cea986e add 'make ch' that boots Redox via Cloud Hypervisor
Signed-off-by: MJ Pooladkhay <mj@pooladkhay.com>
2026-11-03 11:05:39 +00:00
MJ Pooladkhay
592a88f9bb share host directories with Redox from 'make qemu'
'make qemu share=<dir>' (or share="tag=dir ...") starts one virtiofsd per share and
adds the matching vhost-user-fs devices, so the guest sees /scheme/virtio-fsd.<tag>.

podman_bootstrap.sh installs virtiofsd, and the selftest recipe builds from the base source.

Signed-off-by: MJ Pooladkhay <mj@pooladkhay.com>
2026-11-03 11:05:39 +00:00
Jeremy Soller
5313cbba62 Merge branch 'strip-ar' into 'master'
cookbook: Also strip ar files

See merge request redox-os/redox!2427
2026-11-02 18:45:37 -07:00
Wildan M
559496cb6d
cookbook: Fix test 2026-11-03 08:23:09 +07:00
Wildan M
4006aee0bf
cookbook: Also strip ar files 2026-11-03 08:19:14 +07:00
Jeremy Soller
da760947f1 Merge branch 'verbosity' into 'master'
cookbook: Adjustable script verbosity and cleaner strip

See merge request redox-os/redox!2426
2026-11-02 18:00:17 -07:00
Jeremy Soller
28f5c3d7cb Merge branch 'prune-fail' into 'master'
cookbook: Don't always prune sysroot with clean-target enabled

See merge request redox-os/redox!2425
2026-11-02 17:46:28 -07:00
Jeremy Soller
4639c04454 Merge branch 'openssl-update' into 'master'
Update curl, openssl3 and nghttp2

See merge request redox-os/redox!2424
2026-11-02 17:43:36 -07:00
Jeremy Soller
3650a613f3 Merge branch 'python315-update' into 'master'
Update python315

See merge request redox-os/redox!2421
2026-11-02 17:42:34 -07:00
Jeremy Soller
d2abc86a7c Merge branch 'ffmpeg-update' into 'master'
Update ffmpeg6 and add ffmpeg9

See merge request redox-os/redox!2420
2026-11-02 17:42:22 -07:00
Jeremy Soller
c33cf12401 Merge branch 'pipelines' into 'master'
docs: Mention how MR pipelines work

See merge request redox-os/redox!2419
2026-11-02 17:42:04 -07:00
Jeremy Soller
f236d86e60 Merge branch 'meson' into 'master'
Port meson

See merge request redox-os/redox!2416
2026-11-02 17:41:33 -07:00
Wildan M
e684b923d1
cookbook: Adjustable script verbosity and cleaner strip 2026-11-03 07:30:21 +07:00
Wildan M
31b4282059
cookbook: Don't always prune sysroot with clean-target enabled 2026-11-03 06:12:25 +07:00
Jeremy Soller
721493ad46 Merge branch 'nix-fixes' into 'master'
nix: Fix stripping

See merge request redox-os/redox!2418
2026-11-02 08:32:12 -07:00
Wildan M
c57bba090a
Update curl, openssl3 and nghttp2 2026-11-02 20:44:57 +07:00
Wildan M
9bf257dbab
Update python315 2026-11-02 17:55:21 +07:00
Wildan M
b7352eecfd
Update ffmpeg6 and add ffmpeg9 2026-11-02 17:52:11 +07:00
Wildan M
d15b5f9220
docs: Mention how MR pipelines work 2026-11-02 17:19:32 +07:00
Konstantin Shabanov
aa6f01bfb2 nix: Drop autoreconf2.69 workaround 2026-11-02 14:30:37 +07:00
Konstantin Shabanov
7992e91522 nix: Fix stripping
Reduces prefix size from 7.6G to 3.1G.
2026-11-02 14:30:35 +07:00
Wildan Mubarok
604f1187b2 Merge branch 'cosmic-mon' into 'master'
Add cosmic-monitor to ci.toml

See merge request redox-os/redox!2417
2026-11-02 04:28:09 +00:00
Wildan M
8aa1de9e1a
Add cosmic-monitor to ci.toml 2026-11-01 21:08:17 +07:00
Wildan M
858a19e150
Port meson 2026-11-01 19:17:59 +07:00
30 changed files with 1198 additions and 209 deletions

View File

@ -141,6 +141,10 @@ You can see all open issues on [this](https://gitlab.redox-os.org/groups/redox-o
Please follow [our process](https://doc.redox-os.org/book/creating-proper-pull-requests.html) for creating proper pull requests.
### Pull Requests Pipelines
The GitLab CI pipelines is runnable only by maintainer review, otherwise it will be seen as "stuck". Please don't hesitate to ask in Matrix for triggering CI pipelines after being reviewed.
## Important Places to Contribute
Before starting to contribute, we recommend reading the [General FAQ](https://www.redox-os.org/faq/) and the [Redox Book](https://doc.redox-os.org/book/).

View File

@ -96,8 +96,10 @@ include mk/repo.mk
include mk/disk.mk
# Emulation recipes
include mk/virtiofs.mk
include mk/qemu.mk
include mk/virtualbox.mk
include mk/ch.mk
# CI
include mk/ci.mk

View File

@ -62,6 +62,7 @@ coreutils = {}
cosmic-edit = {}
cosmic-files = {}
cosmic-icons = {}
cosmic-monitor = {}
cosmic-reader = {}
cosmic-term = {}
cosmic-text = {}
@ -175,6 +176,7 @@ mesa = {}
mesa-glu = {}
mesa-demos = {}
mesa-demos-x11 = {}
meson = {}
mgba = {}
miniserve = {}
mpc = {}

View File

@ -104,14 +104,13 @@
#TODO: This isn't tested yet, use at your own risk
native = (pkgs.mkShell.override { stdenv = pkgs.gcc14Stdenv; }) rec {
nativeBuildInputs =
let
autoreconf269 = pkgs.writeShellScriptBin "autoreconf2.69" "${pkgs.autoconf269}/bin/autoreconf";
in
with pkgs;
[
(pkgs.writeShellScriptBin "${pkgs.stdenv.hostPlatform.system}-gnu-strip" ''
${pkgs.bintools-unwrapped}/bin/strip $@
'')
ant
autoconf
autoreconf269 # gnu-binutils
autoconf269
automake
bison
cmake

162
mk/ch.mk Normal file
View File

@ -0,0 +1,162 @@
# Configuration file for Cloud Hypervisor
#
# make ch # boot $(DISK), serial console on this terminal
# make ch share=... # also share host directories, see mk/virtiofs.mk
# make ch net=tap # use the tap device $(CH_TAP) instead of passt
# make ch net=no # no network device
# make ch-shutdown # stop the VM, from another terminal
# make ch-fetch # only download Cloud Hypervisor and its firmware
#
# x86_64 only. The guest boots through the CLOUDHV.fd UEFI firmware
# (https://github.com/cloud-hypervisor/edk2/releases). The disks are virtio-blk.
#
# Cloud Hypervisor (cloud-hypervisor-static, ch-remote-static) and the firmware
# are pinned below. They are downloaded on first use into
# build/cloud-hypervisor/$(ARCH) and checked against their sha256. Set CH,
# CH_REMOTE or CH_FIRMWARE to use other files, e.g. CH=cloud-hypervisor for
# the one in PATH.
#
# The serial console puts this terminal in raw mode, so Ctrl-C goes to Redox.
# Redox cannot power off Cloud Hypervisor by itself yet: use make ch-shutdown.
#
# The network is passt by default: a user-mode network stack, started by
# scripts/passt-run.sh, that answers the guest's DHCP and DNS and carries its
# traffic through ordinary host sockets. No tap, root or firewall changes are
# needed. The guest gets the host's address, and nothing reaches it from
# outside unless forwarded. CH_PASST_FLAGS passes options to passt, e.g.
# "-t 8022:22" (host port 8022 to guest port 22) or
# "--pcap $XDG_RUNTIME_DIR/redox.pcap" (capture the traffic).
#
# net=tap uses the tap device $(CH_TAP) instead: a real link that the host
# can reach on any port and watch with tcpdump. Creating it needs root:
# scripts/ch-tap-setup.sh (firewalld only) creates it and makes the host
# the guest's DHCP server and NAT gateway.
# Pinned releases. To update one, change its version and the sha256 of its
# assets, which GitHub shows next to each file on the release page. Every
# version is downloaded into its own directory.
CH_VERSION=v54.0
CH_FIRMWARE_VERSION=ch-97eeb7b09
CH_URL=https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/$(CH_VERSION)
CH_FIRMWARE_URL=https://github.com/cloud-hypervisor/edk2/releases/download/$(CH_FIRMWARE_VERSION)
CH_DIR=build/cloud-hypervisor/$(ARCH)
# Release assets and their sha256, per ARCH
CH_ASSET_x86_64=cloud-hypervisor-static
CH_SHA256_x86_64=4f4f98a3d661a40f3e5272627cc895a1b2e525f2f6bedf5f895f9cd21ba5c65b
CH_REMOTE_ASSET_x86_64=ch-remote-static
CH_REMOTE_SHA256_x86_64=acd5be240d5c73373effbe818908fc03e313ec8486237904bff11d93b71b1c83
CH_FIRMWARE_ASSET_x86_64=CLOUDHV.fd
CH_FIRMWARE_SHA256_x86_64=dc2fc8f0e43b96712d9fccc52a3a590769606412b3e1bc911d217addd3bef624
ifneq ($(CH_ASSET_$(ARCH)),)
CH_PINNED=$(CH_DIR)/$(CH_VERSION)/$(CH_ASSET_$(ARCH))
CH_REMOTE_PINNED=$(CH_DIR)/$(CH_VERSION)/$(CH_REMOTE_ASSET_$(ARCH))
CH_FIRMWARE_PINNED=$(CH_DIR)/edk2-$(CH_FIRMWARE_VERSION)/$(CH_FIRMWARE_ASSET_$(ARCH))
endif
CH?=$(CH_PINNED)
CH_REMOTE?=$(CH_REMOTE_PINNED)
CH_FIRMWARE?=$(CH_FIRMWARE_PINNED)
# Only the pinned files in use are downloaded.
CH_DOWNLOADS=$(filter $(CH_PINNED) $(CH_REMOTE_PINNED) $(CH_FIRMWARE_PINNED),$(CH) $(CH_REMOTE) $(CH_FIRMWARE))
CH_SMP?=4
CH_MEM?=2048
CH_API_SOCK?=$(BUILD)/ch.sock
CH_LOG?=$(BUILD)/ch.log
CH_TAP?=redox0
CH_MAC?=52:54:00:12:34:56
# Not in $(BUILD): SELinux limits passt to $XDG_RUNTIME_DIR and /tmp.
CH_PASST_SOCK?=$(or $(XDG_RUNTIME_DIR),/tmp)/redox-passt-$(ARCH)-$(CONFIG_NAME).sock
CH_PASST_FLAGS?=
CHFLAGS?=-v --log-file $(CH_LOG)
CHFLAGS+=--cpus boot=$(CH_SMP)
CHFLAGS+=--firmware $(CH_FIRMWARE)
CHFLAGS+=--serial tty --console off
CHFLAGS+=--api-socket path=$(CH_API_SOCK)
CHFLAGS+= \
--disk path=$(DISK),image_type=raw,serial=NVME_SERIAL \
--disk path=$(EXTRA_DISK),image_type=raw,serial=NVME_EXTRA
PASST_RUN=
ifeq ($(net),tap)
# The Redox virtio-net driver only acknowledges VIRTIO_NET_F_MAC at the moment.
CHFLAGS+=--net tap=$(CH_TAP),mac=$(CH_MAC),offload_tso=off,offload_ufo=off,offload_csum=off
else ifneq ($(net),no)
CHFLAGS+=--net vhost_user=true,socket=$(CH_PASST_SOCK),mac=$(CH_MAC)
PASST_RUN=scripts/passt-run.sh "$(CH_PASST_SOCK)" $(CH_PASST_FLAGS) --
endif
ch_tap_found=$(shell ip link show "$(CH_TAP)" >/dev/null 2>&1 && echo yes)
# vhost-user backends (virtiofsd, passt) need shared guest RAM.
ifneq ($(strip $(share))$(PASST_RUN),)
CHFLAGS+=--memory size=$(CH_MEM)M,shared=on
else
CHFLAGS+=--memory size=$(CH_MEM)M
endif
ifneq ($(strip $(share)),)
CHFLAGS+=$(foreach i,$(share_idx),--fs tag=$(call vfs_tag,$(i)),socket=$(call vfs_sock,$(i)))
endif
# $(1): CH, CH_REMOTE or CH_FIRMWARE. When it is set to something other than
# the pinned download, it must be an existing file or a command in PATH.
ch_check_set=$(if $(filter-out $($(1)_PINNED),$($(1))),$(if $(or $(wildcard $($(1))),$(shell command -v $($(1)))),,$(error $(1)=$($(1)) not found. Leave $(1) unset to use the pinned download)))
.PHONY: ch ch-check ch-deps ch-fetch ch-shutdown
ch-check:
$(if $(filter x86_64,$(ARCH)),,$(error Cloud Hypervisor: only ARCH=x86_64 is supported))
$(if $(filter $(HOST_ARCH),$(ARCH)),,$(error Cloud Hypervisor: ARCH=$(ARCH) cannot run on this $(HOST_ARCH) host))
$(call ch_check_set,CH)
$(call ch_check_set,CH_REMOTE)
$(call ch_check_set,CH_FIRMWARE)
$(if $(filter tap,$(net)),$(if $(ch_tap_found),,$(error no tap device $(CH_TAP). Create it with scripts/ch-tap-setup.sh or leave out net=tap to use passt)))
ch-deps: $(DISK) $(EXTRA_DISK) $(CH_DOWNLOADS)
ch-fetch: ch-check $(CH_DOWNLOADS)
ch: ch-check ch-deps
ifneq ($(wildcard $(MOUNT_DIR)),)
@echo "Disk is mounted. Unmounting the disk..."
$(MAKE) unmount
endif
@if $(CH_REMOTE) --api-socket "$(CH_API_SOCK)" ping >/dev/null 2>&1; then \
echo "ch: a VM is already running on $(CH_API_SOCK); stop it with make ch-shutdown" >&2; \
exit 1; \
fi
# A leftover socket file makes Cloud Hypervisor fail with "Address in use".
rm -f "$(CH_API_SOCK)"
$(VIRTIOFS_RUN) $(PASST_RUN) $(CH) $(CHFLAGS)
ch-shutdown: $(filter $(CH_REMOTE_PINNED),$(CH_REMOTE))
$(call ch_check_set,CH_REMOTE)
# shutdown alone would leave Cloud Hypervisor running.
$(CH_REMOTE) --api-socket "$(CH_API_SOCK)" shutdown-vmm
# Downloads $(1) to $@ if its sha256 is $(2), and sets mode $(3) if given.
# It goes through $@.partial, so $@ only ever holds a checked download.
define ch_download
mkdir -p "$(@D)"
curl -fL --retry 3 --retry-delay 1 -o "$@.partial" "$(1)"
echo "$(2) $@.partial" | sha256sum --check --quiet - \
|| { rm -f "$@.partial"; echo "ch: $(1) does not match the pinned sha256 $(2)" >&2; exit 1; }
$(if $(3),chmod $(3) "$@.partial")
mv "$@.partial" "$@"
endef
ifneq ($(CH_PINNED),)
$(CH_PINNED):
$(call ch_download,$(CH_URL)/$(@F),$(CH_SHA256_$(ARCH)),+x)
$(CH_REMOTE_PINNED):
$(call ch_download,$(CH_URL)/$(@F),$(CH_REMOTE_SHA256_$(ARCH)),+x)
$(CH_FIRMWARE_PINNED):
$(call ch_download,$(CH_FIRMWARE_URL)/$(@F),$(CH_FIRMWARE_SHA256_$(ARCH)))
endif

View File

@ -189,6 +189,20 @@ else
QEMUFLAGS+=-machine $(QEMU_MACHINE)
endif
# virtio-fs shares (share=...): the list is parsed in mk/virtiofs.mk.
ifneq ($(strip $(share)),)
# vhost-user needs guest RAM to be shared with the virtiofsd processes, and
# the NUMA memdev must be exactly as large as -m. One backend serves all
# shares.
ifeq ($(UNAME),Linux)
QEMUFLAGS+=-object memory-backend-memfd,id=mem,size=$(QEMU_MEM)M,share=on
else
QEMUFLAGS+=-object memory-backend-file,id=mem,size=$(QEMU_MEM)M,mem-path=/dev/shm,share=on
endif
QEMUFLAGS+=-numa node,memdev=mem
QEMUFLAGS+=$(foreach i,$(share_idx),-chardev socket,id=vfs$(i),path=$(call vfs_sock,$(i)) -device vhost-user-fs-pci,queue-size=1024,chardev=vfs$(i),tag=$(call vfs_tag,$(i)))
endif
ifeq ($(audio),no)
# No audio
else ifeq ($(audio),ac97)
@ -383,9 +397,9 @@ $(BUILD)/qemu_uboot.rom:
qemu: qemu-deps
ifeq ($(wildcard $(MOUNT_DIR)),)
$(QEMU) $(QEMUFLAGS)
$(VIRTIOFS_RUN) $(QEMU) $(QEMUFLAGS)
else
@echo "\033[1;38;5;196mDisk is mounted. Unmounting the disk...\033[0m";
$(MAKE) unmount
$(QEMU) $(QEMUFLAGS)
$(VIRTIOFS_RUN) $(QEMU) $(QEMUFLAGS)
endif

44
mk/virtiofs.mk Normal file
View File

@ -0,0 +1,44 @@
# Share host directories with the guest through virtio-fs (QEMU and Cloud Hypervisor).
# make qemu share=/path/to/dir # one share, tag is "host" by default
# make qemu share="tag=/path/to/dir" # one share, tag is specified as "tag"
# make qemu share=/path/a share_tag=tag # one share, tag is specified as "tag"
# make qemu share="tag_1=/path/a tag_2=/path/b" # several shares: tag=dir ...
# make qemu share=redox # this build tree, tag "redox"
# make qemu share="redox=/other/path" # ordinary share, tag "redox"
# make qemu share=/path/to/dir:ro # read-only, also tag=dir:ro and redox:ro
# make ch share=... # the same, on Cloud Hypervisor
#
# Each share gets its own host-side virtiofsd daemon (started and stopped by
# scripts/virtiofs-run.sh), a vhost-user-fs device, and a virtio-fsd scheme
# process on Redox. In the guest, a share appears at /scheme/virtio-fsd.<tag>.
# The emulator flags for each share are added in mk/qemu.mk and mk/ch.mk.
# Shared directories must exist. The guest cannot change anything in a :ro share.
#
# WARNING: share=redox exposes the whole build tree to the guest, including
# the harddrive.img Redox is booted from, .git and .config. Writing to them
# from Redox can corrupt the build system. share=redox:ro avoids that.
share?=
share_tag?=host
share_sockdir?=$(BUILD)
VIRTIOFS_RUN=
ifneq ($(strip $(share)),)
share_norm:=$(foreach s,$(share),$(if $(filter redox redox:ro,$(s)),redox=$(ROOT)$(if $(filter %:ro,$(s)),:ro),$(s)))
ifeq ($(words $(share_norm)),1)
share_list:=$(if $(findstring =,$(share_norm)),$(share_norm),$(share_tag)=$(share_norm))
else
share_list:=$(share_norm)
share_bare:=$(foreach s,$(share_list),$(if $(findstring =,$(s)),,$(s)))
ifneq ($(strip $(share_bare)),)
# Keep the next line free of leading tabs: make would read it as a recipe.
$(error share: every entry must be tag=dir when sharing several directories (bad: $(share_bare)); directories containing spaces are not supported)
endif
endif
share_idx:=$(shell seq 1 $(words $(share_list)))
vfs_entry=$(word $(1),$(share_list))
vfs_tag=$(firstword $(subst =, ,$(call vfs_entry,$(1))))
vfs_sock=$(share_sockdir)/virtiofsd-$(1).sock
VIRTIOFS_RUN=scripts/virtiofs-run.sh $(foreach i,$(share_idx),--share "$(call vfs_sock,$(i))" "$(call vfs_entry,$(i))") --
endif

View File

@ -472,6 +472,116 @@ solus()
fi
}
###############################################################################
# virtiofsd is needed on the host by `make qemu share=<dir>` to share
# directories with Redox (scripts/virtiofs-run.sh only looks for it).
###############################################################################
virtiofsd_find()
{
local c
for c in "${VIRTIOFSD:-}" virtiofsd /usr/libexec/virtiofsd /usr/lib/qemu/virtiofsd \
"${XDG_CACHE_HOME:-$HOME/.cache}/virtiofsd-redox/virtiofsd"; do
[ -n "$c" ] || continue
if [ -f "$c" ] && [ -x "$c" ]; then
echo "$c"
return 0
fi
if command -v "$c" >/dev/null 2>&1; then
command -v "$c"
return 0
fi
done
return 1
}
###############################################################################
# Download a static x86_64 virtiofsd build from the upstream CI into
# ~/.cache/virtiofsd-redox, after asking for confirmation.
# Override the source with VIRTIOFSD_URL.
#
# TODO: this is the CI build of upstream's main branch, so it is neither
# pinned nor checked: virtiofsd releases do not ship binaries or checksums
# yet. Once they do, move this download into mk/virtiofs.mk, pinned to a
# release and checked against its sha256 like Cloud Hypervisor in mk/ch.mk,
# and pass it to scripts/virtiofs-run.sh through VIRTIOFSD.
###############################################################################
virtiofsd_download()
{
local url cache dest tmp answer
url="${VIRTIOFSD_URL:-https://gitlab.com/virtio-fs/virtiofsd/-/jobs/artifacts/main/raw/target/x86_64-unknown-linux-musl/release/virtiofsd?job=publish}"
cache="${XDG_CACHE_HOME:-$HOME/.cache}/virtiofsd-redox"
dest="$cache/virtiofsd"
if [ "$(uname -m)" != "x86_64" ]; then
echo "No prebuilt virtiofsd is available for $(uname -m)."
return 1
fi
echo "A static virtiofsd build can be downloaded from"
echo " gitlab.com/virtio-fs/virtiofsd (CI artifact of the main branch)"
echo "to $dest"
printf "Download it now? (y/N): "
read answer || answer=""
if ! echo "$answer" | grep -iq "^y"; then
return 1
fi
mkdir -p "$cache"
tmp="$(mktemp "$cache/virtiofsd.XXXXXX")"
if command -v curl >/dev/null 2>&1; then
curl -fL --retry 3 --retry-delay 1 -o "$tmp" "$url" || { rm -f "$tmp"; return 1; }
elif command -v wget >/dev/null 2>&1; then
wget -O "$tmp" "$url" || { rm -f "$tmp"; return 1; }
else
echo "Need curl or wget to download virtiofsd."
rm -f "$tmp"
return 1
fi
if [ "$(head -c 4 "$tmp")" != "$(printf '\177ELF')" ]; then
echo "The download is not an ELF binary (see $url)."
rm -f "$tmp"
return 1
fi
chmod +x "$tmp"
mv -f "$tmp" "$dest"
echo "virtiofsd installed at $dest"
}
###############################################################################
# This function makes sure virtiofsd is available: it looks for an existing
# one, then tries the distribution package, then offers a download.
# It never fails the bootstrap, virtiofsd is only needed for `share=`.
# @params: $1 the package manager to use on Debian-based Linux
###############################################################################
virtiofsd_setup()
{
local found
echo "Checking for virtiofsd (used by 'make qemu share=<dir>')..."
if found="$(virtiofsd_find)"; then
echo "virtiofsd found at $found"
return 0
fi
echo "virtiofsd not found."
if command -v pacman >/dev/null 2>&1; then
sudo pacman -S --needed virtiofsd || true
elif command -v dnf >/dev/null 2>&1; then
sudo dnf install virtiofsd || true
elif command -v apt-get >/dev/null 2>&1 && apt-cache show virtiofsd >/dev/null 2>&1; then
sudo "$1" install virtiofsd || true
fi
if found="$(virtiofsd_find)"; then
echo "virtiofsd found at $found"
return 0
fi
if virtiofsd_download; then
return 0
fi
echo "Continuing without virtiofsd. 'make qemu share=<dir>' will not work until"
echo "it is installed (or set VIRTIOFSD=/path/to/virtiofsd), re-run this script"
echo "with -d to retry."
}
######################################################################
# This function outlines the different options available for bootstrap
######################################################################
@ -659,6 +769,11 @@ else
fi
fi
# Directory sharing with `make qemu share=<dir>` needs virtiofsd and a Linux host
if [ "$emulator" == "qemu" ] && [ "$(uname -s)" == "Linux" ]; then
virtiofsd_setup "$defpackman"
fi
if [ "$dependenciesonly" = false ]; then
boot
fi

View File

@ -1,76 +0,0 @@
From effadce6c756247ea8bae32dc13bb3e6f464f0eb Mon Sep 17 00:00:00 2001
From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= <remi@remlab.net>
Date: Sun, 16 Jul 2023 18:18:02 +0300
Subject: [PATCH] avcodec/x86/mathops: clip constants used with shift
instructions within inline assembly
Fixes assembling with binutil as >= 2.41
Signed-off-by: James Almer <jamrial@gmail.com>
---
libavcodec/x86/mathops.h | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/libavcodec/x86/mathops.h b/libavcodec/x86/mathops.h
index 6298f5ed19..ca7e2dffc1 100644
--- a/libavcodec/x86/mathops.h
+++ b/libavcodec/x86/mathops.h
@@ -35,12 +35,20 @@
static av_always_inline av_const int MULL(int a, int b, unsigned shift)
{
int rt, dummy;
+ if (__builtin_constant_p(shift))
__asm__ (
"imull %3 \n\t"
"shrdl %4, %%edx, %%eax \n\t"
:"=a"(rt), "=d"(dummy)
- :"a"(a), "rm"(b), "ci"((uint8_t)shift)
+ :"a"(a), "rm"(b), "i"(shift & 0x1F)
);
+ else
+ __asm__ (
+ "imull %3 \n\t"
+ "shrdl %4, %%edx, %%eax \n\t"
+ :"=a"(rt), "=d"(dummy)
+ :"a"(a), "rm"(b), "c"((uint8_t)shift)
+ );
return rt;
}
@@ -113,19 +121,31 @@ __asm__ volatile(\
// avoid +32 for shift optimization (gcc should do that ...)
#define NEG_SSR32 NEG_SSR32
static inline int32_t NEG_SSR32( int32_t a, int8_t s){
+ if (__builtin_constant_p(s))
__asm__ ("sarl %1, %0\n\t"
: "+r" (a)
- : "ic" ((uint8_t)(-s))
+ : "i" (-s & 0x1F)
);
+ else
+ __asm__ ("sarl %1, %0\n\t"
+ : "+r" (a)
+ : "c" ((uint8_t)(-s))
+ );
return a;
}
#define NEG_USR32 NEG_USR32
static inline uint32_t NEG_USR32(uint32_t a, int8_t s){
+ if (__builtin_constant_p(s))
__asm__ ("shrl %1, %0\n\t"
: "+r" (a)
- : "ic" ((uint8_t)(-s))
+ : "i" (-s & 0x1F)
);
+ else
+ __asm__ ("shrl %1, %0\n\t"
+ : "+r" (a)
+ : "c" ((uint8_t)(-s))
+ );
return a;
}
--
2.30.2

View File

@ -1,7 +1,7 @@
diff -rupN source-original/configure source/configure
--- source-original/configure 2018-03-04 11:13:59.000000000 +0100
+++ source/configure 2018-03-04 11:18:10.026033282 +0100
@@ -5141,6 +5141,8 @@ case $target_os in
diff -ruwN source/configure source-new/configure
--- source/configure 2026-05-05 14:22:01.000000000 +0000
+++ source-new/configure 2026-11-02 05:18:51.788806151 +0000
@@ -5814,6 +5814,8 @@
;;
minix)
;;
@ -10,15 +10,3 @@ diff -rupN source-original/configure source/configure
none)
;;
*)
diff -rupN source-original/fftools/ffmpeg.c source/fftools/ffmpeg.c
--- source-original/fftools/ffmpeg.c 2018-03-04 11:13:59.000000000 +0100
+++ source/fftools/ffmpeg.c 2018-03-04 11:45:38.326394016 +0100
@@ -91,7 +91,7 @@
#if HAVE_TERMIOS_H
#include <fcntl.h>
-#include <sys/ioctl.h>
+//#include <sys/ioctl.h>
#include <sys/time.h>
#include <termios.h>
#elif HAVE_KBHIT

View File

@ -1,9 +1,8 @@
[source]
tar = "https://ffmpeg.org/releases/ffmpeg-6.0.tar.xz"
blake3 = "4879074c357102f85932673044c57c144b0c188ae58edec2a115965536ee340f"
tar = "https://ffmpeg.org/releases/ffmpeg-6.1.5.tar.xz"
blake3 = "da8e6743d96f27d5b5425339218f9a954d9440cb27ba449b449d686b411292e9"
patches = [
"ffmpeg.patch",
"binutils-2.41.patch",
]
[build]

View File

@ -1,6 +1,6 @@
[source]
tar = "https://github.com/nghttp2/nghttp2/releases/download/v1.64.0/nghttp2-1.64.0.tar.xz"
blake3 = "1bbc08de4816769d800c42f501a00c1ba3f5efa1b76e1f65d2e5bdf3aa30354d"
tar = "https://github.com/nghttp2/nghttp2/releases/download/v1.69.0/nghttp2-1.69.0.tar.xz"
blake3 = "dd7432762ac454aaa14ff3b29d40d5b8f641ec3c33e4e24c5ed70e971ac6987b"
script = """
autotools_recursive_regenerate
"""
@ -14,4 +14,4 @@ COOKBOOK_CONFIGURE_FLAGS+=(
--enable-lib-only
)
cookbook_configure
"""
"""

View File

@ -1,6 +1,6 @@
[source]
tar = "https://github.com/openssl/openssl/releases/download/openssl-3.5.3/openssl-3.5.3.tar.gz"
blake3 = "e1622a4587c71c278355bf38ff5a619918bd51e3cd37214d53dd5345b187fc10"
tar = "https://github.com/openssl/openssl/releases/download/openssl-3.5.9/openssl-3.5.9.tar.gz"
blake3 = "be2f7530fe5cd02a06e67d8916e6574f1c53b8071393aae2364b4ed817cf0354"
patches = [ "redox.patch" ]
[build]

View File

@ -1,19 +1,19 @@
diff -ruwN source/apps/lib/apps.c source-new/apps/lib/apps.c
--- source/apps/lib/apps.c 2025-09-16 19:05:33.000000000 +0700
+++ source-new/apps/lib/apps.c 2026-05-05 05:08:40.007422945 +0700
@@ -2839,7 +2839,7 @@
--- source/apps/lib/apps.c 2026-09-29 14:05:00.000000000 +0000
+++ source-new/apps/lib/apps.c 2026-11-02 13:12:01.017080874 +0000
@@ -2863,7 +2863,7 @@
return ret;
}
-#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
+#elif defined(_SC_CLK_TCK) && !defined(__RELIBC__) /* by means of unistd.h */
# include <sys/times.h>
-#elif defined(_SC_CLK_TCK) /* by means of unistd.h */
+#elif defined(_SC_CLK_TCK) && !defined(__RELIBC__) /* by means of unistd.h */
#include <sys/times.h>
double app_tminterval(int stop, int usertime)
diff -ruwN source/Configurations/10-main.conf source-new/Configurations/10-main.conf
--- source/Configurations/10-main.conf 2025-09-16 19:05:33.000000000 +0700
+++ source-new/Configurations/10-main.conf 2026-05-05 05:08:44.812616321 +0700
@@ -208,6 +208,40 @@
--- source/Configurations/10-main.conf 2026-09-29 14:05:00.000000000 +0000
+++ source-new/Configurations/10-main.conf 2026-11-02 13:09:11.387128346 +0000
@@ -209,6 +209,40 @@
shared_extension => ".so",
},
@ -54,7 +54,7 @@ diff -ruwN source/Configurations/10-main.conf source-new/Configurations/10-main.
#### Solaris configurations
"solaris-common" => {
inherit_from => [ "BASE_unix" ],
@@ -693,7 +727,6 @@
@@ -694,7 +728,6 @@
shared_target => "linux-shared",
shared_cflag => "-fPIC",
shared_ldflag => sub { $disabled{pinshared} ? () : "-Wl,-znodelete" },
@ -62,7 +62,7 @@ diff -ruwN source/Configurations/10-main.conf source-new/Configurations/10-main.
},
"linux-latomic" => {
inherit_from => [ "linux-generic32" ],
@@ -890,7 +923,6 @@
@@ -891,7 +924,6 @@
bn_ops => "SIXTY_FOUR_BIT_LONG",
asm_arch => 'x86_64',
perlasm_scheme => "elf",
@ -71,14 +71,14 @@ diff -ruwN source/Configurations/10-main.conf source-new/Configurations/10-main.
"linux-x86_64-clang" => {
inherit_from => [ "linux-x86_64" ],
diff -ruwN source/include/crypto/rand.h source-new/include/crypto/rand.h
--- source/include/crypto/rand.h 2025-09-16 19:05:33.000000000 +0700
+++ source-new/include/crypto/rand.h 2026-05-05 05:08:40.007980910 +0700
@@ -41,7 +41,7 @@
--- source/include/crypto/rand.h 2026-09-29 14:05:00.000000000 +0000
+++ source-new/include/crypto/rand.h 2026-11-02 13:10:37.658190042 +0000
@@ -40,7 +40,7 @@
* default, we will try to read at least one of these files
*/
# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
-# if defined(__linux) && !defined(__ANDROID__)
+# if defined(__linux) && !defined(__RELIBC__) && !defined(__ANDROID__) /* needs sys/shm.h */
# ifndef DEVRANDOM_WAIT
# define DEVRANDOM_WAIT "/dev/random"
# endif
#define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
-#if defined(__linux) && !defined(__ANDROID__)
+#if defined(__linux) && !defined(__ANDROID__) && !defined(__RELIBC__) /* needs sys/shm.h */
#ifndef DEVRANDOM_WAIT
#define DEVRANDOM_WAIT "/dev/random"
#endif

View File

@ -1,29 +0,0 @@
diff --git a/lib/asyn-thrdd.c b/lib/asyn-thrdd.c
index 90f055c2..4db5ab02 100644
--- a/lib/asyn-thrdd.c
+++ b/lib/asyn-thrdd.c
@@ -481,7 +481,11 @@ static void async_thrdd_report_item(struct Curl_easy *data,
struct dynbuf tmp;
const char *sep = "";
const struct Curl_addrinfo *ai = item->res;
+#ifdef USE_IPV6
int ai_family = (item->dns_queries & CURL_DNSQ_AAAA) ? AF_INET6 : AF_INET;
+#else
+ int ai_family = AF_INET;
+#endif
CURLcode result;
if(!CURL_TRC_DNS_is_verbose(data))
@@ -789,10 +793,12 @@ const struct Curl_addrinfo *Curl_async_get_ai(struct Curl_easy *data,
if(thrdd->res_A)
return async_thrdd_get_ai(thrdd->res_A->res, ai_family, index);
break;
+#ifdef USE_IPV6
case AF_INET6:
if(thrdd->res_AAAA)
return async_thrdd_get_ai(thrdd->res_AAAA->res, ai_family, index);
break;
+#endif
default:
break;
}

View File

@ -1,7 +1,7 @@
[source]
git = "https://github.com/curl/curl.git"
rev = "curl-8_20_0"
patches = ["ipv6.patch", "redox.patch"]
rev = "curl-8_23_0"
patches = ["redox.patch"]
shallow_clone = true
[build]
@ -16,12 +16,10 @@ cmakeflags = [
"-DCURL_DISABLE_FTP=On",
"-DCURL_DISABLE_TFTP=On",
"-DENABLE_IPV6=Off",
"-DCURL_DISABLE_NTLM=On",
"-DENABLE_THREADED_RESOLVER=On",
"-DCURL_CA_PATH=/etc/ssl/certs",
"-DUSE_NGHTTP2=On",
"-DCURL_USE_OPENSSL=On",
"-DUSE_ZLIB=On",
"-DCURL_USE_LIBPSL=Off",
]

View File

@ -1,5 +1,5 @@
diff --git a/curl-config.in b/curl-config.in
index a1c8185875..326ea2b9d3 100644
index a1c81858..326ea2b9 100644
--- a/curl-config.in
+++ b/curl-config.in
@@ -167,7 +167,7 @@ while test "$#" -gt 0; do
@ -12,7 +12,7 @@ index a1c8185875..326ea2b9d3 100644
echo 'curl was built with static libraries disabled' >&2
exit 1
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 6961a6c4c1..66221b85e3 100644
index ccc9a09a..2aa0e69c 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -88,7 +88,7 @@
@ -24,7 +24,7 @@ index 6961a6c4c1..66221b85e3 100644
defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \
defined(__CYGWIN__) || defined(AMIGA) || defined(__NuttX__) || \
(defined(__FreeBSD_version) && (__FreeBSD_version < 800000)) || \
@@ -975,11 +975,11 @@ typedef enum {
@@ -987,11 +987,11 @@ typedef enum {
/* Backwards compatibility with older names */
/* These are scheduled to disappear by 2009 */
@ -42,10 +42,10 @@ index 6961a6c4c1..66221b85e3 100644
#endif /* !CURL_NO_OLDIES */
diff --git a/libcurl.pc.in b/libcurl.pc.in
index c0ba5244a8..7898dae358 100644
index 8f7e35dd..78650251 100644
--- a/libcurl.pc.in
+++ b/libcurl.pc.in
@@ -36,6 +36,6 @@ Version: @CURLVERSION@
@@ -40,7 +40,7 @@ Source: https://curl.se/download/curl-@CURLVERSION@.tar.gz
Requires: @LIBCURL_PC_REQUIRES@
Requires.private: @LIBCURL_PC_REQUIRES_PRIVATE@
Libs: -L${libdir} -lcurl @LIBCURL_PC_LIBS@
@ -53,3 +53,4 @@ index c0ba5244a8..7898dae358 100644
+Libs.private: @LIBCURL_PC_LIBS_PRIVATE@
Cflags: -I${includedir} @LIBCURL_PC_CFLAGS@
Cflags.private: @LIBCURL_PC_CFLAGS_PRIVATE@
Link.ABI: c

View File

@ -0,0 +1,7 @@
[source]
# The selftest is a member of the base workspace (base/selftests/virtio-fsd)
same_as = "../../core/base"
[build]
template = "cargo"
cargopackages = ["virtio-fsd-selftest"]

View File

@ -1,5 +1,18 @@
#TODO create a standalone script: https://github.com/mesonbuild/meson#creating-a-standalone-script
#TODO compiled but not tested
[source]
tar = "https://github.com/mesonbuild/meson/releases/download/1.3.0/meson-1.3.0.tar.gz"
git = "https://github.com/mesonbuild/meson"
rev = "1.12.1"
shallow_clone = true
[build]
template = "custom"
template = "python"
dev-dependencies = [
"host:python312",
"python312",
"python3-setuptools",
]
[package]
dependencies = [
"python312",
]

View File

@ -1,7 +1,7 @@
# TODO: Not tested
[source]
tar = "https://www.python.org/ftp/python/3.15.0/Python-3.15.0a8.tar.xz"
blake3 = "b1e24434fc15b352b07222e44e6ff12ce14bbbe8535928a13123ee6a49fa6541"
tar = "https://www.python.org/ftp/python/3.15.2/Python-3.15.2.tar.xz"
blake3 = "be2eb5c42e774473b40d02c6c74839dec00b779ec24c593cb324b4f8c460acf4"
patches = [
"redox.patch"
]
@ -54,7 +54,7 @@ fi
cookbook_configure
# A same file to save 73MB
(cd "${COOKBOOK_STAGE}/usr/lib/python3.15/config-3.15" && \
(cd "${COOKBOOK_STAGE}/usr/lib/python3.15/config-3.15-${ARCH}-${OS}" && \
rm -f libpython3.15.a && ln -s ../../libpython3.15.a)
"""

View File

@ -1,7 +1,7 @@
diff -ruwN source/configure source-new/configure
--- source/configure 2026-04-07 18:24:03.000000000 +0700
+++ source-new/configure 2026-05-07 12:19:48.765197728 +0700
@@ -4163,6 +4163,9 @@
--- source/configure 2026-10-25 16:57:51.000000000 +0000
+++ source-new/configure 2026-11-02 05:14:13.172455982 +0000
@@ -4178,6 +4178,9 @@
*-*-wasi*)
ac_sys_system=WASI
;;
@ -11,7 +11,7 @@ diff -ruwN source/configure source-new/configure
*)
# for now, limit cross builds to known configurations
MACHDEP="unknown"
@@ -4189,6 +4192,7 @@
@@ -4204,6 +4207,7 @@
freebsd*) MACHDEP="freebsd";;
linux-android*) MACHDEP="android";;
linux*) MACHDEP="linux";;
@ -19,7 +19,7 @@ diff -ruwN source/configure source-new/configure
cygwin*) MACHDEP="cygwin";;
darwin*) MACHDEP="darwin";;
'') MACHDEP="unknown";;
@@ -4615,7 +4619,7 @@
@@ -4630,7 +4634,7 @@
if test "$cross_compiling" = yes; then
case "$host" in
@ -28,7 +28,7 @@ diff -ruwN source/configure source-new/configure
case "$host_cpu" in
arm*)
_host_ident=arm
@@ -7771,7 +7775,7 @@
@@ -7813,7 +7817,7 @@
PY3LIBRARY=libpython3.so
fi
;;
@ -37,7 +37,7 @@ diff -ruwN source/configure source-new/configure
LDLIBRARY='libpython$(LDVERSION).so'
BLDLIBRARY='-L. -lpython$(LDVERSION)'
RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
@@ -13777,7 +13781,7 @@
@@ -14234,7 +14238,7 @@
Emscripten*|WASI*)
LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared';;
@ -46,7 +46,7 @@ diff -ruwN source/configure source-new/configure
LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared';;
FreeBSD*)
@@ -13862,7 +13866,7 @@
@@ -14319,7 +14323,7 @@
then CCSHARED="-fPIC";
else CCSHARED="+z";
fi;;
@ -55,7 +55,7 @@ diff -ruwN source/configure source-new/configure
Emscripten*|WASI*)
if test "x$enable_wasm_dynamic_linking" = xyes
then :
@@ -13900,7 +13904,7 @@
@@ -14357,7 +14361,7 @@
LINKFORSHARED="-Wl,-E -Wl,+s";;
# LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
@ -65,8 +65,8 @@ diff -ruwN source/configure source-new/configure
Darwin/*|iOS/*)
LINKFORSHARED="$extra_undefs -framework CoreFoundation"
diff -ruwN source/Include/internal/pycore_time.h source-new/Include/internal/pycore_time.h
--- source/Include/internal/pycore_time.h 2026-04-07 18:24:03.000000000 +0700
+++ source-new/Include/internal/pycore_time.h 2026-05-07 12:55:06.797297037 +0700
--- source/Include/internal/pycore_time.h 2026-10-25 16:57:51.000000000 +0000
+++ source-new/Include/internal/pycore_time.h 2026-11-02 05:14:13.172455982 +0000
@@ -49,6 +49,10 @@
#ifndef Py_INTERNAL_TIME_H
@ -79,9 +79,9 @@ diff -ruwN source/Include/internal/pycore_time.h source-new/Include/internal/pyc
extern "C" {
#endif
diff -ruwN source/Include/pyport.h source-new/Include/pyport.h
--- source/Include/pyport.h 2026-04-07 18:24:03.000000000 +0700
+++ source-new/Include/pyport.h 2026-05-07 12:16:56.305047939 +0700
@@ -541,7 +541,7 @@
--- source/Include/pyport.h 2026-10-25 16:57:51.000000000 +0000
+++ source-new/Include/pyport.h 2026-11-02 05:14:13.173456040 +0000
@@ -502,7 +502,7 @@
# endif
#endif
@ -91,9 +91,9 @@ diff -ruwN source/Include/pyport.h source-new/Include/pyport.h
// See _Py_GetLocaleEncoding(), PyUnicode_DecodeLocale()
// and PyUnicode_EncodeLocale().
diff -ruwN source/Modules/posixmodule.c source-new/Modules/posixmodule.c
--- source/Modules/posixmodule.c 2026-04-07 18:24:03.000000000 +0700
+++ source-new/Modules/posixmodule.c 2026-05-07 12:57:16.208883903 +0700
@@ -11253,7 +11253,7 @@
--- source/Modules/posixmodule.c 2026-10-25 16:57:51.000000000 +0000
+++ source-new/Modules/posixmodule.c 2026-11-02 05:14:13.174456099 +0000
@@ -11340,7 +11340,7 @@
struct tms process;
clock_t elapsed;
errno = 0;
@ -103,8 +103,8 @@ diff -ruwN source/Modules/posixmodule.c source-new/Modules/posixmodule.c
return posix_error();
}
diff -ruwN source/Modules/resource.c source-new/Modules/resource.c
--- source/Modules/resource.c 2026-04-07 18:24:03.000000000 +0700
+++ source-new/Modules/resource.c 2026-05-07 12:16:56.305184305 +0700
--- source/Modules/resource.c 2026-10-25 16:57:51.000000000 +0000
+++ source-new/Modules/resource.c 2026-11-02 05:14:13.174456099 +0000
@@ -245,7 +245,7 @@
{
struct rlimit rl;

View File

@ -0,0 +1,44 @@
# TODO: need j1 relibc function
[source]
tar = "https://ffmpeg.org/releases/ffmpeg-9.0.2.tar.xz"
patches = [
"redox.patch"
]
[build]
template = "custom"
dependencies = [
"liborbital",
"mesa",
"sdl2",
"zlib",
]
dev-dependencies = [
"libstdcxx"
]
compiler = "gcc-no-lto"
script = """
DYNAMIC_INIT
export LDFLAGS="$LDFLAGS -lSDL2 -lorbital -lOSMesa"
ARCH="${TARGET%%-*}"
COOKBOOK_CONFIGURE_FLAGS=(
--enable-cross-compile
--target-os=redox
--arch="${ARCH}"
--cross_prefix="${TARGET}-"
--prefix=/usr
--disable-doc
--enable-shared
--disable-static
--disable-network
--enable-sdl2
--enable-zlib
--enable-pic
--enable-encoder=png
--enable-decoder=png
)
cookbook_configure
mkdir -pv "${COOKBOOK_STAGE}/usr/share/ui/apps"
cp -v "${COOKBOOK_RECIPE}/manifest" "${COOKBOOK_STAGE}/usr/share/ui/apps/ffplay"
"""

View File

@ -0,0 +1,13 @@
diff -ruwN source/configure source-new/configure
--- source/configure 2026-08-03 22:14:47.000000000 +0000
+++ source-new/configure 2026-11-02 10:38:23.591367435 +0000
@@ -6377,6 +6377,9 @@
;;
minix)
;;
+ redox)
+ enable section_data_rel_ro
+ ;;
none)
;;
*)

365
scripts/ch-tap-setup.sh Executable file
View File

@ -0,0 +1,365 @@
#!/usr/bin/env bash
# Host setup for `make ch net=tap`: tap redox0, IPv4 forwarding, firewalld NAT
# and dnsmasq DHCP/DNS. Needs firewalld and dnsmasq. Re-run after a reboot.
# As root without sudo, set TAP_USER=<user>.
set -euo pipefail
# Debian does not put the sbin directories in a normal user's PATH.
PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin"
TAP=redox0
GUEST_MAC=52:54:00:12:34:56
TAP_ADDR=192.168.249.1
TAP_CIDR="${TAP_ADDR}/24"
DHCP_FIRST=192.168.249.10
DHCP_LAST=192.168.249.50
DHCP_RANGE="${DHCP_FIRST},${DHCP_LAST},255.255.255.0,12h"
ZONE=chnet
POLICY=chnet-nat
SYSCTL_DROPIN=/etc/sysctl.d/90-redox-tap.conf
DNSMASQ_PID=/run/redox0-dnsmasq.pid
WAIT_TIMEOUT=3 # seconds
step() {
printf '\n==> %s\n' "$*"
}
info() {
printf ' %s\n' "$*"
}
die() {
echo "error: $*" >&2
exit 1
}
as_root() {
if [[ "${EUID}" -eq 0 ]]; then
"$@"
else
sudo "$@"
fi
}
wait_until() {
local deadline=$((SECONDS + $1))
shift
until "$@"; do
((SECONDS < deadline)) || return 1
sleep 0.1
done
}
# Only tun/tap devices have tun_flags. IFF_TAP is 0x0002, IFF_UP is 0x1,
# owner -1 means none.
tap_exists() {
[[ -e "/sys/class/net/${TAP}" ]]
}
is_tap() {
[[ -r "/sys/class/net/${TAP}/tun_flags" ]] \
&& (($(<"/sys/class/net/${TAP}/tun_flags") & 0x0002))
}
tap_owner() {
cat "/sys/class/net/${TAP}/owner"
}
link_is_up() {
(($(<"/sys/class/net/${TAP}/flags") & 0x1))
}
tap_addrs() {
ip -o -4 addr show dev "${TAP}" | awk '{ print $4 }'
}
has_addr() {
tap_addrs | grep -qx "${TAP_CIDR}"
}
forwarding_on() {
[[ "$(sysctl -n net.ipv4.ip_forward)" == "1" ]]
}
forwarding_persisted_by() {
grep -RlsE '^[[:space:]]*net\.ipv4\.ip_forward[[:space:]]*=[[:space:]]*1[[:space:]]*(#.*)?$' \
/etc/sysctl.conf /etc/sysctl.d /usr/lib/sysctl.d | head -n 1
}
FW_CHANGED=0
fw_ensure_exists() {
local kind="$1" name="$2" list
case "${kind}" in
zone) list=--get-zones ;;
policy) list=--get-policies ;;
esac
if firewall-cmd --permanent "${list}" | tr ' ' '\n' | grep -qx "${name}"; then
info "${kind} ${name}: exists"
else
info "${kind} ${name}: creating"
as_root firewall-cmd --permanent "--new-${kind}=${name}" >/dev/null
FW_CHANGED=1
fi
}
fw_ensure() {
local what="$1" scope="$2" query="$3" add="$4"
if firewall-cmd --permanent "${scope}" "${query}" >/dev/null; then
info "${what}: already set"
else
info "${what}: adding"
as_root firewall-cmd --permanent "${scope}" "${add}" >/dev/null
FW_CHANGED=1
fi
}
# --get-target is permanent-only. The runtime value is the target: line.
policy_accepts() {
[[ "$(firewall-cmd --policy="${POLICY}" --list-all | awk '$1 == "target:" { print $2 }')" == "ACCEPT" ]]
}
dnsmasq_pids() {
pgrep -f "(^|/)dnsmasq .*--interface=${TAP}( |$)" || true
}
# dnsmasq binds DHCP to 0.0.0.0%redox0:67 but DNS to 192.168.249.1:53.
dhcp_listening() {
ss -H -uln | awk -v t="${TAP}" '$4 ~ ("%" t ":67$") { f = 1 } END { exit !f }'
}
dns_listening() {
ss -H -uln | awk -v a="${TAP_ADDR}" -v t="${TAP}" \
'$4 == (a ":53") || $4 == (a "%" t ":53") { f = 1 } END { exit !f }'
}
dnsmasq_answering() {
dhcp_listening && dns_listening
}
dhcp_port_free() {
! dhcp_listening
}
preflight() {
if [[ -z "${TAP_USER:-}" ]]; then
if [[ "${EUID}" -eq 0 ]]; then
TAP_USER="${SUDO_USER:-}"
else
TAP_USER="$(id -un)"
fi
fi
if [[ -z "${TAP_USER}" || "${TAP_USER}" == "root" ]]; then
die "run this as the user that starts cloud-hypervisor (sudo from that user is fine), or set TAP_USER=<user>."
fi
TAP_UID="$(id -u "${TAP_USER}")" || die "no such user: ${TAP_USER}"
if ! command -v firewall-cmd >/dev/null 2>&1 || ! firewall-cmd --state >/dev/null 2>&1; then
die "firewalld is not running. This script only supports firewalld; without it, use plain 'make ch', whose passt network needs no tap."
fi
local cmd
for cmd in ip sysctl dnsmasq ss pgrep; do
command -v "${cmd}" >/dev/null 2>&1 || die "missing command: ${cmd}"
done
echo "Setting up ${TAP} for 'make ch net=tap': host ${TAP_CIDR}, guest DHCP pool ${DHCP_FIRST}-${DHCP_LAST}."
if [[ "${EUID}" -ne 0 ]]; then
echo "Privileged steps run through sudo, which may ask you to authenticate."
fi
}
setup_tap() {
step "Tap device ${TAP}"
TAP_IS_NEW=0
if tap_exists; then
is_tap || die "${TAP} exists but is not a tap device. Remove or rename it first."
local owner
owner="$(tap_owner)"
if [[ "${owner}" == "${TAP_UID}" ]]; then
info "exists and is owned by ${TAP_USER} (uid ${TAP_UID}), keeping it"
return
fi
if [[ "${owner}" == "-1" ]]; then
info "exists but has no owner, not ${TAP_USER} (uid ${TAP_UID}): deleting it"
else
info "exists but is owned by uid ${owner}, not ${TAP_USER} (uid ${TAP_UID}): deleting it"
fi
as_root ip link del "${TAP}"
else
info "does not exist"
fi
info "creating it, owned by ${TAP_USER} so cloud-hypervisor can open it without root"
as_root ip tuntap add "${TAP}" mode tap user "${TAP_USER}"
TAP_IS_NEW=1
}
setup_address() {
step "Host address ${TAP_CIDR} on ${TAP} (the guest's gateway and DNS server)"
local addr
for addr in $(tap_addrs); do
[[ "${addr}" == "${TAP_CIDR}" ]] || die "${TAP} already has ${addr}; this script expects ${TAP_CIDR}."
done
if has_addr; then
info "already set"
else
info "adding it"
as_root ip addr add "${TAP_CIDR}" dev "${TAP}"
fi
if link_is_up; then
info "link is already up"
else
info "setting the link up"
as_root ip link set "${TAP}" up
fi
}
setup_forwarding() {
step "IPv4 forwarding (routes guest packets out of the host)"
if forwarding_on; then
info "net.ipv4.ip_forward is already 1"
else
info "setting net.ipv4.ip_forward=1"
as_root sysctl -q -w net.ipv4.ip_forward=1
fi
local persist
persist="$(forwarding_persisted_by || true)"
if [[ -n "${persist}" ]]; then
info "kept across reboots by ${persist}"
else
info "writing ${SYSCTL_DROPIN} so it survives a reboot"
printf 'net.ipv4.ip_forward = 1\n' | as_root tee "${SYSCTL_DROPIN}" >/dev/null
fi
}
setup_firewalld() {
step "firewalld zone ${ZONE} (lets the guest reach dnsmasq on the host)"
fw_ensure_exists zone "${ZONE}"
fw_ensure "interface ${TAP}" --zone="${ZONE}" --query-interface="${TAP}" --add-interface="${TAP}"
fw_ensure "service dhcp (UDP 67)" --zone="${ZONE}" --query-service=dhcp --add-service=dhcp
fw_ensure "service dns (port 53)" --zone="${ZONE}" --query-service=dns --add-service=dns
step "firewalld policy ${POLICY} (forwards and masquerades guest traffic to the outside)"
fw_ensure_exists policy "${POLICY}"
fw_ensure "ingress zone ${ZONE}" --policy="${POLICY}" --query-ingress-zone="${ZONE}" --add-ingress-zone="${ZONE}"
fw_ensure "egress zone ANY" --policy="${POLICY}" --query-egress-zone=ANY --add-egress-zone=ANY
if [[ "$(firewall-cmd --permanent --policy="${POLICY}" --get-target)" == "ACCEPT" ]]; then
info "target ACCEPT: already set"
else
info "target ACCEPT: setting"
as_root firewall-cmd --permanent --policy="${POLICY}" --set-target=ACCEPT >/dev/null
FW_CHANGED=1
fi
fw_ensure "masquerade" --policy="${POLICY}" --query-masquerade --add-masquerade
step "Applying firewalld settings"
if [[ "${FW_CHANGED}" -eq 1 ]]; then
info "reloading firewalld to apply the permanent changes"
as_root firewall-cmd --reload >/dev/null
else
info "nothing changed, no reload needed"
fi
# firewalld does not always attach an interface that appeared after it
# started.
if firewall-cmd --zone="${ZONE}" --query-interface="${TAP}" >/dev/null; then
info "${TAP} is in zone ${ZONE} at runtime"
else
info "attaching ${TAP} to zone ${ZONE} at runtime (firewalld missed the new interface)"
as_root firewall-cmd --zone="${ZONE}" --add-interface="${TAP}" >/dev/null
fi
}
# dnsmasq --bind-interfaces keeps the old interface index, so a new tap needs
# a new dnsmasq.
setup_dnsmasq() {
step "dnsmasq on ${TAP} (DHCP ${DHCP_FIRST}-${DHCP_LAST}, gateway and DNS ${TAP_ADDR})"
local pids pid
mapfile -t pids < <(dnsmasq_pids)
if [[ "${TAP_IS_NEW}" -eq 0 ]] && dnsmasq_answering; then
info "already answering DHCP and DNS (pid ${pids[*]:-unknown}), keeping it"
return
fi
if [[ "${TAP_IS_NEW}" -eq 0 ]]; then
info "dnsmasq is not answering both DHCP and DNS on ${TAP}"
elif [[ ${#pids[@]} -gt 0 ]]; then
info "${TAP} was recreated, so dnsmasq (pid ${pids[*]}) is bound to the old interface"
fi
for pid in "${pids[@]}"; do
info "stopping dnsmasq pid ${pid}"
as_root kill "${pid}" || true
done
if ! wait_until "${WAIT_TIMEOUT}" dhcp_port_free; then
ss -uln | grep "${TAP}" >&2 || true
die "UDP 67 on ${TAP} is still in use."
fi
info "starting dnsmasq (pid file ${DNSMASQ_PID})"
# --conf-file=/dev/null: /etc/dnsmasq.conf must not add other interfaces.
as_root dnsmasq \
--conf-file=/dev/null \
--interface="${TAP}" \
--bind-interfaces \
--except-interface=lo \
--pid-file="${DNSMASQ_PID}" \
--dhcp-range="${DHCP_RANGE}" \
--dhcp-option=3,"${TAP_ADDR}" \
--dhcp-option=6,"${TAP_ADDR}"
wait_until "${WAIT_TIMEOUT}" dnsmasq_answering || true
}
CHECK_FAILED=0
check() {
local what="$1"
shift
if "$@" >/dev/null 2>&1; then
info "ok ${what}"
else
info "FAILED ${what}"
CHECK_FAILED=1
fi
}
run_checks() {
step "Checking"
check "${TAP} has ${TAP_CIDR}" has_addr
check "net.ipv4.ip_forward is 1" forwarding_on
check "${TAP} is in zone ${ZONE}" firewall-cmd --zone="${ZONE}" --query-interface="${TAP}"
check "zone ${ZONE} allows dhcp" firewall-cmd --zone="${ZONE}" --query-service=dhcp
check "zone ${ZONE} allows dns" firewall-cmd --zone="${ZONE}" --query-service=dns
check "policy ${POLICY} target is ACCEPT" policy_accepts
check "policy ${POLICY} masquerades" firewall-cmd --policy="${POLICY}" --query-masquerade
check "dnsmasq answers DHCP on ${TAP} (UDP 67)" dhcp_listening
check "dnsmasq answers DNS on ${TAP_ADDR} (UDP 53)" dns_listening
if [[ "${CHECK_FAILED}" -ne 0 ]]; then
echo >&2
echo "Sockets on ${TAP}:" >&2
ss -uln | grep -E "%${TAP}:|${TAP_ADDR}:" >&2 || true
die "setup is incomplete, see the FAILED lines above."
fi
}
print_summary() {
echo
echo "${TAP} is ready. It shows NO-CARRIER until cloud-hypervisor opens it; that is normal."
echo "Start Redox with 'make ch net=tap'. It adds:"
echo " --net tap=${TAP},mac=${GUEST_MAC},offload_tso=off,offload_ufo=off,offload_csum=off"
echo "Then optionally run 'dhcpd -v' in Redox and watch leases happen on the host with 'journalctl -t dnsmasq-dhcp -f'."
}
main() {
preflight
setup_tap
setup_address
setup_forwarding
setup_firewalld
setup_dnsmasq
run_checks
print_summary
}
main "$@"

96
scripts/passt-run.sh Executable file
View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
# Runs a command next to a passt vhost-user network backend, for `make ch`.
# passt-run.sh <socket>.sock [passt options...] -- <command...>
# Under SELinux, passt may only use sockets in $XDG_RUNTIME_DIR or /tmp.
set -euo pipefail
STARTUP_TIMEOUT=5 # seconds
die() {
echo "passt: $*" >&2
exit 1
}
usage() {
echo "usage: $0 <socket>.sock [passt options...] -- <command...>" >&2
exit 2
}
[[ $# -ge 1 ]] || usage
SOCK="$1"
shift
PASST_ARGS=()
while [[ $# -gt 0 && "$1" != "--" ]]; do
PASST_ARGS+=("$1")
shift
done
[[ $# -ge 2 ]] || usage
shift # the "--"
[[ "${SOCK}" == *.sock ]] || die "socket '${SOCK}' must end in .sock"
[[ ${#SOCK} -lt 108 ]] || die "socket path too long (${#SOCK} bytes): ${SOCK}"
LOG="${SOCK%.sock}.log"
REPAIR_SOCK="${SOCK}.repair"
PASST_BIN="${PASST:-passt}"
command -v "${PASST_BIN}" >/dev/null 2>&1 \
|| die "passt not found. Install the passt package (dnf, apt and pacman all call it passt) or set PASST=/path/to/passt"
"${PASST_BIN}" --help 2>&1 | grep -q -- '--vhost-user' \
|| die "${PASST_BIN} has no --vhost-user mode, it is too old. Install a passt from 2025 or later."
socket_in_use() {
ss -Hxl | awk -v sock="${SOCK}" '$5 == sock { found = 1 } END { exit !found }'
}
if socket_in_use; then
die "${SOCK} is in use by another passt. Stop that VM first, or choose another socket."
fi
PASST_PID=
cleanup() {
trap - EXIT INT TERM
if [[ -n "${PASST_PID}" ]]; then
kill "${PASST_PID}" 2>/dev/null || true
wait "${PASST_PID}" 2>/dev/null || true
fi
rm -f "${SOCK}" "${REPAIR_SOCK}"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
start_passt() {
mkdir -p "$(dirname "${SOCK}")"
rm -f "${SOCK}" "${REPAIR_SOCK}"
"${PASST_BIN}" --vhost-user --foreground --one-off --socket "${SOCK}" "${PASST_ARGS[@]}" \
</dev/null >"${LOG}" 2>&1 &
PASST_PID=$!
}
start_failed() {
if [[ -s "${LOG}" ]]; then
# After a bad option passt prints its whole usage text.
sed '/^Usage:/,$d' "${LOG}" | tail -n 20 >&2
die "$1; see ${LOG}"
fi
die "$1 and logged nothing. If SELinux is enforcing, put the socket in \$XDG_RUNTIME_DIR or /tmp."
}
wait_for_socket() {
local deadline=$((SECONDS + STARTUP_TIMEOUT))
until [[ -S "${SOCK}" ]]; do
kill -0 "${PASST_PID}" 2>/dev/null || start_failed "passt exited"
((SECONDS < deadline)) || start_failed "passt did not create ${SOCK} within ${STARTUP_TIMEOUT}s"
sleep 0.1
done
}
start_passt
wait_for_socket
echo "passt: user-mode network at ${SOCK} (log: ${LOG})" >&2
# Not exec'd, so cleanup runs when the command ends.
"$@"

150
scripts/virtiofs-run.sh Executable file
View File

@ -0,0 +1,150 @@
#!/usr/bin/env bash
# Runs a command next to one virtiofsd per shared directory, for
# `make qemu share=...` and `make ch share=...`.
# virtiofs-run.sh --share <socket>.sock <tag>=<dir>[:ro] [--share ...] -- <command...>
set -euo pipefail
STARTUP_TIMEOUT=5 # seconds
die() {
echo "virtiofs: $*" >&2
exit 1
}
usage() {
echo "usage: $0 --share <socket>.sock <tag>=<dir>[:ro] [--share ...] -- <command...>" >&2
exit 2
}
SOCKS=()
TAGS=()
DIRS=()
OPTS=()
LABELS=()
while [[ "${1:-}" == --share ]]; do
[[ $# -ge 3 ]] || usage
[[ "$3" == *=* ]] || die "share '$3': expected <tag>=<dir>"
entry="$3" opt="" label=""
if [[ "${entry}" == *:ro ]]; then
entry="${entry%:ro}" opt=--readonly label=" (read-only)"
fi
OPTS+=("${opt}")
LABELS+=("${label}")
SOCKS+=("$2")
TAGS+=("${entry%%=*}")
DIRS+=("${entry#*=}")
shift 3
done
[[ ${#SOCKS[@]} -gt 0 && "${1:-}" == -- && $# -ge 2 ]] || usage
shift # the "--"
# virtiofsd holds a lock on <socket>.pid for as long as it runs.
share_in_use() {
[[ -e "$1.pid" ]] && ! flock -n "$1.pid" true
}
declare -A SEEN_TAGS=()
validate_share() {
local sock="${SOCKS[$1]}" tag="${TAGS[$1]}" dir="${DIRS[$1]}"
[[ -n "${tag}" ]] || die "share '=${dir}': empty tag"
[[ "${tag}" =~ ^[A-Za-z0-9._-]+$ ]] \
|| die "tag '${tag}': only letters, digits, '.', '_' and '-' are allowed (is '${tag}=${dir}' a directory with an '=' in it? use tag=dir)"
[[ ${#tag} -le 36 ]] || die "tag '${tag}': longer than 36 bytes"
[[ -z "${SEEN_TAGS[${tag}]:-}" ]] || die "tag '${tag}' is used twice"
SEEN_TAGS[${tag}]=1
[[ -n "${dir}" ]] || die "share '${tag}': empty directory"
[[ "${dir}" != *[[:space:]]* ]] \
|| die "share '${tag}': directories containing whitespace are not supported ('${dir}')"
[[ -d "${dir}" ]] || die "share '${tag}': ${dir} is not a directory"
[[ "${sock}" == *.sock ]] || die "socket '${sock}' must end in .sock"
[[ ${#sock} -lt 108 ]] \
|| die "socket path too long (${#sock} bytes): ${sock}; use a shorter share_sockdir"
if share_in_use "${sock}"; then
die "${sock} is in use by another virtiofsd. Stop that VM first, or use another share_sockdir."
fi
}
for i in "${!SOCKS[@]}"; do
validate_share "${i}"
done
find_virtiofsd() {
local c
for c in "${VIRTIOFSD:-}" virtiofsd /usr/libexec/virtiofsd /usr/lib/qemu/virtiofsd \
"${XDG_CACHE_HOME:-${HOME:-/tmp}/.cache}/virtiofsd-redox/virtiofsd"; do
[[ -n "${c}" ]] && command -v "${c}" && return 0
done
return 1
}
VIRTIOFSD_BIN="$(find_virtiofsd)" \
|| die "virtiofsd not found. Install it (e.g. 'dnf install virtiofsd' or 'pacman -S virtiofsd'), run ./podman_bootstrap.sh -d, or set VIRTIOFSD=/path/to/virtiofsd"
PIDS=()
cleanup() {
trap - EXIT INT TERM
if [[ ${#PIDS[@]} -gt 0 ]]; then
kill "${PIDS[@]}" 2>/dev/null || true
wait "${PIDS[@]}" 2>/dev/null || true
fi
local sock
for sock in "${SOCKS[@]}"; do
rm -f "${sock}" "${sock}.pid"
done
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
declare -A SHARED_DIRS=()
start_virtiofsd() {
local sock="${SOCKS[$1]}" dir
mkdir -p "$(dirname "${sock}")"
dir="$(cd "${DIRS[$1]}" && pwd)"
if [[ -n "${SHARED_DIRS[${dir}]:-}" ]]; then
echo "virtiofs: warning: ${dir} is shared more than once; the instances do not share caches" >&2
fi
SHARED_DIRS[${dir}]=1
"${VIRTIOFSD_BIN}" \
--socket-path="${sock}" \
--shared-dir "${dir}" \
--sandbox none \
--log-level warn \
--translate-uid="map:0:$(id -u):1" \
--translate-gid="map:0:$(id -g):1" \
${OPTS[$1]} \
</dev/null >"${sock%.sock}.log" 2>&1 &
PIDS+=("$!")
}
start_failed() {
local log="${SOCKS[$1]%.sock}.log"
tail -n 20 "${log}" >&2 || true
die "virtiofsd for '${TAGS[$1]}' $2; see ${log}"
}
wait_for_sockets() {
local deadline=$((SECONDS + STARTUP_TIMEOUT)) i
for i in "${!SOCKS[@]}"; do
until [[ -S "${SOCKS[$i]}" ]]; do
kill -0 "${PIDS[$i]}" 2>/dev/null || start_failed "${i}" "exited"
((SECONDS < deadline)) || start_failed "${i}" "did not create ${SOCKS[$i]} within ${STARTUP_TIMEOUT}s"
sleep 0.1
done
done
}
for i in "${!SOCKS[@]}"; do
start_virtiofsd "${i}"
done
wait_for_sockets
for i in "${!SOCKS[@]}"; do
echo "virtiofs: sharing '${TAGS[$i]}' = ${DIRS[$i]}${LABELS[$i]} (log: ${SOCKS[$i]%.sock}.log)" >&2
done
# Not exec'd, so cleanup runs when the command ends.
"$@"

View File

@ -170,11 +170,10 @@ pub fn init_config() {
config.cook_opt.git_treeless = Some(extract_env("COOKBOOK_GIT_TREELESS", false));
}
if config.cook_opt.verbose.is_none() {
let default = config.cook_opt.logs.unwrap();
config.cook_opt.verbose = Some(extract_env("COOKBOOK_VERBOSE", default));
config.cook_opt.verbose = Some(extract_env("COOKBOOK_VERBOSE", true));
}
if config.cook_opt.verbose_cmd.is_none() {
config.cook_opt.verbose_cmd = Some(extract_env("COOKBOOK_VERBOSE_CMD", true));
config.cook_opt.verbose_cmd = Some(extract_env("COOKBOOK_VERBOSE_CMD", false));
}
if config.cook_opt.nonstop.is_none() {
config.cook_opt.nonstop = Some(extract_env("COOKBOOK_NONSTOP", false));
@ -314,7 +313,7 @@ mod tests {
compressed: false,
git_treeless: false,
verbose: true,
verbose_cmd: true,
verbose_cmd: false,
clean_build: false,
clean_target: false,
write_filetree: false

View File

@ -276,9 +276,21 @@ pub fn build(
};
let have_toolchain = !name.is_host() && !dep_host_pkgars.is_empty();
let (sysroot_cached, toolchain_cached) = (
build_deps_dir(logger, &sysroot_dir, deps_sysroot)?,
build_deps_dir(
logger,
&sysroot_dir,
deps_sysroot,
false,
cook_config.clean_target,
)?,
if have_toolchain {
build_deps_dir(logger, &toolchain_dir, &dep_host_pkgars)?
build_deps_dir(
logger,
&toolchain_dir,
&dep_host_pkgars,
false,
cook_config.clean_target,
)?
} else {
true
},
@ -301,14 +313,12 @@ pub fn build(
remove_stage_dir(stage_dir)?;
}
if cook_config.clean_target {
// no matter what, these two caches are invalid
// both caches are invalid without init tag
if sysroot_cached {
fs::remove_all(&sysroot_dir)?;
build_deps_dir(logger, &sysroot_dir, deps_sysroot)?;
build_deps_dir(logger, &sysroot_dir, deps_sysroot, true, true)?;
}
if toolchain_cached && have_toolchain {
fs::remove_all(&toolchain_dir)?;
build_deps_dir(logger, &toolchain_dir, &dep_host_pkgars)?;
build_deps_dir(logger, &toolchain_dir, &dep_host_pkgars, true, true)?;
}
}
} else {
@ -485,8 +495,15 @@ pub fn build(
}
};
command.env("COOKBOOK_MAKE_JOBS", cli_jobs.to_string());
if cook_config.verbose {
command.env("COOKBOOK_VERBOSE", "true");
} else {
command.env_remove("COOKBOOK_VERBOSE");
}
if cook_config.verbose_cmd {
command.env("COOKBOOK_VERBOSE", "1");
command.env("COOKBOOK_VERBOSE_CMD", "true");
} else {
command.env_remove("COOKBOOK_VERBOSE_CMD");
}
if cook_config.offline && allow_cargo_offline {
command.env("COOKBOOK_OFFLINE", "1");
@ -627,6 +644,8 @@ fn build_deps_dir(
logger: &PtyOut,
deps_dir: &PathBuf,
dep_pkgars: &BTreeSet<(PackageName, PathBuf)>,
check_init_tag: bool,
write_init_tag: bool,
) -> Result<bool> {
let pkey_path = "build/id_ed25519.pub.toml";
let pkey_file = match PublicKeyFile::open(pkey_path) {
@ -675,7 +694,12 @@ fn build_deps_dir(
}
}
}
if cached {
if cached
&& (!check_init_tag || {
let init_tag_file = deps_dir.join(".tags-init");
std::fs::exists(&init_tag_file).unwrap_or(false)
})
{
return Ok(true);
}
fs::remove_all(deps_dir)?;
@ -705,6 +729,13 @@ fn build_deps_dir(
std::fs::write(&tag_file, hash.as_bytes()).map_err(wrap_io_err!("Writing tag"))?;
}
if write_init_tag {
let init_tag_file = deps_dir_tmp.join(".tags-init");
// this file is used to prevent removing deps dir when clean_target
// is enabled, then clean_deps_dir will remove the tag after build.
std::fs::write(init_tag_file, "").map_err(wrap_io_err!("Writing init tag"))?;
}
// Move sysroot.tmp to sysroot atomically
fs::rename(&deps_dir_tmp, deps_dir)?;

View File

@ -64,6 +64,9 @@ pub fn package(
}
if !package_file.is_file() {
if cook_config.compressed && cook_config.verbose {
log_to_pty!(logger, "DEBUG: compressing '{}'", package_file.display());
}
pkgar::create_with_flags(
secret_path,
package_file.to_str().unwrap(),

View File

@ -83,6 +83,16 @@ function DYNAMIC_STATIC_INIT {
function GNU_CONFIG_GET {
wget -O "$1" "https://gitlab.redox-os.org/redox-os/gnu-config/-/raw/master/config.sub?inline=false"
}
# Bash error hook
error_hook() {
local ec=$?;
echo "Cookbook error : failed at line $1 with code $ec" >&2;
echo "Error command : $BASH_COMMAND" >&2;
[ -z "${COOKBOOK_VERBOSE_CMD}" ] && echo "Add 'export COOKBOOK_VERBOSE_CMD=1' in .config to see more" >&2;
exit "$ec";
}
trap 'error_hook $LINENO' ERR
"#;
pub(crate) static BUILD_PRESCRIPT: &str = r#"
@ -215,6 +225,17 @@ COOKBOOK_CONFIGURE_FLAGS=(
--enable-static
)
COOKBOOK_MAKE_FLAGS=()
if [ -n "${COOKBOOK_VERBOSE_CMD}" ]; then
COOKBOOK_MAKE_FLAGS+=(V=1)
else
COOKBOOK_MAKE_FLAGS+=(V=0)
fi
COOKBOOK_NINJA_FLAGS=()
if [ -n "${COOKBOOK_VERBOSE_CMD}" ]; then
COOKBOOK_NINJA_FLAGS+=(--verbose)
fi
COOKBOOK_MAKE="make"
function cookbook_configure {
@ -320,7 +341,7 @@ function cookbook_cmake {
"${COOKBOOK_CMAKE_FLAGS[@]}" \
"$@"
"${COOKBOOK_NINJA}" -j"${COOKBOOK_MAKE_JOBS}"
"${COOKBOOK_NINJA}" "${COOKBOOK_NINJA_FLAGS[@]}" -j"${COOKBOOK_MAKE_JOBS}"
DESTDIR="${COOKBOOK_STAGE}" "${COOKBOOK_NINJA}" install -j"${COOKBOOK_MAKE_JOBS}"
}
@ -381,7 +402,7 @@ function cookbook_meson {
--cross-file cross_file.txt \
"${COOKBOOK_MESON_FLAGS[@]}" \
"$@"
"${COOKBOOK_NINJA}" -j"${COOKBOOK_MAKE_JOBS}"
"${COOKBOOK_NINJA}" "${COOKBOOK_NINJA_FLAGS[@]}" -j"${COOKBOOK_MAKE_JOBS}"
DESTDIR="${COOKBOOK_STAGE}" "${COOKBOOK_NINJA}" install -j"${COOKBOOK_MAKE_JOBS}"
}
COOKBOOK_PYTHON="${COOKBOOK_TOOLCHAIN}/bin/python3"
@ -416,16 +437,38 @@ function cookbook_python {
pub(crate) static BUILD_POSTSCRIPT: &str = r#"
STRIP="${GNU_TARGET}-strip"
STRIP_ARGS=""
if [ -n "${COOKBOOK_VERBOSE_CMD}" ]; then
STRIP_ARGS="-v"
fi
if [[ "$REDOXER_USE_CLANG" = "1" || "$REDOXER_USE_CLANG" = "true" ]]; then
STRIP="llvm-strip"
STRIP_ARGS="--verbose"
# clang 21 does not support verbose flag, only 23 or above
# [ -n "${COOKBOOK_VERBOSE_CMD}" ] && STRIP_ARGS="--verbose"
elif [[ "$REDOXER_USE_LTO" = "1" || "$REDOXER_USE_LTO" = "true" ]]; then
GCC_BIN=$(command -v "${GNU_TARGET}-gcc")
GCC_VER=$("${GNU_TARGET}-gcc" -dumpfullversion)
PLUGIN_PATH=$(realpath "$(dirname "$GCC_BIN")/../libexec/gcc/${GNU_TARGET}/${GCC_VER}/liblto_plugin.so")
[ -f "$PLUGIN_PATH" ] && STRIP_ARGS="--plugin=${PLUGIN_PATH} -v" || echo "DEBUG: $PLUGIN_PATH not found"
# binutils 2.41 does not support strip plugins, only 2.44 or above
# [ -f "$PLUGIN_PATH" ] && STRIP_ARGS="--plugin=${PLUGIN_PATH} -v" || echo "DEBUG: $PLUGIN_PATH not found"
fi
strip_directory() {
local target_dir="$1"
local strip_cmd="${STRIP}"
local strip_flags="${STRIP_ARGS:-}"
find "$target_dir" -type f -print0 | while IFS= read -r -d '' file; do
# check magic bytes for elf and ar before stripping
local magic_bytes="$(od -An -t x1 -N 4 "$file" | tr -d ' \n')"
if [[ "$magic_bytes" = "7f454c46" || "$magic_bytes" = "213c6172" ]]; then
"${STRIP}" ${STRIP_ARGS} "$file"
fi
done
}
if [ -z "${COOKBOOK_NOSTRIP}" ]; then
[ -z "${COOKBOOK_VERBOSE}" ] || echo "DEBUG: stripping binaries and libraries"
fi
# Strip binaries
@ -433,10 +476,12 @@ for dir in "${COOKBOOK_STAGE}/bin" "${COOKBOOK_STAGE}/usr/bin" "${COOKBOOK_STAGE
do
if [ -d "${dir}" ] && [ -z "${COOKBOOK_NOSTRIP}" ]
then
find "${dir}" -type f -exec "${STRIP}" ${STRIP_ARGS} {} ';'
strip_directory "${dir}"
fi
done
# do not strip symbols for libraries
STRIP_ARGS+=" --strip-debug"
# Remove libtool files and strip debugging information
for dir in "${COOKBOOK_STAGE}/lib" "${COOKBOOK_STAGE}/usr/lib"
do
@ -445,7 +490,7 @@ do
find "${dir}" -type f -name '*.la' -exec rm -fv {} ';'
if [ -z "${COOKBOOK_NOSTRIP}" ]
then
find "${dir}" -type f -exec "${STRIP}" ${STRIP_ARGS} --strip-debug {} ';'
strip_directory "${dir}"
fi
fi
done