50a5ad7320
Hierarchical processing makes cpp.req more susceptible to "once-only header" optimization. To demonstrate the problem, I've implemented some debugging facilities. Here is how <gtk/gtk.h> is processed. $ cpp.req -vv /usr/include/gtk-2.0/gtk/gtk.h [...] Include gdk/gdk.h + Push /usr/include/gtk-2.0/gdk/gdk.h Include gdk/gdkapplaunchcontext.h + Push /usr/include/gtk-2.0/gdk/gdkapplaunchcontext.h Include gio/gio.h ! Push /usr/include/glib-2.0/gio/gio.h Include gio/giotypes.h Push /usr/include/glib-2.0/gio/giotypes.h Include gio/gioenums.h Push /usr/include/glib-2.0/gio/gioenums.h Include glib-object.h Push /usr/include/glib-2.0/glib-object.h Include gobject/gbinding.h Push /usr/include/glib-2.0/gobject/gbinding.h Include glib.h Push /usr/include/glib-2.0/glib.h [...] + Push /usr/include/gtk-2.0/gtk/gtkdebug.h Include glib.h Pop [...] recovered glib.h -> /usr/include/glib-2.0/glib.h recovered stdarg.h -> /usr/lib64/gcc/x86_64-alt-linux/4.5.3/include/stdarg.h recovered time.h -> /usr/include/time.h recovered glib-object.h -> /usr/include/glib-2.0/glib-object.h In the output, "Include" lines annotate "#include" instructions which are about to be processed by cpp; "Push" and "Pop" annotate actual file operations performed by cpp. Technically, "Include" annotations are enabled via -dI option which installs cb_include callback in gcc/c-ppoutput.c; "Push" and "Pop" are triggered in the guts of the libcpp library. The library has hardcoded optimization against repeated inclusions. According to "info cpp", "It remembers when a header file has a wrapper #ifndef. If a subsequent #include specifies that header, and the macro in the #ifndef is still defined, it does not bother to rescan the file at all." (See should_stack_file in libcpp/files.c.) This means that, normally, each "Include" should be followed by a corresponding "Push". However, due to "once-only header" optimization, some includes are not followed by a push. This means that the file has already been pushed, and it happens to use a wrapper #ifndef. Note that, in the output, this is exactly the case with <glib2.h>. Also note that, in the output, files internal to the package are marked with "+" on the left. They are tracked down to the first non-packaged file, which makes a dependency; these files are marked with "!". The problem with <glib2.h> is then that it gets first included in an external file. Later it is also included in an internal file, but a "Push" is not triggered. And since the internal file is subordinate to <gtk/gtk.h> and is not going to be processed on its own, the dependency on <glib2.h> is lost. To recover missing pushes, we have to associate each include with the first-time push. In other words, we need a table which maintains a (header -> filename) mapping; in the above example, the table will contain (glib.h -> /usr/include/glib-2.0/glib.h). Using this table, we can ascertain that each internal #include produced a result. Now, this might still have some corner cases: includes with non-canonical header names probably will not be recovered, and it is not clear whether <foo.h> and "foo.h" should be processed differently. It works well enough in simple cases, though. |
||
---|---|---|
.. | ||
.provides.sh | ||
0common-files.req.list | ||
0ldconfig.filetrigger | ||
brp-adjust_libraries.in | ||
brp-alt.in | ||
brp-bytecompile_python.in | ||
brp-cleanup.in | ||
brp-compress.in | ||
brp-debuginfo.in | ||
brp-fix-perms.in | ||
brp-fixup.in | ||
brp-hardlink_pyo_pyc.in | ||
brp-verify_elf.in | ||
brp-verify-info.in | ||
compress_files.in | ||
cpp.req.files | ||
cpp.req.in | ||
debuginfo.prov.files | ||
debuginfo.prov.in | ||
debuginfo.req.files | ||
debuginfo.req.in | ||
files.req.files.in | ||
files.req.in | ||
find-debuginfo-files.in | ||
find-lang.in | ||
find-package.in | ||
find-scriptlet-requires.in | ||
fixup-binconfig.in | ||
fixup-desktop.awk | ||
fixup-desktop.in | ||
fixup-libraries | ||
fixup-libtool.in | ||
fixup-pkgconfig.in | ||
functions | ||
ldd.in | ||
lib.prov.files | ||
lib.prov.in | ||
lib.req.files | ||
lib.req.in | ||
Makefile.am | ||
pam.prov.files | ||
pam.prov.in | ||
pam.req.files | ||
pam.req.in | ||
pkgconfig.req.files | ||
pkgconfig.req.in | ||
pkgconfiglib.req.in | ||
posttrans-filetriggers.in | ||
rpm2cpio.sh | ||
rpmlib.req.files.in | ||
rpmlib.req.in | ||
shebang.req.files | ||
shebang.req.in | ||
shell.prov.files | ||
shell.prov.in | ||
shell.req.files | ||
shell.req.in | ||
shlib.req.awk | ||
static.req.files | ||
static.req.in | ||
symlinks.req.files | ||
symlinks.req.in | ||
tmpdir.sh | ||
verify-elf.in |