Perl/Tips

This page is intended to be a repository of "gotchas", and other little quick fixes, that aren't rare but are just uncommon enough that you forget how you did it last time:) This page is NOT part of the official packaging guidelines.

= Module version dependencies too much specific =

Rounding approach
When writing (Build)Requires, you can find the package requires or uses module Foo in very specific version (e.g. ). If you just copy the version to spec file you can get unresolved depencecies because packaged perl-Foo's provide shorter version numbers (e.g.,  ,  ).

This is caused by the fact that Perl processes version strings as fractional numbers, but RPM as integers (e.g. RPM compares 0 to 0, and 2001 to 30).

There is no right solution. Current practice is to round dependency version up onto the the same number of digits as package version. (e.g.  becomes  ). Of course this approach is meaningful only if current perl-Foo package has at least version 0.21.

If required package does not exist in requested version, the dependency package must be upgraded before (if upstream provides newer (e.g. version 0.30)). If highest upstream provides 0.2001 only, dependency package can be upgraded to provide perl(Foo) = 0.2001, however its maintainer must keep using augmented precision in future versions (e.g. instead of  she must write  ) not to break RPM version comparison (each newer packager must have EVR string greater than previous one).

Dot approach
In the feature, one could consider different less error-prone approach: Instead of version rounding, one could transform each fraction version digit to next level version integer.

E.g. CPAN 12.34 became RPM 12.3.4. This method preserves ordering of fraction numbers, allows extending to more specific numbers and does not request package maintainer to remember number of augmented digits he needs to support in his SPEC file.

One must note that transition to this method can happen only at major version number change (the part before decimal dot) or at cost of new RPM epocha number.

See perl-Geo-IPfree.spec for live example.

= Version contains underscore = Sometimes it is needed update to development release marked with something like _01. To be 100% sure, you should use in spec file: %real_version 1.32_01 Version: 1.32.1

Beware underscores in code if not evaluated can produce warnings and program aborts in strict mode (examplary bug): $VERSION = "1.32_01";

This must be solved by adding eval and reported to upstream as a bug (see Version Numbering in perlmodstyle(1)):

$VERSION = "1.32_01"; $VERSION = eval $VERSION;

= Makefile.PL vs Build.PL =

Perl modules typically utilize one of two different buildsystems:


 * Ext Maker
 * Ext Utils::Make Utils::Build is the (relatively) new kid on the block, with support for things Make Maker cannot do.  While the ultimate choice of which system to employ is clearly in the hands of upstream, if Build.PL is present in a distribution, the packager should employ that build framework, unless there is an awfully good reason otherwise.

= Tests =

Tests / build steps requiring network access
This happens from time to time. Some package's tests (or other steps, e.g. signature validation) require network access to return success, but their actual execution isn't essential to the proper building of the package. In these cases, it's often nice to have a simple, transparent, clean way of enabling these steps on your local system (for, e.g., maximum testing), but to have them disabled when actually run through the buildsys/mock.

One easy way to do this is with the "--with" system of conditionals rpmbuild can handle. Running, e.g., "rpmbuild --with network_tests foo.src.rpm" is analagous to including a "--define '_with_network_tests 1'" on the command line. We can test for the existance of that conditional, and take (or not take!) certain actions based on it.

See, e.g., the perl-POE-Component-Client-HTTP spec file for an example.

One way to indicate this inside your spec is to prepend a notice along the lines of:


 * 1) some text
 * 2) about the change

Then, at the point of the operation, e.g. "make test", that needs to be disabled silently under mock to enable the package build to succeed:

%check %{?!_with_network_tests:rm t/01* t/02* t/09* t/11* t/50* t/54*}

make test

Now to execute local builds with the network bits enabled, either call rpmbuild with "--with network_tests" or add the line "%_with_network_tests 1" to your ~/.rpmmacros file. Remember to test with _with_network_tests undefined before submitting to the buildsys, to check for syntax errors!

Tests require X11 server
Some Perl bindings to graphical toolkits deliver tests that require access to X11 server. rpmbuild was changing his opinion on DISPLAY environment variable. Currently the variable is unset when running locally or in Koji. If you want to run X11 tests, and you want it, you can do it using Xvfb X11 server implementation:

%global use_x11_tests 1

%if %{use_x11_tests} BuildRequires: xorg-x11-server-Xvfb BuildRequires: xorg-x11-xinit BuildRequires: font(:lang=en) %endif
 * 1) X11 tests:

%check %if %{use_x11_tests} xinit /bin/sh -c 'rm -f ok; make test && touch ok' -- /usr/bin/Xvfb :666 test -e ok %else make test %endif

Here the X11 tests are conditionalized by use_x11_tests boolean macro. Real example can be found in perl-Padre or perl-Tk-Pod spec files.

= Autogenerated dependencies =

Filtering autogenerated dependencies does not work
Unfortunately rpm offers (and removes) filtering mechanism on each new release and not all supported mechanisms are compatible.

If you package for Fedora 16 and higher, use %__*_exclude macros. If you package for F15 and older, use %filter_* macros.

If you want to have unified spec file for all Fedoras, you can use both of them, but remember %__*_exclude style inhibits %filter_* style and %__*_exclude style is supported since rpm 4.9. If you use %perl_default_filter, you need to put it in between the two styles to take effect properly (see some early Fedora 16 packages for examples).

