[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Introduction to multiarch: What maintainers must do



Hi,

I got some good feedback from my previous Introduction to multiarch
post and some good questions. I'm singling out Manoj Srivastava here
because he was the most recent to ask this on irc but there where
others with the same or simmilar question.

The full multiarch proposal can be read on:
  https://wiki.ubuntu.com/MultiarchSpec

Manoj as maintainer wondered what, in a few words, would be involved
in migrating his packages to multiarch. I will use amd64 as example
case but any other multiarch combination works just the same.  It
turns out it is more than a few words to spell it all out, on irc is
was just 3 lines. But half the mail are 2 two example patches. So here
we go:


Introduction to multiarch: What maintainers must do
===================================================

To begin with there are 5 cases to consider: (in order of complexity)

1) Architecture: all package
2) Binary package
3) Library package
4) Script interpreter or Service with plugins (and their plugins)
5) none of the above (or I don't care)

For each deb build by your source package you have to decide which of
the 5 cases applies individually. Note that option 5 is safe. You
might hold us all back but you won't break anything.


1) Architecture: all package
----------------------------

You have won. Your package is already multiarch. Hurray.
Now wasn't that easy?


2) Binary package
-----------------

Binary package here means that you package some tool that resides in
[/usr]/[s]bin. For example /bin/sed. Now it does not matter wether sed
is 32bit or 64bit. It also doesn't matter if the program calling sed
is 32bit or 64bit. Now all you need to do is tell dpkg/apt that. You
simply add

  Multi-Arch: foreign

in the debian/control stanza for that package and you are done.
Still easy.


3) Library package
------------------

Library packages are slightly more complex, meaning you do have to do
some actual work. Library package mean that you have some shared
library in [/usr]/lib. For example /usr/lib/libz.so.1.2.3.3. Now it
matters wether the library is 32bit or 64bit. Only 32bit binaries can
use the 32bit library and only 64bit binaries can use the 64bit
library. If the user wants to install a 64bit perl but a 32bit mplayer
he will need both the 64bit and 32bit libz.so.1.2.3.3 installed. For
that you need to do 3 things:

  a) Follow Policy 8.2 (MUST directive)
     No conffiles, no binaries in the library package, no shared files
     (/usr/share/doc/package/ is excempt and dpkg will handle that).
     Many packages do that already and you should have been doing that
     all along.

  b) Move the libraries to multiarch dirs
     To prevent overwrite conflicts in dpkg the libraries on each
     architecture must be in a unique location, namely
     [/usr]/lib/$(DEB_HOST_GNU_TYPE). If you do have library support
     files then they have to be made not unique as well, e.g. go into
     /usr/lib/$(DEB_HOST_GNU_TYPE)/package/.
     For most sources that means running
       ./configure --libdir=/usr/lib/$(DEB_HOST_GNU_TYPE)
     or whatever your build system uses to set the library location.
     The debian/package.install filles might need to be adjusted to
     the new location to or locations used in the rules file itself.

  c) Add Multiarch: same

There, that wasn't so bad, was it?


4) Script interpreter or Service with plugins
---------------------------------------------

This is the big scary monster and can't be done in the first round as
it needs some modifications to dpkg to go into a stable release
first. The problem here is that for python scripts it does not matter
wether you have a 32bit or 64bit python. But the 32bit python gtk
bindings only work with a 32bit python. So we have both packages where
the architecture matters and where not.

So for now perl, python, php, ocaml, apache, ... will not be
multiarchified.  Packages that depend on any one of those and are not
Architecture: all will be forced to have the same architecture as
perl, python, php, ocaml, apache, ... itself.

If your package is a plugin or language binding then you do nothing.
If your package only contains a script or connects to a service then
pick one of 1-3,5 but leave the "Depends: python" (or whatever it is)
as is.


5) none of the above
--------------------

Nothing above did fit? Multiarch makes no sense for your package?
You have no time to implement those changes?

So you do nothing. Doing nothing is the safe option. Doing nothing
might be perfectly alright. Your package will not be multiarchified.
If that is a hinderance I'm sure someone will beat you with a cluebat
or send you patches. Don't be afraid to ask for help and if you do get
patches welcome them.

Examples (in no way complete) where doing nothing it ok:

The -dev packages will not be multiarchified in the first round. Maybe
not in the second. Only thing you need to do in -dev packages is
adjust the *.so link to match the library package.

Your package is a leaf package or in a small leaf cluster. A leaf
package is a package that nothing depends on. A leaf cluster is a set
of packages where nothing outside the cluster depends on. Doing
nothing means that all packages in that cluster (or the one package :)
must all come from the same architecture. Changing the architecture of
one means changing it for all. If the cluster is small that won't
hurt. Generally the more (indirect) reverse depends you do have the
more important it is to multiarchify.

Your package might be architecture specific. You can't multiarchify
something that is only available for one architecture.

If your package is priority standard or higher then it probably does
not belong here. But if in doubt wait for someone to ping you or ask.



I hope that helps maintainers to get a glimse of what lies ahead.
Attached are 2 examples of multiarchifying packages: bzip2 and
libselinux.

MfG
        Goswin

--- Multiarchifying bzip2 --------------------------------------------
# changelog |    6 ++++++
# control   |    2 ++
# rules     |   20 ++++++++++----------
# 3 files changed, 18 insertions(+), 10 deletions(-)

diff -u bzip2-1.0.5/debian/changelog bzip2-1.0.5/debian/changelog
--- bzip2-1.0.5/debian/changelog
+++ bzip2-1.0.5/debian/changelog
@@ -1,3 +1,9 @@
+bzip2 (1.0.5-1a0.multi.1) unstable; urgency=low
+
+  * Convert to multiarch
+
+ -- Goswin von Brederlow <goswin-v-b@web.de>  Mon, 11 May 2009 02:46:51 +0200
+
 bzip2 (1.0.5-1) unstable; urgency=low
 
   * Fix "bzdiff doesn't work if $TMPDIR contains spaces"; closes: #493710
diff -u bzip2-1.0.5/debian/rules bzip2-1.0.5/debian/rules
--- bzip2-1.0.5/debian/rules
+++ bzip2-1.0.5/debian/rules
@@ -152,20 +152,20 @@
 	### Split
 
 	# Development package
-	install -d debian/tmp-dev/usr/lib
+	install -d debian/tmp-dev/usr/lib/$(DEB_HOST_GNU_TYPE)
 	rm debian/tmp/lib/libbz2.so
-	ln -s /lib/libbz2.so.1.0 debian/tmp-dev/usr/lib/libbz2.so
-	mv debian/tmp/lib/libbz2.a debian/tmp-dev/usr/lib/
+	ln -s /lib/$(DEB_HOST_GNU_TYPE)/libbz2.so.1.0 debian/tmp-dev/usr/lib/$(DEB_HOST_GNU_TYPE)/libbz2.so
+	mv debian/tmp/lib/libbz2.a debian/tmp-dev/usr/lib/$(DEB_HOST_GNU_TYPE)/
 	mv debian/tmp/include debian/tmp-dev/usr/include
 	
 
 	# Library package
-	install -d debian/tmp-lib/lib
+	install -d debian/tmp-lib/lib/$(DEB_HOST_GNU_TYPE)
 	for i in $$(ls debian/tmp/lib/libbz2.so*); do \
-	  (set -x; echo $$i; mv $$i debian/tmp-lib/lib/); \
+	  (set -x; echo $$i; mv $$i debian/tmp-lib/lib/$(DEB_HOST_GNU_TYPE)/); \
 	done
