diff options
Diffstat (limited to 'sbopkglint.d/95-pkgconfig.t.sh')
-rw-r--r-- | sbopkglint.d/95-pkgconfig.t.sh | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/sbopkglint.d/95-pkgconfig.t.sh b/sbopkglint.d/95-pkgconfig.t.sh new file mode 100644 index 0000000..64156bb --- /dev/null +++ b/sbopkglint.d/95-pkgconfig.t.sh @@ -0,0 +1,159 @@ +#!/bin/sh + +# sbopkglint test, must be sourced by sbopkglint (not run standalone). + +# PKG, PRGNAM, VERSION, ARCH are set by sbopkglint. also the current +# directory is the root of the installed package tree. + +####################################################################### +# Test .pc (pkgconfig) files. +# - pkgconfig dir must match ARCH (lib vs. lib64). +# - pkg-config must be able to read and parse each file. +# - paths mentioned in the file must exist in the package. +# - for a 32-bit package, libdir must not be /usr/lib64. +# - for a 64-bit package, libdir must not be /usr/lib. +# - .pc files must be either ASCII or Unicode/UTF-8. + +# note: quite a few .pc files don't use the standard variables like +# libdir. it's not required, so we can't just check for that. have to +# actually run pkg-config --cflags and --libs... but we have to +# rip any 'Requires:' line out first, because otherwise, pkg-config +# would pull in the flags/libs from any package mentioned there (if +# installed), or else complain that it doesn't exist. + +check_libinc_dir() { + local type=$1 + local flag=$2 + local file=$3 + local dir + + #echo "===> $flag" + + dir="$( printf "%s" $flag | tail -c+3 )" + [ -d $PKG/$dir ] || warn "$file references $type dir $dir, but it's missing from the package" +} + +check_pc_file() { + local file="$1" + local tmpfile="./$1.tmp.pc" + local mime + local s + + ## echo "===> checking $file" + + if [ ! -f "$file" ]; then + warn "$file is not a regular file:" + ls -ld "$file" + return + fi + + s="$( stat -L -c '%a %U %G' "$file" )" + case "$s" in + "444 root root"|"644 root root") ;; # OK + *) + warn "$file has bad ownership/permissions (should be 0644, root/root)" + ls -ld $file + ;; + esac + + if [ "$s" = "444 root root" ]; then + : # we could warn here someday + elif [ "$s" != "644 root root" ]; then + BADPERMS+="$f " + fi + + + mime="$(file -bL --mime $file)" + + case "$mime" in + text/plain*) + case "$mime" in + *charset=us-ascii|*charset=utf-8) ;; # OK + *) warn "$file has bad character encoding '$( echo "$mime" | sed 's,.*charset=,,' )' (should be us-ascii or utf-8)" + ;; + esac + ;; + *) warn "$file is '$mime', not plain text (are you sure it's a .pc file?)" + ;; + esac + + case "$file" in + *.pc) ;; # OK + *) warn "$file is not a .pc file" ; return ;; + esac + + if ! pkg-config --validate $file; then + warn "$file is not a valid .pc file" + return + fi + + grep -v '^Requires:' $file > $tmpfile + + # the environment stuff keeps pkg-config from stripping out + # -L/usr/lib or -L/usr/lib64 on the grounds that it's a system dir. + for flag in xxx \ + $( env PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 \ + PKG_CONFIG_SYSTEM_LIBRARY_PATH=1 \ + pkg-config --short-errors --libs --cflags $tmpfile ) + do + ## echo "===> $flag" + case $flag in + xxx) ;; # skip (it's just there in case there are no flags at all) + -L/usr/$bad) + warn "$file has /usr/$bad for libdir, should be /usr/$good" + ;; + -L*) check_libinc_dir library "$flag" "$file" + ;; + -I*) check_libinc_dir include "$flag" "$file" + ;; + *) ;; # skip any other flags (-lwhatever, -Dwhatever, etc) + esac + done + + rm -f $tmpfile +} + +check_pc_dir() { + local file + local dir=$1 + + if [ ! -d $dir ]; then + warn "$dir exists but is not a directory!" + return + fi + + # cumbersome way to check if a dir is empty + if [ "$( find $dir -maxdepth 0 -empty )" != "" ]; then + return + fi + + for file in $dir/*; do + check_pc_file $file + done +} + +check_pkgconfig() { + local good bad bits dir + + if [ "$ARCH" = "x86_64" -o "$ARCH" = "aarch64" ]; then + good=lib64; bad=lib; bits=64 + else + good=lib; bad=lib64; bits=32 + fi + + gooddir=usr/$good/pkgconfig + baddir=usr/$bad/pkgconfig + if [ -d $baddir ]; then + if [ -d $gooddir ]; then + warn "$bits-bit package has both $baddir (wrong) and $gooddir (OK)" + else + warn "$bits-bit package has $baddir, should be $gooddir" + fi + fi + + for dir in $baddir $gooddir usr/share/pkgconfig; do + [ -d $dir ] && check_pc_dir $dir + done +} + +check_pkgconfig |