/
Makefile
390 lines (312 loc) · 16.8 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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
##########################################################################
# Makefile for the 'Compilerbau' lecture
##########################################################################
## Run 'make' or 'make help' to display commonly used targets. Targets for
## individual files also exist but should only be used if you know what
## you are doing.
## NOTE:
## The pdf slides that can be generated for certain chapters are named by
## taking the relative path of the respective source file and replacing
## any '/' with an '_' (e.g. A/B/C -> A_B_C). This must be reversable in
## order to find the prerequisites for each output file. Therefore, any
## subdirectory of the $(SRC_DIR) directory must NOT contain an '_'.
#-------------------------------------------------------------------------
# Tools
#-------------------------------------------------------------------------
## Define tools to process various types of source files. By default, a
## custom Docker image will be used. To create this image, run:
## make create-docker-image
##
## Launching tools via a Docker container: make TARGET
## Launch the tools directly: export DOCKER=false; make TARGET
##
## Note: LaTeX needs to be called in the folder of the .tex file to
## be processed. In the rule that generates images from tex files, the
## variable "$<" is set to the current .tex file (incl. path in the working
## directory). Therefore, the working directory for the Docker container is
## set to the folder of the current .tex file. When called directly, we
## need to first change-dir to this folder.
ifneq ($(DOCKER), false)
DOCKER_REPO_MNTPOINT = /data
DOCKER_IMAGE = alpine-pandoc-hugo
DOCKER_COMMAND = docker run --rm -i
DOCKER_USER = -u "$(shell id -u):$(shell id -g)"
DOCKER_VOLUME = -v "$(shell pwd):$(DOCKER_REPO_MNTPOINT)" -w "$(DOCKER_REPO_MNTPOINT)"
DOCKER_TEX_VOLUME = -v "$(dir $(realpath $<)):$(DOCKER_REPO_MNTPOINT)" -w "$(DOCKER_REPO_MNTPOINT)"
# GIT_DIR ensures that git works with the repository
# no matter the owning user of the directory.
# see https://github.com/Compilerbau/CB-Lecture-Bachelor/pull/16 for the discussion
# around this specific workaround and
# https://github.blog/2022-04-12-git-security-vulnerability-announced/ &
# https://stackoverflow.com/questions/71901632/fatal-error-unsafe-repository-home-repon-is-owned-by-someone-else
# for a general overview of the issue.
DOCKER_GIT_ENV = --env GIT_DIR="$(DOCKER_REPO_MNTPOINT)/.git" \
--env GIT_AUTHOR_NAME="$(shell git config user.name)" \
--env GIT_AUTHOR_EMAIL="$(shell git config user.email)" \
--env GIT_COMMITTER_NAME="$(shell git config user.name)" \
--env GIT_COMMITTER_EMAIL="$(shell git config user.email)"
PANDOC = $(DOCKER_COMMAND) $(DOCKER_VOLUME) $(DOCKER_USER) --entrypoint="pandoc" $(DOCKER_IMAGE)
HUGO = $(DOCKER_COMMAND) $(DOCKER_VOLUME) $(DOCKER_USER) --entrypoint="hugo" $(DOCKER_IMAGE)
DOT = $(DOCKER_COMMAND) $(DOCKER_VOLUME) $(DOCKER_USER) --entrypoint="dot" $(DOCKER_IMAGE)
LATEX = $(DOCKER_COMMAND) $(DOCKER_TEX_VOLUME) $(DOCKER_USER) --entrypoint="latex" $(DOCKER_IMAGE)
DELETE_SCRIPT = $(DOCKER_COMMAND) $(DOCKER_VOLUME) $(DOCKER_USER) --entrypoint="/opt/delete-script.rb" $(DOCKER_GIT_ENV) $(DOCKER_IMAGE)
else
PANDOC = pandoc
HUGO = hugo
DOT = dot
LATEX = cd $(dir $(realpath $<)) && latex
DELETE_SCRIPT = ./.github/actions/alpine-pandoc-hugo/delete-script.rb
endif
## Data-Dir: Path to the Git submodule of Pandoc-Lecture
## Resource-Path: Where to search for bib files and other resources?
##
## Note: If Pandoc is used via a Docker container, DATADIR must be the
## working directory or a subdirectory, as the working directory will
## be mounted into the Docker container! References to a parent directory
## of the working directory therefore will not work when using a Docker
## container!
PANDOC_DIRS = --data-dir=.pandoc --resource-path=".:.pandoc"
## Define options for generating images from ".tex" files
LATEX_ARGS = -shell-escape
## Define options for generating images from ".dot" files
DOT_ARGS = -Tpng
## Define options to be used by Hugo
## local.yaml allows to override settings in config.yaml
HUGO_LOCAL = $(wildcard local.yaml)
HUGO_ARGS = --config config.yaml,$(HUGO_LOCAL)
#-------------------------------------------------------------------------
# I/O Directories
#-------------------------------------------------------------------------
## Top level directory for source files
SRC_DIR = markdown
## Top level directory for temporary files
TEMP_DIR = temp
HUGO_TEMP_DIR = resources
HUGO_LOCK = .hugo_build.lock
## Top level directory for generated image files
IMAGES_OUTPUT_DIR = $(TEMP_DIR)/images
## Top level directory for temporary files used to generate website (input for Hugo)
WEB_INTERMEDIATE_DIR = $(TEMP_DIR)/content
## Top level directory for temporary files used in slides generation
SLIDES_INTERMEDIATE_DIR = $(TEMP_DIR)/slides
## Output directory generated by Hugo
WEB_OUTPUT_DIR = docs
## Output directory for generated slides
SLIDES_OUTPUT_DIR = pdf
## Temporary directory for extracing lecture structure
STRUCTURE_TEMP_DIR = $(TEMP_DIR)/structure
## Output .md file for structure
STRUCTURE_SUMMARY = $(STRUCTURE_TEMP_DIR)/structure.md
## Output directory for lecture structure
STRUCTURE_OUTPUT_DIR = structure
## Temporary pdf output file for structure
STRUCTURE_SUMMARY_TEMP_PDF = $(STRUCTURE_SUMMARY:%.md=%.pdf)
## Final pdf output containing the structure of this lecture series
STRUCTURE_SUMMARY_PDF = $(patsubst $(STRUCTURE_TEMP_DIR)/%.pdf,$(STRUCTURE_OUTPUT_DIR)/%.pdf, $(STRUCTURE_SUMMARY_TEMP_PDF))
#-------------------------------------------------------------------------
# Helper lists
#-------------------------------------------------------------------------
## TeX source and target files
TEX_SOURCES = $(shell find $(SRC_DIR) -type f -iname '*.tex')
TEX_INTERMEDIATE = $(patsubst $(SRC_DIR)/%,$(IMAGES_OUTPUT_DIR)/%, $(TEX_SOURCES))
TEX_TARGETS = $(patsubst $(SRC_DIR)/%.tex,$(IMAGES_OUTPUT_DIR)/%.png, $(TEX_SOURCES))
WEB_TEX_TARGETS = $(patsubst $(SRC_DIR)/%.tex,$(WEB_INTERMEDIATE_DIR)/%.png, $(TEX_SOURCES))
SLIDES_TEX_TARGETS = $(patsubst $(SRC_DIR)/%.tex,$(SLIDES_INTERMEDIATE_DIR)/%.png, $(TEX_SOURCES))
## Dot source and target files
DOT_SOURCES = $(shell find $(SRC_DIR) -type f -iname '*.dot')
DOT_TARGETS = $(patsubst $(SRC_DIR)/%.dot,$(IMAGES_OUTPUT_DIR)/%.png, $(DOT_SOURCES))
WEB_DOT_TARGETS = $(patsubst $(SRC_DIR)/%.dot,$(WEB_INTERMEDIATE_DIR)/%.png, $(DOT_SOURCES))
SLIDES_DOT_TARGETS = $(patsubst $(SRC_DIR)/%.dot,$(SLIDES_INTERMEDIATE_DIR)/%.png, $(DOT_SOURCES))
## Standalone image sources and targets
STANDALONE_SOURCES = $(shell find $(SRC_DIR) -type f -iname '*.png')
STANDALONE_TARGETS = $(patsubst $(SRC_DIR)/%,$(IMAGES_OUTPUT_DIR)/%, $(STANDALONE_SOURCES))
WEB_STANDALONE_TARGETS = $(patsubst $(SRC_DIR)/%,$(WEB_INTERMEDIATE_DIR)/%, $(STANDALONE_SOURCES))
SLIDES_STANDALONE_TARGETS = $(patsubst $(SRC_DIR)/%,$(SLIDES_INTERMEDIATE_DIR)/%, $(STANDALONE_SOURCES))
## Image targets for web and slides
WEB_IMAGE_TARGETS = $(WEB_TEX_TARGETS) $(WEB_DOT_TARGETS) $(WEB_STANDALONE_TARGETS)
SLIDES_IMAGE_TARGETS = $(SLIDES_TEX_TARGETS) $(SLIDES_DOT_TARGETS) $(SLIDES_STANDALONE_TARGETS)
## Markdown source and target files
WEB_MARKDOWN_SOURCES = $(shell find $(SRC_DIR) -type f -iname '*.md')
WEB_MARKDOWN_TARGETS = $(WEB_MARKDOWN_SOURCES:$(SRC_DIR)%=$(WEB_INTERMEDIATE_DIR)%)
## Static files for web
WEB_STATIC_SOURCES = $(shell find $(SRC_DIR) -type f \( -path '*files/*' ! -iname '.gitkeep' \))
WEB_STATIC_TARGETS = $(WEB_STATIC_SOURCES:$(SRC_DIR)%=$(WEB_INTERMEDIATE_DIR)%)
## Source and target files for slides
## NOTES:
## (1) The name for the target pdf file is generated from the relative
## path under $(SRC_DIR) with '/' substituted by '_'.
## (2) Directories containing a .noslides file will not be considerd for slides generation.
## Directories to be excluded
SLIDES_EXCLUDE_DIRS = $(dir $(shell find $(SRC_DIR) -type f -iname '.noslides'))
## Page-bundles
SLIDES_BUNDLE_MARKDOWN_SOURCES = $(filter-out $(addsuffix %, $(SLIDES_EXCLUDE_DIRS)), $(shell find $(SRC_DIR) -type f -iname 'index.md'))
SLIDES_BUNDLE_PDF_TARGETS = $(addprefix $(SLIDES_OUTPUT_DIR)/,$(subst /,_, $(patsubst $(SRC_DIR)/%/index.md,%.pdf, $(SLIDES_BUNDLE_MARKDOWN_SOURCES))))
## Single markdown files
SLIDES_SINGLE_MARKDOWN_SOURCES = $(filter-out $(addsuffix %, $(SLIDES_EXCLUDE_DIRS)), $(shell find $(SRC_DIR) -type f -iname '*.md' ! -iname '*index.md' ! -iname 'tldr.md' ! -iname 'outcomes.md'))
SLIDES_SINGLE_PDF_TARGETS = $(addprefix $(SLIDES_OUTPUT_DIR)/,$(subst /,_, $(patsubst $(SRC_DIR)/%.md,%.pdf, $(SLIDES_SINGLE_MARKDOWN_SOURCES))))
## Convenience targets
SLIDES_MARKDOWN_TARGETS = $(SLIDES_BUNDLE_MARKDOWN_SOURCES:$(SRC_DIR)%=$(SLIDES_INTERMEDIATE_DIR)%) $(SLIDES_SINGLE_MARKDOWN_SOURCES:$(SRC_DIR)%=$(SLIDES_INTERMEDIATE_DIR)%)
SLIDES_SHORT_TARGETS = $(patsubst $(SLIDES_OUTPUT_DIR)/%.pdf,%,$(SLIDES_BUNDLE_PDF_TARGETS)) $(patsubst $(SLIDES_OUTPUT_DIR)/%.pdf,%,$(SLIDES_SINGLE_PDF_TARGETS))
STRUCTURE_TARGETS = $(WEB_MARKDOWN_SOURCES:$(SRC_DIR)%=$(STRUCTURE_TEMP_DIR)%)
## Readings data template
READINGS = data/readings.yaml
BIBTEX = cb.bib
#-------------------------------------------------------------------------
# Secondary Expansion
#-------------------------------------------------------------------------
## Enable secondary expansion for subsequent targets. This allows the use
## of automatic variables like '@' in the prerequisite definitions by
## expanding twice (e.g. $$(VAR)). For normal variable references (e.g.
## $(VAR)) the expansion behaviour is unchanged as the second expansion
## has no effect on an already fully expanded reference.
.SECONDEXPANSION:
#-------------------------------------------------------------------------
# Phony Targets
#-------------------------------------------------------------------------
.DEFAULT_GOAL:=help
##@ Helpers
## Display help
.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
.PHONY: list-slides
list-slides: ## List available targets for individual slides
$(foreach target,$(SLIDES_SHORT_TARGETS), $(info $(target)))
@: ## Suppress 'Nothing to be done for ...' message
##@ Building
## Make everything
.PHONY: all
all: slides web ## Make everything
## Create all slides
.PHONY: slides
slides: $(SLIDES_BUNDLE_PDF_TARGETS) $(SLIDES_SINGLE_PDF_TARGETS) ## Create all slides
## Generate pdf slides (shortened target name for convenience)
.PHONY: $(SLIDES_SHORT_TARGETS)
$(SLIDES_SHORT_TARGETS): $$(patsubst %,$(SLIDES_OUTPUT_DIR)/%.pdf,$$@)
## Create website
.PHONY: web
web: $(WEB_MARKDOWN_TARGETS) $(WEB_IMAGE_TARGETS) $(WEB_STATIC_TARGETS) $(READINGS) $(HUGO_LOCAL) ## Create website
$(HUGO) $(HUGO_ARGS)
## Create website and archive
.PHONY: web_zip
web_zip: web ## Create website and archive
cd $(WEB_OUTPUT_DIR) && rm -rf site.zip && zip -r site.zip *
## Build Docker image "alpine-pandoc-hugo"
.PHONY: docker
docker: ## Build Docker image "alpine-pandoc-hugo"
cd .github/actions/alpine-pandoc-hugo && make clean all
##@ Cleanup
.PHONY: clean-all
clean-all: clean-temp ## Clean up all generated files and directories
rm -rf $(SLIDES_OUTPUT_DIR) $(WEB_OUTPUT_DIR) $(READINGS) $(STRUCTURE_OUTPUT_DIR)
.PHONY: clean-temp
clean-temp: ## Clean up all intermediate files and directories
rm -rf $(TEMP_DIR) $(HUGO_TEMP_DIR) $(HUGO_LOCK)
.PHONY: distclean
distclean: clean-all ## Same as clean-all
.PHONY: clean
clean: clean-temp ## Same as clean-temp
##@ New Elements
## Create new lecture stub based on archetype
## Use all sections and the page name, but leave out "content/" and "index.md".
## Example: "markdown/topic/subtopic/lecture/index.md" becomes "topic/subtopic/lecture"
## 1. "make new_chapter TOPIC=topic"
## 2. "make new_chapter TOPIC=topic/subtopic"
## 3. "make new_lecture-bc TOPIC=topic/subtopic/lecture"
TOPIC ?=
PHONY: new_chapter
new_chapter: ## Create new chapter
$(HUGO) new -c "$(ORIG_CONTENT)/" -k chapter $(TOPIC)
PHONY: new_lecture-bc
new_lecture-bc: ## Create new lecture for BC
$(HUGO) new -c "$(ORIG_CONTENT)/" -k lecture-bc $(TOPIC)
PHONY: new_lecture-cg
new_lecture-cg: ## Create new lecture for Carsten
$(HUGO) new -c "$(ORIG_CONTENT)/" -k lecture-cg $(TOPIC)
PHONY: new_lecture-cy
new_lecture-cy: ## Create new lecture for Canan
$(HUGO) new -c "$(ORIG_CONTENT)/" -k lecture-cy $(TOPIC)
PHONY: new_assignment
new_assignment: ## Create new assignment
$(HUGO) new -c "$(ORIG_CONTENT)/" -k assignment $(TOPIC)
#-------------------------------------------------------------------------
# File Targets
#-------------------------------------------------------------------------
## Canned recipe for creating output folder
define create-folder
@mkdir -p $(dir $@)
endef
## Canned recipe for creating output folder and copy output file
define create-dir-and-copy
$(create-folder)
cp $< $@
endef
## Create readings data template
$(READINGS): $(BIBTEX)
$(PANDOC) -s -f biblatex -t markdown $< -o $@
## Copy tex source files to $(IMAGES_OUTPUT_DIR)
## Note: This is necessary because latex generates output in the directory
## it is called in and we do not want the $(SRC_DIR) littered with
## temporary files.
$(TEX_INTERMEDIATE): $(IMAGES_OUTPUT_DIR)/%: $(SRC_DIR)/%
$(create-dir-and-copy)
## Create images from tex files
$(TEX_TARGETS): %.png: %.tex
$(LATEX) $(LATEX_ARGS) $(notdir $<)
## Create images from dot files
$(DOT_TARGETS): $(IMAGES_OUTPUT_DIR)/%.png: $(SRC_DIR)/%.dot
$(create-folder)
$(DOT) $(DOT_ARGS) $< -o $@
## Copy standalone images to $(IMAGES_OUTPUT_DIR)
$(STANDALONE_TARGETS): $(IMAGES_OUTPUT_DIR)/%: $(SRC_DIR)/%
$(create-dir-and-copy)
## Copy image files to $(WEB_INTERMEDIATE_DIR)
$(WEB_IMAGE_TARGETS): $(WEB_INTERMEDIATE_DIR)/%: $(IMAGES_OUTPUT_DIR)/%
$(create-dir-and-copy)
## Process markdown with pandoc (preprocessing for hugo)
$(WEB_MARKDOWN_TARGETS): $(WEB_INTERMEDIATE_DIR)/%: $(SRC_DIR)/%
$(create-folder)
$(PANDOC) $(PANDOC_DIRS) -d hugo $< -o $@
## Copy static files to $(WEB_INTERMEDIATE_DIR)
$(WEB_STATIC_TARGETS): $(WEB_INTERMEDIATE_DIR)/%: $(SRC_DIR)/%
$(create-dir-and-copy)
## Copy image files to $(SLIDES_INTERMEDIATE_DIR)
$(SLIDES_IMAGE_TARGETS): $(SLIDES_INTERMEDIATE_DIR)/%: $(IMAGES_OUTPUT_DIR)/%
$(create-dir-and-copy)
## Copy markdown files to $(SLIDES_INTERMEDIATE_DIR)
$(SLIDES_MARKDOWN_TARGETS): $(SLIDES_INTERMEDIATE_DIR)/%: $(SRC_DIR)/%
$(create-dir-and-copy)
## Generate pdf slides
## Prerequisites are the lessons 'index.md' and the images in the 'images'
## subfolder.
## NOTE: The prerequisites for the images must be added after the 'index.md'
## so that '$<' contains the right input file for pandoc.
## Page-Bundles: path/name/index.md, path/name/images/, path_name.pdf
$(SLIDES_BUNDLE_PDF_TARGETS): $$(patsubst $(SLIDES_OUTPUT_DIR)/%.pdf,$(SLIDES_INTERMEDIATE_DIR)/%/index.md, $$(subst _,/,$$@))
$(create-folder)
$(PANDOC) $(PANDOC_DIRS) -d slides $< -o $@
$(SLIDES_BUNDLE_PDF_TARGETS): $$(filter $$(patsubst $(SLIDES_OUTPUT_DIR)/%.pdf,$(SLIDES_INTERMEDIATE_DIR)/%, $$(subst _,/,$$@))%, $(SLIDES_IMAGE_TARGETS))
## Single Markdown Files: path/name.md, path/<images>/, path_name.pdf
$(SLIDES_SINGLE_PDF_TARGETS): $$(patsubst $(SLIDES_OUTPUT_DIR)/%.pdf,$(SLIDES_INTERMEDIATE_DIR)/%.md, $$(subst _,/,$$@))
$(create-folder)
$(PANDOC) $(PANDOC_DIRS) -d slides $< -o $@
$(SLIDES_SINGLE_PDF_TARGETS): $$(filter $$(dir $$(patsubst $(SLIDES_OUTPUT_DIR)/%.pdf,$(SLIDES_INTERMEDIATE_DIR)/%, $$(subst _,/,$$@)))%, $(SLIDES_IMAGE_TARGETS))
##@ Structure
.PHONY: delete-rem-tags
delete-rem-tags: ## Run delete-script.rb to remove all <--REM--> blocks
$(DELETE_SCRIPT) $(SRC_DIR)
.PHONY: structure
structure: $(STRUCTURE_SUMMARY_PDF) ## Extract structure of the whole lecture series to a pdf
## Extract the structure (title and headings) from each session
$(STRUCTURE_TARGETS): $(STRUCTURE_TEMP_DIR)/%: $(SRC_DIR)/%
$(create-folder)
$(PANDOC) $(PANDOC_DIRS) $< --lua-filter=extract_filewise.lua -o $@
## Summarize the structure of the whole lecture series in one markdown file
$(STRUCTURE_SUMMARY): $(STRUCTURE_TARGETS)
$(PANDOC) $(PANDOC_DIRS) $(STRUCTURE_TARGETS) --lua-filter=extract_summary.lua -o $@
## Convert summery of whole lecture to pdf
$(STRUCTURE_SUMMARY_TEMP_PDF): $(STRUCTURE_SUMMARY)
$(PANDOC) $(PANDOC_DIRS) $(STRUCTURE_SUMMARY) -o $(STRUCTURE_SUMMARY_TEMP_PDF) --number-sections
## Copy structure from temp directory to 'structure' directory
$(STRUCTURE_SUMMARY_PDF): $(STRUCTURE_SUMMARY_TEMP_PDF) ## extract structure of all lectures to a pdf
$(create-dir-and-copy)