### Setup source_d := source target_d := target template := ./template # Check that our directories are set ifndef source_d $(error 'source_d' not defined) endif ifndef target_d $(error 'target_d' not defined) endif # Check that our directories exist source_is_dir = $(shell test -d $(source_d) && echo true || echo false) ifeq ($(source_is_dir),false) $(error directory '$(source_d)' does not exist) endif target_is_dir = $(shell test -d $(target_d) && echo true || echo false) ifeq ($(target_is_dir),false) $(error directory '$(target_d)' does not exist) endif # Check that $(template) is set ifndef template $(error 'template' not defined) endif # Check that $(template) exists template_exists = $(shell test -f $(template) && echo true || echo false) ifeq ($(template_exists),false) $(error template file '$(template)' does not exist) endif # Check that $(template) is executable template_is_exec = $(shell test -x $(template) && echo true || echo false) ifeq ($(template_is_exec),false) $(error template file '$(template)' is not executable) endif # Generate Target Names source_dirs := $(shell find -L $(source_d) -mindepth 1 -type d) source_files := $(shell find -L $(source_d) -type f | rev | sort | rev) # '| rev | sort | rev' sorts filenames by their extenstion # this isn't neccessary, it just makes for cleaner output target_dirs := $(source_dirs:$(source_d)%=$(target_d)%) target_files := $(source_files:$(source_d)%=$(target_d)%) target_files := $(target_files:%.md=%.html) target_files := $(target_files:%.mmd=%.html) target_files := $(target_files:%.scss=%.css) # Check that we actually have targets to build # if $(target_*) is empty $(old_files) will delete everything ifndef target_files $(error no files found in 'target_files') endif ifndef target_dirs $(error no directories found in 'target_dirs') endif # files in $(target_d) that are no longer targets old_files := $(filter-out $(target_files) $(target_dirs), $(shell find $(target_d) -mindepth 1 -depth -type f,d)) # because $(old_files) conists of files that already exist # the $(old_files) rule will not run if it is not .PHONY .PHONY : $(old_files) ### Rules default : all all : $(target_dirs) $(target_files) $(old_files) $(target_dirs) : mkdir -p "$(@)" $(target_d)/%.html : $(source_d)/%.md template markdown "$(<)" | $(template) > "$(@)" $(target_d)/%.css : $(source_d)/%.scss sassc -t expanded "$(<)" > "$(@)" $(target_d)/% : $(source_d)/% cp "$(<)" "$(@)" $(old_files) : @if [[ "$(@)" == "/" ]]; then \ echo error: attempting to rm "$(@)"; \ else \ echo rm -rf "$(@)"; \ rm -rf "$(@)"; \ fi # this method is slightly inefficient. Because $(old_files) contains the # names of the directories to be removed and their contents, this rule will # redundantly run rm on both the contents of a directory and # each of it's contents clean : rm -r $(target_d)/*