Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Cross-Platform code

by GhodMode (Pilgrim)
on Feb 06, 2006 at 00:31 UTC ( [id://528119]=perlquestion: print w/replies, xml ) Need Help??

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

I am developing a Web application on my Linux server at home that needs to work in two different environments: Linux based Web server with a commercial hosting provider & Windows XP on an intranet.

My development server and the Windows computer are both running xampp and the real Web server is running a real LAMP configuration.

I would like to write code so that I can copy it from one machine to the other without having to change anything.

As it is, I have to change the #! line for all of the Perl programs and I don't think I'll be able to avoid that. The other stuff, though, is all related to directories and file locations. This includes a use lib line for a module I wrote for this specific project.

For example, I would like something that works like this:

if ( $linux ) { $logdir = "/home/ghodmode/logs"; $sep = "/"; } elsif ( $windows ) { $logdir = "c:\\xampp\\xampp\\webapp\\logs"; $sep = "\\"; } $logfile = "$logdir${sep}error_log.txt";
I know that the use lib line will be tricker, but is it possible if I put it in a BEGIN block? Does anyone have some advice on how to do this stuff? Thank you,
--
-- GhodMode

Replies are listed 'Best First'.
Re: Cross-Platform code
by ikegami (Patriarch) on Feb 06, 2006 at 00:46 UTC

    1) Instead of changing the #! line, you could have OS-specific .pl's which initialize variables to OS-specific values, the uses do to execute the common code.

    2) You shouldn't need to use $sep. For that, we have core modules File::Spec and File::Basename.

    applic_linux.pl --------------- #!/usr/bin/perl our $logdir = "/home/ghodmode/logs"; do 'applic.pl'; applic_win32.pl --------------- #!c:\perl\bin\perl our $logdir = "c:\\xampp\\xampp\\webapp\\logs"; do 'applic.pl'; applic.pl --------- use strict; use warnings; BEGIN { our $logdir; die(...) unless defined $logdir; } use File::Spec (); my $logfile = File::Spec->catfile($logdir, 'error_log.txt'); ...

    Better yet would be to use a config file to hold the name of the log dir. That would be both OS-independant and more useful.

      And if you're willing to install a module from CPAN or package it along with your app (PAR), consider using Path::Class instead of File::Spec, as it has a considerably nicer interface. (It's pure love.)

      It uses File::Spec under the hood, of course.

Re: Cross-Platform code
by rhesa (Vicar) on Feb 06, 2006 at 00:47 UTC
    I suggest putting the logdir specification in a config file. Put platform-specific variables in your config file, and have the app use those instead of hard-coding them throughout your application.

    You can make Apache on Windows find the correct perl binary through the registry instead of the shebang line. That way you can leave it intact for use on Linux. (You can use the Apache directive ScriptInterpreterSource Registry).

    Perl works fine on Windows using a forward slash as path separator, so you could drop that variable. For really spiffy cross-platform paths, I suggest File::Spec (look at the catfile function).

Re: Cross-Platform code
by GhodMode (Pilgrim) on Feb 06, 2006 at 01:38 UTC

    Thanks to everyone...

    I didn't know about File::Spec and I will definitely be using that.

    Currently, my application consists of 16 Perl files and it's still growing. So, having a version of each of those, for each platform, isn't a good choice for me because they are still undergoing changes. I might need to make a change in the code, then have to remember to do it exactly the same way two more times.

    I'm already using a separate configuration file. That does save some time when I need to copy the code to the other platforms.

    The ScriptInterpreterSource directive is new to me also. It might save me the monotonous task of editing every file every time I move the code to the Windows box, but I am curious what I need to do to make it work. I've read the documentation . This may be a Windows question rather than a Perl question, but maybe you can still help me out: The doc says it will use Shell\ExecCGI\Command or, if it does not exist, Shell\Open\Command from HKEY_CLASSES_ROOT, but I checked and the only subkey I have for the .pl extension is PersistentHandler. Will it still work, or do I need to manually add the key?

    Update : It worked! :) I had to manually add a registry key for the .pl extension in HKEY_CLASSES_ROOT I created keys: Shell/ExecCGI /Command, then (this is the part the doc doesn't mention) I created a string named command and it's value was c:\xampp\xampp\perl\bin\perl.exe %1. Until the registry key was exactly right, it relied on the #! line. I used ScriptInterpreterSource Registry as recommended. I couldn't get it to work with Registry-Strict.
    (End of Update)

    Eventually, this entire application will need to go on an installation CD with an autorun.inf that will put everything in the right place. I'll figure that out. I can even create a .reg file, if necessary.

    I do all of my development on Linux, when possible, and I , personally, am case-sensitive :)

    --
    -- GhodMode
    
Re: Cross-Platform code
by rinceWind (Monsignor) on Feb 06, 2006 at 09:00 UTC

    For deploying scripts and sorting out the #! line, there's a trick:

    perl -MExtUtils::MY -e 'MY->fixin(@ARGV)' *.pl

    This is the same mechanism that make install uses for scripts: it will set the perl path to the right thing on Unix, and run pl2bat on Windows.

    Concerning portability in general, you might be interested in the slides for a talk I have given on portability at two YAPCs.

    --

    Oh Lord, won’t you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, won’t you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

Re: Cross-Platform code
by helphand (Pilgrim) on Feb 06, 2006 at 01:02 UTC

    In addition to what others have posted, I've found the single most aggravating thing about maintaining cross-platform sites is windows case insensitivity. Table names in MySQL and, of course, file names in the filesystem, can cause all sorts of grief.

    My solution is to do all of the development on the Linux platform, then copy to the windows platform.

    Scott

Re: Cross-Platform code
by GhodMode (Pilgrim) on Feb 06, 2006 at 01:58 UTC

    I have the info I need to get rid of my path separator variable and probably to stop editing the #! line every time I copy the code to Windows.

    I can move my module to one of the standard directories from @INC.

    I still have to edit my config. file when I move the code, though. That's actually not too much of a burden, but I think I may have found my solution in the %ENV variable SERVER_SOFTWARE: on the Linux server it shows Apache/2.0.55 (Unix) ... and on the Windows server it shows Apache/2.0.55 (Win32) ... ... That'll work :D

    --
    -- GhodMode
    
      Perhaps you should use the $^O special variable instead, since it doesn't depend on a CGI environment.
      It contains a descriptive name for the OS (e.g. "MSWin32" under Windows).


      acid06
      perl -e "print pack('h*', 16369646), scalar reverse $="
        Dude!! You Rock!! That's what I was looking for in the first place :)
        --
        -- GhodMode
        

        Or you can use the Config module, if you need more information about the system.

        If you're using regular CGI's (and doesn't need mod_perl) you can use Cygwin at the Windows station, without problems. You will avoid annoyances with IIS, permissions or registry. But if you need mod_perl, just forget about. I recently (two weeks ago) had tried to use Apache 2 with Cygwin and it just didn't worked. Looking for answer at Google brought info related to wrong compilation problem and, well... I quit trying!

        Alceu Rodrigues de Freitas Junior
        ---------------------------------
        "You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (3)
As of 2024-04-20 02:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found