#!/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