rpm-build/scripts/cpp.req.in
Alexey Tourbin 8af14dd777 cpp.req: track included files down to the first external file
Some header files have protection against being included into user
code directly.  This means that, when processing such files, cpp
is going to fail, and some dependencies probably will be missing.

/usr/include/gtk-2.0/gtk/gtkaccessible.h:
    20  #if defined(GTK_DISABLE_SINGLE_INCLUDES) && !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
    21  #error "Only <gtk/gtk.h> can be included directly."
    22  #endif
    23
    24  #ifndef __GTK_ACCESSIBLE_H__
    25  #define __GTK_ACCESSIBLE_H__
    26
    27  #include <atk/atk.h>
    28  #include <gtk/gtkwidget.h>

To remedy the problem, we should, as per the above example, process
gtk/gtk.h dependencies recursively.  Dependencies which we now attribute
to gtk/gtk.h are: 1) files which are packaged within the same subpackage
- these dependencies will be optimized out later by rpm; 2) the first
file not packaged into this subpackage, which is atk/atk.h.  Files below
atk/atk.h are not processed.

    Packaged?     Stack
                +---------------------+
        +       | gtk/gtk.h           |
                +---------------------+
        +       | gtk/gtkaccessible.h | <- SPmark
                +---------------------+
        -       | atk/atk.h           |
                +---------------------+
                | ...                 |

Also note that packaged files in cpp output should not be identified by
filenames, since filenames in the output will be possibly non-canonical.
Therefore I use standard unix technique to identify files by (dev,ino).

/usr/include/boost/spirit/home/support/detail/lexer/containers/ptr_vector.hpp:
     9  #include "../size_t.hpp"
2011-09-22 03:08:14 +04:00

152 lines
3.7 KiB
Bash
Executable File

#!/bin/sh -efu
#
# Copyright (C) 2008, 2011 Alexey Tourbin <at@altlinux.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
. @RPMCONFIGDIR@/functions
. @RPMCONFIGDIR@/find-package
. @RPMCONFIGDIR@/tmpdir.sh
[ -n "${RPM_LIBDIR-}" ] || RPM_LIBDIR=`rpm --eval %_libdir`
PKG_CONFIG_PATH=$RPM_LIBDIR/pkgconfig:/usr/share/pkgconfig
[ -z "${RPM_BUILD_ROOT-}" ] ||
PKG_CONFIG_PATH=$RPM_BUILD_ROOT$RPM_LIBDIR/pkgconfig:$RPM_BUILD_ROOT/usr/share/pkgconfig:$PKG_CONFIG_PATH
export PKG_CONFIG_PATH
PkgconfigCflags()
{
local f="$1"; shift
local pc_files
pc_files=$(PackagedFiles "$f" |egrep "^$RPM_LIBDIR/pkgconfig/[^/]+[.]pc\$" || [ $? = 1 ])
if [ -n "${RPM_BUILD_ROOT-}" ]; then
pc_files=$(
echo "$pc_files" |sed "s|^/|0 $RPM_BUILD_ROOT/|"
set +f; ls "$RPM_BUILD_ROOT$RPM_LIBDIR/pkgconfig"/*.pc 2>/dev/null |sed 's|^/|1 /|')
pc_files=$(echo "$pc_files" |sort -u -k2 |sort -n |cut -d' ' -f2-)
Debug "pc_files:" $pc_files
fi
local pc
for pc in $pc_files; do
pkg-config --enable-recursion --cflags "$pc" ||
Fatal "$pc: pkg-config failed"
done
}
Cflags()
{
local f="$1"; shift
local cflags
cflags=$(PkgconfigCflags "$f")
set -- $cflags -I/usr/include -I${f%/*} -I${f%/*/*} -I${f%/*/*/*}
local cf
for cf; do
case $cf in
-D?*) echo $cf ;;
esac
done
for cf; do
[ -n "${RPM_BUILD_ROOT-}" ] || continue
case $cf in
-I/*) echo -I$RPM_BUILD_ROOT${cf#-I} ;;
esac
done
for cf; do
case $cf in
-I/*) echo $cf ;;
esac
done
}
gcc=
cpp=
cxx=
CppReq()
{
local f="$1"; shift
local srpm="${RPM_PACKAGE_NAME-}"
[ -n "$srpm" ] || srpm=$(rpmquery --qf='%{SOURCERPM}' -f "$f" 2>/dev/null) || srpm=foo
case "$srpm" in
gcc | gcc-[345]* | gcc[345]* )
[ -n "$gcc" ] ||
Verbose "$f: $PROG disabled for gcc"
gcc=$srpm
return 0 ;;
esac
if [ -z "$cpp" ]; then
cpp=/usr/bin/${RPM_ARCH:-noarch}-alt-linux-cpp
[ -x "$cpp" ] || cpp=/usr/bin/cpp
[ -z "${GCC_VERSION-}" ] || cpp=$cpp-$GCC_VERSION
Debug "cpp=$cpp"
fi
cflags=$(Cflags "$f")
Debug "$f: cflags:" $cflags
if ! out=$("$cpp" -w $cxx $cflags "$f"); then
if [ -n "$cxx" ]; then
Warning "$f: cpp failed"
return 0
fi
Info "$f: cpp failed, trying c++ mode"
cxx='-x c++'
if ! out=$("$cpp" -w $cxx $cflags "$f"); then
cxx=
Warning "$f: cpp failed"
return 0
fi
fi
out=$(echo "$out" |sed -n '/^#.* "\//{s/"//g;p}')
# Prepare the list of files in cpp output which are packaged in this supbackage.
echo "$out" |cut -d' ' -f3 |
xargs -r --delimiter='\n' stat -c '%d,%i %n' |
sort -u >$tmpdir/out.f2i
PackagedFiles "$f" |sed "s|^|${RPM_BUILD_ROOT-}|" |
xargs -r --delimiter='\n' stat -c '%d,%i %n' |
sort -u >$tmpdir/pkg.f2i
join -o 1.2 $tmpdir/{out,pkg}.f2i >$tmpdir/pf
echo "$out" |awk -v prog="$PROG" -v hdr="$f" -v pf="$tmpdir"/pf '
# info cpp "Preprocessor Output"
BEGIN {
SP = 0
SPmark = 0
Stack[SP] = hdr
while ((getline <pf) > 0)
Packaged[$1] = 1
}
function Push(f) {
if (SPmark == SP && !Printed[f]++)
print f
if (SPmark == SP && Packaged[f])
SPmark++
Stack[++SP] = f
}
function Pop(f) {
if (f != Stack[--SP])
printf "%s: %s: expected pop %s, got pop %s\n",
prog, hdr, Stack[SP], f >"/dev/stderr"
if (SPmark > SP)
SPmark = SP
}
$4==1 { Push($3) }
$4==2 { Pop($3) }
END {
if (SP > 0)
printf "%s: %s: non-empty stack, top %s\n",
prog, hdr, Stack[SP] >"/dev/stderr"
}' |
while read -r h; do
RPM_FINDPACKAGE_HOST_PKG_NAMES=1
FindPackage "$f" "${h#${RPM_BUILD_ROOT-}}"
done
}
ArgvFileAction CppReq "$@"