Re: [PATCH] kbuild: add header check facility as a manually run static analyzer
From: Randy Dunlap
Date: Wed Sep 16 2026 - 18:24:38 EST
Hi Jani,
On 9/15/26 3:43 AM, Jani Nikula wrote:
> There have been various attempts at adding a header test or check
> mechanism in the kernel build system. The header check primarily
> consists of ensuring headers are self-contained, have include guards,
> and, in some cases, pass kernel-doc.
>
> The main problems have been:
>
> - The dependency tracking creates undesirable artefacts (infamously also
> known as disgusting turds) in the build directory.
>
> - Gating the feature behind a kconfig option is complicated due to
> allyesconfig builds. It's possible, but requires a verbose and
> confusing negative proxy config option.
>
> - Naming the dependency tracking files with a dot prefix or placing them
> in a dot prefixed subdirectory in the build directory to hide them has
> been exceedingly difficult to achieve. (In part due to some Makefiles
> building files in subdirectory hierarchies.)
>
> - The debate which headers, if any, should really be self-contained is
> virtually open-ended.
I would expect that headers in include/uapi/*.h should be self-contained,
but apparently that's just a pipe dream on my part, or maybe it's just
a maintainer option.
With 'make HEADER_CHECK="include/uapi/" headercheck'
I see over 70 errors (mostly typedefs or defined constants, but not only
those), such as:
In file included from <command-line>:
./../include/uapi/linux/hdlc/ioctl.h:74:21: error: ‘IFNAMSIZ’ undeclared here (not in a function)
74 | char master[IFNAMSIZ]; /* Name of master FRAD device */
| ^~~~~~~~
In file included from <command-line>:
./../include/uapi/linux/input.h:29:6: warning: ‘__BITS_PER_LONG’ is not defined, evaluates to ‘0’ [-Wundef]
29 | #if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__)
| ^~~~~~~~~~~~~~~
./../include/uapi/linux/input.h:34:9: error: unknown type name ‘__kernel_ulong_t’
34 | __kernel_ulong_t __sec;
| ^~~~~~~~~~~~~~~~
In file included from ./../include/uapi/linux/papr_pdsm.h:14,
from <command-line>:
../include/linux/ndctl.h:19:33: error: ‘PAGE_SIZE’ undeclared here (not in a function)
19 | ND_MIN_NAMESPACE_SIZE = PAGE_SIZE,
| ^~~~~~~~~
In file included from <command-line>:
./../include/uapi/linux/patchkey.h:15:2: error: #error "patchkey.h included directly"
15 | #error "patchkey.h included directly"
| ^~~~~
In file included from <command-line>:
include/uapi/xen/gntdev.h:159:25: error: unknown type name ‘grant_ref_t’
159 | grant_ref_t ref;
| ^~~~~~~~~~~
include/uapi/xen/gntdev.h:161:25: error: unknown type name ‘domid_t’
161 | domid_t domid;
| ^~~~~~~
I like it; I think it's useful.
Tested-by: Randy Dunlap <rdunlap@xxxxxxxxxxxxx>
Acked-by: Randy Dunlap <rdunlap@xxxxxxxxxxxxx>
> Approach the problem from a slightly different angle. Add a top level
> "headercheck" static analysis target which you have to explicitly run,
> and where you have to explicitly state which headers to check:
>
> $ make HEADER_CHECK="(headers|dirs)" headercheck
>
> For example:
>
> $ make HEADER_CHECK="include/drm drivers/gpu/drm/drm_draw_internal.h" headercheck
>
> You can specify multiple path/to/header.h or path/to/dir, relative to
> $(srctree), where path/to/dir is recursively scanned for any .h files.
>
> Add a generic %.header-check rule in scripts/Makefile.build to support
> this. Note that this rule should *not* be used in, say, driver or
> subsystem makefile targets, precisely because of the problems listed
> above.
>
> While this still generates the .header-check dependency tracking
> artefacts in the build directory, you will only get them as a result of
> manually running 'make headercheck', not as part of the regular build.
>
> This approach also allows anyone to check any headers in the tree, with
> no makefile modification or kconfig changes required. What you do with
> the results is up to you, and the header check facility does not enforce
> anything like it would as part of the regular build.
>
> Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
> Cc: Nathan Chancellor <nathan@xxxxxxxxxx>
> Cc: Nicolas Schier <nsc@xxxxxxxxxx>
> Cc: Jason Gunthorpe <jgg@xxxxxxxxxx>
> Cc: Masahiro Yamada <masahiroy@xxxxxxxxxx>
> Cc: linux-kbuild@xxxxxxxxxxxxxxx
> Signed-off-by: Jani Nikula <jani.nikula@xxxxxxxxx>
> ---
> .gitignore | 1 +
> Makefile | 25 ++++++++++++++++++++++++-
> scripts/Makefile.build | 21 +++++++++++++++++++++
> 3 files changed, 46 insertions(+), 1 deletion(-)
thanks.
--
~Randy