diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/check-wrapper-headers.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/scripts/check-wrapper-headers.py b/scripts/check-wrapper-headers.py new file mode 100644 index 0000000000..094faa3ced --- /dev/null +++ b/scripts/check-wrapper-headers.py @@ -0,0 +1,113 @@ +#!/usr/bin/python3 +# Check that a wrapper header exist for each non-sysdeps header. +# Copyright (C) 2019 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# Non-sysdeps subdirectories are not on the C include path, so +# installed headers need to have a sysdep wrapper header. +# +# usage: scripts/checl-wrapper-headers.py \ +# --root=$(..) --subdir=$(subdir) $(headers) \ +# [--generated $(common-generated)] +# +# If invoked with --root=., the script is invoked from the root of the +# source tree, so paths starting with "include/" are skipped (because +# those do not require wrappers). + +import argparse +import os +import sys + +# Some subdirectories are only compiled for essentially one target. +# In this case, we do not need to check for consistent wrapper +# headers. Hurd uses a custom way to Hurd-specific inject wrapper +# headers; see sysdeps/mach/Makefiles under "ifdef in-Makerules". +SINGLE_TARGET_SUBDIRS = frozenset(("hurd", "mach")) + +# Name of the special subdirectory with the wrapper headers. +INCLUDE = "include" + +def check_sysdeps_bits(args): + """Check that the directory sysdeps/generic/bits does not exist.""" + bits = os.path.join(args.root, 'sysdeps', 'generic', 'bits') + if os.path.exists(bits): + # See commit c72565e5f1124c2dc72573e83406fe999e56091f and + # <https://sourceware.org/ml/libc-alpha/2016-05/msg00189.html>. + print('error: directory {} has been added, use bits/ instead'.format( + os.path.relpath(os.path.realpath(bits), args.root))) + return False + return True + +def check_headers_root(args): + """Check headers located at the top level of the source tree.""" + good = True + generated = frozenset(args.generated) + for header in args.headers: + if not (header.startswith('bits/') + or os.path.exists(os.path.join(args.root, INCLUDE, header)) + or header in generated): + print('error: top-level header {} must be in bits/ or {}/' + .format(header, INCLUDE)) + good = False + return good + +def check_headers(args): + """Check headers located in a subdirectory.""" + good = True + for header in args.headers: + # Whitelist .x files, which never have include wrappers. + if header.endswith(".x"): + continue + + is_nonsysdep_header = os.access(header, os.R_OK) + if is_nonsysdep_header: + include_path = os.path.join(args.root, INCLUDE, header) + if not os.access(include_path, os.R_OK): + print('error: missing wrapper header {} for {}'.format( + os.path.join(INCLUDE, header), + os.path.relpath(os.path.realpath(header), args.root))) + good = False + return good + +def main(): + """The main entry point.""" + parser = argparse.ArgumentParser( + description='Check for missing wrapper headers in include/.') + parser.add_argument('--root', metavar='DIRECTORY', required=True, + help='Path to the top-level of the source tree') + parser.add_argument('--subdir', metavar='DIRECTORY', required=True, + help='Name of the subdirectory being processed') + parser.add_argument('--generated', metavar='FILE', default="", nargs="*", + help="Generated files (which are ignored)") + parser.add_argument('headers', help='Header files to process', nargs='+') + args = parser.parse_args() + + good = (args.root == '.') == (args.subdir == '.') + if not good: + print('error: --root/--subdir disagree about top-of-tree location') + + if args.subdir == '.': + good &= check_sysdeps_bits(args) + good &= check_headers_root(args) + elif args.subdir not in SINGLE_TARGET_SUBDIRS: + good &= check_headers(args) + + if not good: + sys.exit(1) + +if __name__ == '__main__': + main() |