#!/usr/bin/make -f
PKGNAME := string-lerp
-
-fallback = $(firstword $(shell command -v $(1)) $(2))
+all:
+ $(info Interesting targets:)
+ $(info lint - validate source (with jshint))
+ $(info test - run tests (with jstest))
+ $(info ugly - generate minified source files)
+ $(info dist - generate redistributables (if git tagged))
+ $(info )
+ $(info (Running these may download packages from npm.))
+ $(info )
+ @:
+
+include javascript.mk
GIT ?= git
-git_ls-tree = $(shell $(GIT) ls-tree -r --name-only $(1))
-git_tag = $(shell $(GIT) name-rev --tags --name-only $(shell $(GIT) rev-parse $(1)))
-
-NPM ?= npm
-NPMBINDIR := ./node_modules/.bin
-JSTEST ?= $(NPMBINDIR)/jstest
-JSHINT ?= $(call fallback,jshint,$(NPMBINDIR)/jshint)
-UGLIFY ?= $(call fallback,uglifyjs,$(NPMBINDIR)/uglifyjs)
-SOURCES := string-lerp.js
-UGLIFIED = $(SOURCES:.js=.min.js)
-
-JSHINTFLAGS += --config tests/jshint.config
+git-describe = $(shell $(GIT) describe --tags --always $1)
-TESTS = $(wildcard tests/*.js)
-LINT_TARGETS = $(patsubst %.js,build/stamp/%.lint,$(SOURCES))
-TEST_TARGETS = $(patsubst %.js,build/stamp/%.test,$(SOURCES)) \
- $(patsubst tests/%.js,build/stamp/%.test,$(TESTS))
-
-.PHONY: all check lint test ugly dist clean distclean install
+SOURCES := string-lerp.js
+UGLIFIED := $(call uglify-stampify,$(SOURCES))
-all:
- @echo "Interesting targets:"
- @echo " lint - validate source (with jshint)"
- @echo " test - run tests (with jstest)"
- @echo " ugly - generate minified/mangled source files"
- @echo " dist - generate redistributables (if git tagged)"
- @echo
- @echo "(Running these may download packages from npm.)"
- @echo
-
-%.min.js: %.js | $(UGLIFY)
- $(UGLIFY) --comments -m < $< > $@
-
-build/stamp/%.lint: %.js | $(JSHINT)
- @mkdir -p $(@D)
- $(JSHINT) $(JSHINTFLAGS) $<
- @touch $@
+JSHINTCONFIG := tests/jshint.config
+JSSTAMPDIR := build/stamp
-build/stamp/%.test: tests/%.js %.js | $(JSTEST)
- @mkdir -p $(@D)
- @echo $(JSTEST) $<
- @$(JSTEST) $< > $@ || (cat $@ && rm -f $@ && exit 1)
- @touch $@
+TESTS := $(wildcard tests/*.js)
+LINTS := $(call jshint-stampify,$(SOURCES) $(TESTS))
+TEST_TARGETS = $(patsubst %.js,build/stamp/tests/%.js.test,$(SOURCES))
-build/stamp/%.test: tests/%.js $(SOURCES) | $(JSTEST)
- @mkdir -p $(@D)
- @echo $(JSTEST) $<
- @$(JSTEST) $< > $@ || (cat $@ && rm -f $@ && exit 1)
- @touch $@
+.DELETE_ON_ERROR:
+.PHONY: all check lint test ugly dist clean distclean install .FORCE
check: lint test
-lint: $(LINT_TARGETS)
+lint: $(LINTS)
test: $(TEST_TARGETS)
-ugly: $(UGLIFIED)
-
-build/dist/$(PKGNAME)-undefined.zip build/dist/$(PKGNAME)-undefined.tar.gz:
- $(error Distributables must be tagged or explicitly versioned)
-
-.SECONDEXPANSION:
-build/dist/$(PKGNAME)-%.zip: $$(call git_ls-tree,$$*)
- @mkdir -p $(@D)
- $(GIT) archive --prefix=$(PKGNAME)-$*/ --output=$@ $* || ($(RM) $@ && exit 1)
+ugly: check $(UGLIFIED)
-.SECONDEXPANSION:
-build/dist/$(PKGNAME)-%.tar.gz: $$(call git_ls-tree,$$*)
+$(PKGNAME)-%.zip $(PKGNAME)-%.tar.gz: .FORCE
@mkdir -p $(@D)
- $(GIT) archive --prefix=$(PKGNAME)-$*/ --output=$@ $* || ($(RM) $@ && exit 1)
+ $(GIT) archive --prefix=$(PKGNAME)-$(*F)/ --output=$@ $(*F)
-dist: check $(addprefix build/dist/$(PKGNAME)-$(call git_tag,HEAD),.zip .tar.gz)
+dist: check $(addprefix build/dist/$(PKGNAME)-$(call git-describe),.zip .tar.gz)
clean:
$(RM) -r build
install: check
$(NPM) install -g .
-
-$(JSTEST):
- $(NPM) install jstest
-
-$(JSHINT):
- $(NPM) install jshint
-
-$(UGLIFY):
- $(NPM) install uglify-js
--- /dev/null
+# This is free and unencumbered software released into the public
+# domain. To the extent possible under law, the author of this file
+# waives all copyright and related or neighboring rights to it.
+
+.DELETE_ON_ERROR:
+
+javascript>fallback = $(firstword $(shell command -v $1) $2 $1)
+
+NPM ?= npm
+NPMROOT ?= .
+
+npmbindir = $(NPMROOT)/node_modules/.bin
+.PRECIOUS: $(npmbindir)/%
+
+from-npm = $(call javascript>fallback,$1,$(npmbindir)/$1)
+
+JSTEST ?= $(npmbindir)/jstest
+JSHINT ?= $(call from-npm,jshint)
+
+uglifyjs_npm_package := uglify-js
+
+UGLIFY ?= $(call from-npm,uglifyjs)
+UGLIFYFLAGS ?= --comments \
+ --compress $(UGLIFYCOMPRESSFLAGS) \
+ --mangle $(UGLIFYMANGLEFLAGS)
+
+JSSTAMPDIR ?= build/stamp
+JSHINTDIR ?= $(JSSTAMPDIR)
+JSTESTDIR ?= $(JSSTAMPDIR)
+JSUGLYDIR ?= .
+
+JSHINTFLAGS += $(if $(JSHINTCONFIG),--config $(JSHINTCONFIG))
+JSTESTFLAGS += $(if $(JSTESTFORMAT),--format $(JSTESTFORMAT))
+JSTESTFORMAT ?= spec
+
+jshint-stampify = $(patsubst %.js,$(JSHINTDIR)/%.js.lint,$1)
+uglify-stampify = $(patsubst %.js,$(JSUGLYDIR)/%.min.js,$1)
+
+javascript>capture-to-target = @echo "$1" && $1 > $@ || (cat $@ && exit 1)
+
+UGLIFY.js = $(UGLIFY) $(UGLIFYFLAGS)
+LINT.js = $(JSHINT) $(JSHINTFLAGS)
+TEST.js = $(JSTEST) $(JSTESTFLAGS)
+
+$(JSUGLYDIR)/%.min.js: %.js | $(UGLIFY)
+ @mkdir -p $(@D)
+ $(UGLIFY.js) < $< > $@
+
+$(JSHINTDIR)/%.js.lint: %.js | $(JSHINT)
+ @mkdir -p $(@D)
+ $(LINT.js) $<
+ @touch $@
+
+$(JSTESTDIR)/%.js.test: %.js | $(JSTEST)
+ @mkdir -p $(@D)
+ $(call javascript>capture-to-target,$(TEST.js) $<)
+
+$(npmbindir)/%:
+ $(NPM) install $(firstword $(value $(@F)_npm_package) $(@F))