4 # Package that encapsulates a Visual C++ solution file generation
6 # src/tools/msvc/Solution.pm
15 my $classname = shift;
24 bless($self, $classname);
26 # integer_datetimes is now the default
27 $options->{integer_datetimes} = 1
28 unless exists $options->{integer_datetimes};
29 $options->{float4byval} = 1
30 unless exists $options->{float4byval};
33 if (!($options->{xslt} && $options->{iconv}))
35 die "XML requires both XSLT and ICONV\n";
38 $options->{blocksize} = 8
39 unless $options->{blocksize}; # undef or 0 means default
40 die "Bad blocksize $options->{blocksize}"
41 unless grep { $_ == $options->{blocksize} } (1, 2, 4, 8, 16, 32);
42 $options->{segsize} = 1
43 unless $options->{segsize}; # undef or 0 means default
44 # only allow segsize 1 for now, as we can't do large files yet in windows
45 die "Bad segsize $options->{segsize}"
46 unless $options->{segsize} == 1;
47 $options->{wal_blocksize} = 8
48 unless $options->{wal_blocksize}; # undef or 0 means default
49 die "Bad wal_blocksize $options->{wal_blocksize}"
50 unless grep { $_ == $options->{wal_blocksize} }
51 (1, 2, 4, 8, 16, 32, 64);
52 $options->{wal_segsize} = 16
53 unless $options->{wal_segsize}; # undef or 0 means default
54 die "Bad wal_segsize $options->{wal_segsize}"
55 unless grep { $_ == $options->{wal_segsize} } (1, 2, 4, 8, 16, 32, 64);
57 $self->DeterminePlatform();
66 # Examine CL help output to determine if we are in 32 or 64-bit mode.
67 $self->{platform} = 'Win32';
68 open(P, "cl /? 2>&1 |") || die "cl command not found";
71 if (/^\/favor:<.+AMD64/)
73 $self->{platform} = 'x64';
78 print "Detected hardware platform: $self->{platform}\n";
81 # Return 1 if $oldfile is newer than $newfile, or if $newfile doesn't exist.
82 # Special case - if config.pl has changed, always return 1
85 my ($newfile, $oldfile) = @_;
86 if ( $oldfile ne 'src\tools\msvc\config.pl'
87 && $oldfile ne 'src\tools\msvc\config_default.pl')
90 if (-f 'src\tools\msvc\config.pl')
91 && IsNewer($newfile, 'src\tools\msvc\config.pl');
93 if (-f 'src\tools\msvc\config_default.pl')
94 && IsNewer($newfile, 'src\tools\msvc\config_default.pl');
96 return 1 if (!(-e $newfile));
97 my @nstat = stat($newfile);
98 my @ostat = stat($oldfile);
99 return 1 if ($nstat[9] < $ostat[9]);
103 # Copy a file, *not* preserving date. Only works for text files.
106 my ($src, $dest) = @_;
107 open(I, $src) || croak "Could not open $src";
108 open(O, ">$dest") || croak "Could not open $dest";
120 my $bits = $self->{platform} eq 'Win32' ? 32 : 64;
122 # Parse configure.in to get version numbers
123 open(C, "configure.in")
124 || confess("Could not open configure.in for reading\n");
127 if (/^AC_INIT\(\[PostgreSQL\], \[([^\]]+)\]/)
129 $self->{strver} = $1;
130 if ($self->{strver} !~ /^(\d+)\.(\d+)(?:\.(\d+))?/)
132 confess "Bad format of version: $self->{strver}\n";
134 $self->{numver} = sprintf("%d%02d%02d", $1, $2, $3 ? $3 : 0);
135 $self->{majorver} = sprintf("%d.%d", $1, $2);
139 confess "Unable to parse configure.in for all variables!"
140 if ($self->{strver} eq '' || $self->{numver} eq '');
143 "src\\include\\pg_config_os.h", "src\\include\\port\\win32.h"))
145 print "Copying pg_config_os.h...\n";
146 copyFile("src\\include\\port\\win32.h",
147 "src\\include\\pg_config_os.h");
151 "src\\include\\pg_config.h", "src\\include\\pg_config.h.win32"))
153 print "Generating pg_config.h...\n";
154 open(I, "src\\include\\pg_config.h.win32")
155 || confess "Could not open pg_config.h.win32\n";
156 open(O, ">src\\include\\pg_config.h")
157 || confess "Could not write to pg_config.h\n";
160 s{PG_VERSION "[^"]+"}{PG_VERSION "$self->{strver}"};
161 s{PG_VERSION_NUM \d+}{PG_VERSION_NUM $self->{numver}};
162 s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY(z)\n#define PG_VERSION_STR "PostgreSQL $self->{strver}, compiled by Visual C++ build " __STRINGIFY2(_MSC_VER) ", $bits-bit"};
165 print O "#define PG_MAJORVERSION \"$self->{majorver}\"\n";
166 print O "#define LOCALEDIR \"/share/locale\"\n"
167 if ($self->{options}->{nls});
168 print O "/* defines added by config steps */\n";
169 print O "#ifndef IGNORE_CONFIGURED_SETTINGS\n";
170 print O "#define USE_ASSERT_CHECKING 1\n"
171 if ($self->{options}->{asserts});
172 print O "#define USE_INTEGER_DATETIMES 1\n"
173 if ($self->{options}->{integer_datetimes});
174 print O "#define USE_LDAP 1\n" if ($self->{options}->{ldap});
175 print O "#define HAVE_LIBZ 1\n" if ($self->{options}->{zlib});
176 print O "#define USE_SSL 1\n" if ($self->{options}->{openssl});
177 print O "#define ENABLE_NLS 1\n" if ($self->{options}->{nls});
179 print O "#define BLCKSZ ", 1024 * $self->{options}->{blocksize}, "\n";
180 print O "#define RELSEG_SIZE ",
181 (1024 / $self->{options}->{blocksize}) *
182 $self->{options}->{segsize} *
184 print O "#define XLOG_BLCKSZ ",
185 1024 * $self->{options}->{wal_blocksize}, "\n";
186 print O "#define XLOG_SEG_SIZE (", $self->{options}->{wal_segsize},
189 if ($self->{options}->{float4byval})
191 print O "#define USE_FLOAT4_BYVAL 1\n";
192 print O "#define FLOAT4PASSBYVAL true\n";
196 print O "#define FLOAT4PASSBYVAL false\n";
198 if ($self->{options}->{float8byval})
200 print O "#define USE_FLOAT8_BYVAL 1\n";
201 print O "#define FLOAT8PASSBYVAL true\n";
205 print O "#define FLOAT8PASSBYVAL false\n";
208 if ($self->{options}->{uuid})
210 print O "#define HAVE_UUID_H\n";
212 if ($self->{options}->{xml})
214 print O "#define HAVE_LIBXML2\n";
215 print O "#define USE_LIBXML\n";
217 if ($self->{options}->{xslt})
219 print O "#define HAVE_LIBXSLT\n";
220 print O "#define USE_LIBXSLT\n";
222 if ($self->{options}->{gss})
224 print O "#define ENABLE_GSS 1\n";
226 if (my $port = $self->{options}->{"--with-pgport"})
228 print O "#undef DEF_PGPORT\n";
229 print O "#undef DEF_PGPORT_STR\n";
230 print O "#define DEF_PGPORT $port\n";
231 print O "#define DEF_PGPORT_STR \"$port\"\n";
233 print O "#define VAL_CONFIGURE \""
234 . $self->GetFakeConfigure() . "\"\n";
235 print O "#endif /* IGNORE_CONFIGURED_SETTINGS */\n";
241 "src\\include\\pg_config_ext.h",
242 "src\\include\\pg_config_ext.h.win32"))
244 print "Copying pg_config_ext.h...\n";
246 "src\\include\\pg_config_ext.h.win32",
247 "src\\include\\pg_config_ext.h");
250 $self->GenerateDefFile(
251 "src\\interfaces\\libpq\\libpqdll.def",
252 "src\\interfaces\\libpq\\exports.txt",
254 $self->GenerateDefFile(
255 "src\\interfaces\\ecpg\\ecpglib\\ecpglib.def",
256 "src\\interfaces\\ecpg\\ecpglib\\exports.txt",
258 $self->GenerateDefFile(
259 "src\\interfaces\\ecpg\\compatlib\\compatlib.def",
260 "src\\interfaces\\ecpg\\compatlib\\exports.txt",
262 $self->GenerateDefFile(
263 "src\\interfaces\\ecpg\\pgtypeslib\\pgtypeslib.def",
264 "src\\interfaces\\ecpg\\pgtypeslib\\exports.txt",
268 'src\backend\utils\fmgrtab.c', 'src\include\catalog\pg_proc.h'))
270 print "Generating fmgrtab.c and fmgroids.h...\n";
271 chdir('src\backend\utils');
273 "perl -I ../catalog Gen_fmgrtab.pl ../../../src/include/catalog/pg_proc.h");
277 'src\include\utils\fmgroids.h',
278 'src\backend\utils\fmgroids.h'))
280 copyFile('src\backend\utils\fmgroids.h',
281 'src\include\utils\fmgroids.h');
284 if (IsNewer('src\include\utils\probes.h', 'src\backend\utils\probes.d'))
286 print "Generating probes.h...\n";
288 'psed -f src\backend\utils\Gen_dummy_probes.sed src\backend\utils\probes.d > src\include\utils\probes.h'
292 if ($self->{options}->{python}
294 'src\pl\plpython\spiexceptions.h',
295 'src\include\backend\errcodes.txt'))
297 print "Generating spiexceptions.h...\n";
299 'perl src\pl\plpython\generate-spiexceptions.pl src\backend\utils\errcodes.txt > src\pl\plpython\spiexceptions.h'
304 'src\include\utils\errcodes.h',
305 'src\backend\utils\errcodes.txt'))
307 print "Generating errcodes.h...\n";
309 'perl src\backend\utils\generate-errcodes.pl src\backend\utils\errcodes.txt > src\backend\utils\errcodes.h'
311 copyFile('src\backend\utils\errcodes.h',
312 'src\include\utils\errcodes.h');
316 'src\pl\plpgsql\src\plerrcodes.h',
317 'src\backend\utils\errcodes.txt'))
319 print "Generating plerrcodes.h...\n";
321 'perl src\pl\plpgsql\src\generate-plerrcodes.pl src\backend\utils\errcodes.txt > src\pl\plpgsql\src\plerrcodes.h'
326 'src\backend\utils\sort\qsort_tuple.c',
327 'src\backend\utils\sort\gen_qsort_tuple.pl'))
329 print "Generating qsort_tuple.c...\n";
331 'perl src\backend\utils\sort\gen_qsort_tuple.pl > src\backend\utils\sort\qsort_tuple.c'
336 'src\interfaces\libpq\libpq.rc',
337 'src\interfaces\libpq\libpq.rc.in'))
339 print "Generating libpq.rc...\n";
340 my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
342 my $d = ($year - 100) . "$yday";
343 open(I, '<', 'src\interfaces\libpq\libpq.rc.in')
344 || confess "Could not open libpq.rc.in";
345 open(O, '>', 'src\interfaces\libpq\libpq.rc')
346 || confess "Could not open libpq.rc";
349 s/(VERSION.*),0/$1,$d/;
356 if (IsNewer('src\bin\psql\sql_help.h', 'src\bin\psql\create_help.pl'))
358 print "Generating sql_help.h...\n";
359 chdir('src\bin\psql');
360 system("perl create_help.pl ../../../doc/src/sgml/ref sql_help");
365 'src\interfaces\ecpg\preproc\preproc.y',
366 'src\backend\parser\gram.y'))
368 print "Generating preproc.y...\n";
369 chdir('src\interfaces\ecpg\preproc');
370 system('perl parse.pl < ..\..\..\backend\parser\gram.y > preproc.y');
371 chdir('..\..\..\..');
375 'src\interfaces\ecpg\include\ecpg_config.h',
376 'src\interfaces\ecpg\include\ecpg_config.h.in'))
378 print "Generating ecpg_config.h...\n";
379 open(O, '>', 'src\interfaces\ecpg\include\ecpg_config.h')
380 || confess "Could not open ecpg_config.h";
382 #if (_MSC_VER > 1200)
383 #define HAVE_LONG_LONG_INT_64
384 #define ENABLE_THREAD_SAFETY 1
386 print O "#define USE_INTEGER_DATETIMES 1\n"
387 if ($self->{options}->{integer_datetimes});
392 unless (-f "src\\port\\pg_config_paths.h")
394 print "Generating pg_config_paths.h...\n";
395 open(O, '>', 'src\port\pg_config_paths.h')
396 || confess "Could not open pg_config_paths.h";
398 #define PGBINDIR "/bin"
399 #define PGSHAREDIR "/share"
400 #define SYSCONFDIR "/etc"
401 #define INCLUDEDIR "/include"
402 #define PKGINCLUDEDIR "/include"
403 #define INCLUDEDIRSERVER "/include/server"
404 #define LIBDIR "/lib"
405 #define PKGLIBDIR "/lib"
406 #define LOCALEDIR "/share/locale"
407 #define DOCDIR "/doc"
408 #define HTMLDIR "/doc"
409 #define MANDIR "/man"
414 my $mf = Project::read_file('src\backend\catalog\Makefile');
415 $mf =~ s{\\s*[\r\n]+}{}mg;
416 $mf =~ /^POSTGRES_BKI_SRCS\s*:?=[^,]+,(.*)\)$/gm
417 || croak "Could not find POSTGRES_BKI_SRCS in Makefile\n";
418 my @allbki = split /\s+/, $1;
419 foreach my $bki (@allbki)
423 'src/backend/catalog/postgres.bki',
424 "src/include/catalog/$bki"))
426 print "Generating postgres.bki and schemapg.h...\n";
427 chdir('src\backend\catalog');
428 my $bki_srcs = join(' ../../../src/include/catalog/', @allbki);
430 "perl genbki.pl -I../../../src/include/catalog --set-version=$self->{majorver} $bki_srcs"
434 'src\backend\catalog\schemapg.h',
435 'src\include\catalog\schemapg.h');
440 open(O, ">doc/src/sgml/version.sgml")
441 || croak "Could not write to version.sgml\n";
443 <!ENTITY version "$self->{strver}">
444 <!ENTITY majorversion "$self->{majorver}">
451 my ($self, $deffile, $txtfile, $libname) = @_;
453 if (IsNewer($deffile, $txtfile))
455 print "Generating $deffile...\n";
456 open(I, $txtfile) || confess("Could not open $txtfile\n");
457 open(O, ">$deffile") || confess("Could not open $deffile\n");
458 print O "LIBRARY $libname\nEXPORTS\n";
464 print O " $f @ $o\n";
473 my ($self, $name, $type, $folder, $initialdir) = @_;
476 VSObjectFactory::CreateProject($self->{vcver}, $name, $type, $self);
477 push @{ $self->{projects}->{$folder} }, $proj;
478 $proj->AddDir($initialdir) if ($initialdir);
479 if ($self->{options}->{zlib})
481 $proj->AddIncludeDir($self->{options}->{zlib} . '\include');
482 $proj->AddLibrary($self->{options}->{zlib} . '\lib\zdll.lib');
484 if ($self->{options}->{openssl})
486 $proj->AddIncludeDir($self->{options}->{openssl} . '\include');
488 $self->{options}->{openssl} . '\lib\VC\ssleay32.lib', 1);
490 $self->{options}->{openssl} . '\lib\VC\libeay32.lib', 1);
492 if ($self->{options}->{nls})
494 $proj->AddIncludeDir($self->{options}->{nls} . '\include');
495 $proj->AddLibrary($self->{options}->{nls} . '\lib\libintl.lib');
497 if ($self->{options}->{gss})
499 $proj->AddIncludeDir($self->{options}->{gss} . '\inc\krb5');
500 $proj->AddLibrary($self->{options}->{gss} . '\lib\i386\krb5_32.lib');
502 $self->{options}->{gss} . '\lib\i386\comerr32.lib');
504 $self->{options}->{gss} . '\lib\i386\gssapi32.lib');
506 if ($self->{options}->{iconv})
508 $proj->AddIncludeDir($self->{options}->{iconv} . '\include');
509 $proj->AddLibrary($self->{options}->{iconv} . '\lib\iconv.lib');
511 if ($self->{options}->{xml})
513 $proj->AddIncludeDir($self->{options}->{xml} . '\include');
514 $proj->AddLibrary($self->{options}->{xml} . '\lib\libxml2.lib');
516 if ($self->{options}->{xslt})
518 $proj->AddIncludeDir($self->{options}->{xslt} . '\include');
519 $proj->AddLibrary($self->{options}->{xslt} . '\lib\libxslt.lib');
529 $self->GenerateFiles();
530 foreach my $fld (keys %{ $self->{projects} })
532 foreach my $proj (@{ $self->{projects}->{$fld} })
538 open(SLN, ">pgsql.sln") || croak "Could not write to pgsql.sln\n";
540 Microsoft Visual Studio Solution File, Format Version $self->{solutionFileVersion}
541 # $self->{visualStudioName}
544 foreach my $fld (keys %{ $self->{projects} })
546 foreach my $proj (@{ $self->{projects}->{$fld} })
549 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "$proj->{name}", "$proj->{name}$proj->{filenameExtension}", "$proj->{guid}"
555 $flduid{$fld} = Win32::GuidGen();
557 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "$fld", "$fld", "$flduid{$fld}"
565 GlobalSection(SolutionConfigurationPlatforms) = preSolution
566 Debug|$self->{platform}= Debug|$self->{platform}
567 Release|$self->{platform} = Release|$self->{platform}
569 GlobalSection(ProjectConfigurationPlatforms) = postSolution
572 foreach my $fld (keys %{ $self->{projects} })
574 foreach my $proj (@{ $self->{projects}->{$fld} })
577 $proj->{guid}.Debug|$self->{platform}.ActiveCfg = Debug|$self->{platform}
578 $proj->{guid}.Debug|$self->{platform}.Build.0 = Debug|$self->{platform}
579 $proj->{guid}.Release|$self->{platform}.ActiveCfg = Release|$self->{platform}
580 $proj->{guid}.Release|$self->{platform}.Build.0 = Release|$self->{platform}
587 GlobalSection(SolutionProperties) = preSolution
588 HideSolutionNode = FALSE
590 GlobalSection(NestedProjects) = preSolution
593 foreach my $fld (keys %{ $self->{projects} })
595 next if ($fld eq "");
596 foreach my $proj (@{ $self->{projects}->{$fld} })
598 print SLN "\t\t$proj->{guid} = $flduid{$fld}\n";
613 my $cfg = '--enable-thread-safety';
614 $cfg .= ' --enable-cassert' if ($self->{options}->{asserts});
615 $cfg .= ' --enable-integer-datetimes'
616 if ($self->{options}->{integer_datetimes});
617 $cfg .= ' --enable-nls' if ($self->{options}->{nls});
618 $cfg .= ' --with-ldap' if ($self->{options}->{ldap});
619 $cfg .= ' --without-zlib' unless ($self->{options}->{zlib});
620 $cfg .= ' --with-openssl' if ($self->{options}->{ssl});
621 $cfg .= ' --with-ossp-uuid' if ($self->{options}->{uuid});
622 $cfg .= ' --with-libxml' if ($self->{options}->{xml});
623 $cfg .= ' --with-libxslt' if ($self->{options}->{xslt});
624 $cfg .= ' --with-gssapi' if ($self->{options}->{gss});
625 $cfg .= ' --with-tcl' if ($self->{options}->{tcl});
626 $cfg .= ' --with-perl' if ($self->{options}->{perl});
627 $cfg .= ' --with-python' if ($self->{options}->{python});
632 package VS2005Solution;
635 # Package that encapsulates a Visual Studio 2005 solution file
640 use base qw(Solution);
644 my $classname = shift;
645 my $self = $classname->SUPER::_new(@_);
646 bless($self, $classname);
648 $self->{solutionFileVersion} = '9.00';
649 $self->{vcver} = '8.00';
650 $self->{visualStudioName} = 'Visual Studio 2005';
655 package VS2008Solution;
658 # Package that encapsulates a Visual Studio 2008 solution file
663 use base qw(Solution);
667 my $classname = shift;
668 my $self = $classname->SUPER::_new(@_);
669 bless($self, $classname);
671 $self->{solutionFileVersion} = '10.00';
672 $self->{vcver} = '9.00';
673 $self->{visualStudioName} = 'Visual Studio 2008';
678 package VS2010Solution;
681 # Package that encapsulates a Visual Studio 2010 solution file
687 use base qw(Solution);
691 my $classname = shift;
692 my $self = $classname->SUPER::_new(@_);
693 bless($self, $classname);
695 $self->{solutionFileVersion} = '11.00';
696 $self->{vcver} = '10.00';
697 $self->{visualStudioName} = 'Visual Studio 2010';
702 package VS2012Solution;
705 # Package that encapsulates a Visual Studio 2012 solution file
711 use base qw(Solution);
715 my $classname = shift;
716 my $self = $classname->SUPER::_new(@_);
717 bless($self, $classname);
719 $self->{solutionFileVersion} = '12.00';
720 $self->{vcver} = '11.00';
721 $self->{visualStudioName} = 'Visual Studio 2012';