#!/usr/bin/python # Copyright (C) 2011 Igalia S.L. # # This 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 of the License, or (at your option) any later version. # # This 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 this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA import common import os import subprocess import sys def is_source_file_listing(line): return line.strip().startswith('Source') def get_listed_makefile_headers(): makefile_text = open(os.path.join(common.build_path('GNUmakefile'))).read() # Automake often places separate includes on the same line. makefile_text = makefile_text.replace(' ', '\n') headers = [] for line in makefile_text.splitlines(): # $(srcdir)/ is the same as an empty string in a source file listing. line = line.replace('$(srcdir)/', '') # If the line doesn't start with 'Source' it isn't listing for # a source file. if not is_source_file_listing(line): continue # Most source listings end with \ indicating that the listing # continues onto the next line. line = line.replace('\\', '') # We only care about header files. Source files result in build # breakage, so we will detect them without this script. line = line.strip() if not line.endswith('.h'): continue # If the line contains a makefile variable we do not care about it. if line.find('$') != -1: continue headers.append(line) return headers def scan_headers_from_dependency_files(): process = subprocess.Popen(['find . -name *.Plo | xargs cat | grep .h:$'], cwd=common.build_path(), stdout=subprocess.PIPE, shell=True) sanitized_lines = set() for line in process.communicate()[0].splitlines(): # Paths in Plo files are relative to the build directory so they might contain # ../.. if the build directory is something like WebKitBuild/Release. line = line.replace('../../', '') if not is_source_file_listing(line): continue # The lines we care about end with ':'. line = line.replace(':', '') line = line.strip() sanitized_lines.add(line) return sanitized_lines def get_unlisted_headers(listed_makefile_headers): unlisted = set() for header in scan_headers_from_dependency_files(): if not header in listed_makefile_headers: unlisted.add(header) return unlisted def get_missing_headers(listed_makefile_headers): missing = set() for header in listed_makefile_headers: if not os.path.exists(common.top_level_path(header)): missing.add(header) return missing listed_makefile_headers = get_listed_makefile_headers() unlisted_headers = get_unlisted_headers(listed_makefile_headers) missing_headers = get_missing_headers(listed_makefile_headers) if unlisted_headers: print 'Headers not listed in the GNUmakefiles:' for header in sorted(unlisted_headers): print '\t%s' % header print if missing_headers: print 'Headers listed in the GNUmakefiles that do not exist:' for header in sorted(missing_headers): print '\t%s' % header print sys.exit(len(unlisted_headers) + len(missing_headers))