App-CPANtoRPM

 view release on metacpan or  search on metacpan

bin/cpantorpm.pod  view on Meta::CPAN

If you will be applying patches to a package, you will need the B<patch>
command.

You also need to be able to read both YAML and JSON files included
in almost every module.  This means that you will need one JSON
module installed out of the following:

   JSON
   JSON::XS
   JSON::PP
   JSON::DWIW

and one YAML module from the following:

   YAML
   YAML::Syck
   YAML::XS
   YAML::Tiny

You will also need to be able to examine POD files using one of the
following modules:

   Pod::Select
   Pod::Simple::TextContent

You'll should have:

   Module::Build
   Module::Build::Tiny
   ExtUtils::MakeMaker

installed in order to build modules that use the Build.PL and Makefile.PL
scripts (both Module::Build and Module::Build::Tiny are supported).

In order to build the rpm, you need the B<rpmbuild> program.

This script also relies on the B<strace> program.  This is necessary
because many Makefile.PL and Build.PL scripts are interactive so when
you run them, they hang waiting for input.  Unfortunately, I was not
able to find any pure perl way to run a program as a child (or in a
thread) and monitor it to see if it's still running because it's doing
work, or still running because it's waiting on user input.  Though
somewhat crude, B<strace> can be used to determine that.

In order to sign packages, you must have the B<gpg> program installed,
and you must have a key set up to sign with.  In order to do this
non-interactively, you also need either the B<Expect> module or the
B<expect> program installed.

In order to install the package, you either must be running as root, or
have the B<sudo> program.  The B<sudo> command may be interactive,
depending on how you have it set up.

In order to install RPMs in a yum repository, the repository must exist.

=head1 HISTORY

This script is based loosely on Erick Calder's cpan2rpm script and
Steven Pritchard's cpanspec script.  Initially, I set out to modify
one or the other of them, but I found that the modifications that I
felt necessary were extensive enough that I decided a fresh
implementation was both faster and cleaner.

=over 4

=item cpan2rpm

cpan2rpm had basically the full functionality that I wanted.  It would
download a module, write a spec file for it, create an RPM, and then
install it.  The only functionality that was missing was some simple
functionality to add it to a local yum repository.  That would have been
very simple to add.  However, it suffered from several other significant
problems.

cpan2rpm is old.  It has not been supported since 2003.  It has
virtually no support for modules built using Build.PL scripts, and
adding it would have been quite complicated.

cpan2rpm is also not written as cleanly, or in a style that I'd like
to maintain, so it would take a bit of cleaning up to turn it into
something I'd want to maintain.

The main problem though is how it gets information from the
Makefile.PL script.  In order to get all of the information necessary
to create a SPEC file, there's a lot of information about the module
that needs to be examined.  Much of that information is stored in the
various META files in any new module distribution.  None of that is
used in cpan2rpm (which predates most of them), so that would have to
be added.  However, even with the META files, some information comes
from the Makefile.PL (or Build.PL script) such as the default install
location.

Since the data is in a script, cpan2rpm tries to be intelligent about
extracting the information.  It loads in the Makefile.PL script,
modifies it (by turning 'exit' into 'return') and evals it.  The
theory is that by eval'ing it, you end up with the appropriate data
structure that you can examine.

The modifications that it makes are completely unjustified though.  It
makes drastic assumptions about what the Makefile.PL file looks like,
and I can think of any number of cases where turning 'exit' into
'return' won't produce the result you want.

As such, cpan2rpm's handling of the Makefile.PL file needed to be
replaced entirely (and since that makes up a significant portion of
the script, that justified a complete rewrite).

In addition, if the script contained in Makefile.PL is interactive,
cpan2rpm hangs silently while trying to eval it, and there is no
easy way to determine what is causing it to hang.

=item cpanspec

cpanspec is much cleaner in most respects.  It is well written, handles
both Makefile.PL and Build.PL installs, and handles all of the new
META files.

However, it has a few other problems.

It was written specifically for redhat distributions (redhat, centos,
fedora) and hardcodes some of the redhat specific paths in it.  Other
RPM based distributions (such as OpenSuSE which I use) use different
paths.  At the very least, the cpanspec file would need to be modified
to add options to override the defaults.

cpanspec also makes assumptions about where you want to install the
modules.  It will only install in the vendor location of the primary
perl installation.  If you want to install them anywhere else, you
are out of luck.

But the single biggest weakness was how it handles the Makefile.PL and
Build.PL scripts.  Rather than evaluating the code, cpanspec just opens
them and tries to parse information from them.

Again, given that these are perl scripts, the only reliable way to
parse them is to actually use the perl interpreter.  Although most
modern modules include Makefile.PL or Build.PL scripts that follow
certain conventions, it is by no means guaranteed, so I was not
satisfied with this assumption.

As with cpan2rpm, cpanspec does not deal with interactive installs.  It
simply shuffles the problem to another location.  In this case, once
the SPEC file is created, it is necessary to run rpmbuild, and this
will hang.

=back

Due to the weaknesses in both of the existing alternatives, I decided
a clean rewrite was in order.  The goals were:

=over 4

=item Beginning-to-end functionality

cpantorpm will download the module from CPAN, create the SPEC file,
generate an RPM, install it, and store the RPM in a local YUM repository
for other hosts to use.

=item Cross platform

cpantorpm will work on any RPM based distribution (though this is only
tested on redhat and OpenSuSE to date).  Also, many of the steps can
be done in many different ways, different one of which may be
available by default platforms, so most steps will try more than one
way to accomplish the task.

For example, to download a module, cpantorpm will use the CPAN module,
the CPANPLUS module, and various tools to download via HTTP (such as
wget, curl, etc.).

=item Correctly handle Makefile.PL and Build.PL

The only way to correctly handle these scripts is to actually build the
module.  The files generated contain all of the information in a
standard format, and we can get it without making any assumptions about
the format of these scripts.

=item Handle interactive installs

Many installs are potentially interactive.  If you are missing
prerequisites, many modules will stop and ask you if you want to
install them first.

cpantorpm traps this behavior and allows you to handle it, rather than
hanging for an unknown reason.

Note: by 'handle it', it will not try to install them.  Rather, the
cpantorpm script will let you know what was being asked, and then
exit, and at that point, it's up to you to correct the problem.  A
future version of cpantorpm may include some automatic handling of
missing prerequisites which is the primary cause of interactive
installs hanging.

=back

All that being said, I have borrowed ideas (and in rare instances,
code) freely from cpanspec and cpan2rpm.  I'm very grateful to the
authors of both cpan2rpm and cpanspec who's work has made mine much
easier.

Hopefully, cpantorpm takes the best of both worlds and improves on
that.

=head1 KNOWN BUGS

None known.

=head1 BUGS AND QUESTIONS



( run in 3.382 seconds using v1.01-cache-2.11-cpan-97f6503c9c8 )