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