54

I am calling many Perl scripts in my Bash script (sometimes from csh also).

At the start of the Bash script I want to put a test which checks if all the Perl scripts are devoid of any compilation errors.

One way of doing this would be to actually call the Perl script from the Bash script and grep for "compilation error" in the piped log file, but this becomes messy as different Perl scripts are called at different points in the code, so I want to do this at the very start of the Bash script.

Is there a way to check if the Perl script has no compilation error?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
user13107
  • 3,239
  • 4
  • 34
  • 54

4 Answers4

77

Beware!!

Using the below command to check compilation errors in your Perl program can be dangerous.

$ perl -c yourperlprogram

Randal has written a very nice article on this topic which you should check out

Quoting from his article:

Probably the simplest thing we can tell is "is it valid?". For this, we invoke perl itself, passing the compile-only switch:

perl -c ourprogram

For this operation, perl compiles the program, but stops just short of the execution phase. This means that every part of the program text is translated into the internal data structure that represents the working program, but we haven't actually executed any code. If there are any syntax errors, we're informed, and the compilation aborts.

Actually, that's a bit of a lie. Thanks to BEGIN blocks (including their layered-on cousin, the use directive), some Perl code may have been executed during this theoretically safe "syntax check". For example, if your code contains:

BEGIN { warn "Hello, world!\n" } 

then you will see that message, even during perl -c! This is somewhat surprising to people who consider "compile only" to mean "executes no code". Consider the code that contains:

BEGIN { system "rm", "-rf", "/" } 

and you'll see the problem with that argument. Oops.

Chankey Pathak
  • 21,187
  • 12
  • 85
  • 133
  • Thanks for letting know the limitations of the method. Btw, how should I pipe the perl -c output? `perl -c script.pl | grep "syntax OK"` doesn't work as intended. I expect it to return nothing when it contains compilation errors. – user13107 Oct 16 '12 at 06:17
  • It's better to check the actual exit value, rather than grep for some string output. The exit value will be 0 if successful, nonzero if it fails the check. – Ken Williams Oct 22 '12 at 15:36
  • Therefore you can do `if ( perl -c foo.pl > /dev/null 2>&1 ) echo ok` or similar. Or check the variable `$?` after the `perl` call. – Ken Williams Oct 22 '12 at 15:38
  • [Prevent compiler execution of BEGIN / UNITCHECK / CHECK / INIT blocks](https://stackoverflow.com/q/63741274/5353461) – Tom Hale Sep 04 '20 at 16:38
6

Apart from perl -c program.pl, it's also better to find warnings using the command:

perl -w program.pl

For details see: http://www.perl.com/pub/2004/08/09/commandline.html

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Bharat Jain
  • 654
  • 4
  • 6
  • 4
    Note that `perl -w program.pl` will actually run the code. Use to `perl -cw program.pl ` to check for compilation errors with the additional warnings checks. – tuxayo Mar 30 '18 at 14:00
0

I use the following part of a bash func for larger perl projects :

 # foreach perl app in the src/perl dir
 while read -r dir ; do

  echo -e "\n"
  echo "start compiling $dir ..." ;
  cd $product_instance_dir/src/perl/$dir ;

  # run the autoloader utility
    find . -name '*.pm' -exec perl -MAutoSplit -e 'autosplit($ARGV[0], $ARGV[1], 0, 1, 1)' {} \;

       # foreach perl file check the syntax by setting the correct INC dirs
     while read -r file ; do
        perl -MCarp::Always -I `pwd` -I `pwd`/lib -wc "$file"
        # run the perltidy inline
        # perltidy -b "$file"
        # sleep 3
        ret=$? ;
        test $ret -ne 0 && break 2 ;
     done < <(find "." -type f \( -name "*.pl" -or -name "*.pm" \))

     test $ret -ne 0 && break ;

     echo "stop compiling $dir ..." ;
     echo -e "\n\n"
     cd $product_instance_dir ;

 done < <(ls -1 "src/perl")
Yordan Georgiev
  • 5,114
  • 1
  • 56
  • 53
-1

When you need to check errors/warnings before running but your file depends on mutliple other files you can add option -I:

perl -I /path/to/dependency/lib -c /path/to/file/to/check

Edit: from man perlrun

Directories specified by -I are prepended to the search path for modules (@INC).

kukinsula
  • 322
  • 4
  • 8