Blame test-symbols-compat

Packit 13e0ca
#! /bin/sh
Packit 13e0ca
# Written by Zack Weinberg <zackw at panix.com> in 2017.
Packit 13e0ca
# To the extent possible under law, Zack Weinberg has waived all
Packit 13e0ca
# copyright and related or neighboring rights to this work.
Packit 13e0ca
#
Packit 13e0ca
# See https://creativecommons.org/publicdomain/zero/1.0/ for further
Packit 13e0ca
# details.
Packit 13e0ca
Packit 13e0ca
# This test is only run if we are building a shared library intended
Packit 13e0ca
# to be binary backward compatible with GNU libc (libcrypt.so.1).
Packit 13e0ca
# It locates any installed version of libcrypt.so.1, and verifies that
Packit 13e0ca
# each public symbol exposed by that library is also exposed by our
Packit 13e0ca
# libcrypt.so.1 with a matching symbol version.
Packit 13e0ca
#
Packit 13e0ca
# Due to limitations in Automake, this program takes parameters from
Packit 13e0ca
# the environment:
Packit 13e0ca
# $lib_la - full pathname of libcrypt.la
Packit 13e0ca
Packit 13e0ca
set -e
Packit 13e0ca
LC_ALL=C; export LC_ALL
Packit 13e0ca
Packit 13e0ca
get_symbols_with_versions ()
Packit 13e0ca
{
Packit 13e0ca
    nm -gD --with-symbol-versions "$1" |
Packit 13e0ca
        grep -v ' U ' | cut -d' ' -f3 |
Packit 13e0ca
        sed -e 's/@@*/ /; /^\([A-Z0-9_.]*\) \1$/d' |
Packit 13e0ca
        sort -u
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
get_our_symbols_with_versions ()
Packit 13e0ca
{
Packit 13e0ca
    eval $(grep dlname= "$1")
Packit 13e0ca
    get_symbols_with_versions "${1%/*}/.libs/${dlname}"
Packit 13e0ca
    unset dlname
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
get_their_symbols_with_versions ()
Packit 13e0ca
{
Packit 13e0ca
    (
Packit 13e0ca
        set -e
Packit 13e0ca
        cd "$1"
Packit 13e0ca
        cat >test.c <<\EOF
Packit 13e0ca
extern char *crypt(const char *, const char *);
Packit 13e0ca
int main(int argc, char **argv)
Packit 13e0ca
{
Packit 13e0ca
  return !!crypt(argv[0], argv[1]);
Packit 13e0ca
}
Packit 13e0ca
EOF
Packit 13e0ca
        ${CC-cc} test.c -lcrypt >&2 || exit 77
Packit 13e0ca
        if ldd ./a.out | grep -qF libcrypt.so.1; then
Packit 13e0ca
            get_symbols_with_versions $(ldd ./a.out | grep -F libcrypt.so.1 |
Packit 13e0ca
                                            cut -d' ' -f3)
Packit 13e0ca
        else
Packit 13e0ca
            exit 77
Packit 13e0ca
        fi
Packit 13e0ca
    )
Packit 13e0ca
    if [ $? -ne 0 ]; then exit $?; fi
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
if [ ! -f "$lib_la" ]; then
Packit 13e0ca
    echo "Usage: lib_la=/path/to/library.la $0" >&2
Packit 13e0ca
    exit 1
Packit 13e0ca
fi
Packit 13e0ca
Packit 13e0ca
# If 'nm' and/or 'ldd' are not available, this test will not work.
Packit 13e0ca
command -v nm > /dev/null 2>&1 || {
Packit 13e0ca
    echo "Error: 'nm' is unavailable" >&2
Packit 13e0ca
    exit 77
Packit 13e0ca
}
Packit 13e0ca
command -v ldd > /dev/null 2>&1 || {
Packit 13e0ca
    echo "Error: 'ldd' is unavailable" >&2
Packit 13e0ca
    exit 77
Packit 13e0ca
}
Packit 13e0ca
Packit 13e0ca
workdir=""
Packit 13e0ca
trap '[ -z "$workdir" ] || rm -rf "$workdir" || :' 0
Packit 13e0ca
workdir="$(mktemp -d)"
Packit 13e0ca
Packit 13e0ca
get_our_symbols_with_versions "$lib_la" > "$workdir/our_symbols"
Packit 13e0ca
get_their_symbols_with_versions "$workdir" > "$workdir/their_symbols"
Packit 13e0ca
Packit 13e0ca
# It's okay if we define more symbol (versions) than they do, but every
Packit 13e0ca
# symbol they define should have a matching definition in our library.
Packit 13e0ca
missing_symbols="$(comm -13 "$workdir/our_symbols" "$workdir/their_symbols")"
Packit 13e0ca
if [ -n "$missing_symbols" ]; then
Packit 13e0ca
    printf '*** Missing symbols: %s\n' "$missing_symbols" >&2
Packit 13e0ca
    exit 1
Packit 13e0ca
fi
Packit 13e0ca
exit 0