1package Solution; 2 3# 4# Package that encapsulates a Visual C++ solution file generation 5# 6# src/tools/msvc/Solution.pm 7# 8use Carp; 9use strict; 10use warnings; 11use VSObjectFactory; 12 13sub _new 14{ 15 my $classname = shift; 16 my $options = shift; 17 my $self = { 18 projects => {}, 19 options => $options, 20 numver => '', 21 strver => '', 22 VisualStudioVersion => undef, 23 MinimumVisualStudioVersion => undef, 24 vcver => undef, 25 platform => undef, }; 26 bless($self, $classname); 27 28 $self->DeterminePlatform(); 29 my $bits = $self->{platform} eq 'Win32' ? 32 : 64; 30 31 # integer_datetimes is now the default 32 $options->{integer_datetimes} = 1 33 unless exists $options->{integer_datetimes}; 34 $options->{float4byval} = 1 35 unless exists $options->{float4byval}; 36 $options->{float8byval} = ($bits == 64) 37 unless exists $options->{float8byval}; 38 die "float8byval not permitted on 32 bit platforms" 39 if $options->{float8byval} && $bits == 32; 40 if ($options->{xml}) 41 { 42 if (!($options->{xslt} && $options->{iconv})) 43 { 44 die "XML requires both XSLT and ICONV\n"; 45 } 46 } 47 $options->{blocksize} = 8 48 unless $options->{blocksize}; # undef or 0 means default 49 die "Bad blocksize $options->{blocksize}" 50 unless grep { $_ == $options->{blocksize} } (1, 2, 4, 8, 16, 32); 51 $options->{segsize} = 1 52 unless $options->{segsize}; # undef or 0 means default 53 # only allow segsize 1 for now, as we can't do large files yet in windows 54 die "Bad segsize $options->{segsize}" 55 unless $options->{segsize} == 1; 56 $options->{wal_blocksize} = 8 57 unless $options->{wal_blocksize}; # undef or 0 means default 58 die "Bad wal_blocksize $options->{wal_blocksize}" 59 unless grep { $_ == $options->{wal_blocksize} } 60 (1, 2, 4, 8, 16, 32, 64); 61 $options->{wal_segsize} = 16 62 unless $options->{wal_segsize}; # undef or 0 means default 63 die "Bad wal_segsize $options->{wal_segsize}" 64 unless grep { $_ == $options->{wal_segsize} } (1, 2, 4, 8, 16, 32, 64); 65 66 return $self; 67} 68 69sub GetAdditionalHeaders 70{ 71 return ''; 72} 73 74sub DeterminePlatform 75{ 76 my $self = shift; 77 78 # Examine CL help output to determine if we are in 32 or 64-bit mode. 79 my $output = `cl /? 2>&1`; 80 $? >> 8 == 0 or die "cl command not found"; 81 $self->{platform} = ($output =~ /^\/favor:<.+AMD64/m) ? 'x64' : 'Win32'; 82 print "Detected hardware platform: $self->{platform}\n"; 83} 84 85# Return 1 if $oldfile is newer than $newfile, or if $newfile doesn't exist. 86# Special case - if config.pl has changed, always return 1 87sub IsNewer 88{ 89 my ($newfile, $oldfile) = @_; 90 -e $oldfile or warn "source file \"$oldfile\" does not exist"; 91 if ( $oldfile ne 'src/tools/msvc/config.pl' 92 && $oldfile ne 'src/tools/msvc/config_default.pl') 93 { 94 return 1 95 if (-f 'src/tools/msvc/config.pl') 96 && IsNewer($newfile, 'src/tools/msvc/config.pl'); 97 return 1 98 if (-f 'src/tools/msvc/config_default.pl') 99 && IsNewer($newfile, 'src/tools/msvc/config_default.pl'); 100 } 101 return 1 if (!(-e $newfile)); 102 my @nstat = stat($newfile); 103 my @ostat = stat($oldfile); 104 return 1 if ($nstat[9] < $ostat[9]); 105 return 0; 106} 107 108# Copy a file, *not* preserving date. Only works for text files. 109sub copyFile 110{ 111 my ($src, $dest) = @_; 112 open(I, $src) || croak "Could not open $src"; 113 open(O, ">$dest") || croak "Could not open $dest"; 114 while (<I>) 115 { 116 print O; 117 } 118 close(I); 119 close(O); 120} 121 122# Fetch version of OpenSSL based on a parsing of the command shipped with 123# the installer this build is linking to. This returns as result an array 124# made of the three first digits of the OpenSSL version, which is enough 125# to decide which options to apply depending on the version of OpenSSL 126# linking with. 127sub GetOpenSSLVersion 128{ 129 my $self = shift; 130 131 # Attempt to get OpenSSL version and location. This assumes that 132 # openssl.exe is in the specified directory. 133 # Quote the .exe name in case it has spaces 134 my $opensslcmd = 135 qq("$self->{options}->{openssl}\\bin\\openssl.exe" version 2>&1); 136 my $sslout = `$opensslcmd`; 137 138 $? >> 8 == 0 139 or croak 140 "Unable to determine OpenSSL version: The openssl.exe command wasn't found."; 141 142 if ($sslout =~ /(\d+)\.(\d+)\.(\d+)(\D)/m) 143 { 144 return ($1, $2, $3); 145 } 146 147 croak 148 "Unable to determine OpenSSL version: The openssl.exe version could not be determined."; 149} 150 151sub GenerateFiles 152{ 153 my $self = shift; 154 my $bits = $self->{platform} eq 'Win32' ? 32 : 64; 155 156 # Parse configure.in to get version numbers 157 open(C, "configure.in") 158 || confess("Could not open configure.in for reading\n"); 159 while (<C>) 160 { 161 if (/^AC_INIT\(\[PostgreSQL\], \[([^\]]+)\]/) 162 { 163 $self->{strver} = $1; 164 if ($self->{strver} !~ /^(\d+)\.(\d+)(?:\.(\d+))?/) 165 { 166 confess "Bad format of version: $self->{strver}\n"; 167 } 168 $self->{numver} = sprintf("%d%02d%02d", $1, $2, $3 ? $3 : 0); 169 $self->{majorver} = sprintf("%d.%d", $1, $2); 170 } 171 } 172 close(C); 173 confess "Unable to parse configure.in for all variables!" 174 if ($self->{strver} eq '' || $self->{numver} eq ''); 175 176 if (IsNewer("src/include/pg_config_os.h", "src/include/port/win32.h")) 177 { 178 print "Copying pg_config_os.h...\n"; 179 copyFile("src/include/port/win32.h", "src/include/pg_config_os.h"); 180 } 181 182 if (IsNewer("src/include/pg_config.h", "src/include/pg_config.h.win32")) 183 { 184 print "Generating pg_config.h...\n"; 185 open(I, "src/include/pg_config.h.win32") 186 || confess "Could not open pg_config.h.win32\n"; 187 open(O, ">src/include/pg_config.h") 188 || confess "Could not write to pg_config.h\n"; 189 my $extraver = $self->{options}->{extraver}; 190 $extraver = '' unless defined $extraver; 191 while (<I>) 192 { 193 s{PG_VERSION "[^"]+"}{PG_VERSION "$self->{strver}$extraver"}; 194 s{PG_VERSION_NUM \d+}{PG_VERSION_NUM $self->{numver}}; 195s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY(z)\n#define PG_VERSION_STR "PostgreSQL $self->{strver}$extraver, compiled by Visual C++ build " __STRINGIFY2(_MSC_VER) ", $bits-bit"}; 196 print O; 197 } 198 print O "#define PG_MAJORVERSION \"$self->{majorver}\"\n"; 199 print O "#define LOCALEDIR \"/share/locale\"\n" 200 if ($self->{options}->{nls}); 201 print O "/* defines added by config steps */\n"; 202 print O "#ifndef IGNORE_CONFIGURED_SETTINGS\n"; 203 print O "#define USE_ASSERT_CHECKING 1\n" 204 if ($self->{options}->{asserts}); 205 print O "#define USE_INTEGER_DATETIMES 1\n" 206 if ($self->{options}->{integer_datetimes}); 207 print O "#define USE_LDAP 1\n" if ($self->{options}->{ldap}); 208 print O "#define HAVE_LIBZ 1\n" if ($self->{options}->{zlib}); 209 print O "#define ENABLE_NLS 1\n" if ($self->{options}->{nls}); 210 211 print O "#define BLCKSZ ", 1024 * $self->{options}->{blocksize}, "\n"; 212 print O "#define RELSEG_SIZE ", 213 (1024 / $self->{options}->{blocksize}) * 214 $self->{options}->{segsize} * 215 1024, "\n"; 216 print O "#define XLOG_BLCKSZ ", 217 1024 * $self->{options}->{wal_blocksize}, "\n"; 218 print O "#define XLOG_SEG_SIZE (", $self->{options}->{wal_segsize}, 219 " * 1024 * 1024)\n"; 220 221 if ($self->{options}->{float4byval}) 222 { 223 print O "#define USE_FLOAT4_BYVAL 1\n"; 224 print O "#define FLOAT4PASSBYVAL true\n"; 225 } 226 else 227 { 228 print O "#define FLOAT4PASSBYVAL false\n"; 229 } 230 if ($self->{options}->{float8byval}) 231 { 232 print O "#define USE_FLOAT8_BYVAL 1\n"; 233 print O "#define FLOAT8PASSBYVAL true\n"; 234 } 235 else 236 { 237 print O "#define FLOAT8PASSBYVAL false\n"; 238 } 239 240 if ($self->{options}->{uuid}) 241 { 242 print O "#define HAVE_UUID_OSSP\n"; 243 print O "#define HAVE_UUID_H\n"; 244 } 245 if ($self->{options}->{xml}) 246 { 247 print O "#define HAVE_LIBXML2\n"; 248 print O "#define USE_LIBXML\n"; 249 } 250 if ($self->{options}->{xslt}) 251 { 252 print O "#define HAVE_LIBXSLT\n"; 253 print O "#define USE_LIBXSLT\n"; 254 } 255 if ($self->{options}->{gss}) 256 { 257 print O "#define ENABLE_GSS 1\n"; 258 } 259 if ($self->{options}->{openssl}) 260 { 261 print O "#define USE_OPENSSL 1\n"; 262 263 my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion(); 264 265 # More symbols are needed with OpenSSL 1.1.0 and above. 266 if ( ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0') 267 || ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0')) 268 { 269 print O "#define HAVE_ASN1_STRING_GET0_DATA 1\n"; 270 print O "#define HAVE_BIO_GET_DATA 1\n"; 271 print O "#define HAVE_BIO_METH_NEW 1\n"; 272 print O "#define HAVE_OPENSSL_INIT_SSL 1\n"; 273 print O "#define HAVE_RAND_OPENSSL 1\n"; 274 } 275 } 276 if (my $port = $self->{options}->{"--with-pgport"}) 277 { 278 print O "#undef DEF_PGPORT\n"; 279 print O "#undef DEF_PGPORT_STR\n"; 280 print O "#define DEF_PGPORT $port\n"; 281 print O "#define DEF_PGPORT_STR \"$port\"\n"; 282 } 283 print O "#define VAL_CONFIGURE \"" 284 . $self->GetFakeConfigure() . "\"\n"; 285 print O "#endif /* IGNORE_CONFIGURED_SETTINGS */\n"; 286 close(O); 287 close(I); 288 } 289 290 if (IsNewer( 291 "src/include/pg_config_ext.h", 292 "src/include/pg_config_ext.h.win32")) 293 { 294 print "Copying pg_config_ext.h...\n"; 295 copyFile( 296 "src/include/pg_config_ext.h.win32", 297 "src/include/pg_config_ext.h"); 298 } 299 300 $self->GenerateDefFile( 301 "src/interfaces/libpq/libpqdll.def", 302 "src/interfaces/libpq/exports.txt", 303 "LIBPQ"); 304 $self->GenerateDefFile( 305 "src/interfaces/ecpg/ecpglib/ecpglib.def", 306 "src/interfaces/ecpg/ecpglib/exports.txt", 307 "LIBECPG"); 308 $self->GenerateDefFile( 309 "src/interfaces/ecpg/compatlib/compatlib.def", 310 "src/interfaces/ecpg/compatlib/exports.txt", 311 "LIBECPG_COMPAT"); 312 $self->GenerateDefFile( 313 "src/interfaces/ecpg/pgtypeslib/pgtypeslib.def", 314 "src/interfaces/ecpg/pgtypeslib/exports.txt", 315 "LIBPGTYPES"); 316 317 if (IsNewer( 318 'src/backend/utils/fmgrtab.c', 'src/include/catalog/pg_proc.h')) 319 { 320 print "Generating fmgrtab.c and fmgroids.h...\n"; 321 chdir('src/backend/utils'); 322 system( 323"perl -I ../catalog Gen_fmgrtab.pl ../../../src/include/catalog/pg_proc.h"); 324 chdir('../../..'); 325 } 326 if (IsNewer( 327 'src/include/utils/fmgroids.h', 328 'src/backend/utils/fmgroids.h')) 329 { 330 copyFile('src/backend/utils/fmgroids.h', 331 'src/include/utils/fmgroids.h'); 332 } 333 334 if (IsNewer( 335 'src/include/storage/lwlocknames.h', 336 'src/backend/storage/lmgr/lwlocknames.txt')) 337 { 338 print "Generating lwlocknames.c and lwlocknames.h...\n"; 339 chdir('src/backend/storage/lmgr'); 340 system('perl generate-lwlocknames.pl lwlocknames.txt'); 341 chdir('../../../..'); 342 } 343 if (IsNewer( 344 'src/include/storage/lwlocknames.h', 345 'src/backend/storage/lmgr/lwlocknames.h')) 346 { 347 copyFile( 348 'src/backend/storage/lmgr/lwlocknames.h', 349 'src/include/storage/lwlocknames.h'); 350 } 351 352 if (IsNewer( 353 'src/include/dynloader.h', 'src/backend/port/dynloader/win32.h')) 354 { 355 copyFile('src/backend/port/dynloader/win32.h', 356 'src/include/dynloader.h'); 357 } 358 359 if (IsNewer('src/include/utils/probes.h', 'src/backend/utils/probes.d')) 360 { 361 print "Generating probes.h...\n"; 362 system( 363'perl src/backend/utils/Gen_dummy_probes.pl src/backend/utils/probes.d > src/include/utils/probes.h' 364 ); 365 } 366 367 if ($self->{options}->{python} 368 && IsNewer( 369 'src/pl/plpython/spiexceptions.h', 370 'src/backend/utils/errcodes.txt')) 371 { 372 print "Generating spiexceptions.h...\n"; 373 system( 374'perl src/pl/plpython/generate-spiexceptions.pl src/backend/utils/errcodes.txt > src/pl/plpython/spiexceptions.h' 375 ); 376 } 377 378 if (IsNewer( 379 'src/include/utils/errcodes.h', 380 'src/backend/utils/errcodes.txt')) 381 { 382 print "Generating errcodes.h...\n"; 383 system( 384'perl src/backend/utils/generate-errcodes.pl src/backend/utils/errcodes.txt > src/backend/utils/errcodes.h' 385 ); 386 copyFile('src/backend/utils/errcodes.h', 387 'src/include/utils/errcodes.h'); 388 } 389 390 if (IsNewer( 391 'src/pl/plpgsql/src/plerrcodes.h', 392 'src/backend/utils/errcodes.txt')) 393 { 394 print "Generating plerrcodes.h...\n"; 395 system( 396'perl src/pl/plpgsql/src/generate-plerrcodes.pl src/backend/utils/errcodes.txt > src/pl/plpgsql/src/plerrcodes.h' 397 ); 398 } 399 400 if ($self->{options}->{tcl} 401 && IsNewer( 402 'src/pl/tcl/pltclerrcodes.h', 'src/backend/utils/errcodes.txt')) 403 { 404 print "Generating pltclerrcodes.h...\n"; 405 system( 406'perl src/pl/tcl/generate-pltclerrcodes.pl src/backend/utils/errcodes.txt > src/pl/tcl/pltclerrcodes.h' 407 ); 408 } 409 410 if (IsNewer( 411 'src/backend/utils/sort/qsort_tuple.c', 412 'src/backend/utils/sort/gen_qsort_tuple.pl')) 413 { 414 print "Generating qsort_tuple.c...\n"; 415 system( 416'perl src/backend/utils/sort/gen_qsort_tuple.pl > src/backend/utils/sort/qsort_tuple.c' 417 ); 418 } 419 420 if (IsNewer( 421 'src/interfaces/libpq/libpq.rc', 422 'src/interfaces/libpq/libpq.rc.in')) 423 { 424 print "Generating libpq.rc...\n"; 425 my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = 426 localtime(time); 427 my $d = ($year - 100) . "$yday"; 428 open(I, '<', 'src/interfaces/libpq/libpq.rc.in') 429 || confess "Could not open libpq.rc.in"; 430 open(O, '>', 'src/interfaces/libpq/libpq.rc') 431 || confess "Could not open libpq.rc"; 432 while (<I>) 433 { 434 s/(VERSION.*),0/$1,$d/; 435 print O; 436 } 437 close(I); 438 close(O); 439 } 440 441 if (IsNewer('src/bin/psql/sql_help.h', 'src/bin/psql/create_help.pl')) 442 { 443 print "Generating sql_help.h...\n"; 444 chdir('src/bin/psql'); 445 system("perl create_help.pl ../../../doc/src/sgml/ref sql_help"); 446 chdir('../../..'); 447 } 448 449 if (IsNewer( 450 'src/interfaces/ecpg/preproc/preproc.y', 451 'src/backend/parser/gram.y')) 452 { 453 print "Generating preproc.y...\n"; 454 chdir('src/interfaces/ecpg/preproc'); 455 system('perl parse.pl < ../../../backend/parser/gram.y > preproc.y'); 456 chdir('../../../..'); 457 } 458 459 if (IsNewer( 460 'src/interfaces/ecpg/include/ecpg_config.h', 461 'src/interfaces/ecpg/include/ecpg_config.h.in')) 462 { 463 print "Generating ecpg_config.h...\n"; 464 open(O, '>', 'src/interfaces/ecpg/include/ecpg_config.h') 465 || confess "Could not open ecpg_config.h"; 466 print O <<EOF; 467#if (_MSC_VER > 1200) 468#define HAVE_LONG_LONG_INT 1 469#define HAVE_LONG_LONG_INT_64 1 470#endif 471#define ENABLE_THREAD_SAFETY 1 472EOF 473 print O "#define USE_INTEGER_DATETIMES 1\n" 474 if ($self->{options}->{integer_datetimes}); 475 close(O); 476 } 477 478 unless (-f "src/port/pg_config_paths.h") 479 { 480 print "Generating pg_config_paths.h...\n"; 481 open(O, '>', 'src/port/pg_config_paths.h') 482 || confess "Could not open pg_config_paths.h"; 483 print O <<EOF; 484#define PGBINDIR "/bin" 485#define PGSHAREDIR "/share" 486#define SYSCONFDIR "/etc" 487#define INCLUDEDIR "/include" 488#define PKGINCLUDEDIR "/include" 489#define INCLUDEDIRSERVER "/include/server" 490#define LIBDIR "/lib" 491#define PKGLIBDIR "/lib" 492#define LOCALEDIR "/share/locale" 493#define DOCDIR "/doc" 494#define HTMLDIR "/doc" 495#define MANDIR "/man" 496EOF 497 close(O); 498 } 499 500 my $mf = Project::read_file('src/backend/catalog/Makefile'); 501 $mf =~ s{\\\r?\n}{}g; 502 $mf =~ /^POSTGRES_BKI_SRCS\s*:?=[^,]+,(.*)\)$/gm 503 || croak "Could not find POSTGRES_BKI_SRCS in Makefile\n"; 504 my @allbki = split /\s+/, $1; 505 foreach my $bki (@allbki) 506 { 507 next if $bki eq ""; 508 if (IsNewer( 509 'src/backend/catalog/postgres.bki', 510 "src/include/catalog/$bki")) 511 { 512 print "Generating postgres.bki and schemapg.h...\n"; 513 chdir('src/backend/catalog'); 514 my $bki_srcs = join(' ../../../src/include/catalog/', @allbki); 515 system( 516"perl genbki.pl -I../../../src/include/catalog --set-version=$self->{majorver} $bki_srcs" 517 ); 518 chdir('../../..'); 519 copyFile( 520 'src/backend/catalog/schemapg.h', 521 'src/include/catalog/schemapg.h'); 522 last; 523 } 524 } 525 526 open(O, ">doc/src/sgml/version.sgml") 527 || croak "Could not write to version.sgml\n"; 528 print O <<EOF; 529<!ENTITY version "$self->{strver}"> 530<!ENTITY majorversion "$self->{majorver}"> 531EOF 532 close(O); 533} 534 535sub GenerateDefFile 536{ 537 my ($self, $deffile, $txtfile, $libname) = @_; 538 539 if (IsNewer($deffile, $txtfile)) 540 { 541 print "Generating $deffile...\n"; 542 open(I, $txtfile) || confess("Could not open $txtfile\n"); 543 open(O, ">$deffile") || confess("Could not open $deffile\n"); 544 print O "LIBRARY $libname\nEXPORTS\n"; 545 while (<I>) 546 { 547 next if (/^#/); 548 next if (/^\s*$/); 549 my ($f, $o) = split; 550 print O " $f @ $o\n"; 551 } 552 close(O); 553 close(I); 554 } 555} 556 557sub AddProject 558{ 559 my ($self, $name, $type, $folder, $initialdir) = @_; 560 561 my $proj = 562 VSObjectFactory::CreateProject($self->{vcver}, $name, $type, $self); 563 push @{ $self->{projects}->{$folder} }, $proj; 564 $proj->AddDir($initialdir) if ($initialdir); 565 if ($self->{options}->{zlib}) 566 { 567 $proj->AddIncludeDir($self->{options}->{zlib} . '\include'); 568 $proj->AddLibrary($self->{options}->{zlib} . '\lib\zdll.lib'); 569 } 570 if ($self->{options}->{openssl}) 571 { 572 $proj->AddIncludeDir($self->{options}->{openssl} . '\include'); 573 my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion(); 574 575 # Starting at version 1.1.0 the OpenSSL installers have 576 # changed their library names from: 577 # - libeay to libcrypto 578 # - ssleay to libssl 579 if ( ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0') 580 || ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0')) 581 { 582 my $dbgsuffix; 583 my $libsslpath; 584 my $libcryptopath; 585 586 # The format name of the libraries is slightly 587 # different between the Win32 and Win64 platform, so 588 # adapt. 589 if (-e "$self->{options}->{openssl}/lib/VC/sslcrypto32MD.lib") 590 { 591 # Win32 here, with a debugging library set. 592 $dbgsuffix = 1; 593 $libsslpath = '\lib\VC\libssl32.lib'; 594 $libcryptopath = '\lib\VC\libcrypto32.lib'; 595 } 596 elsif (-e "$self->{options}->{openssl}/lib/VC/sslcrypto64MD.lib") 597 { 598 # Win64 here, with a debugging library set. 599 $dbgsuffix = 1; 600 $libsslpath = '\lib\VC\libssl64.lib'; 601 $libcryptopath = '\lib\VC\libcrypto64.lib'; 602 } 603 else 604 { 605 # On both Win32 and Win64 the same library 606 # names are used without a debugging context. 607 $dbgsuffix = 0; 608 $libsslpath = '\lib\libssl.lib'; 609 $libcryptopath = '\lib\libcrypto.lib'; 610 } 611 612 $proj->AddLibrary($self->{options}->{openssl} . $libsslpath, 613 $dbgsuffix); 614 $proj->AddLibrary($self->{options}->{openssl} . $libcryptopath, 615 $dbgsuffix); 616 } 617 else 618 { 619 # Choose which set of libraries to use depending on if 620 # debugging libraries are in place in the installer. 621 if (-e "$self->{options}->{openssl}/lib/VC/ssleay32MD.lib") 622 { 623 $proj->AddLibrary( 624 $self->{options}->{openssl} . '\lib\VC\ssleay32.lib', 1); 625 $proj->AddLibrary( 626 $self->{options}->{openssl} . '\lib\VC\libeay32.lib', 1); 627 } 628 else 629 { 630 # We don't expect the config-specific library 631 # to be here, so don't ask for it in last 632 # parameter. 633 $proj->AddLibrary( 634 $self->{options}->{openssl} . '\lib\ssleay32.lib', 0); 635 $proj->AddLibrary( 636 $self->{options}->{openssl} . '\lib\libeay32.lib', 0); 637 } 638 } 639 } 640 if ($self->{options}->{nls}) 641 { 642 $proj->AddIncludeDir($self->{options}->{nls} . '\include'); 643 $proj->AddLibrary($self->{options}->{nls} . '\lib\libintl.lib'); 644 } 645 if ($self->{options}->{gss}) 646 { 647 $proj->AddIncludeDir($self->{options}->{gss} . '\include'); 648 $proj->AddIncludeDir($self->{options}->{gss} . '\include\krb5'); 649 if ($self->{platform} eq 'Win32') 650 { 651 $proj->AddLibrary( 652 $self->{options}->{gss} . '\lib\i386\krb5_32.lib'); 653 $proj->AddLibrary( 654 $self->{options}->{gss} . '\lib\i386\comerr32.lib'); 655 $proj->AddLibrary( 656 $self->{options}->{gss} . '\lib\i386\gssapi32.lib'); 657 } 658 else 659 { 660 $proj->AddLibrary( 661 $self->{options}->{gss} . '\lib\amd64\krb5_64.lib'); 662 $proj->AddLibrary( 663 $self->{options}->{gss} . '\lib\amd64\comerr64.lib'); 664 $proj->AddLibrary( 665 $self->{options}->{gss} . '\lib\amd64\gssapi64.lib'); 666 } 667 } 668 if ($self->{options}->{iconv}) 669 { 670 $proj->AddIncludeDir($self->{options}->{iconv} . '\include'); 671 $proj->AddLibrary($self->{options}->{iconv} . '\lib\iconv.lib'); 672 } 673 if ($self->{options}->{xml}) 674 { 675 $proj->AddIncludeDir($self->{options}->{xml} . '\include'); 676 $proj->AddIncludeDir($self->{options}->{xml} . '\include\libxml2'); 677 $proj->AddLibrary($self->{options}->{xml} . '\lib\libxml2.lib'); 678 } 679 if ($self->{options}->{xslt}) 680 { 681 $proj->AddIncludeDir($self->{options}->{xslt} . '\include'); 682 $proj->AddLibrary($self->{options}->{xslt} . '\lib\libxslt.lib'); 683 } 684 return $proj; 685} 686 687sub Save 688{ 689 my ($self) = @_; 690 my %flduid; 691 692 $self->GenerateFiles(); 693 foreach my $fld (keys %{ $self->{projects} }) 694 { 695 foreach my $proj (@{ $self->{projects}->{$fld} }) 696 { 697 $proj->Save(); 698 } 699 } 700 701 open(SLN, ">pgsql.sln") || croak "Could not write to pgsql.sln\n"; 702 print SLN <<EOF; 703Microsoft Visual Studio Solution File, Format Version $self->{solutionFileVersion} 704# $self->{visualStudioName} 705EOF 706 707 print SLN $self->GetAdditionalHeaders(); 708 709 foreach my $fld (keys %{ $self->{projects} }) 710 { 711 foreach my $proj (@{ $self->{projects}->{$fld} }) 712 { 713 print SLN <<EOF; 714Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "$proj->{name}", "$proj->{name}$proj->{filenameExtension}", "$proj->{guid}" 715EndProject 716EOF 717 } 718 if ($fld ne "") 719 { 720 $flduid{$fld} = Win32::GuidGen(); 721 print SLN <<EOF; 722Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "$fld", "$fld", "$flduid{$fld}" 723EndProject 724EOF 725 } 726 } 727 728 print SLN <<EOF; 729Global 730 GlobalSection(SolutionConfigurationPlatforms) = preSolution 731 Debug|$self->{platform}= Debug|$self->{platform} 732 Release|$self->{platform} = Release|$self->{platform} 733 EndGlobalSection 734 GlobalSection(ProjectConfigurationPlatforms) = postSolution 735EOF 736 737 foreach my $fld (keys %{ $self->{projects} }) 738 { 739 foreach my $proj (@{ $self->{projects}->{$fld} }) 740 { 741 print SLN <<EOF; 742 $proj->{guid}.Debug|$self->{platform}.ActiveCfg = Debug|$self->{platform} 743 $proj->{guid}.Debug|$self->{platform}.Build.0 = Debug|$self->{platform} 744 $proj->{guid}.Release|$self->{platform}.ActiveCfg = Release|$self->{platform} 745 $proj->{guid}.Release|$self->{platform}.Build.0 = Release|$self->{platform} 746EOF 747 } 748 } 749 750 print SLN <<EOF; 751 EndGlobalSection 752 GlobalSection(SolutionProperties) = preSolution 753 HideSolutionNode = FALSE 754 EndGlobalSection 755 GlobalSection(NestedProjects) = preSolution 756EOF 757 758 foreach my $fld (keys %{ $self->{projects} }) 759 { 760 next if ($fld eq ""); 761 foreach my $proj (@{ $self->{projects}->{$fld} }) 762 { 763 print SLN "\t\t$proj->{guid} = $flduid{$fld}\n"; 764 } 765 } 766 767 print SLN <<EOF; 768 EndGlobalSection 769EndGlobal 770EOF 771 close(SLN); 772} 773 774sub GetFakeConfigure 775{ 776 my $self = shift; 777 778 my $cfg = '--enable-thread-safety'; 779 $cfg .= ' --enable-cassert' if ($self->{options}->{asserts}); 780 $cfg .= ' --enable-integer-datetimes' 781 if ($self->{options}->{integer_datetimes}); 782 $cfg .= ' --enable-nls' if ($self->{options}->{nls}); 783 $cfg .= ' --enable-tap-tests' if ($self->{options}->{tap_tests}); 784 $cfg .= ' --with-ldap' if ($self->{options}->{ldap}); 785 $cfg .= ' --without-zlib' unless ($self->{options}->{zlib}); 786 $cfg .= ' --with-extra-version' if ($self->{options}->{extraver}); 787 $cfg .= ' --with-openssl' if ($self->{options}->{openssl}); 788 $cfg .= ' --with-ossp-uuid' if ($self->{options}->{uuid}); 789 $cfg .= ' --with-libxml' if ($self->{options}->{xml}); 790 $cfg .= ' --with-libxslt' if ($self->{options}->{xslt}); 791 $cfg .= ' --with-gssapi' if ($self->{options}->{gss}); 792 $cfg .= ' --with-tcl' if ($self->{options}->{tcl}); 793 $cfg .= ' --with-perl' if ($self->{options}->{perl}); 794 $cfg .= ' --with-python' if ($self->{options}->{python}); 795 my $port = $self->{options}->{'--with-pgport'}; 796 $cfg .= " --with-pgport=$port" if defined($port); 797 798 return $cfg; 799} 800 801package VS2005Solution; 802 803# 804# Package that encapsulates a Visual Studio 2005 solution file 805# 806 807use strict; 808use warnings; 809use base qw(Solution); 810 811sub new 812{ 813 my $classname = shift; 814 my $self = $classname->SUPER::_new(@_); 815 bless($self, $classname); 816 817 $self->{solutionFileVersion} = '9.00'; 818 $self->{vcver} = '8.00'; 819 $self->{visualStudioName} = 'Visual Studio 2005'; 820 821 return $self; 822} 823 824package VS2008Solution; 825 826# 827# Package that encapsulates a Visual Studio 2008 solution file 828# 829 830use strict; 831use warnings; 832use base qw(Solution); 833 834sub new 835{ 836 my $classname = shift; 837 my $self = $classname->SUPER::_new(@_); 838 bless($self, $classname); 839 840 $self->{solutionFileVersion} = '10.00'; 841 $self->{vcver} = '9.00'; 842 $self->{visualStudioName} = 'Visual Studio 2008'; 843 844 return $self; 845} 846 847package VS2010Solution; 848 849# 850# Package that encapsulates a Visual Studio 2010 solution file 851# 852 853use Carp; 854use strict; 855use warnings; 856use base qw(Solution); 857 858sub new 859{ 860 my $classname = shift; 861 my $self = $classname->SUPER::_new(@_); 862 bless($self, $classname); 863 864 $self->{solutionFileVersion} = '11.00'; 865 $self->{vcver} = '10.00'; 866 $self->{visualStudioName} = 'Visual Studio 2010'; 867 868 return $self; 869} 870 871package VS2012Solution; 872 873# 874# Package that encapsulates a Visual Studio 2012 solution file 875# 876 877use Carp; 878use strict; 879use warnings; 880use base qw(Solution); 881 882sub new 883{ 884 my $classname = shift; 885 my $self = $classname->SUPER::_new(@_); 886 bless($self, $classname); 887 888 $self->{solutionFileVersion} = '12.00'; 889 $self->{vcver} = '11.00'; 890 $self->{visualStudioName} = 'Visual Studio 2012'; 891 892 return $self; 893} 894 895package VS2013Solution; 896 897# 898# Package that encapsulates a Visual Studio 2013 solution file 899# 900 901use Carp; 902use strict; 903use warnings; 904use base qw(Solution); 905 906sub new 907{ 908 my $classname = shift; 909 my $self = $classname->SUPER::_new(@_); 910 bless($self, $classname); 911 912 $self->{solutionFileVersion} = '12.00'; 913 $self->{vcver} = '12.00'; 914 $self->{visualStudioName} = 'Visual Studio 2013'; 915 $self->{VisualStudioVersion} = '12.0.21005.1'; 916 $self->{MinimumVisualStudioVersion} = '10.0.40219.1'; 917 918 return $self; 919} 920 921package VS2015Solution; 922 923# 924# Package that encapsulates a Visual Studio 2015 solution file 925# 926 927use Carp; 928use strict; 929use warnings; 930use base qw(Solution); 931 932sub new 933{ 934 my $classname = shift; 935 my $self = $classname->SUPER::_new(@_); 936 bless($self, $classname); 937 938 $self->{solutionFileVersion} = '12.00'; 939 $self->{vcver} = '14.00'; 940 $self->{visualStudioName} = 'Visual Studio 2015'; 941 $self->{VisualStudioVersion} = '14.0.24730.2'; 942 $self->{MinimumVisualStudioVersion} = '10.0.40219.1'; 943 944 return $self; 945} 946 947package VS2017Solution; 948 949# 950# Package that encapsulates a Visual Studio 2017 solution file 951# 952 953use Carp; 954use strict; 955use warnings; 956use base qw(Solution); 957 958sub new 959{ 960 my $classname = shift; 961 my $self = $classname->SUPER::_new(@_); 962 bless($self, $classname); 963 964 $self->{solutionFileVersion} = '12.00'; 965 $self->{vcver} = '15.00'; 966 $self->{visualStudioName} = 'Visual Studio 2017'; 967 $self->{VisualStudioVersion} = '15.0.26730.3'; 968 $self->{MinimumVisualStudioVersion} = '10.0.40219.1'; 969 970 return $self; 971} 972 973package VS2019Solution; 974 975# 976# Package that encapsulates a Visual Studio 2019 solution file 977# 978 979use Carp; 980use strict; 981use warnings; 982use base qw(Solution); 983 984no warnings qw(redefine); ## no critic 985 986sub new 987{ 988 my $classname = shift; 989 my $self = $classname->SUPER::_new(@_); 990 bless($self, $classname); 991 992 $self->{solutionFileVersion} = '12.00'; 993 $self->{vcver} = '16.00'; 994 $self->{visualStudioName} = 'Visual Studio 2019'; 995 $self->{VisualStudioVersion} = '16.0.28729.10'; 996 $self->{MinimumVisualStudioVersion} = '10.0.40219.1'; 997 998 return $self; 999} 1000 1001sub GetAdditionalHeaders 1002{ 1003 my ($self, $f) = @_; 1004 1005 return qq|VisualStudioVersion = $self->{VisualStudioVersion} 1006MinimumVisualStudioVersion = $self->{MinimumVisualStudioVersion} 1007|; 1008} 1009 10101; 1011