The idea here is to use Debian's multiarch support to migrate from the i386 to amd64 architecture on my laptop.

Note: I made a blog post about this if people want to leave feedback.

Prior art

There are at least four other howtos like this, but like them, I found that the previous howto were not good enough, so I rolled my own (to my defense, before finding the wiki page):

(!) Exercise for the reader: read all those procedures, try them and figure out the best mix, then update the wiki to document the best practice. This should probably end up in the CrossGrading article in the Debian wiki.

Preparation work

First, make backups. Or expect to lose all your data and have to reinstall again. You have been warned.

Then you will want to remove some cruft in your package system. As Ewan's recommends, you should make sure all the packages you have have a amd64 counterpart, with the amazing commandline:

aptitude search '?narrow(?not(?archive("^[^n][^o].*$")),?version(CURRENT))?architecture(i386)' 

This yielded a few results for me, so I went in aptitude and cleaned up orphan packages. We can also mark all libs as "automatically installed", which will cleanup a lot of cruft (go in installed -> libs and libdevel then type "M"). Finally, remove all pending configs ("L~c" then inspect).

I also removed packages causing trouble:

systemd
josm
libreoffice
openjdk-6-jre

Those can be reinstalled later.

Basic amd64 bootstrap

Next we bootstrap in a 64 bit kernel, which is available in i386:

apt-get install linux-image-amd64 busybox-static dctrl-tools aptitude
dpkg --add-architecture amd64
apt-get update
reboot

Pre-filling apt's cache

Then, download all the packages:

apt-get clean
aptitude search --disable-columns -F%p '~ri386~i!~o' | sed '/libc6-i686/d;/libstlport4.6ldbl/d;/linux-headers-.*686.*/d;/xserver-xorg-video-geode/d' | xargs apt-get -o APT::Architecture=amd64 download

Getting as far as possible with multi-arch

Then install a first round of packages:

grep-status --field=Status "install ok installed" | \
    grep-dctrl --field=Multi-Arch same --show-field=Package --no-field-names | \
    sed '/libc6-i686/d;/libstlport4.6ldbl/d;/linux-headers-.*686.*/d;/xserver-xorg-video-geode/d' | \
    sed 's/$/:amd64/' | \
    xargs apt-get -y install 

This works if you have only a few packages, but on a fully-fledged desktop, this will simply fail because apt can't figure out a proper dependency graph, because so many packages are "missing" in amd64.

Installing packages by hand with dpkg

This is where I totally went off the rails from Stuart's approach. This was a fully-fledged experimental desktop with lots of packages (~2500) installed, so the above wouldn't work, and I didn't like the approach of running dpkg or apt-get that often.

So instead I went ahead and bootstrapped dpkg and a bunch of base packages:

apt-get download dpkg:amd64 apt:amd64 liblzma5:amd64 libselinux1:amd64
dpkg -i gcc-4.7-base_4.7.2-5_amd64.deb libgcc1_1%3a4.7.2-5_amd64.deb libc6_2.13-38+deb7u1_amd64.deb libbz2-1.0_1.0.6-4_amd64.deb selinux*
dpkg -i zlib1g_1%3a1.2.7.dfsg-13_amd64.deb libstdc++6_4.7.2-5_amd64.deb liblzma5_5.1.1alpha+20120614-2_amd64.deb libapt-pkg4.12_0.9.7.9+deb7u1_amd64.deb  dpkg_1.16.12_amd64.deb apt_0.9.7.9+deb7u1_amd64.deb

This jumps directly to the step where we replace dpkg and apt with amd64 versions. From here on, dpkg and apt believe their primary architecture is amd64.

For example, base-files can easily be upgraded now:

root@angela:/var/cache/apt/archives# dpkg -i base-files_7.1wheezy4_amd64.deb
(Lecture de la base de données... 364617 fichiers et répertoires déjà installés.)
Préparation du remplacement de base-files 7.1wheezy4 (en utilisant base-files_7.1wheezy4_amd64.deb) ...
Dépaquetage de la mise à jour de base-files ...
Paramétrage de base-files (7.1wheezy4) ...
Traitement des actions différées (« triggers ») pour « man-db »...
Traitement des actions différées (« triggers ») pour « install-info »...

