• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#
2# Makefile for Python documentation
3# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4#
5
6# You can set these variables from the command line.
7PYTHON       = python3
8VENVDIR      = ./venv
9UV           = uv
10SPHINXBUILD  = PATH=$(VENVDIR)/bin:$$PATH sphinx-build
11BLURB        = PATH=$(VENVDIR)/bin:$$PATH blurb
12JOBS         = auto
13PAPER        =
14SOURCES      =
15DISTVERSION  = $(shell $(PYTHON) tools/extensions/patchlevel.py)
16REQUIREMENTS = requirements.txt
17SPHINXERRORHANDLING = -W
18
19# Internal variables.
20PAPEROPT_a4     = -D latex_elements.papersize=a4paper
21PAPEROPT_letter = -D latex_elements.papersize=letterpaper
22
23ALLSPHINXOPTS = -b $(BUILDER) \
24                -d build/doctrees \
25                -j $(JOBS) \
26                $(PAPEROPT_$(PAPER)) \
27                $(SPHINXOPTS) $(SPHINXERRORHANDLING) \
28                . build/$(BUILDER) $(SOURCES)
29
30.PHONY: help
31help:
32	@echo "Please use \`make <target>' where <target> is one of"
33	@echo "  clean      to remove build files"
34	@echo "  venv       to create a venv with necessary tools"
35	@echo "  html       to make standalone HTML files"
36	@echo "  gettext    to generate POT files"
37	@echo "  htmlview   to open the index page built by the html target in your browser"
38	@echo "  htmllive   to rebuild and reload HTML files in your browser"
39	@echo "  htmlhelp   to make HTML files and a HTML help project"
40	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
41	@echo "  text       to make plain text files"
42	@echo "  texinfo    to make Texinfo file"
43	@echo "  epub       to make EPUB files"
44	@echo "  changes    to make an overview over all changed/added/deprecated items"
45	@echo "  linkcheck  to check all external links for integrity"
46	@echo "  coverage   to check documentation coverage for library and C API"
47	@echo "  doctest    to run doctests in the documentation"
48	@echo "  pydoc-topics  to regenerate the pydoc topics file"
49	@echo "  dist       to create a \"dist\" directory with archived docs for download"
50	@echo "  check      to run a check for frequent markup errors"
51
52.PHONY: build
53build:
54	-mkdir -p build
55# Look first for a Misc/NEWS file (building from a source release tarball
56# or old repo) and use that, otherwise look for a Misc/NEWS.d directory
57# (building from a newer repo) and use blurb to generate the NEWS file.
58	@if [ -f  ../Misc/NEWS ] ; then \
59		echo "Using existing Misc/NEWS file"; \
60		cp ../Misc/NEWS build/NEWS; \
61	elif $(BLURB) help >/dev/null 2>&1 && $(SPHINXBUILD) --version >/dev/null 2>&1; then \
62		if [ -d ../Misc/NEWS.d ]; then \
63			echo "Building NEWS from Misc/NEWS.d with blurb"; \
64			$(BLURB) merge -f build/NEWS; \
65		else \
66			echo "Neither Misc/NEWS.d nor Misc/NEWS found; cannot build docs"; \
67			exit 1; \
68		fi \
69	else \
70		echo ""; \
71		echo "Missing the required blurb or sphinx-build tools."; \
72		echo "Please run 'make venv' to install local copies."; \
73		echo ""; \
74		exit 1; \
75	fi
76	$(SPHINXBUILD) $(ALLSPHINXOPTS)
77	@echo
78
79.PHONY: html
80html: BUILDER = html
81html: build
82	@echo "Build finished. The HTML pages are in build/html."
83
84.PHONY: htmlhelp
85htmlhelp: BUILDER = htmlhelp
86htmlhelp: build
87	@echo "Build finished; now you can run HTML Help Workshop with the" \
88	      "build/htmlhelp/pydoc.hhp project file."
89
90.PHONY: latex
91latex: BUILDER = latex
92latex: build
93	@echo "Build finished; the LaTeX files are in build/latex."
94	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
95	      "run these through (pdf)latex."
96
97.PHONY: text
98text: BUILDER = text
99text: build
100	@echo "Build finished; the text files are in build/text."
101
102.PHONY: texinfo
103texinfo: BUILDER = texinfo
104texinfo: build
105	@echo "Build finished; the python.texi file is in build/texinfo."
106	@echo "Run \`make info' in that directory to run it through makeinfo."
107
108.PHONY: epub
109epub: BUILDER = epub
110epub: build
111	@echo "Build finished; the epub files are in build/epub."
112
113.PHONY: changes
114changes: BUILDER = changes
115changes: build
116	@echo "The overview file is in build/changes."
117
118.PHONY: linkcheck
119linkcheck: BUILDER = linkcheck
120linkcheck:
121	@$(MAKE) build BUILDER=$(BUILDER) || { \
122	echo "Link check complete; look for any errors in the above output" \
123	     "or in build/$(BUILDER)/output.txt"; \
124	false; }
125
126.PHONY: coverage
127coverage: BUILDER = coverage
128coverage: build
129	@echo "Coverage finished; see c.txt and python.txt in build/coverage"
130
131.PHONY: doctest
132doctest: BUILDER = doctest
133doctest:
134	@$(MAKE) build BUILDER=$(BUILDER) || { \
135	echo "Testing of doctests in the sources finished, look at the" \
136	     "results in build/doctest/output.txt"; \
137	false; }
138
139.PHONY: pydoc-topics
140pydoc-topics: BUILDER = pydoc-topics
141pydoc-topics: build
142	@echo "Building finished; now run this:" \
143	      "cp build/pydoc-topics/topics.py ../Lib/pydoc_data/topics.py"
144
145.PHONY: gettext
146gettext: BUILDER = gettext
147gettext: override SPHINXOPTS := -d build/doctrees-gettext $(SPHINXOPTS)
148gettext: build
149
150.PHONY: htmlview
151htmlview: html
152	$(PYTHON) -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('build/html/index.html'))"
153
154.PHONY: htmllive
155htmllive: SPHINXBUILD = PATH=$(VENVDIR)/bin:$$PATH sphinx-autobuild
156htmllive: SPHINXOPTS = --re-ignore="/venv/" --open-browser --delay 0
157htmllive: _ensure-sphinx-autobuild html
158
159.PHONY: clean
160clean: clean-venv
161	-rm -rf build/*
162
163.PHONY: clean-venv
164clean-venv:
165	rm -rf $(VENVDIR)
166
167.PHONY: venv
168venv:
169	@if [ -d $(VENVDIR) ] ; then \
170		echo "venv already exists."; \
171		echo "To recreate it, remove it first with \`make clean-venv'."; \
172	else \
173		echo "Creating venv in $(VENVDIR)"; \
174		if $(UV) --version >/dev/null 2>&1; then \
175			$(UV) venv $(VENVDIR); \
176			VIRTUAL_ENV=$(VENVDIR) $(UV) pip install -r $(REQUIREMENTS); \
177		else \
178			$(PYTHON) -m venv $(VENVDIR); \
179			$(VENVDIR)/bin/python3 -m pip install --upgrade pip; \
180			$(VENVDIR)/bin/python3 -m pip install -r $(REQUIREMENTS); \
181		fi; \
182		echo "The venv has been created in the $(VENVDIR) directory"; \
183	fi
184
185.PHONY: dist-no-html
186dist-no-html: dist-text dist-pdf dist-epub dist-texinfo
187
188.PHONY: dist
189dist:
190	rm -rf dist
191	mkdir -p dist
192	$(MAKE) dist-html
193	$(MAKE) dist-text
194	$(MAKE) dist-pdf
195	$(MAKE) dist-epub
196	$(MAKE) dist-texinfo
197
198.PHONY: dist-html
199dist-html:
200	# archive the HTML
201	@echo "Building HTML..."
202	mkdir -p dist
203	rm -rf build/html
204	find dist -name 'python-$(DISTVERSION)-docs-html*' -exec rm -rf {} \;
205	$(MAKE) html
206	cp -pPR build/html dist/python-$(DISTVERSION)-docs-html
207	tar -C dist -cf dist/python-$(DISTVERSION)-docs-html.tar python-$(DISTVERSION)-docs-html
208	bzip2 -9 -k dist/python-$(DISTVERSION)-docs-html.tar
209	(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-html.zip python-$(DISTVERSION)-docs-html)
210	rm -r dist/python-$(DISTVERSION)-docs-html
211	rm dist/python-$(DISTVERSION)-docs-html.tar
212	@echo "Build finished and archived!"
213
214.PHONY: dist-text
215dist-text:
216	# archive the text build
217	@echo "Building text..."
218	mkdir -p dist
219	rm -rf build/text
220	find dist -name 'python-$(DISTVERSION)-docs-text*' -exec rm -rf {} \;
221	$(MAKE) text
222	cp -pPR build/text dist/python-$(DISTVERSION)-docs-text
223	tar -C dist -cf dist/python-$(DISTVERSION)-docs-text.tar python-$(DISTVERSION)-docs-text
224	bzip2 -9 -k dist/python-$(DISTVERSION)-docs-text.tar
225	(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-text.zip python-$(DISTVERSION)-docs-text)
226	rm -r dist/python-$(DISTVERSION)-docs-text
227	rm dist/python-$(DISTVERSION)-docs-text.tar
228	@echo "Build finished and archived!"
229
230.PHONY: dist-pdf
231dist-pdf:
232	# archive the A4 latex
233	@echo "Building LaTeX (A4 paper)..."
234	mkdir -p dist
235	rm -rf build/latex
236	find dist -name 'python-$(DISTVERSION)-docs-pdf*' -exec rm -rf {} \;
237	$(MAKE) latex PAPER=a4
238	# remove zip & bz2 dependency on all-pdf,
239	# as otherwise the full latexmk process is run twice.
240	# ($$ is needed to escape the $; https://www.gnu.org/software/make/manual/make.html#Basics-of-Variable-References)
241	-sed -i 's/: all-$$(FMT)/:/' build/latex/Makefile
242	(cd build/latex; $(MAKE) clean && $(MAKE) --jobs=$$((`nproc`+1)) --output-sync LATEXMKOPTS='-quiet' all-pdf && $(MAKE) FMT=pdf zip bz2)
243	cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-a4.zip
244	cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-a4.tar.bz2
245	@echo "Build finished and archived!"
246
247.PHONY: dist-epub
248dist-epub:
249	# copy the epub build
250	@echo "Building EPUB..."
251	mkdir -p dist
252	rm -rf build/epub
253	rm -f dist/python-$(DISTVERSION)-docs.epub
254	$(MAKE) epub
255	cp -pPR build/epub/Python.epub dist/python-$(DISTVERSION)-docs.epub
256	@echo "Build finished and archived!"
257
258.PHONY: dist-texinfo
259dist-texinfo:
260	# archive the texinfo build
261	@echo "Building Texinfo..."
262	mkdir -p dist
263	rm -rf build/texinfo
264	find dist -name 'python-$(DISTVERSION)-docs-texinfo*' -exec rm -rf {} \;
265	$(MAKE) texinfo
266	$(MAKE) info --directory=build/texinfo
267	cp -pPR build/texinfo dist/python-$(DISTVERSION)-docs-texinfo
268	tar -C dist -cf dist/python-$(DISTVERSION)-docs-texinfo.tar python-$(DISTVERSION)-docs-texinfo
269	bzip2 -9 -k dist/python-$(DISTVERSION)-docs-texinfo.tar
270	(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-texinfo.zip python-$(DISTVERSION)-docs-texinfo)
271	rm -r dist/python-$(DISTVERSION)-docs-texinfo
272	rm dist/python-$(DISTVERSION)-docs-texinfo.tar
273	@echo "Build finished and archived!"
274
275.PHONY: _ensure-package
276_ensure-package: venv
277	if $(UV) --version >/dev/null 2>&1; then \
278		VIRTUAL_ENV=$(VENVDIR) $(UV) pip install $(PACKAGE); \
279	else \
280		$(VENVDIR)/bin/python3 -m pip install $(PACKAGE); \
281	fi
282
283.PHONY: _ensure-pre-commit
284_ensure-pre-commit:
285	$(MAKE) _ensure-package PACKAGE=pre-commit
286
287.PHONY: _ensure-sphinx-autobuild
288_ensure-sphinx-autobuild:
289	$(MAKE) _ensure-package PACKAGE=sphinx-autobuild
290
291.PHONY: check
292check: _ensure-pre-commit
293	$(VENVDIR)/bin/python3 -m pre_commit run --all-files
294
295.PHONY: serve
296serve:
297	@echo "The serve target was removed, use htmllive instead (see gh-80510)"
298
299# Targets for daily automated doc build
300# By default, Sphinx only rebuilds pages where the page content has changed.
301# This means it doesn't always pick up changes to preferred link targets, etc
302# To ensure such changes are picked up, we build the published docs with
303# `-E` (to ignore the cached environment) and `-a` (to ignore already existing
304# output files)
305
306# for development releases: always build
307.PHONY: autobuild-dev
308autobuild-dev: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short)
309autobuild-dev:
310	$(MAKE) dist-no-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION)
311
312# for HTML-only rebuilds
313.PHONY: autobuild-dev-html
314autobuild-dev-html: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short)
315autobuild-dev-html:
316	$(MAKE) dist-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION)
317
318# for stable releases: only build if not in pre-release stage (alpha, beta)
319# release candidate downloads are okay, since the stable tree can be in that stage
320.PHONY: autobuild-stable
321autobuild-stable:
322	@case $(DISTVERSION) in *[ab]*) \
323		echo "Not building; $(DISTVERSION) is not a release version."; \
324		exit 1;; \
325	esac
326	@$(MAKE) autobuild-dev
327
328.PHONY: autobuild-stable-html
329autobuild-stable-html:
330	@case $(DISTVERSION) in *[ab]*) \
331		echo "Not building; $(DISTVERSION) is not a release version."; \
332		exit 1;; \
333	esac
334	@$(MAKE) autobuild-dev-html
335