Build RPMs of CPAN Modules

If you’ve been reading my blog for a while, you probably already know that I have an interest in building RPMs of CPAN modules. I run a small RPM repository where I make available all of the RPMs that I have built for myself. These will either be modules that aren’t available in other RPM repositories or modules where I wanted a newer version than the currently available one.

I’m happy to take requests for my repo, but I don’t often get any. That’s probably because most people very sensibly use the cpanminus/local::lib approach or something along those lines.

But earlier this week, I was sitting on IRC and Ilmari asked if I had a particular module available. When I said that I didn’t, he asked if I had a guide for building an RPM. I didn’t (well there are slides from YAPC 2008 – but they’re a bit dated) but I could see that it was a good suggestion. So here it is. Oh, and I built the missing RPM for him.

Setting Up

In order to build RPMs you’ll need a few things set up. This is stuff you’ll only need to do once. Firstly, you’ll need two new packages installed – cpanspec (which parses a CPAN distribution and produces a spec file) and rpm-build (which takes a spec file and a distribution and turns them into an RPM). They will be available in the standard repos for your distribution (assuming your distribution is something RPM-based like Fedora or Centos) so installing them is as simple as:

If you’re using Fedora 22 or later, “yum” has been replaced with “dnf”.

Next, you’ll need a directory structure in which to build your RPMs. I always have an “rpm” directory in my home directory, but it can be anywhere and called anything you like. Within that directory you will need subdirectories called BUILD, BUILDROOT, RPMS, SOURCES, SPECS and SRPMS. We’ll see what most of those are for a little later.

The final thing you’ll need is a file called “.rpmmacros” in your home directory. At a minimum, it should contain this:

The packager and vendor settings are just to stop you having to type in that information every time you build an RPM. The _topdir setting points to the “rpm” directory that you created a couple of paragraphs up.

I would highly recommend adding the following line as well:

This turns off the default behavior for adding “Requires” data to the RPM. The standard behaviour is to parse the module’s source code looking for every “use” statement. By turning that off, you instead trust the information in the META.yml to be correct. If you’re interesting in hearing more detail about why I think the default behaviour is broken, then ask me in a pub sometime.

Ok. Now we’re all set. We can build our first RPM.

Building an RPM

Building an RPM is simple. You use “cpanspec” to make the spec file and then “rpmbuild” to build the RPM. You can use “cpanspec” in a few different modes. If you have the module tarball, then you can pass that to “cpanspec”.

That will unwrap the tarball, parse the code and create the spec file.

But if you’re building an RPM for a CPAN module, you don’t need to download the tarball first, “cpanspec” will do that for you if you give it a distribution name.

That will connect to CPAN, find the latest version of the distribution, download the right tarball and then do all the unwrapping, parsing and spec creation.

But there’s another, even cleverer way to use “cpanspec” and that’s the one that I use. If you only know the module’s name and you’re not sure which distribution it’s in, then you can just pass the name of the module.

This is the mode that I always use it in.

No matter how you invoke “cpanspec”, you will end up with the distribution tarball and the spec file – which will be called “perl-Some-Module.spec”. You need to copy these files into the correct directories under your rpm building directory. The tarball goes into SOURCES and the spec goes into SPECS. It’s also probably easiest if you change directory into your rpm building directory.

You can now build the RPM with this command:

You’ll see a lot of output as “rpmbuild” goes through the whole CPAN module testing and building process. But hopefully eventually you’ll see some output saying that the build has succeeded and that an RPM has been written under your RPMS directory (in either the “noarch” or “x86_64” subdirectory). You can install that RPM with any of the following commands:

And that should be that. Of course there are a few things that can go wrong. And that’s what the next section is about.

Fixing Problems

There are a number of things that can go wrong when building RPMs. Here are some of the most common, along with suggested fixes.

Missing prerequisites

This is also known as “dependency hell”. The module you are building is likely to require other modules. And you will need to have those installed before “rpmbuild” will let you build the RPM (and, note, they’ll need to be installed as RPMS – the RPM database doesn’t know about modules you have installed with “cpan” or “cpanminus”).

