Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
include_unused Namespace Reference

Functions

 has_unbuilt_branch (text)
 
 read (path)
 
 project_files ()
 
 strip_comments_and_strings (text)
 
 declared_names (text)
 
 resolve (inc, from_path, known)
 
 analyse ()
 
 _all_targets ()
 
 ninja_target_for (path)
 
 verify (results, limit)
 
 main ()
 
 _strip (path, incs)
 
 _build (targets=None)
 
 _implicated (log, owned)
 
 _apply_only (subset, originals, targets)
 
 _bisect_set (files, originals, targets)
 
 apply_mode (results, prefix, skip_guarded)
 
 _object_to_source ()
 
 _failing_sources (log, obj2src)
 
 _consumers_of (header)
 
 push_down (results)
 

Variables

str SRC = 'src'
 
str BUILD = 'build'
 
 INCLUDE_RE = re.compile(r'^([ \t]*#[ \t]*include[ \t]+")([^"]+)(".*)$', re.M)
 
 IDENT_RE = re.compile(r'\b[A-Za-z_][A-Za-z0-9_]*\b')
 
dict SIDE_EFFECT_HEADERS
 
list DECL_PATTERNS
 
tuple OS_MACROS
 
 OS_COND_RE = re.compile(r'^[ \t]*#[ \t]*(?:if|ifdef|ifndef|elif)\b[^\n]*\b(?:' + OS_MACROS + r')\b', re.M)
 
 COND_RE = re.compile(r'^[ \t]*#[ \t]*(if|ifdef|ifndef|elif|else|endif)\b([^\n]*)', re.M)
 
 FEATURE_RE = re.compile(r'\b(?:HAVE_[A-Z0-9_]+|__SSE2__|__ARM_NEON|_OPENMP)\b')
 
 ATTRIBUTE_RE = re.compile(r'__attribute__\s*\‍(\‍((?:[^()]|\‍([^()]*\‍))*\‍)\‍)')
 
 _TARGETS_CACHE = None
 

Detailed Description

Find `#include`s that a file does not need.

Two stages, because neither alone is trustworthy:

  1. STATIC (fast, whole tree, no build).  Index every project header by the names it
     DECLARES (macros, typedefs, tags, enum constants, function and variable
     declarations).  For each file F and each header H that F includes directly, if F
     mentions none of H's own names, H is a *candidate* for removal.

     This over-reports: F may include H legitimately to reach something H itself
     includes (a transitive dependency).  That is exactly the coupling we want to make
     explicit, but removing such an include still breaks the build, so a candidate is
     a question, never a verdict.

  2. VERIFY (slow, exact w.r.t. the current build config).  Actually comment the
     include out, recompile the affected object with ninja, and keep the removal only
     if it still compiles.  Run this on the candidates from stage 1.

The verify stage cannot prove an include is unneeded on OTHER platforms: an include
used only inside `#ifdef _WIN32` looks removable on Linux and is not.  Candidates whose
symbol use is under a conditional are flagged `platform-guarded` and must never be
removed on the strength of a Linux-only build.  See doc/include-hygiene-roadmap.md.

Usage:
  python3 tools/include_unused.py                       # static pass, summary
  python3 tools/include_unused.py --headers             # only .h files
  python3 tools/include_unused.py --sources             # only .c/.cc files
  python3 tools/include_unused.py --file src/iop/x.c    # one file, verbose
  python3 tools/include_unused.py --json out.json       # machine-readable
  python3 tools/include_unused.py --verify --limit 40   # empirically test candidates

Function Documentation

◆ _all_targets()

include_unused._all_targets ( )
protected

Definition at line 202 of file include_unused.py.

Referenced by ninja_target_for().

◆ _apply_only()

include_unused._apply_only (   subset,
  originals,
  targets 
)
protected
Restore every touched file, then re-strip just `subset`.

Definition at line 383 of file include_unused.py.

References _strip().

Referenced by _bisect_set().

◆ _bisect_set()

