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

Hiya Monks, I've got two programs that are reliant on GNU based applications which Perl does "system" calls as part of the script. Obviously this creates a dependency on something external to Perl, which I'm not overly keen on.

For example, I have a utility that finds and removes unwanted temporary files on our File Server. The heart of the script uses the GNU "find" command. This is done on a win2000 box. I then compile this into an exe using Indigo Star's perl2exe. Obviously if you then try to run this on another box without the GNU version of find installed you get problems.

So my question is can you get Perl it include the GNU appliction into itself so that on compilation there is no external dependency? Am I making sense?

Any advice appreciated. It would help with portability of my programs.

Dean

Programming these days takes more than a lone avenger with a compiler. - sam
  • Comment on Importing external dependencies into source

Replies are listed 'Best First'.
Re: Importing external dependencies into source
by arden (Curate) on Mar 03, 2004 at 16:45 UTC
    crabbdean, I don't know about perl2exe, but with ActiveState's perlapp you can bind other files into your executable with the  --bind argument.

    - - arden.

      Okay this helped. IndigoStar's User Manual gives the command for compiling an external file into the exe. Yahoo!

      Okay, there is another extension to this problem. find.exe is also a windows application. Previously, to get my script to find the GNU version BEFORE the windows version I had to put the directory of the GNU find earlier in my "path" environment variable.

      I've now run and tested the new compiled version and it appears to have imported the GNU find.exe into the exe. Yay! Small win. BUT ... taking it to another box, having no actual directory in which the GNU version of find sits how can I get my script to use it? It appears to look for the windows "find.exe" when it makes the call to find. I can see by the error message generated its using Windows "find.exe" but the exe of my script has the GNU find compiled into it. Help?!

      Thanks
      Dean

      Programming these days takes more than a lone avenger with a compiler. - sam
        crabbdean, don't call it by  system('find','arg1','arg2'); but call it with  system('/dir/to/find','arg1','arg2'); or  system('./find','arg1','arg2'); so that you don't have to worry about the system using it's own version of find.

        This, of course, assumes that you know where it puts your find.exe file. Look at the docs and see how to use binded files. . .

        - - arden.

Re: Importing external dependencies into source
by mirod (Canon) on Mar 03, 2004 at 16:50 UTC

    I don't know about the second application you depend on, but find can certainly be replaced by pure perl code. In fact perl even comes with the find2perl tool that will do just that!

      Thanks, but I have gone for the external dependency on the GNU find.exe because the File::Find module (which is also included in the code that the find2perl application generates) has a memory leak. Refer to File::Find memory leak

      The other GNU application I'm still to write into my code but it will most likely be "rsync". I'm just investigating it now as an option, but doing so prompted this thread

      Dean

      Programming these days takes more than a lone avenger with a compiler. - sam
Re: Importing external dependencies into source
by rinceWind (Monsignor) on Mar 03, 2004 at 17:00 UTC
    I've got two programs that are reliant on GNU based applications which Perl does "system" calls as part of the script. Obviously this creates a dependency on something external to Perl, which I'm not overly keen on.
    You're absolutely right not to be keen on scripts that execute commands via system. Here lies non-portability.

    What you need to do is to look and see if the equivalent of the command exists in perl - either in the core distribution, or available from CPAN.

    As others have pointed out, the equivalent of find is available inside perl, see File::Find.

    If you can list out what commands are being run externally, we might be able to suggest appropriate modules for you.

    --
    I'm Not Just Another Perl Hacker

Re: Importing external dependencies into source
by iburrell (Chaplain) on Mar 03, 2004 at 23:12 UTC
    First, you are going to have to find a Windows binary for GNU find. GNU find is in Cygwin, a Unix emulation environment for Windows. Cygwin requires an extra DLL in the simplest case and treats everything like a Unix filesystem.

    Try http://unxutils.sourceforge.net/ or http://gnuwin32.sourceforge.net/.

      Thanks, I've already got cygwin installed, this is where I've got my GNU find.exe from.

      I'm currently working on the correct syntax of how to use the GNU find.exe in my script so that it properly uses it once compiled INTO a single exe. I'll either post a full answer with syntax and compile commands or in a few hours issue a post to get further assistance. The answer I'm sure will be useful to a lot of people (and myself) so that the external dependency is gone and it offers a good solution that doesn't utilise the File::Find module.

      Dean

      Programming these days takes more than a lone avenger with a compiler. - sam
        Okay, finally here is the solution to compiling external source GNU applications into your Perl source on Win32 systems using http://www.indigostar.com/perl2exe.htm compiler. My GNU applications came from an installation of cygwin http://unxutils.sourceforge.net/ or http://gnuwin32.sourceforge.net/

        As per IndigoStar's manual page http://www.indigostar.com/pxman.htm you have to use the "-tiny" option when compiling your source.

        perl2exe -tiny /path/to/your/source/code/source.pl
        In your Perl source code you also have to add in commands to "include" the external dependent modules into your EXE at compile time.
        #perl2exe_bundle "C:\cygwin\bin\find.exe" #perl2exe_bundle "C:\cygwin\bin\cygwin1.dll" #perl2exe_bundle "C:\cygwin\bin\cygintl-1.dll" my $this_dir = $ENV{TEMP} || $ENV{TMP} || ($^O eq "MSWin32" ? $ENV{WIN +DIR} : '/tmp');
        For this example I'm importing GNU find.exe. The extra DLL's are required also by cygwin. If you run it without these DLL's compiled you get an error requesting you import them also. And yes the hash (#) at the beginning of the line is required.

        The last line there is important, once its compiled how does your application know where the compiled components will reside at runtime? IndigoStar's compiler makes temporary copies of the imported programs to a temporary directory, which are removed at the end of execution. Where that temporary directory actually is for your system is based on this command, so use it yourself. Then in your code when you utilise the "find.exe" add this variable into your code so your program can find it.
        open( FIND, "$this_dir\\find . -type d -print0 |" ) or die "can't run find: $!";
        This will compile all the external dependencies into one exe, with a few extra dll's that are created because of the "-tiny" option. This is now fully portable to any other box, and doesn't require perl or cygwin installed. No more dependencies!!

        Enjoy!
        Dean

        Programming these days takes more than a lone avenger with a compiler. - sam