Repository navigation
Expand file tree
/
Copy pathmakefile
More file actions
145 lines (124 loc) · 5.27 KB
/
Copy pathmakefile
File metadata and controls
145 lines (124 loc) · 5.27 KB
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
# Makefile
# --------
#
# Build targets:
# make full → cv-full.pdf (complete academic CV)
# make full-public → cv-full-public.pdf (full minus mentorship section)
# make industry → cv-industry.pdf (selected pubs, lean)
# make speaking → cv-speaking.pdf (talks + selected pubs)
# make resume → resume.pdf (one-page industry resume; uses resume.tex)
# make all → builds all five outputs
# make pdf → compile current cv-preset.tex → cv.pdf (internal)
# make clean → remove LaTeX build artifacts
#
# cv-preset.tex is auto-generated by the preset targets.
# If it doesn't exist (fresh clone), it defaults to config/full.tex.
#
# resume.pdf has its own pipeline — it builds from resume.tex + awesome-cv-resume.cls
# and does NOT go through cv-preset.tex or biber. Keep both files in sync with the
# rest of the CV when content changes (see resume.tex header for guidance).
.PHONY: all full full-public industry speaking resume pdf clean fetch fetch-dry dedup test validate check-breaks audit-authors setup check-deps status
# Build all outputs
all: full full-public industry speaking resume
# Individual preset targets
full:
cp config/full.tex cv-preset.tex
$(MAKE) pdf
mv cv.pdf cv-full.pdf
@echo "→ cv-full.pdf"
full-public:
cp config/full-public.tex cv-preset.tex
$(MAKE) pdf
mv cv.pdf cv-full-public.pdf
cp cv-full-public.pdf shabnam-hakimi-cv.pdf
@echo "→ cv-full-public.pdf (also published as shabnam-hakimi-cv.pdf)"
industry:
cp config/industry.tex cv-preset.tex
$(MAKE) pdf
mv cv.pdf cv-industry.pdf
@echo "→ cv-industry.pdf"
speaking:
cp config/speaking.tex cv-preset.tex
$(MAKE) pdf
mv cv.pdf cv-speaking.pdf
@echo "→ cv-speaking.pdf"
# One-page industry resume — standalone pipeline (no biber, no cv-preset.tex).
# Two xelatex passes are sufficient since resume.tex has no bibliography.
resume:
xelatex -interaction=nonstopmode resume.tex
xelatex -interaction=nonstopmode resume.tex
@echo "→ resume.pdf"
# Core LaTeX compile (used internally by preset targets)
# cv-preset.tex must exist before calling this directly.
cv-preset.tex:
@echo "No cv-preset.tex found — using default (full)."
cp config/full.tex cv-preset.tex
pdf: cv-preset.tex
xelatex cv.tex
biber cv
xelatex cv.tex
xelatex cv.tex
clean:
rm -f cv.aux cv.bbl cv.bcf cv.blg cv.log cv.out cv.run.xml cv.toc cvbibcounts.tex
rm -f resume.aux resume.log resume.out
rm -f cv-full.pdf cv-full-public.pdf cv-industry.pdf cv-speaking.pdf cv.pdf shabnam-hakimi-cv.pdf resume.pdf
fetch:
python scripts/update_refs.py
fetch-dry:
python scripts/update_refs.py --dry-run
dedup:
python scripts/update_refs.py --dedup-only
test:
python3 -m pytest tests/ -v
validate:
python3 scripts/validate_bib.py
# Verify the built PDFs obey the page-break style rules (cv.tex:
# keepCitationsWhole) -- no bibliography entry split across a page, no
# heading stranded at the foot of one. Checks rendered output because a
# lapsed TeX rule produces no error, only a worse-looking PDF.
# Run after `make all`; needs the PDFs to exist.
check-breaks:
python3 scripts/check_pagebreaks.py
# Checks author lists against Crossref (publisher DOIs) and DataCite
# (arXiv DOIs). Hits the network, so it is not part of `validate`.
# Worth running after any fetch, and after hand-editing an author list.
audit-authors:
python3 scripts/audit_authors.py
# First-run setup. Installs `requests` + `bibtexparser` (required for
# fetchers and dedup) and `pytest` (required for `make test`).
setup:
python3 -m pip install -r requirements-dev.txt
# Working-tree and upstream state for this repo and the research corpus.
#
# Every git call goes through `git -C <dir>` rather than `cd <dir> && git`.
# A cd-chain reports whatever directory the shell happens to be sitting in,
# so one missing cd makes it print another repo's state under this repo's
# heading -- wrong, and indistinguishable from right.
#
# cv-preset.tex is rewritten by every preset target, so it shows as modified
# after any build. That is expected and is called out below rather than
# filtered, so the count always matches what git actually reports.
CORPUS_DIR ?= $(HOME)/projects/research-corpus
status:
@for d in "$(CURDIR)" "$(CORPUS_DIR)"; do \
name=$$(basename "$$d"); \
if [ ! -e "$$d/.git" ]; then \
printf '%-18s not a git repo (%s)\n' "$$name" "$$d"; continue; \
fi; \
branch=$$(git -C "$$d" rev-parse --abbrev-ref HEAD 2>/dev/null); \
head=$$(git -C "$$d" log -1 --format=%h 2>/dev/null); \
dirty=$$(git -C "$$d" status --porcelain | wc -l | tr -d ' '); \
ahead=$$(git -C "$$d" rev-list --count '@{u}..HEAD' 2>/dev/null || echo '-'); \
behind=$$(git -C "$$d" rev-list --count 'HEAD..@{u}' 2>/dev/null || echo '-'); \
printf '%-18s %-6s %-9s dirty:%-4s ahead:%-4s behind:%s\n' \
"$$name" "$$branch" "$$head" "$$dirty" "$$ahead" "$$behind"; \
git -C "$$d" status --porcelain | sed 's/^/ /'; \
done
@echo
@echo "(cv-preset.tex modified after a build is expected, not dirt.)"
# Preflight: verify required Python deps are importable. Prints an
# actionable hint instead of a bare ImportError traceback.
check-deps:
@python3 -c "import requests, bibtexparser" 2>/dev/null && \
echo "Python deps OK." || \
(echo "Missing Python deps. Run: make setup" && exit 1)