openSUSE:Packaging Perl

Jump to: navigation, search


The Packaging Perl is a step by step introduction on how to build Perl software packages for openSUSE and others using the Open Build Service.

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