Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I've been asked to write a perl script to run on various flavours of UNIX which will include disc and filesystem manipulation. To me it makes sense to have operating system specific modules to perform the disc import/export and filesystem manipulations and have the main use whichever module is relevant to the particular operating system (with the various operating system specific modules exporting the same function and variable names). The question is how can I execute some code to identify the operating system and then call the relevant use statement, as I understand use is a compile time directive ?

Replies are listed 'Best First'.
Re: Selective use of Use
by davorg (Chancellor) on Jul 31, 2006 at 08:36 UTC

    You can find out which operating system you are running on by looking at the $^O variable (see perlvar for details).

    The easiest way to conditionally "use" modules is to replace the "use" with calls to "require" and "import" - as these are executed at runtime.

    if ($some_condition) { require SomeModule; SomeModule->import; } else { require SomeOtherModule; SomeOtherModule->import; }

    Alternatively, you could look at if.

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: Selective use of Use
by Corion (Patriarch) on Jul 31, 2006 at 08:37 UTC

    The easiest way is the string form of eval:

    if ($^O eq 'WhizBang Unix') { eval "use Module::WhizBang;"; die $@ if $@; } else ...

    As the documentation tells you, use is basically equivalent to

    BEGIN { require Module::Name; Module::Name->import(); };

    so you can avoid the string eval (which is safe in this instance) by using

    BEGIN { my $module = "Module::Name"; my $module_file = $module; # Translate module name into file name $module_file =~ s!::!/!g; $module_file .= '.pm'; require $module_file; $module->import(); };
Re: Selective use of Use
by McDarren (Abbot) on Jul 31, 2006 at 08:45 UTC
    With regards to getting the OS name, from perldoc perlvar:
    $^O The name of the operating system under which this copy +of Perl was built, as determined during the configuration process. T +he value is identical to $Config{'osname'}. See also Config and the -V command-line switch documented in per +lrun. In Windows platforms, $^O is not very helpful: since it + is always "MSWin32", it doesn't tell the difference between 95/98/ME +/NT/2000/XP/CE/.NET. Use Win32::GetOSName() or Win32::GetOSVersion() (see Win32 and perlport) to disti +nguish between the variants.

    And with regards to your main question, I believe that a BEGIN block is probably what you need. From the Camel (3rd Edition, Chapter 18):

    "Because a BEGIN block executes immediately, it can pull in subroutine declarations, definitions, and importations before the rest of the file is even compiled. These can alter how the compiler parses the rest of the current file, particularly if you import subroutine definitions."

    Hope this helps,
    Darren :)

Re: Selective use of Use
by CountZero (Bishop) on Jul 31, 2006 at 09:38 UTC
    My personal idea is that you better first look at what manipulations to the file-system you need to do and see if you indeed need operating-system specific modules to do that. A lot of these things are handled quite transparently by Perl already.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Selective use of Use
by bart (Canon) on Jul 31, 2006 at 09:03 UTC
    My personal opionion would be that you could look at the implementation of File::Spec as an example. AnyDBM_File has a somewhat similar setup, trying to load one of a few virtually equivalent modules, depending on what kind of DBM_File is supported on your sytem.

    As a second idea, you could try out using if, and let the condition depend on $^O.

Re: Selective use of Use
by rodion (Chaplain) on Jul 31, 2006 at 08:44 UTC
    I prefer the "$Config{'osname'}" version of that information. It gives you the same thing, but it can be clearer to others what's going on. The choice depends on who's going to be reading the code. (And how much patience you have to type and read the more descriptive version.)
Re: Selective use of Use
by ysth (Canon) on Jul 31, 2006 at 15:30 UTC
    I'm curious to know what kind of "disc and filesystem manipulation" you need to do. Chances are you'll be able to do it without resorting to different modules for different operating systems.

    To identify the operating system, check the $^O variable; possible values are listed in perlport.