2 # Check that a wrapper header exist for each non-sysdeps header.
3 # Copyright (C) 2019-2023 Free Software Foundation, Inc.
4 # This file is part of the GNU C Library.
6 # The GNU C Library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2.1 of the License, or (at your option) any later version.
11 # The GNU C Library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with the GNU C Library; if not, see
18 # <https://www.gnu.org/licenses/>.
20 # Non-sysdeps subdirectories are not on the C include path, so
21 # installed headers need to have a sysdep wrapper header.
23 # usage: scripts/checl-wrapper-headers.py \
24 # --root=$(..) --subdir=$(subdir) $(headers) \
25 # [--generated $(common-generated)]
27 # If invoked with --root=., the script is invoked from the root of the
28 # source tree, so paths starting with "include/" are skipped (because
29 # those do not require wrappers).
35 # Some subdirectories are only compiled for essentially one target.
36 # In this case, we do not need to check for consistent wrapper
37 # headers. Hurd uses a custom way to Hurd-specific inject wrapper
38 # headers; see sysdeps/mach/Makefiles under "ifdef in-Makerules".
39 SINGLE_TARGET_SUBDIRS
= frozenset(("hurd", "mach"))
41 # Name of the special subdirectory with the wrapper headers.
44 def check_sysdeps_bits(args
):
45 """Check that the directory sysdeps/generic/bits does not exist."""
46 bits
= os
.path
.join(args
.root
, 'sysdeps', 'generic', 'bits')
47 if os
.path
.exists(bits
):
48 # See commit c72565e5f1124c2dc72573e83406fe999e56091f and
49 # <https://sourceware.org/ml/libc-alpha/2016-05/msg00189.html>.
50 print('error: directory {} has been added, use bits/ instead'.format(
51 os
.path
.relpath(os
.path
.realpath(bits
), args
.root
)))
55 def check_headers_root(args
):
56 """Check headers located at the top level of the source tree."""
58 generated
= frozenset(args
.generated
)
59 for header
in args
.headers
:
60 if not (header
.startswith('bits/')
61 or os
.path
.exists(os
.path
.join(args
.root
, INCLUDE
, header
))
62 or header
in generated
):
63 print('error: top-level header {} must be in bits/ or {}/'
64 .format(header
, INCLUDE
))
68 def check_headers(args
):
69 """Check headers located in a subdirectory."""
71 for header
in args
.headers
:
72 # Whitelist .x files, which never have include wrappers.
73 if header
.endswith(".x"):
76 is_nonsysdep_header
= os
.access(header
, os
.R_OK
)
77 if is_nonsysdep_header
:
78 # Skip Fortran header files.
79 if header
.startswith("finclude/"):
82 include_path
= os
.path
.join(args
.root
, INCLUDE
, header
)
83 if not os
.access(include_path
, os
.R_OK
):
84 print('error: missing wrapper header {} for {}'.format(
85 os
.path
.join(INCLUDE
, header
),
86 os
.path
.relpath(os
.path
.realpath(header
), args
.root
)))
91 """The main entry point."""
92 parser
= argparse
.ArgumentParser(
93 description
='Check for missing wrapper headers in include/.')
94 parser
.add_argument('--root', metavar
='DIRECTORY', required
=True,
95 help='Path to the top-level of the source tree')
96 parser
.add_argument('--subdir', metavar
='DIRECTORY', required
=True,
97 help='Name of the subdirectory being processed')
98 parser
.add_argument('--generated', metavar
='FILE', default
="", nargs
="*",
99 help="Generated files (which are ignored)")
100 parser
.add_argument('headers', help='Header files to process', nargs
='+')
101 args
= parser
.parse_args()
103 good
= (args
.root
== '.') == (args
.subdir
== '.')
105 print('error: --root/--subdir disagree about top-of-tree location')
107 if args
.subdir
== '.':
108 good
&= check_sysdeps_bits(args
)
109 good
&= check_headers_root(args
)
110 elif args
.subdir
not in SINGLE_TARGET_SUBDIRS
:
111 good
&= check_headers(args
)
116 if __name__
== '__main__':