I’m currently building Solaris IPS packages for Some Ruby gems. Yes, I know rubygems does a very good job of keeping everything together. But that does not work so well on backend systems where you don’t have a free internet access and where repeatability is important. So I decided to wrap the gems we need into IPS packages.
The IPS pkg* tools work pretty well when they try to find dependencies between different packages automatically. But so far, they claim to do it only for ELF binaries and Python files. So for Ruby, I would either have to specify dependencies manually (and miss half of them) or try to find a way to inspect the Ruby files as well.
So I tried to get some bash lines together to do what I wanted;-) They will probably not be complete yet!! But so far, they work pretty well. I also found, that the pkgdepend does not really handle the #!/usr/bin/env ruby
code found in some scripts, so I tried to fix that as well.
So for the old Mongrel gem, the following dependencies were automatically created;-) I think that’s pretty complete.
depend fmri=pkg:/my_prefix/ruby/gem/cgi_multipart_eof_fix@2.5.0-0.1 type=require depend fmri=pkg:/my_prefix/ruby/gem/daemons@1.1.6-0.1 type=require depend fmri=pkg:/my_prefix/ruby/gem/fastthread@1.0.7-0.1 type=require depend fmri=pkg:/my_prefix/ruby/gem/gem_plugin@0.2.3-0.1 type=require depend fmri=pkg:/my_prefix/ruby/rubygems@1.6.2-0.1 type=require depend fmri=pkg:/my_prefix/ruby@1.8.7.357-0.1 type=require depend fmri=pkg:/system/library/math@0.5.11-0.174.0.0.0.0.0 type=require depend fmri=pkg:/system/library@0.5.11-0.175.0.2.0.3.1 type=require depend fmri=pkg:/system/linker@0.5.11-0.175.0.2.0.2.1 type=require
Most IPS guides specify to run pkgdepend generate
and then pkgdepend resolve
, the following code would go right in between those two steps.
pkgdepend generate -md $DESTDIR/dist/ $DESTDIR/pkg/$SW.p5m.2 | \ pkgfmt > $DESTDIR/pkg/$SW.p5m.3 # XXX handle the usr/bin/env ruby case dest_prefix=`echo $DEST | sed -e 's:^/::'` mv $DESTDIR/pkg/$SW.p5m.3 $DESTDIR/pkg/$SW.p5m.3.orig awk -F= -e " BEGIN { e = 0; } \$4 ~ /^env / { e = 1; printf \"%s=%s=%s=ruby \\\\\n\", \$1, \$2, \$3; next; } e == 1 && \$2 ~ /^usr\/bin / { printf \"%s=$dest_prefix/bin \\\\\n\", \$1; e = 0; next; } { e = 0; print \$0; }" < $DESTDIR/pkg/$SW.p5m.3.orig > $DESTDIR/pkg/$SW.p5m.3 for i in `find $DESTDIR/dist$DEST/lib/ruby/gems/1.8/gems/*/lib/ -name '*.rb' ` do i_path=`echo $i | sed -e "s:$DESTDIR/dist/::"` i_reqs=`awk '$1 == "require" { print $2; }' < $i | tr -d "'" | tr -d '"' | sort -u` for k in $i_reqs do x="" y="" x=`ls $DESTDIR/dist$DEST/lib/ruby/gems/1.8/gems/*/lib/$k.rb 2>/dev/null` if [ -z "$x" ] then # XXX might not find the best version? y=`ls -r $DEST/lib/ruby/gems/1.8/gems/*/lib/$k.rb 2>/dev/null | head -1` fi if [ -z "$x" -a -z "$y" ] then y=`ls $DEST/lib/ruby/1.*/$k.rb 2>/dev/null` fi if [ -z "$x" -a -z "$y" ] then y=`ls $DEST/lib/ruby/vendor_ruby/$k.rb 2>/dev/null` fi if [ -z "$x" -a -z "$y" ] then y=`ls $DEST/lib/ruby/site_ruby/$k.rb 2>/dev/null` fi if [ -n "$y" ] then echo "depend type=require fmri=__TBD pkg.debug.depend.file="`basename $y`" \\" echo " pkg.debug.depend.path="`dirname $y | sed -e 's:^/::'`" \\" echo " pkg.debug.depend.reason=$i_path pkg.debug.depend.type=script" fi done done >> $DESTDIR/pkg/$SW.p5m.3 i=`ls $DESTDIR/dist$DEST/lib/ruby/gems/1.8/specifications/*.gemspec 2>/dev/null` if [ -n "$i" ] then for k in $i do echo "depend type=require fmri=__TBD pkg.debug.depend.file=gem \\" echo " pkg.debug.depend.path="`echo $DEST/bin | sed -e 's:^/::'`" \\" echo " pkg.debug.depend.reason="`echo $k | sed -e "s:$DESTDIR/dist/::"` dev_deps=`fgrep 'add_development_dependency(' < $k | \ sed -e 's:^.*add_development_dependency(%q<\([^>]*\)>.*$:\1:' | \ sort -u` deps=`fgrep 'add_dependency(' < $k | \ sed -e 's:^.*add_dependency(%q<\([^>]*\)>.*$:\1:' | \ sort -u` for l in $deps do found=0 for m in $dev_deps do if [ "$l" = "$m" ] then found=1 fi done if [ $found -eq 0 ] then spec=`ls -r $DEST/lib/ruby/gems/1.8/specifications/$l-*.gemspec | head -1` if [ -n "$spec" ] then echo "depend type=require fmri=__TBD pkg.debug.depend.file="`basename $spec`" \\" echo " pkg.debug.depend.path="`dirname $spec | sed -e 's:^/::'`" \\" echo " pkg.debug.depend.reason="`echo $k | sed -e "s:$DESTDIR/dist/::"` fi fi done done fi >> $DESTDIR/pkg/$SW.p5m.3 pkgdepend resolve -m $DESTDIR/pkg/$SW.p5m.3