Check module compatibility with different Perl versions - perl

Is there a command line switch or any other easy way that I can check the compatibility of my module with different versions of perl? I understand that if I put use 5.6.1; at the top of a script, the script will have any features later than 5.6.1 disabled. But if I have a module which uses several other modules and so on, I need a quicker way to check what minimum version of Perl to require in my Makefile.PL or Build.PL.

Run your module against Perl::MinimumVersion.

use v5.6.1 and similar will primarily raise a compile-time error if the version of Perl in use is older than that specified. In addition, the corresponding feature bundle is enabled, and if the version is v5.11 or higher, the strict pragma is enabled as well.
use v5.6.1 will not make Perl v5.8 behave like v5.6.1, and there is no way of achieving this. Even in later versions it is only features that can be controlled using the feature pragma that are adjusted to a given version.
To test your module you will have to install each different version of Perl and test it separately

You can just install different versions of perl and test against those. I install them by hand in different locations but if you want to automate that, use perlbrew.
There might be scripts or strategies that try to find the minimum version of perl needed, but everything i tried several years ago to obtain and aggregate the minimum perl version i found clunky and unreliable. Which of course doesn't mean, that it doesn't exist or can't be done, but just that i couldn't find it.

Related

Do all my perl module .pm files need a `$VERSION` definition?

I just added a new file to the PDL::IO::Touchstone distribution and noticed that CPAN's indexer says version is undef since $VERSION is missing:
module : PDL::IO::MDIF
version: undef
in file: PDL-IO-Touchstone-1.009/lib/PDL/IO/MDIF.pm
status : indexed
So ::MDIF does not have $VERSION but really it is the same as the distribution version as noted in Makefile.PL:
my %WriteMakefileArgs = (
VERSION_FROM => 'lib/PDL/IO/Touchstone.pm',
...
);
Questions:
So does this module within the distribution need a version?
If so, should the new module's $VERSION be maintained separately from $VERSION provided by VERSION_FROM in Makefile.PL?
I could do $VERSION = $PDL::IO::Touchstone::VERSION but not sure if CPAN will figure that out. Will it?
I looked around and found lots of discussion of versioning practices, but nothing about versions of modules within the same Perl distribution package. Please share what the best practice here should be, I'm new to Perl modules and this is the first 2-file distribution that I've pushed out.
I'm sure I'll update the primary file when releasing a new dist, but not sure if I'll remember to bump the version of other modules in the dist when they change. It would be nice if there is a low-maintenance option here.
Update
I tried the suggestion in some answers below. Neither of these work:
$VERSION = do { use PDL::IO::Touchstone; $PDL::IO::Touchstone::VERSION };
use PDL::IO::Touchstone; our $VERSION = $PDL::IO::Touchstone::VERSION;
This is the MDIF.pm file at github: https://github.com/KJ7LNW/perl-PDL-IO-Touchstone/blob/master/lib/PDL/IO/MDIF.pm#L22
CPAN still shows version: undef:
Status: Version parsing problem
===============================
module : PDL::IO::MDIF
version: undef
...
Ok, so who gets the checkmark... any other ideas?
I like to give all of my modules versions. It's not a requirement, but consider the user experience while trying to upgrade when they don't know anything, or very little, about how CPAN works. ikegami already gave the tl;dr for this.
When you want to update a module from CPAN, the tool looks at that module's $VERSION (well VERSION sub). If that module doesn't have a version, that's undef. When CPAN.pm (or other tools maybe) looks to see if there is a more recent version, it does not find one it thinks is more recent because the latest version is also undef.
A concrete example is Mojo::UserAgent. Mojolicious only versions the main module. The other modules do not have versions. I typically do a lot of web client stuff, so my work product doesn't care about the web server side of Mojo. People using some of my stuff might not even know there is a different part of Mojo aside from the client stuff (they might even know Perl).
If I run cpan Mojo::UserAgent, it compares my currently installed version (undef) to the latest on CPAN (undef). This means that CPAN.pm guesses that I do not have something earlier than the latest available.
$ cpan -D Mojo::UserAgent
Mojo::UserAgent
-------------------------------------------------------------------------
(no description)
S/SR/SRI/Mojolicious-9.28.tar.gz
/usr/local/perls/perl-5.36.0/lib/site_perl/5.36.0/Mojo/UserAgent.pm
Installed: undef
CPAN: undef up to date
Sebastian Riedel (SRI)
kraihx#googlemail.com
Now, I have this special knowledge that this distro does this. But someone merely using something I wrote with Mojo::UserAgent probably doesn't. If they need Mojolicious 8 to get particular CSS selectors then, how do they know that?
Normally, you can specify a minimum version of a module:
use File::Glob 8.0;
I can't require a minimum version of Mojo::UserAgent:
use Mojo::Usergent 8.0;
I get a weird error (there are other import issues and design decisions going along with this):
Can't locate 8.pm in #INC (#INC contains: ...)
This isn't a big deal because Mojolicious is mostly self-contained, so I can specify its minimum version:
use Mojolicious 8.0;
But, I have to know how all of this works, how that distro works, and how Perl works to do that. For the casual user of my stuff who just wants to get work down, including modifying what I've done, they have to discover some lore to know this. They have to know how CPAN.pm or PAUSE decides what the latest version is, and so on.
Furthermore, this is a problem for modules in a distribution that don't change and have no logical reason for a version bump. Well, they do because they have an implicit dependency on the main module that does have a version, but we're not in the habit of declaring that version. Consider, for example, some module that works with an API that has changed, but the meat of the change is in another module it uses. The module you use directly has not changed its literal text, but it can't work as is because the world is different. But, since the literal text in that file hasn't changed so we typically don't bump the version.
Maybe we should declare that main module dependency, but that's a lot of work. It adds some seemingly gratuitous churn to files, which is annoying in repo history. Ah hell, now that I've thought of that, I need to fix this in some distros. Some-not all. I don't know. Something to think about.
Of course, I can document all of this in the distro, script, or whatever. But we know that I can say it and they can read it and still not appreciate the importance. And, by this time we're a far way away from "just working".
CPAN only requires a version for the distribution, and you have provided that using VERSION_FROM.
There are a variety of practices.
Only the "main module" has a version.
Each file has its own version.
Each file shares the distro's version.
CPAN evals the line that sets $VERSION, so the following should work if it's all on one line:
use PDL::IO::Touchstone; $VERSION = $PDL::IO::Touchstone::VERSION;