If you have missing prerequisites, the first step is to try to install them using “yum” (or “dnf”). Sometimes you will get lucky, other times the prerequisites won’t exist in the repos that you’re using and you will have to build them yourself. This is the point at which building an RPM for a single module suddenly spirals into three hours of painstaking work as you struggle to keep track of how far down the rabbit-hole you have gone.

I keep thinking that I should build a tool which parses the prerequisites, works out which ones already exist and automatically tries to build the ones that are missing. It would need to work recursively of course. I haven’t summoned the courage yet.

Extra files

Sometimes at the end of an RPM build, you’ll get an error saying that files were found which weren’t listed in the spec file. This usually means that the distribution contains programs that “cpanspec” didn’t find and therefore didn’t add to the spec file. This is a simple fix. Open the spec file in an editor and look for the section labelled ‘%files’. Usually, it will look something like this:

This is a list of the files which will be added to the RPM. See the _mandir entry? That’s the man page for the module that is generated from the module’s Pod (section 3 is where library documentation goes). We just need to add two lines to the bottom of this section:

This says “add any files you find in the binaries directories (and also any man pages you find for those programs)”.

If you add these lines and re-run the “rpmbuild” command, the build should now succeed.

Missing header files

If you’re building an XS module that is a wrapped around a C library then you will also need the C header files for that library in order to compile the XS files. If you get errors about missing definitions, then this is probably the problem. In RedHat-land a C library called “mycoolthing” will live in an RPM called “libmycoolthing” and the headers will be in an RPM library called “libmycoolthing-devel”. You will need both of those installed.

Your users, however, will only need the C library (libmycoolthing) installed. It’s well worth telling the RPM system that this external library is required by adding the following line to the spec file:

That way, when people install your module using “yum” or “dnf”, it will pull in the correct C library too. “cpanspec” will automatically generate “Requires” lines for other Perl RPMs, but it can’t do it for libraries that aren’t declared in the META.yml file.


So that’s it. A basic guide to building RPMs from CPAN distributions. There’s a lot more detail that I could cover, but this should be enough to work for 80-90% of the modules that you will want to build.

If you have any questions, then please leave a comment below.

Send to Kindle

“I Do Not Want To Use Any Modules”

Almost every day on the Perl groups on LinkedIn (or Facebook, or StackOverflow, or somewhere like that) I see a question that includes the restriction “I do not want to use any modules”.

There was one on LinkedIn yesterday. He wanted to create a MIME message to pass to sendmail, but he didn’t want to install any modules. Because “getting a module installed will have to go though a long long process of approvals”.

And I understand that. I really do. We’ve all seen places where getting new software installed is a problem. But I see that problem as a bug in the development process. A bug that needs to be fixed before anything can get done in a reasonable manner. Here’s what I’ve just written in reply:

Of course it can be achieved without modules. Just create an email in the correct format and pass it to sendmail.

Ah, but what’s the right format? Well, that is (of course) the tricky bit. I have no idea what the correct format is. Oh, I could Google a bit and come up with some ideas. I might even find the RFC that defines the MIME format. And then I’d be able to knock up some code that created something that looked like it would work. But would I be sure that it works? In every case? With all the weird corner-cases that people might throw at it?

This is where CPAN modules come in handy. You’re using someone else’s knowledge. Someone who is (hopefully) an expert in the field. And because modules are used by lots of people, bugs get found and fixed.

A lot of modern Perl programming is about choosing the right set of CPAN modules and plumbing them together. That’s what makes Perl so powerful. That’s what makes Perl programmers so efficient. We’re standing on the shoulders of giants and re-using other people’s code.

If you’re not going to use CPAN then you might as well use shell-scripting or awk.

If you’re in a situation where getting CPAN modules installed is hard, then fixing that problem should be your first priority. Because that’s a big impediment to your Perl programming. And investing time in fixing that will be massively beneficial to you in a very short amount of time.

The obvious solution is to install your own module tree (alongside your own Perl) as part of your application. But that might be overkill in some situations, so you could also consider using the system Perl and asking your sysadmin to install packages from your distribution’s repositories. Of course, that might need a change in process. But it’s a change that is well worth making; a change that will improve your (programming) life immensely.

Update: Some very interesting discussion about this over on Reddit.

Send to Kindle

Installing Modules

If you’ve seen me giving my “Kingdom of the Blind” lightning talk this year, then you’ll know that I’ve been hanging around places like the LinkedIn Perl groups and StackOverflow trying to help people get the most out of Perl. It can be an “interesting” experience.

