Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

How to have OS specific code sections in Perl

by perltux (Beadle)
on Oct 31, 2012 at 16:55 UTC ( #1001707=perlquestion: print w/ replies, xml ) Need Help??
perltux has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
I'm trying to make some code in my perl script OS specific, but I still get the following error when I try to run the code below on Windows:

Can't locate MIDI/ALSA.pm in @INC

The "OS is Linux" line only gets printed on Linux as expected, on Windows it doesn't get printed, so the 'if' subroutine is never entered in Windows as expected, that's why I don't understand the above error on Windows.

The script:
#!/usr/bin/perl if ($^O eq 'linux') { $LINUX=1; }; if ($LINUX) { print STDERR "OS is Linux\n"; use MIDI::ALSA ('SND_SEQ_EVENT_PORT_UNSUBSCRIBED', 'SND_SEQ_EVENT_SYSEX'); MIDI::ALSA::client('test',1,1,1); MIDI::ALSA::connectfrom(0,'MidiSport 4x4:0'); MIDI::ALSA::connectto(1,'MidiSport 4x4:0'); MIDI::ALSA::start(); }

Basically I want to load a Linux only module and then execute a few module specific commands only on Linux, on Windows I want that section of the script to be ignored.

How do I make this work?

Comment on How to have OS specific code sections in Perl
Download Code
Re: How to have OS specific code sections in Perl
by VinsWorldcom (Priest) on Oct 31, 2012 at 17:03 UTC

    There error is happening because the module MIDI::ALSA is not installed on your Windows machine.

    use doesn't work the way you're thinking it does. It is not evaluated as the code is run, but before that. So your "logic" is correct, but your logic is wrong - if that makes sense ;-)

    There have been many suggestions on how to do this with the if pragma for example, but I've found this to work for me:

    use strict; use warnings; my $HAVE_MIDI_ALSA = 0; eval "use MIDI::ALSA"; if($@) { print "MIDI::ALSA required\n"; exit } else { $HAVE_MIDI_ALSA = 1 } if (($^O eq 'linux') and $HAVE_MIDI_ALSA) { MIDI::ALSA::client('test',1,1,1); MIDI::ALSA::connectfrom(0,'MidiSport 4x4:0'); MIDI::ALSA::connectto(1,'MidiSport 4x4:0'); MIDI::ALSA::start(); }
      Thanks for the explanation as to why my logic is wrong. :-)
Re: How to have OS specific code sections in Perl
by choroba (Abbot) on Oct 31, 2012 at 17:14 UTC
    See if.
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: How to have OS specific code sections in Perl
by toolic (Chancellor) on Oct 31, 2012 at 17:14 UTC
    if (untested):
    use warnings; use strict; my $LINUX = 0; if ($^O eq 'linux') { $LINUX=1; }; use if $LINUX, 'MIDI::ALSA' => ('SND_SEQ_EVENT_PORT_UNSUBSCRIBED', 'SND_SEQ_EVENT_SYSEX'); if ($LINUX) { print STDERR "OS is Linux\n"; MIDI::ALSA::client('test',1,1,1); MIDI::ALSA::connectfrom(0,'MidiSport 4x4:0'); MIDI::ALSA::connectto(1,'MidiSport 4x4:0'); MIDI::ALSA::start(); }

    UPDATE: deleted 2nd 'use'

      Thanks, this works great (apart from the second 'use' after the comma in the 'use if' line which is incorrect) and does exactly what I wanted!
        You're welcome.

        Thanks for pointing out the copy'n'paste error; I updated the post to delete it.

      Actually unfortunately I spoke to soon, the code now works fine in Windows (no errors anymore) but now I get an error in Linux:

      Undefined subroutine &MIDI::ALSA::client called at ./test.pl line 15

      It looks like the 'use if' line needs some more tweaking to work correctly, but how?

        The problem is that the conditional block is only evaluated at run time, by which time it's too late for use if.

        You want:

        my $LINUX; BEGIN { $LINUX = ($^O eq 'linux') }; use if $LINUX, 'MIDI::ALSA' => ('SND_SEQ_EVENT_PORT_UNSUBSCRIBED', 'SN +D_SEQ_EVENT_SYSEX');

        Or better:

        use if ($^O eq 'linux'), 'MIDI::ALSA' => ('SND_SEQ_EVENT_PORT_UNSUBSCR +IBED', 'SND_SEQ_EVENT_SYSEX');
        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      The 'use if' line seems to work only if written as follows:

      use if ($^O eq 'linux'), 'MIDI::ALSA' => ('SND_SEQ_EVENT_PORT_UNSUBSCR +IBED', 'SND_SEQ_EVENT_SYSEX');

      Any other way to write the 'use if' CONDITION doesn't seem to work.
      Weird...
      Unfortunately, this is not going to work because $LINUX is undef at compile-time:
      $ perl if ($^O eq 'linux') { $LINUX=1; }; use if $LINUX, 'MIDI::ALSA' => ('SND_SEQ_EVENT_PORT_UNSUBSCRIBED', 'SND_SEQ_EVENT_SYSEX'); __END__ $ perl -MMIDI::ALSA Can't locate MIDI/ALSA.pm in @INC (@INC contains: /home/aitap/perl5/li +b/perl5/i486-linux-gnu-thread-multi-64int /home/aitap/perl5/lib/perl5 +/i486-linux-gnu-thread-multi-64int /home/aitap/perl5/lib/perl5 /etc/p +erl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/ +perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/l +ocal/lib/site_perl .). BEGIN failed--compilation aborted.
      But if the test is done in the BEGIN{} section, everything works (well, not for me because of the absence of the module):
      $ perl BEGIN{ if ($^O eq 'linux') { $LINUX=1; }; } use if $LINUX, 'MIDI::ALSA' => ('SND_SEQ_EVENT_PORT_UNSUBSCRIBED', 'SND_SEQ_EVENT_SYSEX'); Can't locate MIDI/ALSA.pm in @INC (@INC contains: /home/aitap/perl5/li +b/perl5/i486-linux-gnu-thread-multi-64int /home/aitap/perl5/lib/perl5 +/i486-linux-gnu-thread-multi-64int /home/aitap/perl5/lib/perl5 /etc/p +erl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/ +perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/l +ocal/lib/site_perl .) at /usr/share/perl/5.14/if.pm line 13. BEGIN failed--compilation aborted at - line 3.
      Sorry if my advice was wrong.
        Thank you, that explains why I had to use:

        use if ($^O eq 'linux'), 'MIDI::ALSA'

        and why any other alternative with $LINUX I tried didn't work!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1001707]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (10)
As of 2014-10-23 18:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (126 votes), past polls