Fork me on GitHub

One of my favorite things about Arch Linux is pacman. It’s a simple, fast, versatile package manager on which Arch is built. I really love how easy it is to create packages using makepkg that can be installed with pacman and I actually maintain a few packages myself over in the AUR. More info on creating your own packages can be found here.

That’s all fine and good, but what if (for whatever reason) you don’t even want to create a PKGBUILD and run it through makepkg? Under certain circumstances it might be easier to simply create the package install tarball “by hand” (and if not easier, at least it’s an interesting exercise :) ).

Motivation: Today I needed to install a piece of proprietary software that uses a GUI installer and decided that rather than cooking up a full PKGBUILD for the thing I would just set the install directory to some temporary location, tar that up and compress it with xz, add the necessary metadata, and then install it with pacman -U.

So, here we go! You can follow along in a terminal if you want.


First, we create an area where we’ll create the hierarchy of files that we want pacman to install to our system:

mkdir /tmp/manualpackage/pkg; cd /tmp/manualpackage/pkg

Now, fill up the pkg directory with some junk (this will be placed on / later by pacman):

mkdir -p usr/share/manualpackage
echo "all your base are belong to us" > usr/share/manualpackage/pizza.txt

Note: at this stage, rather than creating a bunch of files manually, you could do something like run a GUI installer, setting the install location to /tmp/manualpackage/pkg.

Now we have to provide some metadata that pacman will use to manage its database. At a bare minimum, we have to include a file named .PKGINFO with some basic information about our package:

touch .PKGINFO

Paste the following into .PKGINFO:

pkgname = manualpackage
pkgver = 1.0.0-1
pkgdesc = Test package
url = http://mgalgs.github.com
builddate = 1323390194
packager = manual
size = 8192
arch = any

Note: This file is sort of touchy! I got the pkgver variable wrong the first time (I was simply using the number 1) and it sort of corrupted my pacman database (all I had to do to fix it was remove the offending directory from /var/lib/pacman/local and the installed files manually). There’s not much validation going on because this file is usually generated by another tool (like makepkg).

Anyways, here’s what we have so far:

$ tree -a
.
`-- pkg
    |-- .PKGINFO
    `-- usr
        `-- share
            `-- manualpackage
                `-- pizza.txt

4 directories, 2 files

We’re now ready to create the package tarball. Since 2010, Arch Linux has been using the xz format (also known as lzma2) to compress packages. xz is a little slower than, say, gzip, but it achieves much higher compression ratios. Here’s how we compress our package using tar and xz (lifted from /usr/bin/makepkg):

$ tar -cf - .PKGINFO * | xz -c -z - > ../manualpackage.pkg.tar.xz

That’s it! We now have a package that can be fully managed by pacman!

Just for fun let’s take one last peek at what we have:

$ tar tf manualpackage.pkg.tar.xz 
.PKGINFO
usr/
usr/share/
usr/share/manualpackage/
usr/share/manualpackage/pizza.txt

Now, let’s install it:

$ sudo pacman -U manualpackage.pkg.tar.xz 
resolving dependencies...
looking for inter-conflicts...

Targets (1): manualpackage-1.0.0-1

Total Download Size:    0.00 MB
Total Installed Size:   0.01 MB

Proceed with installation? [Y/n] y
(1/1) checking package integrity                   [######################] 100%
(1/1) checking for file conflicts                  [######################] 100%
(1/1) installing manualpackage                     [######################] 100%

Verify that it is indeed installed and manageable by pacman:

$ pacman -Q | grep manualpackage
manualpackage 1.0.0-1

Verify that our package files were installed to the filesystem:

$ ls -l /usr/share/ | grep manualpackage | wc -l
1

$ cat /usr/share/manualpackage/pizza.txt 
all your base are belong to us

Now, let’s remove it:

$ sudo pacman -R manualpackage 
checking dependencies...

Remove (1): manualpackage-1.0.0-1

Total Removed Size:   0.01 MB

Do you want to remove these packages? [Y/n] y
(1/1) removing manualpackage                       [######################] 100%

And verify that it’s gone:

$ pacman -Q | grep manualpackage
# ...no output...

$ ls -l /usr/share/ | grep manualpackage | wc -l
0

Clean as a whistle! Thanks pacman!


blog comments powered by Disqus