1

I want to write module(s) that if you load from windows, it will load MSWin32 module and from linux it will load linux modules. The subroutine implementation will be different based on platform.
e.g.


package Common::Copy::MSWin32;
sub do_this {}

package Common::Copy::linux;
sub do_this {}


#!/bin/perl
use lib Common::Copy::$^O;

do_this();

How to achieve that?

Kamikaze
  • 854
  • 13
  • 19
  • 2
    You can use a [BEGIN block to conditionally include modules at startup](http://perldoc.perl.org/functions/use.html), or [conditionally include and reference modules at runtime](http://stackoverflow.com/questions/1917261/how-can-i-dynamically-include-perl-modules-without-using-eval). All that's left is [branching by platform](http://stackoverflow.com/questions/334686/how-can-i-detect-the-operating-system-in-perl). For sanity's sake, I'd strongly recommend providing a single public interface as an abstraction layer. – rutter Feb 14 '14 at 23:36
  • possible duplicate of [How do I conditionally use a Perl module only if I'm on Windows?](http://stackoverflow.com/questions/1441689/how-do-i-conditionally-use-a-perl-module-only-if-im-on-windows) – mob Feb 15 '14 at 05:44
  • @mob Actually it isn't a duplicate as Kamikaze is trying to load one of several modules, instead of only one conditionally. – Brad Gilbert Feb 18 '14 at 17:47

2 Answers2

3

The standard way of doing this is to check the variable $^O ($OSNAME with the English pragma enabled). It reflects the operating system that was specified when the perl executable was built, and the values it can take are listed in perldoc perlport. For any Windows system it will be MSWin32.

If you need to distinguish between the different incarnations of Windows then you can use the Win32 module, which provides the Win32::GetOSVersion function to tell you exactly which Windows system and patch level you are working with.

To include different modules according to the value of $^O you should use the if pragma, like this

use if $^O eq 'MSWin32', 'Common::Copy::MSWin32';
use if $^O ne 'MSWin32', 'Common::Copy::Linux';
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • @Kamikaze: Your edit to my answer has been rejected. What you have to say is valid, but it belongs as a comment. You shouldn't modify people's answers except to improve or correct them – Borodin Feb 15 '14 at 05:02
0

You could load the modules the same way that File::Spec does.

( Assume that use warnings;, use strict;, and a version declaration immediately follow all of the package declarations throughout this post )

package Common::Copy::Win32;
sub do_this {}
package Common::Copy::Linux;
sub do_this {}
package Common::Copy;
    
my %module = (
    MSWin32 => 'Win32',
    linux => 'Linux',
);

my $module = $module{$^O} || 'Linux';

require "Common/Copy/$module.pm";
our @ISA = ("Common::Copy::$module");
#!/bin/perl
use Common::Copy;

Common::Copy->do_this();

This would require that the subroutines are written as methods which is probably not what you want.


It looks like you actually want it to export in a similar way to how File::Spec::Functions does.
This implementation assumes that the subroutines aren't written as methods.

package Common::Copy;
require Exporter;
our @ISA = qw'Exporter'; # use Exporters `import` method
 
our @EXPORT = qw'do_this';
our @EXPORT_OK = qw'';
our %EXPORT_TAGS = ( ALL => [ @EXPORT_OK, @EXPORT ] );
 
my %module = (
    MSWin32 => 'Win32',
    linux => 'Linux',
);
our $module = $module{$^O} || 'Linux';
require "Common/Copy/$module.pm";
$module = "Common::Copy::$module"; # full name of actual module

foreach my $subname (@EXPORT, @EXPORT_OK) {
    my $subref = $module->can($meth); # misuses method lookup

    no strict 'refs';
    # import the subroutines into this namespace
    # assumes they aren't written as methods
    *{$subname} = \&$subref;
}
#!/bin/perl
use Common::Copy;
# use Common::Copy qw':all';
# use Common::Copy qw'do_this';

do_this();
Community
  • 1
  • 1
Brad Gilbert
  • 33,846
  • 11
  • 78
  • 129