#!/bin/bash

# Check dependencies required by libtool to use .la files.
#
# Copyright (C) 2005 Stanislav Brabec <sbrabec@suse.cz>, SuSE CR
#
# 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.
#
# See http://www.gnu.org/copyleft/lesser.html
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

RC=0
WARN=0

# Set default PKG_CONFIG_PATH, if not defined.
if test -d $BUILD_ROOT/usr/lib64 ; then
    BUILD_LD_LIBRARY_PATH=/lib64:/usr/lib64
else
    BUILD_LD_LIBRARY_PATH=/lib:/usr/lib
fi

shopt -s nullglob
for DIR in $BUILD_ROOT/usr/lib*/gcc-lib/*/* $BUILD_ROOT/usr/lib*/gcc/*/* ; do
    BUILD_LD_LIBRARY_PATH=$BUILD_LD_LIBRARY_PATH:${DIR#$BUILD_ROOT}
done

function get_ld_library_path {
    local FILE
    local -a INCLUDES
    for FILE in $@ ; do
	if ! test -r $BUILD_ROOT$FILE ; then
	    continue
	fi
	exec 3<$BUILD_ROOT$FILE
	while read -u3 ; do
	    if test "$REPLY" = "${REPLY#include}" ; then
		BUILD_LD_LIBRARY_PATH="$BUILD_LD_LIBRARY_PATH $REPLY"
	    else
		INCLUDES[${#INCLUDES[@]}]=${REPLY#include}
	    fi
	done
	exec 3<&-
    done
    for FILE in ${INCLUDES[@]} ; do
	eval get_ld_library_path $FILE
    done
}
get_ld_library_path /etc/ld.so.conf

BUILD_LD_LIBRARY_PATH="$BUILD_LD_LIBRARY_PATH $(unset LD_LIBRARY_PATH ; for FILE in $BUILD_ROOT/etc/profile.d/*.sh ; do echo $FILE ; source $FILE ; done >/dev/null 2>&1 ; echo $LD_LIBRARY_PATH)"

# Assign file to RPM package.
# assign_rpm file
function assign_rpm {
    ASSIGN_RPM=$(chroot $BUILD_ROOT rpm --queryformat '%{NAME}\n' -qf $1)
}

# Prepare for rpm_find_all_deps and clean after rpm_find_all_deps.
# rpm_find_all_deps_reset
function rpm_find_all_deps_reset {
    unset DUMMY ${!rpmsym_*}
    rm -f $BUILD_ROOT/tmp/all-requires $BUILD_ROOT/tmp/all-deps
}

# List all dependent packages exploring only explicit dependencies.
# rpm_find_all_deps package_name >$BUILD_ROOT/tmp/all-deps
function rpm_find_all_deps {
    local -a SYMBOLS
    local SYMBOL
    SYMBOL_NAME=${1//_/_U_}
    SYMBOL_NAME=${SYMBOL_NAME//-/_H_}
    SYMBOL_NAME=${SYMBOL_NAME//./_D_}
    SYMBOL_NAME=${SYMBOL_NAME//\//_S_}
    SYMBOL_NAME=${SYMBOL_NAME//(/_OB_}
    SYMBOL_NAME=${SYMBOL_NAME//)/_CB_}
    SYMBOL_NAME=${SYMBOL_NAME//[^A-Za-z0-9]/_X_}
    SYMBOL_NAME=know_$SYMBOL_NAME
    eval "known=\$$SYMBOL_NAME"
    if test -z "$known"; then
        # the double quotes are necessary to retain the line endings
        known="$(chroot $BUILD_ROOT rpm -q --requires $1 2>/dev/null)"
        if test $? -gt 0 ; then
	    known=nonrpm
        fi
	eval "$SYMBOL_NAME=\"$known\""
    fi
    if test "$known" = "nonrpm"; then
        return
    fi
    echo $1
    while read ; do
	SYMBOL=${REPLY%% *}
	SYMBOL_NAME=${SYMBOL//_/_U_}
	SYMBOL_NAME=${SYMBOL_NAME//-/_H_}
	SYMBOL_NAME=${SYMBOL_NAME//./_D_}
	SYMBOL_NAME=${SYMBOL_NAME//\//_S_}
	SYMBOL_NAME=${SYMBOL_NAME//(/_OB_}
	SYMBOL_NAME=${SYMBOL_NAME//)/_CB_}
	SYMBOL_NAME=${SYMBOL_NAME//[^A-Za-z0-9]/_X_}
	SYMBOL_NAME=rpmsym_$SYMBOL_NAME
	eval "if test -z \"\$$SYMBOL_NAME\" ; then
	    SYMBOLS[${#SYMBOLS[@]}]='$SYMBOL'
	fi"
	eval "$SYMBOL_NAME=1"
    done <<<"$known"
    for SYMBOL in ${SYMBOLS[@]} ; do
	rpm_find_all_deps $SYMBOL
    done
}

# Check requirements of RPM package.
# check_rpm_requires rpm
function check_rpm_requires {
    PACK=$1
    PACK=${PACK##$BUILD_ROOT}
    : > $BUILD_ROOT/tmp/missings-$ASSIGN_RPM
    LAST_RPM=
    for LA in $(chroot $BUILD_ROOT rpm -qlp $PACK | grep '.*/lib.*/.*\.la$') ; do
	LOCAL_LIBRARY_PATH=$BUILD_LD_LIBRARY_PATH
	assign_rpm $LA
	RPM=$ASSIGN_RPM
	if test "$LAST_RPM" != "$RPM"; then
	    rpm_find_all_deps_reset
	    rpm_find_all_deps $RPM >$BUILD_ROOT/tmp/all-deps
	    LAST_RPM=$RPM
	fi
	test "$(source $BUILD_ROOT$LA; echo $shouldnotlink)" = yes && continue
	for LIB in $(source $BUILD_ROOT$LA ; echo "$dependency_libs") ; do
	    case $LIB in
		-L* )
		    LOCAL_LIBRARY_PATH="$LOCAL_LIBRARY_PATH ${LIB#-L}"
		    continue
		    ;;
		-l* )
		    DEPLIB=
		    for DIR in $LOCAL_LIBRARY_PATH ; do
			if test -f $BUILD_ROOT$DIR/lib${LIB#-l}.so ; then
			    DEPLIB=$DIR/lib${LIB#-l}.so
			    break
			fi
			if test -f $BUILD_ROOT$DIR/lib${LIB#-l}.a ; then
			    DEPLIB=$DIR/lib${LIB#-l}.a
			    break
			fi
		    done
		    if test -z "$DEPLIB" ; then
			echo "Error: Required library ${LIB#-l} not found (required by $LA from $RPM).
Please add proper package to neededforbuild to complete this check."
			RC=1
			continue
		    fi
		    ;;
		*.la )
		    DEPLIB=$LIB
		    ;;
		* )
		    echo "Warning: Unknown argument $LIB in dependency_libs. Please report to sbrabec@suse.cz."
		    ;;
	    esac
	    assign_rpm $DEPLIB
	    # FIXME: Can it happen, that library is not part of any package?
	    if ! grep -q ^$ASSIGN_RPM'\( \|$\)' $BUILD_ROOT/tmp/all-deps ; then
	    	test -f $BUILD_ROOT/tmp/missing-$RPM && grep -q "$ASSIGN_RPM" $BUILD_ROOT/tmp/missing-$RPM && continue
		echo "$ASSIGN_RPM" >> $BUILD_ROOT/tmp/missing-$RPM
		if test "$ASSIGN_RPM" != "$RPM" ; then
		    if test "${RPM#*-devel}" ; then
			echo "Warning: Missing \"Requires: $ASSIGN_RPM\" in dependency chain ($LA from $RPM requires $DEPLIB)."
			WARN=1
		    else
			echo "Error: Missing \"Requires: $ASSIGN_RPM\" in dependency chain ($LA from $RPM requires $DEPLIB)."
			RC=1
		    fi
		fi
	    fi
	done
    done
}

echo "... testing devel dependencies required by libtool .la files"

if fgrep -q skip-check-libtool-deps $BUILD_ROOT/usr/src/packages/SOURCES/$PNAME.spec ; then
    echo "    skipped by \"skip-check-libtool-deps\""
    exit 0
fi
echo "    (can be skipped by \"skip-check-libtool-deps\" anywhere in spec)"

shopt -s nullglob
IFS=$IFS":,"

for RPM in $BUILD_ROOT/usr/src/packages/RPMS/*/*.rpm ; do
    check_rpm_requires $RPM
done
rpm_find_all_deps_reset


if test $RC -gt 0 ; then
    echo "All errors are just warnings for now.
Note that it is possible, that these dependencies are missing in one of dependent packages.
Please find lowest level package and fix."
fi

if test $WARN -gt 0 ; then
    echo "Think about moving all .la (and .a) files to -devel subpackage."
fi

if test $RC -gt 0 -o $WARN -gt 0 ; then
    echo "For .la files of modules, you can think about removing .la files.
If you have problems with check-libtool-deps, please contact sbrabec@suse.cz."

fi

exit 0
exit $RC