-	ln -s libbz2.so.1.0.4 debian/tmp-lib/lib/libbz2.so.1
-	chmod -x debian/tmp-lib/lib/*
+	ln -s libbz2.so.1.0.4 debian/tmp-lib/lib/$(DEB_HOST_GNU_TYPE)/libbz2.so.1
+	chmod -x debian/tmp-lib/lib/$(DEB_HOST_GNU_TYPE)/*
 
 	# Binary package
 	install -d debian/tmp-run
@@ -221,14 +221,14 @@
 	  fi; \
 	done
 	$(DEBSTRIP) --strip-unneeded -R .note -R .comment \
-	  debian/tmp-lib/lib/*.so*
-	$(DEBSTRIP) --strip-debug debian/tmp-dev/usr/lib/*.a
+	  debian/tmp-lib/lib/$(DEB_HOST_GNU_TYPE)/*.so*
+	$(DEBSTRIP) --strip-debug debian/tmp-dev/usr/lib/$(DEB_HOST_GNU_TYPE)/*.a
 
 	# Control files
 	install -d debian/tmp-{lib,dev,run}/DEBIAN
 	cp debian/shlibs debian/tmp-lib/DEBIAN/shlibs
 
-	dpkg-shlibdeps debian/tmp-lib/lib/*.so*
+	dpkg-shlibdeps debian/tmp-lib/lib/$(DEB_HOST_GNU_TYPE)/*.so*
 	dpkg-gencontrol -isp -Pdebian/tmp-lib -plibbz2-1.0
 	rm debian/substvars
 	dpkg-gencontrol -isp -Pdebian/tmp-dev -plibbz2-dev
diff -u bzip2-1.0.5/debian/control bzip2-1.0.5/debian/control
--- bzip2-1.0.5/debian/control
+++ bzip2-1.0.5/debian/control
@@ -11,6 +11,7 @@
 Priority: important
 Section: libs
 Architecture: any
+Multi-Arch: same
 Depends: ${shlibs:Depends}, ${misc:Depends}
 Description: high-quality block-sorting file compressor library - runtime
  This package contains libbzip2 which is used by the bzip2 compressor.
@@ -56,6 +57,7 @@
 Priority: optional
 Section: utils
 Architecture: any
+Multi-Arch: foreign
 Depends: libbz2-1.0 (=${binary:Version}), ${shlibs:Depends}
 Suggests: bzip2-doc
 Replaces: libbz2 (<<0.9.5d-3)





--- Multiarchifying libselinux ---------------------------------------
# debian/changelog     |    6 ++++++
# debian/control       |    2 ++
# debian/local-vars.mk |    2 +-
# debian/local.mk      |    6 ++++--
# src/Makefile         |    9 +++++----
# 5 files changed, 18 insertions(+), 7 deletions(-)

diff -u libselinux-2.0.71/debian/local.mk libselinux-2.0.71/debian/local.mk
--- libselinux-2.0.71/debian/local.mk
+++ libselinux-2.0.71/debian/local.mk
@@ -15,6 +15,8 @@
 ## 
 ###############################################################################
 
+export DEB_HOST_GNU_TYPE
+
 testdir:
 	$(testdir)
 
@@ -124,8 +126,8 @@
 	$(MAKE)		    DESTDIR=$(TMPTOP) -C include install
 	$(MAKE)		    DESTDIR=$(TMPTOP) -C src install
 	rm -fr		    $(LIBDIR)
-	rm -f		    $(TMPTOP)/usr/lib/libselinux.so
-	ln -s               /lib/libselinux.so.1     $(TMPTOP)/usr/lib/libselinux.so
+	rm -f		    $(TMPTOP)/usr/lib/$(DEB_HOST_GNU_TYPE)/libselinux.so
+	ln -s               /lib/$(DEB_HOST_GNU_TYPE)/libselinux.so.1     $(TMPTOP)/usr/lib/$(DEB_HOST_GNU_TYPE)/libselinux.so
 	rm -rf              $(TMPTOP)/usr/lib/python2.4/
 	$(install_file)	    debian/changelog 	     $(DOCDIR)/changelog.Debian
 	$(install_file)	    ChangeLog		     $(DOCDIR)/changelog
diff -u libselinux-2.0.71/debian/changelog libselinux-2.0.71/debian/changelog
--- libselinux-2.0.71/debian/changelog
+++ libselinux-2.0.71/debian/changelog
@@ -1,3 +1,9 @@
+libselinux (2.0.71-1a0.multi.1) unstable; urgency=low
+
+  * Convert to multiarch
+
+ -- Goswin von Brederlow <goswin-v-b@web.de>  Mon, 11 May 2009 09:30:29 +0200
+
 libselinux (2.0.71-1) unstable; urgency=low
 
   * New upstream release
diff -u libselinux-2.0.71/debian/local-vars.mk libselinux-2.0.71/debian/local-vars.mk
--- libselinux-2.0.71/debian/local-vars.mk
+++ libselinux-2.0.71/debian/local-vars.mk
@@ -27,7 +27,7 @@
 
 PREFIX  = /usr
 BINDIR  = $(TMPTOP)$(PREFIX)/bin
-LIBDIR  = $(TMPTOP)/lib
+LIBDIR  = $(TMPTOP)/lib/$(DEB_HOST_GNU_TYPE)
 INCLUDE = $(TMPTOP)$(PREFIX)/include
 INCDIR  = $(INCLUDE)/selinux
 
diff -u libselinux-2.0.71/debian/control libselinux-2.0.71/debian/control
--- libselinux-2.0.71/debian/control
+++ libselinux-2.0.71/debian/control
@@ -10,6 +10,7 @@
 
 Package: selinux-utils
 Architecture: any
+Multi-Arch: foreign
 Section: admin
 Depends: ${shlibs:Depends}
 Description: SELinux utility programs
@@ -22,6 +23,7 @@
 
 Package: libselinux1
 Architecture: any
+Multi-Arch: same
 Section: libs
 Priority: required
 Depends: ${shlibs:Depends}
diff -u libselinux-2.0.71/src/Makefile libselinux-2.0.71/src/Makefile
--- libselinux-2.0.71/src/Makefile
+++ libselinux-2.0.71/src/Makefile
@@ -1,7 +1,7 @@
 # Installation directories.
 PREFIX ?= /usr
-LIBDIR ?= $(PREFIX)/lib
-SHLIBDIR ?= $(DESTDIR)/lib
+LIBDIR ?= $(PREFIX)/lib/$(DEB_HOST_GNU_TYPE)
+SHLIBDIR ?= $(DESTDIR)/lib/$(DEB_HOST_GNU_TYPE)
 INCLUDEDIR ?= $(PREFIX)/include
 PYLIBVER ?= $(shell python -c 'import sys;print "python%d.%d" % sys.version_info[0:2]')
 PYINC ?= /usr/include/$(PYLIBVER)
@@ -9,8 +9,9 @@
 PYTHONLIBDIR ?= $(LIBDIR)/$(PYLIBVER)
 RUBYLIBVER ?= $(shell ruby -e 'print RUBY_VERSION.split(".")[0..1].join(".")')
 RUBYPLATFORM ?= $(shell ruby -e 'print RUBY_PLATFORM')
-RUBYINC ?= $(LIBDIR)/ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
-RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
+RUBYLIB ?= $(PREFIX)/lib/ruby
+RUBYINC ?= $(RUBYLIB)/$(RUBYLIBVER)/$(RUBYPLATFORM)
+RUBYINSTALL ?= $(RUBYLIB)/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM)
 
 LIBVERSION = 1
 


Reply to: