@@ -28,6 +28,7 @@ my $libpgcommon;
2828my $libpgfeutils ;
2929my $postgres ;
3030my $libpq ;
31+ my @unlink_on_exit ;
3132
3233# Set of variables for modules in contrib/ and src/test/modules/
3334my $contrib_defines = { ' refint' => ' REFINT_VERBOSE' };
@@ -517,34 +518,154 @@ sub mkvcbuild
517518 my $plperl =
518519 $solution -> AddProject(' plperl' , ' dll' , ' PLs' , ' src/pl/plperl' );
519520 $plperl -> AddIncludeDir($solution -> {options }-> {perl } . ' /lib/CORE' );
521+ $plperl -> AddReference($postgres );
522+
523+ my $perl_path = $solution -> {options }-> {perl } . ' \lib\CORE\*perl*' ;
524+
525+ # ActivePerl 5.16 provided perl516.lib; 5.18 provided libperl518.a
526+ my @perl_libs =
527+ grep { / perl\d +\. lib$|libperl\d +\. a$ / } glob ($perl_path );
528+ if (@perl_libs == 1)
529+ {
530+ $plperl -> AddLibrary($perl_libs [0]);
531+ }
532+ else
533+ {
534+ die
535+ " could not identify perl library version matching pattern $perl_path \n " ;
536+ }
520537
521538 # Add defines from Perl's ccflags; see PGAC_CHECK_PERL_EMBED_CCFLAGS
522539 my @perl_embed_ccflags ;
523540 foreach my $f (split (" " , $Config {ccflags }))
524541 {
525- if ( $f =~ / ^-D[^_]/
526- || $f =~ / ^-D_USE_32BIT_TIME_T/ )
542+ if ($f =~ / ^-D[^_]/ )
527543 {
528544 $f =~ s /\- D// ;
529545 push (@perl_embed_ccflags , $f );
530546 }
531547 }
532548
533- # Perl versions before 5.13.4 don't provide -D_USE_32BIT_TIME_T
534- # regardless of how they were built. On 32-bit Windows, assume
535- # such a version was built with a pre-MSVC-2005 compiler, and
536- # define the symbol anyway, so that we are compatible if we're
537- # being built with a later MSVC version.
538- push (@perl_embed_ccflags , ' _USE_32BIT_TIME_T' )
539- if $solution -> {platform } eq ' Win32'
540- && $Config {PERL_REVISION } == 5
541- && ($Config {PERL_VERSION } < 13
542- || ( $Config {PERL_VERSION } == 13
543- && $Config {PERL_SUBVERSION } < 4));
544-
545- # Also, a hack to prevent duplicate definitions of uid_t/gid_t
549+ # hack to prevent duplicate definitions of uid_t/gid_t
546550 push (@perl_embed_ccflags , ' PLPERL_HAVE_UID_GID' );
547551
552+ # Windows offers several 32-bit ABIs. Perl is sensitive to
553+ # sizeof(time_t), one of the ABI dimensions. To get 32-bit time_t,
554+ # use "cl -D_USE_32BIT_TIME_T" or plain "gcc". For 64-bit time_t, use
555+ # "gcc -D__MINGW_USE_VC2005_COMPAT" or plain "cl". Before MSVC 2005,
556+ # plain "cl" chose 32-bit time_t. PostgreSQL doesn't support building
557+ # with pre-MSVC-2005 compilers, but it does support linking to Perl
558+ # built with such a compiler. MSVC-built Perl 5.13.4 and later report
559+ # -D_USE_32BIT_TIME_T in $Config{ccflags} if applicable, but
560+ # MinGW-built Perl never reports -D_USE_32BIT_TIME_T despite typically
561+ # needing it. Ignore the $Config{ccflags} opinion about
562+ # -D_USE_32BIT_TIME_T, and use a runtime test to deduce the ABI Perl
563+ # expects. Specifically, test use of PL_modglobal, which maps to a
564+ # PerlInterpreter field whose position depends on sizeof(time_t).
565+ if ($solution -> {platform } eq ' Win32' )
566+ {
567+ my $source_file = ' conftest.c' ;
568+ my $obj = ' conftest.obj' ;
569+ my $exe = ' conftest.exe' ;
570+ my @conftest = ($source_file , $obj , $exe );
571+ push @unlink_on_exit , @conftest ;
572+ unlink $source_file ;
573+ open my $o , ' >' , $source_file
574+ || croak " Could not write to $source_file " ;
575+ print $o '
576+ /* compare to plperl.h */
577+ #define __inline__ __inline
578+ #define PERL_NO_GET_CONTEXT
579+ #include <EXTERN.h>
580+ #include <perl.h>
581+
582+ int
583+ main(int argc, char **argv)
584+ {
585+ int dummy_argc = 1;
586+ char *dummy_argv[1] = {""};
587+ char *dummy_env[1] = {NULL};
588+ static PerlInterpreter *interp;
589+
590+ PERL_SYS_INIT3(&dummy_argc, (char ***) &dummy_argv,
591+ (char ***) &dummy_env);
592+ interp = perl_alloc();
593+ perl_construct(interp);
594+ {
595+ dTHX;
596+ const char key[] = "dummy";
597+
598+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
599+ hv_store(PL_modglobal, key, sizeof(key) - 1, newSViv(1), 0);
600+ return hv_fetch(PL_modglobal, key, sizeof(key) - 1, 0) == NULL;
601+ }
602+ }
603+ ' ;
604+ close $o ;
605+
606+ # Build $source_file with a given #define, and return a true value
607+ # if a run of the resulting binary exits successfully.
608+ my $try_define = sub {
609+ my $define = shift ;
610+
611+ unlink $obj , $exe ;
612+ my @cmd = (
613+ ' cl' ,
614+ ' -I' . $solution -> {options }-> {perl } . ' /lib/CORE' ,
615+ (map { " -D$_ " } @perl_embed_ccflags , $define || ()),
616+ $source_file ,
617+ ' /link' ,
618+ $perl_libs [0]);
619+ my $compile_output = ` @cmd 2>&1` ;
620+ -f $exe || die " Failed to build Perl test:\n $compile_output " ;
621+
622+ {
623+
624+ # Some builds exhibit runtime failure through Perl warning
625+ # 'Can't spawn "conftest.exe"'; supress that.
626+ no warnings;
627+
628+ # Disable error dialog boxes like we do in the postmaster.
629+ # Here, we run code that triggers relevant errors.
630+ use Win32API::File qw( SetErrorMode :SEM_) ;
631+ my $oldmode = SetErrorMode(
632+ SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
633+ system (" .\\ $exe " );
634+ SetErrorMode($oldmode );
635+ }
636+
637+ return !($? >> 8);
638+ };
639+
640+ my $define_32bit_time = ' _USE_32BIT_TIME_T' ;
641+ my $ok_now = $try_define -> (undef );
642+ my $ok_32bit = $try_define -> ($define_32bit_time );
643+ unlink @conftest ;
644+ if (!$ok_now && !$ok_32bit )
645+ {
646+
647+ # Unsupported configuration. Since we used %Config from the
648+ # Perl running the build scripts, this is expected if
649+ # attempting to link with some other Perl.
650+ die " Perl test fails with or without -D$define_32bit_time " ;
651+ }
652+ elsif ($ok_now && $ok_32bit )
653+ {
654+
655+ # Resulting build may work, but it's especially important to
656+ # verify with "vcregress plcheck". A refined test may avoid
657+ # this outcome.
658+ warn " Perl test passes with or without -D$define_32bit_time " ;
659+ }
660+ elsif ($ok_32bit )
661+ {
662+ push (@perl_embed_ccflags , $define_32bit_time );
663+ } # else $ok_now, hence no flag required
664+ }
665+
666+ print " CFLAGS recommended by Perl: $Config {ccflags}\n " ;
667+ print " CFLAGS to compile embedded Perl: " ,
668+ (join ' ' , map { " -D$_ " } @perl_embed_ccflags ), " \n " ;
548669 foreach my $f (@perl_embed_ccflags )
549670 {
550671 $plperl -> AddDefine($f );
@@ -614,20 +735,6 @@ sub mkvcbuild
614735 die ' Failed to create plperl_opmask.h' . " \n " ;
615736 }
616737 }
617- $plperl -> AddReference($postgres );
618- my $perl_path = $solution -> {options }-> {perl } . ' \lib\CORE\*perl*' ;
619- # ActivePerl 5.16 provided perl516.lib; 5.18 provided libperl518.a
620- my @perl_libs =
621- grep { / perl\d +\. lib$|libperl\d +\. a$ / } glob ($perl_path );
622- if (@perl_libs == 1)
623- {
624- $plperl -> AddLibrary($perl_libs [0]);
625- }
626- else
627- {
628- die
629- " could not identify perl library version matching pattern $perl_path \n " ;
630- }
631738
632739 # Add transform module dependent on plperl
633740 my $hstore_plperl = AddTransformModule(
@@ -956,4 +1063,9 @@ sub AdjustModule
9561063 }
9571064}
9581065
1066+ END
1067+ {
1068+ unlink @unlink_on_exit ;
1069+ }
1070+
95910711;
0 commit comments