aboutsummaryrefslogtreecommitdiff
path: root/sbopkglint.d/95-pkgconfig.t.sh
blob: 64156bb37d50af722d1d6645b3f4c507cd6a9adc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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