App-CPANtoRPM
view release on metacpan or search on metacpan
bin/cpantorpm.pod view on Meta::CPAN
=item B<--spec-only>
By default, the script creates a SPEC file, and then builds
RPMs (both source and binary).
With the B<--spec-only> option, the SPEC file is created, but no
further action is taken.
=item B<--no-clean>
By default, the build tree will be removed after the RPM is built.
If this option is given, it will be left in place.
=item B<-s/--sign>
If this option is given, a GPG signature will be added to the package.
It should be noted that this step is often interactive, so if the
installation process is scripted in any way, adding this option may
interfere with the process.
Please refer to the secrtion SIGN THE RPM PACKAGE for more information.
=item B<-I/--install>
=item B<--install-new>
=item B<--install-force>
If any of these options are given, cpantorpm will attempt to install
the RPM on the system after it is built. If you are running as root,
this will be done by simply running the appropriate rpm command. If
you are running as any other user, the command will be run using
B<sudo>.
By default, the '-U' flag is given to the B<rpm> command which will cause
it to install the RPM if it is a new package, or an upgrade to an existing
package.
If the B<--install-new> option is given, the '-i' option will be passed
to the B<rpm> command and the RPM will only be installable if it is a new
package.
If the B<--install-force> option is used, the flags '-U --force' will
be used which will replace an existing package, even if the same
version is already installed.
=item B<-y/--yum DIR>
If this option is given, the RPMs (both binary and source) will be
copied to a local yum repository once they are built.
=back
=head2 Misc Options
The following misc. options are also available:
=over 4
=item B<--gpg-path PATH>
=item B<--gpg-name NAME>
These options are used to set the path the the GPG directory (which
contains the keyring) and the name of the key that will be used.
=item B<--gpg-password PASSWORD>
=item B<--gpg-passfile FILE>
When signing a package, this script become interactive unless B<expect>
(or perl B<Expect>) is available. If one of these is available, the
password can be passed in at the command line (or a file containing the
password) using one of these two commands.
=item B<--env VAR=VAL>
Sets an environment variable before building the package. This option
can be used any number of times.
=back
=head1 OBTAIN THE PERL MODULE
The perl module may be obtained in a number of different ways. The
perl module may exist on local disk either as an archive file or a
directory, or it can be retrieved from a URL or from CPAN.
For example, any of the following ways could be used:
cpantorpm Foo::Bar
cpantorpm http://some.host.com/some/path/Foo-Bar-1.00.tar.gz
cpantorpm /tmp/Foo-Bar-1.00.tar.gz
cpantorpm /tmp/Foo-Bar-1.00
When working with a CPAN module, you must use the form:
Foo::Bar
instead of a file form:
Foo-Bar
Foo-Bar-1.00
Foo-Bar-1.00.tar.gz
These are not currently supported.
When downloading from a URL, both ftp:// and http:// URLs are
supported (though others such as file:// and https:// are not
supported at this time).
For this script to work, the perl module must meet a few validity
requirements:
=over 4
=item Valid name format
The name of the distribution must be of the form:
PACKAGE-VERS
if obtained from a local directory, or
PACKAGE-VERS.EXT
if obtained from an archive (a local file, a URL, or from CPAN). Here
VERS is any string which does NOT contain a dash (-). EXT may be any
of the following extensions:
bin/cpantorpm.pod view on Meta::CPAN
It watches the process to see if it enters a state where it's waiting
for user input, and if it does, the process ends and the RPM is not built,
and you can then go in and correct the problem (typically by installing
some build prerequisite, or supplying a non-standard option to the
build process, or in the worst case, by providing a patch to the module
source that removes the interactive nature.
=head1 GENERATE A SPEC FILE
Much of the process of generating a spec file is taken from the
cpanspec package.
The first step in creating a SPEC file is to determine where the
RPM build hierachy lives (since that is where the SPEC file will live).
This script supports using the standard build hierarchy, or specifying
an alternate location.
If the B<--rpmbuild> option is used, it is used to specify the location
of the build hierarchy. Otherwise, the standard location will be used.
If a location is specified, and if there is a B<~/.rpmmacros> file present,
the B<~/.rpmmacros> file must not contain the macro B<%_topdir> that is
different than the one specified by the B<--rpmbuild> option. If
the macro does exist, you can use the B<--rpm-clean> option to specify a
clean version of the B<.rpmmacros> file be used.
The SPEC file created by this script does deviate from the recommended
form in one respect. The recommended way to handle the list of
requirements and the list of features provided by an RPM is to leave
out these lists in the SPEC file and allow rpmbuild to generate them
automatically. In the SPEC file, you only list changes to the
defaults. In other words, you can add features that are required or
that the package provides that were not picked up automatically, or you
can add lines to the SPEC file to filter out features that you do not
want the rpm to depend on or provide.
Unfortunately, even though adding prerequisites and provided features
works well, removing them does not work nearly as smoothly. The
methods for filtering prerequisites and features does not work well
cross platform (attempts that worked for redhat would not work for
openSuSE for example).
As a result, I do not let the SPEC file tell rpmbuild to generate these
lists. Instead, I generate the lists (using the standard rpm utilities
when available, or using an included script when they are not) and
explicitly put them in the SPEC file.
=head1 CREATE THE RPM PACKAGES
Once the SPEC file is done, the RPM can be created using the standard
RPM tool 'rpmbuild'.
It uses the standard RPM file structure and creates both a source RPM
and a binary RPM.
=head1 SIGN THE RPM PACKAGES
This is an optional step. If can be used to embed a GPG signature in
the package.
In order sign a package, you must have a GPG key available. You must
have the gpg package installed on your system and you must have at least
one GPG key created.
The path to the GPG directory be specified by one of the following:
the value of the --gpg-path option
the value of the %_gpg_path rpm macro
the value determined by gpg using any currently
set environment variables
If no keyring is found, signing is not available.
The key to use is specified by:
the value of the --gpg-name option
the value of the %_gpg_name rpm macro
the only key in the keyring (if the keyring
contains exactly one key)
If the key cannot be uniquely determined, signing is not available.
The rpm command to sign a package is interactive. In order to script
everything, it is necessary to use a tool like expect. If such a tool
is not available, and if you are signing packages, this script will be
interactive. Currently, if the B<expect> program is installed or the
perl B<Expect> module is available, signing can be done non-interactively
if either the --gpg-passwd or --gpg-passfile options are passed in.
=head1 INSTALL THE RPM
This is an optional step.
After the RPM is successfully built, it can be installed on the system.
This will be done in one of two ways. If you are running this as root,
it will simply use the rpm command. Otherwise, it will use B<sudo> to
run the rpm command.
=head1 STORE THE RPM IN A LOCAL YUM REPOSITORY
This is an optional step.
If the B<--yum DIR> option is passed in, the RPMs (both source and
binary) are copied in to a local yum repository. The repository is
stored at B<DIR> and should have the following directories:
RPMS
SRPMS
RPMs will be stored in either the RPMS/<arch> directory (if it exists)
or directly in the RPMS directory. <arch> is typicall something like
'noarch' or 'x86_64'.
=head1 CONFIG FILE
A config file can be created which sets options on a per-module
basis. It can be either a YAML file (ending in .yaml or .yml) or
a JSON file (ending in .json).
A sample YAML file is:
---
Crypt::SSLeay:
- --config=--default
Foo::Bar:
- --name Foobar
Each line should contain one option of any of the forms:
--opt=val
--opt val
-o val
If val contains spaces, you should NOT put quotes around it. Use:
--summary This is the summary
instead of:
--summary "This is the summary"
=head1 SYSTEM REQUIREMENTS
This script will try to function under many different situations, and
it will often try multiple methods to accomplish a task, and many of
those methods will be available on any common linux configuration. As
such, a rigorous list of system requirements is overly complicated and
won't be listed here. In the event that the script fails, it will list
the methods tried and you can make sure that one of them will function
on your host.
The most common requirements will be listed here. In all probability, if
you meet these requirements, this script will run.
Since the most common way to obtain a module will be from CPAN, you will
need one of the following modules installed and correctly configured:
CPAN
CPANPLUS
To make sure it's configured, make sure you can run B<cpan> or B<cpanp>
at the command line and have it work.
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
( run in 1.144 second using v1.01-cache-2.11-cpan-df04353d9ac )