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