< Solaris
Revision as of 12:35, 8 December 2009 by *>SunTzuTech (add the extract_plist.sh snippet)

Solaris/FOSS specfiles

Currently, solaris.bionicmutton.org/SRC contains tarballs that originate from Stefan Teleman's KDE4 on Solaris porting effort located on cvsdude.com. (http://kdesolaris.svn.cvsdude.com). The tarballs are almost always a relative directory starting with Solaris/, and contain patch, configure, build, and install scripts, as well as patches, and any custom files needed to build a module.

However, they are difficult to deal with, and regenerating them is a bit of a PITA, and pretty much makes working on KDE4 an exclusive club with secret handshake, because unless you have a full Dude checkout (like 7GB) it can be a real hassle.

Starting in the kde4-specs-440 tree, there is an effort going on to convert all those modules from the DUDE tarball, to a purely spec format. Due to the fact that the FOSS modules are built for both 32-bit and 64-bit, there are two components minimum to each module.

1) FOSS<modulename>.spec - this contains all the high level information, with package name, version, description, license, package dependencies, and a package list. Any new modules or updated modules should include a explicit package list, so that changes between versions of packages can be tracked. Globals in the plist is just sloppy. Unless you know what should pop out, generate a complete plist. How do you do that? Use a global plist, and then convert it using this little gem with the pkg name.

ie: ./extract_plist.sh FOSSexpat

  1. !/bin/bash

if [ -z "$1" ]; then echo "no package" exit fi pkginfo -q $1 if [ $? -ne 0 ]; then echo "pkg $1 not found" exit 1 fi egrep "${1}$|${1} " /var/sadm/install/contents | cut -f1-2 -d\ | egrep -v d$ | awk '{print $1}' | cut -f1 -d= | sed -e 's,/opt/foss/include,%{_includedir},' -e 's,/opt/foss/lib/amd64,%{_libdir}/%{_arch64},' -e 's,/opt/foss/lib/,%{_libdir}/,' -e 's,/opt/foss/bin/amd64,%{_bindir}/%{_arch64},' -e 's,/opt/foss/sbin/amd64,%{_sbindir}/%{_arch64},' -e 's,/opt/foss/sbin/,%{_sbindir}/,' -e 's,/opt/foss/bin/,%{_bindir}/,' -e 's,/opt/foss/share/locale,%{_localedir},' -e 's,/opt/foss/share/man,%{_mandir},' -e 's,/opt/foss/share/aclocal,%{_datadir}/aclocal,' -e 's,/opt/foss/share/doc,%{_docdir},' -e 's,/opt/foss/qt4/include,%{foss_qt4_inc},'

Basically, it looks for the pkg in the contents file, extracts the files (and not the dirs, since most high level ones we've already defined, and the lower ones can become really tedious to document, *especially* locale), and then converts it to a appropriate plist format. then glue in the pieces.

2) base-specs/base-<module>.spec - this contains pretty much what was found in the DUDE Solaris tarball (typically Solaris-PGKNAME-REVISION,MINORREV.tar.gz). Decomposing a Solaris tarball should go something like this:

a) extract all the patches. prefix them with the packagename-version, postfixed with an index starting at 01, and ending in .diff

typically, an apply_patches script has something like: #!/bin/sh for file in \

    configure.diff \
    config.h.diff \
    Makefile.diff \
    somecfile.c.diff \


    gpatch -p1 Solaris/diffs/$file


I convert it to read:

#!/bin/sh N=0

  for file in \
    configure.diff \
    config.h.diff \
    Makefile.diff \
    somecfile.c.diff \


  1. Strip off the trailing ".diff"

NM=`echo $file | sed 's\.diff$,,'`

  1. in case there's a trailing index value we want to remove...
  2. so if the file was configure.01.diff, NM sees configure.01,
  3. and what we really want is "configure".

NM=`echo ${NM} | sed 's,\.[0-9]*$,,'`

  1. just a counter so we can build the patchlist for the spec file,
  2. and we match it to the patch, so it's really clear which patch
  3. it should be

N=`echo ${N} | awk '{printf "%.02d",$1+1}'`

  1. strip off preceding 0 for the %patch and Patch${Y} commands

Y=`echo ${N} | sed 's,^0,,'`

  1. rename the file to something more "unique"

mv $file Mypkg-1.0.1-${NM}.${N}.diff

  1. Create the patchlist entry for this patch.

echo "Patch${Y}:\t\t%{patchprefix}-${NM}.${N}.diff" >> patchlist

  1. Create the patching entry for this patch (%prep area)

echo "%patch${Y} -p1" >> patching done

what this does is move all the files into a more "orderly" list with a created patchlist that can be imported into the base-spec file, as well as the patching order.

b) the section above %prep, is where you will insert "patchlist" Above patchlist, you %define patchprefix %{src_name}-%{src_ver} so we don't have to care about changing the stupid patch file names every time we uprev a package.

There are a couple of reasons we do this: 1) patches must have unique names because they are copied to packages/SOURCES 2) when we up rev a package, we don't lose the ability to build a

  previous revision of the package, without some "mecurial" magic.

3) a patch has been submitted the pkgbuild repo to allow the

  patch mechanism to use relative paths to patches, which means
  that patches/<PKG NAME>/<SRC VER>/patchname.diff. Eventually,
  this means that  spec/patches won't have to be a dumping ground
  for all patches.

It also makes it dead simple to copy existing patches from a previous revision for a new one and tune those patches for the next revision. To understand this value, I was able to use this method to uprev gstreamer-0.10.17 to gstreamer-0.10.22 iteratively in less that 2 hours. I got stuck at 0.10.23 since that wanted glib2-2.14 and FOSS at that time only had glib2-2.12.12

c) in the %prep section, include "patching" file from above. Additionally, include the configure.sh, converting most ${} variables to %{} variables, unless they are truly shell variables.

d) in the %build section, import build.sh. clean it up

e) in the %install section, import install.sh, clean it up. This section is usually trickiest because of the way 32 and 64 bit binaries get made, and how some packages have a hard time honoring the configured paths.

All your new patches should go in spec/patches/%{src_name}/%{src_ver} and then symlink those into spec/patches.

Using a very simple %if clause, a spec file can now support multiple revisions, with all the behavior customized off that specific version to include package requirements, explicit plists, patches, applying patches, configure changes, etc. It takes a little bit more effort than just chopping up a spec file because a bunch of stuff changed.

Content is available under Creative Commons License SA 4.0 unless otherwise noted.