forked from SBECK-github/App-CPANtoRPM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
1114 lines (833 loc) · 42.7 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
NAME
cpantorpm - An RPM packager for perl modules
SYNOPSIS
cpantorpm [OPTIONS] MODULE
This script takes a perl module and creates an RPM for it.
DESCRIPTION
This script automates the entire process of obtaining a perl module and
turning it into an RPM package. This includes the steps of obtaining the
module distribution, creating an RPM from it, and then making the
package available in various ways.
The following steps are involved in this process, and are discussed in
more detail below:
Obtain the perl module
Parse various perl modules files for necessary information
Build the package
Generate a spec file
Create the RPM packages
Sign the RPM packages (optional)
Install the RPM (optional)
Store the RPM in a local yum repository (optional)
OPTIONS
General Options
The following general purpose options exist.
-h/--help
Prints a help message describing command usage.
-v/--version
Prints the version of this program.
-D/--debug
Enable verbose debugging output.
-t/--tmpdir DIR
The cpantorpm script makes use of a default directory to store all
of it's working files in. It defaults to:
/tmp/cpantorpm
but can be set explicitly with this option.
-f/--optfile FILE
All of the options below that may be specified on the command line
may also come from a config file. The config file may contain the
options for any number of modules and is described below.
Obtain the perl module Options
The following options affect how a module is downloaded.
-c/--cpan
When downloading modules from CPAN, the script will first try to use
CPANPLUS and, if that is not available, it will use CPAN. If this
option is included, only CPAN will be tried.
--extracted DIR
Occasionally, the archive file on CPAN is broken in that the archive
file (minus the relevent suffixes) is not the same as the archived
directory.
For example, the archive Foo-Bar-1.00.tar.gz contains the directory
Foo-Bar instead of Foo-Bar-1.00 .
Set DIR to be the name of the directory that it contains.
Module Description Options
Once the module is downloaded, it will be analyzed and various
information about the module which will be used in creating the RPM is
gathered. This includes looking at the perl META files, the main POD
document, and the build scripts (Makefile.PL or Build.PL).
The following options impact these operations:
--name NAME
By default, the name of the package will be obtained from the
distribution name. This option can be used to explicitly set the
name, overriding the distribution name.
NOTE: the name of the RPM will be based on this, but will typically
have a prefix added. See the --prefix and --no-prefix options below
for more details.
--summary TEXT
Every package has a 1-line summary description. By default, this
comes from the main POD document or the META files, but can be
explicitly set using this option.
--description FILE
Every package has a multi-line description. To override the
description that comes from the POD document, put the description in
a local file, and pass that file name to this option.
--mainpod FILE
The description and summary of the module typically come from the
main POD document, if it can be determined using the normal methods
described below.
In a few cases (where the POD document is named in some non-standard
way), it may not be possible to determine which is the main POD
document. In this case, you can specify it using this option.
FILE is the path to the file relative to the top level in the module
distribution. For example, it might be:
lib/Foo/Bar.pm
--author AUTHOR
This lists an author for the module, overriding the values from the
META files. This option can be included multiple times for multiple
authors.
--vers VERSION
This specifies the version of the RPM. It defaults to the version of
the package, but can be overridden here.
SPEC File Options
The following options are used during the SPEC file creation step:
-n/--no-tests
--NO-TESTS
When creating a module RPM, typically, the module tests are run as
part of the process. These two options can be used to modify this
behavior.
The first will add the lines necessary to run the tests to the SPEC
file, but (by use of an environment variable), the tests will not be
run when the RPM is created. In this instance, if the SPEC file is
used to create an RPM at some later date, the tests will run (unless
the environment variable RPMBUILD_NOTESTS is set).
With the second option, the lines necessary to run the tests will
not be added to the SPEC file at all.
-d/--no-deps
--NO-DEPS
By default, when building an RPM, the prerequisites for the module
will be tested.
There are three types of prerequisites:
prerequisites to build the module
prerequisites to run the module tests
prerequisites to use the installed module
It is slightly unfortunate that RPM only recognizes two types. There
is no way to specify requirements to run tests.
As such, the build requirements will include those requirements to
run the tests unless the --NO-TESTS option is given. In this case,
requirements to run the tests will be omitted.
If the --no-deps option is given, dependencies will not be tested
(though they will be added to the SPEC file).
If the --NO-DEPS option is given, dependencies will not be added to
the SPEC file at all.
In addition, if either of these are given, --no-tests is implied.
--no-compat
By default, the SPEC file includes a line of the form:
Requires: perl(:MODULE_COMPAT_ ...
This is recommended in the fedora packaging guidelines, so is
included by default. Some linux distros may not have a version of
perl that provides a MODULE_COMPAT, so in these cases, you may need
to omit this from the spec. Use this option to do so.
--prefix PREFIX
--no-prefix
By default, a prefix of 'perl-' is added to the name of the package
(or the name supplied using the --name option).
To specify that no prefix be added, use the --no-prefix option. To
specify an alternate prefix, use the --prefix option.
-p/--packager PACKAGER
Use this option to specify the name of the packager. The name of the
packager may be suplied using the '%packager' macro in the
~/.rpmmacros file. If it is not there, this option must be included.
--rpmbuild DIR
RPMs are built in the RPM build hierarchy. This defaults to the
value of the '%_topdir' macro, or it can be specified using this
option.
If this option is used, the path must be fully specified. A relative
path will not work.
The directory will have the following subdirectories:
BUILD
SOURCES
SPECS
SRPMS
RPMS
--clean-macros
By default, macros included in the existing ~/.rpmmacros file will
be used. With this option, that file is temporarily removed (it will
be restored when the script exits).
--group GROUP
Every package is a member of a group. If this is not specified, it
defaults to:
Development/Libraries
--release STRING
--disttag STRING
The full name of an RPM is something like:
foo-bar-1.00-1a-noarch.rpm
The string '1a' here consists of the release (1) and a disttag (a).
By default, release is '1' and disttag is the macro '%{?dist}', but
these can be overridden with these options.
--epoch EPOCH
This sets an epoch number in the RPM when the version number is not
sufficient to determine the relative age of two different versions.
--add-require FEATURE[=VERS]
--add-provide FEATURE[=VERS]
Every RPM has a list of features that are required in order to use
it, and a list of features that it provides.
In some cases, you may need to add featurs to these two lists. Both
options may include a version:
--add-requires Foo::Bar=0.45
--rem-require FEATURE
--rem-provide FEATURE
Related to the previous options, these options allow you to remove a
feature from the requirements list, or the list of features
provided.
--repl-require FEATURE=VERS
--repl-provide FEATURE=VERS
Occasionally, the module author explicitly defines the version of a
feature that is required, or provided by this module, in a way that
breaks things.
These options (which can be included any number of times) will
replace the version for either a required feature or a provided
feature as they will appear in the spec file. That way, for example,
you can make the version of the requirement match what is provided
in other RPMs.
For example, if the perl RPM that is installed on the system
provides the feature perl=5.24.1 but the module requires
perl=5.008001, rpmbuild may fail because it doesn't know how to
compare these two version numbers to know whether the requirement is
met. When this happens, rpmbuild will fail due to missing
dependencies.
In this cae, you could reformat the dependency version by passing
in:
--repl-require perl=5.08.1
-m, --macros
Use the macro form of common SPEC constructs over the environment
variable form (e.g. %{buildroot} vs $RPM_BUILD_ROOT).
--build-rec, --test-rec, --runtime-rec
Many modules have a list of modules that are recommended to be
installed at build time, test time, or at run time, but they are not
absolutely required. By default, these modules will not be included
as requirements for the various steps. Adding these options will
require them.
Module Build Options
The perl module must be built as part of the process. The following
options are used during the build:
--build-type TYPE
TYPE must be 'make' or 'build' and specifies that the build must be
done using the Makefile.PL or Build.PL files respectively (for those
modules that have both). If that file does not exist, an error is
triggered.
--config STRING
The given string is passed to either the 'perl Build.PL' or 'perl
Makefile.PL' command used to configure the module and create a Build
script or a Makefile. This option can be passed in any number of
times, but only a single option should be included in each STRING.
STRING is passed in as a command line argument:
perl Makefile.PL STRING
perl Build.PL STRING
Since the arguments passed in differ when using a Makefile.PL and a
Build.PL procedure, for safety, you should always include the
--build-type option when using this option.
--build STRING
Similar to the --config option except this passes strings which are
passed to either the './Build' or 'make' command used to actually
build the module. This option can be passed in any number of times.
--config-input STRING
Sometimes, the configure step prompts for input that cannot be set
using an environment variable. In this case, this option may be used
to pass in a single line of input to the 'perl Build.PL' or 'perl
Makefile.PL' command used to configure the module and create a Build
script or a Makefile. This option can be passed in any number of
times, but each value should include a single line of input. This
will result in the following:
echo STRING | perl Makefile.PL
echo STRING | perl Build.PL
Since the arguments passed in differ when using a Makefile.PL and a
Build.PL procedure, for safety, you should always include the
--build-type option when using this option.
--build-input STRING
Similar to the --config-input option except this passes strings
which are passed to either the './Build' or 'make' command used to
actually build the module. This option can be passed in any number
of times.
-T/--install-type TYPE
-i/--install-base DIR
These options allow you to specify where the module will be
installed. By default, the module will be built to install in the
standard perl location. In most cases, that would mean installing
the module, documentation, and scripts in:
BASEDIR/lib/perl5/PERLVERS
BASEDIR/man
BASEDIR/bin
where BASEDIR is the place where perl is installed (which is
typically /usr) and PERLVERS is the version directory (i.e. 5.14.2).
To install in /usr/local instead of /usr, just use the option:
--install-base /usr/local
To change the module installation directory (but not the directory
of the documentation or scripts) to either the site_perl or
vendor_perl location, use:
--install-type site
--install-type vendor
to set the module directory to be:
BASEDIR/lib/perl5/site_perl/PERLVERS
BASEDIR/lib/perl5/vendor_perl/PERLVERS
respectively.
The --install-type value must be one of:
perl (or core)
site
vendor
and defaults to 'perl'. 'perl' and 'core' are synonyms. If this is
passed in, it will override any default value set in the Makefile.PL
or Build.PL scripts (so be careful about rebuilding core modules).
--mandir STRING
When specifying a prefix (using the --install-base option), it is
necessary to determine where man pages should be installed relative
to this directory.
Most of the time, this can be determined automatically, but if your
version of perl installs man pages by default in a completely
separate location from where it installs libraries, it may not be
able to be determined correctly and should be specified using this.
The only time this would happen would be if the man pages were
installed in one hierarchy and the libraries in a completely
different hierarchy (i.e. man pages in /usr and libraries in /opt
for example).
--patch FILE
--patch-dir DIR
--script FILE
--script-dir DIR
In a few cases, a distribution cannot be properly packaged unless it
is first modified. The modification can be done by applying a patch,
or by running a script, or both. Patches are applied first, followed
by scripts.
To specify a patch file or script file, use the --patch or --script
options. Alternately, you can specify a directory containing files
named PACKAGE.sh or PACKAGE.diff where PACKAGE is the string that
was passed in on the command line.
By default, no patch or script will be used. They will only be used
if one of these options is given.
Scripts and patches will both be applied while in the top directory
of the package (i.e. the directory where a Makefile.PL or Build.PL
script exists).
The --script-dir option has a second use. If there is a file named
PACKAGE.build-sh in it, the lines in that file are added to the SPEC
file at the end of the %build step.
Options Controlling Cpantorpm Steps
To control what steps get done, the following options are available:
--spec-only
By default, the script creates a SPEC file, and then builds RPMs
(both source and binary).
With the --spec-only option, the SPEC file is created, but no
further action is taken.
--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.
-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.
-I/--install
--install-new
--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
sudo.
By default, the '-U' flag is given to the 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 --install-new option is given, the '-i' option will be passed
to the rpm command and the RPM will only be installable if it is a
new package.
If the --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.
-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.
Misc Options
The following misc. options are also available:
--gpg-path PATH
--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.
--gpg-password PASSWORD
--gpg-passfile FILE
When signing a package, this script become interactive unless expect
(or perl 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.
--env VAR=VAL
Sets an environment variable before building the package. This
option can be used any number of times.
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:
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:
.tar
.tar.gz
.tgz
.tar.bz2
.zip
Standard install script
The module must contain either a Build.PL or Makefile.PL script. A
module using some other non-standard build procedure cannot be built
with this script.
Getting the module in each of the 4 ways requires different system
requirements. In general, the script will try several different ways to
get the module, and will only fail if all of the different methods fail.
The following system requirements exist for the different ways of
obtaining a module:
From a local directory
You must be able to run the system command 'cp -r' (to recursively
copy a directory) or be able to load the module
File::Copy::Recursive.
From a local file
You must be able to run the system command 'cp' (to copy a file) or
be able to load the module File::Copy.
In addition, you must meet additional requirements for working with
the different types of archives as described next.
From a URL
To get a module from a URL, you have to have one of the following
packages installed:
curl
wget
lynx
links
lftp
or be able to load one of the modules:
LWP::UserAgent
HTTP::Lite
In addition, you must meet additional requirements for working with
the different types of archives as described next.
From CPAN
To get a module from CPAN, you must be able to load one of the perl
modules:
CPANPLUS::Backend
CPAN
In addition, you must meet additional requirements for working with
the different types of archives as described next.
In each case (except for obaining a module from a local directory), once
you have obtained the archive, you need to be able to extract it.
To do this, you need to meet the system requirements for the appropriate
type of archive:
.tar, .tar.gz, .tgz files
You need to be able to run the system 'tar' command, or be able to
load one of the perl modules:
Archive::Extract
Archive::Tar
These modules will make use of other modules to handle .gz or .bz2
compression.
.zip files
You need to be able to run the system 'unzip' command, or be able to
load one of the perl modules:
Archive::Extract
Archive::Zip
Once the package is obtained, in some cases it may be necessary to apply
patches or run a script in it to fix things that make it not suitable
for packaging.
PARSE VARIOUS PERL MODULES FILES FOR NECESSARY INFORMATION
Building an RPM correctly involves getting a great deal of information
from the module. We have to know what features are provided by this
module, what features are required by the module to run, as well as the
description of the module, the author, etc.
This information can be obtained by a number of different files
including:
Makefile.PL, Build.PL
Currently, these are only used to determine how the module should be
built. Although they typically contain a great deal more
information, it is written as perl code and there is no reasonable
way to get the information from them.
However, one of the steps done by this script is to actually build a
Build script or Makefile (this ensures that the perl module can be
correctly built), and information can be extracted from them since
they do follow regular formats.
META.json, MYMETA.json
For a description of the type of data stored here, please refer to
the CPAN-Meta documentation on CPAN.
In order to interpret a JSON file, you have to be able to load one
of the following perl modules:
Parse::CPAN::Meta 1.40
JSON
JSON::XS
JSON::PP
JSON::DWIW
Most of the information can be obtained from a complete JSON file.
META.yml, MYMETA.yml
For a description of the type of data stored here, please refer to
the CPAN-Meta documentation on CPAN.
In order to interpret a YAML file, you have to be able to load one
of the following perl modules:
YAML
YAML::Syck
YAML::XS
YAML::Tiny
Most of the information can be obtained from a complete YAML file.
Pod file
In most instances, some of the information (primarily the summary
and description of the module) must be obtained from a pod document.
This will require one of the modules:
Pod::Select
Pod::Simple::TextContent
The script will need to determine which POD file to get this
informaion from (the primary POD file for the package). Most of the
time, the script is able to determine which file to use, but if it
fails, it can be manually specified using the --mainpod option.
BUILD THE PACKAGE
The next step is to actually build the module.
This step is a departure from the way cpanspec and cpan2rpm work. In
both of these scripts, the SPEC file contains the procedure for building
the perl module, but it is never tested to see if it works.
This has a couple significant advantages:
It ensures that the package builds
A number of perl modules cannot be built automatically because the
scripts are interactive. Unfortunately, the RPM build process does
not handle this well, so what you end up with is a hanging process
that (eventually) you will have to kill by hand. In other cases, the
build process fails for other reasons.
When the build process is put in the SPEC file untested, the RPM
build process will either fail or hang.
This script avoids many of those problems.
It generates additional meta data
Both cpanspec and cpan2rpm would interpret the Makefile.PL and
Build.PL scripts directly to obtain information from them. Since
there is no guarantee that these scripts follow any convention, I
considered this a very poor option.
By actually building the module, it creates either a Makefile or a
_build hierarchy, and these DO follow regular conventions, and
information can be obtained from them with a much greater chance of
success.
This script actually builds the module to ensure that it can be done. 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.
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 --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 ~/.rpmmacros file present, the
~/.rpmmacros file must not contain the macro %_topdir that is different
than the one specified by the --rpmbuild option. If the macro does
exist, you can use the --rpm-clean option to specify a clean version of
the .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.
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.
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 expect program is installed or the perl
Expect module is available, signing can be done non-interactively if
either the --gpg-passwd or --gpg-passfile options are passed in.
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 sudo to run
the rpm command.
STORE THE RPM IN A LOCAL YUM REPOSITORY
This is an optional step.
If the --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 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'.
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"
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 cpan or cpanp at the
command line and have it work.
If you will be applying patches to a package, you will need the 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 rpmbuild program.
This script also relies on the 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,
strace can be used to determine that.
In order to sign packages, you must have the 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 Expect module or the expect
program installed.
In order to install the package, you either must be running as root, or
have the sudo program. The 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.
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.
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.
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.