#!/bin/sh

# List the modules required by a particular L4Re program configuration.
#
# Copyright (C) 2018, 2019, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
#
# 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.
#
# 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.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA  02110-1301, USA

MODULES="$1"

if [ ! "$MODULES" ] || [ ! -e "$MODULES" ] ; then
    cat 1>&2 <<EOF
Usage: $0 <module list filename> [ --ignore-missing ] [ <arch> ] [ <build directory> ]

List modules required by the given system/payload configuration. These modules
should be added to the configuration file so that the dynamic linker can find
them in the running system.

The optional build directory indicates where executable programs may be found,
having been built. An initial build must have been performed before running this
program.
EOF
    exit 1
fi

# Skip the module list file.

shift 1

# Get flag.

if [ "$1" ] && [ "$1" = '--ignore-missing' ] ; then
    IGNORE_MISSING="$1"
    shift 1
else
    IGNORE_MISSING=
fi

# Get other options.

ARCHDIR=
BUILDDIR=

# Look for an architecture or build directory.

if [ "$1" ] && [ ! -e "$1" ] ; then
    ARCH="$1"
    shift 1
else
    ARCH=
fi

# Look for any additional build directory.

if [ "$1" ] && [ -e "$1" ] ; then
    BUILDDIR="$1"
fi

# Use a default build directory if none specified or found.

if [ ! "$BUILDDIR" ] ; then
    BUILDDIR=mybuild
fi

if [ ! -e "$BUILDDIR" ] ; then
    cat 1>&2 <<EOF
Not found (build directory): $BUILDDIR
EOF
    exit 1
fi

# Test for architecture-specific program directories.

for FILENAME in "$BUILDDIR/bin/"* ; do
    if [ "$FILENAME" = "$BUILDDIR/bin/*" ] ; then
        cat 1>&2 <<EOF
No architecture-specific directories in the build directory hierarchy:

$BUILDDIR/bin
EOF
        exit 1
    fi

    BASENAME=$(basename "$FILENAME")

    if [ "$BASENAME" = 'host' ] ; then
        :
    elif [ ! "$ARCH" ] || [ "$ARCH" = "$BASENAME" ] ; then
        ARCHDIR="$BASENAME"
        break
    fi
done

# Exit if no architecture resources available.

if [ ! "$ARCHDIR" ] ; then
    cat 1>&2 <<EOF
Architecture not in use or no appropriate program directory found.
Possible architectures are as follows:

EOF
    for FILENAME in "$BUILDDIR/bin/"* ; do
        ARCH=$(basename "$FILENAME")
        if [ "$ARCH" != 'host' ] ; then
            echo "$ARCH"
        fi
    done
    exit 1
fi

# Obtain module details.

BIN="$BUILDDIR/bin/$ARCHDIR/l4f"
TMPLIBS=_libs.txt

echo -n > "$TMPLIBS"

for MODULE in $(grep '^module ' "$MODULES" | sed 's/module //') ; do
    PROG=$(basename "$MODULE" .cfg)
    if [ "$PROG" != "$MODULE" ] ; then
        continue
    fi
    PROG=$(basename "$MODULE" .io)
    if [ "$PROG" != "$MODULE" ] ; then
        continue
    fi
    PROG=$(basename "$MODULE" .so)
    if [ "$PROG" != "$MODULE" ] ; then
        continue
    fi
    PROG=$(basename "$MODULE" .txt)
    if [ "$PROG" != "$MODULE" ] ; then
        continue
    fi
    if [ ! -e "$BIN/$PROG" ] && [ ! "$IGNORE_MISSING" ] ; then
        echo "Not found: $PROG" 1>&2
        rm "$TMPLIBS"
        exit 1
    fi

    # NOTE: Architecture needs fixing.

    mipsel-linux-gnu-readelf -d "$BIN/$PROG" | grep NEEDED | sed 's/.*\[//;s/\]$//' >> "$TMPLIBS"
done

# Explicitly add undetected module.

echo "libl4sys-direct.so" >> "$TMPLIBS"

sort -u "$TMPLIBS" | sed 's/^/module /'
rm "$TMPLIBS"

# vim: tabstop=4 expandtab shiftwidth=4
