History

tools/docs: check-variable-fonts.py: split into a lib and an exec file

As we'll be using the actual code inside sphinx-build-wrapper, split the library from the executable, placing the exec at the new place we've been using: tools/docs No functional changes.

Mauro Carvalho Chehab committed 1 year ago

Commit 4515ffd1 parent 75539be5 files · +186 −167Browse files

Unified · Split

5 files
  1. Documentation/Makefile +1 −1
  2. MAINTAINERS +0 −1
  3. scripts/check-variable-fonts.py +0 −165
  4. tools/docs/check-variable-fonts.py +23 −0
  5. tools/docs/lib/latex_fonts.py +162 −0
Documentation/Makefile+1−1
@@ -149,7 +149,7 @@ pdfdocs: DENY_VF = XDG_CONFIG_HOME=$(FONTS_CONF_DENY_VF) · 148 unmodified lines
149pdfdocs: latexdocs149pdfdocs: latexdocs
150 @$(srctree)/scripts/sphinx-pre-install --version-check150 @$(srctree)/scripts/sphinx-pre-install --version-check
151 $(foreach var,$(SPHINXDIRS), \151 $(foreach var,$(SPHINXDIRS), \
152 $(MAKE) PDFLATEX="$(PDFLATEX)" LATEXOPTS="$(LATEXOPTS)" $(DENY_VF) -C $(BUILDDIR)/$(var)/latex || $(PYTHON3) $(srctree)/scripts/check-variable-fonts.py || exit; \152 $(MAKE) PDFLATEX="$(PDFLATEX)" LATEXOPTS="$(LATEXOPTS)" $(DENY_VF) -C $(BUILDDIR)/$(var)/latex || $(PYTHON3) $(srctree)/tools/docs/check-variable-fonts.py || exit; \
153 mkdir -p $(BUILDDIR)/$(var)/pdf; \153 mkdir -p $(BUILDDIR)/$(var)/pdf; \
154 mv $(subst .tex,.pdf,$(wildcard $(BUILDDIR)/$(var)/latex/*.tex)) $(BUILDDIR)/$(var)/pdf/; \154 mv $(subst .tex,.pdf,$(wildcard $(BUILDDIR)/$(var)/latex/*.tex)) $(BUILDDIR)/$(var)/pdf/; \
155 )155 )
MAINTAINERS+0−1
@@ -7301,7 +7301,6 @@ S: Maintained · 7300 unmodified lines
7301P: Documentation/doc-guide/maintainer-profile.rst7301P: Documentation/doc-guide/maintainer-profile.rst
7302T: git git://git.lwn.net/linux.git docs-next7302T: git git://git.lwn.net/linux.git docs-next
7303F: Documentation/7303F: Documentation/
7304F: scripts/check-variable-fonts.py
7305F: scripts/checktransupdate.py7304F: scripts/checktransupdate.py
7306F: scripts/documentation-file-ref-check7305F: scripts/documentation-file-ref-check
7307F: scripts/get_abi.py7306F: scripts/get_abi.py
scripts/check-variable-fonts.py+0−165
@@ -1,165 +0,0 @@
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-only
3# Copyright (C) Akira Yokosawa, 2024
4#
5# Ported to Python by (c) Mauro Carvalho Chehab, 2025
6#
7# For "make pdfdocs", reports of build errors of translations.pdf started
8# arriving early 2024 [1, 2]. It turned out that Fedora and openSUSE
9# tumbleweed have started deploying variable-font [3] format of "Noto CJK"
10# fonts [4, 5]. For PDF, a LaTeX package named xeCJK is used for CJK
11# (Chinese, Japanese, Korean) pages. xeCJK requires XeLaTeX/XeTeX, which
12# does not (and likely never will) understand variable fonts for historical
13# reasons.
14#
15# The build error happens even when both of variable- and non-variable-format
16# fonts are found on the build system. To make matters worse, Fedora enlists
17# variable "Noto CJK" fonts in the requirements of langpacks-ja, -ko, -zh_CN,
18# -zh_TW, etc. Hence developers who have interest in CJK pages are more
19# likely to encounter the build errors.
20#
21# This script is invoked from the error path of "make pdfdocs" and emits
22# suggestions if variable-font files of "Noto CJK" fonts are in the list of
23# fonts accessible from XeTeX.
24#
25# References:
26# [1]: https://lore.kernel.org/r/8734tqsrt7.fsf@meer.lwn.net/
27# [2]: https://lore.kernel.org/r/1708585803.600323099@f111.i.mail.ru/
28# [3]: https://en.wikipedia.org/wiki/Variable_font
29# [4]: https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts
30# [5]: https://build.opensuse.org/request/show/1157217
31#
32#===========================================================================
33# Workarounds for building translations.pdf
34#===========================================================================
35#
36# * Denylist "variable font" Noto CJK fonts.
37# - Create $HOME/deny-vf/fontconfig/fonts.conf from template below, with
38# tweaks if necessary. Remove leading "# ".
39# - Path of fontconfig/fonts.conf can be overridden by setting an env
40# variable FONTS_CONF_DENY_VF.
41#
42# * Template:
43# -----------------------------------------------------------------
44# <?xml version="1.0"?>
45# <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
46# <fontconfig>
47# <!--
48# Ignore variable-font glob (not to break xetex)
49# -->
50# <selectfont>
51# <rejectfont>
52# <!--
53# for Fedora
54# -->
55# <glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob>
56# <!--
57# for openSUSE tumbleweed
58# -->
59# <glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob>
60# </rejectfont>
61# </selectfont>
62# </fontconfig>
63# -----------------------------------------------------------------
64#
65# The denylisting is activated for "make pdfdocs".
66#
67# * For skipping CJK pages in PDF
68# - Uninstall texlive-xecjk.
69# Denylisting is not needed in this case.
70#
71# * For printing CJK pages in PDF
72# - Need non-variable "Noto CJK" fonts.
73# * Fedora
74# - google-noto-sans-cjk-fonts
75# - google-noto-serif-cjk-fonts
76# * openSUSE tumbleweed
77# - Non-variable "Noto CJK" fonts are not available as distro packages
78# as of April, 2024. Fetch a set of font files from upstream Noto
79# CJK Font released at:
80# https://github.com/notofonts/noto-cjk/tree/main/Sans#super-otc
81# and at:
82# https://github.com/notofonts/noto-cjk/tree/main/Serif#super-otc
83# , then uncompress and deploy them.
84# - Remember to update fontconfig cache by running fc-cache.
85#
86# !!! Caution !!!
87# Uninstalling "variable font" packages can be dangerous.
88# They might be depended upon by other packages important for your work.
89# Denylisting should be less invasive, as it is effective only while
90# XeLaTeX runs in "make pdfdocs".
91
92import os
93import re
94import subprocess
95import sys
96import textwrap
97
98class LatexFontChecker:
99 """
100 Detect problems with CJK variable fonts that affect PDF builds for
101 translations.
102 """
103
104 def __init__(self):
105 deny_vf = os.environ.get('FONTS_CONF_DENY_VF', "~/deny-vf")
106
107 self.environ = os.environ.copy()
108 self.environ['XDG_CONFIG_HOME'] = os.path.expanduser(deny_vf)
109
110 self.re_cjk = re.compile(r"([^:]+):\s*Noto\s+(Sans|Sans Mono|Serif) CJK")
111
112 def get_noto_cjk_vf_fonts(self):
113 """Get Noto CJK fonts"""
114
115 cjk_fonts = set()
116 cmd = ["fc-list", ":", "file", "family", "variable"]
117 try:
118 result = subprocess.run(cmd,stdout=subprocess.PIPE,
119 stderr=subprocess.PIPE,
120 universal_newlines=True,
121 env=self.environ,
122 check=True)
123
124 except subprocess.CalledProcessError as exc:
125 sys.exit(f"Error running fc-list: {repr(exc)}")
126
127 for line in result.stdout.splitlines():
128 if 'variable=True' not in line:
129 continue
130
131 match = self.re_cjk.search(line)
132 if match:
133 cjk_fonts.add(match.group(1))
134
135 return sorted(cjk_fonts)
136
137 def check(self):
138 """Check for problems with CJK fonts"""
139
140 fonts = textwrap.indent("\n".join(self.get_noto_cjk_vf_fonts()), " ")
141 if not fonts:
142 return None
143
144 rel_file = os.path.relpath(__file__, os.getcwd())
145
146 msg = "=" * 77 + "\n"
147 msg += 'XeTeX is confused by "variable font" files listed below:\n'
148 msg += fonts + "\n"
149 msg += textwrap.dedent(f"""
150 For CJK pages in PDF, they need to be hidden from XeTeX by denylisting.
151 Or, CJK pages can be skipped by uninstalling texlive-xecjk.
152
153 For more info on denylisting, other options, and variable font, see header
154 comments of {rel_file}.
155 """)
156 msg += "=" * 77
157
158 return msg
159
160if __name__ == "__main__":
161 msg = LatexFontChecker().check()
162 if msg:
163 print(msg)
164
165 sys.exit(1)
tools/docs/check-variable-fonts.py+23−0
@@ -0,0 +1,23 @@
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-only
3# Copyright (C) Akira Yokosawa, 2024
4#
5# Ported to Python by (c) Mauro Carvalho Chehab, 2025
6#
7# pylint: disable=C0103
8
9"""
10Detect problematic Noto CJK variable fonts.
11
12or more details, see lib/latex_fonts.py.
13"""
14
15import sys
16
17from lib.latex_fonts import LatexFontChecker
18
19msg = LatexFontChecker().check()
20if msg:
21 print(msg)
22
23sys.exit(1)
tools/docs/lib/latex_fonts.py+162−0
@@ -0,0 +1,162 @@
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-only
3# Copyright (C) Akira Yokosawa, 2024
4#
5# Ported to Python by (c) Mauro Carvalho Chehab, 2025
6
7"""
8Detect problematic Noto CJK variable fonts.
9
10For "make pdfdocs", reports of build errors of translations.pdf started
11arriving early 2024 [1, 2]. It turned out that Fedora and openSUSE
12tumbleweed have started deploying variable-font [3] format of "Noto CJK"
13fonts [4, 5]. For PDF, a LaTeX package named xeCJK is used for CJK
14(Chinese, Japanese, Korean) pages. xeCJK requires XeLaTeX/XeTeX, which
15does not (and likely never will) understand variable fonts for historical
16reasons.
17
18The build error happens even when both of variable- and non-variable-format
19fonts are found on the build system. To make matters worse, Fedora enlists
20variable "Noto CJK" fonts in the requirements of langpacks-ja, -ko, -zh_CN,
21-zh_TW, etc. Hence developers who have interest in CJK pages are more
22likely to encounter the build errors.
23
24This script is invoked from the error path of "make pdfdocs" and emits
25suggestions if variable-font files of "Noto CJK" fonts are in the list of
26fonts accessible from XeTeX.
27
28References:
29[1]: https://lore.kernel.org/r/8734tqsrt7.fsf@meer.lwn.net/
30[2]: https://lore.kernel.org/r/1708585803.600323099@f111.i.mail.ru/
31[3]: https://en.wikipedia.org/wiki/Variable_font
32[4]: https://fedoraproject.org/wiki/Changes/Noto_CJK_Variable_Fonts
33[5]: https://build.opensuse.org/request/show/1157217
34
35#===========================================================================
36Workarounds for building translations.pdf
37#===========================================================================
38
39* Denylist "variable font" Noto CJK fonts.
40 - Create $HOME/deny-vf/fontconfig/fonts.conf from template below, with
41 tweaks if necessary. Remove leading "".
42 - Path of fontconfig/fonts.conf can be overridden by setting an env
43 variable FONTS_CONF_DENY_VF.
44
45 * Template:
46-----------------------------------------------------------------
47<?xml version="1.0"?>
48<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
49<fontconfig>
50<!--
51 Ignore variable-font glob (not to break xetex)
52-->
53 <selectfont>
54 <rejectfont>
55 <!--
56 for Fedora
57 -->
58 <glob>/usr/share/fonts/google-noto-*-cjk-vf-fonts</glob>
59 <!--
60 for openSUSE tumbleweed
61 -->
62 <glob>/usr/share/fonts/truetype/Noto*CJK*-VF.otf</glob>
63 </rejectfont>
64 </selectfont>
65</fontconfig>
66-----------------------------------------------------------------
67
68 The denylisting is activated for "make pdfdocs".
69
70* For skipping CJK pages in PDF
71 - Uninstall texlive-xecjk.
72 Denylisting is not needed in this case.
73
74* For printing CJK pages in PDF
75 - Need non-variable "Noto CJK" fonts.
76 * Fedora
77 - google-noto-sans-cjk-fonts
78 - google-noto-serif-cjk-fonts
79 * openSUSE tumbleweed
80 - Non-variable "Noto CJK" fonts are not available as distro packages
81 as of April, 2024. Fetch a set of font files from upstream Noto
82 CJK Font released at:
83 https://github.com/notofonts/noto-cjk/tree/main/Sans#super-otc
84 and at:
85 https://github.com/notofonts/noto-cjk/tree/main/Serif#super-otc
86 , then uncompress and deploy them.
87 - Remember to update fontconfig cache by running fc-cache.
88
89!!! Caution !!!
90 Uninstalling "variable font" packages can be dangerous.
91 They might be depended upon by other packages important for your work.
92 Denylisting should be less invasive, as it is effective only while
93 XeLaTeX runs in "make pdfdocs".
94"""
95
96import os
97import re
98import subprocess
99import textwrap
100import sys
101
102class LatexFontChecker:
103 """
104 Detect problems with CJK variable fonts that affect PDF builds for
105 translations.
106 """
107
108 def __init__(self):
109 deny_vf = os.environ.get('FONTS_CONF_DENY_VF', "~/deny-vf")
110
111 self.environ = os.environ.copy()
112 self.environ['XDG_CONFIG_HOME'] = os.path.expanduser(deny_vf)
113
114 self.re_cjk = re.compile(r"([^:]+):\s*Noto\s+(Sans|Sans Mono|Serif) CJK")
115
116 def get_noto_cjk_vf_fonts(self):
117 """Get Noto CJK fonts"""
118
119 cjk_fonts = set()
120 cmd = ["fc-list", ":", "file", "family", "variable"]
121 try:
122 result = subprocess.run(cmd,stdout=subprocess.PIPE,
123 stderr=subprocess.PIPE,
124 universal_newlines=True,
125 env=self.environ,
126 check=True)
127
128 except subprocess.CalledProcessError as exc:
129 sys.exit(f"Error running fc-list: {repr(exc)}")
130
131 for line in result.stdout.splitlines():
132 if 'variable=True' not in line:
133 continue
134
135 match = self.re_cjk.search(line)
136 if match:
137 cjk_fonts.add(match.group(1))
138
139 return sorted(cjk_fonts)
140
141 def check(self):
142 """Check for problems with CJK fonts"""
143
144 fonts = textwrap.indent("\n".join(self.get_noto_cjk_vf_fonts()), " ")
145 if not fonts:
146 return None
147
148 rel_file = os.path.relpath(__file__, os.getcwd())
149
150 msg = "=" * 77 + "\n"
151 msg += 'XeTeX is confused by "variable font" files listed below:\n'
152 msg += fonts + "\n"
153 msg += textwrap.dedent(f"""
154 For CJK pages in PDF, they need to be hidden from XeTeX by denylisting.
155 Or, CJK pages can be skipped by uninstalling texlive-xecjk.
156
157 For more info on denylisting, other options, and variable font, see header
158 comments of {rel_file}.
159 """)
160 msg += "=" * 77
161
162 return msg