Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

[Win32, MinGW] Building extensions that access libfoo's foo-config file

by syphilis (Canon)
on Aug 31, 2012 at 05:23 UTC ( #990923=CUFP: print w/ replies, xml ) Need Help??

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

Comment on [Win32, MinGW] Building extensions that access libfoo's foo-config file
Select or Download Code
Re: [Win32, MinGW] Building extensions that access libfoo's foo-config file
by Anonymous Monk on Aug 31, 2012 at 07:47 UTC

    I learned from gtk2 there is one script to rule them all :) pkg-config

    perhaps you can persuade the gsl/taglib mamas/papas to embrace it?

    ExtUtils::PkgConfig - simplistic interface to pkg-config

    PkgConfig - Pure-Perl Core-Only replacement for pkg-config

      ExtUtils::PkgConfig - simplistic interface to pkg-config

      Yes, EU::PC works well once it is installed - it's the gtk2 dependency that deters me from promoting it.

      I take it that PkgConfig.pm replaces *both* EU::PC and plg-config ?

      I'll take a closer look at PkgConfig.pm when I get a chance - though unless module authors start using it, there's not so much incentive to look at it.
      Do any modules use it yet ?

      Math-GSL-0.26 used EU::PC, but then they added the gsl-config stuff in 0.27. They still left the EU::PC stuff in there as a fallback, but managed to break it in the process.

      The lib-config approach is certainly nice where it works - no extra modules or packages to install.
      It's just unfortunate that a native Win32 executable version of the lib-config file doesn't get built on Windows.

      Cheers,
      Rob

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://990923]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (7)
As of 2014-10-23 03:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (123 votes), past polls