Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
198 lines (167 loc) · 7.66 KB
/
Copy pathMakefile
File metadata and controls
198 lines (167 loc) · 7.66 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
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
# Copyright (C) 2026 Cristian Adam <cristian.adam@gmail.com>
#
# This file is part of python-doc
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/.
# Builds the Python documentation as a Qt Help archive. See README.md.
PYTHON ?= python3
PYTHON_VERSION ?= 3.15
# The branch of CPython the documentation is built from. A released version
# has a maintenance branch of its own; `main` is what the next one is on.
CPYTHON_URL ?= https://github.com/python/cpython.git
CPYTHON_BRANCH ?= $(PYTHON_VERSION)
CPYTHON_DIR ?= cpython-src
VENV_DIR ?= venv
QHELPGENERATOR ?= qhelpgenerator
# What the archive is known by once it is registered. The version is in the
# namespace rather than in the virtual folder so that the URLs stay short,
# and in one of the two so that several versions can be registered at once.
NAMESPACE ?= org.python.$(PYTHON_VERSION)
VIRTUAL_FOLDER ?= python
# Where the pages say they came from, which the footer of each one links.
ONLINE_URL ?= https://docs.python.org/$(PYTHON_VERSION)
prefix ?= /usr/local
datadir ?= $(prefix)/share
docdir ?= $(datadir)/doc/python-doc
DOC_DIR = $(CPYTHON_DIR)/Doc
QTHELP_DIR = $(DOC_DIR)/build/qthelp
OUTPUT_DIR = output
STAGE_DIR = $(OUTPUT_DIR)/python-$(PYTHON_VERSION)-qch
QCH = $(OUTPUT_DIR)/python-$(PYTHON_VERSION).qch
VENV_PYTHON = $(VENV_DIR)/bin/python
# `make` cannot depend on a directory, whose timestamp says only when
# something was last added to it, so each step that fills one leaves a stamp.
SOURCE_STAMP = $(CPYTHON_DIR)/.stamp-$(CPYTHON_BRANCH)
VENV_STAMP = $(VENV_DIR)/.stamp
QTHELP_STAMP = $(QTHELP_DIR)/.stamp
STAGE_STAMP = $(STAGE_DIR)/.stamp
.PHONY: all
all: doc_qch
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " source to clone the CPython documentation sources"
@echo " update to pull new commits into a clone already here"
@echo " venv to create the virtualenv Sphinx is run from"
@echo " doc_qthelp to run Sphinx's Qt Help builder over the sources"
@echo " doc_qch to build $(QCH)"
@echo " install to install the archive under $(docdir)"
@echo " clean to remove everything built here"
@echo " distclean to remove the CPython clone and the virtualenv too"
# -- the sources -----------------------------------------------------------
.PHONY: source
source: $(SOURCE_STAMP)
# Fetching the branch onto a detached head, which is both how a clone that is
# already here is moved onto another version and how `update` refreshes one.
FETCH_BRANCH = git -C "$(CPYTHON_DIR)" fetch --depth 1 origin "$(CPYTHON_BRANCH)" && git -C "$(CPYTHON_DIR)" checkout --detach FETCH_HEAD
# Shallow, because nothing here reads the history, and of one branch, because
# the clone is pinned to the version being built. A clone that is already
# here is moved onto the branch asked for, so that switching versions does
# not call for a fresh one. The stamp names the branch, so this runs again
# on the way back; what it does not do is go out to the network for a version
# already checked out, which keeps a rebuild off the network and builds of
# the same version comparable. See `update` for picking up new commits.
$(SOURCE_STAMP):
@if [ -d "$(CPYTHON_DIR)/.git" ]; then \
echo "Updating $(CPYTHON_DIR) to $(CPYTHON_BRANCH)"; \
$(FETCH_BRANCH); \
else \
echo "Cloning $(CPYTHON_URL) at $(CPYTHON_BRANCH)"; \
git clone --depth 1 --branch "$(CPYTHON_BRANCH)" \
"$(CPYTHON_URL)" "$(CPYTHON_DIR)"; \
fi
rm -f $(CPYTHON_DIR)/.stamp-*
touch "$@"
# Brings the clone up to the tip of its branch, and leaves the stamp newer
# than everything built from it, so that the next `make` rebuilds.
.PHONY: update
update:
@test -d "$(CPYTHON_DIR)/.git" \
|| { echo "No clone in $(CPYTHON_DIR); run \`make source'"; exit 1; }
$(FETCH_BRANCH)
rm -f $(CPYTHON_DIR)/.stamp-*
touch "$(SOURCE_STAMP)"
# -- the virtualenv --------------------------------------------------------
.PHONY: venv
venv: $(VENV_STAMP)
# CPython pins what its documentation builds with, so take the pins from the
# clone rather than keeping a list of our own that would drift from them.
# `pylock.toml` is what CPython's own `Doc/Makefile` installs; the
# `requirements.txt` beside it is the loose input those pins were resolved
# from, and is the fallback for a branch old enough to predate the lock file.
# That the pins come from the clone is also why the clone, and not the file
# in it, is what this waits on: there is nothing to read to decide whether to
# run until the clone is here.
$(VENV_STAMP): $(SOURCE_STAMP)
$(PYTHON) -m venv "$(VENV_DIR)"
$(VENV_PYTHON) -m pip install --upgrade pip
@if [ -f "$(DOC_DIR)/pylock.toml" ]; then \
echo "Installing the pins in $(DOC_DIR)/pylock.toml"; \
$(VENV_PYTHON) -m pip install -r "$(DOC_DIR)/pylock.toml"; \
else \
echo "No lock file; installing $(DOC_DIR)/requirements.txt"; \
$(VENV_PYTHON) -m pip install -r "$(DOC_DIR)/requirements.txt"; \
fi
touch "$@"
# -- the Sphinx build ------------------------------------------------------
.PHONY: doc_qthelp
doc_qthelp: $(QTHELP_STAMP)
# Driven through CPython's own makefile, which assembles the changelog from
# `Misc/NEWS.d` before it runs Sphinx. Its `--fail-on-warning` is dropped:
# it is there to hold contributors to a clean build, and a warning from a
# builder upstream does not use is no reason to produce no archive here.
#
# The directory is emptied first. Sphinx writes a page per document and
# never removes the ones left over from documents that are gone, and this
# directory is not named after the version, so a page dropped between two of
# them -- `whatsnew/3.15.html` once the clone has moved to 3.14 -- would sit
# there to be staged and listed in the archive. Clearing it costs a full
# rebuild, which this rule only runs for a clone or a virtualenv that has
# changed under it anyway.
$(QTHELP_STAMP): $(VENV_STAMP) $(SOURCE_STAMP)
rm -rf "$(QTHELP_DIR)"
$(MAKE) -C "$(DOC_DIR)" build BUILDER=qthelp \
VENVDIR="$(abspath $(VENV_DIR))" SPHINXERRORHANDLING=
touch "$@"
# -- the Qt Help archive ---------------------------------------------------
# The pages, the stylesheets and the help project, ready for qhelpgenerator.
$(STAGE_STAMP): $(QTHELP_STAMP) build_qch.py \
$(wildcard commands/*.py) static-qthelp/qthelp.css.in
$(VENV_PYTHON) build_qch.py \
--src "$(QTHELP_DIR)" \
--dst "$(STAGE_DIR)" \
--namespace "$(NAMESPACE)" \
--virtual-folder "$(VIRTUAL_FOLDER)" \
--online-url "$(ONLINE_URL)" \
--doc-dir "$(DOC_DIR)"
touch "$@"
# qhelpgenerator resolves the file list against its own directory, so the
# help project has to sit among the pages it lists.
$(QCH): $(STAGE_STAMP)
@mkdir -p "$(OUTPUT_DIR)"
"$(QHELPGENERATOR)" "$(STAGE_DIR)/python.qhp" -o "$(abspath $(QCH))"
.PHONY: doc_qch
doc_qch: $(QCH)
# -- installing and cleaning -----------------------------------------------
.PHONY: install
install: doc_qch
install -d "$(DESTDIR)$(docdir)/qch"
install -m 644 "$(QCH)" "$(DESTDIR)$(docdir)/qch/"
.PHONY: clean
clean:
rm -rf "$(OUTPUT_DIR)"
rm -rf "$(DOC_DIR)/build"
.PHONY: distclean
distclean: clean
rm -rf "$(CPYTHON_DIR)" "$(VENV_DIR)"