Tuesday, April 10, 2012

A neat trick for testing patches in Gentoo (source-based distros are great!)

Imagine you are running... say... Kubuntu, OpenSuSE, or Fedora, or any other of these famous and fantastic binary Linux distributions. You find a bug, report it to the authors of the package, and they come up with a possible solution. "Hey, here's a small patch to the source, could you please try if applying that helps?" Well... Either now you compile manually, which may or may not give the same packages as your distribution. Or you start setting up the full build system of your distro, which will take a while...
With Gentoo as a source-based distribution, however, this is very easy. Let's assume you want to apply a patch for more debug output to some kde plasma applets. The patch file is called debug.patch, the package name for the plasma applets is kde-base/plasma-apps. All you have to do is
mkdir -p /etc/portage/patches/kde-base/plasma-apps
cp debug.patch /etc/portage/patches/kde-base/plasma-apps/
emerge -a1 kde-base/plasma-apps
Finished. The patch is automatically applied during the emerge command:
 >>> Preparing source in /var/tmp/portage/kde-base/plasma-apps-4.8.2/work/plasma-apps-4.8.2 ...
 * Applying user patches from /etc/portage/patches//kde-base/plasma-apps ...
 *   debug.patch ...                      [ ok ]
 * Done with patching
>>> Source prepared.
Isn't that a nice trick? :)
Just one small warning... this does not work for all ebuilds in the portage tree yet, in case of doubt better check the build log if your patch was really applied. It does work for all ebuilds using base.eclass, which effectively includes all of KDE and all KDE applications.

13 comments:

  1. Don't you need this in bashrc for it to work?

    [code]
    post_src_unpack() {
    if type epatch_user >& /dev/null; then
    cd "${S}"
    epatch_user
    fi
    }[/code]

    ReplyDelete
    Replies
    1. No (and that will cause trouble), because kde4-base_src_prepare calls base_src_prepare, which calls epatch_user... :)

      Delete
    2. I don't think it causes trouble, because epatch_user is specifically designed to be able to be called multiple times but only apply patches once. Also, your post implied that this method can be used generally, not just for KDE. So this bashrc code makes this work for other ebuilds too, as long as they end inheriting the needed eclass :-)

      Delete
    3. You are correct, it's designed such that the patches are only applied once. From the eclass code:

      # It is safe to call the function
      # repeatedly, so it is always possible to add a call at the ebuild
      # level. The first call is the time when the patches will be
      # applied.

      Delete
  2. In defense of openSuSE, their packages are all in OBS (https://build.opensuse.org/), which makes it really easy to take a package and modify it, and submit back fixes (in fact, it can be done right out of Gentoo, with dev-util/osc :)

    Of course Gentoo is way more convenient since you don't have to wait forever for OBS to finish installing the ALL the packages from scratch before telling you that build failed because you made a typo. And besides, ebuilds are just so much nicer than spec files :D

    ReplyDelete
  3. Yes /etc/portage/patches is definitely awesome. But something I have recently noticed is that I have to mangle the paths in the patch:

    Patch has:

    19 --- a/Makefile.am
    20 +++ b/Makefile.am

    I have to do:

    %s/ a\// a\/udev-182\//g
    %s/ b\// b\/udev-182\//g

    What am I missing?

    ReplyDelete
  4. You don't need a source distro just to do an *occasional* manual package compilation with patches applied...

    Arch Linux, albeit a binary distro, makes this pretty easy too:

    1) Install the abs[1] package if you don't have it already, and run `abs` as root to automatically fetch the latest versions of all PKGBUILD scripts which were used to build the packages in the official repos.

    2) Copy the /var/abs/[repo-name]/[package-name]/ folder (containing the PKGBUILD + sometimes auxillary files) to some temporary location, move the debug.patch file to it, and add the line
    patch -p0 <debug.patch
    to the build() function in the PKGBUILD.

    3) Run
    makepkg -i
    in the temporary folder, to automatically compile and install the patched package.

    It might be slightly less convenient than the Gentoo recipe, but then again the other 99,7% of the time, when you *don't* want to apply a patch before installation, a binary distro is simply more convenient...

    --
    [1] https://wiki.archlinux.org/index.php/ABS_FAQ

    ReplyDelete
  5. Arch is both binary as well as source-based. So it's easy there too.

    ReplyDelete
  6. Yeah! Arch fanboys again! I missed you!
    Seriously we were speaking about a Gentoo trick!
    @Andreas: Will it work for every ebuild or only for those who automatically call epatch_user?
    Thank you very much!

    ReplyDelete
    Replies
    1. If you dont do any special tricks, it will work only for ebuilds where epatch_user is called somewhere. That's a quite large part of the tree though (directly in the eclasses autotools-utils, base, elisp, kernel-2, toolchain, vdr-plugin; base is inherited by e.g. cmake-utils, games, gnustep-2, java-utils-2, kde4-base, latex-package, perl-module, qt4-r2, ...)
      For the other ebuilds there are tricks how you can achieve the same effect, basically by using hooks in the portage code. If you search for epatch_user in the forums, you will find a lot of more or less useful stuff.

      Delete
  7. I'm probably just weird but I really don't like dealing with patches. I wish Gentoo would distribute all packages via git rather than using the tarball + patch method.

    The customizing a package could be as easy as making a new branch and telling Portage to use it instead of the official branch.

    ReplyDelete
  8. Just updated the Gentoo Wiki /etc/portage/patches page to include a trick that works for *all* ebuilds.

    ReplyDelete