Ever want to customize packages in the AUR Repo, but don’t want to keep a separate PKGBUILD? Not to mention having to keep it updated when there’s a package that’s almost the same on AUR?

Enter Customizepkg, an Arch AUR package that will automatically modify the PKGBUILD of a package when that package installs or updates via Yaourt (and possibly others), doing so according to whatever you tell it to do.

I’m going to show how set it up and use it. I will also give examples of how to use it to build the h2o webserver with different arguments, such as using the system’s OpenSSL over the bundled LibreSSL, using the latest version of LibreSSL, or even modifying to source code to change the program’s internal name!

Install

First, you will need to install and setup Yaourt, or any other AUR package manager (though you may have to modify it to use Customizepkg). This guide will give instructions on how to integrate with Yaourt.

So, first install it with yaourt:

yaourt -Sy customizepkg-git

Setup

It works by reading your package configurations in your /etc/customizepkg/ folder. So make that folder:

mkdir /etc/customizepkg/

When you want to change a package, you put your desired changes into a file with the same name. If this file does not have executable permissions, it is read for actions. If it is executable, it is run instead.

/etc/customizepkg/$PACKAGENAME

These files can contain:

  • Actions (addline, remove, removeline, add, addline or replace )
  • Patches
  • Executables to download, fix, or do other things with the build.

Using Actions

An action is simply a line that tells customizepkg how to customize the desired package. They are in the format:

ACTION#CONTEXT#PATTERN#VALUE

Where

  • Action can be: remove, removeline, add, addline or replace
  • Context can be: depends, conflicts, makedepends etc.. or global for matching regexp in the whole PKGBUILD
  • Pattern can be any rexgexp
  • Value (only needed for replace) can be any string
  • Comments start with #

Example: Replace/Removeline to enable OpenSSL

To enable OpenSSL on h2o, we can change or remove the -DWITH_BUNDLED_SSL= option.

We can use either replace:

replace#build#-DWITH_BUNDLED_SSL=on#-DWITH_BUNDLED_SSL=off

Which shows in yaourt:

=> replaces '-DWITH_BUNDLED_SSL=on' with '-DWITH_BUNDLED_SSL=off' in build
--- ./PKGBUILD
+++ ./PKGBUILD.custom
@@ -26,7 +26,7 @@
   msg2 'Building...'
   cmake \
     -DCMAKE_INSTALL_PREFIX=/usr \
-    -DWITH_BUNDLED_SSL=on \
+    -DWITH_BUNDLED_SSL=off \
     -DWITH_MRUBY=on \
     .
   make

or removeline:

removeline#build#-DWITH_BUNDLED_SSL=on \\

Which shows something like:

=> remove whole line containing '-DWITH_BUNDLED_SSL=on \\' in build
--- ./PKGBUILD
+++ ./PKGBUILD.custom
@@ -26,7 +26,6 @@
   msg2 'Building...'
   cmake \
     -DCMAKE_INSTALL_PREFIX=/usr \
-    -DWITH_BUNDLED_SSL=on \
     -DWITH_MRUBY=on \
     .
   make

Using either of these (don’t use both!) will find OpenSSL:

-- Found OpenSSL: /usr/lib64/libssl.so;/usr/lib64/libcrypto.so (found version "1.0.2h")

Example: Use latest LibreSSL

In this example, we will build h2o with a statically linked LibreSSL, same as it is by default, but we want it to be the latest version (2.4.2 at this writing). h2o by default uses an older (but more stable) version, which is 2.2.7.

Why? Say for example the latest LibreSSL version has support for some feature we need. This will allow it. Now we could get the package and modify it, keep it updated, and all that fun (not!). Instead, we will tell customizepkg to change PKGBUILD to fit our needs (well, wants).

First, get the h20 PKGBUILD and h2o archive:

curl 'https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=h2o' -o PKGBUILD
curl 'https://codeload.github.com/h2o/h2o/tar.gz/v2.0.1' -o h2o-2.0.1.tar.gz

Inspecting the h2o archive we find that the libressl-2.2.7.tar.gz file is stored in the misc folder, and there’s a libressl.mk file that controls the version that the h2o compiler/configuration scripts look for:

