openSUSE:Packaging Perl
Build Service Tutorial · Tips & Tricks · Cross Distribution Howto · Packaging checks
Desktop menu categories · RPM Macros · Scriptlets · Init scripts · How to write good changes
build tools
cpanspec
cpanspec is possibly the best tool to bring a CPAN package into the openSUSE buildservice. This is an example procedure packaging the perl module File::LibMagic for the buildservice:
zypper in cpanspec # if cpan was never used before, run it once and answer the questions cpan # if inside the cpan shell exit cd your_checked_out_build_service_project osc mkpac perl-File-LibMagic cd perl-File-LibMagic cpanspec -v File::LibMagic osc build --local # vi *.spec ... BuildRequires: perl(Other::Package) BuildRequires: libfile-devel ZZ osc ci
cpanspec will download the tar-ball from cpan, analyze it, and create perl-File-LibMagic.spec and an initial *.changes file. cpanspec is activly maintained in devel:languages:perl.
Unlike the original Fedora version at [1] this one is patched to suit the needs of our buildservice.
cpanspec_obs
An additional wrapper script cpanspec_obs is available for full automation of simple cases. The only requirements are that you navigate to a checkout directory of the obs project, where you want to submit a new perl package to, then call cpanspec_obs with the exact CPAN name, followed by an osc commit call.
cpan2spec
Is a misnomer. People say 'cpan2spec', when they mean 'cpanspec. See above.
cpan2dist
Writing spec-files for packaging perl modules is simplified by cpan2dist. It comes bundled with e.g. perl-5.10.0 and updates are available at CPAN and is developed at github.
This is an example procedure packaging the perl module File::LibMagic for the buildservice:
# add devel:languages:perl zypper ar http://download.opensuse.org/repositories/devel:/languages:/perl/openSUSE_11.2/devel:languages:perl.repo zypper in perl-CPANPLUS-Dist-RPM zypper in perl-CPANPLUS-Dist-SUSE
cd your_checked_out_build_service_project osc mkpac perl-File-LibMagic cd perl-File-LibMagic cpan2dist --format CPANPLUS::Dist::SUSE File::LibMagic osc vc perl-File-LibMagic osc add File-LibMagic*.tar.* perl-File-LibMagic.{changes,spec} osc build --local-package # vi *.spec osc ci
With version 0.01 of CPANPLUS::Dist::SUSE, the following items need attention:
- Group should be: Development/Libraries/Perl (almost good, "/Perl" is missing).
- BuildRequires: for non-perl packages (typically *-devel) are missing.
- Requires: for perl packages are often missing. Check Makefile.PL
- %install section should not do rm -rf %{buildroot}
- %install touches an empty %{buildroot}/%{_mandir}/man3/*.3pm.gz
- %install section has no %perl_process_packlist
- %install section has no %perl_gen_filelist
- %files section should use %files -f %{name}.files
- %bcond_with test
%if %{with test}
to make a slow test section optional. (osc build --with test)
- %description: no description found
- License: GPL or GPLv2 or GPLv3
An inofficial version 0.01.3 is available from devel:languages:perl, fixing most of the above. It also adds a few BuildRequires: and as an experiment, this:
BuildRecommends: perl(Test::CheckManifest)
This causes no error, but I've never seen it pull in Test::CheckManifest - ever. How should a Requires: tag be written, if it is needed at build time?
Instead of adding a copy of the tar-ball, a _service link containing the cpan-url of the tar-ball could also be used. See devel:languages:perl:CPAN for further examples.
What license to use for perl modules
The vast majority of perl modules carry a short notice of license terms at the end of the README file. Sometimes there is a LICENSE or COPYING file present in the package as well. If a perl module carries the license "under the same terms as Perl itself" (as it usually the case) then the spec file %License should read:
License: Artistic-1.0 or GPL-1.0+
If the license is not "under the same terms as Perl itself" then choose the appropriate spec file %License syntax from openSUSE:Accepted_licences#Good_Licenses (the Short Name category provides the string that should be entered in the spec file). For more complicated licensing scenarios more guidance is available from the Fedora Packager's Licensing Guidelines.
RPM_Macros for perl modules
(from openSUSE:Packaging_Conventions_RPM_Macros)
%if 0%{?suse_version} < 1120 BuildRequires: perl-macros %endif
Add the above BuildRequires, if you get error messages like
+ %perl_gen_filelist /var/tmp/rpm-tmp.6091: line 40: fg: no job control
Remove the above, if you need to build on SLE_11_SP2 .
%perl_archlib
Many perl packages are pure perl. And can be built noarch. If possible, add this to your specfile:
BuildArch: noarch
Otherwise, %perl_archlib is helpful.
This macro is substituted by the path where architecture-specific parts of Perl are installed, for example, /usr/lib/perl5/5.8.5/i586-linux-thread-multi
.
It is normally only used by the perl
package itself and by the macro %perl_process_packlist
. See below.
%perl_make_install
This macro does the make install call correctly on various products. Before SL 9.0, the normal way to invoke it was:
make PREFIX=$RPM_BUILD_ROOT/%_prefix \ INSTALLMAN1DIR=$RPM_BUILD_ROOT/%_mandir/man1 \ INSTALLMAN3DIR=$RPM_BUILD_ROOT/%_mandir/man3 \ install
For 9.0 and later versions:
make DESTDIR=$RPM_BUILD_ROOT install_vendor
With the macro %perl_make_install
, this is done correctly according to the version.
This example comes from the package perl-URI
:
%install %perl_make_install
%perl_process_packlist
This macro prepares some files, related to perl modules, for the final package. It does the following actions:
Each package including a perl module should call this macro in the section %install
.
for 0%{?suse_version} > 1130
- Searches for the installed
.packlist
files and removes them from$RPM_BUILD_ROOT%perl_vendorarch/auto
.
If %{_target_cpu} == noarch
then empty dirs are removed from $RPM_BUILD_ROOT%perl_vendorarch/auto
.
- Removes the
$RPM_BUILD_ROOT%perl_archlib/perllocal.pod
file.
This example is taken from the package perl-HTML-Parser
:
%install %perl_make_install %perl_process_packlist %perl_gen_filelist %files -f %{name}.files %doc Changes mkhctype mkpfunc README TODO eg %changelog
for 0%{?suse_version} <= 1130
- Removes
$RPM_BUILD_ROOT
from%perl_archlib/perllocal.pod
and renames the file to a package-specific file. See below for more details. - Searches for the installed
.packlist
files and removes$RPM_BUILD_ROOT
from them.
The file %perl_archlib/perllocal.pod
must be renamed because it contains information about additional installed perl modules and evidently cannot be installed at the same place from multiple packages. Therefore, it is renamed and a special SuSEconfig module, /sbin/conf.d/SuSEconfig.perl
, adds this information to the system %perl_archlib/perllocal.pod
after the package is installed.
%perl_gen_filelist
Since 11.2 (or with BuildRequires: perl-macros), more automation can be achieved like this:
%install %perl_make_install %perl_process_packlist %perl_gen_filelist %files -f %{name}.files %defattr(-,root,root,-) %doc README CHANGES COPYING
Note that this macro cannot see files that were not installed. Hence we still use %doc to collect important files directly from the source tree.
%perl_sitearch
This macro is substituted by the path where architecture-specific parts of Perl modules are installed by a local administrator (/usr/lib/perl5/site_perl/5.8.5/i586-linux-thread-multi
). The packages distributed within SUSE Linux use the path defined by %perl_vendorarch
instead. See below.
%perl_sitelib
This macro is substituted by the path where architecture-independent parts of Perl modules are installed by a local administrator (/usr/lib/perl5/site_perl/5.8.5
). The packages distributed within SUSE Linux use the path defined by %perl_vendorlib
instead (see below).
%perl_vendorarch
This macro is substituted by the path where architecture-specific parts of Perl modules are installed by a Linux vendor (/usr/lib/perl5/vendor_perl/5.8.5/i586-linux-thread-multi
). The macro is typically used in the file list. This example comes from the package perl-URI
:
%files [...] %{perl_vendorarch}/auto/URI
This path has been used since SL 9.0. Until then, the Perl modules were installed below /usr/lib/perl5/site_perl
using the macro %perl_sitearch
. The directory site_perl
is now intended for modules installed by a local administrator (see above at %perl_sitearch
).
%perl_vendorlib
This macro substitutes for the path where architecture-independent parts of Perl modules are installed by a Linux vendor (/usr/lib/perl5/vendor_perl/5.8.5
). The macro is typically used in the file list. This example comes from the package perl-URI
:
%files [...] %{perl_vendorlib}/URI.pm %{perl_vendorlib}/URI
This path has been used since SL 9.0. Until then, the Perl modules were installed below /usr/lib/perl5/site_perl
using the macro %perl_sitearch
. The directory site_perl
is now intended for modules installed by a local administrator (see above at %perl_sitelib
).
%perl_version
This macro is substituted by the version of Perl used for building the package, such as 5.8.5
. It is used in packages providing a perl module to define the dependency on Perl.
In older repositories, it was typically used the following way.
Requires: perl = %{perl_version} # deprecated, use %perl_requires
%perl_requires
Since 11.4 the requirement for the current version of perl should be written as:
%if 0%{?suse_version} < 1140 Requires: perl = %{perl_version} %else %{perl_requires} %endif
Before 11.4, we need an explicit 'Requires' using the %perl_version macro.
Please note that e.g. quilt on 11.3 no longer works when using this macro.
%__perl
The name of the perl that is installed in the system.
Trouble with rpmlint
auto directory is included
The build aborts with
... running 04-check-filelist ... checking filelist perl-File-MMagic-XS: auto directory is included in the perl package
This is typically seen when your spec-file has
%files [...] %{perl_vendorlib}/*
As would be the default with spec-files created by cpan2dist from perl-5.10.0 . This glob includes %{perl_vendorlib}/i586-linux-thread-multi/auto, if your package contains some *.so libraries. It must not include the '*/auto' directory itself; only contents and subdirectories.
%files [...] %{perl_vendorlib}/*/auto/* %{perl_vendorlib}/*/File %{perl_vendorlib}/*/File/*
would work for a File::* module. See also %perl_gen_filelist above for a possibly better solution.
Linking fails with: undefined reference to "function name"
If you get errors that you have undefined references, but the needed libraries are defined, this means that the linking order isn't correct. All libraries in openSUSE > 1110 are linked with the ld flag --as-needed. Lets look at an example:
Assume that you built a static library libwurst and it uses the pow() function from the math library.
$ gcc -Wl,--as-needed --static main.c -o wurstsalat -L. -lm -lwurst ./libwurst.a(wurst.o): In function `wurst': wurst.c:(.text+0x29): undefined reference to `pow'
The problem here is, that the linker doesn't find any reference to pow() in main.c. Then the first library is libm and as it is not needed, the linker skips it. So you have to link against libwurst.a before you link against libm.
$ gcc -Wl,--as-needed --static main.c -o wurstsalat -L. -lwurst -lm
To summarize it: When using --as-needed, the order in which the libraries appear in the command line is relevant: any library X must precede all libraries Y that offer symbols that X uses.
If your package is too complex or you lack the experience with patching, add in your %build section:
export SUSE_ASNEEDED=0
That will skip the part with --as-needed aswell.
For further details see http://www.gentoo.org/proj/en/qa/asneeded.xml#doc_chap2
Create man pages out of perl documentation
If your scripts already contain some help documentation following the standard Perl documentation guidelines, you might consider creating the requested man pages out of this documentation to avoid to maintain an extra man page.
Here is a short script that you can use as additional source named create_manfile.pl in your package:
#!/usr/bin/perl use Pod::Man; my $parser = Pod::Man->new (release => $ARGV[0], section => $ARGV[1]); $parser->parse_from_file ($ARGV[2], $ARGV[3]);
Needed snipplets for the spec file
In the spec file header:
Source4: create_manfile.pl BuildRequires: perl(Pod::Man)
In the %install section (please replace $location_of_your_installed_script and $manpage_name accordingly):
mkdir -p %buildroot/%_mandir/man1 perl %{SOURCE4} "%version" "1" %buildroot/$location_of_your_installed_script %buildroot/%_mandir/man1/$manpage_name.1
In the %doc section:
%doc %_mandir/man1/$manpage_name.1