SRC_DIR := src
BUILD_DIR := build
-MARKDOWN_FILES := $(wildcard $(SRC_DIR)/**/*.md)
-HTML_FILES := $(patsubst $(SRC_DIR)/%.md, $(BUILD_DIR)/%, $(MARKDOWN_FILES))
+IGNORE_VCS=*.git*
.PHONY: all clean index
-all: $(HTML_FILES)
-
-index:
+# Pro/con - this builds *everything* due to recursion
+# Pro - simple
+# Con - I can't do make build/demo; make index to get a partial build.
+# Idea -
+# I think I could use mindepth/maxdepth in the subdirs find.
+# Then, make index wouldn't recurse.
+index: $(BUILD_DIR)
scripts/index.sh > build/index.html
-# Build HTML file from Markdown
+# This pattern defines a multi-target rule; it defines a target
+# build/DIR for each DIR in src/DIR.
+subdirs := $(shell find -L $(SRC_DIR) -type d -not -path $(IGNORE_VCS))
+builddirs := $(patsubst $(SRC_DIR)%, $(BUILD_DIR)%, $(subdirs))
+
+# USAGE: `make $(BUILD_DIR)/arbitary-dir`
+# BEHAVIOR: For each file in the build dir, invoke the markdown rule.
+# UNDERSTANDING THE APPROACH:
+# 1. From build target $@,
+# 2. Get a list of corresponding md files in SRC_DIR $(shell find ...), and
+# 3. Rewrite the result as a build target $(patsubstr $(SRC_DIR)%.md, ...)
+# WHY $$ and .SECONDEXPANSION?
+# To let users specify arbitrary directories, I wanted to use the target $@
+# in the prerequisites. To get scoping to work for $@ in the prerequisites,
+# you must go through a second phase of expansion. The $$ defers expansion
+# until the second phase. Single $ can be expanded on the first phase.
+.SECONDEXPANSION:
+$(builddirs): $$(patsubst $(SRC_DIR)%.md, $(BUILD_DIR)%, $$(shell find -L $$(patsubst $(BUILD_DIR)%, $(SRC_DIR)%, $$@) -name '*.md'))
+
+# For a given md file in src, make the corresponding html in build.
$(BUILD_DIR)/%: $(SRC_DIR)/%.md
@mkdir -p $(dir $@)
@pandoc \
--standalone \
--defaults=./defaults.yml \
--output=$@ $<
- @echo "Building $@ from $<"
+ @echo "Building $@ from $<..."
# Clean up generated HTML files
clean: