mono-find-requires 4.8 KB

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