What is the real purpose of the $VERSION variable in Perl?

I've read that it's considered good practice to always include a $VERSION number in all of your Perl scripts, but I never fully understood the purpose.
What do you really gain by including a version number in your script?
You can specify a minimum version of a module in the use statement:
use Foo 1.23;
When Perl loads that module, it looks at the $VERSION variable to check that it's equal to or greater than that number. That way you get the right set of features and fixes.
The CPAN clients use $VERSION to determine if you are up-to-date or if you should install the latest version of a module.
For programs or scripts, you typically don't need a $VERSION.
Only modules, and only those pushed to CPAN really benefit from specifying $VERSION. There's not much use for it in a script except to use a familiar name rather than inventing a new one if you want the script's version to be accessible.
Primary uses:
CPAN uses it as the version of the distribution, allowing it to index different versions of the same distribution.
cpan and cpanm uses it to check if an installed module is of sufficiently high level to meet the required minimum version of a dependency.
As brian d foy mentioned, it can also be checked by use Foo 1.23;, but most people avoid this in favour of specifying the required versions of dependencies in their distribution's META file. This allows cpan and cpanm to update the dependency if needed (where use using use Foo 1.23; would cause the installation to fail during testing). Due to the lack of use of the feature, it's hardly a primary use.

Invoking a HTTP URL from perl script - Perl Version 5.8.4

We have perl version 5.8.4 installed on our servers. I am trying to invoke a HTTP URL from within the perl script and based on the output that the HTTP URL returns I have a logic to be executed.
I am very new to perl and am looking for help to achieve this. The Cpan and other modules seem to be unavailable with the current version we have.
Please let me know how we could achieve this.
Thanks,
Sachin
Take a look at LWP and LWP::simple.
Even older versions of perl will have support for this library, although you may have to install it via cpan.
We have perl version 5.8.4 installed on our servers
Then that should be the first thing that you fix. 5.8.4 is ten years old. It is completely unsupported.
The Cpan and other modules seem to be unavailable with the current version we have.
No. CPAN works fine with versions of Perl back far earlier than 5.8.4. If you are having a problem using them that is a local problem that you should work on getting fixed. Good Perl programming is a case of wiring together the correct CPAN modules. If you can't install CPAN modules then you are missing most of the power of Perl.
The correct answer to your problem is to install LWP::Simple and use its get function. If you don't want to do that, then reading the source code for that module will show you the lower level code that you would need to write.

Will all perl versions support older modules?

