aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--changes/ticket264475
-rwxr-xr-xscripts/maint/checkIncludes.py26
3 files changed, 31 insertions, 4 deletions
diff --git a/Makefile.am b/Makefile.am
index 202197f5f5..3df35ad3f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -203,7 +203,7 @@ doxygen:
test: all
$(top_builddir)/src/test/test
-check-local: check-spaces check-changes
+check-local: check-spaces check-changes check-includes
need-chutney-path:
@if test ! -d "$$CHUTNEY_PATH"; then \
@@ -320,7 +320,7 @@ endif
check-includes:
if USEPYTHON
- $(top_srcdir)/scripts/maint/checkIncludes.py
+ $(PYTHON) $(top_srcdir)/scripts/maint/checkIncludes.py
endif
check-docs: all
diff --git a/changes/ticket26447 b/changes/ticket26447
new file mode 100644
index 0000000000..757a4022ff
--- /dev/null
+++ b/changes/ticket26447
@@ -0,0 +1,5 @@
+ o Minor features (code correctness, testing):
+ - Tor's build process now includes a "check-includes" make target
+ to verify that no module of Tor relies on any headers from a
+ higher-level module. We hope to use this feature over time to
+ help refactor our codebase. Closes ticket 26447.
diff --git a/scripts/maint/checkIncludes.py b/scripts/maint/checkIncludes.py
index 5cf7ead47e..d13ff565cb 100755
--- a/scripts/maint/checkIncludes.py
+++ b/scripts/maint/checkIncludes.py
@@ -1,6 +1,21 @@
#!/usr/bin/python3
# Copyright 2018 The Tor Project, Inc. See LICENSE file for licensing info.
+"""This script looks through all the directories for files matching *.c or
+ *.h, and checks their #include directives to make sure that only "permitted"
+ headers are included.
+
+ Any #include directives with angle brackets (like #include <stdio.h>) are
+ ignored -- only directives with quotes (like #include "foo.h") are
+ considered.
+
+ To decide what includes are permitted, this script looks at a .may_include
+ file in each directory. This file contains empty lines, #-prefixed
+ comments, filenames (like "lib/foo/bar.h") and file globs (like lib/*/*.h)
+ for files that are permitted.
+"""
+
+
from __future__ import print_function
import fnmatch
@@ -8,20 +23,26 @@ import os
import re
import sys
+# Global: Have there been any errors?
trouble = False
def err(msg):
+ """ Declare that an error has happened, and remember that there has
+ been an error. """
global trouble
trouble = True
print(msg, file=sys.stderr)
def fname_is_c(fname):
+ """ Return true iff 'fname' is the name of a file that we should
+ search for possibly disallowed #include directives. """
return fname.endswith(".h") or fname.endswith(".c")
INCLUDE_PATTERN = re.compile(r'\s*#\s*include\s+"([^"]*)"')
RULES_FNAME = ".may_include"
class Rules(object):
+ """ A 'Rules' object is the parsed version of a .may_include file. """
def __init__(self, dirpath):
self.dirpath = dirpath
self.patterns = []
@@ -59,6 +80,7 @@ class Rules(object):
print("Pattern {} in {} was never used.".format(p, self.dirpath))
def load_include_rules(fname):
+ """ Read a rules file from 'fname', and return it as a Rules object. """
result = Rules(os.path.split(fname)[0])
with open(fname, 'r') as f:
for line in f:
@@ -81,6 +103,6 @@ for dirpath, dirnames, fnames in os.walk("src"):
if trouble:
err(
-"""To change which includes are allowed in a C file, edit the {} files in its
-enclosing directory.""".format(RULES_FNAME))
+"""To change which includes are allowed in a C file, edit the {}
+files in its enclosing directory.""".format(RULES_FNAME))
sys.exit(1)