Since Fedora 16, %perl_default_filter uses %__*_exclude style, so if you use %perl_default_filter, you need to define filtering in the %__*_exclude style too.

Modules provided by private shared objects are not auto-provided by rpmbuild
Some CPAN packages contain native code and the native code can provide Perl module. E.g. XS file contains:

MODULE=Wx PACKAGE=Wx::Process

and it's compiled into /usr/lib64/perl5/vendor_perl/auto/Wx/Wx.so. When including the main package Wx, the Wx::Process becomes accessible and other module can use it:

perl -MWx -e 'use base qw(Wx::Process);'

Problem is rpmbuild discovers Requires for perl(Wx::Process), but does not discover the Provides. This leads to unresolvable dependencies in RPM repository.

Until rpmbuild will be fixed, you need to provide modules declared only in shared objects manually:

%package Wx Provides: perl(Wx::Process)

You can use a script to do it for you:

cd Wx-* for i in `grep -r "PACKAGE=" * | cut -d " " -f 2 | sed 's|PACKAGE=|perl(|g' | grep "Wx::" | sort -n |uniq`; do printf "Provides: $i)\\n"; done

This problem is described in bug #675992.

Autoprovides are missing version specifier
Not all submodules define their version. This is not good for current RPM.

Then rpmbuild generates following Provides: $ rpm -q --provides -p perl-Statistics-Basic-1.6602-1.fc14.noarch.rpm perl(Statistics::Basic) = 1.6602 perl(Statistics::Basic::ComputedVector) perl(Statistics::Basic::Correlation) […] perl-Statistics-Basic = 1.6602-1.fc14

According Paul Howarth, unversioned Provides satisfies versioned requires. E.g. if perl-Foo requires perl(Statistics::Basic::ComputedVector) >= 2.000 it will be satisfied by perl-Statistics-Basic-1.6602 because it provides perl(Statistics::Basic::ComputedVector).

IMHO, it sounds like a bug in RPM, you can patch it by following Provides filtering:

%filter_from_provides s/^\(perl(Statistics::Basic\>[^=]*\)$/\1 = %{version}/

It will add the version specifier equaled to package version to each sub-module missing any version specifier.

Bugs in RPM dependency generator
If you find a bug or shot-coming in dependency generator, report it into Bugzilla for rpm component, make proper subject (e.g. write prefix Perl dependency generator:), and make the bug blocking bug 694496 ((requirements, rpm) rpm requirements - provides/requires (tracker)).

= rpmlint errors =

Problem
W: perl-Class-MakeMethods file-not-utf8 /usr/share/man/man3/Class::MakeMethods::Docs::ReadMe.3pm.gz W: perl-Class-MakeMethods file-not-utf8 /usr/share/man/man3/Class::MakeMethods::Attribute.3pm.gz

Solution
Convert the errant file to UTF-8. Assuming the codepage the file is currently under is ISO-8859-1, this will do the trick (often by reviewers wanted in %prep section, in %build for generated man pages):

cd blib/man3 for i in Docs::ReadMe.3pm Attribute.3pm ; do iconv --from=ISO-8859-1 --to=UTF-8 Class::MakeMethods::$i > new mv new Class::MakeMethods::$i done

If you are using iconv, you should be BR'ing it, but it's in glibc-common, which is installed anyway...

Problem
W: private-shared-object-provides /usr/lib64/perl5/vendor_perl/auto/File/Map/Map.so Map.so(64bit)

The Map.so is a private shared library dynamically loaded by XS loader when a Perl binding to a C library is called. These files are not intended for public use and they must be filtered from Provides. In addition, the files have name similar to original C libraries which can clashes while resolving RPM dependencies while installing packages.

Solution
Filter the unneeded Provides by %{?perl_default_filter} macro.

Problem
Rpmlint returns something to the effect of:

E: perl-WWW-Myspace script-without-shellbang /usr/lib/perl5/vendor_perl/5.8.8/WWW/Myspace/Comment.pm E: perl-WWW-Myspace script-without-shellbang /usr/lib/perl5/vendor_perl/5.8.8/WWW/Myspace/MyBase.pm E: perl-WWW-Myspace script-without-shellbang /usr/lib/perl5/vendor_perl/5.8.8/WWW/Myspace/FriendAdder.pm

Solution
This error is caused by the exec bit being set on one or more .pm files. The solution is to strip the exec bit, for example, in the %install section:

find %{buildroot} -type f -name '*.pm' -exec chmod -x {} 2>/dev/null ';'

= Compatibility issues after upgrading Perl =

Problem
When compiling package driven by ExtUtils::MakeMaker that utilizes CCFLAGS argument, you get message:

Not a CODE reference at /usr/lib/perl5/DynaLoader.pm

Solution
This is bug in ExtUtils::MakeMaker probably. It replaces CCFLAGS instead of adding them to Perl default ccflags. See message perl 5.14 ExtUtils::MakeMaker overriding CCFLAGS in perl-devel mailing list and Debian bug report.

= New Perl specific spec file macros =

If you find out that some code snippets repeat in your spec files, you could say: Hey, there should be a macro for that! Then propose the macro for inclusion into /etc/rpm/macros.perl. The file is owned by perl package and is automatically included by rpmbuild tool. Ask perl package maintainer for adding the macro.