Don't create Python bytecode when building the kernel
Subsystems (5)
v4 cover Don't create Python bytecode when building the kernel
As reported by Andy, the Kernel build system runs kernel-doc script for DRM, when W=1. Due to Python's normal behavior, its JIT compiler will create a bytecode and store it under scripts/lib/*/__pycache__. As one may be using O= and even having the sources on a read-only mount point, disable its creation during build time.
This is done by adding PYTHONDONTWRITEBYTECODE=1 on every place where the script is called within Kbuild and when called via another script.
This only solves half of the issue though, as one may be manually running the script by hand, without asking Python to not store any bytecode. This should be OK, but afterwards, git status will list the __pycache__ as not committed. To prevent that, add *.pyc to .gitignore.
This series contain 4 patches:
- patch 1 adjusts a variable that pass extra data to scripts/kerneldoc.py;
- patch 2moves scripts/kernel-doc location to the main makefile and exports it, as scripts/Makefile.build will need it;
- patch 3 disables __pycache__ generation and ensure that the entire Kbuild will use KERNELDOC var for the location of kernel-doc;
- patch 4 adds *.pyc at the list of object files to be ignored.
---
v4:
- placed *.pyc at the alphabetical order at the final patch
v3:
- move KERNELDOC to the main Makefile;
- get rid of the badly-named KERNELDOC_CONF var.
v2:
- added a .gitignore file;
- add PYTHONDONTWRITEBYTECODE=1 to the places where kernel-doc is called.
Mauro Carvalho Chehab (4):
docs: Makefile: get rid of KERNELDOC_CONF env variable
Makefile: move KERNELDOC macro to the main Makefile scripts/kernel-doc.py: don't create *.pyc files .gitignore: ignore Python compiled bytecode
.gitignore | 1 + Documentation/Makefile | 5 ++--- Makefile | 5 +++++ drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/i915/Makefile | 2 +- include/drm/Makefile | 2 +- scripts/Makefile.build | 2 +- scripts/find-unused-docs.sh | 2 +- 8 files changed, 13 insertions(+), 8 deletions(-)
Signature · 1 line
2.49.0
PATCH v4 1/4 docs: Makefile: get rid of KERNELDOC_CONF env variable
Despite its name, what's there is a set of Sphinx arguments that are passed to sphinx/kerneldoc.py:
- kerneldoc_srctree: location of the source tree;
- kerneldoc_bin: external script to excecute kernel-doc
Drop it, and just place the values at the already-existing ALLSPHINXOPTS variable.
--- Documentation/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/Makefile +2 -2
@@ -61,8 +61,8 @@ endif #HAVE_LATEXMK PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter KERNELDOC = $(srctree)/scripts/kernel-doc.py -KERNELDOC_CONF = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC) -ALLSPHINXOPTS = $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) +ALLSPHINXOPTS = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC) +ALLSPHINXOPTS += $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ifneq ($(wildcard $(srctree)/.config),) ifeq ($(CONFIG_RUST),y) # Let Sphinx know we will include rustdoc
Signature · 1 line
2.49.0
PATCH v4 2/4 Makefile: move KERNELDOC macro to the main Makefile
In reply to Mauro Carvalho ChehabAs kernel-doc script is used not only on Documentation, but also on scripts and drivers/drm Makefiles, move it to the main makefile, as otherwise sub-makefiles may not have it.
--- Documentation/Makefile | 1 - Makefile | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-)
Documentation/Makefile +0 -1
@@ -60,7 +60,6 @@ endif #HAVE_LATEXMK # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter -KERNELDOC = $(srctree)/scripts/kernel-doc.py ALLSPHINXOPTS = -D kerneldoc_srctree=$(srctree) -D kerneldoc_bin=$(KERNELDOC) ALLSPHINXOPTS += $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ifneq ($(wildcard $(srctree)/.config),)
Makefile +5 -0
@@ -458,6 +458,11 @@ endif HOSTRUSTC = rustc HOSTPKG_CONFIG = pkg-config +# the KERNELDOC macro needs to be exported, as scripts/Makefile.build +# has a logic to call it +KERNELDOC = $(srctree)/scripts/kernel-doc.py +export KERNELDOC + KBUILD_USERHOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes \ -O2 -fomit-frame-pointer -std=gnu11 KBUILD_USERCFLAGS := $(KBUILD_USERHOSTCFLAGS) $(USERCFLAGS)
Signature · 1 line
2.49.0
PATCH v4 3/4 scripts/kernel-doc.py: don't create *.pyc files
In reply to Mauro Carvalho ChehabAs reported by Andy, kernel-doc.py is creating a __pycache__ directory at build time.
Disable creation of __pycache__ for the libraries used by kernel-doc.py, when excecuted via the build system or via scripts/find-unused-docs.sh.
--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/i915/Makefile | 2 +- include/drm/Makefile | 2 +- scripts/Makefile.build | 2 +- scripts/find-unused-docs.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/Makefile +1 -1
@@ -236,7 +236,7 @@ always-$(CONFIG_DRM_HEADER_TEST) += \ quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) cmd_hdrtest = \ $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ - $(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ touch $@ $(obj)/%.hdrtest: $(src)/%.h FORCE
drivers/gpu/drm/i915/Makefile +1 -1
@@ -408,7 +408,7 @@ obj-$(CONFIG_DRM_I915_GVT_KVMGT) += kvmgt.o # # Enable locally for CONFIG_DRM_I915_WERROR=y. See also scripts/Makefile.build ifdef CONFIG_DRM_I915_WERROR - cmd_checkdoc = $(srctree)/scripts/kernel-doc -none -Werror $< + cmd_checkdoc = PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -none -Werror $< endif # header test
include/drm/Makefile +1 -1
@@ -11,7 +11,7 @@ always-$(CONFIG_DRM_HEADER_TEST) += \ quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) cmd_hdrtest = \ $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ - $(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ touch $@ $(obj)/%.hdrtest: $(src)/%.h FORCE
scripts/Makefile.build +1 -1
@@ -83,7 +83,7 @@ else ifeq ($(KBUILD_CHECKSRC),2) endif ifneq ($(KBUILD_EXTRA_WARN),) - cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $(KDOCFLAGS) \ + cmd_checkdoc = PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -none $(KDOCFLAGS) \ $(if $(findstring 2, $(KBUILD_EXTRA_WARN)), -Wall) \ $< endif
scripts/find-unused-docs.sh +1 -1
@@ -54,7 +54,7 @@ for file in `find $1 -name '*.c'`; do if [[ ${FILES_INCLUDED[$file]+_} ]]; then continue; fi - str=$(scripts/kernel-doc -export "$file" 2>/dev/null) + str=$(PYTHONDONTWRITEBYTECODE=1 scripts/kernel-doc -export "$file" 2>/dev/null) if [[ -n "$str" ]]; then echo "$file" fi
Signature · 1 line
2.49.0
Re: [PATCH v4 3/4] scripts/kernel-doc.py: don't create *.pyc files
Quoted 24 lines · On Thu, Apr 24, 2025 at 08:16:23AM +0800 Mauro Carvalho Chehab wrote:
As reported by Andy,
kernel-doc.pyis creating a__pycache__directory at build time.Disable creation of
__pycache__for the libraries used bykernel-doc.py, when excecuted via the build system or viascripts/find-unused-docs.sh.Reported-by Andy Shevchenko <[email protected]>Signed-off-by Mauro Carvalho Chehab <[email protected]>Tested-by Andy Shevchenko <[email protected]>--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/i915/Makefile | 2 +- include/drm/Makefile | 2 +- scripts/Makefile.build | 2 +- scripts/find-unused-docs.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)drivers/gpu/drm/Makefile +0
-0
drivers/gpu/drm/Makefile always-$(CONFIG_DRM_HEADER_TEST) += \ · line 239
Quoted 5 lines
drivers/gpu/drm/Makefile +1
-1@@ -236,7 +236,7 @@ always-$(CONFIG_DRM_HEADER_TEST) += \ quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) cmd_hdrtest = \ $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ - $(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \
Did someone check if we could add
sys.dont_write_bytecode = True
to the script itself instead of cluttering PYTHONDONTWRITEBYTECODE everywhere [1]?
Kind regards,
Nicolas
[1]: https://docs.python.org/3/library/sys.html#sys.dont_write_bytecode
Re: [PATCH v4 3/4] scripts/kernel-doc.py: don't create *.pyc files
Em Fri, 25 Apr 2025 20:46:41 +0200
Nicolas Schier <[email protected]> escreveu:
Quoted 33 lines · On Thu, Apr 24, 2025 at 08:16:23AM +0800 Mauro Carvalho Chehab wrote:
Quoted 24 lines
As reported by Andy,
kernel-doc.pyis creating a__pycache__directory at build time.Disable creation of
__pycache__for the libraries used bykernel-doc.py, when excecuted via the build system or viascripts/find-unused-docs.sh.Reported-by Andy Shevchenko <[email protected]>Signed-off-by Mauro Carvalho Chehab <[email protected]>Tested-by Andy Shevchenko <[email protected]>--- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/i915/Makefile | 2 +- include/drm/Makefile | 2 +- scripts/Makefile.build | 2 +- scripts/find-unused-docs.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)drivers/gpu/drm/Makefile +0
-0drivers/gpu/drm/Makefile always-$(CONFIG_DRM_HEADER_TEST) += \ · line 239
Quoted 5 lines
drivers/gpu/drm/Makefile +1
-1@@ -236,7 +236,7 @@ always-$(CONFIG_DRM_HEADER_TEST) += \ quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@) cmd_hdrtest = \ $(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \ - $(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \ + PYTHONDONTWRITEBYTECODE=1 $(KERNELDOC) -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \Did someone check if we could add
Quoted 4 lines
sys.dont_write_bytecode = True
to the script itself instead of cluttering PYTHONDONTWRITEBYTECODE everywhere [1]?
Nice to know that we can set it at the script level. Yet, this is is meant to be a temporary solution, as IMO the best is to set PYTHONCACHEPREFIX to match the directory on O=, when it is used.
Thanks,
Mauro
PATCH v4 4/4 .gitignore: ignore Python compiled bytecode
In reply to Mauro Carvalho ChehabWhile the building system doesn't create any Python JIT bytecode, if one manually runs kernel-doc.py or get_abi.py, Python will, by default, create a bytecode and store it under scripts/lib/*.
This is normal, and not controlled by the Kernel itself. So, add *.pyc as an extension to be ignored.
--- .gitignore | 1 + 1 file changed, 1 insertion(+)
.gitignore +1 -0
@@ -40,6 +40,7 @@ *.o *.o.* *.patch +*.pyc *.rmeta *.rpm *.rsi
Signature · 1 line
2.49.0
Re: [PATCH v4 4/4] .gitignore: ignore Python compiled bytecode
Quoted 9 lines · Mauro Carvalho Chehab
While the building system doesn't create any Python JIT bytecode, if one manually runs
kernel-doc.pyorget_abi.py, Python will, by default, create a bytecode and store it underscripts/lib/*.This is normal, and not controlled by the Kernel itself. So, add *.pyc as an extension to be ignored.
Signed-off-by Mauro Carvalho Chehab <[email protected]>
Looks sorted now, thanks!
Cheers,
Miguel
Quoted 14 lines · Mauro Carvalho Chehab
As reported by Andy, the Kernel build system runs kernel-doc script for DRM, when W=1. Due to Python's normal behavior, its JIT compiler will create a bytecode and store it under
scripts/lib/*/__pycache__. As one may be using O= and even having the sources on a read-only mount point, disable its creation during build time.This is done by adding PYTHONDONTWRITEBYTECODE=1 on every place where the script is called within
Kbuildand when called via another script.This only solves half of the issue though, as one may be manually running the script by hand, without asking Python to not store any bytecode. This should be OK, but afterwards, git status will list the
__pycache__as not committed. To prevent that, add *.pyc to .gitignore.
Quoted 8 lines
This series contain 4 patches:
- patch 1 adjusts a variable that pass extra data to
scripts/kerneldoc.py;
- patch 2movesscripts/kernel-doclocation to the main makefile and exports it, asscripts/Makefile.buildwill need it;
- patch 3 disables__pycache__generation and ensure that the entireKbuildwill use KERNELDOC var for the location of kernel-doc;
- patch 4 adds *.pyc at the list of object files to be ignored.
I've applied the set, thanks.
jon
Hi Andy,
Responding to Mauro's cover-letter of v4 at:
https://lore.kernel.org/[email protected]/
, which did not CC'd to you.
Quoted 14 lines · Mauro Carvalho Chehab
As reported by Andy, the Kernel build system runs kernel-doc script for DRM, when W=1. Due to Python's normal behavior, its JIT compiler will create a bytecode and store it under
scripts/lib/*/__pycache__. As one may be using O= and even having the sources on a read-only mount point, disable its creation during build time.This is done by adding PYTHONDONTWRITEBYTECODE=1 on every place where the script is called within
Kbuildand when called via another script.This only solves half of the issue though, as one may be manually running the script by hand, without asking Python to not store any bytecode. This should be OK, but afterwards, git status will list the
__pycache__as not committed. To prevent that, add *.pyc to .gitignore.
Quoted 8 lines
This series contain 4 patches:
- patch 1 adjusts a variable that pass extra data to
scripts/kerneldoc.py;
- patch 2movesscripts/kernel-doclocation to the main makefile and exports it, asscripts/Makefile.buildwill need it;
- patch 3 disables__pycache__generation and ensure that the entireKbuildwill use KERNELDOC var for the location of kernel-doc;
- patch 4 adds *.pyc at the list of object files to be ignored.
I see Jon has merged them all, but responding here anyway.
Quoted 5 lines · you
This started well, until it becomes a
scripts/lib/kdoc.
So, it makes themake O=...builds dirty *). Please make sure this doesn't leave "disgusting turd" )as said by Linus) in the clean tree.*) it creates that
__pycache__disaster. And no, .gitignore IS NOT a solution.w
Andy, I don't agree with your words "__pycache__ disaster" and ".gitignore IS NOT a solution".
Running "find . -name ".gitignore" -exec grep -nH --null -F -e ".pyc" \{\} +" under today's Linus master returns this:
-------------------------------------------------------------
./scripts/gdb/linux/.gitignore:2:*.pyc ./drivers/comedi/drivers/ni_routing/tools/.gitignore:3:*.pyc ./tools/perf/.gitignore:32:*.pyc ./tools/testing/selftests/tc-testing/.gitignore:3:*.pyc ./Documentation/.gitignore:3:*.pyc
-------------------------------------------------------------
, and they have been working perfectly.
Having seen your response at https://lore.kernel.org/[email protected]/ :
Quoted 4 lines
I tried before, but I admit, that I have missed something. It was a mess in that case. Now I probably can't repeat as I don't remember what was the environment and settings I had that time. I'm really glad to see it is working this way!
, I'm guessing you had a traumatic experience caused by python's bytecode caching in the past. Do you still believe ".gitignore IS NOT a solution"?
From my viewpoint, applying only 4/4 of this series is the right thing to do.
Bothering with might-become-incompatilbe-in-the-future python environment variables in kernel Makefiles looks over-engineering to me. Also, as Mauro says in 3/4, it is incomplete in that it does not cover the cases where those scripts are invoked outside of kernel build. And it will interfere with existing developers who want the benefit of bytecode caching.
I'm not precluding the possibility of incoherent bytecode cache; for example by using a shared kernel source tree among several developers, and only one of them (owner) has a write permission of it. In that case, said owner might update the tree without running relevant python scripts.
I don't know if python can notice outdated cache and disregard it.
In such a situation, setting PYTHONPYCACHEPREFIX as an environment variable should help, for sure, but only in such special cases.
Andy, what do you say if I ask reverts of 1/4, 2/4/, and 3/4?
Regards,
Akira
Hi Akira,
Em Sat, 26 Apr 2025 11:39:05 +0900
Akira Yokosawa <[email protected]> escreveu:
Quoted 12 lines
Bothering with might-become-incompatilbe-in-the-future python environment variables in kernel Makefiles looks over-engineering to me. Also, as Mauro says in 3/4, it is incomplete in that it does not cover the cases where those scripts are invoked outside of kernel build. And it will interfere with existing developers who want the benefit of bytecode caching.
I'm not precluding the possibility of incoherent bytecode cache; for example by using a shared kernel source tree among several developers, and only one of them (owner) has a write permission of it. In that case, said owner might update the tree without running relevant python scripts.
Quoted 6 lines
I don't know if python can notice outdated cache and disregard it.
In such a situation, setting PYTHONPYCACHEPREFIX as an environment variable should help, for sure, but only in such special cases.
Andy, what do you say if I ask reverts of 1/4, 2/4/, and 3/4?
Patches 1 and 2 are, IMO, needed anyway, as they fix a problem:
KERNELDOC environment is not used consistently.
Now, patch 3 is the one that may require more thinking.
I agree with Andy that, when O=<dir> is used, nothing shall be written to source dir.
There are a couple of reasons for that:
1. source dir may be read only;
2. one may want to do cross compilation and use multiple output directories, one for each version;
3. the source dir could be mapped via NFS to multiple machines with different architectures.
For (3), it could mean that multiple machines may have different Python versions, so, sharing the Python bytecode from source dir doesn't sound a good idea. Also, I'm not sure if the pyc from different archs would be identical.
With that, there are two options:
a. disable cache;
b. set PYTHONCACHEPREFIX.
We're currently doing (a). I guess everybody agrees that this is is not ideal.
So, ideally, we should move to (b). For Spinx, the easiest solution is just to place it under Documentation/output, but this is not generic enough: ideally, we should revert patch 3 and set PYTHONCACHEPREFIX when O is used. Eventually, we can apply my patch for Documentation/output, while we craft such logic.
Regards,
Mauro
Quoted 43 lines · Mauro Carvalho Chehab
Em Sat, 26 Apr 2025 11:39:05 +0900
Akira Yokosawa <[email protected]> escreveu:Quoted 12 lines
Bothering with might-become-incompatilbe-in-the-future python environment variables in kernel Makefiles looks over-engineering to me. Also, as Mauro says in 3/4, it is incomplete in that it does not cover the cases where those scripts are invoked outside of kernel build. And it will interfere with existing developers who want the benefit of bytecode caching.
I'm not precluding the possibility of incoherent bytecode cache; for example by using a shared kernel source tree among several developers, and only one of them (owner) has a write permission of it. In that case, said owner might update the tree without running relevant python scripts.
Quoted 6 lines
I don't know if python can notice outdated cache and disregard it.
In such a situation, setting PYTHONPYCACHEPREFIX as an environment variable should help, for sure, but only in such special cases.
Andy, what do you say if I ask reverts of 1/4, 2/4/, and 3/4?
Patches 1 and 2 are, IMO, needed anyway, as they fix a problem:
KERNELDOC environment is not used consistently.Now, patch 3 is the one that may require more thinking.
I agree with Andy that, when O=<dir> is used, nothing shall be written to source dir.
There are a couple of reasons for that:
1. source dir may be read only;
2. one may want to do cross compilation and use multiple output directories, one for each version;
3. the source dir could be mapped via NFS to multiple machines with different architectures.For (3), it could mean that multiple machines may have different Python versions, so, sharing the Python bytecode from source dir doesn't sound a good idea. Also, I'm not sure if the pyc from different archs would be identical.
Quoted 4 lines
With that, there are two options:
a. disable cache;
b. set PYTHONCACHEPREFIX.
Thanks, Mauro, for replying. I'm with you on all of it.
Quoted 2 lines
We're currently doing (a). I guess everybody agrees that this is is not ideal.
Yes, I also prefer to have cache working if it's possible. The only BUT here is that users should not suffer from it.
Quoted 5 lines
So, ideally, we should move to (b). For Spinx, the easiest solution is just to place it under
Documentation/output, but this is not generic enough: ideally, we should revert patch 3 and set PYTHONCACHEPREFIX when O is used. Eventually, we can apply my patch forDocumentation/output, while we craft such logic.
Signature · 2 lines
With Best Regards, Andy Shevchenko