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

Hello Monks,

I am using the Perl module Win32. But it is available only on Windows and I want my code to work on Unix flavors too. So, I am looking for an equivalent of '#ifdef' in C pre-processor, for Perl, as so to make my code portable across the platforms.

Just to give a brief history on the problem -- I was trying to solve problem due to the space in the path on windows and so I had to use the Win32::GetShortPathName function to work around the problem, which resulted in the inclusion of Win32 module.

Note: I can use some pre-processor, like, cpp and generate platform specific code and bundle them as 'per platform' secific deliverable. But, I don't want to do this and I am looking for a single-portable-script solution.

Thank you,
-sureshr
  • Comment on Portability question: Is there something like '#ifdef' in Perl?

Replies are listed 'Best First'.
Re: Portability question: Is there something like '#ifdef' in Perl?
by Abigail-II (Bishop) on Sep 29, 2003 at 15:19 UTC
    Yes, you can use #ifdef in Perl, in combination with the -P switch (see man perlrun). But I've never seen a serious program using it, and I can't imagine a situation where you want to use it.

    If you want to use a module Win32::Foo only if the OS is Windows, do something like:

    use if $^O =~ /Win32/, Win32::Foo => qw /arg1 arg2 arg3/;

    Abigail

Re: Portability question: Is there something like '#ifdef' in Perl?
by perrin (Chancellor) on Sep 29, 2003 at 15:43 UTC
    If you want to check whether or not a particular module is available, you do that like this:
    eval 'require Win32::GetShortPathName'; if ($@) { # nope, not on this system } else { # yes, go ahead with it }
    Note that you must leave out the "use" for the module.

    Or were you asking how to tell what platform you're on?

      Thank you! Its just the kind of solution I was looking for, though I was planning to insert code based on ifdef doing a platform check.

      Thanks to others too, who have answered my original query!

      -sureshr
Re: Portability question: Is there something like '#ifdef' in Perl?
by Elian (Parson) on Sep 29, 2003 at 17:09 UTC
    Use $^O. It holds the name of the OS you're currently running on, and you can use it in conditional code all you like. It's the traditional way to do this sort of thing in perl. For conditional inclusion, throw things in a BEGIN block with require and import:
    BEGIN { if ($^O eq 'Win32') { require Win32::Foo; import Win32::Foo; } elsif ($^O eq 'Linux') { require Linux::Foo; import Linux::Foo; } }
Re: Portability question: Is there something like '#ifdef' in Perl?
by PodMaster (Abbot) on Sep 29, 2003 at 15:26 UTC
    I suspect you don't really need GetShortpathName, so I'm gonna ask: Why do you think you need to use GetShortpathName?. If you're doing exec/system/open there are variants of each which avoid the shell, so spaces in paths aren't significant.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

      I am using system and I cannot use exec, as I wait on the result (may be fork). But, I have'nt tried anything besides system. And the problem of 'spaces in the path' is certainly a hindrance in the 'system' call, so I had use the getshortname call :(

      Could you please send me the variant or the reference to the document for the call that handles the space problem in system call?

      Thanks, -sureshr

        If you use the scalar args form of system

        ... system( "command \\path\\with spaces\\file" ); ...

        you'll may have problems with the spaces.

        If you use the list form of the system function.

        ... system( '\path\to\command.exe', '\path\with spaces\file' ); ...

        Note the use of 's rather than "s, to avoid the need to escape the backslashes.

        cmd.exe will be bypassed and the spaces in the filename won't cause a problem. However, you will need to specify the full path of the command as well.

        You can also avoid the need for using short filenames by quoting the filepath.

        ... system( q[command "\path\with spaces\file" ] ); ...

        Which allows the shell to resolve the location of the command for you and forces it to see the quoted path as a single argument.

        Note though, if your in an open environment, the risk entailed in allowing your shell to do this for you.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
        If I understand your problem, I can solve it! Of course, the same can be said for you.