--- /dev/null
+{
+ "browser": true,
+ "laxbreak": true,
+ "globalstrict": true,
+ "validthis": true,
+ "devel": true,
+ "unused": "vars",
+ "camelcase": true,
+ "eqeqeq": true,
+ "latedef": true,
+ "nonew": true,
+ "undef": true,
+ "trailing": true,
+ "globals": {
+ "Event": false,
+ "Promise": false,
+ "Hammer": false,
+ "Buffer": false,
+ "gl": false,
+ "yf": false,
+ "yT": false,
+ "yuu": false,
+ "ystorage": false,
+ "mat4": false,
+ "vec3": false,
+ "vec2": false,
+ "quat": false,
+ "exports": false,
+ "module": false,
+ "process": false,
+ "require": false,
+ "escape": true
+ }
+}
#!/usr/bin/make -f
+#
+# 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.
nwjs-version := 0.12.0
-all:
-print-%: ; @echo $*=$($*)
+stampprefix := build/stamp/
-.DELETE_ON_ERROR:
-include rules/programs.mk
-include rules/javascript.mk
-include rules/icons.mk
-include rules/git.mk
-include rules/nwjs.mk
-include rules/pngcrush.mk
+include rules/default.mk
+$(call include-once,rules/*.mk)
-.PHONY: all check distclean lint test dist clean serve
+.PHONY: all check clean distclean lint test dist
APPLICATION := pwl6
-DISTDIR := build/dist
+DISTDIR := build/dist/
VERSION := $(call git-describe)
-DISTROOT := $(DISTDIR)/$(APPLICATION)_$(VERSION)
+DISTROOT := $(DISTDIR)$(APPLICATION)_$(VERSION)
-FIND_FILES := -type f ! -name '.*'
-FIND_JS := -type f -name '*.js'
+MY_SOURCES := $(call find-js,src -path 'src/ext' -prune -o)
+TEST_SOURCES := $(call find-js,test/spec)
-SOURCES := $(shell cd src && find . $(FIND_FILES))
-MY_SOURCES := $(shell cd src && find . $(FIND_JS) -not -path './ext/*')
-
-TEST_SOURCES := $(shell find test/spec $(FIND_JS))
-
-LINT_TARGETS := $(call jshint-stampify,$(MY_SOURCES))
-TEST_TARGETS := $(call jstest-stampify,$(TEST_SOURCES))
-
-JSHINTCONFIG := test/jshint.config
-JSTEST_NODE_PATH := src
VPATH := src
-ICONSETS := $(shell find src -type d -name '*.iconset')
-ICONS := $(ICONSETS:.iconset=.icns) $(ICONSETS:.iconset=.ico)
-
-IMAGEGZSRC := $(shell find src -type f -name '*.xcf.gz')
-IMAGESRC := $(shell find src -type f -name '*.xcf')
-IMAGES := $(IMAGEGZSRC:.xcf.gz=.png) $(IMAGESRC:.xcf=.png)
+ICONS := $(call iconset>icons,$(call find-iconsets,src))
+XCFS := $(call find-xcfs,src)
+OBJPNGS := $(call xcf>png,$(XCFS))
+PNGS := $(call find-files,src,-name '*.png') $(OBJPNGS)
-BUILT := $(ICONS) $(IMAGES)
+BUILT := $(ICONS) $(OBJPNGS)
+CRUSHABLE := $(call pngcrush-stampify,$(PNGS))
+LINTABLE := $(call jshint-stampify,$(MY_SOURCES))
+TESTABLE := $(call jstest-stampify,$(TEST_SOURCES))
+DISTFILES := $(addprefix $(DISTROOT)-,$(nwjs-platforms))
-HTTP_SERVER_PORT ?= 8000
+all:: check $(BUILT) $(CRUSHABLE)
-all: check $(BUILT) $(call pngcrush-stampify,$(IMAGES))
+dist: $(DISTFILES)
-$(DISTDIR):
- mkdir -p $@
-
-dist: $(addprefix $(DISTROOT),-src.zip -src.tar.gz .appcache .nw -osx-ia32.zip -osx-x64.zip -linux-ia32.tar.gz -linux-x64.tar.gz -win-ia32.zip)
-
-test/spec/%.js: %.js
+test/spec/%.js:: %.js
touch $@
-lint: $(LINT_TARGETS)
-
-test: $(TEST_TARGETS)
-
-check: lint test
+lint:: $(LINTABLE)
+test:: $(TESTABLE)
-serve: | $(npmbindir)/http-server
- $(npmbindir)/http-server $(@D) -p $(HTTP_SERVER_PORT) -c-1
+check:: lint test
-clean:
- $(RM) $(IMAGES)
- $(RM) $(ICONS)
- $(RM) -r build
+clean::
+ $(RM) $(DISTFILES)
+ $(RM) $(BUILT)
+ $(RM) $(LINTABLE)
+ $(RM) $(TESTABLE)
+ $(RM) $(CRUSHABLE)
+ $(call rmdir-r,build)
-distclean: clean
+distclean:: clean
$(RM) -r node_modules
- $(RM) $(nwjs-archives)
$(DISTROOT)-src.zip $(DISTROOT)-src.tar.gz: | .git
- mkdir -p $(@D)
+ $(MKDIR) $(@D)
$(call git-archive,$@,$(notdir $(DISTROOT))/)
$(DISTROOT).bare.zip: | .git
$(RM) $@
$(RM) -r $@.tmp
- mkdir -p $@.tmp
+ $(MKDIR) $@.tmp
cd src && $(GIT) archive $(call git-describe) . | tar -x -C ../$@.tmp
$(MAKE) $(BUILT:src/%=$@.tmp/%)
- $(RM) $(IMAGESRC:src/%=$@.tmp/%) $(IMAGEGZSRC:src/%=$@.tmp/%)
+ $(RM) $(XCFS:src/%=$@.tmp/%)
cd $@.tmp && $(ZIP) ../$(@F) -r .
$(RM) -r $@.tmp
--- /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.
+
+# Should be defaults.
+.DELETE_ON_ERROR:
+.DEFAULT_GOAL: all
+
+# Force these to be double-colon targets, so individual makefiles can
+# extend them as necessary (particularly for clean).
+all::
+clean::
+distclean::
+
+# http://blog.jgc.org/2015/04/the-one-line-you-should-add-to-every.html
+# Depends on FORCE because "implicit [pattern] rule search is skipped
+# for .PHONY targets."
+print-%: FORCE ; @echo $*=$($*)
+
+.PHONY: FORCE all clean distclean
+
+# Use with include to ensure files are included only once. e.g.:
+# $(call include-once,example.mk more-rules/*.mk)
+include-once = $(if $(wildcard $1),\
+ $(foreach f,$(sort $(wildcard $1)),\
+ $(eval include $(filter-out $(MAKEFILE_LIST),$f))),\
+ $(error $1: No such file or directory))
+
+# Call before including anything for the current makefile's directory.
+where-am-i = $(dir $(lastword $(MAKEFILE_LIST)))
+
+# Like include-once, but the files are searched for relative to the most
+# recently included file (usually the current one) not the current
+# working directory.
+include-once. = $(call include-once,$(addprefix $(call where-am-i),$1))
+
+
+# Quiet the output of a command, unless an error occurs. This is
+# similar to the shell 'chronic' / 'cronic' programs.
+#
+# To hide output unless an error occurs, pass a single argument:
+# $(call quiet,munge somefile)
+#
+# To store output to a file unless an error occurs, pass a second
+# argument of the filename. If an error occurs, this file will not
+# exist. Such a file will often be the rule's target.
+# $(call quiet,munge somefile,$@)
+
+define quiet
+@echo "$1" $(if $2,"> $2")
+$(eval QUIETTMP := $(firstword $2 $(shell mktemp -t make-quiet.XXXXX)))
+@($1) > $(QUIETTMP) \
+ || (STATUS=$$? \
+ && cat "$(QUIETTMP)" \
+ && $(RM) "$(QUIETTMP)" \
+ && exit $$STATUS)
+$(if $2,,$(RM) "$(QUIETTMP)")
+endef
+
endef
.git:
- $(error "This target must be run inside a git repository.")
+ $(error This target must be run inside a git repository.)
+++ /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:
-
-XCF2PNG ?= xcf2png
-
-%.png: %.xcf
- $(XCF2PNG) $< > $@
-
-# First: xcf2png by default calls zcat rather than gzcat. This is
-# totally always broken; zcat forces a .Z extension on its input
-# filename. So we can't rely on xcf2png's default behavior. But it
-# offers -Z for a custom decompression program.
-#
-# BUT: Gimp produces gz files with some padding zeros because, I don't
-# know, someone might want to save their compressed xcfs to DECtape.
-# gzip has a -q option to not *print* the warning associated with this
-# harmless thing, but then goes ahead and exits non-zero anyway, which
-# makes xcf2png barf and die before writing anything even though it
-# got perfectly good data.
-#
-# So: 1) use gunzip, 2) manually feed it to xcf2png, 3) hope nothing is
-# set to die based on pipe status, 4) hope that if the xcf data is
-# actually busted xcf2png will do something helpful.
-%.png: %.xcf.gz
- gunzip -c $< | $(XCF2PNG) - > $@
-
-.SECONDEXPANSION:
-
-ICONUTIL ?= $(firstword $(shell command -v iconutil icnsutil) iconutil)
-
-%.icns: %.iconset $$(wildcard $$(@D)/$$*.iconset/icon_*.png)
- $(ICONUTIL) -c icns -o $@ $<
-
-%.ico: %.iconset $$(wildcard $$(@D)/$$*.iconset/icon_*[0-9].png)
- convert -background transparent -colors 256 $(filter-out $<,$^) $@
-
--- /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.
+
+$(call include-once.,programs.mk)
+
+XCF2PNG ?= xcf2png
+ICONUTIL := $(call command-v,iconutil icnsutil)
+
+PNGCRUSH ?= pngcrush
+PNGCRUSHFLAGS ?= -brute -blacken -reduce -q
+CRUSH.png ?= $(PNGCRUSH) $(PNGCRUSHFLAGS) -ow
+
+%.png: %.xcf
+ $(XCF2PNG) $< > $@
+
+# First: xcf2png by default calls zcat rather than gzcat. This is
+# totally always broken; non-GNU zcat forces a .Z extension on its
+# input filename. So we can't rely on xcf2png's default behavior.
+# Luckily it offers -Z for a custom decompression program.
+#
+# BUT: When Gimp saves a .xcf.gz (and related formats), it doesn't
+# truncate the file, it just writes until it's done and closes, and
+# whatever data was after that, is still after that. This is terrible
+# because it means the file never shrinks, but it's still nominally a
+# valid gzip file, according to http://www.gzip.org/#faq8.
+#
+# BUT: The suggestion to use gzip -q in the FAQ doesn't work for
+# non-GNU gzip. It shuts up the 'warning,' yes, but it still exits
+# with status code 1 (not even 2, like GNU gzip does for all
+# warnings). It does write out the data perfectly well, at least.
+#
+# BUT (of course): The non-zero exit (somewhat reasonably) makes
+# xcf2png barf and die before writing anything even though it got all
+# the data it needs.
+#
+# So: 1) use gunzip, 2) manually feed it to xcf2png, 3) hope nothing
+# is set to die based on pipe status, 4) hope that if the xcf data is
+# truly busted xcf2png will do something helpful.
+%.png: %.xcf.gz
+ gunzip -c $< | $(XCF2PNG) - > $@
+
+# https://korewanetadesu.com/make-icons.html
+.SECONDEXPANSION:
+%.icns: %.iconset $$(wildcard $$(@D)/$$*.iconset/icon_*.png)
+ $(ICONUTIL) -c icns -o $@ $<
+
+%.ico: %.iconset $$(wildcard $$(@D)/$$*.iconset/icon_*[0-9].png)
+ convert -background transparent -colors 256 $(filter-out $<,$^) $@
+
+find-iconsets = $(shell find $1 -type d -name '*.iconset')
+find-xcfs = $(shell find $1 -type f -name '*.xcf.gz' -or -name '*.xcf')
+
+iconset>icons = $(1:.iconset=.icns) $(1:.iconset=.ico)
+xcf>png = $(patsubst %.xcf,%.png,$(patsubst %.xcf.gz,%.xcf,$1))
+
+pngcrush-stampprefix ?= $(stampprefix)
+pngcrush-stampify = $(1:%.png=$(pngcrush-stampprefix)%.png.crushed)
+
+$(pngcrush-stampprefix)%.png.crushed: %.png
+ $(MKDIR) $(@D)
+ $(CRUSH.png) $<
+ touch $@
# 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)
+$(call include-once.,programs.mk)
NPM ?= npm
NPMROOT ?= $(CURDIR)
npmbindir = $(NPMROOT)/node_modules/.bin
.PRECIOUS: $(npmbindir)/%
-npmbin = $(call javascript>fallback,$1,$(npmbindir)/$1)
+npmbin = $(call command-v,$1 $(npmbindir)/$1)
JSTEST ?= $(npmbindir)/jstest
JSHINT ?= $(call npmbin,jshint)
--compress $(UGLIFYCOMPRESSFLAGS) \
--mangle $(UGLIFYMANGLEFLAGS)
-BUILDDIR ?= build/
-JSSTAMPDIR ?= $(BUILDDIR)/stamp
-JSHINTDIR ?= $(JSSTAMPDIR)
-JSTESTDIR ?= $(JSSTAMPDIR)
-JSUGLYDIR ?= $(CURDIR)
+jsstampprefix ?= $(stampprefix)
+jsuglyprefix ?=
-JSHINTFLAGS += $(if $(JSHINTCONFIG),--config $(JSHINTCONFIG))
JSTESTFLAGS += $(if $(JSTESTFORMAT),--format $(JSTESTFORMAT))
+JSTEST_NODE_PATH ?= $(VPATH)
JSTESTENV += $(if $(JSTEST_NODE_PATH),NODE_PATH=$(JSTEST_NODE_PATH))
JSTESTFORMAT ?= spec
-jshint-stampify = $(patsubst %.js,$(JSHINTDIR)/%.js.lint,$1)
-jstest-stampify = $(patsubst %.js,$(JSTESTDIR)/%.js.test,$1)
-uglify-stampify = $(patsubst %.js,$(JSUGLYDIR)/%.min.js,$1)
+jshint-stampify = $(patsubst %.js,$(jsstampprefix)%.js.lint,$1)
+jstest-stampify = $(patsubst %.js,$(jsstampprefix)%.js.test,$1)
+uglify-stampify = $(patsubst %.js,$(jsuglyprefix)%.min.js,$1)
-javascript>capture-to-target = @echo "$1" && $1 > $@ || (cat $@ && exit 1)
+find-js = $(shell find $1 $(if $2,$2 -o) -type f -name '*.js' -print)
UGLIFY.js = $(UGLIFY) $(UGLIFYFLAGS)
LINT.js = $(JSHINT) $(JSHINTFLAGS)
TEST.js = $(JSTESTENV) $(JSTEST) $(JSTESTFLAGS)
-$(JSUGLYDIR)/%.min.js: %.js | $(UGLIFY)
- mkdir -p $(@D)
+$(jsuglyprefix)/%.min.js: %.js | $(UGLIFY)
+ $(MKDIR) $(@D)
$(UGLIFY.js) < $< > $@
-$(JSHINTDIR)/%.js.lint: %.js | $(JSHINT)
- mkdir -p $(@D)
+$(jsstampprefix)%.js.lint: %.js | $(JSHINT)
+ $(MKDIR) $(@D)
$(LINT.js) $<
touch $@
-$(JSTESTDIR)/%.js.test: %.js | $(JSTEST)
- mkdir -p $(@D)
- $(call javascript>capture-to-target,$(TEST.js) $<)
+$(jsstampprefix)%.js.test: %.js | $(JSTEST)
+ $(MKDIR) $(@D)
+ $(call quiet,$(TEST.js) $<,$@)
$(npmbindir)/%:
$(NPM) install $(firstword $(value $(@F)_npm_package) $(@F))
# 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:
-
-include $(dir $(realpath $(lastword $(MAKEFILE_LIST))))programs.mk
+$(call include-once.,programs.mk)
nwjs-platforms := \
osx-x64.zip osx-ia32.zip \
linux-x64.tar.gz linux-ia32.tar.gz \
win-ia32.zip
-nwjs-pattern := \
- $(addprefix nwjs-v%-,$(nwjs-platforms))
+nwjs-pattern := $(addprefix nwjs-v%-,$(nwjs-platforms))
# These are like 30MB, don't download them every time.
.PRECIOUS: $(nwjs-pattern)
$(nwjs-pattern):
- mkdir -p $(@D)
- wget -O $@ http://dl.nwjs.io/v$(*F)/$(@F) || ($(RM) $@ && exit 1)
+ $(MKDIR) '$(@D)'
+ wget -O '$@'.inprogress 'http://dl.nwjs.io/v$(*F)/$(@F)'
+ mv '$@'.inprogress "$@"
-nwjs-version ?= 0.10.2
-nwjs-prefix ?= nwjs/
-nwjs-directx = $(addprefix $(nwjs-prefix),d3dcompiler_43.dll d3dcompiler_46.dll)
+nwjs-version ?= 0.12.0
+nwjsdir ?= nwjs/
+nwjs-directx = $(addprefix $(nwjsdir),d3dcompiler_43.dll d3dcompiler_46.dll)
-nwjs = $(nwjs-prefix)nwjs-v$(firstword $(value nwjs-version-$1) $(nwjs-version))-$1
+nwjs = $(nwjsdir)nwjs-v$(firstword $(value nwjs-version-$1) $(nwjs-version))-$1
nwjs-archives = $(foreach p,$(nwjs-platforms),$(call nwjs,$(p)))
$(RM) $@
$(RM) -r $(@:.tar.gz=)
tar -C $(@D) -xzf $2
- mkdir -p $(@:.tar.gz=)
+ $(MKDIR) $(@:.tar.gz=)
mv $(@D)/$(notdir $(2:.tar.gz=)) $(@:.tar.gz=)/nw
cp -a $1 $(@:.tar.gz=)/nw/package.nw
cp -a tools/nw-linux-wrapper $(@:.tar.gz=)/`echo $(notdir $1) | sed -E 's/_.+//'`
%-linux-x64.tar.gz: %.nw $(call nwjs,linux-x64.tar.gz)
$(call nwjs-package-linux,$<,$(word 2,$^))
-WINE ?= wine
-
nwjs-icon = $(shell $(UNZIP) -p $1 package.json | grep -Eo '"[^"]+.ico"' -m 1)
define nwjs-package-win
$(RM) $@
$(RM) -r $(@:.zip=)
- if $(UNZIP) -l $2 credits.html > /dev/null; then $(UNZIP) -d $(@D)/$(notdir $(2:.zip=)) $2; else $(UNZIP) -d $(@D) $2; fi
+ $(UNZIP) -d $(@D) $2
mv $(@D)/$(notdir $(2:.zip=)) $(@:.zip=)
$(RM) $(@:.zip=)/nwjc.exe
$(UNZIP) -p $< $(call nwjs-icon,$<) > $(@D)/icon.ico
$(nwjs-directx):
wget -O $@ 'https://github.com/cefsharp/cef-binary/raw/1e51255cf77d267899bf7834768b8774affaad2d/cef_binary_3.y.z_windows32/Release/'$(notdir $@)
-$(nwjs-prefix)dxwebsetup.exe:
+$(nwjsdir)dxwebsetup.exe:
wget -O $@ http://download.microsoft.com/download/1/7/1/1718CCC4-6315-4D8E-9543-8E28A4E18C4C/dxwebsetup.exe
+
+distclean::
+ $(RM) $(nwjs-archives)
+ $(RM) $(nwjs-directx)
+ $(RM) $(nwjsdir)dxwebsetup.exe
+++ /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:
-
-BUILDDIR ?= build/
-PNGCRUSHSTAMPDIR ?= $(BUILDDIR)/stamp
-
-pngcrush-stampify = $(patsubst %.png,$(PNGCRUSHSTAMPDIR)/%.png.crushed,$1)
-
-PNGCRUSH ?= pngcrush
-PNGCRUSHFLAGS ?= -brute -blacken -reduce -q
-
-CRUSH.png ?= $(PNGCRUSH) $(PNGCRUSHFLAGS)
-
-$(PNGCRUSHSTAMPDIR)/%.png.crushed: %.png
- $(CRUSH.png) -ow $<
- mkdir -p $(@D)
- touch $@
ZIP = zip $(ZIPFLAGS)
ifneq ($(OS),Windows_NT)
- WINE ?= wine
+WINE ?= wine
endif
+
+find-files = $(shell find $1 -type f $2 -print $3)
+
+rmdir-r = [ ! -e $1 ] || find -d $1 -type d -delete
+
+# Use to find the best command to execute out of a series of possible
+# equivalent ones, or provide a fallback. If a second argument is
+# supplied it is used as the fallback, otherwise the first element of
+# the checked executables is used. e.g.
+# PYLINTER := $(call command-v,flake8 pyflakes,python -mpy_compile)
+# will pick flake8 if it's installed, or pyflakes if it isn't,
+# or python -mpy_compile (a syntax check) if neither is
+# installed.
+command-v = $(firstword $(shell command -v $1) $2 $1)
+
+# Use in place of 'mkdir -p' to avoid littering every other line of
+# output with a redundant mkdir call; the downside is that it can't be
+# silenced itself.
+MKDIR = @$(SHELL) -c '[ -d "$$0" ] || echo mkdir -p "$$0" && mkdir -p "$$0"'
--- /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.
+
+$(call include-once.,javascript.mk)
+
+HTTP_SERVER_PORT ?= 8000
+
+serve: | $(npmbindir)/http-server
+ $(npmbindir)/http-server $(@D) -p $(HTTP_SERVER_PORT) -c-1
+
+.PHONY: serve
+++ /dev/null
-{
- "browser": true,
- "laxbreak": true,
- "globalstrict": true,
- "validthis": true,
- "devel": true,
- "unused": "vars",
- "camelcase": true,
- "eqeqeq": true,
- "latedef": true,
- "nonew": true,
- "undef": true,
- "trailing": true,
- "globals": {
- "Event": false,
- "Promise": false,
- "Hammer": false,
- "Buffer": false,
- "gl": false,
- "yf": false,
- "yT": false,
- "yuu": false,
- "ystorage": false,
- "mat4": false,
- "vec3": false,
- "vec2": false,
- "quat": false,
- "exports": false,
- "module": false,
- "process": false,
- "require": false,
- "escape": true
- }
-}