http://www.perlmonks.org?node_id=990923

Hi,
This isn't really all that cool ... and perhaps not, generally, all that useful ... but, apart from that, I'm sure that this is the right place for it.

There's a growing number of of perl extensions that build against a 3rd party library, and whose Makefile.PL/Build.PL wants to access information from that library's config file.

For example, in Math::GSL's Build.PL we find:
print "Checking for GSL..\n"; chomp(my $gv = qx{gsl-config --version}); chomp(my $gsl_prefix = qx{gsl-config --prefix}); chomp(my $gsl_cflags = qx{gsl-config --cflags}); chomp(my $gsl_libs = qx{gsl-config --libs});
And in Audio::TagLib's Makefile.PL:
bail("Please install the taglib C++ library first. \nI need the packag +e that has taglib-config") unless system('taglib-config --version > /dev/null') == 0; chomp(my $libver = qx{taglib-config --version}); ... chomp(my $libs = qx{taglib-config --libs}); ... chomp(my $inc = qx{taglib-config --cflags});
I have those files (gsl-config and taglib-config) - they're installed when I build and install the gsl and taglib libraries.
Unfortunately they're shell scripts that can't be directly executed in the cmd.exe shell, so the commands that I've listed above simply return the empty string and print out the information that gsl-config/taglib-config "is not recognized as an internal or external command, operable program or batch file".

After years of working around this sort of thing with various hacks, it finally occurred to me that, since I have sh.exe (comes with msys), I could actually execute those library-config files as `sh gsl-config --version` etc.

So I wrote the below script (cnf2bat.pl) to access that info, and write it into a batch file. (NOTE that you do need sh.exe to successfully run this script.)
With the batch file (gsl-config.bat/taglib-config.bat) created, and in the current directory, the above Makefile.PL and Build.PL commands run as intended.

I even converted the perl script to a batch file using pl2bat.
Now whenever I run perl Makefile.PL and it fails because foo-config is not executable, I can run cnf2bat C:/path/to/foo-config and I'm then ready to re-run perl Makefile.PL (and push on to the next problem ;-).
#!perl ##################################################################### # NOTE: This script (cnf2bat.pl) requires sh.exe. # # (Both msys and cygwin ship with sh.exe.) # # # # Provide an executable .bat file from a 3rd party library-config # # file. These config files (eg gsl-config, gdlib-config, # # taglib-config) are not executable in the cmd.exe shell. # # This script provides an executable .bat replacement # # (eg gsl-config.bat, gdlib-config.bat, taglib-config.bat). # # # # Then when a Makefile.PL does something like: # # # # $libs = chomp(`gsl-config --libs`); # # # # courtesy of gsl-config.bat, $libs will be set to the correct # # value - instead of being set to the empty string, and we don't # # get hit with the message that 'gsl-config' is not recognized as # # an internal or external command, operable program or batch file. # # # # Obviously, this relies on the generated .bat file being in either # # the current directory, or the path. # # # # NOTE: You ought to update the batch file (by re-running) this # # script whenever the library in question is updated. # # # # Not all options are available in the .bat file - only --prefix, # # --libs, --cflags and --version, as these are usually the only # # options that a Makefile.PL queries. (Others could easily be added # # if necessary.) # # # # This script takes the following arguments: # # 1) the name (fully qualified name) of the library-config file; # # 2) (optionally) the directory into which the generated batch # # file is to be placed. Default is '.' (cwd). # # # # You'll also need to set $sh_location (below) to the location # # of sh.exe on your machine. # # # # NOTE: This script can, itself, be converted to a batch file by # # running 'pl2bat cnf2bat.pl' # + ##################################################################### use warnings; use strict; use File::Copy; die "Usage: 'cnf2bat.pl /full/path/to/lib-config [/full/path/to/dest_d +ir]'\n" unless $ARGV[0]; my $destination = '.'; if($ARGV[1]) { die "$ARGV[1] is not an existing directory" unless -d $ARGV[1]; $destination = $ARGV[1]; } ################################################# # Hard code this to the location of sh.exe. # ################################################# my $sh_location = "C:\\MinGW\\msys\\1.0\\bin"; ################################################# # Make sure that sh.exe is in the path # ################################################# $ENV{PATH} .= ";$sh_location"; ################################################# # Check that the config file specified in # # $ARGV[0] exists, then run the write_bat_file # # subroutine. # ################################################# if(-e $ARGV[0]) {write_bat_file($ARGV[0], $destination)} else {die "$ARGV[0]: No such file"} sub write_bat_file { ################################################# # Collect the --prefix, --version, --libs and # # -cflags values from the library-config file, # # and hard code them into the batch file. # # The generated batch file has the same name as # # the library-config file, but with a '.bat' # # extension. # ################################################# my $lc = $_[0]; $lc =~ s/\\/\//g; my $filename = (split /\//, $lc)[-1]; my $lc_bat = "${destination}/${filename}.bat"; my $prefix = `sh $lc --prefix`; my $version = `sh $lc --version`; my $cflags = `sh $lc --cflags`; my $libs = `sh $lc --libs`; chomp for ($prefix, $version, $cflags, $libs); open(WR, '>', $lc_bat) or die "Can't open $lc_bat for writing: $!"; print WR "\@echo off\n\n"; print WR "if \"%1\" == \"--version\" goto VERSION\n"; print WR "if \"%1\" == \"--prefix\" goto PREFIX\n"; print WR "if \"%1\" == \"--cflags\" goto CFLAGS\n"; print WR "if \"%1\" == \"--libs\" goto LIBS\n"; print WR "if \"%1\" == \"\" goto USAGE\n\n"; print WR "echo %1 : Unknown option && echo.\ngoto endofbat\n\n"; print WR ":VERSION\n"; print WR "echo $version && echo.\n"; print WR "goto endofbat\n\n"; print WR ":CFLAGS\n"; print WR "echo $cflags && echo.\n"; print WR "goto endofbat\n\n"; print WR ":PREFIX\n"; print WR "echo $prefix && echo.\n"; print WR "goto endofbat\n\n"; print WR ":LIBS\n"; print WR "echo $libs && echo.\n"; print WR "goto endofbat\n\n"; print WR ":USAGE\n"; print WR "echo Usage: %0 --arg (where arg is either version, libs, p +refix, or cflags) && echo.\n"; print WR "goto endofbat\n\n"; print WR ":endofbat\n\n"; close WR or die "Can't close $lc_bat after writing: $!"; print "$lc_bat has been written\n"; }
Perhaps someone else might find it useful at some time ... perhaps not ;-)

Cheers,
Rob