One of the most frequent questions I see is some variant of “I have found this program, but when I try to run it I get an error saying it can’t find this module”. Of course, the solution to this is simple. You tell them to install the missing module. But, as always, the devil is in the detail and I think that in many cases the answers I seen could be improved.

Most people seem to leap in and suggest that the original poster should install the module using cpan (advanced students might suggest cpanminus instead). These are, of course, great tools. But I don’t think this is the best answer in to these questions.

In most cases, the people asking questions are new to Perl. In some cases they don’t even want to learn any Perl – they just want to use a useful program that happens to be written in Perl. I think that launching these people into the CPAN ecosystem is a bad idea. Yes, eventually, it would be good to get them using perlbrew, local::lib and cpanminus. But one step at a time. First let’s show them how easy it can be to use Perl.

In many of these cases, I think that the best approach is to suggest that they use their native package manager to install a pre-packaged version of the required module.

Yes, I know the system Perl is evil and outdated. Yes, I know that they probably won’t get the latest and greatest version of your CPAN module from apt-get or yum.  And, yes, I know there’s a chance that the required module won’t be available from the package repositories. But I still think it’s worth giving it a try. Because in most cases the module will be  there and available as a recent enough version that it will solve their immediate problem and let them get on with their work.

There are three main reasons for this suggestion:

  1. People in this situation will almost certainly be using the system Perl anyway. And the  system Perl will already have pre-packaged modules installed alongside it. And installing modules using cpanminus alongside pre-packaged modules in the same library installation is a recipe for disaster. The package manager no longer knows what’s installed or what versions are installed and hilarity ensues.
  2. The pre-packaged versions will know about non-Perl requirements for the CPAN module and will pull those in as well as other required CPAN modules. One of the most common requests I see is for GD or one of its related modules. Your package manager will know about the underlying requirement for  libgd. cpanminus and friends probably won’t.
  3. The user is more likely to be used to using their package manager. Teaching them about the CPAN ecosystem can come later. Let’s ease them into using Perl by starting them off with tools that they are familiar with.

I know that both Fedora/Centos/RHEL and Ubuntu/Debian have large numbers of CPAN modules already pre-packaged for easy installation. Let’s suggest that people make use of this work to get up and running with Perl quickly. Later on we can show the the power and flexibility that comes with using the Perl-specific tools.

Of course there’s then a debate about when (and how) we start to wean these people off of the system Perl and pre-build packages and on to perlbrew/cpanminus/etc. But I think that having a community of people who are used to using CPAN modules (albeit in this slightly restricted manner) is an improvement on the current situation where people often avoid CPAN completely because module installation is seen as too difficult.

What do you think? Are there obvious errors in my thinking?

Send to Kindle


If you’ve been reading my blog for a while, you’ll know that I have an interest in packaging CPAN modules as RPMs for Linux distributions based on Red Hat.

For a few years, I’ve been (infrequently) building spreadsheets which list the various modules that are available as RPMs from the better know repositories (and my own small repository). Over the weekend, I thought that those spreadsheets might be more useful if they were turned into web pages. So that’s what I did.

You can see the lists for Fedora and Centos. Over the next few days, I plan to set up cron jobs so that they are rebuilt daily.

Please let me know if you find these lists useful.

Send to Kindle

Removing Modules from Core

I was on holiday last week and missed most of the discussions about removing Module::Build and CGI from the Perl core in the next few years. I hope you won’t mind if I chime in a little late with my thoughts.


I’m a little bemused by the Module::Build story. Well, perhaps “bemused” isn’t quite the right word. Perhaps I should say “embarrassed”. Embarrassed because the discussions around Module::Build just show how out of touch I am with important parts of the Perl ecosystem.

I remember seeing Schwern’s MakeMaker Is DOOMED! talk ten years ago. What he said made a lot of sense to me and I switched all of my CPAN modules to Module::Build over the next few years. And then I rather took my eye off the ball. I was vaguely aware that people were complaining about Module::Build and were switching to things like Module::Install and Dist::Zilla. But I was happy with Module::Build and just stuck with it.

