Print a warning to stderr instead of generating invalid deps containing
[mono.git] / scripts / mono-find-requires.in
1 #!/bin/bash
2 #
3 # mono-find-requires
4 #
5 # Authors:
6 #       Ben Maurer (bmaurer@ximian.com)
7 #       Wade Berrier (wberrier@novell.com)
8 #
9 # (C) 2008 Novell (http://www.novell.com)
10 #
11
12 IFS=$'\n'
13 filelist=($(grep -Ev '/usr/doc/|/usr/share/doc/'))
14 monolist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.(exe|dll)\$"))
15
16 # parse .config files to find which native libraries to depend on 
17 #  (target attribute must have double quotes for this to work, ie: target="file" )
18 # Add /etc/mono/config ?
19 configlist=($(printf "%s\n" "${filelist[@]}" | egrep "\\.config\$"))
20
21 # Set the prefix, unless it is overriden (used when building mono rpms)
22 : ${prefix=@prefix@}
23
24 libdir=$prefix/@reloc_libdir@
25 bindir=$prefix/bin
26
27 # Bail out if monodis or libmono is missing
28 if [ ! -x $bindir/monodis ] || [ ! -f $libdir/libmono.so ] ; then
29         echo "monodis missing or unusable, exiting..." 1>&2
30         exit 1
31 fi
32
33 # special case for 64bit archs
34 if test "x@reloc_libdir@" = "xlib64" ; then
35         libext="()(64bit)"
36 else
37         # (note, this works on ppc64 since we only have 32bit mono)
38         libext=""
39 fi
40
41 # Exceptions:
42 case `uname -m` in
43         # ia64 doesn't use lib64 for 'libdir' (sles 9 rpm used to provide both... no longer)
44         ia64)   libext="()(64bit)" ;;
45 esac
46
47 # set LD_LIBRARY_PATH to ensure that libmono.so is found
48 export LD_LIBRARY_PATH=$libdir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
49
50 REQUIRES=$(
51         for i in "${monolist[@]}"; do
52                 ($bindir/monodis --assemblyref $i | awk '
53                         BEGIN { START=0; LIBNAME=""; VERSION=""; }
54                         (START==0) && /^[0-9]+: Version=/ {
55                                 START=1;
56                                 sub(/Version=/, "", $2);
57                                 VERSION=$2
58                         }
59
60                         (START==1) && /^\tName=/ {
61                                 sub(/Name=/, "", $1);
62                                 LIBNAME=$1
63                                 # Allow rpm deps to be resolved for 1.0 profile version
64                                 if (VERSION=="1.0.3300.0")
65                                         OP=">="
66                                 else
67                                         OP="="
68                                 print "mono(" LIBNAME ") " OP " " VERSION
69                                 START=0
70                         }
71                     ') 2> /dev/null
72         done
73 )
74
75 rpm_config_REQUIRES=$(
76         # Parse the xml .config files to see what native binaries we call into
77         # TODO: also check monodis --moduleref
78         for i in "${configlist[@]}"; do
79                 awk 'match($_, /<dllmap .*target=.*/) {
80                         ignore=0
81                         req=""
82                         split($_, toks, "\"")
83                         toks_size=0
84                         for(tok in toks) { toks_size++ }
85                         for(i=1; i <= toks_size; i++) {
86                                 if(toks[i] ~ /target=/) {
87                                         req=toks[i+1]
88                                 }
89                                 if(toks[i] ~ /os=/) {
90                                         negate=0
91                                         found=0
92
93                                         attr=toks[i+1]
94                                         if(attr ~ /^!/) {
95                                                 attr=substr(attr, 2, length(attr)-1)
96                                                 negate=1
97                                         }
98
99                                         split(attr, os_targets, ",")
100                                         os_targets_size=0
101                                         for(os_target in os_targets) { os_targets_size++ }
102                                         for(j=1; j <= os_targets_size; j++) {
103                                                 if(os_targets[j] == "linux") {
104                                                         found=1
105                                                 }
106                                         }
107
108                                         if(negate) {
109                                                 found=!found
110                                         }
111                                         if (!found) {
112                                                 ignore=1
113                                         } 
114                                 }
115                         }
116                         if(!ignore) {
117                                 print req"'$libext'"
118                         }
119                 } ' $i 2>/dev/null
120         done
121 )
122
123 # Resolve provides to packages, warning on missing to stderr
124 config_REQUIRES=$(
125         for i in ${rpm_config_REQUIRES[@]} ; do
126                 out=$(rpm -q --whatprovides --queryformat "%{NAME}\n" $i)
127                 if [ $? -eq 0 ] ; then
128                         echo $out
129                 else
130                         # echo to stderr
131                         echo "mono-find-requires: Warning, could not find package that provides: $i" >&2
132                 fi
133         done
134 )
135
136 # Note about above:
137 #  Use to do: system("rpm -q --whatprovides --queryformat \"%{NAME}\n\" ""\""req"'$libext'""\"")
138 #  rpmlint prefers to have lib names instead of package names.  There was a reason I was using package names but it slips me now...
139 #  Ah... now I remember... it's for noarch packs.  The noarch packages can be built on either 32 or 64 bit... so we have to depend
140 #   on the package name instead.
141
142 PROVIDES=$(
143         for i in "${monolist[@]}"; do
144                 ($bindir/monodis --assembly $i | awk '
145                         BEGIN { LIBNAME=""; VERSION=""; }
146                         /^Version:/ { VERSION=$2 }
147                         /^Name:/    { LIBNAME=$2 }
148                         END {
149                                 if (VERSION && LIBNAME)
150                                         print "mono(" LIBNAME ") = " VERSION
151                         }
152                     ') 2>/dev/null
153         done
154 )
155 #
156 # This is a little magic trick to get all REQUIRES that are not
157 # in PROVIDES. While RPM functions correctly when such deps exist,
158 # they make the metadata a bit bloated.
159 #
160 # TODO: make this use the mono-find-provides script, to share code
161
162 # Filter out dups from both lists
163 REQUIRES=$(echo "$REQUIRES" "$config_REQUIRES"  | sort | uniq)
164 PROVIDES=$(echo "$PROVIDES" | sort | uniq)
165
166 #
167 # Get a list of elements that exist in exactly one of PROVIDES or REQUIRES
168 #
169 UNIQ=$(echo "$PROVIDES
170 $REQUIRES" | sort | uniq -u)
171
172 #
173 # Of those, only choose the ones that are in REQUIRES
174 #
175 echo "$UNIQ
176 $REQUIRES" | sort | uniq -d