include_unused._bisect_set (   files,
  originals,
  targets 
)
protected
Largest subset of `files` whose removals still build. Removals are independent
in practice, so recursive halving is sound; the caller re-verifies the union.

Definition at line 392 of file include_unused.py.

References _apply_only(), _bisect_set(), and _build().

Referenced by _bisect_set(), and apply_mode().

◆ _build()

include_unused._build (   targets = None)
protected

Definition at line 359 of file include_unused.py.

Referenced by _bisect_set(), apply_mode(), and push_down().

◆ _consumers_of()

include_unused._consumers_of (   header)
protected
Files that include `header` directly (either spelling).

Definition at line 542 of file include_unused.py.

References read().

Referenced by push_down().

◆ _failing_sources()

include_unused._failing_sources (   log,
  obj2src 
)
protected

Definition at line 533 of file include_unused.py.

Referenced by push_down().

◆ _implicated()

include_unused._implicated (   log,
  owned 
)
protected
Source files in `owned` that the build log blames, directly or through a
generated introspection_*.c that textually includes them.

Definition at line 365 of file include_unused.py.

Referenced by apply_mode().

◆ _object_to_source()

include_unused._object_to_source ( )
protected
Reverse-map ninja object targets back to source files, via compdb.

Definition at line 511 of file include_unused.py.

Referenced by push_down().

◆ _strip()

include_unused._strip (   path,
  incs 
)
protected
Remove whole #include lines. Returns the ones actually removed.

Must match the LINE, not the exact string `#include "x"\n`: an include carrying a
trailing comment would silently fail to match, and the caller would then report a
removal that never happened -- which is how this tool once claimed 7 removals for a
3-line diff.

Definition at line 340 of file include_unused.py.

References read().

Referenced by _apply_only(), apply_mode(), and push_down().

◆ analyse()

include_unused.analyse ( )

◆ apply_mode()

include_unused.apply_mode (   results,
  prefix,
  skip_guarded 
)

Definition at line 416 of file include_unused.py.

References _bisect_set(), _build(), _implicated(), _strip(), and read().

Referenced by main().

◆ declared_names()

include_unused.declared_names (   text)

Definition at line 134 of file include_unused.py.

References strip_comments_and_strings().

Referenced by analyse().

◆ has_unbuilt_branch()

include_unused.has_unbuilt_branch (   text)
True if the file contains a branch this build does not compile.

Definition at line 89 of file include_unused.py.

Referenced by analyse().

◆ main()

include_unused.main ( void  )

Definition at line 253 of file include_unused.py.

References analyse(), apply_mode(), push_down(), and verify().

Referenced by push_down().

◆ ninja_target_for()

include_unused.ninja_target_for (   path)
Best-effort mapping from a source file to one ninja object target.

Definition at line 214 of file include_unused.py.

References _all_targets().

Referenced by verify().

◆ project_files()

include_unused.project_files ( )

Definition at line 113 of file include_unused.py.

Referenced by analyse().

◆ push_down()

include_unused.push_down (   results)

Definition at line 559 of file include_unused.py.

References _build(), _consumers_of(), _failing_sources(), _object_to_source(), _strip(), main(), and read().

Referenced by main().

◆ read()

include_unused.read (   path)

Definition at line 108 of file include_unused.py.

Referenced by _consumers_of(), _strip(), analyse(), apply_mode(), push_down(), and verify().

◆ resolve()

include_unused.resolve (   inc,
  from_path,
  known 
)

Definition at line 155 of file include_unused.py.

Referenced by analyse().

◆ strip_comments_and_strings()

include_unused.strip_comments_and_strings (   text)
Crude but adequate: we only need identifier presence, not exact syntax.

Definition at line 123 of file include_unused.py.

Referenced by analyse(), and declared_names().

◆ verify()

include_unused.verify (   results,
  limit 
)
Comment each candidate out, rebuild its object, keep only what still compiles.

Definition at line 223 of file include_unused.py.

References ninja_target_for(), and read().

Referenced by main().

Variable Documentation

◆ _TARGETS_CACHE

include_unused._TARGETS_CACHE = None
protected

Definition at line 199 of file include_unused.py.

◆ ATTRIBUTE_RE

include_unused.ATTRIBUTE_RE = re.compile(r'__attribute__\s*\‍(\‍((?:[^()]|\‍([^()]*\‍))*\‍)\‍)')

Definition at line 131 of file include_unused.py.

◆ BUILD

str include_unused.BUILD = 'build'

Definition at line 41 of file include_unused.py.

◆ COND_RE

include_unused.COND_RE = re.compile(r'^[ \t]*#[ \t]*(if|ifdef|ifndef|elif|else|endif)\b([^\n]*)', re.M)

Definition at line 85 of file include_unused.py.

◆ DECL_PATTERNS

list include_unused.DECL_PATTERNS
Initial value:
1= [
2 re.compile(r'^[ \t]*#[ \t]*define[ \t]+([A-Za-z_][A-Za-z0-9_]*)', re.M),
3 re.compile(r'^[ \t]*}[ \t]*([A-Za-z_][A-Za-z0-9_]*)[ \t]*;', re.M), # } dt_foo_t;
4 re.compile(r'\btypedef\b[^;{]*?\b([A-Za-z_][A-Za-z0-9_]*)[ \t]*;', re.M), # typedef X dt_y_t;
5 re.compile(r'\b(?:struct|union|enum)[ \t]+([A-Za-z_][A-Za-z0-9_]*)', re.M),
6 re.compile(r'^[A-Za-z_][A-Za-z0-9_ \t\*]*?\b([A-Za-z_][A-Za-z0-9_]*)[ \t]*\‍(', re.M),
7 re.compile(r'^[ \t]*extern[^;=]*?\b([A-Za-z_][A-Za-z0-9_]*)[ \t]*(?:\[|;)', re.M),
8]

Definition at line 63 of file include_unused.py.

◆ FEATURE_RE

include_unused.FEATURE_RE = re.compile(r'\b(?:HAVE_[A-Z0-9_]+|__SSE2__|__ARM_NEON|_OPENMP)\b')

Definition at line 86 of file include_unused.py.

◆ IDENT_RE

include_unused.IDENT_RE = re.compile(r'\b[A-Za-z_][A-Za-z0-9_]*\b')

Definition at line 44 of file include_unused.py.

◆ INCLUDE_RE

include_unused.INCLUDE_RE = re.compile(r'^([ \t]*#[ \t]*include[ \t]+")([^"]+)(".*)$', re.M)

Definition at line 43 of file include_unused.py.

◆ OS_COND_RE

include_unused.OS_COND_RE = re.compile(r'^[ \t]*#[ \t]*(?:if|ifdef|ifndef|elif)\b[^\n]*\b(?:' + OS_MACROS + r')\b', re.M)

Definition at line 84 of file include_unused.py.

◆ OS_MACROS

tuple include_unused.OS_MACROS
Initial value:
1= (r'_WIN32|WIN32|__WIN32__|__MINGW\w*|_MSC_VER|__APPLE__|__MACH__'
2 r'|GDK_WINDOWING_QUARTZ|__FreeBSD__|__NetBSD__|__OpenBSD__|__DragonFly__')

Definition at line 82 of file include_unused.py.

◆ SIDE_EFFECT_HEADERS

dict include_unused.SIDE_EFFECT_HEADERS
Initial value:
1= {
2 'config.h',
3 'common/poison.h', # #pragma-poisons forbidden libc calls
4 'win/win.h', # #undefs legacy windows.h macros
5 'common/module_api.h', # X-macro, generates struct members
6 'views/view_api.h',
7 'libs/lib_api.h',
8 'imageio/format/imageio_format_api.h',
9 'imageio/storage/imageio_storage_api.h',
10 'external/ThreadSafetyAnalysis.h',
11 'darktable.h', # the orchestrator: handled by its own migration
12}

Definition at line 48 of file include_unused.py.

◆ SRC

str include_unused.SRC = 'src'

Definition at line 40 of file include_unused.py.