improve MSVC support some more
authorTony Cook <tony@develop-help.com>
Sun, 23 Oct 2011 00:34:55 +0000 (11:34 +1100)
committerTony Cook <tony@develop-help.com>
Sun, 23 Oct 2011 00:36:24 +0000 (11:36 +1100)
Changes
FT2/inc/Devel/CheckLib.pm
GIF/inc/Devel/CheckLib.pm
JPEG/inc/Devel/CheckLib.pm
PNG/inc/Devel/CheckLib.pm
T1/inc/Devel/CheckLib.pm
TIFF/inc/Devel/CheckLib.pm
W32/inc/Devel/CheckLib.pm
inc/Devel/CheckLib.pm
lib/Imager/Probe.pm

diff --git a/Changes b/Changes
index b93fcf6..1d0f45d 100644 (file)
--- a/Changes
+++ b/Changes
@@ -66,6 +66,8 @@ Bug fixes:
    prefixed names on Win32.
    https://rt.cpan.org/Ticket/Display.html?id=71642
 
+ - fix library detection with MSVC
+
 Imager 0.85_01 - 10 Oct 2011
 ==============
 
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index 531a623..c396ee4 100644 (file)
@@ -245,13 +245,13 @@ sub assert_lib {
        }
     }
     if(defined($args{INC})) {
-        foreach my $arg (split(' ', $args{INC})) {
+        foreach my $arg (_shellwords($args{INC})) {
             die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
             push @incpaths, substr($arg, 2);
         }
     }
 
-    my @cc = _findcc();
+    my ($cc, $ld) = _findcc();
     my @missing;
     my @wrongresult;
     my @use_headers;
@@ -271,21 +271,25 @@ sub assert_lib {
         if ( $Config{cc} eq 'cl' ) {                 # Microsoft compiler
             require Win32;
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 "/Fe$exefile",
-                (map { '/I'.Win32::GetShortPathName($_) } @incpaths)
+                (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
+                "/link",
+                @$ld
             );
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
                 (map { "-I$_" } @incpaths),
                 "-o$exefile",
-                $cfile
+                $cfile,
+                @$ld
             );
         } else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
             @sys_cmd = (
-                @cc,
+                @$cc,
+                @$ld,
                 $cfile,
                 (map { "-I$_" } @incpaths),
                 "-o", "$exefile"
@@ -317,18 +321,20 @@ sub assert_lib {
             } @libpaths; 
             # this is horribly sensitive to the order of arguments
             @sys_cmd = (
-                @cc,
+                @$cc,
                 $cfile,
                 ( map { "$_.lib" } @$libs ),
                 "/Fe$exefile", 
                 (map { '/I'.Win32::GetShortPathName($_) } @incpaths),
                 "/link",
+               @$ld,
                 (map {'/libpath:'.Win32::GetShortPathName($_)} @$paths),
             );
         } elsif($Config{cc} eq 'CC/DECC') {          # VMS
         } elsif($Config{cc} =~ /bcc32(\.exe)?/) {    # Borland
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 "-o$exefile",
                 (map { "-l$_" } @$libs ),
                 (map { "-I$_" } @incpaths),
@@ -337,7 +343,8 @@ sub assert_lib {
         } else {                                     # Unix-ish
                                                      # gcc, Sun, AIX (gcc, cc)
             @sys_cmd = (
-                @cc,
+                @$cc,
+               @$ld,
                 $cfile,
                 "-o", "$exefile",
                 (map { "-l$_" } @$libs ),
@@ -368,23 +375,55 @@ sub _cleanup_exe {
     unlink $exefile if -f $exefile;
     unlink $ofile if -f $ofile;
     unlink "$exefile\.manifest" if -f "$exefile\.manifest";
+    if ( $Config{cc} eq 'cl' ) {
+       # MSVC also creates foo.ilk and foo.pdb
+       my $ilkfile = $exefile;
+       $ilkfile =~ s/$Config{_exe}$/.ilk/;
+       my $pdbfile = $exefile;
+       $pdbfile =~ s/$Config{_exe}$/.pdb/;
+       unlink $ilkfile if -f $ilkfile;
+       unlink $pdbfile if -f $pdbfile;
+    }
     return
 }
-    
+
+# return ($cc, $ld)
+# where $cc is an array ref of compiler name, compiler flags
+# where $ld is an array ref of linker flags
 sub _findcc {
     # Need to use $keep=1 to work with MSWin32 backslashes and quotes
-    my @Config_ccflags_ldflags =  @Config{qw(ccflags ldflags)};  # use copy so ASPerl will compile
-    my @flags = grep { length } map { quotewords('\s+', 1, $_ || ()) } @Config_ccflags_ldflags;
+    my $Config_ccflags =  $Config{ccflags};  # use copy so ASPerl will compile
+    my @Config_ldflags =  @Config{qw(ldflags perllibs)};
+    my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags);
+    my @ldflags = grep { length } quotewords('\s+', 1, @Config_ldflags);
     my @paths = split(/$Config{path_sep}/, $ENV{PATH});
     my @cc = split(/\s+/, $Config{cc});
-    return (@cc, @flags) if -x $cc[0];
+    return ( [ @cc, @ccflags ], \@ldflags ) if -x $cc[0];
     foreach my $path (@paths) {
         my $compiler = File::Spec->catfile($path, $cc[0]) . $Config{_exe};
-        return ($compiler, @cc[1 .. $#cc], @flags) if -x $compiler;
+        return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
+            if -x $compiler;
     }
     die("Couldn't find your C compiler\n");
 }
 
+sub _shellwords {
+    my $line = shift;
+
+    if ($^O eq "MSWin32") {
+       my @elements;
+       $line =~ s/^\s+//;
+       while ($line =~ s/^"([^"]*)"// || $line =~ s/^(\S+)//) {
+         push @elements, $1;
+         $line =~ s/^\s+//;
+       }
+       return @elements;
+    }
+    else {
+       return quotewords('\s+', 0, shift);
+    } 
+}
+
 # code substantially borrowed from IPC::Run3
 sub _quiet_system {
     my (@cmd) = @_;
index e8db68e..611c182 100644 (file)
@@ -130,6 +130,38 @@ sub _probe_pkg {
   return;
 }
 
+sub _is_msvc {
+  return $Config{cc} eq "cl";
+}
+
+sub _lib_basename {
+  my ($base) = @_;
+
+  if (_is_msvc()) {
+    return $base;
+  }
+  else {
+    return "lib$base";
+  }
+}
+
+sub _lib_option {
+  my ($base) = @_;
+
+  if (_is_msvc()) {
+    return $base . $Config{_a};
+  }
+  else {
+    return "-l$base";
+  }
+}
+
+sub _quotearg {
+  my ($opt) = @_;
+
+  return $opt =~ /\s/ ? qq("$opt") : $opt;
+}
+
 sub _probe_check {
   my ($req) = @_;
 
@@ -139,9 +171,10 @@ sub _probe_check {
     # synthesize a libcheck
     my $lext=$Config{'so'};   # Get extensions of libraries
     my $aext=$Config{'_a'};
+    my $basename = _lib_basename($libbase);
     $libcheck = sub {
-      -e File::Spec->catfile($_[0], "lib$libbase$aext")
-       || -e File::Spec->catfile($_[0], "lib$libbase.$lext")
+      -e File::Spec->catfile($_[0], "$basename$aext")
+       || -e File::Spec->catfile($_[0], "$basename.$lext")
       };
   }
 
@@ -187,7 +220,7 @@ sub _probe_check {
     push @libs, $req->{libopts};
   }
   elsif ($libbase) {
-    push @libs, "-l$libbase";
+    push @libs, _lib_option($libbase);
   }
   else {
     die "$req->{altname}: inccheck but no libbase or libopts";
@@ -195,8 +228,8 @@ sub _probe_check {
 
   return
     {
-     INC => "-I$found_incpath",
-     LIBS => "@libs",
+     INC => _quotearg("-I$found_incpath"),
+     LIBS => join(" ", map _quotearg($_), @libs),
      DEFINE => "",
     };
 }