blob: 6f38a980c623399a8aa01a012d67977377fd2b7a [file] [edit]
#! /bin/sh
# Script to test a directory listing. We use this to verify that the list of
# files installed by Autoconf, CMake, or Meson matches what we expect.
set -e
# Ensure stable ordering of `sort` output
LANG=C
LC_ALL=C
export LANG LC_ALL
if [ "$#" -lt 3 ] || [ "$#" -gt 4 ]; then
echo "Usage: $0 <dir> <manifest name> <producer> [<build type>]" >&2
exit 1
fi
input_dir="$1"
expected_manifest="$2"
producer="$3"
build_type="${4:-release}"
die()
{
echo "$*" >&2
exit 1
}
case "$producer" in
autoconf|cmake|meson|tarball) ;;
*)
die "Unknown producer: $producer (expected autoconf, cmake, meson, or tarball)"
;;
esac
actual_file=`basename "$expected_manifest"`.actual
expected_file=`basename "$expected_manifest"`.expected
expected_temp="$expected_file.$$"
trap 'rm -f "$expected_temp"' 0 1 2 15
sed=sed
# Solaris' native sed does not support all the expressions used below.
if [ -f /usr/bin/gsed ]; then
sed=/usr/bin/gsed
fi
# Compare relative to the installed prefix, independently of DESTDIR staging.
# For example, an Autoconf install staged at install-dir/usr/local must have
# the same manifest paths as a CMake or Meson install at install-dir.
read -r root_mode root_path < "$expected_manifest"
(
cd "$input_dir"
find . -print | \
sort | \
while IFS= read -r path; do
ls -l -d -n "$path"
done | \
"$sed" -e 's/ */ /g' -e 's/^\(..........\). /\1 /' | \
cut -d' ' -f '1,9-' | \
"$sed" -e "s@^\([^ ]* \)\.@\1$root_path@"
) > "$actual_file"
transform_expected()
{
"$sed" "$@" "$expected_file" > "$expected_temp"
mv "$expected_temp" "$expected_file"
}
library_tuple()
{
library="$1"
tuple=$("$sed" -n "s/^m4_define(libpcre2_${library}_version,[[:space:]]*\[\([^]]*\)\]).*/\1/p" "$configure_ac")
[ -n "$tuple" ] || die "Missing libpcre2_${library}_version in $configure_ac"
case "$tuple" in
*'
'*) die "Duplicate libpcre2_${library}_version in $configure_ac" ;;
esac
printf '%s\n' "$tuple"
}
library_filename_versions()
{
original_tuple="$1"
tuple=$(printf '%s\n' "$original_tuple" | "$sed" 's/[[:space:]]//g')
IFS=: read -r current revision age extra <<EOF
$tuple
EOF
[ -z "$extra" ] || die "Invalid libtool version: $original_tuple"
for component in "$current" "$revision" "$age"; do
case "$component" in
''|*[!0123456789]*) die "Invalid libtool version: $original_tuple" ;;
esac
done
soname=$((current - age))
printf '%s %s\n' "$soname.$age.$revision" "$soname"
}
cp "$expected_manifest" "$expected_file"
if [ "$producer" != "tarball" ]; then
# The common install manifests include both CMake and libtool metadata. Adjust
# only the expected listing: unexpected installed files must still fail the
# check, even if another build system would legitimately install them.
if [ "$producer" != "cmake" ]; then
# Only CMake installs find_package(CONFIG) metadata and exported targets.
# Autoconf and Meson provide pkg-config metadata, but not these CMake files.
transform_expected \
-e '/\/lib\/cmake$/d' \
-e '/\/lib\/cmake\/pcre2$/d' \
-e '/\/lib\/cmake\/pcre2\/pcre2-config\.cmake$/d' \
-e '/\/lib\/cmake\/pcre2\/pcre2-config-version\.cmake$/d' \
-e '/\/lib\/cmake\/pcre2\/pcre2-targets\.cmake$/d' \
-e '/\/lib\/cmake\/pcre2\/pcre2-targets-@CMAKE_BUILD@\.cmake$/d'
# The manifests use CMake's native ELF shared-library modes, which can be
# 0644. Autoconf and Meson install the real .so files as 0755 instead.
transform_expected \
-e '/\/libpcre2-[^/]*\.so\.@LIB_[^@]*_VERSION@$/s/^-rw-r--r-- /-rwxr-xr-x /'
fi
if [ "$producer" != "autoconf" ]; then
# Only Autoconf's libtool build installs .la archives containing link metadata.
transform_expected -e '/\/lib\/libpcre2-[^/]*\.la$/d'
fi
if [ "$producer" = "meson" ]; then
# On macOS, Meson installs a real major-version dylib instead of the
# full-version dylib and its major-version symlink.
transform_expected \
-e '/^l[^ ]* .*\/libpcre2-[^/]*\.@LIB_[^@]*_SONAME@\.dylib -> /d' \
-e '/^-[^ ]* .*\/libpcre2-[^/]*\.@LIB_[^@]*_VERSION@\.dylib$/s/_VERSION@\.dylib$/_SONAME@.dylib/'
fi
# CMake's configuration name is lower-case in its exported target filename.
transform_expected -e "s/@CMAKE_BUILD@/$build_type/g"
if [ "$producer" = "autoconf" ]; then
unversioned_target=VERSION
else
unversioned_target=SONAME
fi
transform_expected -e "s/_UNVERSIONED_TARGET@/_${unversioned_target}@/g"
manifest_dir=$(dirname "$expected_manifest")
configure_ac="$manifest_dir/../configure.ac"
[ -f "$configure_ac" ] || die "Missing configure.ac: $configure_ac"
for library in 8 16 32 posix; do
case "$library" in
posix) placeholder_library=POSIX ;;
*) placeholder_library="$library" ;;
esac
version_values=$(library_filename_versions "$(library_tuple "$library")")
set -- $version_values
library_version="$1"
library_soname="$2"
transform_expected \
-e "s/@LIB_${placeholder_library}_VERSION@/$library_version/g" \
-e "s/@LIB_${placeholder_library}_SONAME@/$library_soname/g"
done
if "$sed" -n '/@LIB_/p; /@CMAKE_BUILD@/p' "$expected_file" | grep . >/dev/null; then
die "Unexpanded placeholders in $expected_file"
fi
fi
if ! diff -u "$expected_file" "$actual_file"; then
echo "Installed files differ from expected"
echo "===Actual==="
cat "$actual_file"
echo "===End==="
exit 1
fi
echo "Installed files match expected"
rm -f "$actual_file" "$expected_file"