Now I’m hearing people saying that Module::Build is fundamentally flawed. Someone whose opinion I value mentioned that he lowers his estimate of the IQ of any CPAN author who uses Module::Build. That, presumably, includes me. But when I ask people what the problems are with Module::Build, I can’t get anyone to give me a detailed and dispassionate answer.

I’m quite prepared to believe that there are problems with Module::Build. Given the calibre of the people who are telling me that these problems exist, it would be astonishing if it wasn’t true. But it would be nice if there was a good explanation available somewhere of just what these problems are.

And I think that this is indicative of a deeper problem that the Perl community has. I like to think that I’m pretty much in touch with what is going on in the Perl community. I read the blogs. I’m subscribed to (too many) mailing lists. But it appears I’m not following discussions of the CPAN toolchain closely enough. I guess it’s something that I just expect to work. And I guess I expect that if there are important discussions going on, then I’ll hear about them through other channels – blog posts, for example. But that doesn’t seem to have happened here. Of course I can subscribe myself to another mailing list or two to correct that, but I don’t think I’m unusual in not trying to follow every single Perl discussion. There are surely many people like me who would like information like this to be disseminated better. This is part of the reason why Leo and I set up the Perl News site. But we have a tiny number of editors and we can’t know everything that is worth publishing. If you think we’ve missed an interesting story then please let us know about it.

So I’m not going to object to Module::Build leaving the core. I’m sure there are good reasons, I just wish I knew what they are. I am, however, slightly disappointed to find that Schwern was wrong ten years ago and that ExtUtils::MakeMaker wasn’t doomed.

CGI and I go back a long way. In fact I think was added to the Perl core at about the same time as I started using Perl.

It’s obvious why it was added to the core. Back in 1997, Perl and CGI were tightly bound together in many people’s minds. I had people telling me that Perl could only be used to write CGI programs and other people telling me that CGI programs could only be written in Perl. Both sets of people were, of course, wrong; but it’s easy to see how they reached both of those conclusions.

Before was added to the Perl core, people used to parse CGI parameters using horribly broken code copied from Matt Wright (code which he had originally copied from Reuven Lerner). Of course, adding the module to the Perl core didn’t magically rewrite all those horrible CGI programs to use CGI::params, but at least it meant that the option was there.

This became important to me when I started the nms project. This project rewrote Matt Wright’s scripts using a better standard of Perl code. The problem was that many people started by installing one of Matt’s scripts on their server and later, when they wanted to move on from using other people’s code, they would use Matt’s code as a template for their own first steps into Perl. This is partly what made Perl so popular. But it’s also what lead to the preponderance of terrible Perl code that you still find on the web today.

We wrote the nms programs to work, as far as possible, in the same environment as Matt’s scripts. Matt said that his scripts would work fine on Perl 4 (back then, there were still many cheap hosting plans that came with Perl 4). We decided not to put ourselves through that pain and to target Perl 5.004 – because that was the first version to include Remember, we were targeting Matt Wright’s users. And they were people who used cheap hosting plans with basic FTP access and little or no chance of installing anything from CPAN. We had to rely on core modules. If hadn’t been in the Perl core, then the nms programs would have been far harder to write and the project may have never been started.

The nms project was started over ten years ago. What is the situation like now? Those cheap hosting plans still exist. People still use them for simple web sites. Some of those people still use Matt’s scripts or the nms alternatives. But the numbers of people using those programs are far smaller than they used to be. These days, people wanting to add simple dynamic functionality to a web site are far more likely to use a PHP program. And those cheap web hosts are far more likely to want to support PHP.

Of course, these days, no serious Perl developer uses to write web programs. We’d be far more likely to use something based on PSGI. And even if we did want to use, we’d know how to get it installed from CPAN. The only people who are going to suffer from the removal of are the people using something like the nms programs on a cheap hosting plan. I worry a little about the influx of support email we will get when some cheap hosting company updates from Perl 5.18 to Perl 5.21 and suddenly all the nms programs stop working. It’s slightly galling to realise that Matt’s scripts will continue to work at that point. Of course, the kinds of companies that we’re talking about tend to lag well behind the bleeding edge of Perl versions, so this might not happen for eight or more years. So I think it might well be someone else’s problem.