I'm have Perl 5.8 installed on all of our servers and wanted to use the DBI and DBD::Oracle modules to access our databases. My main concern is with the newer versions of perl the DBI and DBD modules will stop working with 5.8. Then I'd have to upgrade every server to the newest perl version.
My question is as perl itself becomes later versions and modules are developed for them will they still be backwards compatible? "CPAN does not carry all ancient releases and patchlevels of Perl", if I create documentation saying run "cpan -i DBI" if the newest version of DBI will not function with 5.8?
There is no guarantee.
In general, you want to use the same versions of the modules on all your systems. If you use different versions then you will have different bugs and features available on different servers.
I'd suggest creating Debs / RPMS / etc for the ones you are going to use and then run a package repository that all your servers share.
Not absolutely, but in general perl is pretty gentle about breaking code, with not many breaking changes, and long deprecation cycles on the ones that do happen. A pretty hefty portion of the code that was uploaded to CPAN in 1999 will run without modification in perl 5.14.
Since perl 5.12, the perl release cycle has become shorter, and the deprecation periods have also become shorter, which is cause for concern, but at the same time the concept of feature versioning has gained currency. The idea is that code may declare the version of perl that it's targeting with use VERSION (e.g. use 5.16.0), and any code that doesn't declare a version is assumed to be targeting approximately 5.10. When code that targets an older perl version is run on a newer perl version, newer features that might cause compatibility issues (e.g. new keywords) are disabled, and old misfeatures may be re-enabled in the name of compatibility. This isn't an absolute guarantee, but it will be adhered to as much as practical.
More information about back-compatibility and deprecation is in perlpolicy.
In general, no. There are a lot of great new features in recent releases of Perl (smart match operator, the // operator, for two one example) that are not backwards compatible. Many authors will decide to take advantage of these features rather than keep their modules compatible with older versions of Perl.
Check the CPAN Tester's Matrix of a module, including the link about the max version that passes all of the distribution's tests, to get an idea of what versions of Perl are compatible with each version of a module.
cpan -i Some::Module will indeed attempt to install the latest version of the module Some::Module, but with a little research, it can be used to install older versions too. You need to find or guess the author of an older version and provide the path to the distribution on the CPAN mirror servers. For example,
cpan -i J/JF/JFRIEDL/Yahoo-Search-1.9.12.tar.gz
cpan -i A/AS/ASG/List-Gen-0.80.tar.gz
CPAN authors may delete their older distributions from CPAN. But even then, the distribution is available at the BackPAN if you're willing to download, unpack, and build the distribution yourself.

How do I use a vendor Apache with a self-compiled Perl and mod_perl?

I want to use Apple's or RedHat's built-in Apache but I want to use Perl 5.10 and mod_perl. What's the least intrusive way to accomplish this? I want the advantage of free security patching for the vendor's Apache, dav, php, etc., but I care a lot about which version of Perl I use and what's in my #INC path. I don't mind compiling my own mod_perl.
Build your version of Perl 5.10 following any special instructions from the mod_perl documentation. Tell Perl configurator to install in some non-standard place, like /usr/local/perl/5.10.0
Use the instructions to build a shared library (or dynamic, or .so) mod_perl against your distribution's Apache, but make sure you run the Makefile.PL using your version of perl:
/usr/local/perl/5.10.0/bin/perl Makefile.PL APXS=/usr/bin/apxs
Install and configure mod_perl like normal.
It may be helpful, after step one, to change your path so you don't accidentially get confused about which version of Perl you're using:
export PATH=/usr/local/perl/5.10.0/bin:$PATH
You'll want to look into mod_so
I've done this before. It wasn't pretty, but it worked, especially since vendor perl's are usually 2-3 years old.
I started with making my own perl RPM that installed perl into a different location, like /opt/. This was pretty straight forward. I mostly started with this because I didn't want the system utilities that used perl to break when I upgraded/installed new modules. I had to modify all my scripts to specify #!/opt/bin/perl at the top and sometimes I even played with the path to make sure my perl came first.
Next, I grabbed a mod_perl source RPM and modified it to use my /opt/bin/perl instead of /usr/bin/perl. I don't have access to the changes I made, since it was at a different gig. It took me a bit of playing around to get it.
It did work, but I'm not an RPM wizard, so dependency checking didn't work out so well. For example, I could uninstall my custom RPM and break everything. It wasn't a big deal for me, so I moved on.
I was also mixing RPM's with CPAN installs of modules (did I mention we built our own custom CPAN mirror with our own code?). This was a bit fragile too. Again, I didn't have the resources (ie, time) to figure out how to bend cpan2rpm to use my perl and not cause RPM conflicts.
If I had it all to do again, I would make a custom 5.10 perl RPM and just replace the system perl. Then I would use cpan2rpm to create the RPM packages I needed for my software and compile my own mod_perl RPM.