RustForge

foundry

Foundry OS: the operating system built on the Rustbelt kernel

foundry / Makefile
5023 bytes ยท raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# Foundry OS -- the single entry point. `make help` lists the targets.
#
# Everything generated goes to out/ (git-ignored); `make clean` removes it.
# Downloads (musl source etc.) go to cache/ (git-ignored, SHA256-checked).

include config.mk

OUT        := $(CURDIR)/out
IMAGE      := $(OUT)/$(IMAGE_NAME)
STAGING    := $(OUT)/staging
RUST_OUT   := $(OUT)/rust-target/x86_64-unknown-none/release
FIXTURES   := $(OUT)/fixtures
KSRC       := $(OUT)/kernel-src
KTARGET    := $(OUT)/kernel-target
KBOOT      := $(OUT)/kernel/bootimage.bin
KBOOT_HL   := $(OUT)/kernel/bootimage-headless.bin
SYSROOT    := $(OUT)/sysroot
FCC        := $(CURDIR)/toolchain/foundry-cc
C_OUT      := $(OUT)/c
# Everything in /bin, in order: the kernel's list, then Foundry OS's own.
ALL_BIN    := $(BIN_ORDER) $(FOUNDRY_C)

.DEFAULT_GOAL := image
.PHONY: help image rust fixtures cprogs staging kernel kernel-src run test test-reference compare musl clean distclean

help:
	@echo "Foundry OS (userland for the Rustbelt kernel $(KERNEL_VERSION) @ $(KERNEL_REV))"
	@echo ""
	@echo "  make / make image   build out/$(IMAGE_NAME), the disk image (contract $(CONTRACT))"
	@echo "  make rust           cargo build the Rust programs in rust/"
	@echo "  make fixtures       build the kernel's ABI test programs from the pinned kernel"
	@echo "  make cprogs         build our C programs (c/) as static-PIEs with toolchain/foundry-cc"
	@echo "  make staging        assemble out/staging (rootfs/ + /bin)"
	@echo "  make kernel         build the pinned kernel into out/kernel-target"
	@echo "  make run            boot the image in a QEMU window"
	@echo "  make test           headless boot + the shell self-test + expected-line checks"
	@echo "  make test-reference  the same headless test, but booting the kernel's own disk.img (baseline)"
	@echo "  make compare        compare out/$(IMAGE_NAME) with the kernel's own disk.img"
	@echo "  make musl           fetch (cache/) + build musl $(MUSL_VERSION) into out/sysroot"
	@echo "  make clean          rm -rf out   (distclean also removes cache/)"

# ---- the pinned kernel -------------------------------------------------------
kernel-src:
	scripts/build-kernel.sh $(KERNEL_DIR) $(KERNEL_REV) $(OUT) --export-only

kernel:
	scripts/build-kernel.sh $(KERNEL_DIR) $(KERNEL_REV) $(OUT)

# ---- programs ---------------------------------------------------------------
rust:
	cd rust && CARGO_TARGET_DIR=$(OUT)/rust-target cargo build --release

fixtures: kernel-src
	scripts/build-fixtures.sh $(KSRC) $(FIXTURES) "$(FIXTURE_RUST)" "$(FIXTURE_C)" "$(FIXTURE_MUSL)"

# Our own C programs: gcc + our musl, static-PIE (docs/porting.md).
cprogs: $(SYSROOT)/lib/musl-pie.specs
	mkdir -p $(C_OUT)
	for p in $(FOUNDRY_C); do \
	    $(FCC) -O2 -Wall -Wextra -pthread -Wl,--build-id=none c/$$p.c -o $(C_OUT)/$$p || exit 1; \
	done
	@echo "[cprogs] built $(FOUNDRY_C) into $(C_OUT)"

# ---- the image ---------------------------------------------------------------
# Contract v1: rootfs/ minus etc/ (etc/ is for the contract-v2 ext2 root,
# see docs/plan.md) goes to the top of the FAT32 volume, programs to /bin.
staging: rust fixtures cprogs
	rm -rf $(STAGING) && mkdir -p $(STAGING)/bin
	cd rootfs && for e in $$(ls -A); do [ "$$e" = etc ] && [ "$(CONTRACT)" = v1 ] && continue; cp -r "$$e" $(STAGING)/; done
	for p in $(filter-out sh,$(RUST_PROGRAMS)); do cp $(RUST_OUT)/$$p $(STAGING)/bin/; done
	cp $(RUST_OUT)/rbsh $(STAGING)/bin/sh    # contract v1: the kernel runs /mnt/disk0/bin/sh
	cp $(FIXTURES)/* $(STAGING)/bin/
	for p in $(FOUNDRY_C); do cp $(C_OUT)/$$p $(STAGING)/bin/; done

image: staging
	scripts/mkimage.sh $(STAGING) $(IMAGE) $(IMAGE_MIB) $(IMAGE_LABEL) "$(ALL_BIN)"

# ---- booting ----------------------------------------------------------------
run: image kernel
	scripts/run-qemu.sh $(IMAGE) $(KBOOT) $(KTARGET) $(OUT)

# What the expected-line checks need to know about the pinned kernel.
TEST_ENV   := KERNEL_BANNER="$(KERNEL_BANNER)" KERNEL_VERSION=$(KERNEL_VERSION)

test: image kernel
	$(TEST_ENV) BIN_COUNT=$(words $(ALL_BIN)) EXTRA_EXPECT=scripts/expect-foundry.txt \
	    scripts/run-headless.sh $(IMAGE) $(KBOOT_HL) $(KTARGET) $(OUT)

# The baseline: the kernel's own disk.img through the very same checks
# (without Foundry OS's own programs and expected lines, which it lacks).
test-reference: kernel
	$(TEST_ENV) BIN_COUNT=$(words $(BIN_ORDER)) \
	    scripts/run-headless.sh $(KTARGET)/disk.img $(KBOOT_HL) $(KTARGET) $(OUT)/reference

compare: image kernel
	FOUNDRY_BIN="$(FOUNDRY_C)" scripts/compare-image.sh $(IMAGE) $(KTARGET)/disk.img $(OUT)

# ---- toolchain ---------------------------------------------------------------
# musl is built once; delete out/sysroot (or run `make musl`) to rebuild it.
musl:
	toolchain/musl/fetch.sh cache
	toolchain/musl/build.sh cache $(OUT)/musl-build $(SYSROOT)

$(SYSROOT)/lib/musl-pie.specs: toolchain/musl/musl.sha256 toolchain/musl/musl-pie.specs.in toolchain/musl/build.sh
	$(MAKE) musl

clean:
	rm -rf out

distclean: clean
	rm -rf cache