On 02/05/2014 01:52 PM, Tom Lane wrote: > Craig Ringer <cr...@2ndquadrant.com> writes: >> On 02/05/2014 06:29 AM, Tom Lane wrote: >>> I had been okay with the manual PGDLLIMPORT-sprinkling approach >>> (not happy with it, of course, but prepared to tolerate it) as long >>> as I believed the buildfarm would reliably tell us of the need for >>> it. That assumption has now been conclusively disproven, though. > >> I'm kind of horrified that the dynamic linker doesn't throw its toys >> when it sees this. > > Indeed :-(. > > The truly strange part of this is that it seems that the one Windows > buildfarm member that's telling the truth (or most nearly so, anyway) > is narwhal, which appears to have the oldest and cruftiest toolchain > of the lot. I'd really like to come out the other end of this > investigation with a clear understanding of why the newer toolchains > are failing to report a link problem, and yet not building working > executables.
For MSVC, here's a patch that makes gendef.pl emit DATA annotations for global var exports. Unfortunately, my Windows test machine has been chewing up its file system with memory errors due to a hardware fault, so compilation attempts (of anything) are currently generating internal compiler errors. The output of the script looks correct, but I can't get a good build with or without the patch. I'll try to get my build box working for testing, but have to get on to other things now, so I won't be able to work further on it today. Also attached is a patch to make vcregress.pl produce a better error message when there's no build output, instead of just reporting that ".. is not a recognized internal or external command, operable program, or batch file" -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
>From 8a30733daf62afbb4e01869be1032b80f10f5dae Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Sun, 9 Feb 2014 20:33:56 +0800 Subject: [PATCH 1/2] Emit DATA annotations for global vars in gendef.pl --- src/tools/msvc/gendef.pl | 206 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 155 insertions(+), 51 deletions(-) diff --git a/src/tools/msvc/gendef.pl b/src/tools/msvc/gendef.pl index 8ef0422..c6710ec 100644 --- a/src/tools/msvc/gendef.pl +++ b/src/tools/msvc/gendef.pl @@ -1,72 +1,176 @@ my @def; +use warnings; +use strict; +use 5.8.0; +use List::Util qw(max); + # # Script that generates a .DEF file for all objects in a directory # # src/tools/msvc/gendef.pl # -die "Usage: gendef.pl <modulepath> <platform>\n" - unless (($ARGV[0] =~ /\\([^\\]+$)/) - && ($ARGV[1] == 'Win32' || $ARGV[1] == 'x64')); +sub dumpsyms +{ + my ($objfile, $symfile) = @_; + system("dumpbin /symbols /out:symbols.out $_ >NUL") + && die "Could not call dumpbin"; + rename("symbols.out", $symfile); +} + +# Given a symbol file path, loops over its contents +# and returns a list of symbols of interest as a dictionary +# of 'symbolname' -> symtype, where symtype is: +# +# 0 a CODE symbol, left undecorated in the .DEF +# 1 A DATA symbol, i.e. global var export +# +sub extract_syms +{ + my ($symfile, $def) = @_; + open(F, "<$symfile") || die "Could not open $symfile for $_\n"; + while (<F>) + { + # Expected symbol lines look like: + # + # 0 1 2 3 4 5 6 + # IDX SYMBOL SECT SYMTYPE SYMSTATIC SYMNAME + # ------------------------------------------------------------------------ + # 02E 00000130 SECTA notype External | _standbyState + # 02F 00000009 SECT9 notype Static | _LocalRecoveryInProgress + # 064 00000020 SECTC notype () Static | _XLogCheckBuffer + # 065 00000000 UNDEF notype () External | _BufferGetTag + # + # See http://msdn.microsoft.com/en-us/library/b842y285.aspx + # + # We're not interested in the symbol index or offset. + # + # SECT[ION] is only examined to see whether the symbol is defined in a + # COFF section of the local object file; if UNDEF, it's a symbol to be + # resolved at link time from another object so we can't export it. + # + # SYMTYPE is always notype for C symbols as there's no typeinfo and no + # way to get the symbol type from name (de)mangling. However, we care + # if "notype" is suffixed by "()" or not. The presence of () means the + # symbol is a function, the absence means it isn't. + # + # SYMSTATIC indicates whether it's a compilation-unit local "static" + # symbol ("Static"), or whether it's available for use from other + # compilation units ("External"). We export all symbols that aren't + # static as part of the whole program DLL interface to produce UNIX-like + # default linkage. + # + # SYMNAME is, obviously, the symbol name. The leading underscore indicates + # that the _cdecl calling convention is used. See: + # + # http://www.unixwiz.net/techtips/win32-callconv.html + # http://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified + # + s/notype \(\)/func/g; + s/notype/data/g; + + my @pieces = split; + # Skip file and section headers and other non-symbol entries + next unless defined($pieces[0]) and $pieces[0] =~ /^[A-F0-9]{3,}$/; + # Skip blank symbol names + next unless $pieces[6]; + # Skip externs used from another compilation unit + next if ($pieces[2] eq "UNDEF"); + # Skip static symbols + next unless ($pieces[4] eq "External"); + # Skip some more MSVC-generated crud + next if $pieces[6] =~ /^@/; + next if $pieces[6] =~ /^\(/; + # __real and __xmm are out-of-line floating point literals and + # (for __xmm) their SIMD equivalents. They shouldn't be part + # of the DLL interface. + next if $pieces[6] =~ /^__real/; + next if $pieces[6] =~ /^__xmm/; + # __imp entries are imports from other DLLs, eg __imp__malloc . + # (We should never have one of these that hasn't already been skipped + # by the UNDEF test above, though). + next if $pieces[6] =~ /^__imp/; + # More under-documented internal crud + next if $pieces[6] =~ /NULL_THUNK_DATA$/; + next if $pieces[6] =~ /^__IMPORT_DESCRIPTOR/; + next if $pieces[6] =~ /^__NULL_IMPORT/; + # Skip string literals + next if $pieces[6] =~ /^\?\?_C/; + + # We assume that if a symbol is defined as data, then as a function, + # the linker will reject the binary anyway. So it's OK to just pick + # whatever came last. + $def->{$pieces[6]} = $pieces[3]; + } + close(F); +} + +sub writedef +{ + my ($deffile, $platform, $def) = @_; + open(DEF, ">$deffile") || die "Could not write to $deffile\n"; + print DEF "EXPORTS\n"; + foreach my $f (sort keys %{$def}) + { + my $isdata = $def->{$f} eq 'data'; + # Strip the leading underscore for win32, but not x64 + $f =~ s/^_// + unless ($platform eq "x64"); + + # Emit just the name if it's a function symbol, or emit the name + # decorated with the DATA option for variables. + if ($isdata) { + print DEF " $f DATA\n"; + } else { + print DEF " $f\n"; + } + } + close(DEF); +} + + +sub usage { + die ("Usage: gendef.pl <modulepath> <platform>\n" + . " modulepath: path to dir with obj files, no trailing slash" + . " platform: Win32 | x64"); +} + +usage() + unless + scalar(@ARGV) == 2 + && (($ARGV[0] =~ /\\([^\\]+$)/) + && ($ARGV[1] eq 'Win32' || $ARGV[1] eq 'x64')); my $defname = uc $1; +my $deffile = "$ARGV[0]/$defname.def"; my $platform = $ARGV[1]; -if (-f "$ARGV[0]/$defname.def") +# if the def file exists and is newer than all input object files, skip +# its creation +if ( + -f $deffile + && (-M $deffile > max( map { -M } <$ARGV[0]/*.obj> )) + ) { - print "Not re-generating $defname.DEF, file already exists.\n"; - exit(0); + print "Not re-generating $defname.DEF, file already exists.\n"; + exit(0); } print "Generating $defname.DEF from directory $ARGV[0], platform $platform\n"; +my %def = (); + while (<$ARGV[0]/*.obj>) { - my $symfile = $_; - $symfile =~ s/\.obj$/.sym/i; - print "."; - system("dumpbin /symbols /out:symbols.out $_ >NUL") - && die "Could not call dumpbin"; - open(F, "<symbols.out") || die "Could not open symbols.out for $_\n"; - while (<F>) - { - s/\(\)//g; - my @pieces = split; - next unless $pieces[0] =~ /^[A-F0-9]{3,}$/; - next unless $pieces[6]; - next if ($pieces[2] eq "UNDEF"); - next unless ($pieces[4] eq "External"); - next if $pieces[6] =~ /^@/; - next if $pieces[6] =~ /^\(/; - next if $pieces[6] =~ /^__real/; - next if $pieces[6] =~ /^__imp/; - next if $pieces[6] =~ /^__xmm/; - next if $pieces[6] =~ /NULL_THUNK_DATA$/; - next if $pieces[6] =~ /^__IMPORT_DESCRIPTOR/; - next if $pieces[6] =~ /^__NULL_IMPORT/; - next if $pieces[6] =~ /^\?\?_C/; - - push @def, $pieces[6]; - } - close(F); - rename("symbols.out", $symfile); + my $objfile = $_; + my $symfile = $objfile; + $symfile =~ s/\.obj$/.sym/i; + dumpsyms($objfile, $symfile); + print "."; + extract_syms($symfile, \%def); } print "\n"; -open(DEF, ">$ARGV[0]/$defname.def") || die "Could not write to $defname\n"; -print DEF "EXPORTS\n"; -my $i = 0; -my $last = ""; -foreach my $f (sort @def) -{ - next if ($f eq $last); - $last = $f; - $f =~ s/^_// - unless ($platform eq "x64"); # win64 has new format of exports - $i++; - - # print DEF " $f \@ $i\n"; # ordinaled exports? - print DEF " $f\n"; -} -close(DEF); -print "Generated $i symbols\n"; +writedef($deffile, $platform, \%def); + +print "Generated " . scalar(keys(%def)) . " symbols\n"; -- 1.8.3.1
>From d953d4038dc3de467cef025a45a226a950f45825 Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Mon, 10 Feb 2014 09:22:27 +0800 Subject: [PATCH 2/2] Make vcregress.pl bail out informatively when there's nothing to test --- src/tools/msvc/vcregress.pl | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl index 447b4a1..f8fe152 100644 --- a/src/tools/msvc/vcregress.pl +++ b/src/tools/msvc/vcregress.pl @@ -2,7 +2,14 @@ # src/tools/msvc/vcregress.pl +BEGIN { + chdir "../../.." if (-d "../../../src/tools/msvc"); + push(@INC, "src/tools/msvc"); +} + use strict; +use warnings; +use 5.10.1; our $config; @@ -11,9 +18,9 @@ use File::Copy; use Install qw(Install); + my $startdir = getcwd(); -chdir "../../.." if (-d "../../../src/tools/msvc"); my $topdir = getcwd(); @@ -42,7 +49,16 @@ else } # use a capital C here because config.pl has $config -my $Config = -e "release/postgres/postgres.exe" ? "Release" : "Debug"; +my $Config; +if (-e "Release/postgres/postgres.exe") { + $Config = "Release"; + print("Testing RELEASE build\n"); +} elsif (-e "Debug/postgres/postgres.exe") { + $Config = "Debug"; + print("Testing DEBUG build\n"); +} else { + die("No postgres/postgres.exe found in Release or Debug dirs"); +} copy("$Config/refint/refint.dll", "src/test/regress"); copy("$Config/autoinc/autoinc.dll", "src/test/regress"); -- 1.8.3.1
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers