= deheader(1)
:doctype: manpage
:manmanual: Development Tools
:mansource: deheader

// spellcheck: add sourcefile sourcefiles sys builddir cmake gcc
// spellcheck: add ifdef endif Werror Wfatal-errors makefile CFLAGS
// spellcheck: add Targetless pre-release deheadered POSIX

== Name
deheader - report which includes in C or C++ compiles can be removed

== Synopsis
*deheader* [-h] [-m _command_] [-b _builddir_] [-i _pattern_] [-q] [-r] [-v] [-x _pattern_] [-V] [_file-or-dir_]

== Description

This tool takes a list of C or C++ sourcefiles and generates a report
on which #includes can be omitted from them; also, what standard
inclusions may be required for portability. The test, for each foo.c
or foo.cc or foo.cpp, is simply whether "rm foo.o; make foo.o" returns
a zero status (but the build command may be overridden).

Exception: Under cmake, foo.o is a phony target. Therefore, when a
"CMakeList.txt" is detected, "make clean" is done rather than "rm
foo.o".

Optionally, with the *-r* switch, the unneeded headers are removed
from the sourcefiles. Don't use this option unless you have your
sourcefiles safely under version control and can revert!

If a sourcefile argument is a directory, the report is generated on
all source files beneath it. Subdirectories beginning with a dot are
assumed to be repository directories for version-control systems and
ignored. If no arguments are given, the program runs as if the name of
the current directory had been passed to it.

Inclusions within the scope of #if/#ifdef/#else/#endif directives are
left alone, because trying to reason about potential combinations of
-D and U options would be too complicated and prone to weird
errors. One exception: headers protected only by S_SPLINT_S, the
conditional for blocking scanning by the static analysis tool
splint(1), are scanned normally.

The tool will also emit warnings about duplicate inclusions, and
inclusions required for portability but not present.

It is recommended that you arrange to compile with options that will
stop the compiler on warnings when using this tool; otherwise it will
report headers that only declare prototypes and return types (and thus
throw only warnings) as being not required. Under gcc the compiler
options to accomplish this are -Werror -Wfatal-errors. If your
makefile follows normal conventions, running with *-m "make
CFLAGS='-Werror -Wfatal-errors' %s"* may do the right thing; you can
check this by running with -v -v -v to see what compilation commands
are actually emitted.

On each test compile, the original sourcefile is moved to a name with
an .orig suffix and restored on interrupt or after processing with its
original timestamp, unless the *-r* option was given and headers
removed.

If the -b option is given, it tells the program that generated .o
files live in a file tree parallel to the source tree but rooted at
the specified argument. If the argument is a relative path, it is
interpreted relative to the directory in which *deheader* is run.

If the first test compilation from the top-level directory fails,
*deheader* descends into the subdirectory of the source file and retries
compiling inside there.

At verbosity level 0, only messages indicating removable headers are
issued. At verbosity 1, test compilations are timed and progress
indicated with a twirling-baton prompt. At verbosity level 2, you get
verbose progress messages on the analysis. At verbosity level 3, you
see the output from the make and compilation commands.

If the -q (--quiet) option flag was not set, the last line of the
output will be a statistical summary.

Running *deheader* will leave a lot of binaries in your directory that
were compiled in ways possibly not invoked by your normal build
process. Running "make clean" afterwards (or the equivalent under
whatever build system you are using) is strongly recommended.

== Options

*-h*::
Display some help and exit.

*-m* _command_::
Set the build command used for test compiles. Defaults to 'make %s'. A
%s in the build command is replaced with the make target. Targetless
builders such as meson can be supported with, e.g. "-m 'ninja -C
build'"

*-b* _builddir_::
Set the build directory for object files.

*-i* _pattern_::
Set a pattern for includes to be ignored. Takes a Python regular expression.

*-q*::
Suppress statistical summary.

*-r*::
Remove header inclusions from sourcefiles where they are not required.

*-v*::
Set verbosity.

*-x* _pattern_::
Exclude files with names matching the specified Python regexp.

*-V*::
Show version of program and exit.

== Return Values

Returns 1 if unneeded includes were found, 0 otherwise. Thus, you can
use it for pre-release sanity checking in Makefile.

== Bugs

Very rarely, test-compiling after running with *-r* may show that this
tool removed some headers that are actually required for your
build. This can happen because *deheader* doesn't know about all the
strange things your build system gets up to, and the problem of
analyzing your build to understand them would be
Turing-complete. Simply revert the altered files and continue.

Due to minor variations in system headers, it is possible your program
may not port correctly in older Unix variants after being
deheadered. This is normally not a problem with the portion of the API
specified by POSIX and ANSI C, but may be for headers that are not
standardized or only weakly standardized. The sockets API
(<sys/select.h+, +sys/sockets.h+, and friends such as +sys/types.h+
and +sys.stat.h+) is perhaps the most serious trouble spot. *deheader*
has an internal table of rules that heads off the most common problems
by suppressing deletion of headers that are required for portability,
but your mileage may vary.

The dependency scanner does not ignore the text of comments. This,
e.g, a reference to "log10" in a comment will produce a spurious
warning that +<math.h>+ is required for portability.

Sufficiently perverse C++ can silently invalidate the brute-force
algorithm this tool uses. Example: if an overloaded function has
different overloads from two different files, removing one may expose
the other, changing runtime semantics without a compile-time
warning. Similarly, removing a later file containing a template
specialization may lead to undefined behavior from a template defined
in an earlier file. Use this with caution near such features, and test
carefully.

== Author

Eric S. Raymond <esr@snark.thyrsus.com>; (home page at http://www.catb.org/~esr/).
