Blob Blame Raw
#! /bin/sh

# Replace the multilib-unclean header file with multilib-clean stub, while the
# original file is moved to unique architecture-specific location.
#
# The solution is taken from Fedora PostgreSQL RPM package.
#
# Pavel Raiskup <praiskup@redhat.com>
#
# This file is to be moved into redhat-rpm-config (or something like this).

progname=$(basename "$0")

opt_arch=$(uname -i)
# See rhbz#1242873 for more info.
test "$opt_arch" = ppc64p7 && opt_arch=ppc64

opt_destdir=
opt_basename=
opt_buildroot=$(pwd)
opt_verbose=:
opt_additional_suffix=

# TODO: we could pretty easily implement other then 'cpp-header' stubs, if the
# target file type allows some kind of "transparent" file inclusion.  For
# example shell scripts might use '. "${opt_destdir}/${opt_basename}_x86_64.sh'.
print_stub ()
{
cat <<EOF
/*
 * Kluge to support multilib installation of both 32- and 64-bit RPMS:
 * we need to arrange that header files that appear in both RPMs are
 * identical.  Hence, this file is architecture-independent and calls
 * in an arch-dependent file that will appear in just one RPM.
 *
 * To avoid breaking arches not explicitly supported by Red Hat, we
 * use this indirection file *only* on known multilib arches.
 *
 * Note: this may well fail if user tries to use gcc's -I- option.
 * But that option is deprecated anyway.
 */
#if defined(__x86_64__)
#include "${opt_basename}${opt_additional_suffix}_x86_64.h"
#elif defined(__i386__)
#include "${opt_basename}${opt_additional_suffix}_i386.h"
#elif defined(__ppc64__) || defined(__powerpc64__)
#include "${opt_basename}${opt_additional_suffix}_ppc64.h"
#elif defined(__ppc__) || defined(__powerpc__)
#include "${opt_basename}${opt_additional_suffix}_ppc.h"
#elif defined(__s390x__)
#include "${opt_basename}${opt_additional_suffix}_s390x.h"
#elif defined(__s390__)
#include "${opt_basename}${opt_additional_suffix}_s390.h"
#elif defined(__sparc__) && defined(__arch64__)
#include "${opt_basename}${opt_additional_suffix}_sparc64.h"
#elif defined(__sparc__)
#include "${opt_basename}${opt_additional_suffix}_sparc.h"
#endif
EOF
}

print_help ()
{
    _h_exit=false
    test -n "$1" && _h_exit=:

    cat <<EOF
Usage: $progname [OPTIONS]

Replace the multilib-unclean header file with multilib-clean stub, while the
original file is moved to unique architecture-specific location.  This should be
absolutely safe operation (effects of '#include <HEADER.h>' are unchanged.

To allow us to do incompatible changes in this script, packagers should use this
script only through %ml_fix_c_header wrapping macro.

--destdir       absolute path name where the old header file is stored, e.g.
                /some/pat
--basename      when you deal with '/some/path/test.h', specify 'test'
--buildroot     prefix (directory where we play with installed files, usually
                after 'make install DESTDIR=buildroot')
--additional-suffix     we usually move 'test.h' to 'test_\$ARCH.h'.  However
                this file could already exit.  With this option the multilib
                file will be named 'test_\$ARCH\$SUFFIX.h'
--verbose       print some useful information
--help          show this help
EOF

    $_h_exit && exit "$1"
}

verbose ()
{
    $opt_verbose && echo "INFO: $progname: $*"
}

die ()
{
    echo >&2 " # $*"
    print_help 1
}

error ()
{
    error_occurred=:
    echo >&2 " ! $*"
}

error_occurred=false

while test $# -gt 0
do
    _opt=$1 ; shift
    case $_opt in
        --destdir)
            opt_destdir=$1 ; shift || die "$_opt requires argument"
            ;;
        --basename)
            opt_basename=$1 ; shift || die "$_opt require argument"
            ;;
        --buildroot)
            opt_buildroot=$1 ; shift || die "$_opt require argument"
            ;;
        --arch)
            opt_arch=$1 ; shift || die "$_opt require argument"
            ;;
        --additional-suffix)
            opt_additional_suffix=$1 ; shift || die "$_opt require argument"
            ;;
        --help)
            print_help 0
            ;;
        *)
            error "unexpected '$_opt' program argument"
            ;;
    esac
done
$error_occurred && print_help 1

for i in arch buildroot destdir basename
do
    eval "test -z \"\$opt_$i\"" && error "--$i needs to be set"
done
$error_occurred && print_help 1

original_file="$opt_buildroot$opt_destdir/$opt_basename".h
multilib_file="$opt_buildroot$opt_destdir/$opt_basename${opt_additional_suffix}_$opt_arch".h

test -f "$original_file" || die "can't find '$original_file'"

case $opt_arch in
  # we only apply this to known Red Hat multilib arches, per bug #177564
  i386|x86_64|ppc|ppc64|s390|s390x|sparc|sparc64)
      ;;
  *)
      verbose "we don't need multilib haeder hack for '$opt_arch' architecture (no-op)"
      exit 0
      ;;
esac

verbose "moving: '$original_file' to '$multilib_file'"

mv "$original_file" "$multilib_file" || exit 1
if print_stub > "$original_file" && chmod 644 "$original_file"; then
    :
else
    die "can't write into '$original_file'"
fi

: