Math-Pari
view release on metacpan or search on metacpan
auto-dbg/auto-debug-module.pl view on Meta::CPAN
# We assume that MANIFEST contains no filenames with spaces
chdir '..' or die "chdir ..: $!"
if not -f 'MANIFEST' and -f '../MANIFEST'; # we may be in ./t
# Try to avoid debugging a code failing by some other reason than crashing.
# In principle, it is easier to do in the "trigger" code with proper BEGIN/END;
# just be extra careful, and recheck. (And we can be used standalone as well!)
# There are 4 cases detected below, with !@ARGV thrown in, one covers 8 types.
my($skip_makefiles, $mod_load_out);
if ($chk_module) {
# Using blib may give a false positive (blib fails) unless distribution
# is already built; but the cost is small: just a useless rebuild+test
if (system $^X, q(-wle), q(use blib)) {
warn <<EOW;
Given that -Mblib fails, `perl Makefile.PL; make' was not run here yet...
I can't do any intelligent pre-flight testing now;
EOW
die "Having no FAILING-SCRIPT makes no sense when -Mblib fails"
unless @ARGV;
warn <<EOW;
... so I just presume YOU know that machine-code debugging IS needed...
EOW
$skip_makefiles = 1;
} else { #`
# The most common "perpendicular" problem is that a loader would not load DLL ==> no crash.
# Then there is no point in running machine code debugging; try to detect this:
my $mod_load = `$^X -wle "use blib; print(eval q(use $chk_module; 1) ? 123456789 : 987654321)" 2>&1`;
# Crashes ==> no "digits" output; DO debug. Do not debug if no crash, and no load
if ($mod_load =~ /987654321/) { # DLL does not load, no crash
$mod_load_out = `$^X -wle "use blib; use $chk_module" 2>&1`;
warn "Module $chk_module won't load: $mod_load_out";
@ARGV = (); # machine-code debugging won't help
} elsif ($mod_load =~ /123456789/) { # Loads OK
# a (suspected) failure has a chance to be helped by machine-code debug
($opt{'q'} or warn(<<EOW)), exit 0 unless @ARGV;
Module loads without a problem. (No FAILING-SCRIPT, so I skip debugging step.)
EOW
} # else: Crash during DLL load. Do debug
}
}
unless ($skip_makefiles) {
report_Makefile($_) for grep -f "$_.PL" && -f, map "$_/Makefile", '.', <*>;
}
exit 0 unless @ARGV or not $chk_module;
my $dbxname = 'dbx';
my $gdb = `gdb --version` unless $opt{d};
my $dbx = `dbx -V -c quit` unless $gdb;
my $lldb = `lldb --version` unless $gdb or $dbx; # untested
$dbx = `dbxtool -V` and $dbxname = 'dbxtool' unless $gdb or $dbx or $lldb;
sub find_candidates () {
my($sep, @cand) = quotemeta $Config{path_sep};
for my $dir (split m($sep), ($ENV{PATH} || '')) {
for my $f (<$dir/*>) {
push @cand, $f if $f =~ m{dbx|gdb|lldb}i and -x $f;
}
}
warn 'Possible candidates for debuggers: {{{'. join('}}} {{{', @cand), '}}}' if @cand;
}
unless ($gdb or $dbx or $lldb) {
find_candidates() unless $gdb = `gdb --version`;
}
sub report_no_debugger () {
die "Can't find gdb or dbx or lldb" unless defined $gdb or defined $dbx or defined $lldb;
die "Can't parse output of gdb --version: {{{$gdb}}}"
unless $dbx or $lldb or $gdb =~ /\b GDB \b | \b Copyright \b .* \b Free Software \b/x;
die "Can't parse output of `dbx -V -c quit': {{{$dbx}}}"
unless $gdb or $lldb or $dbxname eq 'dbxtool' or $dbx =~ /\b dbx \s+ debugger \b/xi;
warn "Can't parse output of `dbxtool -V': {{{$dbx}}}"
unless $gdb or $lldb or $dbxname eq 'dbx' or $dbx =~ /\b dbx \s+ debugger \b/xi;
die "Can't parse output of lldb --version: {{{$lldb}}}"
unless $dbx or $gdb or $lldb =~ /\b lldb-\S*\d/x;
}
$@ = '';
my $postpone = ( eval {report_no_debugger(); 1 } ? '' : "$@" );
if ($opt{B}) {
warn "No debugger found. Nevertheless, I build a new version per -B switch." if $postpone;
} else {
die $postpone if $postpone;
}
my $build_was_OK = -f "$bd/autodebug-make-ok";
die "Directory $bd exist; won't overwrite" if -d $bd and not ($opt{U} and $build_was_OK);
mkdir $bd or die "mkdir $bd: $!" unless -d $bd;
chdir $bd or die "chdir $bd: $!";
sub do_subdir_build () {
open MF, '../MANIFEST' or die "Can't read MANIFEST: $!";
while (<MF>) {
next unless /^\S/;
s/\s.*//;
my ($f, $d) = m[^((.*/)?.*)];
-d $d or mkpath $d if defined $d; # croak()s itself
copy "../$f", $f or die "copy `../$f' to `$f' (inside $bd): $!";
}
close MF or die "Can't close MANIFEST: $!";
my(@extraflags, $more, $subst) = 'OPTIMIZE=-g';
# Work around bugs in Config: 'ccflags' may contain (parts???) of 'optimize'.
if ($opt{O}) { # Do not change debugging
@extraflags = ();
} elsif ($Config{ccflags} =~ s/(?<!\S)\Q$Config{optimize}\E(?!\S)//) {
# e.g., Strawberry Perl
$subst++;
} elsif ($Config{gccversion} or $Config{cc} =~ /\b\w?cc\b/i) { # assume cc-flavor
# http://www.cpantesters.org/cpan/report/ef2ee424-1c8e-11e6-b928-8293027c4940
# http://www.cpantesters.org/cpan/report/4837b230-1d9d-11e6-91cb-6b7bc172c7fc
# Extra check:
$more++ if $Config{optimize} =~ /(?<!\S)-O(\d*|[a-z]?)(?!\S)/;
}
( run in 1.140 second using v1.01-cache-2.11-cpan-71847e10f99 )