diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f7a2e14
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,43 @@
+arch := x86_64
+kernel := build/$(arch)/kernel.bin
+iso := build/$(arch)/os.iso
+rs_target := $(arch)-unknown-none
+rs_kernel := target/$(rs_target)/debug/libsparkle_os.a
+
+asm_src := $(wildcard src/arch/$(arch)/*.asm)
+asm_obj := $(patsubst src/arch/$(arch)/%.asm, build/$(arch)/%.o, $(asm_src))
+rs_src := $(wildcard src/*.rs)
+linker_script := src/arch/$(arch)/linker.ld
+grub_cfg := src/arch/$(arch)/grub.cfg
+
+.PHONY: all clean run iso
+
+all: $(kernel)
+
+clean:
+	rm -r build/ target/
+
+run: $(iso)
+	qemu-system-x86_64 -cdrom $(iso) -s
+
+run-trif: $(iso)
+	qemu-system-x86_64 -cdrom $(iso) -no-reboot -d int -s
+
+iso: $(iso)
+
+$(iso): $(kernel)
+	mkdir -p build/isofiles/boot/grub
+	cp $(kernel) build/isofiles/boot/kernel.bin
+	cp $(grub_cfg) build/isofiles/boot/grub
+	grub-mkrescue -o $(iso) build/isofiles
+	rm -r build/isofiles
+
+$(kernel): $(asm_obj) $(rs_kernel)
+	ld -n --gc-sections -T $(linker_script) -o $(kernel) $^
+
+$(rs_kernel): $(rs_src)
+	xargo build --target $(rs_target)
+
+build/$(arch)/%.o: src/arch/$(arch)/%.asm
+	@mkdir -p $(shell dirname $@)
+	nasm -felf64 $< -o $@