-
Notifications
You must be signed in to change notification settings - Fork 4
/
Makefile
340 lines (277 loc) · 9.57 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
## Copyright (C) 2018 David Pinto <[email protected]>
##
## Copying and distribution of this file, with or without modification,
## are permitted in any medium without royalty provided the copyright
## notice and this notice are preserved. This file is offered as-is,
## without any warranty.
PACKAGE := SPEKcheck
VERSION := 0.2+dev
## Configuration
##
## This Makefile should probably be generated by a configure script
## from a Makefile.in. We are not doing that so instead of configure,
## users can set this via environment variables or Make options. Like
## so:
##
## make NPM=~/.local/bin/npm
BASE64 ?= base64
GZIP ?= gzip
ICOTOOL ?= icotool
MKDIR ?= mkdir
MKDIR_P ?= mkdir -p
NPM ?= npm
PYTHON ?= python
RSVG_CONVERT ?= rsvg-convert
SED ?= sed
SHASUM ?= shasum
TAR ?= tar
XXD ?= xxd
ZIP ?= zip
GZIP_ENV ?= --best
##
##
##
distdir := $(PACKAGE)-$(VERSION)
DIST_TARGETS := dist-gzip dist-zip
npm_css := \
node_modules/bootstrap/dist/css/bootstrap.min.css
## The order of this dependencies matters because it's the order that
## will be used when creating the index.html and help.html files.
npm_js := \
node_modules/jquery/dist/jquery.min.js \
node_modules/popper.js/dist/umd/popper.min.js \
node_modules/bootstrap/dist/js/bootstrap.min.js \
node_modules/chart.js/dist/Chart.min.js
npm_licenses := \
node_modules/jquery/LICENSE.txt \
node_modules/bootstrap/LICENSE \
node_modules/chart.js/LICENSE.md
## popper does not include a LICENSE file on their distribution but
## they have the MIT header on the min.js file that we include.
npm_files := \
$(npm_css) \
$(npm_js) \
$(npm_licenses)
## The data files are a bit different, we will handle each of the data
## directories as one thing, rather than multiple individual files.
##
## The reason for this is that the data files can have any character
## on the name. If we then use their filenames on bash commands, we
## need to be extra careful and we don't want to because that's really
## tricky (we can just quote them but then we have to handle quotes in
## the filename and anything else that may be expanded by the shell).
## Also, they can't be used as Make targets or pre-requesites at all
## because they may have whitespace on name.
data_dirs := \
data/detectors \
data/dyes \
data/excitation \
data/filters
data_indices := $(foreach dtype, $(data_dirs), $(dtype).json)
## The SPEKcheck releases includes all the files, and we even have a
## good portion of them committed to the repo because they are few,
## small, change rarely, and require special tools. Still, list them
## separate so we can remove them all with maintainer-clean.
buildable_files := \
help.html \
images/favicon.ico \
images/favicon.png \
images/micron-logo.png \
images/spekcheck-logo.png \
images/visible-spectrum.png \
index.html \
$(data_indices) \
$(npm_files)
DISTFILES := \
COPYING \
Makefile \
NEWS \
README \
css/spekcheck.css \
data/setups.json \
images/micron-logo.svg \
images/README \
images/spekcheck-logo.svg \
js/spekcheck.js \
src/create-spectrum.py \
templates/spekcheck.html \
$(buildable_files)
## Default target (first declared target) must be all (per GNU
## standards). For the case of SPEKcheck, this is just DISTFILES.
all: $(DISTFILES)
help:
@echo "Targets:"
@echo " serve serve site at http://localhost:8000"
@echo " dist create all distribution files (tar.gz and zip)"
@echo " dist-zip create distribution zip file"
@echo " dist-gzip create distribution tar.gz file"
@echo ""
@echo " maintainer-clean"
@echo " Removes all files that can be rebuilt. It may"
@echo " require special tools to do so though."
##
## Rules for the images, logos, etc.
##
images/visible-spectrum.png: src/create-spectrum.py
$(PYTHON) $^ $@
## visible-spectrum.png is a prerequesite because it is linked from
## the svg file.
images/spekcheck-logo.png: images/spekcheck-logo.svg images/visible-spectrum.png
$(RSVG_CONVERT) --format png $< > $@
images/favicon.png: images/spekcheck-logo.svg images/visible-spectrum.png
$(RSVG_CONVERT) --format png --width 16 --height 16 $< > $@
images/micron-logo.png: images/micron-logo.svg
$(RSVG_CONVERT) --format png $< > $@
## Not all browsers support png for their icons, so we need this
## conversion. See https://caniuse.com/#feat=link-icon-png
images/favicon.ico: images/favicon.png
$(ICOTOOL) --create --raw $< > $@
##
## Rules for the data stuff.
##
## This makes the files dependent on the directory which is mehh. I'm
## a bit unsure about the implications and when the json file then
## becomes out of date.
%.json: %
$(PYTHON) -c \
"import os, json; \
files = [f for f in os.listdir('$^') if f.endswith('.csv')]; \
print(json.dumps([x[:-4] for x in sorted(files)], \
separators=(',',': '), indent=2));" \
> $@
##
## Rules for the external dependecies (npm packages)
##
npm_basedir := node_modules
npm_pkg_name = $(word 2, $(subst /, ,$(1)))
npm_pkg_json = $(npm_basedir)/$(1)/package.json
## We use npm to download all of our dependencies. Because some of
## them are dependent on each other and npm will automatically get
## their dependencies, we have to prevent make from running in
## parallel.
.NOTPARALLEL:
define NPM_INSTALL_RULE
$(call npm_pkg_json,$1):
$(NPM) install $1
endef
$(foreach file, $(npm_files), \
$(eval $(file): $(call npm_pkg_json,$(call npm_pkg_name,$(file)))))
## sort removes duplicates which is what we want
npm_packages := \
$(sort $(foreach file, $(npm_files),$(call npm_pkg_name,$(file))))
$(foreach pkg, $(npm_packages), \
$(eval $(call NPM_INSTALL_RULE,$(pkg))))
##
## Rules for index.html and help.html
##
## We download the external dependencies via npm when preparing the
## package, and we check the integrity values of that. This seems
## kinda pointless but the idea is to make it easier to have a
## configure-like option to have the files regenerated pointing to a
## CDN.
templates/link-includes.in: $(npm_css)
$(RM) $@
for FILE in $^ ; do \
INTEGRITY=`$(SHASUM) -b -a 384 "$$FILE" | $(XXD) -r -p | $(BASE64)`; \
echo ' <link rel="stylesheet" type="text/css"' >> $@; \
echo ' href="'"$$FILE"'"' >> $@; \
echo ' integrity="sha384-'"$$INTEGRITY"'"' >> $@; \
echo ' crossorigin="anonymous"/>' >> $@; \
done
templates/script-includes.in: $(npm_js)
$(RM) $@
for FILE in $^ ; do \
INTEGRITY=`$(SHASUM) -b -a 384 "$$FILE" | $(XXD) -r -p | $(BASE64)`; \
echo ' <script src="'"$$FILE"'"' >> $@; \
echo ' integrity="sha384-'"$$INTEGRITY"'"' >> $@; \
echo ' crossorigin="anonymous"></script>' >> $@; \
done
%.html: templates/%.html.in templates/script-includes.in templates/link-includes.in
$(SED) -e '/@EXTERNAL_SCRIPT_INCLUDES@/ {' \
-e ' r templates/script-includes.in' \
-e ' d' \
-e '}' \
-e '/@EXTERNAL_LINK_INCLUDES@/ {' \
-e ' r templates/link-includes.in' \
-e ' d' \
-e '}' \
$< > $@
##
## Rules for testing
##
serve: all
$(PYTHON) -m SimpleHTTPServer
check:
@echo "We should have but we don't have any tests yet."
##
## Rules to prepare distribution
##
## Creates a directory with the files to include in the distribution
## and build packages out of that. The directory itself should be
## created anew each time to avoid having an old directory around with
## old files.
## Individual dist recipes call 'post_remove_distdir' at the end, so
## we need a way to disable it when calling multiple dist-* targets.
## Having this as a variable allows that. See recipe for 'dist' which
## builds all DIST_TARGETS. But we also need one that is not
## overridable to be used at the start of the distdir target, hence
## the two functions *remove_distdir.
remove_distdir = \
if test -d "$(distdir)"; then \
find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
&& $(RM) -r "$(distdir)" \
|| { sleep 5 && $(RM) -r "$(distdir)"; }; \
else :; fi
post_remove_distdir = $(remove_distdir)
dist:
$(MAKE) $(DIST_TARGETS) post_remove_distdir='@:'
$(post_remove_distdir)
distdir: $(DISTFILES)
$(remove_distdir)
$(MKDIR) "$(distdir)"
$(MKDIR_P) $(addprefix $(distdir)/, \
$(sort $(filter-out ./, $(dir $(DISTFILES)))))
for FILE in $(DISTFILES); do \
cp "$$FILE" "$(distdir)/$$FILE"; \
done
## The data files are handled differently, because we don't
## know their filenames.
for DIR in $(data_dirs); do \
cp -R "$$DIR" "$(distdir)/$$DIR"; \
done
dist-gzip: distdir
@$(TAR) chof - $(distdir) | $(GZIP) $(GZIP_ENV) -c > $(distdir).tar.gz
$(post_remove_distdir)
## We remove any old zip file before creating a new one, because if
## the zip file already exists, the zip command will add files to the
## existing archive instead of creating a new one.
dist-zip: distdir
$(RM) $(distdir).zip
$(ZIP) -rq $(distdir).zip $(distdir)
$(post_remove_distdir)
## The 'clean' target removes files normally created by building the
## program. The 'distclean' target would also remove files by
## configure so that only the files originally in the release are
## left. The SPEKcheck releases, there's none, but keep the target
## for consistency.
clean:
distclean: clean
## Delete almost everything that can be reconstructed with this
## Makefile.
maintainer-clean: distclean
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
$(RM) $(buildable_files)
$(RM) -r $(npm_basedir)
.PHONY: \
all \
check \
clean \
dist \
dist-gzip \
dist-zip \
distclean \
distdir \
help \
maintainer-clean \
serve