diff options
author | gregor herrmann <gregoa@debian.org> | 2022-05-07 20:46:02 +0200 |
---|---|---|
committer | gregor herrmann <gregoa@debian.org> | 2022-05-07 20:46:02 +0200 |
commit | a1d39bf853e20805af41cf9de4205611dd372626 (patch) | |
tree | 922944217f8fcae2c353f0b19d09e58b8c893a36 | |
parent | cbcab4aaf385d75640e976f304e3a9974547e3a9 (diff) |
New upstream version 1.16
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | META.json | 8 | ||||
-rw-r--r-- | META.yml | 4 | ||||
-rw-r--r-- | lib/Devel/CheckLib.pm | 226 | ||||
-rw-r--r-- | t/exit_with_message.t | 2 | ||||
-rw-r--r-- | t/lib/Helper.pm | 24 | ||||
-rw-r--r-- | t/multi-word-compiler.t | 9 |
7 files changed, 132 insertions, 146 deletions
@@ -1,3 +1,8 @@ +1.16 2022-05-04 Stop all the tests that require a working compiler from + skipping on AIX + +1.15 2022-05-04 Refactor, stop GCC optimising away test code + 1.14 2019-11-12 Use Capture::Tiny instead of Capture::Output 1.13 2018-06-23 Improve Makefile.PL @@ -6,13 +6,13 @@ "Yasuhiro Matsumoto" ], "dynamic_config" : 0, - "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", + "generated_by" : "ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" + "version" : 2 }, "name" : "Devel-CheckLib", "no_index" : { @@ -54,6 +54,6 @@ "url" : "http://github.com/mattn/p5-Devel-CheckLib" } }, - "version" : "1.14", - "x_serialization_backend" : "JSON::PP version 2.27400_02" + "version" : "1.16", + "x_serialization_backend" : "JSON::PP version 4.02" } @@ -12,7 +12,7 @@ build_requires: configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 -generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' +generated_by: 'ExtUtils::MakeMaker version 7.34, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html @@ -29,5 +29,5 @@ requires: perl: '5.00405' resources: repository: http://github.com/mattn/p5-Devel-CheckLib -version: '1.14' +version: '1.16' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff --git a/lib/Devel/CheckLib.pm b/lib/Devel/CheckLib.pm index 1efd43f..2e5a252 100644 --- a/lib/Devel/CheckLib.pm +++ b/lib/Devel/CheckLib.pm @@ -5,9 +5,9 @@ package Devel::CheckLib; use 5.00405; #postfix foreach use strict; use vars qw($VERSION @ISA @EXPORT); -$VERSION = '1.14'; +$VERSION = '1.16'; use Config qw(%Config); -use Text::ParseWords 'quotewords'; +use Text::ParseWords qw(quotewords shellwords); use File::Spec; use File::Temp; @@ -260,21 +260,79 @@ sub _parse_line { return(@pieces); } +sub _parsewords { + return shellwords @_ if $^O ne 'MSWin32'; + # for Win32, take off "" but leave \ + map { my $s=$_; $s =~ s/^"(.*)"$/$1/; $s } grep defined && length, quotewords '\s+', 1, @_; +} + +sub _compile_cmd { + my ($Config_cc, $cc, $cfile, $exefile, $incpaths, $ld, $Config_libs, $lib, $libpaths) = @_; + my @sys_cmd = @$cc; + if ( $Config_cc eq 'cl' ) { # Microsoft compiler + # this is horribly sensitive to the order of arguments + push @sys_cmd, + $cfile, + (defined $lib ? "${lib}.lib" : ()), + "/Fe$exefile", + (map '/I'.$_, @$incpaths), + "/link", + @$ld, + _parsewords($Config_libs), + (defined $lib ? map '/libpath:'.$_, @$libpaths : ()), + ; + } elsif($Config_cc =~ /bcc32(\.exe)?/) { # Borland + push @sys_cmd, + @$ld, + (map "-I$_", @$incpaths), + "-o$exefile", + (defined $lib ? ((map "-L$_", @$libpaths), "-l$lib") : ()), + $cfile, + ; + } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ... + push @sys_cmd, + (map "-I$_", @$incpaths), + $cfile, + (!defined $lib ? () : ( + (map "-L$_", @$libpaths), + ($^O eq 'darwin' ? (map { "-Wl,-rpath,$_" } @$libpaths) : ()), + "-l$lib", + )), + @$ld, + "-o", $exefile, + ; + } + @sys_cmd; +} + +sub _make_cfile { + my ($use_headers, $function, $debug) = @_; + my $code = ''; + $code .= qq{#include <$_>\n} for @$use_headers; + $code .= "int main(int argc, char *argv[]) { ".($function || 'return 0;')." }\n"; + if ($debug) { + (my $c = $code) =~ s:^:# :gm; + warn "# Code:\n$c\n"; + } + my ($ch, $cfile) = File::Temp::tempfile( + 'assertlibXXXXXXXX', SUFFIX => '.c' + ); + print $ch $code; + close $ch; + (my $ofile = $cfile) =~ s/\.c$/$Config{_o}/; + ($cfile, $ofile); +} + sub assert_lib { my %args = @_; - my (@libs, @libpaths, @headers, @incpaths); - - # FIXME: these four just SCREAM "refactor" at me - @libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib}) - if $args{lib}; - @libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath}) - if $args{libpath}; - @headers = (ref($args{header}) ? @{$args{header}} : $args{header}) - if $args{header}; - @incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath}) - if $args{incpath}; + $args{$_} = [$args{$_}] + for grep $args{$_} && !ref($args{$_}), qw(lib libpath header incpath); + my @libs = @{$args{lib} || []}; + my @libpaths = @{$args{libpath} || []}; + my @headers = @{$args{header} || []}; + my @incpaths = @{$args{incpath} || []}; my $analyze_binary = $args{analyze_binary}; - my $not_execute = $args{not_execute}; + my $execute = !$args{not_execute}; my @argv = @ARGV; push @argv, _parse_line('\s+', 0, $ENV{PERL_MM_OPT}||''); @@ -292,15 +350,14 @@ sub assert_lib { } } - # using special form of split to trim whitespace if(defined($args{LIBS})) { - foreach my $arg (split(' ', $args{LIBS})) { + foreach my $arg (_parsewords($args{LIBS})) { die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/); push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2); } } if(defined($args{INC})) { - foreach my $arg (split(' ', $args{INC})) { + foreach my $arg (_parsewords($args{INC})) { die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/); push @incpaths, substr($arg, 2); } @@ -315,45 +372,9 @@ sub assert_lib { # first figure out which headers we can't find ... for my $header (@headers) { push @use_headers, $header; - my($ch, $cfile) = File::Temp::tempfile( - 'assertlibXXXXXXXX', SUFFIX => '.c' - ); - my $ofile = $cfile; - $ofile =~ s/\.c$/$Config{_o}/; - print $ch qq{#include <$_>\n} for @use_headers; - print $ch qq{int main(void) { return 0; }\n}; - close($ch); + my ($cfile, $ofile) = _make_cfile(\@use_headers, '', $args{debug}); my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe}; - my @sys_cmd; - # FIXME: re-factor - almost identical code later when linking - if ( $Config{cc} eq 'cl' ) { # Microsoft compiler - require Win32; - @sys_cmd = ( - @$cc, - $cfile, - "/Fe$exefile", - (map { '/I'.Win32::GetShortPathName($_) } @incpaths), - "/link", - @$ld, - split(' ', $Config{libs}), - ); - } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland - @sys_cmd = ( - @$cc, - @$ld, - (map { "-I$_" } @incpaths), - "-o$exefile", - $cfile - ); - } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ... - @sys_cmd = ( - @$cc, - (map { "-I$_" } @incpaths), - $cfile, - @$ld, - "-o", "$exefile" - ); - } + my @sys_cmd = _compile_cmd($Config{cc}, $cc, $cfile, $exefile, \@incpaths, $ld, $Config{libs}); warn "# @sys_cmd\n" if $args{debug}; my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); push @missing, $header if $rv != 0 || ! -f $exefile; @@ -362,58 +383,13 @@ sub assert_lib { } # now do each library in turn with headers - my($ch, $cfile) = File::Temp::tempfile( - 'assertlibXXXXXXXX', SUFFIX => '.c' - ); - my $ofile = $cfile; - $ofile =~ s/\.c$/$Config{_o}/; - print $ch qq{#include <$_>\n} foreach (@headers); - print $ch "int main(int argc, char *argv[]) { ".($args{function} || 'return 0;')." }\n"; - close($ch); + my ($cfile, $ofile) = _make_cfile(\@use_headers, @args{qw(function debug)}); for my $lib ( @libs ) { + last if $Config{cc} eq 'CC/DECC'; # VMS my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe}; - my @sys_cmd; - if ( $Config{cc} eq 'cl' ) { # Microsoft compiler - require Win32; - my @libpath = map { - q{/libpath:} . Win32::GetShortPathName($_) - } @libpaths; - # this is horribly sensitive to the order of arguments - @sys_cmd = ( - @$cc, - $cfile, - "${lib}.lib", - "/Fe$exefile", - (map { '/I'.Win32::GetShortPathName($_) } @incpaths), - "/link", - @$ld, - split(' ', $Config{libs}), - (map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths), - ); - } elsif($Config{cc} eq 'CC/DECC') { # VMS - } elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland - @sys_cmd = ( - @$cc, - @$ld, - "-o$exefile", - (map { "-I$_" } @incpaths), - (map { "-L$_" } @libpaths), - "-l$lib", - $cfile); - } else { # Unix-ish - # gcc, Sun, AIX (gcc, cc) - @sys_cmd = ( - @$cc, - (map { "-I$_" } @incpaths), - $cfile, - (map { "-L$_" } @libpaths), - "-l$lib", - @$ld, - "-o", "$exefile", - ); - } + my @sys_cmd = _compile_cmd($Config{cc}, $cc, $cfile, $exefile, \@incpaths, $ld, $Config{libs}, $lib, \@libpaths); warn "# @sys_cmd\n" if $args{debug}; - local $ENV{LD_RUN_PATH} = join(":", grep $_, @libpaths, $ENV{LD_RUN_PATH}) unless $^O eq 'MSWin32'; + local $ENV{LD_RUN_PATH} = join(":", grep $_, @libpaths, $ENV{LD_RUN_PATH}) unless $^O eq 'MSWin32' or $^O eq 'darwin'; local $ENV{PATH} = join(";", @libpaths).";".$ENV{PATH} if $^O eq 'MSWin32'; my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd); if ($rv != 0 || ! -f $exefile) { @@ -423,24 +399,24 @@ sub assert_lib { chmod 0755, $exefile; my $absexefile = File::Spec->rel2abs($exefile); $absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/; - if (!$not_execute && system($absexefile) != 0) { - push @wrongresult, $lib; - } - else { - if ($analyze_binary) { - push @wronganalysis, $lib if !$analyze_binary->($lib, $exefile) - } + warn "# Execute($execute): $absexefile\n" if $args{debug}; + if ($execute) { + my $retval = system($absexefile); + warn "# return value: $retval\n" if $args{debug}; + push @wrongresult, $lib if $retval != 0; } + push @wronganalysis, $lib + if $analyze_binary and !$analyze_binary->($lib, $exefile); } _cleanup_exe($exefile); - } + } unlink $cfile; - my $miss_string = join( q{, }, map { qq{'$_'} } @missing ); + my $miss_string = join( q{, }, map qq{'$_'}, @missing ); die("Can't link/include C library $miss_string, aborting.\n") if @missing; - my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult); + my $wrong_string = join( q{, }, map qq{'$_'}, @wrongresult); die("wrong result: $wrong_string\n") if @wrongresult; - my $analysis_string = join(q{, }, map { qq{'$_'} } @wronganalysis ); + my $analysis_string = join(q{, }, map qq{'$_'}, @wronganalysis ); die("wrong analysis: $analysis_string") if @wronganalysis; } @@ -459,14 +435,12 @@ sub _cleanup_exe { $pdbfile =~ s/$Config{_exe}$/.pdb/; push @rmfiles, $ilkfile, $pdbfile; } - foreach (@rmfiles) { - if ( -f $_ ) { - unlink $_ or warn "Could not remove $_: $!"; - } + foreach (grep -f, @rmfiles) { + unlink $_ or warn "Could not remove $_: $!"; } return } - + # return ($cc, $ld) # where $cc is an array ref of compiler name, compiler flags # where $ld is an array ref of linker flags @@ -474,14 +448,15 @@ sub _findcc { my ($debug, $user_ccflags, $user_ldflags) = @_; # Need to use $keep=1 to work with MSWin32 backslashes and quotes my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile + $Config_ccflags =~ s:-O\S*::; # stop GCC optimising away test code my @Config_ldflags = (); for my $config_val ( @Config{qw(ldflags)} ){ push @Config_ldflags, $config_val if ( $config_val =~ /\S/ ); } - my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||'', $user_ccflags||''); - my @ldflags = grep { length && $_ !~ m/^-Wl/ } quotewords('\s+', 1, @Config_ldflags, $user_ldflags||''); + my @ccflags = grep { length } _parsewords($Config_ccflags||'', $user_ccflags||''); + my @ldflags = grep { length && $_ !~ m/^-Wl/ } _parsewords(@Config_ldflags, $user_ldflags||''); my @paths = split(/$Config{path_sep}/, $ENV{PATH}); - my @cc = split(/\s+/, $Config{cc}); + my @cc = _parsewords($Config{cc}); if (check_compiler ($cc[0], $debug)) { return ( [ @cc, @ccflags ], \@ldflags ); } @@ -510,11 +485,10 @@ sub check_compiler { my ($compiler, $debug) = @_; if (-f $compiler && -x $compiler) { - if ($debug) { - warn("# Compiler seems to be $compiler\n"); - } + warn "# Compiler seems to be $compiler\n" if $debug; return 1; } + warn "# Compiler was not $compiler\n" if $debug; return ''; } diff --git a/t/exit_with_message.t b/t/exit_with_message.t index 67daae1..b79d207 100644 --- a/t/exit_with_message.t +++ b/t/exit_with_message.t @@ -12,7 +12,7 @@ check_lib_or_exit( qw/lib hlagh/ ); ENDPRINT $fh->close; -my $err = `$^X $fh 2>&1`; +my $err = `"$^X" $fh 2>&1`; if($err =~ /Couldn't find your C compiler/) { plan skip_all => "Couldn't find your C compiler"; diff --git a/t/lib/Helper.pm b/t/lib/Helper.pm index f298c71..ca08b35 100644 --- a/t/lib/Helper.pm +++ b/t/lib/Helper.pm @@ -43,7 +43,7 @@ sub create_testlib { print {$code_fh} "int libversion() { return 42; }\nint foo() { return 0; }\n"; $code_fh->close; - my $cc = $Config{cc}; + my $cc = (split(/\s+/, $Config{cc}))[0]; my $gccv = $Config{gccversion}; my $rv = $cc eq 'gcc' ? _gcc_lib( $libname ) : @@ -62,20 +62,19 @@ sub _gcc_lib { my $ar = find_binary('ar') or return; my $ranlib = find_binary('ranlib') or return; my $ccflags = $Config{ccflags}; - - _quiet_system("$cc $ccflags -c ${libname}.c") and return; - _quiet_system("$ar rc lib${libname}.a ${libname}.o") and return; - _quiet_system("$ranlib lib${libname}.a") and return; - return -f "lib${libname}.a" + my $libfile = "lib${libname}.a"; + _quiet_system(qq{"$cc" $ccflags -c ${libname}.c}) and return; + _quiet_system($ar, 'rc', $libfile, "${libname}$Config{_o}") and return; + _quiet_system($ranlib, $libfile) and return; + return -f $libfile } sub _cl_lib { my ($libname) = @_; my $cc = find_compiler() or return; my $ar = find_binary('lib') or return; - _quiet_system($cc, '/c', "${libname}.c") and return; - _quiet_system($ar, "${libname}.obj") and return; + _quiet_system($ar, "${libname}$Config{_o}") and return; return -f "${libname}.lib"; } @@ -115,7 +114,14 @@ sub lib_to_bin { } sub find_compiler { - return find_binary($Config{cc}); + my $result = find_binary($Config{cc}); + return $result if($result); + + # sometimes $Config{cc} isn't very clean eg it can be 'cc -q32' on AIX + return find_binary((split(/\s+/, $Config{cc}))[0]) + if($Config{cc} =~ /\s/); + + undef; } 1; # must be true diff --git a/t/multi-word-compiler.t b/t/multi-word-compiler.t index 1fe415a..c9c0f86 100644 --- a/t/multi-word-compiler.t +++ b/t/multi-word-compiler.t @@ -20,19 +20,20 @@ BEGIN { } } +my $fake_cc = qq{"$^X" $Config{cc}}; if ($Mock::Config::VERSION) { - Mock::Config->import(cc => "$^X $Config{cc}"); + Mock::Config->import(cc => $fake_cc); } elsif (defined($ActivePerl::VERSION) && $Config{cc} =~ /\bgcc\b/) { my $obj = tied %Config::Config; - $obj->{cc} = "$^X $Config{cc}"; + $obj->{cc} = $fake_cc; } else { - eval { $Config{cc} = "$^X $Config{cc}"; } + eval { $Config{cc} = $fake_cc; } } SKIP: { skip "Couldn't update %Config", 1 if $@ =~ /%Config::Config is read-only/; eval "use Devel::CheckLib"; - ok(!$@, "Good multi-word compiler is OK"); + is $@, "", "Good multi-word compiler is OK"; } |