summaryrefslogtreecommitdiff
path: root/dist
diff options
context:
space:
mode:
authorDavid Golden <dagolden@cpan.org>2010-12-15 10:47:14 -0500
committerDavid Golden <dagolden@cpan.org>2010-12-15 10:48:56 -0500
commit8ba25f7a636c7e234b1c5bc09aa0b35eaa143601 (patch)
treec95e76a857d4caa234f281a98884dee98b9eea40 /dist
parentf1c605336053dab86b920ac27a6262e25665bc65 (diff)
downloadperl-8ba25f7a636c7e234b1c5bc09aa0b35eaa143601.tar.gz
Change ExtUtils::CBuilder upstream to blead
ExtUtils::CBuilder now has blead as its upstream repository. The distribution has been moved to the dist/ directory consistent with this change.
Diffstat (limited to 'dist')
-rw-r--r--dist/ExtUtils-CBuilder/Changes390
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder.pm331
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Base.pm383
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Unix.pm40
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/VMS.pm294
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows.pm291
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm130
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm151
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm131
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/aix.pm31
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/cygwin.pm33
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/darwin.pm22
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/dec_osf.pm18
-rw-r--r--dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/os2.pm80
-rw-r--r--dist/ExtUtils-CBuilder/t/00-have-compiler.t57
-rw-r--r--dist/ExtUtils-CBuilder/t/01-basic.t106
-rw-r--r--dist/ExtUtils-CBuilder/t/02-link.t97
-rw-r--r--dist/ExtUtils-CBuilder/t/03-cplusplus.t63
-rw-r--r--dist/ExtUtils-CBuilder/t/04-base.t412
19 files changed, 3060 insertions, 0 deletions
diff --git a/dist/ExtUtils-CBuilder/Changes b/dist/ExtUtils-CBuilder/Changes
new file mode 100644
index 0000000000..41b4de2d72
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/Changes
@@ -0,0 +1,390 @@
+Revision history for Perl extension ExtUtils::CBuilder.
+
+0.2802 - Sun Dec 12 07:22:43 EST 2010
+
+ Fixed:
+
+ - Incorporated another t/04-base.t fix from bleadperl
+ [Chris Williams]
+
+0.2801 - Wed Dec 8 21:36:56 EST 2010
+
+ Fixed:
+
+ - Fixed spurious t/04-base.t failure when run from Perl core
+ [David Golden]
+
+0.2800 - Mon Dec 6 16:05:46 EST 2010
+
+ - No changes from 0.27_07
+
+0.27_07 - Wed Sep 29 21:48:55 EDT 2010
+
+ Fixed:
+
+ - Fixed t/02-link.t on perl < 5.8
+
+0.27_06 - Mon Sep 27 15:29:54 EDT 2010
+
+ Fixed:
+
+ - Preserves exit status on VMS [Craig Berry]
+
+ - Fix Win32 split_like_shell escaping [Christian Walde]
+
+0.27_05 - Wed Jul 28 15:29:59 EDT 2010
+
+ Fixed:
+
+ - Tests no longer fail if user has set the CC environment variable
+
+0.27_04 - Mon Jul 26 22:41:43 EDT 2010
+
+ Added:
+ - handle c compiler and c++ compiler separately
+ (adds requirement for IPC::Cmd) [Jens Rehsack]
+
+ Others:
+ - rely on File::Temp::tempfile and File::Spec::tmpdir to
+ get unique file name for checking for compiler
+ [Jens Rehsack]
+
+ - Code base modernization and substantial code coverage improvments
+ [Jim Keenan]
+
+0.2703 - Tue Mar 16 17:10:55 EDT 2010
+
+ Bugs fixed:
+ - fixed tests for Windows and MSVC [Jan Dubois]
+
+0.2702 - Mon Feb 22 15:10:52 EST 2010
+
+ Bugs fixed:
+ - compile() changes in 0.2701 did not work on Windows. Now fixed.
+
+0.2701 - Tue Feb 16 09:12:45 EST 2010
+
+ Bugs fixed:
+ - compile() now accepts both string & array for 'include_dirs'
+ argument, as documented.(RT#54606) [Alberto Simões]
+
+0.27 - Thu Oct 29 21:29:56 EDT 2009
+
+ Other:
+ - Removed Build.PL to avoid creating a circular dependency
+ - Added version numbers to Windows compiler driver modules
+
+0.26_05 - Sun Oct 25 17:29:02 EDT 2009
+
+ Bugs fixed:
+ - Fixed t/02link.t failures on cygwin with Perl 5.8 [David Golden]
+
+ Other:
+ - Made have_compiler (and have_cplusplus) quiet without echoing
+ the test command to STDOUT [David Golden]
+
+0.26_04 - Mon Oct 19 21:57:46 EDT 2009
+
+ Enhancements:
+ - Added 'have_cplusplus()' method to check for C++ support
+ - Added patches for building Perl with mingw64 [Sisyphus]
+ - Allow CC environment variable to override $Config{cc}
+
+ Bugs fixed:
+ - Fixed link executable command for Win32 MSVC (RT#40819) [Cosimo
+ Streppone]
+ - Removed MSVC version check when embedding a manifest file
+ (RT #43002) [Steve Hay]
+
+ Other:
+ - Split Windows compiler driver packages into individual *.pm files
+
+0.260301 - Sat Aug 29 11:04:41 EDT 2009
+
+ Bugs fixed:
+ - Fixed linking error on Win32 with gcc compiler (RT#49000)
+ [kmx]
+
+0.2603 - Sat Jul 18 06:56:06 EDT 2009
+
+ Bugs fixed:
+ - Makefile.PL had wrong INSTALLDIRS setting for older Perls
+ (RT#47985) [David Golden]
+
+0.2602 - Sat Jul 4 10:57:12 EDT 2009
+
+ Bugs fixed:
+ - Fixed 00-have-compiler.t if $^X is a relative path [David Wheeler]
+
+0.2601 - Wed Jul 1 09:37:39 EDT 2009
+
+ Bugs fixed:
+ - On VMS, cleans up extra files generated during testing
+ [John E. Malmberg, Craig Berry]
+
+0.26 - Mon Jun 29 20:11:52 EDT 2009
+
+ - No changes from 0.25_01
+
+0.25_01 - Sat Jun 27 23:13:20 EDT 2009
+
+ - Changed test library to Test::More
+
+ - Added tests for have_compiler
+
+ - Skips tests that need a compiler if have_compiler is false
+
+ - have_compiler will try to compile in the current directory
+ if compiling in tmpdir fails for whatever reason
+
+0.25 - Fri Jun 26 16:18:13 EDT 2009
+
+ - Slight diagnostic improvements in link.t
+
+0.24_01 - Sun Mar 8 14:50:10 2009
+
+ - On Windows, don't generate "mt" command when CRT is statically
+ linked. [Jan Dubois]
+
+ - On Cygwin, examine $Config{useshrplib} to see whether we're
+ supposed to be linking with a shared perl library or not. [Reini
+ Urban]
+
+ - In link_executable() on Cygwin, trust $Config{ld} rather than using
+ $Config{cc} for linking. [Reini Urban]
+
+ - Add 'haiku' as a Unix-like platform. [Ingo Weinhold]
+
+0.24 - Fri Aug 15 22:01:48 2008
+
+ - Added 'gnu' and 'gnukfreebsd' as Unix variants. [Niko Tyni]
+
+ - Brought in some VMS fixes from bleadperl: "Correct and complete
+ CBuilder's handling of external libraries when linking on VMS."
+ [Craig Berry]
+
+0.23 - Sat Apr 19 22:28:03 2008
+
+ - Fixed some problems (some old, some new) with Strawberry Perl on
+ Windows. [Alberto Simo~es]
+
+ - Will now install in the core perl lib directory when the user's
+ perl is new enough to have us in core. [Yi Ma Mao]
+
+0.22 - Fri Feb 8 21:52:21 2008
+
+ - Replaced the split_like_shell() method on Windows with a
+ near-no-op, which is probably more correct and has the benefit of
+ not messing up UNC paths. [John R. LoVerso, see
+ http://rt.cpan.org/Ticket/Display.html?id=26545]
+
+ - Fixed extra_compiler_flags on Windows, they were being
+ ignored. [Robert May]
+
+0.21 - Tue Oct 30 06:46:01 2007
+
+ - Clean up perl_src path using Cwd::realpath(). Only affects usage
+ as part of the perl core.
+
+ - Protect $., $@, $!, $^E, and $? from any clobbering that might
+ occur in our DESTROY method. [Zefram]
+
+ - From bleadperl, a patch to clean up debug symbol files (.pdb for
+ VC++, .tds for BCC) when running have_compiler(). [Steve Hay &
+ Steve Peters]
+
+0.19 - Sun May 13 14:29:18 2007
+
+ - When building as part of the perl core (so this is irrelevant for
+ people downloading from CPAN) we now try a little harder to find
+ the perl sources. [Jos Boumans]
+
+ - Fixed a part of the manifest thingy that got broken on 64-bit
+ Windows platforms in version 0.18. [Steve Hay, Jan Dubois]
+
+0.18 - Mon Mar 26 21:29:09 2007
+
+ - Various OS/2 fixes:
+ + Put .LIB file near .DEF file
+ + Got library-file building working better
+ + Handled libperl_overrides better
+ [Ilya Zakharevich]
+
+ - On Windows: embed manifest files in DLLs built with Module-Build
+ when using VC8. [Steve Hay]
+
+ - Added a workaround for a config error on dec_osf: the linker is
+ $Config{cc}, not $Config{ld}. [Jarkko Hietaniemi]
+
+ - Borland's compiler "response files" will not pass through macro
+ definitions that contain quotes. The quotes get stripped and there
+ seems to be no way to escape them. So we leave macros on the
+ command line. [Randy W. Sims]
+
+0.18 Sat Mar 25 13:35:47 CST 2006
+
+ - Yet more fixes for arg_defines() on VMS. [Craig A. Berry and John
+ E. Malmberg]
+
+0.17 Wed Mar 15 22:46:15 CST 2006
+
+ - When we're being run from an uninstalled perl distribution
+ (e.g. one that's in the process of being built and tested), we
+ search for perl first in the current working directory. [Randy
+ Sims]
+
+ - More fixing of the arg_defines() method on VMS. [Craig A. Berry and
+ John E. Malmberg]
+
+0.16 Mon Mar 13 17:08:21 CST 2006
+
+ - Fix quoting of command line arguments on Windows. [Yitzchak
+ Scott-Thoennes]
+
+ - Provided a custom arg_defines() on VMS that does essentially the
+ same thing for /define that version 0.14 did for /include. [Craig
+ A. Berry]
+
+ - Documented the existing 'quiet' parameter, which silences the
+ printing of system() commands. [Suggested by Yitzchak
+ Scott-Thoennes]
+
+0.15 Mon Oct 3 17:10:32 CDT 2005
+
+ - Several OS/2 fixes have been made, including: 1) adding the
+ necessary version string to DLLs, 2) passing the executable's name
+ to 'ldopts' without the .exe extension, 3) avoiding calling 'env'
+ via the 'shrpenv' thingy, since it triggers a fork() bug. [Ilya
+ Zakharevich]
+
+ - Integrate a couple cleanup-related changes from bleadperl that
+ somehow never got into this copy. [Steve Hay]
+
+ - Added a new 'defines' parameter to compile(), which gives a
+ platform-independant way to specify various -Dfoo=bar (or the
+ equivalent) compiler defines. [Randy W. Sims]
+
+0.14 Mon Sep 19 13:40:37 CDT 2005
+
+ - Several fixes have been made for VMS, including: 1) there can only
+ be one /include qualifier, so merge multiple /includes into one; 2)
+ make sure the executable is named the same way that dynaloader will
+ look for it; 3) make sure the option files for the exported symbols
+ and the PERLSHR image are passed properly to the linker. [John
+ E. Malmberg]
+
+0.13 Wed Aug 24 20:05:59 CDT 2005
+
+ - Several temporary files weren't being cleaned up during testing,
+ because the 'cleanup' mechanism was never properly implemented.
+ This is now fixed. [Steve Hay]
+
+0.12 Mon May 30 16:40:10 CDT 2005
+
+ - In order to integrate into the perl core, patches were contributed
+ that a) put a $VERSION variable in each .pm file, b) add a 'quiet'
+ parameter to new() to shut up some of the command-echoing, c)
+ checks for the perl source headers in the CORE/ directory in the
+ perl source tree, not in the post-installation location, and d)
+ adjusts the CWD when running the regression tests under the perl
+ core. [Yitzchak Scott-Thoennes]
+
+ - Various parts of the code were looking for the CORE/ directory in
+ $Config{archlib}, $Config{installarchlib}, and $Config{archlibexp}.
+ Only the latter is correct, so we use that everywhere now.
+ [Curt Tilmes]
+
+ - For Unix-ish platforms, link_executable() will now prefer
+ $Config{cc} to $Config{ld}, because that typically works
+ better. [Jarkko Hietaniemi and H.Merijn Brand]
+
+ - Prelinking (invoking ExtUtils::Mksymlists to create options-files)
+ is now only done when we're building dynamic libraries. [Yitzchak
+ Scott-Thoennes]
+
+0.11 Tue Apr 5 20:58:41 CDT 2005
+
+ - Added a licensing statement to CBuilder.pm. [Spotted by Chip
+ Salzenberg]
+
+0.10 Mon Mar 14 20:18:19 CST 2005
+
+ - Split out a few simple routines that format how compile switches
+ are formatted, so that we can override them for platforms like VMS
+ where they're very different.
+
+ - Fix compile() and link() on VMS. [Help from Michael Schwern and
+ Peter Prymmer]
+
+0.09 Tue Feb 8 17:57:41 CST 2005
+
+ - Fixed a broken link_executable() method on cygwin - it now uses
+ 'gcc' instead of $Config{ld} for the linking, because the latter is
+ actually a shell script which calls a perl script which calls gcc
+ in a way that only works for creating shared libraries, not
+ executables.
+
+0.08 Tue Jan 18 21:54:11 CST 2005
+
+ - Fixed a testing error in which I had the prototype wrong for the
+ main() function. [Jose Pedro Oliveira]
+
+0.07 Wed Jan 12 21:50:34 CST 2005
+
+ - Added the link_executable() method, which provides the ability to
+ create standalone executables. This is NOT yet implemented on
+ Windows, and therefore the tests for it are skipped on Win32.
+ [Alberto Manuel Brandao Simoes]
+
+ - Integrated the latest split_like_shell() for Windows from
+ Module::Build (really need to find a better home for this code...),
+ which now does a much better job of handling quotes and backslashes
+ and so on. [Randy Sims]
+
+ - Fixed a couple of Windows problems related to the output-file name
+ in link(), and some clobbering of the 'include_dirs' parameter to
+ compile(). [Randy Sims]
+
+0.06 Mon Dec 27 22:51:36 CST 2004
+
+ - Fixed a bug on Unix environments in which our work-around for
+ shell-commands like "FOO=BAR cc" (which is supposed to be turned
+ into "env FOO=BAR cc" to actually work) wasn't being called.
+
+0.05 Wed Oct 13 23:09:09 CDT 2004
+
+ - Fixed a bug in split_like_shell() in which leading whitespace was
+ creating an empty word, manifesting as something like "gcc - no
+ such file or directory" during tests. [Spotted by Warren L. Dodge]
+
+ - Incorporate another split_like_shell() fix from Module::Build.
+
+0.04 Sun Oct 10 00:31:08 CDT 2004
+
+ - Changed the split_like_shell() method to use the shellwords()
+ function from Text::ParseWords (a core module since 5.0), which
+ does a much better job than the split() we were using.
+
+
+0.03 Fri May 14 23:12:23 CDT 2004
+
+ - Fixed minor problems with the Build.PL file, the module names
+ should be quoted.
+
+ - The VMS module declared itself with the wrong package name.
+
+
+0.02 Fri Feb 20 10:17:40 CST 2004
+
+ - Fixed a bug in .../Platform/Windows.pm, in which compile() was
+ ignoring an 'include_dirs' argument. [Randy Sims]
+
+ - Fixed a bug in .../Platform/Windows.pm, in which output files were
+ being created in the root directory \ when they should be created
+ in the current directory. [Randy Sims]
+
+
+0.01 Mon Jan 12 08:12:35 CST 2004
+
+ - Original release, taken from Module::Build's C-building code, with
+ patching help from Randy Sims.
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder.pm
new file mode 100644
index 0000000000..e93e4f3469
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder.pm
@@ -0,0 +1,331 @@
+package ExtUtils::CBuilder;
+
+use File::Spec ();
+use File::Path ();
+use File::Basename ();
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+$VERSION = eval $VERSION;
+
+# Okay, this is the brute-force method of finding out what kind of
+# platform we're on. I don't know of a systematic way. These values
+# came from the latest (bleadperl) perlport.pod.
+
+my %OSTYPES = qw(
+ aix Unix
+ bsdos Unix
+ dgux Unix
+ dynixptx Unix
+ freebsd Unix
+ linux Unix
+ hpux Unix
+ irix Unix
+ darwin Unix
+ machten Unix
+ next Unix
+ openbsd Unix
+ netbsd Unix
+ dec_osf Unix
+ svr4 Unix
+ svr5 Unix
+ sco_sv Unix
+ unicos Unix
+ unicosmk Unix
+ solaris Unix
+ sunos Unix
+ cygwin Unix
+ os2 Unix
+ gnu Unix
+ gnukfreebsd Unix
+ haiku Unix
+
+ dos Windows
+ MSWin32 Windows
+
+ os390 EBCDIC
+ os400 EBCDIC
+ posix-bc EBCDIC
+ vmesa EBCDIC
+
+ MacOS MacOS
+ VMS VMS
+ VOS VOS
+ riscos RiscOS
+ amigaos Amiga
+ mpeix MPEiX
+ );
+
+# We only use this once - don't waste a symbol table entry on it.
+# More importantly, don't make it an inheritable method.
+my $load = sub {
+ my $mod = shift;
+ eval "use $mod";
+ die $@ if $@;
+ @ISA = ($mod);
+};
+
+{
+ my @package = split /::/, __PACKAGE__;
+
+ if (grep {-e File::Spec->catfile($_, @package, 'Platform', $^O) . '.pm'} @INC) {
+ $load->(__PACKAGE__ . "::Platform::$^O");
+
+ } elsif (exists $OSTYPES{$^O} and
+ grep {-e File::Spec->catfile($_, @package, 'Platform', $OSTYPES{$^O}) . '.pm'} @INC) {
+ $load->(__PACKAGE__ . "::Platform::$OSTYPES{$^O}");
+
+ } else {
+ $load->(__PACKAGE__ . "::Base");
+ }
+}
+
+sub os_type { $OSTYPES{$^O} }
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::CBuilder - Compile and link C code for Perl modules
+
+=head1 SYNOPSIS
+
+ use ExtUtils::CBuilder;
+
+ my $b = ExtUtils::CBuilder->new(%options);
+ $obj_file = $b->compile(source => 'MyModule.c');
+ $lib_file = $b->link(objects => $obj_file);
+
+=head1 DESCRIPTION
+
+This module can build the C portions of Perl modules by invoking the
+appropriate compilers and linkers in a cross-platform manner. It was
+motivated by the C<Module::Build> project, but may be useful for other
+purposes as well. However, it is I<not> intended as a general
+cross-platform interface to all your C building needs. That would
+have been a much more ambitious goal!
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+Returns a new C<ExtUtils::CBuilder> object. A C<config> parameter
+lets you override C<Config.pm> settings for all operations performed
+by the object, as in the following example:
+
+ # Use a different compiler than Config.pm says
+ my $b = ExtUtils::CBuilder->new( config =>
+ { ld => 'gcc' } );
+
+A C<quiet> parameter tells C<CBuilder> to not print its C<system()>
+commands before executing them:
+
+ # Be quieter than normal
+ my $b = ExtUtils::CBuilder->new( quiet => 1 );
+
+=item have_compiler
+
+Returns true if the current system has a working C compiler and
+linker, false otherwise. To determine this, we actually compile and
+link a sample C library. The sample will be compiled in the system
+tempdir or, if that fails for some reason, in the current directory.
+
+=item have_cplusplus
+
+Just like have_compiler but for C++ instead of C.
+
+=item compile
+
+Compiles a C source file and produces an object file. The name of the
+object file is returned. The source file is specified in a C<source>
+parameter, which is required; the other parameters listed below are
+optional.
+
+=over 4
+
+=item C<object_file>
+
+Specifies the name of the output file to create. Otherwise the
+C<object_file()> method will be consulted, passing it the name of the
+C<source> file.
+
+=item C<include_dirs>
+
+Specifies any additional directories in which to search for header
+files. May be given as a string indicating a single directory, or as
+a list reference indicating multiple directories.
+
+=item C<extra_compiler_flags>
+
+Specifies any additional arguments to pass to the compiler. Should be
+given as a list reference containing the arguments individually, or if
+this is not possible, as a string containing all the arguments
+together.
+
+=item C<C++>
+
+Specifies that the source file is a C++ source file and sets appropriate
+compiler flags
+
+=back
+
+The operation of this method is also affected by the
+C<archlibexp>, C<cccdlflags>, C<ccflags>, C<optimize>, and C<cc>
+entries in C<Config.pm>.
+
+=item link
+
+Invokes the linker to produce a library file from object files. In
+scalar context, the name of the library file is returned. In list
+context, the library file and any temporary files created are
+returned. A required C<objects> parameter contains the name of the
+object files to process, either in a string (for one object file) or
+list reference (for one or more files). The following parameters are
+optional:
+
+
+=over 4
+
+=item lib_file
+
+Specifies the name of the output library file to create. Otherwise
+the C<lib_file()> method will be consulted, passing it the name of
+the first entry in C<objects>.
+
+=item module_name
+
+Specifies the name of the Perl module that will be created by linking.
+On platforms that need to do prelinking (Win32, OS/2, etc.) this is a
+required parameter.
+
+=item extra_linker_flags
+
+Any additional flags you wish to pass to the linker.
+
+=back
+
+On platforms where C<need_prelink()> returns true, C<prelink()>
+will be called automatically.
+
+The operation of this method is also affected by the C<lddlflags>,
+C<shrpenv>, and C<ld> entries in C<Config.pm>.
+
+=item link_executable
+
+Invokes the linker to produce an executable file from object files. In
+scalar context, the name of the executable file is returned. In list
+context, the executable file and any temporary files created are
+returned. A required C<objects> parameter contains the name of the
+object files to process, either in a string (for one object file) or
+list reference (for one or more files). The optional parameters are
+the same as C<link> with exception for
+
+
+=over 4
+
+=item exe_file
+
+Specifies the name of the output executable file to create. Otherwise
+the C<exe_file()> method will be consulted, passing it the name of the
+first entry in C<objects>.
+
+=back
+
+=item object_file
+
+ my $object_file = $b->object_file($source_file);
+
+Converts the name of a C source file to the most natural name of an
+output object file to create from it. For instance, on Unix the
+source file F<foo.c> would result in the object file F<foo.o>.
+
+=item lib_file
+
+ my $lib_file = $b->lib_file($object_file);
+
+Converts the name of an object file to the most natural name of a
+output library file to create from it. For instance, on Mac OS X the
+object file F<foo.o> would result in the library file F<foo.bundle>.
+
+=item exe_file
+
+ my $exe_file = $b->exe_file($object_file);
+
+Converts the name of an object file to the most natural name of an
+executable file to create from it. For instance, on Mac OS X the
+object file F<foo.o> would result in the executable file F<foo>, and
+on Windows it would result in F<foo.exe>.
+
+
+=item prelink
+
+On certain platforms like Win32, OS/2, VMS, and AIX, it is necessary
+to perform some actions before invoking the linker. The
+C<ExtUtils::Mksymlists> module does this, writing files used by the
+linker during the creation of shared libraries for dynamic extensions.
+The names of any files written will be returned as a list.
+
+Several parameters correspond to C<ExtUtils::Mksymlists::Mksymlists()>
+options, as follows:
+
+ Mksymlists() prelink() type
+ -------------|-------------------|-------------------
+ NAME | dl_name | string (required)
+ DLBASE | dl_base | string
+ FILE | dl_file | string
+ DL_VARS | dl_vars | array reference
+ DL_FUNCS | dl_funcs | hash reference
+ FUNCLIST | dl_func_list | array reference
+ IMPORTS | dl_imports | hash reference
+ VERSION | dl_version | string
+
+Please see the documentation for C<ExtUtils::Mksymlists> for the
+details of what these parameters do.
+
+=item need_prelink
+
+Returns true on platforms where C<prelink()> should be called
+during linking, and false otherwise.
+
+=item extra_link_args_after_prelink
+
+Returns list of extra arguments to give to the link command; the arguments
+are the same as for prelink(), with addition of array reference to the
+results of prelink(); this reference is indexed by key C<prelink_res>.
+
+=back
+
+=head1 TO DO
+
+Currently this has only been tested on Unix and doesn't contain any of
+the Windows-specific code from the C<Module::Build> project. I'll do
+that next.
+
+=head1 HISTORY
+
+This module is an outgrowth of the C<Module::Build> project, to which
+there have been many contributors. Notably, Randy W. Sims submitted
+lots of code to support 3 compilers on Windows and helped with various
+other platform-specific issues. Ilya Zakharevich has contributed
+fixes for OS/2; John E. Malmberg and Peter Prymmer have done likewise
+for VMS.
+
+=head1 AUTHOR
+
+Ken Williams, kwilliams@cpan.org
+
+=head1 COPYRIGHT
+
+Copyright (c) 2003-2005 Ken Williams. All rights reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+perl(1), Module::Build(3)
+
+=cut
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Base.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Base.pm
new file mode 100644
index 0000000000..3249032e4a
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Base.pm
@@ -0,0 +1,383 @@
+package ExtUtils::CBuilder::Base;
+
+use strict;
+use File::Spec;
+use File::Basename;
+use Cwd ();
+use Config;
+use Text::ParseWords;
+use IO::File;
+use Data::Dumper;$Data::Dumper::Indent=1;
+use IPC::Cmd qw(can_run);
+use File::Temp qw(tempfile);
+
+use vars qw($VERSION);
+$VERSION = '0.2802';
+
+# More details about C/C++ compilers:
+# http://developers.sun.com/sunstudio/documentation/product/compiler.jsp
+# http://gcc.gnu.org/
+# http://publib.boulder.ibm.com/infocenter/comphelp/v101v121/index.jsp
+# http://msdn.microsoft.com/en-us/vstudio/default.aspx
+
+my %cc2cxx = (
+ # first line order is important to support wrappers like in pkgsrc
+ cc => [ 'c++', 'CC', 'aCC', 'cxx', ], # Sun Studio, HP ANSI C/C++ Compilers
+ gcc => [ 'g++' ], # GNU Compiler Collection
+ xlc => [ 'xlC' ], # IBM C/C++ Set, xlc without thread-safety
+ xlc_r => [ 'xlC_r' ], # IBM C/C++ Set, xlc with thread-safety
+ cl => [ 'cl' ], # Microsoft Visual Studio
+);
+
+sub new {
+ my $class = shift;
+ my $self = bless {@_}, $class;
+
+ $self->{properties}{perl} = $class->find_perl_interpreter
+ or warn "Warning: Can't locate your perl binary";
+
+ while (my ($k,$v) = each %Config) {
+ $self->{config}{$k} = $v unless exists $self->{config}{$k};
+ }
+ $self->{config}{cc} = $ENV{CC} if defined $ENV{CC};
+ $self->{config}{ccflags} = $ENV{CFLAGS} if defined $ENV{CFLAGS};
+ $self->{config}{cxx} = $ENV{CXX} if defined $ENV{CXX};
+ $self->{config}{cxxflags} = $ENV{CXXFLAGS} if defined $ENV{CXXFLAGS};
+ $self->{config}{ld} = $ENV{LD} if defined $ENV{LD};
+ $self->{config}{ldflags} = $ENV{LDFLAGS} if defined $ENV{LDFLAGS};
+
+ unless ( exists $self->{config}{cxx} ) {
+ my ($ccpath, $ccbase, $ccsfx ) = fileparse($self->{config}{cc}, qr/\.[^.]*/);
+ foreach my $cxx (@{$cc2cxx{$ccbase}}) {
+ if( can_run( File::Spec->catfile( $ccpath, $cxx, $ccsfx ) ) ) {
+ $self->{config}{cxx} = File::Spec->catfile( $ccpath, $cxx, $ccsfx );
+ last;
+ }
+ if( can_run( File::Spec->catfile( $cxx, $ccsfx ) ) ) {
+ $self->{config}{cxx} = File::Spec->catfile( $cxx, $ccsfx );
+ last;
+ }
+ if( can_run( $cxx ) ) {
+ $self->{config}{cxx} = $cxx;
+ last;
+ }
+ }
+ unless ( exists $self->{config}{cxx} ) {
+ $self->{config}{cxx} = $self->{config}{cc};
+ my $cflags = $self->{config}{cflags};
+ $self->{config}{cxxflags} = '-x c++';
+ $self->{config}{cxxflags} .= " $cflags" if defined $cflags;
+ }
+ }
+
+ return $self;
+}
+
+sub find_perl_interpreter {
+ my $perl;
+ File::Spec->file_name_is_absolute($perl = $^X)
+ or -f ($perl = $Config::Config{perlpath})
+ or ($perl = $^X); # XXX how about using IPC::Cmd::can_run here?
+ return $perl;
+}
+
+sub add_to_cleanup {
+ my $self = shift;
+ foreach (@_) {
+ $self->{files_to_clean}{$_} = 1;
+ }
+}
+
+sub cleanup {
+ my $self = shift;
+ foreach my $file (keys %{$self->{files_to_clean}}) {
+ unlink $file;
+ }
+}
+
+sub get_config {
+ return %{ $_[0]->{config} };
+}
+
+sub object_file {
+ my ($self, $filename) = @_;
+
+ # File name, minus the suffix
+ (my $file_base = $filename) =~ s/\.[^.]+$//;
+ return "$file_base$self->{config}{obj_ext}";
+}
+
+sub arg_include_dirs {
+ my $self = shift;
+ return map {"-I$_"} @_;
+}
+
+sub arg_nolink { '-c' }
+
+sub arg_object_file {
+ my ($self, $file) = @_;
+ return ('-o', $file);
+}
+
+sub arg_share_object_file {
+ my ($self, $file) = @_;
+ return ($self->split_like_shell($self->{config}{lddlflags}), '-o', $file);
+}
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return ('-o', $file);
+}
+
+sub arg_defines {
+ my ($self, %args) = @_;
+ return map "-D$_=$args{$_}", keys %args;
+}
+
+sub compile {
+ my ($self, %args) = @_;
+ die "Missing 'source' argument to compile()" unless defined $args{source};
+
+ my $cf = $self->{config}; # For convenience
+
+ my $object_file = $args{object_file}
+ ? $args{object_file}
+ : $self->object_file($args{source});
+
+ my $include_dirs_ref =
+ (exists($args{include_dirs}) && ref($args{include_dirs}) ne "ARRAY")
+ ? [ $args{include_dirs} ]
+ : $args{include_dirs};
+ my @include_dirs = $self->arg_include_dirs(
+ @{ $include_dirs_ref || [] },
+ $self->perl_inc(),
+ );
+
+ my @defines = $self->arg_defines( %{$args{defines} || {}} );
+
+ my @extra_compiler_flags =
+ $self->split_like_shell($args{extra_compiler_flags});
+ my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
+ my @ccflags = $self->split_like_shell($args{'C++'} ? $cf->{cxxflags} : $cf->{ccflags});
+ my @optimize = $self->split_like_shell($cf->{optimize});
+ my @flags = (
+ @include_dirs,
+ @defines,
+ @cccdlflags,
+ @extra_compiler_flags,
+ $self->arg_nolink,
+ @ccflags,
+ @optimize,
+ $self->arg_object_file($object_file),
+ );
+ my @cc = $self->split_like_shell($args{'C++'} ? $cf->{cxx} : $cf->{cc});
+
+ $self->do_system(@cc, @flags, $args{source})
+ or die "error building $object_file from '$args{source}'";
+
+ return $object_file;
+}
+
+sub have_compiler {
+ my ($self, $is_cplusplus) = @_;
+ my $have_compiler_flag = $is_cplusplus ? "have_cxx" : "have_cc";
+ my $suffix = $is_cplusplus ? ".cc" : ".c";
+ return $self->{$have_compiler_flag} if defined $self->{$have_compiler_flag};
+
+ my $result;
+ my $attempts = 3;
+ # tmpdir has issues for some people so fall back to current dir
+
+ # don't clobber existing files (rare, but possible)
+ my ( $FH, $tmpfile ) = tempfile( "compilet-XXXXX", SUFFIX => $suffix );
+ binmode $FH;
+
+ if ( $is_cplusplus ) {
+ print $FH "class Bogus { public: int boot_compilet() { return 1; } };\n";
+ }
+ else {
+ print $FH "int boot_compilet() { return 1; }\n";
+ }
+ close $FH;
+
+ my ($obj_file, @lib_files);
+ eval {
+ local $^W = 0;
+ local $self->{quiet} = 1;
+ $obj_file = $self->compile('C++' => $is_cplusplus, source => $tmpfile);
+ @lib_files = $self->link(objects => $obj_file, module_name => 'compilet');
+ };
+ $result = $@ ? 0 : 1;
+
+ foreach (grep defined, $tmpfile, $obj_file, @lib_files) {
+ 1 while unlink;
+ }
+
+ return $self->{$have_compiler_flag} = $result;
+}
+
+sub have_cplusplus {
+ push @_, 1;
+ goto &have_compiler;
+}
+
+sub lib_file {
+ my ($self, $dl_file) = @_;
+ $dl_file =~ s/\.[^.]+$//;
+ $dl_file =~ tr/"//d;
+ return "$dl_file.$self->{config}{dlext}";
+}
+
+
+sub exe_file {
+ my ($self, $dl_file) = @_;
+ $dl_file =~ s/\.[^.]+$//;
+ $dl_file =~ tr/"//d;
+ return "$dl_file$self->{config}{_exe}";
+}
+
+sub need_prelink { 0 }
+
+sub extra_link_args_after_prelink { return }
+
+sub prelink {
+ my ($self, %args) = @_;
+
+ my ($dl_file_out, $mksymlists_args) = _prepare_mksymlists_args(\%args);
+
+ require ExtUtils::Mksymlists;
+ # dl. abbrev for dynamic library
+ ExtUtils::Mksymlists::Mksymlists( %{ $mksymlists_args } );
+
+ # Mksymlists will create one of these files
+ return grep -e, map "$dl_file_out.$_", qw(ext def opt);
+}
+
+sub _prepare_mksymlists_args {
+ my $args = shift;
+ ($args->{dl_file} = $args->{dl_name}) =~ s/.*::// unless $args->{dl_file};
+
+ my %mksymlists_args = (
+ DL_VARS => $args->{dl_vars} || [],
+ DL_FUNCS => $args->{dl_funcs} || {},
+ FUNCLIST => $args->{dl_func_list} || [],
+ IMPORTS => $args->{dl_imports} || {},
+ NAME => $args->{dl_name}, # Name of the Perl module
+ DLBASE => $args->{dl_base}, # Basename of DLL file
+ FILE => $args->{dl_file}, # Dir + Basename of symlist file
+ VERSION => (defined $args->{dl_version} ? $args->{dl_version} : '0.0'),
+ );
+ return ($args->{dl_file}, \%mksymlists_args);
+}
+
+sub link {
+ my ($self, %args) = @_;
+ return $self->_do_link('lib_file', lddl => 1, %args);
+}
+
+sub link_executable {
+ my ($self, %args) = @_;
+ return $self->_do_link('exe_file', lddl => 0, %args);
+}
+
+sub _do_link {
+ my ($self, $type, %args) = @_;
+
+ my $cf = $self->{config}; # For convenience
+
+ my $objects = delete $args{objects};
+ $objects = [$objects] unless ref $objects;
+ my $out = $args{$type} || $self->$type($objects->[0]);
+
+ my @temp_files;
+ @temp_files =
+ $self->prelink(%args, dl_name => $args{module_name})
+ if $args{lddl} && $self->need_prelink;
+
+ my @linker_flags = (
+ $self->split_like_shell($args{extra_linker_flags}),
+ $self->extra_link_args_after_prelink(
+ %args, dl_name => $args{module_name}, prelink_res => \@temp_files
+ )
+ );
+
+ my @output = $args{lddl}
+ ? $self->arg_share_object_file($out)
+ : $self->arg_exec_file($out);
+ my @shrp = $self->split_like_shell($cf->{shrpenv});
+ my @ld = $self->split_like_shell($cf->{ld});
+
+ $self->do_system(@shrp, @ld, @output, @$objects, @linker_flags)
+ or die "error building $out from @$objects";
+
+ return wantarray ? ($out, @temp_files) : $out;
+}
+
+
+sub do_system {
+ my ($self, @cmd) = @_;
+ print "@cmd\n" if !$self->{quiet};
+ return !system(@cmd);
+}
+
+sub split_like_shell {
+ my ($self, $string) = @_;
+
+ return () unless defined($string);
+ return @$string if UNIVERSAL::isa($string, 'ARRAY');
+ $string =~ s/^\s+|\s+$//g;
+ return () unless length($string);
+
+ # Text::ParseWords replaces all 'escaped' characters with themselves, which completely
+ # breaks paths under windows. As such, we forcibly replace backwards slashes with forward
+ # slashes on windows.
+ $string =~ s@\\@/@g if $^O eq 'MSWin32';
+
+ return Text::ParseWords::shellwords($string);
+}
+
+# if building perl, perl's main source directory
+sub perl_src {
+ # N.B. makemaker actually searches regardless of PERL_CORE, but
+ # only squawks at not finding it if PERL_CORE is set
+
+ return unless $ENV{PERL_CORE};
+
+ my $Updir = File::Spec->updir;
+ my $dir = File::Spec->curdir;
+
+ # Try up to 5 levels upwards
+ for (0..10) {
+ if (
+ -f File::Spec->catfile($dir,"config_h.SH")
+ &&
+ -f File::Spec->catfile($dir,"perl.h")
+ &&
+ -f File::Spec->catfile($dir,"lib","Exporter.pm")
+ ) {
+ return Cwd::realpath( $dir );
+ }
+
+ $dir = File::Spec->catdir($dir, $Updir);
+ }
+
+ warn "PERL_CORE is set but I can't find your perl source!\n";
+ return ''; # return empty string if $ENV{PERL_CORE} but can't find dir ???
+}
+
+# directory of perl's include files
+sub perl_inc {
+ my $self = shift;
+
+ $self->perl_src() || File::Spec->catdir($self->{config}{archlibexp},"CORE");
+}
+
+sub DESTROY {
+ my $self = shift;
+ local($., $@, $!, $^E, $?);
+ $self->cleanup();
+}
+
+1;
+
+# vim: ts=2 sw=2 et:
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Unix.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Unix.pm
new file mode 100644
index 0000000000..4bddff1e7f
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Unix.pm
@@ -0,0 +1,40 @@
+package ExtUtils::CBuilder::Platform::Unix;
+
+use strict;
+use ExtUtils::CBuilder::Base;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Base);
+
+sub link_executable {
+ my $self = shift;
+
+ # On some platforms (which ones??) $Config{cc} seems to be a better
+ # bet for linking executables than $Config{ld}. Cygwin is a notable
+ # exception.
+ local $self->{config}{ld} =
+ $self->{config}{cc} . " " . $self->{config}{ldflags};
+ return $self->SUPER::link_executable(@_);
+}
+
+sub link {
+ my $self = shift;
+ my $cf = $self->{config};
+
+ # Some platforms (notably Mac OS X 10.3, but some others too) expect
+ # the syntax "FOO=BAR /bin/command arg arg" to work in %Config
+ # (notably $Config{ld}). It usually works in system(SCALAR), but we
+ # use system(LIST). We fix it up here with 'env'.
+
+ local $cf->{ld} = $cf->{ld};
+ if (ref $cf->{ld}) {
+ unshift @{$cf->{ld}}, 'env' if $cf->{ld}[0] =~ /^\s*\w+=/;
+ } else {
+ $cf->{ld} =~ s/^(\s*\w+=)/env $1/;
+ }
+
+ return $self->SUPER::link(@_);
+}
+
+1;
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/VMS.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/VMS.pm
new file mode 100644
index 0000000000..c9ad1d9c00
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/VMS.pm
@@ -0,0 +1,294 @@
+package ExtUtils::CBuilder::Platform::VMS;
+
+use strict;
+use ExtUtils::CBuilder::Base;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Base);
+
+use File::Spec::Functions qw(catfile catdir);
+
+# We do prelink, but don't want the parent to redo it.
+
+sub need_prelink { 0 }
+
+sub arg_defines {
+ my ($self, %args) = @_;
+
+ s/"/""/g foreach values %args;
+
+ my @config_defines;
+
+ # VMS can only have one define qualifier; add the one from config, if any.
+ if ($self->{config}{ccflags} =~ s{/ def[^=]+ =+ \(? ([^\/\)]*) } {}ix) {
+ push @config_defines, $1;
+ }
+
+ return '' unless keys(%args) || @config_defines;
+
+ return ('/define=('
+ . join(',',
+ @config_defines,
+ map "\"$_" . ( length($args{$_}) ? "=$args{$_}" : '') . "\"",
+ keys %args)
+ . ')');
+}
+
+sub arg_include_dirs {
+ my ($self, @dirs) = @_;
+
+ # VMS can only have one include list, add the one from config.
+ if ($self->{config}{ccflags} =~ s{/inc[^=]+(?:=)+(?:\()?([^\/\)]*)} {}i) {
+ unshift @dirs, $1;
+ }
+ return unless @dirs;
+
+ return ('/include=(' . join(',', @dirs) . ')');
+}
+
+sub _do_link {
+ my ($self, $type, %args) = @_;
+
+ my $objects = delete $args{objects};
+ $objects = [$objects] unless ref $objects;
+
+ if ($args{lddl}) {
+
+ # prelink will call Mksymlists, which creates the extension-specific
+ # linker options file and populates it with the boot symbol.
+
+ my @temp_files = $self->prelink(%args, dl_name => $args{module_name});
+
+ # We now add the rest of what we need to the linker options file. We
+ # should replicate the functionality of C<ExtUtils::MM_VMS::dlsyms>,
+ # but there is as yet no infrastructure for handling object libraries,
+ # so for now we depend on object files being listed individually on the
+ # command line, which should work for simple cases. We do bring in our
+ # own version of C<ExtUtils::Liblist::Kid::ext> so that any additional
+ # libraries (including PERLSHR) can be added to the options file.
+
+ my @optlibs = $self->_liblist_ext( $args{'libs'} );
+
+ my $optfile = 'sys$disk:[]' . $temp_files[0];
+ open my $opt_fh, '>>', $optfile
+ or die "_do_link: Unable to open $optfile: $!";
+ for my $lib (@optlibs) {print $opt_fh "$lib\n" if length $lib }
+ close $opt_fh;
+
+ $objects->[-1] .= ',';
+ push @$objects, $optfile . '/OPTIONS,';
+
+ # This one not needed for DEC C, but leave for completeness.
+ push @$objects, $self->perl_inc() . 'perlshr_attr.opt/OPTIONS';
+ }
+
+ return $self->SUPER::_do_link($type, %args, objects => $objects);
+}
+
+sub arg_nolink { return; }
+
+sub arg_object_file {
+ my ($self, $file) = @_;
+ return "/obj=$file";
+}
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return ("/exe=$file");
+}
+
+sub arg_share_object_file {
+ my ($self, $file) = @_;
+ return ("$self->{config}{lddlflags}=$file");
+}
+
+
+sub lib_file {
+ my ($self, $dl_file) = @_;
+ $dl_file =~ s/\.[^.]+$//;
+ $dl_file =~ tr/"//d;
+ $dl_file = $dl_file .= '.' . $self->{config}{dlext};
+
+ # Need to create with the same name as DynaLoader will load with.
+ if (defined &DynaLoader::mod2fname) {
+ my ($dev,$dir,$file) = File::Spec->splitpath($dl_file);
+ $file = DynaLoader::mod2fname([$file]);
+ $dl_file = File::Spec->catpath($dev,$dir,$file);
+ }
+ return $dl_file;
+}
+
+# The following is reproduced almost verbatim from ExtUtils::Liblist::Kid::_vms_ext.
+# We can't just call that because it's tied up with the MakeMaker object hierarchy.
+
+sub _liblist_ext {
+ my($self, $potential_libs,$verbose,$give_libs) = @_;
+ $verbose ||= 0;
+
+ my(@crtls,$crtlstr);
+ @crtls = ( ($self->{'config'}{'ldflags'} =~ m-/Debug-i ? $self->{'config'}{'dbgprefix'} : '')
+ . 'PerlShr/Share' );
+ push(@crtls, grep { not /\(/ } split /\s+/, $self->{'config'}{'perllibs'});
+ push(@crtls, grep { not /\(/ } split /\s+/, $self->{'config'}{'libc'});
+ # In general, we pass through the basic libraries from %Config unchanged.
+ # The one exception is that if we're building in the Perl source tree, and
+ # a library spec could be resolved via a logical name, we go to some trouble
+ # to ensure that the copy in the local tree is used, rather than one to
+ # which a system-wide logical may point.
+ if ($self->perl_src) {
+ my($lib,$locspec,$type);
+ foreach $lib (@crtls) {
+ if (($locspec,$type) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i) {
+ if (lc $type eq '/share') { $locspec .= $self->{'config'}{'exe_ext'}; }
+ elsif (lc $type eq '/library') { $locspec .= $self->{'config'}{'lib_ext'}; }
+ else { $locspec .= $self->{'config'}{'obj_ext'}; }
+ $locspec = catfile($self->perl_src, $locspec);
+ $lib = "$locspec$type" if -e $locspec;
+ }
+ }
+ }
+ $crtlstr = @crtls ? join(' ',@crtls) : '';
+
+ unless ($potential_libs) {
+ warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose;
+ return ('', '', $crtlstr, '', ($give_libs ? [] : ()));
+ }
+
+ my(@dirs,@libs,$dir,$lib,%found,@fndlibs,$ldlib);
+ my $cwd = cwd();
+ my($so,$lib_ext,$obj_ext) = @{$self->{'config'}}{'so','lib_ext','obj_ext'};
+ # List of common Unix library names and their VMS equivalents
+ # (VMS equivalent of '' indicates that the library is automatically
+ # searched by the linker, and should be skipped here.)
+ my(@flibs, %libs_seen);
+ my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '',
+ 'malloc' => '', 'crypt' => '', 'resolv' => '', 'c_s' => '',
+ 'socket' => '', 'X11' => 'DECW$XLIBSHR',
+ 'Xt' => 'DECW$XTSHR', 'Xm' => 'DECW$XMLIBSHR',
+ 'Xmu' => 'DECW$XMULIBSHR');
+ if ($self->{'config'}{'vms_cc_type'} ne 'decc') { $libmap{'curses'} = 'VAXCCURSE'; }
+
+ warn "Potential libraries are '$potential_libs'\n" if $verbose;
+
+ # First, sort out directories and library names in the input
+ foreach $lib (split ' ',$potential_libs) {
+ push(@dirs,$1), next if $lib =~ /^-L(.*)/;
+ push(@dirs,$lib), next if $lib =~ /[:>\]]$/;
+ push(@dirs,$lib), next if -d $lib;
+ push(@libs,$1), next if $lib =~ /^-l(.*)/;
+ push(@libs,$lib);
+ }
+ push(@dirs,split(' ',$self->{'config'}{'libpth'}));
+
+ # Now make sure we've got VMS-syntax absolute directory specs
+ # (We don't, however, check whether someone's hidden a relative
+ # path in a logical name.)
+ foreach $dir (@dirs) {
+ unless (-d $dir) {
+ warn "Skipping nonexistent Directory $dir\n" if $verbose > 1;
+ $dir = '';
+ next;
+ }
+ warn "Resolving directory $dir\n" if $verbose;
+ if (!File::Spec->file_name_is_absolute($dir)) {
+ $dir = catdir($cwd,$dir);
+ }
+ }
+ @dirs = grep { length($_) } @dirs;
+ unshift(@dirs,''); # Check each $lib without additions first
+
+ LIB: foreach $lib (@libs) {
+ if (exists $libmap{$lib}) {
+ next unless length $libmap{$lib};
+ $lib = $libmap{$lib};
+ }
+
+ my(@variants,$variant,$cand);
+ my($ctype) = '';
+
+ # If we don't have a file type, consider it a possibly abbreviated name and
+ # check for common variants. We try these first to grab libraries before
+ # a like-named executable image (e.g. -lperl resolves to perlshr.exe
+ # before perl.exe).
+ if ($lib !~ /\.[^:>\]]*$/) {
+ push(@variants,"${lib}shr","${lib}rtl","${lib}lib");
+ push(@variants,"lib$lib") if $lib !~ /[:>\]]/;
+ }
+ push(@variants,$lib);
+ warn "Looking for $lib\n" if $verbose;
+ foreach $variant (@variants) {
+ my($fullname, $name);
+
+ foreach $dir (@dirs) {
+ my($type);
+
+ $name = "$dir$variant";
+ warn "\tChecking $name\n" if $verbose > 2;
+ $fullname = VMS::Filespec::rmsexpand($name);
+ if (defined $fullname and -f $fullname) {
+ # It's got its own suffix, so we'll have to figure out the type
+ if ($fullname =~ /(?:$so|exe)$/i) { $type = 'SHR'; }
+ elsif ($fullname =~ /(?:$lib_ext|olb)$/i) { $type = 'OLB'; }
+ elsif ($fullname =~ /(?:$obj_ext|obj)$/i) {
+ warn "Note (probably harmless): "
+ ."Plain object file $fullname found in library list\n";
+ $type = 'OBJ';
+ }
+ else {
+ warn "Note (probably harmless): "
+ ."Unknown library type for $fullname; assuming shared\n";
+ $type = 'SHR';
+ }
+ }
+ elsif (-f ($fullname = VMS::Filespec::rmsexpand($name,$so)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.exe'))) {
+ $type = 'SHR';
+ $name = $fullname unless $fullname =~ /exe;?\d*$/i;
+ }
+ elsif (not length($ctype) and # If we've got a lib already,
+ # don't bother
+ ( -f ($fullname = VMS::Filespec::rmsexpand($name,$lib_ext)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.olb')))) {
+ $type = 'OLB';
+ $name = $fullname unless $fullname =~ /olb;?\d*$/i;
+ }
+ elsif (not length($ctype) and # If we've got a lib already,
+ # don't bother
+ ( -f ($fullname = VMS::Filespec::rmsexpand($name,$obj_ext)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.obj')))) {
+ warn "Note (probably harmless): "
+ ."Plain object file $fullname found in library list\n";
+ $type = 'OBJ';
+ $name = $fullname unless $fullname =~ /obj;?\d*$/i;
+ }
+ if (defined $type) {
+ $ctype = $type; $cand = $name;
+ last if $ctype eq 'SHR';
+ }
+ }
+ if ($ctype) {
+ # This has to precede any other CRTLs, so just make it first
+ if ($cand eq 'VAXCCURSE') { unshift @{$found{$ctype}}, $cand; }
+ else { push @{$found{$ctype}}, $cand; }
+ warn "\tFound as $cand (really $fullname), type $ctype\n"
+ if $verbose > 1;
+ push @flibs, $name unless $libs_seen{$fullname}++;
+ next LIB;
+ }
+ }
+ warn "Note (probably harmless): "
+ ."No library found for $lib\n";
+ }
+
+ push @fndlibs, @{$found{OBJ}} if exists $found{OBJ};
+ push @fndlibs, map { "$_/Library" } @{$found{OLB}} if exists $found{OLB};
+ push @fndlibs, map { "$_/Share" } @{$found{SHR}} if exists $found{SHR};
+ $lib = join(' ',@fndlibs);
+
+ $ldlib = $crtlstr ? "$lib $crtlstr" : $lib;
+ warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose;
+ wantarray ? ($lib, '', $ldlib, '', ($give_libs ? \@flibs : ())) : $lib;
+}
+
+1;
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows.pm
new file mode 100644
index 0000000000..0fdd37097b
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows.pm
@@ -0,0 +1,291 @@
+package ExtUtils::CBuilder::Platform::Windows;
+
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+
+use ExtUtils::CBuilder::Base;
+use IO::File;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Base);
+
+=begin comment
+
+The compiler-specific packages implement functions for generating properly
+formatted commandlines for the compiler being used. Each package
+defines two primary functions 'format_linker_cmd()' &
+'format_compiler_cmd()' that accepts a list of named arguments (a
+hash) and returns a list of formatted options suitable for invoking the
+compiler. By default, if the compiler supports scripting of its
+operation then a script file is built containing the options while
+those options are removed from the commandline, and a reference to the
+script is pushed onto the commandline in their place. Scripting the
+compiler in this way helps to avoid the problems associated with long
+commandlines under some shells.
+
+=end comment
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ my $cf = $self->{config};
+
+ # Inherit from an appropriate compiler driver class
+ my $driver = "ExtUtils::CBuilder::Platform::Windows::" . $self->_compiler_type;
+ eval "require $driver" or die "Could not load compiler driver: $@";
+ unshift @ISA, $driver;
+
+ return $self;
+}
+
+sub _compiler_type {
+ my $self = shift;
+ my $cc = $self->{config}{cc};
+
+ return ( $cc =~ /cl(\.exe)?$/ ? 'MSVC'
+ : $cc =~ /bcc32(\.exe)?$/ ? 'BCC'
+ : 'GCC');
+}
+
+sub split_like_shell {
+ # Since Windows will pass the whole command string (not an argument
+ # array) to the target program and make the program parse it itself,
+ # we don't actually need to do any processing here.
+ (my $self, local $_) = @_;
+
+ return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY');
+ return unless defined() && length();
+ return ($_);
+}
+
+sub do_system {
+ # See above
+ my $self = shift;
+ my $cmd = join(" ",
+ grep length,
+ map {$a=$_;$a=~s/\t/ /g;$a=~s/^\s+|\s+$//;$a}
+ grep defined, @_);
+ return $self->SUPER::do_system($cmd);
+}
+
+sub arg_defines {
+ my ($self, %args) = @_;
+ s/"/\\"/g foreach values %args;
+ return map qq{"-D$_=$args{$_}"}, keys %args;
+}
+
+sub compile {
+ my ($self, %args) = @_;
+ my $cf = $self->{config};
+
+ die "Missing 'source' argument to compile()" unless defined $args{source};
+
+ $args{include_dirs} = [ $args{include_dirs} ]
+ if exists($args{include_dirs}) && ref($args{include_dirs}) ne "ARRAY";
+
+ my ($basename, $srcdir) =
+ ( File::Basename::fileparse($args{source}, '\.[^.]+$') )[0,1];
+
+ $srcdir ||= File::Spec->curdir();
+
+ my @defines = $self->arg_defines( %{ $args{defines} || {} } );
+
+ my %spec = (
+ srcdir => $srcdir,
+ builddir => $srcdir,
+ basename => $basename,
+ source => $args{source},
+ output => $args{object_file} || File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
+ cc => $cf->{cc},
+ cflags => [
+ $self->split_like_shell($cf->{ccflags}),
+ $self->split_like_shell($cf->{cccdlflags}),
+ $self->split_like_shell($args{extra_compiler_flags}),
+ ],
+ optimize => [ $self->split_like_shell($cf->{optimize}) ],
+ defines => \@defines,
+ includes => [ @{$args{include_dirs} || []} ],
+ perlinc => [
+ $self->perl_inc(),
+ $self->split_like_shell($cf->{incpath}),
+ ],
+ use_scripts => 1, # XXX provide user option to change this???
+ );
+
+ $self->normalize_filespecs(
+ \$spec{source},
+ \$spec{output},
+ $spec{includes},
+ $spec{perlinc},
+ );
+
+ my @cmds = $self->format_compiler_cmd(%spec);
+ while ( my $cmd = shift @cmds ) {
+ $self->do_system( @$cmd )
+ or die "error building $cf->{dlext} file from '$args{source}'";
+ }
+
+ (my $out = $spec{output}) =~ tr/'"//d;
+ return $out;
+}
+
+sub need_prelink { 1 }
+
+sub link {
+ my ($self, %args) = @_;
+ my $cf = $self->{config};
+
+ my @objects = ( ref $args{objects} eq 'ARRAY' ? @{$args{objects}} : $args{objects} );
+ my $to = join '', (File::Spec->splitpath($objects[0]))[0,1];
+ $to ||= File::Spec->curdir();
+
+ (my $file_base = $args{module_name}) =~ s/.*:://;
+ my $output = $args{lib_file} ||
+ File::Spec->catfile($to, "$file_base.$cf->{dlext}");
+
+ # if running in perl source tree, look for libs there, not installed
+ my $lddlflags = $cf->{lddlflags};
+ my $perl_src = $self->perl_src();
+ $lddlflags =~ s/\Q$cf->{archlibexp}\E[\\\/]CORE/$perl_src/ if $perl_src;
+
+ my %spec = (
+ srcdir => $to,
+ builddir => $to,
+ startup => [ ],
+ objects => \@objects,
+ libs => [ ],
+ output => $output,
+ ld => $cf->{ld},
+ libperl => $cf->{libperl},
+ perllibs => [ $self->split_like_shell($cf->{perllibs}) ],
+ libpath => [ $self->split_like_shell($cf->{libpth}) ],
+ lddlflags => [ $self->split_like_shell($lddlflags) ],
+ other_ldflags => [ $self->split_like_shell($args{extra_linker_flags} || '') ],
+ use_scripts => 1, # XXX provide user option to change this???
+ );
+
+ unless ( $spec{basename} ) {
+ ($spec{basename} = $args{module_name}) =~ s/.*:://;
+ }
+
+ $spec{srcdir} = File::Spec->canonpath( $spec{srcdir} );
+ $spec{builddir} = File::Spec->canonpath( $spec{builddir} );
+
+ $spec{output} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.'.$cf->{dlext} );
+ $spec{manifest} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.'.$cf->{dlext}.'.manifest');
+ $spec{implib} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . $cf->{lib_ext} );
+ $spec{explib} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.exp' );
+ if ($cf->{cc} eq 'cl') {
+ $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.pdb' );
+ }
+ elsif ($cf->{cc} eq 'bcc32') {
+ $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.tds' );
+ }
+ $spec{def_file} ||= File::Spec->catfile( $spec{srcdir} ,
+ $spec{basename} . '.def' );
+ $spec{base_file} ||= File::Spec->catfile( $spec{srcdir} ,
+ $spec{basename} . '.base' );
+
+ $self->add_to_cleanup(
+ grep defined,
+ @{[ @spec{qw(manifest implib explib dbg_file def_file base_file map_file)} ]}
+ );
+
+ foreach my $opt ( qw(output manifest implib explib dbg_file def_file map_file base_file) ) {
+ $self->normalize_filespecs( \$spec{$opt} );
+ }
+
+ foreach my $opt ( qw(libpath startup objects) ) {
+ $self->normalize_filespecs( $spec{$opt} );
+ }
+
+ (my $def_base = $spec{def_file}) =~ tr/'"//d;
+ $def_base =~ s/\.def$//;
+ $self->prelink( dl_name => $args{module_name},
+ dl_file => $def_base,
+ dl_base => $spec{basename} );
+
+ my @cmds = $self->format_linker_cmd(%spec);
+ while ( my $cmd = shift @cmds ) {
+ $self->do_system( @$cmd );
+ }
+
+ $spec{output} =~ tr/'"//d;
+ return wantarray
+ ? grep defined, @spec{qw[output manifest implib explib dbg_file def_file map_file base_file]}
+ : $spec{output};
+}
+
+# canonize & quote paths
+sub normalize_filespecs {
+ my ($self, @specs) = @_;
+ foreach my $spec ( grep defined, @specs ) {
+ if ( ref $spec eq 'ARRAY') {
+ $self->normalize_filespecs( map {\$_} grep defined, @$spec )
+ } elsif ( ref $spec eq 'SCALAR' ) {
+ $$spec =~ tr/"//d if $$spec;
+ next unless $$spec;
+ $$spec = '"' . File::Spec->canonpath($$spec) . '"';
+ } elsif ( ref $spec eq '' ) {
+ $spec = '"' . File::Spec->canonpath($spec) . '"';
+ } else {
+ die "Don't know how to normalize " . (ref $spec || $spec) . "\n";
+ }
+ }
+}
+
+# directory of perl's include files
+sub perl_inc {
+ my $self = shift;
+
+ my $perl_src = $self->perl_src();
+
+ if ($perl_src) {
+ File::Spec->catdir($perl_src, "lib", "CORE");
+ } else {
+ File::Spec->catdir($self->{config}{archlibexp},"CORE");
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::CBuilder::Platform::Windows - Builder class for Windows platforms
+
+=head1 DESCRIPTION
+
+This module implements the Windows-specific parts of ExtUtils::CBuilder.
+Most of the Windows-specific stuff has to do with compiling and
+linking C code. Currently we support the 3 compilers perl itself
+supports: MSVC, BCC, and GCC.
+
+This module inherits from C<ExtUtils::CBuilder::Base>, so any functionality
+not implemented here will be implemented there. The interfaces are
+defined by the L<ExtUtils::CBuilder> documentation.
+
+=head1 AUTHOR
+
+Ken Williams <ken@mathforum.org>
+
+Most of the code here was written by Randy W. Sims <RandyS@ThePierianSpring.org>.
+
+=head1 SEE ALSO
+
+perl(1), ExtUtils::CBuilder(3), ExtUtils::MakeMaker(3)
+
+=cut
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm
new file mode 100644
index 0000000000..4810e79e70
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm
@@ -0,0 +1,130 @@
+package ExtUtils::CBuilder::Platform::Windows::BCC;
+
+use vars qw($VERSION);
+$VERSION = '0.2802';
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ %spec = $self->write_compiler_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{cc}, '-c' ,
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ "-o$spec{output}" ,
+ $spec{source} ,
+ ) ];
+}
+
+sub write_compiler_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.ccs' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ # XXX Borland "response files" seem to be unable to accept macro
+ # definitions containing quoted strings. Escaping strings with
+ # backslash doesn't work, and any level of quotes are stripped. The
+ # result is is a floating point number in the source file where a
+ # string is expected. So we leave the macros on the command line.
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(includes cflags optimize perlinc) } )
+ );
+
+ push @{$spec{includes}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-L$path";
+ }
+
+ push( @{$spec{startup}}, 'c0d32.obj' )
+ unless ( $spec{starup} && @{$spec{startup}} );
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{ld} ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{other_ldflags}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} , ',',
+ $spec{output} , ',',
+ $spec{map_file} , ',',
+ $spec{libperl} ,
+ @{$spec{perllibs}} , ',',
+ $spec{def_file}
+ ) ];
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ # To work around Borlands "unique" commandline syntax,
+ # two scripts are used:
+
+ my $ld_script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+ my $ld_libs = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lbs' );
+
+ $self->add_to_cleanup($ld_script, $ld_libs);
+
+ print "Generating scripts '$ld_script' and '$ld_libs'.\n" if !$self->{quiet};
+
+ # Script 1: contains options & names of object files.
+ my $LD_SCRIPT = IO::File->new( ">$ld_script" )
+ or die( "Could not create linker script '$ld_script': $!" );
+
+ print $LD_SCRIPT join( " +\n",
+ map { @{$_} }
+ grep defined,
+ delete(
+ @spec{ qw(lddlflags libpath other_ldflags startup objects) } )
+ );
+
+ # Script 2: contains name of libs to link against.
+ my $LD_LIBS = IO::File->new( ">$ld_libs" )
+ or die( "Could not create linker script '$ld_libs': $!" );
+
+ print $LD_LIBS join( " +\n",
+ (delete $spec{libperl} || ''),
+ @{delete $spec{perllibs} || []},
+ );
+
+ push @{$spec{lddlflags}}, '@"' . $ld_script . '"';
+ push @{$spec{perllibs}}, '@"' . $ld_libs . '"';
+
+ return %spec;
+}
+
+1;
+
+
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm
new file mode 100644
index 0000000000..98f1176741
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm
@@ -0,0 +1,151 @@
+package ExtUtils::CBuilder::Platform::Windows::GCC;
+
+use vars qw($VERSION);
+$VERSION = '0.2802';
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ # split off any -arguments included in cc
+ my @cc = split / (?=-)/, $spec{cc};
+
+ return [ grep {defined && length} (
+ @cc, '-c' ,
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ '-o', $spec{output} ,
+ $spec{source} ,
+ ) ];
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+ my $cf = $self->{config};
+
+ # The Config.pm variable 'libperl' is hardcoded to the full name
+ # of the perl import library (i.e. 'libperl56.a'). GCC will not
+ # find it unless the 'lib' prefix & the extension are stripped.
+ $spec{libperl} =~ s/^(?:lib)?([^.]+).*$/-l$1/;
+
+ unshift( @{$spec{other_ldflags}}, '-nostartfiles' )
+ if ( $spec{startup} && @{$spec{startup}} );
+
+ # From ExtUtils::MM_Win32:
+ #
+ ## one thing for GCC/Mingw32:
+ ## we try to overcome non-relocateable-DLL problems by generating
+ ## a (hopefully unique) image-base from the dll's name
+ ## -- BKS, 10-19-1999
+ File::Basename::basename( $spec{output} ) =~ /(....)(.{0,4})/;
+ $spec{image_base} = sprintf( "0x%x0000", unpack('n', $1 ^ $2) );
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-L$path";
+ }
+
+ my @cmds; # Stores the series of commands needed to build the module.
+
+ my $DLLTOOL = $cf->{dlltool} || 'dlltool';
+
+ push @cmds, [
+ $DLLTOOL, '--def' , $spec{def_file},
+ '--output-exp' , $spec{explib}
+ ];
+
+ # split off any -arguments included in ld
+ my @ld = split / (?=-)/, $spec{ld};
+
+ push @cmds, [ grep {defined && length} (
+ @ld ,
+ '-o', $spec{output} ,
+ "-Wl,--base-file,$spec{base_file}" ,
+ "-Wl,--image-base,$spec{image_base}" ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ @{$spec{other_ldflags}} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{explib} ,
+ $spec{map_file} ? ('-Map', $spec{map_file}) : ''
+ ) ];
+
+ push @cmds, [
+ $DLLTOOL, '--def' , $spec{def_file},
+ '--output-exp' , $spec{explib},
+ '--base-file' , $spec{base_file}
+ ];
+
+ push @cmds, [ grep {defined && length} (
+ @ld ,
+ '-o', $spec{output} ,
+ "-Wl,--image-base,$spec{image_base}" ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ @{$spec{other_ldflags}} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{explib} ,
+ $spec{map_file} ? ('-Map', $spec{map_file}) : ''
+ ) ];
+
+ return @cmds;
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT ( 'SEARCH_DIR(' . $_ . ")\n" )
+ for @{delete $spec{libpath} || []};
+
+ # gcc takes only one startup file, so the first object in startup is
+ # specified as the startup file and any others are shifted into the
+ # beginning of the list of objects.
+ if ( $spec{startup} && @{$spec{startup}} ) {
+ print $SCRIPT 'STARTUP(' . shift( @{$spec{startup}} ) . ")\n";
+ unshift @{$spec{objects}},
+ @{delete $spec{startup} || []};
+ }
+
+ print $SCRIPT 'INPUT(' . join( ',',
+ @{delete $spec{objects} || []}
+ ) . ")\n";
+
+ print $SCRIPT 'INPUT(' . join( ' ',
+ (delete $spec{libperl} || ''),
+ @{delete $spec{perllibs} || []},
+ ) . ")\n";
+
+ #it is important to keep the order 1.linker_script - 2.other_ldflags
+ unshift @{$spec{other_ldflags}}, '"' . $script . '"';
+
+ return %spec;
+}
+
+1;
+
+
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm
new file mode 100644
index 0000000000..df1b7cefd7
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm
@@ -0,0 +1,131 @@
+package ExtUtils::CBuilder::Platform::Windows::MSVC;
+
+use vars qw($VERSION);
+$VERSION = '0.2802';
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return "/OUT:$file";
+}
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ %spec = $self->write_compiler_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{cc},'-nologo','-c',
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ "-Fo$spec{output}" ,
+ $spec{source} ,
+ ) ];
+}
+
+sub write_compiler_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.ccs' );
+
+ $self->add_to_cleanup($script);
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(includes cflags optimize defines perlinc) } )
+ );
+
+ push @{$spec{includes}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+ my $cf = $self->{config};
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-libpath:$path";
+ }
+
+ my $output = $spec{output};
+
+ $spec{def_file} &&= '-def:' . $spec{def_file};
+ $spec{output} &&= '-out:' . $spec{output};
+ $spec{manifest} &&= '-manifest ' . $spec{manifest};
+ $spec{implib} &&= '-implib:' . $spec{implib};
+ $spec{map_file} &&= '-map:' . $spec{map_file};
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ my @cmds; # Stores the series of commands needed to build the module.
+
+ push @cmds, [ grep {defined && length} (
+ $spec{ld} ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{other_ldflags}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ $spec{map_file} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{def_file} ,
+ $spec{implib} ,
+ $spec{output} ,
+ ) ];
+
+ # Embed the manifest file if it exists
+ push @cmds, [
+ 'if', 'exist', $spec{manifest}, 'mt', '-nologo', $spec{manifest}, '-outputresource:' . "$output;2"
+ ];
+
+ return @cmds;
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(lddlflags libpath other_ldflags
+ startup objects libperl perllibs
+ def_file implib map_file) } )
+ );
+
+ push @{$spec{lddlflags}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+1;
+
+
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/aix.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/aix.pm
new file mode 100644
index 0000000000..4789ff77c5
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/aix.pm
@@ -0,0 +1,31 @@
+package ExtUtils::CBuilder::Platform::aix;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+use File::Spec;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+sub need_prelink { 1 }
+
+sub link {
+ my ($self, %args) = @_;
+ my $cf = $self->{config};
+
+ (my $baseext = $args{module_name}) =~ s/.*:://;
+ my $perl_inc = $self->perl_inc();
+
+ # Massage some very naughty bits in %Config
+ local $cf->{lddlflags} = $cf->{lddlflags};
+ for ($cf->{lddlflags}) {
+ s/\Q$(BASEEXT)\E/$baseext/;
+ s/\Q$(PERL_INC)\E/$perl_inc/;
+ }
+
+ return $self->SUPER::link(%args);
+}
+
+
+1;
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/cygwin.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/cygwin.pm
new file mode 100644
index 0000000000..442bbd8df1
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/cygwin.pm
@@ -0,0 +1,33 @@
+package ExtUtils::CBuilder::Platform::cygwin;
+
+use strict;
+use File::Spec;
+use ExtUtils::CBuilder::Platform::Unix;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+# TODO: If a specific exe_file name is requested, if the exe created
+# doesn't have that name, we might want to rename it. Apparently asking
+# for an exe of "foo" might result in "foo.exe". Alternatively, we should
+# make sure the return value is correctly "foo.exe".
+# C.f http://rt.cpan.org/Public/Bug/Display.html?id=41003
+sub link_executable {
+ my $self = shift;
+ return $self->SUPER::link_executable(@_);
+}
+
+sub link {
+ my ($self, %args) = @_;
+
+ my $lib = $self->{config}{useshrplib} ? 'libperl.dll.a' : 'libperl.a';
+ $args{extra_linker_flags} = [
+ File::Spec->catfile($self->perl_inc(), $lib),
+ $self->split_like_shell($args{extra_linker_flags})
+ ];
+
+ return $self->SUPER::link(%args);
+}
+
+1;
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/darwin.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/darwin.pm
new file mode 100644
index 0000000000..89565b837e
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/darwin.pm
@@ -0,0 +1,22 @@
+package ExtUtils::CBuilder::Platform::darwin;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+sub compile {
+ my $self = shift;
+ my $cf = $self->{config};
+
+ # -flat_namespace isn't a compile flag, it's a linker flag. But
+ # it's mistakenly in Config.pm as both. Make the correction here.
+ local $cf->{ccflags} = $cf->{ccflags};
+ $cf->{ccflags} =~ s/-flat_namespace//;
+ $self->SUPER::compile(@_);
+}
+
+
+1;
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/dec_osf.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/dec_osf.pm
new file mode 100644
index 0000000000..2798c696d9
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/dec_osf.pm
@@ -0,0 +1,18 @@
+package ExtUtils::CBuilder::Platform::dec_osf;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+use File::Spec;
+
+use vars qw($VERSION @ISA);
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+$VERSION = '0.2802';
+
+sub link_executable {
+ my $self = shift;
+ # $Config{ld} is 'ld' but that won't work: use the cc instead.
+ local $self->{config}{ld} = $self->{config}{cc};
+ return $self->SUPER::link_executable(@_);
+}
+
+1;
diff --git a/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/os2.pm b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/os2.pm
new file mode 100644
index 0000000000..e4f161df57
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/lib/ExtUtils/CBuilder/Platform/os2.pm
@@ -0,0 +1,80 @@
+package ExtUtils::CBuilder::Platform::os2;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.2802';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+sub need_prelink { 1 }
+
+sub prelink {
+ # Generate import libraries (XXXX currently near .DEF; should be near DLL!)
+ my $self = shift;
+ my %args = @_;
+
+ my @res = $self->SUPER::prelink(%args);
+ die "Unexpected number of DEF files" unless @res == 1;
+ die "Can't find DEF file in the output"
+ unless $res[0] =~ m,^(.*)\.def$,si;
+ my $libname = "$1$self->{config}{lib_ext}"; # Put .LIB file near .DEF file
+ $self->do_system('emximp', '-o', $libname, $res[0]) or die "emxexp: res=$?";
+ return (@res, $libname);
+}
+
+sub _do_link {
+ my $self = shift;
+ my ($how, %args) = @_;
+ if ($how eq 'lib_file'
+ and (defined $args{module_name} and length $args{module_name})) {
+
+ # DynaLoader::mod2fname() is a builtin func
+ my $lib = DynaLoader::mod2fname([split /::/, $args{module_name}]);
+
+ # Now know the basename, find directory parts via lib_file, or objects
+ my $objs = ( (ref $args{objects}) ? $args{objects} : [$args{objects}] );
+ my $near_obj = $self->lib_file(@$objs);
+ my $ref_file = ( defined $args{lib_file} ? $args{lib_file} : $near_obj );
+ my $lib_dir = ($ref_file =~ m,(.*)[/\\],s ? "$1/" : '' );
+ my $exp_dir = ($near_obj =~ m,(.*)[/\\],s ? "$1/" : '' );
+
+ $args{dl_file} = $1 if $near_obj =~ m,(.*)\.,s; # put ExportList near OBJ
+ $args{lib_file} = "$lib_dir$lib.$self->{config}{dlext}"; # DLL file
+
+ # XXX _do_link does not have place to put libraries?
+ push @$objs, $self->perl_inc() . "/libperl$self->{config}{lib_ext}";
+ $args{objects} = $objs;
+ }
+ # Some 'env' do exec(), thus return too early when run from ksh;
+ # To avoid 'env', remove (useless) shrpenv
+ local $self->{config}{shrpenv} = '';
+ return $self->SUPER::_do_link($how, %args);
+}
+
+sub extra_link_args_after_prelink {
+ # Add .DEF file to the link line
+ my ($self, %args) = @_;
+
+ my @DEF = grep /\.def$/i, @{$args{prelink_res}};
+ die "More than one .def files created by `prelink' stage" if @DEF > 1;
+ # XXXX No "$how" argument here, so how to test for dynamic link?
+ die "No .def file created by `prelink' stage"
+ unless @DEF or not @{$args{prelink_res}};
+
+ my @after_libs = ($OS2::is_aout ? ()
+ : $self->perl_inc() . "/libperl_override$self->{config}{lib_ext}");
+ # , "-L", "-lperl"
+ (@after_libs, @DEF);
+}
+
+sub link_executable {
+ # ldflags is not expecting .exe extension given on command line; remove -Zexe
+ my $self = shift;
+ local $self->{config}{ldflags} = $self->{config}{ldflags};
+ $self->{config}{ldflags} =~ s/(?<!\S)-Zexe(?!\S)//;
+ return $self->SUPER::link_executable(@_);
+}
+
+
+1;
diff --git a/dist/ExtUtils-CBuilder/t/00-have-compiler.t b/dist/ExtUtils-CBuilder/t/00-have-compiler.t
new file mode 100644
index 0000000000..581a21461b
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/t/00-have-compiler.t
@@ -0,0 +1,57 @@
+#! perl -w
+
+use File::Spec;
+my $perl;
+BEGIN {
+ $perl = File::Spec->rel2abs($^X);
+}
+
+use strict;
+use Test::More;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+
+plan tests => 7;
+
+require_ok "ExtUtils::CBuilder";
+
+my $b = eval { ExtUtils::CBuilder->new(quiet => 1) };
+ok( $b, "got CBuilder object" ) or diag $@;
+
+my $bogus_path = 'djaadjfkadjkfajdf';
+my $run_perl = "$perl -e1 --";
+# test missing compiler
+$b->{config}{cc} = $bogus_path;
+$b->{config}{ld} = $bogus_path;
+
+$b->{have_cc} = undef;
+is( $b->have_compiler, 0, "have_compiler: fake missing cc" );
+$b->{have_cxx} = undef;
+is( $b->have_cplusplus, 0, "have_cplusplus: fake missing c++" );
+
+# test found compiler
+$b->{config}{cc} = $run_perl;
+$b->{config}{ld} = $run_perl;
+$b->{config}{cxx} = $run_perl;
+$b->{have_cc} = undef;
+is( $b->have_compiler, 1, "have_compiler: fake present cc" );
+$b->{have_cxx} = undef;
+is( $b->have_cplusplus, 1, "have_cpp_compiler: fake present c++" );
+
+# test missing cpp compiler
+
+# test one non-exported subroutine
+{
+ my $type = ExtUtils::CBuilder::os_type();
+ if ($type) {
+ pass( "OS type $type located for $^O" );
+ }
+ else {
+ pass( "OS type not yet listed for $^O" );
+ }
+}
diff --git a/dist/ExtUtils-CBuilder/t/01-basic.t b/dist/ExtUtils-CBuilder/t/01-basic.t
new file mode 100644
index 0000000000..ffcd60ce9c
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/t/01-basic.t
@@ -0,0 +1,106 @@
+#! perl -w
+
+use strict;
+use Test::More;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+use ExtUtils::CBuilder;
+use File::Spec;
+
+# TEST does not like extraneous output
+my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
+my ($source_file, $object_file, $lib_file);
+
+my $b = ExtUtils::CBuilder->new(quiet => $quiet);
+
+# test plan
+if ( ! $b->have_compiler ) {
+ plan skip_all => "no compiler available for testing";
+}
+else {
+ plan tests => 12;
+}
+
+ok $b, "created EU::CB object";
+
+ok $b->have_compiler, "have_compiler";
+
+$source_file = File::Spec->catfile('t', 'compilet.c');
+{
+ local *FH;
+ open FH, "> $source_file" or die "Can't create $source_file: $!";
+ print FH "int boot_compilet(void) { return 1; }\n";
+ close FH;
+}
+ok -e $source_file, "source file '$source_file' created";
+
+$object_file = $b->object_file($source_file);
+ok 1;
+
+is $object_file, $b->compile(source => $source_file);
+
+$lib_file = $b->lib_file($object_file);
+ok 1;
+
+my ($lib, @temps) = $b->link(objects => $object_file,
+ module_name => 'compilet');
+$lib =~ tr/"'//d;
+is $lib_file, $lib;
+
+for ($source_file, $object_file, $lib_file) {
+ tr/"'//d;
+ 1 while unlink;
+}
+
+if ($^O eq 'VMS') {
+ 1 while unlink 'COMPILET.LIS';
+ 1 while unlink 'COMPILET.OPT';
+}
+
+my @words = $b->split_like_shell(' foo bar');
+
+SKIP: {
+ skip "MSWindows", 3 if $^O =~ m/MSWin/;
+ is( @words, 2 );
+ is( $words[0], 'foo' );
+ is( $words[1], 'bar' );
+}
+
+# include_dirs should be settable as string or list
+{
+ package Sub;
+ use vars '@ISA';
+ @ISA = ('ExtUtils::CBuilder');
+ my $saw = 0;
+ sub do_system {
+ if ($^O eq "MSWin32") {
+ # ExtUtils::CBuilder::MSVC::write_compiler_script() puts the
+ # include_dirs into a response file and not the commandline
+ for (@_) {
+ next unless /^\@"(.*)"$/;
+ open(my $fh, "<", $1) or next;
+ local $/;
+ $saw = 1 if <$fh> =~ /another dir/;
+ last;
+ }
+ }
+ $saw = 1 if grep {$_ =~ /another dir/} @_;
+ return 1;
+ }
+
+ package main;
+ my $s = Sub->new();
+ $s->compile(source => 'foo',
+ include_dirs => 'another dir');
+ ok $saw;
+
+ $saw = 0;
+ $s->compile(source => 'foo',
+ include_dirs => ['a dir', 'another dir']);
+ ok $saw;
+}
diff --git a/dist/ExtUtils-CBuilder/t/02-link.t b/dist/ExtUtils-CBuilder/t/02-link.t
new file mode 100644
index 0000000000..822b071223
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/t/02-link.t
@@ -0,0 +1,97 @@
+#! perl -w
+
+use strict;
+use Test::More;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+use ExtUtils::CBuilder;
+use File::Spec;
+
+# TEST does not like extraneous output
+my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
+my ($source_file, $object_file, $exe_file);
+
+my $b = ExtUtils::CBuilder->new(quiet => $quiet);
+
+# test plan
+if ($^O eq 'MSWin32') {
+ plan skip_all => "link_executable() is not implemented yet on Win32";
+}
+elsif ( ! $b->have_compiler ) {
+ plan skip_all => "no compiler available for testing";
+}
+else {
+ plan tests => 8;
+}
+
+ok $b, "created EU::CB object";
+
+$source_file = File::Spec->catfile('t', 'compilet.c');
+{
+ open my $FH, "> $source_file" or die "Can't create $source_file: $!";
+ print $FH "int main(void) { return 11; }\n";
+ close $FH;
+}
+ok -e $source_file, "generated '$source_file'";
+
+# Compile
+eval { $object_file = $b->compile(source => $source_file) };
+is $@, q{}, "no exception from compilation";
+ok -e $object_file, "found object file";
+
+# Link
+SKIP: {
+ skip "error compiling source", 4
+ unless -e $object_file;
+
+ my @temps;
+ eval { ($exe_file, @temps) = $b->link_executable(objects => $object_file) };
+ is $@, q{}, "no exception from linking";
+ ok -e $exe_file, "found executable file";
+ ok -x $exe_file, "executable file appears to be executable";
+
+ if ($^O eq 'os2') { # Analogue of LDLOADPATH...
+ # Actually, not needed now, since we do not link with the generated DLL
+ my $old = OS2::extLibpath(); # [builtin function]
+ $old = ";$old" if defined $old and length $old;
+ # To pass the sanity check, components must have backslashes...
+ OS2::extLibpath_set(".\\$old");
+ }
+
+ # Try the executable
+ my $ec = my_system($exe_file);
+ is( $ec, 11, "got expected exit code from executable" )
+ or diag( $ec == -1 ? "Could not run '$exe_file': $!\n"
+ : "Unexpected exit code '$ec'\n");
+}
+
+# Clean up
+for ($source_file, $object_file, $exe_file) {
+ tr/"'//d;
+ 1 while unlink;
+}
+
+if ($^O eq 'VMS') {
+ 1 while unlink 'COMPILET.LIS';
+ 1 while unlink 'COMPILET.OPT';
+}
+
+sub my_system {
+ my $cmd = shift;
+ my $ec;
+ if ($^O eq 'VMS') {
+ # Preserve non-posixified status and don't bit shift the result
+ # because we're running under "use vmsish";
+ $ec = system("mcr $cmd");
+ return $ec;
+ }
+ else {
+ $ec = system($cmd);
+ return $ec == -1 ? -1 : $ec >> 8;
+ }
+}
diff --git a/dist/ExtUtils-CBuilder/t/03-cplusplus.t b/dist/ExtUtils-CBuilder/t/03-cplusplus.t
new file mode 100644
index 0000000000..02555df3db
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/t/03-cplusplus.t
@@ -0,0 +1,63 @@
+#! perl -w
+
+use strict;
+use Test::More;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+use ExtUtils::CBuilder;
+use File::Spec;
+
+# TEST does not like extraneous output
+my $quiet = $ENV{PERL_CORE} && !$ENV{HARNESS_ACTIVE};
+my ($source_file, $object_file, $lib_file);
+
+my $b = ExtUtils::CBuilder->new(quiet => $quiet);
+
+# test plan
+if ( ! $b->have_cplusplus ) {
+ plan skip_all => "no compiler available for testing";
+}
+else {
+ plan tests => 7;
+}
+
+ok $b, "created EU::CB object";
+
+ok $b->have_cplusplus, "have_cplusplus";
+
+$source_file = File::Spec->catfile('t', 'compilet.cc');
+{
+ open my $FH, "> $source_file" or die "Can't create $source_file: $!";
+ print $FH "class Bogus { public: int boot_compilet() { return 1; } };\n";
+ close $FH;
+}
+ok -e $source_file, "source file '$source_file' created";
+
+$object_file = $b->object_file($source_file);
+ok 1;
+
+is $object_file, $b->compile(source => $source_file, 'C++' => 1);
+
+$lib_file = $b->lib_file($object_file);
+ok 1;
+
+my ($lib, @temps) = $b->link(objects => $object_file,
+ module_name => 'compilet');
+$lib =~ tr/"'//d;
+is $lib_file, $lib;
+
+for ($source_file, $object_file, $lib_file) {
+ tr/"'//d;
+ 1 while unlink;
+}
+
+if ($^O eq 'VMS') {
+ 1 while unlink 'COMPILET.LIS';
+ 1 while unlink 'COMPILET.OPT';
+}
+
diff --git a/dist/ExtUtils-CBuilder/t/04-base.t b/dist/ExtUtils-CBuilder/t/04-base.t
new file mode 100644
index 0000000000..988f7ae49e
--- /dev/null
+++ b/dist/ExtUtils-CBuilder/t/04-base.t
@@ -0,0 +1,412 @@
+#! perl -w
+
+use strict;
+use Test::More tests => 58;
+BEGIN {
+ if ($^O eq 'VMS') {
+ # So we can get the return value of system()
+ require vmsish;
+ import vmsish;
+ }
+}
+use Config;
+use Cwd;
+use File::Path qw( mkpath );
+use File::Temp qw( tempdir );
+use ExtUtils::CBuilder::Base;
+
+# XXX protect from user CC as we mock everything here
+local $ENV{CC};
+
+my ( $base, $phony, $cwd );
+my ( $source_file, $object_file, $lib_file );
+
+$base = ExtUtils::CBuilder::Base->new();
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+
+{
+ $phony = 'foobar';
+ $base = ExtUtils::CBuilder::Base->new(
+ config => { cc => $phony },
+ );
+ ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+ isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+ is( $base->{config}->{cc}, $phony,
+ "Got expected value when 'config' argument passed to new()" );
+}
+
+{
+ $phony = 'barbaz';
+ local $ENV{CC} = $phony;
+ $base = ExtUtils::CBuilder::Base->new();
+ ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+ isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+ is( $base->{config}->{cc}, $phony,
+ "Got expected value \$ENV{CC} set" );
+}
+
+{
+ my $path_to_perl = File::Spec->catfile( '', qw| usr bin perl | );
+ local $^X = $path_to_perl;
+ is(
+ ExtUtils::CBuilder::Base::find_perl_interpreter(),
+ $path_to_perl,
+ "find_perl_interpreter() returned expected absolute path"
+ );
+}
+
+{
+ my $path_to_perl = 'foobar';
+ local $^X = $path_to_perl;
+ # %Config is read-only. We cannot assign to it and we therefore cannot
+ # simulate the condition that would occur were its value something other
+ # than an existing file.
+ if ( !$ENV{PERL_CORE} and $Config::Config{perlpath}) {
+ is(
+ ExtUtils::CBuilder::Base::find_perl_interpreter(),
+ $Config::Config{perlpath},
+ "find_perl_interpreter() returned expected file"
+ );
+ }
+ else {
+ local $^X = $path_to_perl = File::Spec->rel2abs($path_to_perl);
+ is(
+ ExtUtils::CBuilder::Base::find_perl_interpreter(),
+ $path_to_perl,
+ "find_perl_interpreter() returned expected name"
+ );
+ }
+}
+
+{
+ $cwd = cwd();
+ my $tdir = tempdir();
+ chdir $tdir;
+ $base = ExtUtils::CBuilder::Base->new();
+ ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+ isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+ is( scalar keys %{$base->{files_to_clean}}, 0,
+ "No files needing cleaning yet" );
+
+ my $file_for_cleaning = File::Spec->catfile( $tdir, 'foobar' );
+ open my $IN, '>', $file_for_cleaning
+ or die "Unable to open dummy file: $!";
+ print $IN "\n";
+ close $IN or die "Unable to close dummy file: $!";
+
+ $base->add_to_cleanup( $file_for_cleaning );
+ is( scalar keys %{$base->{files_to_clean}}, 1,
+ "One file needs cleaning" );
+
+ $base->cleanup();
+ ok( ! -f $file_for_cleaning, "File was cleaned up" );
+
+ chdir $cwd;
+}
+
+# fake compiler is perl and will always succeed
+$base = ExtUtils::CBuilder::Base->new(
+ config => {
+ cc => File::Spec->rel2abs($^X) . " -e1 --",
+ ld => File::Spec->rel2abs($^X) . " -e1 --",
+ }
+);
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+eval {
+ $base->compile(foo => 'bar');
+};
+like(
+ $@,
+ qr/Missing 'source' argument to compile/,
+ "Got expected error message when lacking 'source' argument to compile()"
+);
+
+$base = ExtUtils::CBuilder::Base->new( quiet => 1 );
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+
+$source_file = File::Spec->catfile('t', 'compilet.c');
+create_c_source_file($source_file);
+ok(-e $source_file, "source file '$source_file' created");
+
+# object filename automatically assigned
+my $obj_ext = $base->{config}{obj_ext};
+is( $base->object_file($source_file),
+ File::Spec->catfile('t', "compilet$obj_ext"),
+ "object_file(): got expected automatically assigned name for object file"
+);
+
+# object filename explicitly assigned
+$object_file = File::Spec->catfile('t', 'my_special_compilet.o' );
+is( $object_file,
+ $base->compile(
+ source => $source_file,
+ object_file => $object_file,
+ ),
+ "compile(): returned object file with specified name"
+);
+
+$lib_file = $base->lib_file($object_file);
+ok( $lib_file, "lib_file() returned true value" );
+
+my ($lib, @temps);
+($lib, @temps) = $base->link(
+ objects => $object_file,
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+($lib, @temps) = $base->link(
+ objects => [ $object_file ],
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+($lib, @temps) = $base->link(
+ lib_file => $lib_file,
+ objects => [ $object_file ],
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+$lib = $base->link(
+ objects => $object_file,
+ module_name => 'compilet',
+);
+$lib =~ tr/"'//d; #"
+is($lib_file, $lib, "lib_file(): got expected value for $lib");
+
+{
+ local $ENV{PERL_CORE} = '' unless $ENV{PERL_CORE};
+ my $include_dir = $base->perl_inc();
+ ok( $include_dir, "perl_inc() returned true value" );
+ ok( -d $include_dir, "perl_inc() returned directory" );
+}
+
+#
+$base = ExtUtils::CBuilder::Base->new( quiet => 1 );
+ok( $base, "ExtUtils::CBuilder::Base->new() returned true value" );
+isa_ok( $base, 'ExtUtils::CBuilder::Base' );
+
+$source_file = File::Spec->catfile('t', 'compilet.c');
+create_c_source_file($source_file);
+ok(-e $source_file, "source file '$source_file' created");
+$object_file = File::Spec->catfile('t', 'my_special_compilet.o' );
+is( $object_file,
+ $base->compile(
+ source => $source_file,
+ object_file => $object_file,
+ defines => { alpha => 'beta', gamma => 'delta' },
+ ),
+ "compile() completed when 'defines' provided; returned object file with specified name"
+);
+
+my $exe_file = $base->exe_file($object_file);
+my $ext = $base->{config}{_exe};
+my $expected = File::Spec->catfile('t', qq|my_special_compilet$ext| );
+is(
+ $exe_file,
+ $expected,
+ "exe_file(): returned expected name of executable"
+);
+
+my %args = ();
+my @defines = $base->arg_defines( %args );
+ok( ! @defines, "Empty hash passed to arg_defines() returns empty list" );
+
+%args = ( alpha => 'beta', gamma => 'delta' );
+my $defines_seen_ref = { map { $_ => 1 } $base->arg_defines( %args ) };
+is_deeply(
+ $defines_seen_ref,
+ { '-Dalpha=beta' => 1, '-Dgamma=delta' => 1 },
+ "arg_defines(): got expected defines",
+);
+
+my $include_dirs_seen_ref =
+ { map {$_ => 1} $base->arg_include_dirs( qw| alpha beta gamma | ) };
+is_deeply(
+ $include_dirs_seen_ref,
+ { '-Ialpha' => 1, '-Ibeta' => 1, '-Igamma' => 1 },
+ "arg_include_dirs(): got expected include_dirs",
+);
+
+is( '-c', $base->arg_nolink(), "arg_nolink(): got expected value" );
+
+my $seen_ref =
+ { map {$_ => 1} $base->arg_object_file('alpha') };
+is_deeply(
+ $seen_ref,
+ { '-o' => 1, 'alpha' => 1 },
+ "arg_object_file(): got expected option flag and value",
+);
+
+$seen_ref = { map {$_ => 1} $base->arg_share_object_file('alpha') };
+my %exp = map {$_ => 1} $base->split_like_shell($base->{config}{lddlflags});
+$exp{'-o'} = 1;
+$exp{'alpha'} = 1;
+
+is_deeply(
+ $seen_ref,
+ \%exp,
+ "arg_share_object_file(): got expected option flag and value",
+);
+
+$seen_ref =
+ { map {$_ => 1} $base->arg_exec_file('alpha') };
+is_deeply(
+ $seen_ref,
+ { '-o' => 1, 'alpha' => 1 },
+ "arg_exec_file(): got expected option flag and value",
+);
+
+ok(! $base->split_like_shell(undef),
+ "split_like_shell(): handled undefined argument as expected" );
+
+my $array_ref = [ qw| alpha beta gamma | ];
+my %split_seen = map { $_ => 1 } $base->split_like_shell($array_ref);
+%exp = ( alpha => 1, beta => 1, gamma => 1 );
+is_deeply( \%split_seen, \%exp,
+ "split_like_shell(): handled array ref as expected" );
+
+{
+ $cwd = cwd();
+ my $tdir = tempdir();
+ my $subdir = File::Spec->catdir(
+ $tdir, qw| alpha beta gamma delta epsilon
+ zeta eta theta iota kappa lambda |
+ );
+ mkpath($subdir, { mode => 0711 } );
+ chdir $subdir
+ or die "Unable to change to temporary directory for testing";
+ local $ENV{PERL_CORE} = 1;
+ my $capture = q{};
+ local $SIG{__WARN__} = sub { $capture = $_[0] };
+ my $expected_message =
+ qr/PERL_CORE is set but I can't find your perl source!/; #'
+ my $rv;
+
+ $rv = $base->perl_src();
+ is( $rv, q{}, "perl_src(): returned empty string as expected" );
+ like( $capture, $expected_message,
+ "perl_src(): got expected warning" );
+ $capture = q{};
+
+ my $config = File::Spec->catfile( $subdir, 'config_h.SH' );
+ touch_file($config);
+ $rv = $base->perl_src();
+ is( $rv, q{}, "perl_src(): returned empty string as expected" );
+ like( $capture, $expected_message,
+ "perl_src(): got expected warning" );
+ $capture = q{};
+
+ my $perlh = File::Spec->catfile( $subdir, 'perl.h' );
+ touch_file($perlh);
+ $rv = $base->perl_src();
+ is( $rv, q{}, "perl_src(): returned empty string as expected" );
+ like( $capture, $expected_message,
+ "perl_src(): got expected warning" );
+ $capture = q{};
+
+ my $libsubdir = File::Spec->catdir( $subdir, 'lib' );
+ mkpath($libsubdir, { mode => 0711 } );
+ my $exporter = File::Spec->catfile( $libsubdir, 'Exporter.pm' );
+ touch_file($exporter);
+ $rv = $base->perl_src();
+ ok( -d $rv, "perl_src(): returned a directory" );
+ is( $rv, Cwd::realpath($subdir), "perl_src(): identified directory" );
+ is( $capture, q{}, "perl_src(): no warning, as expected" );
+
+ chdir $cwd
+ or die "Unable to change from temporary directory after testing";
+}
+
+my ($dl_file_out, $mksymlists_args);
+my $dlf = 'Kappa';
+%args = (
+ dl_vars => [ qw| alpha beta gamma | ],
+ dl_funcs => {
+ 'Homer::Iliad' => [ qw(trojans greeks) ],
+ 'Homer::Odyssey' => [ qw(travellers family suitors) ],
+ },
+ dl_func_list => [ qw| delta epsilon | ],
+ dl_imports => { zeta => 'eta', theta => 'iota' },
+ dl_name => 'Tk::Canvas',
+ dl_base => 'Tk::Canvas.ext',
+ dl_file => $dlf,
+ dl_version => '7.7',
+);
+($dl_file_out, $mksymlists_args) =
+ ExtUtils::CBuilder::Base::_prepare_mksymlists_args(\%args);
+is( $dl_file_out, $dlf, "_prepare_mksymlists_args(): Got expected name for dl_file" );
+is_deeply( $mksymlists_args,
+ {
+ DL_VARS => [ qw| alpha beta gamma | ],
+ DL_FUNCS => {
+ 'Homer::Iliad' => [ qw(trojans greeks) ],
+ 'Homer::Odyssey' => [ qw(travellers family suitors) ],
+ },
+ FUNCLIST => [ qw| delta epsilon | ],
+ IMPORTS => { zeta => 'eta', theta => 'iota' },
+ NAME => 'Tk::Canvas',
+ DLBASE => 'Tk::Canvas.ext',
+ FILE => $dlf,
+ VERSION => '7.7',
+ },
+ "_prepare_mksymlists_args(): got expected arguments for Mksymlists",
+);
+
+$dlf = 'Canvas';
+%args = (
+ dl_name => 'Tk::Canvas',
+ dl_base => 'Tk::Canvas.ext',
+);
+($dl_file_out, $mksymlists_args) =
+ ExtUtils::CBuilder::Base::_prepare_mksymlists_args(\%args);
+is( $dl_file_out, $dlf, "_prepare_mksymlists_args(): got expected name for dl_file" );
+is_deeply( $mksymlists_args,
+ {
+ DL_VARS => [],
+ DL_FUNCS => {},
+ FUNCLIST => [],
+ IMPORTS => {},
+ NAME => 'Tk::Canvas',
+ DLBASE => 'Tk::Canvas.ext',
+ FILE => $dlf,
+ VERSION => '0.0',
+ },
+ "_prepare_mksymlists_args(): got expected arguments for Mksymlists",
+);
+
+#####
+
+for ($source_file, $object_file, $lib_file) {
+ tr/"'//d; #"
+ 1 while unlink;
+}
+
+pass("Completed all tests in $0");
+
+if ($^O eq 'VMS') {
+ 1 while unlink 'COMPILET.LIS';
+ 1 while unlink 'COMPILET.OPT';
+}
+
+sub create_c_source_file {
+ my $source_file = shift;
+ open my $FH, '>', $source_file or die "Can't create $source_file: $!";
+ print $FH "int boot_compilet(void) { return 1; }\n";
+ close $FH;
+}
+
+sub touch_file {
+ my $f = shift;
+ open my $FH, '>', $f or die "Can't create $f: $!";
+ print $FH "\n";
+ close $FH;
+ return $f;
+}