All in all, I think it will be sad to see removed from the core. It will effectively see the end of even half-decent Perl code being used on bottom of the range hosting plans. But Perl has been losing that market for years and, speaking as someone who spent a lot of time helping out on support forums for basic Perl/CGI code, I’m far from convinced that I’ll miss those users. So my sadness at seeing CGI,pm go, will be purely historical.

But I’d really like to see some cut-down version of PSGI take its place!

Send to Kindle

Give Me MetaCPAN

Ever since MetaCPAN launched I’ve been getting increasingly irritated with people who still use links to Isn’t it obvious that MetaCPAN is better? Why do people still insist on sharing links to the older site?

Of course they do it for various reasons. Perhaps they aren’t as in touch with the modern Perl world as I am. Perhaps they are wary about changing to use the new shiny toys because they know that a newer shinier one will be along soon. Perhaps I’m reading a web page from five years ago and they can be forgiven for not linking to a site that didn’t exist at the time.

Eventually I realised that there was no point in getting annoyed. I had a computer. Surely I could do something that would fix this problem.

My first idea was to write a GreaseMonkey script. Then I realised that would be hard. MetaCPAN and CPAN have slightly different URL schemes. I’d need to recognise a CPAN URL and convert it to the equivalent MetaCPAN URL. Not an impossible task at all, but not something I could knock up in an hour or so. Especially not in Javascript.

So I asked on the #metacpan IRC channel. Surely I couldn’t be the first person to have this problem. And someone there introduced me to There’s no point in clicking on that link. You’ll just end up on MetaCPAN. Because that’s what mcpan does. It’s a URL rewriting service. You give it a CPAN URL (with the changed to and it redirects you to the equivalent page on MetaCPAN.

That’s the hard bit of the problem. The bit I didn’t want to write. And someone else has already written it. But they seem to have kept it very quiet. This deserves more publicity. I wish I could remember who wrote it. If you know, please leave a comment.

So we’re now most of the way there. Now if I click on a CPAN link, I can just edit the location bar to add an ‘m’ and I’ll be redirected to the right place. But we can do better than that. I’d like to be automatically redirected. That’s when I discovered the Redirector extension for Firefox. Once it’s installed you can configure it to redirect certain URLs to other ones. I have it configured so that* redirects to$1. See how you can use wildcards to match URLs and then use whatever they matched in the replacement URL. It’s a lot like regexes in Perl.

And we’re done. Now whenever I click on an old-style CPAN link, I’m automatically redirected to mcpan, And that, in turn, redirects me to MetaCPAN. And, best of all, I didn’t have to write any code. It was just a case of putting together tools that already existed.

I did all this a few months ago. I meant to write this blog post at the time, but I forgot. I was reminded this morning when Chisel mentioned a GreaseMonkey script he had written to do all of this. See, Chisel isn’t afraid of parsing URLs in Javascript like I was. He just went ahead and did it.

But having alternative solutions to the problem is good, right?

Update: I’ve just been talking about this on the #metacpan IRC channel and it seems that I was rather misunderstanding what was going on here. Here are the details.

Firstly, it was dpetrov who told me about It’s his domain. I asked him for the code, and he pointed out that there is no code. just redirects everything to a domain called which is where the magic happens. He just got tired of editing to so he registered another, simpler, domain.

So the actual cleverness happens over on And that’s really just a list of rewrite rules (the code is on github). I say “just”, but I still wouldn’t want to write them myself.

All this means that mcpan,org is only a convenient tool for when you’re manually editing your location bar. When you’re using the Redirector extension for Firefox you can miss out the middle man and redirect straight to So I’ve updated my Redirector rule appropriately.

Send to Kindle


XML::Feed is the module that does most of the heavy lifting for Perlanet and, as such, it powers some important parts of the Perl community’s infrastructure. Unfortunately, for a while now it’s had a rather long list of outstanding bugs that weren’t getting fixed.

Sometime last year, Matt Trout got co-maintainership on the module and shortly afterwards he shared it with me. I released a couple of versions last year (largely to fix one particular and important bug) and fixed a few of the easier bugs on the list, but most of the list remained untouched.

Whilst working on these few fixes I set up a copy of the repository on Github. And about a month ago, that started to pay dividends as I got a couple of pull requests from Gabor. In combination with a couple of new bug reports that came it at about the same time, this galvanised me into putting a bit more effort into the module.

