#!/bin/bash

# Check dependencies required by libtool to use .la files.
#
# Copyright (C) 2005 Stanislav Brabec <sbrabec@suse.cz>, SuSE CR
# Copyright (C) 2022 Andreas Stieger <Andreas.Stieger@gmx.de>
#
# 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.

TOPDIR=/usr/src/packages
test -d "$BUILD_ROOT/.build.packages" && TOPDIR=/.build.packages

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
        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
	if eval 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 grep -F -q skip-check-libtool-deps "$BUILD_ROOT"$TOPDIR/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"$TOPDIR/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
