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

I have an external command dep, that requires also a min version.
For example, xargs.

I've looked on cpan something to test that we a) have an external command available, and b) have at least that version, I can't find this Test::ExternalCommand like module.
Am I looking in the wrong place?

This has been my hack .. I know it's .. well.. hackish.

#!/usr/bin/perl use Test::Simple 'no_plan'; use File::Which; # gnu xargs v 4.4 or more ok( command_dependency( 'xargs', '4.2.27', 0 ), "have at least xargs 4 +.2.27"); ok( command_dependency( 'find', '4', 1 ), 'find 4'); ok( command_dependency( 'tar', '1.15' ), 'tar 1.15'); sub command_dependency { my ($name, $version, $debug)=@_; $^O=~/win/ and warn("Will not work on non posix systems.") and retu +rn; $debug or local $SIG{__WARN__} = sub { 1 }; no warnings; require File::Which; my $which = File::Which::which($name) or return; warn("Got which $name: $which"); if (defined $version){ # version have.. my $_version; # get version output if ( system("$which --version") == 0 ){ # some cli respond to -v + instead of --version $_version = `$which --version`; } elsif ( system("$which -v") ==0 ){ $_version = `$which -v`; } else { warn("Command '$name' does not return version with -v or --ve +rsion"); return; } chomp $_version; warn("got '$_version'"); # resolve to actual version string if( $_version=~/version\s+([\d\.]+)\b/ ){ warn("match 1"); $_version = $1; } elsif ( $_version=~/v\s*([\d\.]+)\b/ ){ warn("match 2"); $_version = $1; } elsif ( $_version=~/\b([\d\.]+)\b/ ){ warn("match 3"); $_version = $1; } else { warn("match missing, match into version output for '$name', d +idn't resolve to actual version string in '$_version'"); return; } # test against version argument to sub my @version = split(/\./, $version); my @_version = split(/\./, $_version); # only test as far as argument provided go my $count= scalar @version; # i know, there are quicker ways to +do this.. but.. # this is more clear for anybody viewing the code warn "count.. $count\n"; my $index = 0; for ( 0 .. $count ){ defined $version[$index] or next; if ( $version[$index] > $_version[$index] ){ return 1; # obviously higher overall. } elsif ( $version[$index] < $_version[$index] ){ return 0; # no high enough } $index++; # just high enough next; } # if we got here, have the version we want at least return 1; } # did not check version, but have command return 1; }

I'm sure there's something out there that doesn't list look like it works, but actually works. (?) Any suggestions where that may be?

Would be useful for testing c libs etc. Maybe then, this should simply be coded into the makefile? They must have this down pat by now (?)

Code updated

Replies are listed 'Best First'.
Re: test for non perl command dependency
by Crackers2 (Parson) on Jul 14, 2009 at 05:02 UTC

    Not really an answer to your question, but...

    I've found that in most cases checking for a minimum version isn't as useful as it seems, for one or more of the reasons below:

    • Distributions apply their own patches which can cause versions below your specified minimum to work fine with your programs.
    • Or they may take away features because they think they're not mature enough yet or cause problems.
    • Or they may use a from-scratch reimplementation with different version numbers

    In most cases if an external tool doesn't support a feature it'll probably exit with an error when you call it, and you can just print an error at that point.

    If it's really important to know in advance, do a test for the actual feature, not just a version number.

    And, even though people might not read it, clearly add the dependencies to the documentation.

      This kinda is an answer.. xargs does have a feature that was later introduced. The --delimiter cli argument.

      I considered testing for that, but I thought it would be too cheesy, too hacky.. but then.. I am glad to see you suggest this. Good idea. Thank you!