diff --git a/Makefile b/Makefile index 261bd62a..d9a9593e 100755 --- a/Makefile +++ b/Makefile @@ -5,10 +5,16 @@ # or manually build with meson once. # # The cell shop is at ~/.cell and core scripts are installed to ~/.cell/core +# +# See BUILDING.md for details on the bootstrap process and .mach files. CELL_SHOP = $(HOME)/.cell CELL_CORE_PACKAGE = $(CELL_SHOP)/packages/core +# .cm sources that compile to .mach bytecode +MACH_SOURCES = tokenize.cm parse.cm fold.cm mcode.cm \ + internal/bootstrap.cm internal/engine.cm + maker: install makecell: @@ -16,7 +22,7 @@ makecell: cp cell /opt/homebrew/bin/ # Install core: symlink this directory to ~/.cell/core -install: bootstrap $(CELL_SHOP) +install: bootstrap .mach.stamp $(CELL_SHOP) @echo "Linking cell core to $(CELL_CORE_PACKAGE)" rm -rf $(CELL_CORE_PACKAGE) ln -s $(PWD) $(CELL_CORE_PACKAGE) @@ -40,6 +46,16 @@ libcell_runtime.dylib: $(CELL_SHOP)/build/dynamic cell_main: source/main.c libcell_runtime.dylib cc -o cell_main source/main.c -L. -lcell_runtime -Wl,-rpath,@loader_path -Wl,-rpath,/opt/homebrew/lib +# Regenerate .mach bytecode when any .cm source changes +.mach.stamp: $(MACH_SOURCES) + ./cell --core . regen.cm + @touch $@ + +# Force-regenerate all .mach bytecode files +regen: + ./cell --core . regen.cm + @touch .mach.stamp + # Create the cell shop directories $(CELL_SHOP): mkdir -p $(CELL_SHOP) @@ -57,7 +73,7 @@ static: # Bootstrap: build cell from scratch using meson (only needed once) # Also installs core scripts to ~/.cell/core -bootstrap: +bootstrap: meson setup build_bootstrap -Dbuildtype=debugoptimized meson compile -C build_bootstrap cp build_bootstrap/cell . @@ -68,7 +84,7 @@ bootstrap: # Clean build artifacts clean: rm -rf $(CELL_SHOP)/build build_bootstrap - rm -f cell cell_main libcell_runtime.dylib + rm -f cell cell_main libcell_runtime.dylib .mach.stamp # Ensure dynamic build directory exists $(CELL_SHOP)/build/dynamic: $(CELL_SHOP) @@ -79,4 +95,4 @@ meson: meson setup build_dbg -Dbuildtype=debugoptimized meson install -C build_dbg -.PHONY: cell static bootstrap clean meson install +.PHONY: cell static bootstrap clean meson install regen diff --git a/internal/bootstrap.cm b/internal/bootstrap.cm index 07fec6e1..2f0984e8 100644 --- a/internal/bootstrap.cm +++ b/internal/bootstrap.cm @@ -48,6 +48,41 @@ if (use_mcode) { mcode_mod = boot_load("mcode", boot_env) } +// Warn if any .cm source is newer than its .mach bytecode +function check_mach_stale() { + var pairs = [ + ["tokenize.cm", "tokenize.mach"], + ["parse.cm", "parse.mach"], + ["fold.cm", "fold.mach"], + ["mcode.cm", "mcode.mach"], + ["internal/bootstrap.cm", "internal/bootstrap.mach"], + ["internal/engine.cm", "internal/engine.mach"] + ] + var stale = [] + var _i = 0 + var cm_path = null + var mach_path = null + var cm_stat = null + var mach_stat = null + while (_i < length(pairs)) { + cm_path = core_path + '/' + pairs[_i][0] + mach_path = core_path + '/' + pairs[_i][1] + if (fd.is_file(cm_path) && fd.is_file(mach_path)) { + cm_stat = fd.stat(cm_path) + mach_stat = fd.stat(mach_path) + if (cm_stat.mtime > mach_stat.mtime) { + push(stale, pairs[_i][0]) + } + } + _i = _i + 1 + } + if (length(stale) > 0) { + print("warning: bytecode is stale for: " + text(stale, ", ") + "\n") + print("run 'make regen' or './cell --core . regen.cm' to update\n") + } +} +check_mach_stale() + // analyze: tokenize + parse, check for errors function analyze(src, filename) { var tok_result = tokenize_mod(src, filename) diff --git a/internal/bootstrap.mach b/internal/bootstrap.mach index a188f1bf..452430bb 100644 Binary files a/internal/bootstrap.mach and b/internal/bootstrap.mach differ