-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
127 lines (97 loc) · 3.57 KB
/
Makefile
File metadata and controls
127 lines (97 loc) · 3.57 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
CC = gcc
INC = -Iinclude
DIR = bin
BIN = $(DIR)/vbo
PYTHON ?= python3
# minimal RISCV32I VM build
SRC_COMMON = src/riscv32i.c src/utils.c
SRC_MAIN = src/main.c $(SRC_COMMON)
FLAGS = -Wall -Wextra -Werror -g -std=c11 -pedantic
# RISC-V cross toolchain (see the wiki)
RV_PREFIX ?= ~/.local/xPacks/riscv-none-elf-gcc/xpack-riscv-none-elf-gcc-14.2.0-3/bin/riscv-none-elf-
RV_GCC := $(RV_PREFIX)gcc
RV_OBJCOPY:= $(RV_PREFIX)objcopy
# Example app pipeline
OUT_DIR ?= out
EXAMPLES_DIR ?= examples
APP_SRC ?= $(EXAMPLES_DIR)/hello.c
APP_ELF := $(OUT_DIR)/app.elf
APP_BIN := $(OUT_DIR)/app.bin
APP_IMG := $(OUT_DIR)/app.img
ORIGIN ?= 0x3000
define ensure_rv_toolchain
@if ! command -v $(RV_GCC) >/dev/null 2>&1; then \
echo "[Make] Missing toolchain: $(RV_GCC). See the wiki for info on how to install and add to PATH."; \
exit 1; \
fi
@if ! command -v $(RV_OBJCOPY) >/dev/null 2>&1; then \
echo "[Make] Missing tool: $(RV_OBJCOPY). Check your riscv-none-elf toolchain installation."; \
exit 1; \
fi
endef
EMBED_IMAGE ?=
EMBED_OBJ :=
ifneq ($(strip $(EMBED_IMAGE)),)
EMBED_OBJ := images/vbo_image.o
endif
TEST_DIR = test
.PHONY: all build clean test app image embed run demo distclean test-integration test-all help
all: build
build: $(EMBED_OBJ)
mkdir -p $(DIR)
$(CC) $(INC) $(SRC_MAIN) $(EMBED_OBJ) -o $(BIN) $(FLAGS)
images/vbo_image.o: $(EMBED_IMAGE) tools/embed_image.py
mkdir -p images
$(PYTHON) tools/embed_image.py --input "$(EMBED_IMAGE)" --output $@
clean:
rm -f $(BIN)
rm -f $(TEST_DIR)/test_utils
rm -f images/vbo_image.o
rm -rf $(OUT_DIR)
distclean: clean
test: build
$(CC) $(INC) $(TEST_DIR)/test_utils.c src/utils.c src/riscv32i.c -o $(TEST_DIR)/test_utils $(FLAGS)
$(TEST_DIR)/test_utils
rm $(TEST_DIR)/test_utils
$(CC) $(INC) $(TEST_DIR)/test_riscv32i.c src/riscv32i.c -o $(TEST_DIR)/test_riscv32i $(FLAGS)
$(TEST_DIR)/test_riscv32i
rm $(TEST_DIR)/test_riscv32i
@if ! command -v $(RV_GCC) >/dev/null 2>&1 || ! command -v $(RV_OBJCOPY) >/dev/null 2>&1; then \
echo "[Test] Skipping integration test (toolchain not found). See the wiki"; \
exit 0; \
fi
@$(MAKE) --no-print-directory image
@out=$$($(BIN) $(APP_IMG)); echo "$$out" | grep -q "Hello from RV32I VM" && echo "OK" || (echo "FAIL"; exit 1)
# --- App build pipeline ---
$(OUT_DIR):
mkdir -p $(OUT_DIR)
app: $(APP_ELF)
$(APP_ELF): $(APP_SRC) | $(OUT_DIR)
$(call ensure_rv_toolchain)
$(RV_GCC) \
-march=rv32i -mabi=ilp32 -nostdlib -ffreestanding -Os -s -fno-pic \
-Wl,--build-id=none -Wl,-Ttext=$(ORIGIN) -Wl,-e,_start \
-Iinclude -o $@ $<
$(APP_BIN): $(APP_ELF) | $(OUT_DIR)
$(RV_OBJCOPY) -O binary $< $@
image: $(APP_IMG)
$(APP_IMG): $(APP_BIN) | $(OUT_DIR)
$(PYTHON) -c 'import sys,struct; o=int(sys.argv[1],16) if str(sys.argv[1]).startswith("0x") else int(sys.argv[1]); open(sys.argv[2],"wb").write(struct.pack(">I",o)+open(sys.argv[3],"rb").read())' \
$(ORIGIN) $@ $<
# Embed convenience: uses APP_IMG if EMBED_IMAGE not provided
embed: image
$(MAKE) build EMBED_IMAGE=$(APP_IMG)
run: build image
$(BIN) $(APP_IMG)
demo: embed run
help:
@echo "Targets:"
@echo " build - Build the VM"
@echo " app - Build example app (set APP_SRC=...)"
@echo " image - Make flat image with origin header from app"
@echo " embed - Embed image and rebuild VM"
@echo " run - Run VM with built image"
@echo " demo - Build+embed+run example app end-to-end"
@echo " test - Run unit tests"
@echo " test-all - Run unit + integration tests (if toolchain available)"
@echo " clean / distclean- Remove build artifacts"