# SplitBit Programs Makefile # Anachronaut # # Builds every SplitBit program into build/, and keeps track of which libraries # each one includes so that editing a library reassembles whatever depends on it. # # make Assemble everything. # make clean Throw away build/. # make run-hello Assemble and run one program. ASM ?= ../Assembler EMU ?= ../SplitBit BUILD ?= build # Libraries are included by bare name, so the assembler is told where to find them. # CosmOS owns the filesystem library and the service names, so it is a place to look too. INCLUDES = -I Libraries -I CosmOS/Source # The programs worth building. Every one lives in a directory that says what kind it is: # Examples/ is what you read to learn, Loader/ is the standalone loader CosmOS grew out of, # CosmOS/ is the system. Files in Libraries/ are left out because they have no entry point # of their own, and the ones in testPrograms/ are covered by 'make test' in the parent # directory. PROGRAMS = \ CosmOS/Source/cosmos.asm \ Examples/hello.asm \ Examples/printHello.asm \ Examples/inputTest.asm \ Examples/replCalculator.asm \ Examples/Fibonacci/8bitFibonacci.asm \ Examples/Fibonacci/16bitFibonacci.asm \ Examples/Fibonacci/32bitFibonacci.asm \ Examples/primeSieve/8bitSieve.asm \ Examples/primeSieve/16bitSegmentedSieve.asm \ Examples/primeSieve/16bitSegmentedSieveModern.asm \ Examples/gameOfLife/16x16Life.asm \ Examples/gameOfLife/16x16LifeModern.asm \ Loader/loader.asm \ Loader/loadable.asm BINARIES = $(PROGRAMS:%.asm=$(BUILD)/%.bin) DEPENDENCIES = $(BINARIES:.bin=.d) all: $(BINARIES) # -M writes out which source files went into the binary, in the form of a make rule. $(BUILD)/%.bin: %.asm @mkdir -p $(@D) $(ASM) $(INCLUDES) -M $(@:.bin=.d) -o $@ $< # Assemble and run a single program, as in 'make run-hello'. # # THE NAME IS THE PROGRAM'S, NOT ITS PATH. This used to be a pattern rule against # $(BUILD)/%.bin, which worked while every program sat at the top of this directory and # stopped working the moment they were filed into Examples/ - 'make run-hello' had nothing # to match. Somebody trying the one command the header advertises should not be the way # that is discovered, so the name is now looked up among the programs instead. run-%: @target=`echo $(BINARIES) | tr ' ' '\n' | grep -E "(^|/)$*\.bin$$" | head -1`; \ if [ -z "$$target" ]; then \ echo "There is no program called '$*'. What there is:"; \ echo $(PROGRAMS) | tr ' ' '\n' | sed 's|.*/||;s|\.asm$$||;s|^| |'; \ exit 1; \ fi; \ $(MAKE) --no-print-directory "$$target" && $(EMU) "$$target" # ---- CosmOS ---- # # make cosmos Assemble the system and everything it can load. # make cosmos-disk ... and put the loadable programs on a disk image. # make run-cosmos ... and boot the machine with that disk in the drive. # # Programs in Apps/ say where they live with #Base, so the assembler writes them out as # loadable programs rather than as boot images. They are named .sbx to keep that # difference visible: a .bin is something the machine boots, a .sbx is something a # running system loads. DISKTOOL ?= ../SplitDisk COSMOS = $(BUILD)/CosmOS/Source/cosmos.bin APPS = $(patsubst CosmOS/Apps/%.asm,$(BUILD)/CosmOS/Apps/%.sbx,$(wildcard CosmOS/Apps/*.asm)) COSMOS_DISK = $(BUILD)/cosmos.img DEPENDENCIES += $(APPS:.sbx=.d) $(BUILD)/CosmOS/Apps/%.sbx: CosmOS/Apps/%.asm @mkdir -p $(@D) $(ASM) $(INCLUDES) -M $(@:.sbx=.d) -o $@ $< # The assembler that runs on the machine. It is not in Apps/ because it is not one file: # it has a directory of its own, the way the C assembler does. Its own pieces are found # beside it without being told, since an include is looked for next to the file that asked # for it before anywhere else; only services.asm needs the include path. NATIVE_ASM = $(BUILD)/CosmOS/Assembler/Asm.sbx DEPENDENCIES += $(NATIVE_ASM:.sbx=.d) $(NATIVE_ASM): CosmOS/Assembler/Asm.asm @mkdir -p $(@D) $(ASM) $(INCLUDES) -M $(@:.sbx=.d) -o $@ $< cosmos: $(COSMOS) $(APPS) $(NATIVE_ASM) # Made from scratch every time, so that what is on it is what is in Apps/ now and not # also whatever used to be. # # TWENTY FOUR DIRECTORY BLOCKS, WHICH IS ONE HUNDRED AND NINETY TWO NAMES. It was eight, # and that is sixty four, of which thirty nine were already spoken for. The two ceilings a # disk has were nowhere near each other: at the average file on here, twenty six blocks, # sixty four names run out with the disk forty one per cent full. Names were going to be # gone long before space was. # # A directory block is 256 bytes and holds eight entries, so the difference costs sixteen # blocks of four thousand and ninety six - three tenths of one per cent - to buy a hundred # and twenty eight more names. The superblock has carried this number per disk since the # format was written, so nothing but this line knows what it is. $(COSMOS_DISK): $(APPS) $(NATIVE_ASM) testPrograms/stringKeyword.asm \ CosmOS/Apps/hello.asm CosmOS/Apps/Say.asm CosmOS/Apps/Keys.asm \ CosmOS/Source/services.asm CosmOS/Source/console.asm \ $(wildcard CosmOS/Source/*.asm) $(wildcard CosmOS/Assembler/*.asm) @mkdir -p $(@D) rm -f $@ $(DISKTOOL) format $@ 4096 24 @for app in $(APPS); do $(DISKTOOL) put $@ $$app; done $(DISKTOOL) put $@ $(NATIVE_ASM) @# SOURCE goes on as well, because an assembler with nothing to assemble is a @# demonstration of nothing. @# @# hello.asm and Say.asm are the APPLICATION versions, so each assembles to a .sbx @# written straight over the one the host tool put there - which means the next @# thing loaded is a program the machine built itself, in the same breath. @# @# Keys.asm is the one that brings a vector of its own, so assembling it exercises the @# version two header and the Vector Segment: the loader installs its handler, the @# console interrupts into it, and the shell takes the vector back at exit. @# @# strings.asm is the odd one out on purpose: it has no #Include and no #Base, so it @# comes out as a boot image rather than a loadable program, and the difference @# between the two is visible on one disk. $(DISKTOOL) put $@ CosmOS/Apps/hello.asm $(DISKTOOL) put $@ CosmOS/Apps/Say.asm $(DISKTOOL) put $@ CosmOS/Apps/Keys.asm $(DISKTOOL) put $@ CosmOS/Source/services.asm $(DISKTOOL) put $@ CosmOS/Source/console.asm $(DISKTOOL) put $@ testPrograms/stringKeyword.asm strings.asm @# And the whole of CosmOS, and the whole of the assembler, so that the machine can @# build the system it is running on and then build the thing that built it: @# @# > load Asm.sbx @# > run cosmos.asm @# > run Asm.asm @# @# Both come out byte for byte what the host tool makes from the same source. @for f in CosmOS/Source/*.asm CosmOS/Assembler/*.asm; do \ $(DISKTOOL) put $@ $$f >/dev/null; done # The system as well as the disk. Building only the image leaves whatever cosmos.bin was # there before, or none at all, and then the disk is booted with a system that does not # match the programs on it. cosmos-disk: $(COSMOS) $(COSMOS_DISK) run-cosmos: $(COSMOS) $(COSMOS_DISK) $(EMU) --disk $(COSMOS_DISK) $(COSMOS) clean: rm -rf $(BUILD) # Pull in the dependency rules written by -M above, so that touching a library # reassembles every program that includes it. -include $(DEPENDENCIES) .PHONY: all clean cosmos cosmos-disk run-cosmos