-
Notifications
You must be signed in to change notification settings - Fork 30
/
makefile
250 lines (207 loc) · 7.9 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
# ===== Makefile Configuration =====
# Favor local npm devDependencies if they are installed
export PATH := node_modules/.bin:$(PATH)
# Use the `>` character rather than tabs for indentation
ifeq ($(origin .RECIPEPREFIX), undefined)
$(error This Make does not support .RECIPEPREFIX. Please use GNU Make 4.0 or later)
endif
.RECIPEPREFIX = >
# Use one shell to run all commands in a given target rather than using
# the default setting of running each command in a separate shell
.ONESHELL:
# Make's default shell is `sh`. Setting this to `bash` enables
# the shell flags below to work.
SHELL := bash
# set -e = bash immediately exits if any command has a non-zero exit status.
# set -u = a reference to any shell variable you haven't previously
# defined -- with the exceptions of $* and $@ -- is an error, and causes
# the program to immediately exit with non-zero code.
# set -o pipefail = the first non-zero exit code emitted in one part of a
# pipeline (e.g. `cat file.txt | grep 'foo'`) will be used as the exit
# code for the entire pipeline. If all exit codes of a pipeline are zero,
# the pipeline will emit an exit code of 0.
.SHELLFLAGS := -eu -o pipefail -c
# Emits a warning if you are referring to Make variables that don’t exist.
MAKEFLAGS += --warn-undefined-variables
# Removes a large number of built-in rules. Remove "magic" and only do
# what we tell Make to do.
MAKEFLAGS += --no-builtin-rules
# ===== Makefile - Repo Commands =====
# Variables get that a list of all recipes that can be run on
# Node.js or browser backends
#
# wildcard = expand globs and add a space in-between each one
# patsubst = patsubst(textToFind,replaceItWithThisText,originalText)
targetsNodeWithCI := $(patsubst recipes/%/nodeSupported.md,%-node,$(wildcard recipes/*/nodeSupported.md))
targetsNodeSkipCI := $(patsubst recipes/%/nodeSupportedSkipCI.md,%-node,$(wildcard recipes/*/nodeSupportedSkipCI.md))
targetsNode := $(targetsNodeWithCI) $(targetsNodeSkipCI)
targetsWeb := $(patsubst recipes/%/web,%-web,$(wildcard recipes/*/web))
# Targets for CI
targetsNodeBuildOnlyCI := $(patsubst %-node,%-build,$(targetsNodeSkipCI))
targetsWebBuildOnlyCI := $(patsubst %-web,%-buildWeb,$(targetsWeb))
targetsAllCI := $(targetsNodeWithCI) $(targetsNodeBuildOnlyCI) $(targetsWebBuildOnlyCI)
# Build everything. For editor tags.
targetsBuild := $(patsubst recipes/%/,%-build,$(wildcard recipes/*/))
# Note: usages of `.PHONY: <target>` mean the target name is not an actual file
# .PHONY: targetName
# Prints all the recipes one could run via make and clarifying text.
# For now, we assume that each recipe has a `node` and `web` command,
# but not all of these will work.
.PHONY: list
list:
> @echo Use \"make RecipeName-target\" to run a recipe
> @echo
> @echo === Node Recipes ===
> @echo $(foreach t,$(targetsNode),make_$(t)) | tr ' ' '\n' | tr '_' ' '
> @echo
> @echo === Web Recipes ===
> @echo $(foreach t,$(targetsWeb),make_$(t)) | tr ' ' '\n' | tr '_' ' '
# Regenerate the ReadMe and its Recipe ToC using the current list of recipes
.PHONY: readme
readme:
> @echo Recreating the repo\'s README.md file...
> ./scripts/generateRecipeTable.sh > README.md
> @echo Done!
# Prints version and path information.
# For troubleshooting version mismatches.
.PHONY: info
info:
> which purs
> purs --version
> which spago
> spago version
> which parcel
> parcel --version
> which npm
> npm --version
# Downloads all dependencies and sets up cookbook, so that end-user doesn't
# accidentally use `npm`.
.PHONY: installDeps
installDeps:
> npm i
> rm package-lock.json
# Format PureScript code
.PHONY: format
format:
> npx purs-tidy format-in-place recipes broken
# Check PureScript code is formatted
.PHONY: formatCheck
formatCheck:
> npx purs-tidy check recipes broken
# ===== Makefile - Recipe-related Commands =====
# Tests if recipe actually exists.
# The unused dummy lowpriority prerequisite is just to allow
# the rule for recipes/%/web/index.html to take priority over this rule.
# https://stackoverflow.com/questions/62494658/gnu-make-not-matching-shortest-stem
recipes/%: lowpriority%
> @if [ ! -d $* ]
> then
> echo
> echo Recipe $* does not exist
> echo
> exit 1
> fi
# Does nothing. See above for explanation.
lowpriority%:
@:
# Variables shared across most targets
recipes := $(shell ls recipes)
# Functions shared across most targets that help generate paths
main = $1.Main
recipeDir = recipes/$1
recipeSpago = $(call recipeDir,$1)/spago.dhall
# Functions for Node.js-comptabile recipes that help generate paths
nodeCompat = $(call recipeDir,$1)/nodeSupported.md
nodeCompatSkipCI = $(call recipeDir,$1)/nodeSupportedSkipCI.md
# Tests whether recipe can be run on Node.js backend
.PHONY: %-nodeCompatible
%-nodeCompatible:
> @if [ ! -f $(call nodeCompat,$*) ] && [ ! -f $(call nodeCompatSkipCI,$*) ]
> then
> echo
> echo Recipe $* is not compatible with Node.js backend
> echo
> exit 1
> fi
# Runs recipe as node.js console app
.PHONY: %-node
%-node: $(call recipeDir,%) %-nodeCompatible
> @echo === Running $* on the Node.js backend ===
> spago -x $(call recipeSpago,$*) run --main $(call main,$*)
# Watches for changes and rebuilds and reruns recipe as node.js console app
.PHONY: %-node-watch
%-node-watch: $(call recipeDir,%) %-nodeCompatible
> @echo === Watching to build and run $* on the Node.js backend ===
> spago -x $(call recipeSpago,$*) run --main $(call main,$*) -w
# Functions for browser-comptabile recipes that help generate paths
webDir = $(call recipeDir,$1)/web
webHtml = $(call webDir,$1)/index.html
webJs = $(call webDir,$1)/index.js
webDistDir = $(call recipeDir,$1)/web-dist
prodDir = $(call recipeDir,$1)/prod
prodHtml = $(call prodDir,$1)/index.html
prodJs = $(call prodDir,$1)/index.js
prodDistDir = $(call recipeDir,$1)/prod-dist
# Builds a single recipe. A build is necessary before parcel commands.
.PHONY: %-build
%-build:
> @echo === Building $* ===
> spago -x $(call recipeSpago,$*) build
# Watches for changes and rebuilds recipe
.PHONY: %-build-watch
%-build-watch:
> @echo === Watching to Build $* ===
> spago -x $(call recipeSpago,$*) build -w
# Tests whether recipe can be run on web browser backend
recipes/%/web:
> @echo Recipe $* is not compatible with the web browser backend
> exit 1
# Check if index.js points to another recipe.
%-indexCheck:
> @if ! grep "import { main } from \"../../../output/$*.Main/index.js\";" $(call webJs,$*) --quiet
> then
> echo Error: $(call webJs,$*) points to another recipe:
> cat $(call webJs,$*)
> exit 1
> fi
.PHONY: %-web
# Launches recipe in web browser
%-web: $(call recipeDir,%) $(call webDir,%) %-indexCheck %-build
> @echo === Launching $* in the web browser ===
> parcel $(call webHtml,$*) --dist-dir $(call webDistDir,$*) --open
.PHONY: %-buildWeb
# Uses parcel to quickly create an unminified build.
# For CI purposes.
%-buildWeb: export NODE_ENV=development
%-buildWeb: $(call recipeDir,%) $(call webDir,%) %-indexCheck %-build
> @echo === Building $* for the web browser backend ===
> parcel build $(call webHtml,$*) --dist-dir $(call webDistDir,$*) --no-optimize --no-source-maps
# How to make prodDir
recipes/%/prod:
> mkdir -p $@
# How to make prodHtml
recipes/%/prod/index.html: $(call prodDir,%)
> cp $(call webHtml,$*) $(call prodDir,$*)
.PHONY: %-buildProd
# Creates a minified production build.
# For reference.
%-buildProd: $(call recipeDir,%) $(call webDir,%) $(call prodHtml,%)
> @echo === Building $* for production ===
> spago -x $(call recipeSpago,$*) bundle-app --main $(call main,$*) --to $(call prodJs,$*)
> parcel build $(call prodHtml,$*) --dist-dir $(call prodDistDir,$*)
# Build everything. For editor tags.
.PHONY: buildAll
buildAll: $(targetsBuild)
# ===== Makefile - CI Commands =====
# Run all recipes CI
.PHONY: testAllCI
testAllCI: $(targetsAllCI)
.PHONY: testAllCommands
# Verifies that running all the above commands for a single
# recipe actually works.
testAllCommands:
> $(MAKE)
> $(MAKE) HelloLog-node
> $(MAKE) HelloLog-build
> $(MAKE) HelloLog-buildWeb
> $(MAKE) HelloLog-buildProd