So the problem is just a matter of resolving the dependency tree, something that apt-get cannot figure out right now. We can make things easier on ourself already however.

Installing some base packages

Installing some essential first will unblock a bunch of changes:

dpkg -i libc6_2.13-38+deb7u1_amd64.deb  libgcc1_1%3a4.7.2-5_amd64.deb libgcc1_4.7.2-5_amd64.deb
dpkg -i dash_0.5.7-3_amd64.deb findutils_4.4.2-4_amd64.deb

Bootstrapping all libraries

It may also help to first install all libraries, because so much stuff depend on it, and it makes for a tighter loop:

dpkg -i lib*_amd64.deb

(We should consider using --force-depends here and in later dpkg -i invocations. But this was performed without any --force so far - just run that install multiple times.)

Try to run this until all errors are gone, basically. Then:

for deb in *_amd64.deb; do dpkg -i $deb; done

Run that a few times to make sure all is installed.

Make sure you run this from time to ime::

dpkg --configure -a

... to run the configuration of unpacked packages. This will finish configuring unpacked packages and remove the need to rerun dpkg -i on those packages (depending on the failure point). This is especially useful if you fix some obvious dependency problems by hand (which you should, to make the whole process shorter).

Making sure we're on par

At this point, we're getting closer: the majority of packages is now amd64, but even after 2-3 runs of the above, I still had i386 packages lying around:

dpkg -l | grep i386 | wc # 558 packages

So now I'll install all those packages in amd64 version just to make sure they're around:

dpkg -i $(echo $(grep-status --field=Status "install ok installed"| grep-dctrl --field=Architecture i386 --show-field=Package --no-field-names | sed 's/$/*.deb/'))

Some of those installs will likely fail: make sure you try to resolve issues that creep up.

For example, I had to remove some i386 libs because there's a bug in those packages about conflicting files. List of packages to manually remove from i386:

gstreamer0.10-plugins-ugly:i386
libopenraw1:i386 libgegl-0.2-0:i386
libexo-helpers:i386 libexo-1-0:i386

I also had to download some packages that were not downloaded in the first run, with a simple:

apt-get download gawk:amd64 libgadu3:amd64

Cleaning up

At this point, every i386 package should have been upgraded to amd64 (the majority) or have a amd64 counterpart (the ~500 packages above in my case). You can inspect the list of packages to see if the associated amd64 package is installed for every i386 package:

dpkg -l | grep -B 1 i386

I threw together a check arch.pl script to make sure things are in order.

Once you are satisfied, you can try:

apt-get install -f

But you may want to take a look this is not removing stuff you don't have installed in amd64. Again, the script can be used for that. In my case, it was saying:

$ ./check_arch.pl i386 amd64
finished parsing dpkg -l, 550 remaining packages found in arch i386
package libc6-i686 missing in arch amd64

And those packages were mostly libraries. However, apt-get install -f was removing way more than that! gnome, my window manager and much more were removed. "That's not acceptable soldier." So try:

apt-get dist-upgrade -f

In this case, the result was more satisfactory: it was removing only old i386 libraries - but only 46 of them... But it should be enough to cleanup up the dependency mess we made before, so you should now be able to do:

apt-get autoremove

... to remove those old i386 libs lying around. After that, I had only around 200 i386 packages still standing. Those packages were still there because they were marked as manually installed - aptitude can clean that up easily:

aptitude markauto '~ri386~i'

This will ask you to remove the remaining i386 packages, normally. Yet it's possible that still more packages refuse to be removed at this point - for example pam libraries - I had to run:

aptitude purge '~ri386~i'

.. to really get rid of them all - but be careful here, this is one step you can properly shoot yourself in your last remaining feet.

You may also want to cleanup "configured but removed" packages:

aptitude purge '~ri386~c'

When you are happy with the result, have rebooted and made sure everything works, you can simply remove the i386 architecture and you're done!

dpkg --remove-architecture i386
Created . Edited .