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

Help! Is there a way to do something like the following and not getting an error when I only have DiskFree installed on the Unix side? I like to keep the code the same on NT and Unix and not having to install DiskFree on NT and DriveInfo on Unix.
my $Format = $^O; if ($Format eq 'MSWin32') { use Win32::DriveInfo; } else { use DiskFree; } Can't locate DiskFree.pm in @INC (@INC contains: C:/PERL/lib C:/PERL/s +ite/lib .).....
Thanks

Replies are listed 'Best First'.
Re: use package
by dws (Chancellor) on Jul 26, 2002 at 22:16 UTC
    To make the package load happen at runtime, you need to use require rather than use, and for safety, wrap it in an eval block to check errors. The basic approach is
    if ( $Format eq "MSWin32" ) { eval { require Win32::DriveInfo }; if ( $@ ) { # handle error }
Re: use package
by DamnDirtyApe (Curate) on Jul 26, 2002 at 22:20 UTC

    This is untested, but based on the perldoc for use, I'd guess you could do something like:

    BEGIN { my $module ; if ( $^O =~ /MSWin32/ ) { $module = 'Win32::DriveInfo' ; } else { $module = 'DiskFree' ; } require $module ; import $module ; }

    Update: Thanks samtregar, you're right, this won't do. Try something more like this:

    BEGIN { if ( $^O =~ /MSWin32/ ) { require 'Win32/DriveInfo.pm' ; import Win32::DriveInfo ; } else { require 'DiskFree.pm' ; import DiskFree ; } }

    _______________
    D a m n D i r t y A p e
    Home Node | Email
      That doesn't work. The "magic" form of require where you give a package name instead of a path doesn't work with variables. Either do this:

      eval "require $module"; die $@ if $@;

      Or this:

      $module = "Win32/DriveInfo.pm"; require $module;

      -sam

      Or slight improvement:

      BEGIN { if( $^O =~ /MSWin32/ ) { require Win32::DriveInfo; import Win32::DriveInfo; } else { require Filesys::DiskFree; import Filesys::DiskFree; } }
      But note that you can't make use of the (conditional) compile-time magic such as calling the imported routines without using parens unless it happens that both modules import routines having that same name. This means that the BEGIN block is rarely of much use and can often be dropped.

      Further, I suggest that it is often a very good idea to drop the BEGIN block so that you don't accidentally try to make use of some conditional compile-time magic and release a version of your code that won't compile in the "other" case (or just so you save yourself the trouble of finding these bugs when you test the "other" case).

      It doesn't appear that either of these modules actually export any symbols. So they should probably have their documentation updated to replace use with require and you can probably drop both of the import lines above (as well as the BEGIN block):

      if( $^O =~ /MSWin32/ ) { require Win32::DriveInfo; } else { require Filesys::DiskFree; }
      (:

              - tye (but my friends call me "Tye")