[user]$ ls ./misc/libressl*
./misc/libressl.mk
./misc/libressl-2.2.7.tar.gz

[user]$ grep VERSION ./misc/libressl.mk
VERSION=2.2.7

So we need to change those, adding the libressl-2.4.2.tar.gz to the misc folder, and replacing the VERSION with 2.4.2

In short, we need a PKGBUILD that specifies the archive url (and save location), and a sed to replace the VERSION.

# PKGBUILD for h2o
...
arch=('i686' 'x86_64')
libressl_ver=2.4.2
libressl_hash='5f87d778e5d62822d60e38fa9621c1c5648fc559d198ba314bd9d89cbf67d9e3'
...
source=(....
        $srcdir/misc/libressl-${libressl_ver}.tar.gz::http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${libressl_ver}.tar.gz
        ...
sha256sums=(...
        ${libressl_hash} # <-- I put up as a variable as I kept on forgetting to update it.
        ...
build() {
   cd "$srcdir/$pkgname-$pkgver"
   sed -i 's/VERSION=.*/VERSION='${libressl_ver}'/' ./misc/libressl.mk
   mv ../libressl-${libressl_ver}.tar.gz ./misc/
   ...

Now back to our /etc/customizepkg/h2o file. Let’s get the version and hash in it:

addline#global#arch\s*=\s*(#libressl_ver=2.4.2
addline#global#arch\s*=\s*(#libressl_hash='5f87d778e5d62822d60e38fa9621c1c5648fc559d198ba314bd9d89cbf67d9e3'

We need the sed/mv after the cd "$srcdir/$pkgname-$pkgver" in the build section, so that’s:

addline#build#cd "*$srcdir/$pkgname-$pkgver"*#sed -i 's/VERSION=.*/VERSION='${libressl_ver}'/' ./misc/libressl.mk\nmv ../libressl-${libressl_ver}.tar.gz ./misc/

And then we need the source and sha256sum:

addline#global#source\s*=\s*(#http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${libressl_ver}.tar.gz
addline#global#sha256sums\s*=\s*(.*#${libressl_hash}

Remember that’s ACTION # CONTEXT # PATTERN # VALUE. We are adding lines here, in the global and build contexts. It’s looking for source or sha256sum and placing a line under the found items. And I chose source and sha256sums` because they will always show, and adding a line under then will always match.

We could have also just used replace to put them as the first source. It’s all the same.

replace#global#source\s*=\s*(#source=(http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${libressl_ver}.tar.gz\n
replace#global#sha256sums\s*=\s*(#sha256sums=(${libressl_hash}\n

And yes, the source\s*=\s*( is in case the package maintainer decides to put spaces in.

Once run, you will get

[user]$ h2o --version
h2o version 2.0.1
OpenSSL: LibreSSL 2.4.1
mruby: YES

Example: Enable OpenSSL via an Executable Script

Now we talked about how you could make your /etc/customizepkg/$PACKAGENAME script executable, and it would run it, right? Well let’s do that here (even though it’s not needed. It just helps to see it work).

Set your etc/customizepkg/h2o to:

#!/bin/bash

sed 's/-DWITH_BUNDLED_SSL=on/-DWITH_BUNDLED_SSL=off/g' < $1 > $2

As you can see, we are using sed again to disable the bundled ssl.

  • $1 is the original PKGBUILD
  • $2 is the custom PKGBUILD

Be sure to remove any files in /etc/customizepkg/h2o.files. They seemed to want to run rather than be included. But your mileage may vary.

Set the script to execute:

chmod +x /etc/customizepkg.d/h2o

Install it and it will change the options so it uses OpenSSL.

yaourt -Sy h2o

Adding Files

You can also add files to the /etc/customizepkg/$PACKAGENAME.files/ and then call then from your config file. For example, to add the patch file file.patch, add this to your /etc/customizepkg/$PACKAGENAME file

patch#pkgbuild#file.patch

and then save your patch file as /etc/customizepkg/$PACKAGENAME.files/file.patch

This can be useful in adding patches, or extra files.

Example: Patching the Source Code

Yes, that’s right, we can patch the source code before building the source code. This is really useful if the source code is failing to build and there’s a patch for it, or if there’s a security issue that hasn’t been fixed yet, or you just really want to do some awesome thing to make the program even better.

In this case, let’s change the h2o name and it’s version number to something awesome, like ‘h2o, the blazing web server on a surf board, version 5000’!

Warning

Don’t modify the source code of a program on a production machine unless you know what you’re doing! I’m just having some fun while showing you how to use customizepkg to do so. You have been warned!

So make your patch file as /etc/customizepkg/h2o.files/blazing-h2o.patch with the following. Note that this patch may not work, as code does change. Especially the second part where we add to the software name. It would be better to run and executable or replace option. But it’s just an example.

--- old/version.h.in   2016-06-23 17:04:34.000000000 -0600
+++ new/version.h.in   2016-08-01 20:20:40.523633395 -0600
@@ -22,7 +22,7 @@
 #ifndef h2o__version_h
 #define h2o__version_h

-#define H2O_VERSION "@VERSION@"
+#define H2O_VERSION "5000"

 #define H2O_VERSION_MAJOR @VERSION_MAJOR@
 #define H2O_VERSION_MINOR @VERSION_MINOR@

--- old/src/main.c	2016-06-23 17:04:34.000000000 -0600
+++ new/src/main.c	2016-08-01 20:20:40.523633395 -0600
@@ -1597,7 +1597,7 @@
                 conf.run_mode = RUN_MODE_TEST;
                 break;
             case 'v':
-                printf("h2o version " H2O_VERSION "\n");
+                printf("h2o, the blazing web server on a surf board, version " H2O_VERSION "\n");
                 printf("OpenSSL: %s\n", SSLeay_version(SSLEAY_VERSION));
 #if H2O_USE_MRUBY
                 printf(
@@ -1605,7 +1605,7 @@
 #endif
                 exit(0);
             case 'h':
-                printf("h2o version " H2O_VERSION "\n"
+                printf("h2o, the blazing web server on a surf board, version " H2O_VERSION "\n"
                        "\n"
                        "Usage:\n"
                        "  h2o [options]\n"

And add this to your config file /etc/customizepkg/h2o

patch#1#blazing-h2o.patch

When you run it will show:

-source=($pkgname-$pkgver.tar.gz::https://codeload.github.com/h2o/$pkgname/tar.gz/v$pkgver
+source=('blazing-h2o.patch' $pkgname-$pkgver.tar.gz::https://codeload.github.com/h2o/$pkgname/tar.gz/v$pkgver

-sha256sums=('c53d11589c8c76491cf3a940b649d0a9cb27c36eb276963811ac1bc16cd2bf2c'
+sha256sums=('edb73a2d5797a707a28c54f1147c3805bcb40e5683a370b4d4f1998aba2275ed'
'c53d11589c8c76491cf3a940b649d0a9cb27c36eb276963811ac1bc16cd2bf2c'

+patch -Np1 -i blazing-h2o.patch

as it’s adding the patch file to the PKGBUILD sources, sha256sums, and the build where it will run.

So now run it:

yaourt -Sy h2o

And it will error out (Now you’re thinking “Hey, you broke it!” but I’m going to show you how to fix it.)

==> Starting build()...
patch: **** Can't open patch file blazing-h2o.patch : No such file or directory
==> ERROR: A failure occurred in build().
    Aborting...

What is happening is it’s inputting the patching after it changes to the h2o source directory. But the patch is above the directory.

# from the PKGBUILD:
cd "$srcdir/$pkgname-$pkgver"
patch -Np1 -i blazing-h2o.patch
# but the path to the patch is ../blazing-h2o.patch

So to fix it, we’ll just add a little replace to /etc/customizepkg/h2o under our patch line:

patch#1#blazing-h2o.patch

replace#build#blazing-h2o.patch#../blazing-h2o.patch

See, not too hard. And this won’t always be needed. That’s why I showed you how I fixed it.

And now it should build just fine. If you take a look at the output, you’ll see:

--- ./PKGBUILD
+++ ./PKGBUILD.custom
@@ -12,9 +12,9 @@
 makedepends=('cmake' 'libtool' 'make' 'pkg-config' 'ruby')
 url="https://github.com/h2o/h2o"
 license=('MIT')
-source=($pkgname-$pkgver.tar.gz::https://codeload.github.com/h2o/$pkgname/tar.gz/v$pkgver
+source=('blazing-h2o.patch' $pkgname-$pkgver.tar.gz::https://codeload.github.com/h2o/$pkgname/tar.gz/v$pkgver
         h2o.service)
-sha256sums=('c53d11589c8c76491cf3a940b649d0a9cb27c36eb276963811ac1bc16cd2bf2c'
+sha256sums=('99c0ce5c6b62becac6dc0584c9c2b81b598242eacd1b93385ceeab7c16904811'
'c53d11589c8c76491cf3a940b649d0a9cb27c36eb276963811ac1bc16cd2bf2c'
             '8a85462b6798deaaab343b5dae73437e251c5018d70d260a4a4440b9bbb053e6')
backup=('etc/h2o.conf')
provides=('h2o' 'libh2o')
@@ -22,6 +22,7 @@

build() {
  cd "$srcdir/$pkgname-pkgver"
+patch -Np1 -i ../blazing-h2o.patch
...
==> Starting build()...
patching file version.h.in
patching file src/main.c
  -> Building...

So you know it’s doing its job.

And now, it should show:

[user]$ h2o --version
h2o, the blazing web server on a surf board, version 5000
...

Example: Enable OpenSSL via a patch to PKGBUILD

Say we just want to have apply a simple patch to the PKGBUILD. You probably shouldn’t do this, but I put it here for completeness.

Patches are specified in the file:

patch#pkgbuild#file.patch

We can use our patch earlier:

--- ./PKGBUILD
+++ ./PKGBUILD.custom
@@ -26,7 +26,6 @@
   msg2 'Building...'
   cmake \
     -DCMAKE_INSTALL_PREFIX=/usr \
-    -DWITH_BUNDLED_SSL=on \
     -DWITH_MRUBY=on \
     .
   make

Place that in our /etc/customizepkg/h2o.files directory:

/etc/customizepkg.d/h2o.files/openssl-enable.patch

Then add this to /etc/customizepkg/h2o:

patch#pkgbuild#openssl-enable.patch

When you run it you’ll see:

--- ./PKGBUILD
+++ ./PKGBUILD.custom
@@ -12,9 +12,9 @@
 makedepends=('cmake' 'libtool' 'make' 'pkg-config' 'ruby')
 url="https://github.com/h2o/h2o"
 license=('MIT')
-source=($pkgname-$pkgver.tar.gz::https://codeload.github.com/h2o/$pkgname/tar.gz/v$pkgver
+source=('openssl.patch' $pkgname-$pkgver.tar.gz::https://codeload.github.com/h2o/$pkgname/tar.gz/v$pkgver
         h2o.service)
-sha256sums=('c53d11589c8c76491cf3a940b649d0a9cb27c36eb276963811ac1bc16cd2bf2c'
+sha256sums=('99c0ce5c6b62becac6dc0584c9c2b81b598242eacd1b93385ceeab7c16904811'
'c53d11589c8c76491cf3a940b649d0a9cb27c36eb276963811ac1bc16cd2bf2c'
             '8a85462b6798deaaab343b5dae73437e251c5018d70d260a4a4440b9bbb053e6')

And once again OpenSSL will be found and used.

Make sure you chmod -x after you are done with this example, unless you plan to keep it.

Click here to visit the author’s site for more examples.

Conclusion

This program is a fantastic find! While browsing the AUR sometimes I see people posting comments about how they want some package to support this or do that. If only they knew what they could already do! I mean, yes, you can do this already with a PKGBUILD and makepkg, but with this you can build off of what someone else has already done, and make your customizations. It really allows you to customize your installs in a really great way, like Gentoo but without the need to do so with the whole system. (Gentoo, you guys are awesome too!)