125 lines
4.0 KiB
Makefile
125 lines
4.0 KiB
Makefile
# SplitBit Emulator and Assembler Makefile
|
|
# Anachronaut
|
|
# 10/16/2024
|
|
|
|
# Compiler and flags
|
|
CC ?= gcc
|
|
CFLAGS ?= -Wall -Os
|
|
PREFIX ?= /usr/local
|
|
|
|
# Have the compiler write out which headers each object depends on, so that
|
|
# editing a header rebuilds everything that includes it.
|
|
DEPFLAGS = -MMD -MP
|
|
|
|
# Both tools use POSIX interfaces that ISO C does not have: realpath, clock_gettime,
|
|
# strdup, dirname and getopt. Asking for POSIX.1-2008 by name means the build does
|
|
# not rely on the compiler happening to default to a mode where those are visible,
|
|
# and it survives someone overriding CFLAGS, which is why it is kept separate.
|
|
POSIXFLAGS = -D_POSIX_C_SOURCE=200809L
|
|
|
|
# Directories
|
|
SRC_DIR_EMU = Source/Emulator
|
|
SRC_DIR_ASM = Source/Assembler
|
|
SRC_DIR_DSK = Source/DiskTool
|
|
OBJ_DIR = Object
|
|
|
|
# Source files
|
|
EMU_SRCS = emulator.c io.c controller.c utility.c cpu.c bootstrap.c assembly.c
|
|
ASM_SRCS = Assembler.c assembly.c firstPass.c Assm-util.c secondPass.c
|
|
DSK_SRCS = SplitDisk.c
|
|
|
|
EMU_OBJS = $(EMU_SRCS:%.c=$(OBJ_DIR)/%.o)
|
|
ASM_OBJS = $(ASM_SRCS:%.c=$(OBJ_DIR)/%.o)
|
|
DSK_OBJS = $(DSK_SRCS:%.c=$(OBJ_DIR)/%.o)
|
|
|
|
# Output binary names
|
|
EMU_TARGET = SplitBit
|
|
ASM_TARGET = Assembler
|
|
DSK_TARGET = SplitDisk
|
|
|
|
# Default target: build both emulator and assembler
|
|
all: $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET)
|
|
|
|
# Emulator binary
|
|
$(EMU_TARGET): $(EMU_OBJS)
|
|
$(CC) $(CFLAGS) -o $(EMU_TARGET) $(EMU_OBJS)
|
|
|
|
# Assembler binary
|
|
$(ASM_TARGET): $(ASM_OBJS)
|
|
$(CC) $(CFLAGS) -o $(ASM_TARGET) $(ASM_OBJS)
|
|
|
|
# Compile emulator source files to object files
|
|
$(OBJ_DIR)/%.o: $(SRC_DIR_EMU)/%.c
|
|
mkdir -p $(OBJ_DIR)
|
|
$(CC) $(CFLAGS) $(POSIXFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# Disk tool binary
|
|
$(DSK_TARGET): $(DSK_OBJS)
|
|
$(CC) $(CFLAGS) -o $(DSK_TARGET) $(DSK_OBJS)
|
|
|
|
# Compile disk tool source files to object files
|
|
$(OBJ_DIR)/%.o: $(SRC_DIR_DSK)/%.c
|
|
@mkdir -p $(OBJ_DIR)
|
|
$(CC) $(CFLAGS) $(POSIXFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# Compile assembler source files to object files
|
|
$(OBJ_DIR)/%.o: $(SRC_DIR_ASM)/%.c
|
|
mkdir -p $(OBJ_DIR)
|
|
$(CC) $(CFLAGS) $(POSIXFLAGS) $(DEPFLAGS) -c $< -o $@
|
|
|
|
# Pull in the header dependencies written out by the compiler above.
|
|
-include $(EMU_OBJS:.o=.d) $(ASM_OBJS:.o=.d) $(DSK_OBJS:.o=.d)
|
|
|
|
# Run the test suite against the programs in Programs/
|
|
test: $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET)
|
|
@./Tests/run.sh
|
|
@echo
|
|
@./Tests/disk.sh
|
|
@echo
|
|
@./Tests/terminal.sh
|
|
@echo
|
|
@./Tests/docs.sh
|
|
|
|
# Rebuild both tools with the address and undefined behaviour sanitizers and run
|
|
# the test suite under them. Slower than 'make test', and worth running before a
|
|
# release or after anything that touches memory handling.
|
|
#
|
|
# The sanitizers catch reads and writes off the end of an array, use after free,
|
|
# leaks, and undefined arithmetic. They also fill fresh allocations with a junk
|
|
# pattern, which is what turns a read of uninitialised memory from something that
|
|
# quietly works into something the tests notice.
|
|
#
|
|
# If the suite fails, the sanitizer binaries are deliberately left in place so
|
|
# that the failing case can be run again by hand. 'make' puts the normal ones back.
|
|
SANITIZE_FLAGS = -Wall -Wextra -g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer
|
|
|
|
sanitize:
|
|
@$(MAKE) --no-print-directory clean
|
|
@$(MAKE) --no-print-directory CFLAGS="$(SANITIZE_FLAGS)"
|
|
@echo "Running the test suite under AddressSanitizer and UndefinedBehaviorSanitizer."
|
|
@./Tests/run.sh
|
|
@echo
|
|
@./Tests/terminal.sh
|
|
@$(MAKE) --no-print-directory clean
|
|
@$(MAKE) --no-print-directory
|
|
@echo "Sanitizer run finished cleanly. Normal binaries rebuilt."
|
|
|
|
# Record the current output of every test as the expected result.
|
|
# Only do this when the current output is known to be correct.
|
|
bless: $(EMU_TARGET) $(ASM_TARGET)
|
|
@./Tests/run.sh --bless
|
|
|
|
# Clean up object and binary files
|
|
clean:
|
|
rm -rf $(OBJ_DIR)
|
|
rm -rf Tests/build
|
|
rm -f $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET)
|
|
|
|
# Install compiled binaries
|
|
install: $(EMU_TARGET) $(ASM_TARGET) $(DSK_TARGET)
|
|
mkdir -p "$(PREFIX)/bin"
|
|
install -m 755 $^ "$(PREFIX)/bin/"
|
|
|
|
# Phony targets
|
|
.PHONY: all clean install test bless sanitize
|