I’ve released a couple of new versions in the last week. Most importantly, I think that version 0.48 fixes the test failures that were common in the last few releases – and initial indications are that I’m right.

It seems that people are interested in this module. So let’s see if we can get a little community going. I’ve set up a mailing list to discuss the module and. of course, there’s already the bug list and the Github repository.

Patches welcome. Github pull requests even more so. But if you just have ideas and suggestions or want advice on how to use the module, I’d love to hear from you.

Send to Kindle

Fedora and Centos CPAN RPMs

Today I’ve updated my spreadsheets of the CPAN modules that are available as RPMs from various repositories for Fedora and Centos. I see that in many cases the “official” repos are now more up to date than my own repo (which I originally set up because the official repos are sometimes out of date).

This is all a precursor to doing a lot more work on my repo. I need to know which RPMs are being kept up to date by other people so that I can ignore those modules.

But I thought that other people might find the data useful or interesting.

Send to Kindle


Sometimes it’s good to just take a new idea and hack on it for a couple of hours to see what happens. That’s what I’ve done this evening.

I’ve been using Songkick for a while. Songkick is a web site that tracks users’ attendance at gigs. I’ve been tracking the gigs I’ve been going to as well as trying to fill in over thirty years of old gigs.

I’ve known for some time that Songkick has an API, but until yesterday the API has been for invited partners only. But yesterday on Get Satisfaction they announced that it was now public.

The public API doesn’t do that much yet. There are only four documented calls. But it’s already useful and I’m sure it will gain more functionality quickly.

And this evening I’ve spent some time writing a very simple Net::Songkick module. This is really just a proof of concept, but I’ve got big plans for improving it. And I can already write a useful program like this:

If you have any interest in gigs then I highly recommend Songkick to you. And if you like attending gigs and hacking Perl (although not necessarily at the same time) then why not give Net::Songkick a try. All you’ll need is an API key from Songkick.

There’s a Github repository too; if you feel like hacking on it…

Send to Kindle

Learning About Traits

I’ve been teaching basic Moose in my training courses for several years now. And, as I’ve mentioned before, I’ve been slowly converting some of my CPAN modules to use Moose. But there are still bits of Moose that I haven’t really needed to get to grips with.

One such area is Moose’s support for Traits. Oh, I knew vaguely what they were and I understood why you might use them. But I’d never implemented a system using traits, so my knowledge about how you’d actually use them was a bit shaky to say the least.

But over the last few days I’ve learned quite a lot about how to use traits. And I’ve had to learn it pretty quickly.

It all started a few weeks ago when I got a github pull request from Oliver Charles. Oliver had taken a fork of my Perlanet repository and had massively refactored the codebase so that all the clever bits were implemented as traits.

What this means is that the core Perlanet code is pretty dumb. In order to do anything really useful with it to need to add in some traits. There are traits to read the configuration from a YAML file, traits to carry out various kinds of cleaning of the input and a trait to produce the output using the Template Toolkit. There are also traits to handle caching and OPML generation. All in all it makes the code far nicer to work on.

Oh, and there’s a Perlanet::Simple module which uses all of the traits required to implement the Perlanet behaviour that users currently expect.

There were a few problems with Oliver’s initial version. Some of the dependencies weren’t quite right. But we soon fixed that and last week I finally released Perlanet 0.47 which implemented these changes.

Then I installed it on the server which hosts most of my planets. And everything broke.

So I’ve spent a lot of the weekend fixing these issues. Part of it was that Oliver’s changes assumed some configuration file changes that I hadn’t implemented. I changed his changes so that they worked with the existing configuration settings (we don’t want users having to change configuration files unnecessarily). Other changes were harder to track down. I particularly enjoyed one where no feeds were fetched unless the user turned on OPML support. I learned a lot about how traits worked by tracking that one down.

But it all seems to be fixed now. Perlanet version 0.51 is available on CPAN and it will hopefully be a lot easier to customise to your needs. I hope we’ll see a number of other Perlanet traits appearing over the next few months.

And, most importantly, I’ve learnt a lot about traits. I think I understand them now.

If you want to learn traits, I can highly recommend asking someone to implement traits in one of your projects. And it’s even better if they do it in a slightly broken way so that you need to debug it.

Send to Kindle