Fix MSVC build script's check for obsolete node support functions.
[pgsql.git] / src / tools / msvc / Solution.pm
blobcc82668457ff0410f8cf6007450f652021683354
2 # Copyright (c) 2021-2022, PostgreSQL Global Development Group
4 package Solution;
7 # Package that encapsulates a Visual C++ solution file generation
9 # src/tools/msvc/Solution.pm
11 use Carp;
12 use strict;
13 use warnings;
14 use VSObjectFactory;
16 no warnings qw(redefine); ## no critic
18 sub _new
20 my $classname = shift;
21 my $options = shift;
22 my $self = {
23 projects => {},
24 options => $options,
25 VisualStudioVersion => undef,
26 MinimumVisualStudioVersion => undef,
27 vcver => undef,
28 platform => undef,
30 bless($self, $classname);
32 $self->DeterminePlatform();
34 if ($options->{xslt} && !$options->{xml})
36 die "XSLT requires XML\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);
53 return $self;
56 sub GetAdditionalHeaders
58 return '';
61 sub DeterminePlatform
63 my $self = shift;
65 if ($^O eq "MSWin32")
67 # Examine CL help output to determine if we are in 32 or 64-bit mode.
68 my $output = `cl /help 2>&1`;
69 $? >> 8 == 0 or die "cl command not found";
70 $self->{platform} =
71 ($output =~ /^\/favor:<.+AMD64/m) ? 'x64' : 'Win32';
73 else
75 $self->{platform} = 'FAKE';
77 print "Detected hardware platform: $self->{platform}\n";
78 return;
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
83 sub IsNewer
85 my ($newfile, $oldfile) = @_;
86 -e $oldfile or warn "source file \"$oldfile\" does not exist";
87 if ( $oldfile ne 'src/tools/msvc/config.pl'
88 && $oldfile ne 'src/tools/msvc/config_default.pl')
90 return 1
91 if (-f 'src/tools/msvc/config.pl')
92 && IsNewer($newfile, 'src/tools/msvc/config.pl');
93 return 1
94 if (-f 'src/tools/msvc/config_default.pl')
95 && IsNewer($newfile, 'src/tools/msvc/config_default.pl');
97 return 1 if (!(-e $newfile));
98 my @nstat = stat($newfile);
99 my @ostat = stat($oldfile);
100 return 1 if ($nstat[9] < $ostat[9]);
101 return 0;
104 # Copy a file, *not* preserving date. Only works for text files.
105 sub copyFile
107 my ($src, $dest) = @_;
108 open(my $i, '<', $src) || croak "Could not open $src";
109 open(my $o, '>', $dest) || croak "Could not open $dest";
110 while (<$i>)
112 print $o $_;
114 close($i);
115 close($o);
116 return;
119 # Fetch version of OpenSSL based on a parsing of the command shipped with
120 # the installer this build is linking to. This returns as result an array
121 # made of the three first digits of the OpenSSL version, which is enough
122 # to decide which options to apply depending on the version of OpenSSL
123 # linking with.
124 sub GetOpenSSLVersion
126 my $self = shift;
128 # Attempt to get OpenSSL version and location. This assumes that
129 # openssl.exe is in the specified directory.
130 # Quote the .exe name in case it has spaces
131 my $opensslcmd =
132 qq("$self->{options}->{openssl}\\bin\\openssl.exe" version 2>&1);
133 my $sslout = `$opensslcmd`;
135 $? >> 8 == 0
136 or croak
137 "Unable to determine OpenSSL version: The openssl.exe command wasn't found.";
139 if ($sslout =~ /(\d+)\.(\d+)\.(\d+)(\D)/m)
141 return ($1, $2, $3);
144 croak
145 "Unable to determine OpenSSL version: The openssl.exe version could not be determined.";
148 sub GenerateFiles
150 my $self = shift;
151 my $bits = $self->{platform} eq 'Win32' ? 32 : 64;
152 my $ac_init_found = 0;
153 my $package_name;
154 my $package_version;
155 my $package_bugreport;
156 my $package_url;
157 my ($majorver, $minorver);
158 my $ac_define_openssl_api_compat_found = 0;
159 my $openssl_api_compat;
161 # Parse configure.ac to get version numbers
162 open(my $c, '<', "configure.ac")
163 || confess("Could not open configure.ac for reading\n");
164 while (<$c>)
166 if (/^AC_INIT\(\[([^\]]+)\], \[([^\]]+)\], \[([^\]]+)\], \[([^\]]*)\], \[([^\]]+)\]/
169 $ac_init_found = 1;
171 $package_name = $1;
172 $package_version = $2;
173 $package_bugreport = $3;
174 #$package_tarname = $4;
175 $package_url = $5;
177 if ($package_version !~ /^(\d+)(?:\.(\d+))?/)
179 confess "Bad format of version: $package_version\n";
181 $majorver = sprintf("%d", $1);
182 $minorver = sprintf("%d", $2 ? $2 : 0);
184 elsif (/\bAC_DEFINE\(OPENSSL_API_COMPAT, \[([0-9xL]+)\]/)
186 $ac_define_openssl_api_compat_found = 1;
187 $openssl_api_compat = $1;
190 close($c);
191 confess "Unable to parse configure.ac for all variables!"
192 unless $ac_init_found && $ac_define_openssl_api_compat_found;
194 if (IsNewer("src/include/pg_config_os.h", "src/include/port/win32.h"))
196 print "Copying pg_config_os.h...\n";
197 copyFile("src/include/port/win32.h", "src/include/pg_config_os.h");
200 print "Generating configuration headers...\n";
201 my $extraver = $self->{options}->{extraver};
202 $extraver = '' unless defined $extraver;
203 my $port = $self->{options}->{"--with-pgport"} || 5432;
205 # Every symbol in pg_config.h.in must be accounted for here. Set
206 # to undef if the symbol should not be defined.
207 my %define = (
208 ALIGNOF_DOUBLE => 8,
209 ALIGNOF_INT => 4,
210 ALIGNOF_LONG => 4,
211 ALIGNOF_LONG_LONG_INT => 8,
212 ALIGNOF_PG_INT128_TYPE => undef,
213 ALIGNOF_SHORT => 2,
214 AC_APPLE_UNIVERSAL_BUILD => undef,
215 BLCKSZ => 1024 * $self->{options}->{blocksize},
216 CONFIGURE_ARGS => '"' . $self->GetFakeConfigure() . '"',
217 DEF_PGPORT => $port,
218 DEF_PGPORT_STR => qq{"$port"},
219 DLSUFFIX => '".dll"',
220 ENABLE_GSS => $self->{options}->{gss} ? 1 : undef,
221 ENABLE_NLS => $self->{options}->{nls} ? 1 : undef,
222 ENABLE_THREAD_SAFETY => 1,
223 HAVE_APPEND_HISTORY => undef,
224 HAVE_ASN1_STRING_GET0_DATA => undef,
225 HAVE_ATOMICS => 1,
226 HAVE_ATOMIC_H => undef,
227 HAVE_BACKTRACE_SYMBOLS => undef,
228 HAVE_BIO_GET_DATA => undef,
229 HAVE_BIO_METH_NEW => undef,
230 HAVE_COMPUTED_GOTO => undef,
231 HAVE_COPYFILE => undef,
232 HAVE_COPYFILE_H => undef,
233 HAVE_CRTDEFS_H => undef,
234 HAVE_CRYPTO_LOCK => undef,
235 HAVE_DECL_FDATASYNC => 0,
236 HAVE_DECL_F_FULLFSYNC => 0,
237 HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER => 0,
238 HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER => 0,
239 HAVE_DECL_LLVMGETHOSTCPUNAME => 0,
240 HAVE_DECL_LLVMGETHOSTCPUFEATURES => 0,
241 HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN => 0,
242 HAVE_DECL_POSIX_FADVISE => 0,
243 HAVE_DECL_PREADV => 0,
244 HAVE_DECL_PWRITEV => 0,
245 HAVE_DECL_STRLCAT => 0,
246 HAVE_DECL_STRLCPY => 0,
247 HAVE_DECL_STRNLEN => 1,
248 HAVE_EDITLINE_HISTORY_H => undef,
249 HAVE_EDITLINE_READLINE_H => undef,
250 HAVE_EXECINFO_H => undef,
251 HAVE_EXPLICIT_BZERO => undef,
252 HAVE_FSEEKO => 1,
253 HAVE_GCC__ATOMIC_INT32_CAS => undef,
254 HAVE_GCC__ATOMIC_INT64_CAS => undef,
255 HAVE_GCC__SYNC_CHAR_TAS => undef,
256 HAVE_GCC__SYNC_INT32_CAS => undef,
257 HAVE_GCC__SYNC_INT32_TAS => undef,
258 HAVE_GCC__SYNC_INT64_CAS => undef,
259 HAVE_GETADDRINFO => undef,
260 HAVE_GETHOSTBYNAME_R => undef,
261 HAVE_GETIFADDRS => undef,
262 HAVE_GETOPT => undef,
263 HAVE_GETOPT_H => undef,
264 HAVE_GETOPT_LONG => undef,
265 HAVE_GETPEEREID => undef,
266 HAVE_GETPEERUCRED => undef,
267 HAVE_GSSAPI_GSSAPI_H => undef,
268 HAVE_GSSAPI_H => undef,
269 HAVE_HMAC_CTX_FREE => undef,
270 HAVE_HMAC_CTX_NEW => undef,
271 HAVE_HISTORY_H => undef,
272 HAVE_HISTORY_TRUNCATE_FILE => undef,
273 HAVE_IFADDRS_H => undef,
274 HAVE_INET_ATON => undef,
275 HAVE_INET_PTON => 1,
276 HAVE_INT_TIMEZONE => 1,
277 HAVE_INT64 => undef,
278 HAVE_INT8 => undef,
279 HAVE_INTTYPES_H => undef,
280 HAVE_INT_OPTERR => undef,
281 HAVE_INT_OPTRESET => undef,
282 HAVE_IPV6 => 1,
283 HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P => undef,
284 HAVE_KQUEUE => undef,
285 HAVE_LANGINFO_H => undef,
286 HAVE_LDAP_H => undef,
287 HAVE_LDAP_INITIALIZE => undef,
288 HAVE_LIBCRYPTO => undef,
289 HAVE_LIBLDAP => undef,
290 HAVE_LIBLZ4 => undef,
291 HAVE_LIBM => undef,
292 HAVE_LIBPAM => undef,
293 HAVE_LIBREADLINE => undef,
294 HAVE_LIBSELINUX => undef,
295 HAVE_LIBSSL => undef,
296 HAVE_LIBWLDAP32 => undef,
297 HAVE_LIBXML2 => undef,
298 HAVE_LIBXSLT => undef,
299 HAVE_LIBZ => $self->{options}->{zlib} ? 1 : undef,
300 HAVE_LIBZSTD => undef,
301 HAVE_LOCALE_T => 1,
302 HAVE_LONG_INT_64 => undef,
303 HAVE_LONG_LONG_INT_64 => 1,
304 HAVE_MBARRIER_H => undef,
305 HAVE_MBSTOWCS_L => 1,
306 HAVE_MEMORY_H => 1,
307 HAVE_MEMSET_S => undef,
308 HAVE_MKDTEMP => undef,
309 HAVE_NETINET_TCP_H => undef,
310 HAVE_NET_IF_H => undef,
311 HAVE_OPENSSL_INIT_SSL => undef,
312 HAVE_OSSP_UUID_H => undef,
313 HAVE_PAM_PAM_APPL_H => undef,
314 HAVE_POSIX_FADVISE => undef,
315 HAVE_POSIX_FALLOCATE => undef,
316 HAVE_PPC_LWARX_MUTEX_HINT => undef,
317 HAVE_PPOLL => undef,
318 HAVE_PS_STRINGS => undef,
319 HAVE_PTHREAD => undef,
320 HAVE_PTHREAD_BARRIER_WAIT => undef,
321 HAVE_PTHREAD_IS_THREADED_NP => undef,
322 HAVE_PTHREAD_PRIO_INHERIT => undef,
323 HAVE_READLINE_H => undef,
324 HAVE_READLINE_HISTORY_H => undef,
325 HAVE_READLINE_READLINE_H => undef,
326 HAVE_RL_COMPLETION_MATCHES => undef,
327 HAVE_RL_COMPLETION_SUPPRESS_QUOTE => undef,
328 HAVE_RL_FILENAME_COMPLETION_FUNCTION => undef,
329 HAVE_RL_FILENAME_QUOTE_CHARACTERS => undef,
330 HAVE_RL_FILENAME_QUOTING_FUNCTION => undef,
331 HAVE_RL_RESET_SCREEN_SIZE => undef,
332 HAVE_RL_VARIABLE_BIND => undef,
333 HAVE_SECURITY_PAM_APPL_H => undef,
334 HAVE_SETPROCTITLE => undef,
335 HAVE_SETPROCTITLE_FAST => undef,
336 HAVE_SOCKLEN_T => 1,
337 HAVE_SPINLOCKS => 1,
338 HAVE_STDBOOL_H => 1,
339 HAVE_STDINT_H => 1,
340 HAVE_STDLIB_H => 1,
341 HAVE_STRCHRNUL => undef,
342 HAVE_STRERROR_R => undef,
343 HAVE_STRINGS_H => undef,
344 HAVE_STRING_H => 1,
345 HAVE_STRLCAT => undef,
346 HAVE_STRLCPY => undef,
347 HAVE_STRNLEN => 1,
348 HAVE_STRSIGNAL => undef,
349 HAVE_STRUCT_ADDRINFO => 1,
350 HAVE_STRUCT_CMSGCRED => undef,
351 HAVE_STRUCT_OPTION => undef,
352 HAVE_STRUCT_SOCKADDR_SA_LEN => undef,
353 HAVE_STRUCT_SOCKADDR_STORAGE => 1,
354 HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY => 1,
355 HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN => undef,
356 HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY => undef,
357 HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN => undef,
358 HAVE_STRUCT_SOCKADDR_UN => undef,
359 HAVE_STRUCT_TM_TM_ZONE => undef,
360 HAVE_SYNC_FILE_RANGE => undef,
361 HAVE_SYNCFS => undef,
362 HAVE_SYSLOG => undef,
363 HAVE_SYS_EPOLL_H => undef,
364 HAVE_SYS_EVENT_H => undef,
365 HAVE_SYS_IPC_H => undef,
366 HAVE_SYS_PERSONALITY_H => undef,
367 HAVE_SYS_PRCTL_H => undef,
368 HAVE_SYS_PROCCTL_H => undef,
369 HAVE_SYS_RESOURCE_H => undef,
370 HAVE_SYS_SELECT_H => undef,
371 HAVE_SYS_SEM_H => undef,
372 HAVE_SYS_SHM_H => undef,
373 HAVE_SYS_SIGNALFD_H => undef,
374 HAVE_SYS_SOCKIO_H => undef,
375 HAVE_SYS_STAT_H => 1,
376 HAVE_SYS_TYPES_H => 1,
377 HAVE_SYS_UCRED_H => undef,
378 HAVE_SYS_UIO_H => undef,
379 HAVE_SYS_UN_H => undef,
380 HAVE_TERMIOS_H => undef,
381 HAVE_TYPEOF => undef,
382 HAVE_UCRED_H => undef,
383 HAVE_UINT64 => undef,
384 HAVE_UINT8 => undef,
385 HAVE_UNION_SEMUN => undef,
386 HAVE_UNISTD_H => 1,
387 HAVE_USELOCALE => undef,
388 HAVE_UUID_BSD => undef,
389 HAVE_UUID_E2FS => undef,
390 HAVE_UUID_OSSP => undef,
391 HAVE_UUID_H => undef,
392 HAVE_UUID_UUID_H => undef,
393 HAVE_WINLDAP_H => undef,
394 HAVE_WCSTOMBS_L => 1,
395 HAVE_VISIBILITY_ATTRIBUTE => undef,
396 HAVE_X509_GET_SIGNATURE_NID => 1,
397 HAVE_X86_64_POPCNTQ => undef,
398 HAVE__BOOL => undef,
399 HAVE__BUILTIN_BSWAP16 => undef,
400 HAVE__BUILTIN_BSWAP32 => undef,
401 HAVE__BUILTIN_BSWAP64 => undef,
402 HAVE__BUILTIN_CLZ => undef,
403 HAVE__BUILTIN_CONSTANT_P => undef,
404 HAVE__BUILTIN_CTZ => undef,
405 HAVE__BUILTIN_FRAME_ADDRESS => undef,
406 HAVE__BUILTIN_OP_OVERFLOW => undef,
407 HAVE__BUILTIN_POPCOUNT => undef,
408 HAVE__BUILTIN_TYPES_COMPATIBLE_P => undef,
409 HAVE__BUILTIN_UNREACHABLE => undef,
410 HAVE__CONFIGTHREADLOCALE => 1,
411 HAVE__CPUID => 1,
412 HAVE__GET_CPUID => undef,
413 HAVE__STATIC_ASSERT => undef,
414 INT64_MODIFIER => qq{"ll"},
415 LOCALE_T_IN_XLOCALE => undef,
416 MAXIMUM_ALIGNOF => 8,
417 MEMSET_LOOP_LIMIT => 1024,
418 OPENSSL_API_COMPAT => $openssl_api_compat,
419 PACKAGE_BUGREPORT => qq{"$package_bugreport"},
420 PACKAGE_NAME => qq{"$package_name"},
421 PACKAGE_STRING => qq{"$package_name $package_version"},
422 PACKAGE_TARNAME => lc qq{"$package_name"},
423 PACKAGE_URL => qq{"$package_url"},
424 PACKAGE_VERSION => qq{"$package_version"},
425 PG_INT128_TYPE => undef,
426 PG_INT64_TYPE => 'long long int',
427 PG_KRB_SRVNAM => qq{"postgres"},
428 PG_MAJORVERSION => qq{"$majorver"},
429 PG_MAJORVERSION_NUM => $majorver,
430 PG_MINORVERSION_NUM => $minorver,
431 PG_PRINTF_ATTRIBUTE => undef,
432 PG_USE_STDBOOL => 1,
433 PG_VERSION => qq{"$package_version$extraver"},
434 PG_VERSION_NUM => sprintf("%d%04d", $majorver, $minorver),
435 PG_VERSION_STR =>
436 qq{"PostgreSQL $package_version$extraver, compiled by Visual C++ build " CppAsString2(_MSC_VER) ", $bits-bit"},
437 PROFILE_PID_DIR => undef,
438 PTHREAD_CREATE_JOINABLE => undef,
439 RELSEG_SIZE => (1024 / $self->{options}->{blocksize}) *
440 $self->{options}->{segsize} * 1024,
441 SIZEOF_BOOL => 1,
442 SIZEOF_LONG => 4,
443 SIZEOF_OFF_T => undef,
444 SIZEOF_SIZE_T => $bits / 8,
445 SIZEOF_VOID_P => $bits / 8,
446 STDC_HEADERS => 1,
447 STRERROR_R_INT => undef,
448 USE_ARMV8_CRC32C => undef,
449 USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK => undef,
450 USE_ASSERT_CHECKING => $self->{options}->{asserts} ? 1 : undef,
451 USE_BONJOUR => undef,
452 USE_BSD_AUTH => undef,
453 USE_ICU => $self->{options}->{icu} ? 1 : undef,
454 USE_LIBXML => undef,
455 USE_LIBXSLT => undef,
456 USE_LZ4 => undef,
457 USE_LDAP => $self->{options}->{ldap} ? 1 : undef,
458 USE_LLVM => undef,
459 USE_NAMED_POSIX_SEMAPHORES => undef,
460 USE_OPENSSL => undef,
461 USE_PAM => undef,
462 USE_SLICING_BY_8_CRC32C => undef,
463 USE_SSE42_CRC32C => undef,
464 USE_SSE42_CRC32C_WITH_RUNTIME_CHECK => 1,
465 USE_SYSTEMD => undef,
466 USE_SYSV_SEMAPHORES => undef,
467 USE_SYSV_SHARED_MEMORY => undef,
468 USE_UNNAMED_POSIX_SEMAPHORES => undef,
469 USE_WIN32_SEMAPHORES => 1,
470 USE_WIN32_SHARED_MEMORY => 1,
471 USE_ZSTD => undef,
472 WCSTOMBS_L_IN_XLOCALE => undef,
473 WORDS_BIGENDIAN => undef,
474 XLOG_BLCKSZ => 1024 * $self->{options}->{wal_blocksize},
475 _FILE_OFFSET_BITS => undef,
476 _LARGEFILE_SOURCE => undef,
477 _LARGE_FILES => undef,
478 inline => '__inline',
479 pg_restrict => '__restrict',
480 # not defined, because it'd conflict with __declspec(restrict)
481 restrict => undef,
482 typeof => undef,);
484 if ($self->{options}->{uuid})
486 $define{HAVE_UUID_OSSP} = 1;
487 $define{HAVE_UUID_H} = 1;
489 if ($self->{options}->{xml})
491 $define{HAVE_LIBXML2} = 1;
492 $define{USE_LIBXML} = 1;
494 if ($self->{options}->{xslt})
496 $define{HAVE_LIBXSLT} = 1;
497 $define{USE_LIBXSLT} = 1;
499 if ($self->{options}->{lz4})
501 $define{HAVE_LIBLZ4} = 1;
502 $define{USE_LZ4} = 1;
504 if ($self->{options}->{zstd})
506 $define{HAVE_LIBZSTD} = 1;
507 $define{USE_ZSTD} = 1;
509 if ($self->{options}->{openssl})
511 $define{USE_OPENSSL} = 1;
513 my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
515 # More symbols are needed with OpenSSL 1.1.0 and above.
516 if ( ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
517 || ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
519 $define{HAVE_ASN1_STRING_GET0_DATA} = 1;
520 $define{HAVE_BIO_GET_DATA} = 1;
521 $define{HAVE_BIO_METH_NEW} = 1;
522 $define{HAVE_HMAC_CTX_FREE} = 1;
523 $define{HAVE_HMAC_CTX_NEW} = 1;
524 $define{HAVE_OPENSSL_INIT_SSL} = 1;
528 $self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
529 $self->GenerateConfigHeader('src/include/pg_config_ext.h', \%define, 0);
530 $self->GenerateConfigHeader('src/interfaces/ecpg/include/ecpg_config.h',
531 \%define, 0);
533 $self->GenerateDefFile(
534 "src/interfaces/libpq/libpqdll.def",
535 "src/interfaces/libpq/exports.txt",
536 "LIBPQ");
537 $self->GenerateDefFile(
538 "src/interfaces/ecpg/ecpglib/ecpglib.def",
539 "src/interfaces/ecpg/ecpglib/exports.txt",
540 "LIBECPG");
541 $self->GenerateDefFile(
542 "src/interfaces/ecpg/compatlib/compatlib.def",
543 "src/interfaces/ecpg/compatlib/exports.txt",
544 "LIBECPG_COMPAT");
545 $self->GenerateDefFile(
546 "src/interfaces/ecpg/pgtypeslib/pgtypeslib.def",
547 "src/interfaces/ecpg/pgtypeslib/exports.txt",
548 "LIBPGTYPES");
550 chdir('src/backend/utils');
551 my $pg_proc_dat = '../../../src/include/catalog/pg_proc.dat';
552 if ( IsNewer('fmgr-stamp', 'Gen_fmgrtab.pl')
553 || IsNewer('fmgr-stamp', '../catalog/Catalog.pm')
554 || IsNewer('fmgr-stamp', $pg_proc_dat)
555 || IsNewer('fmgr-stamp', '../../../src/include/access/transam.h'))
557 system(
558 "perl -I ../catalog Gen_fmgrtab.pl --include-path ../../../src/include/ $pg_proc_dat"
560 open(my $f, '>', 'fmgr-stamp')
561 || confess "Could not touch fmgr-stamp";
562 close($f);
564 chdir('../../..');
566 if (IsNewer(
567 'src/include/utils/fmgroids.h',
568 'src/backend/utils/fmgroids.h'))
570 copyFile('src/backend/utils/fmgroids.h',
571 'src/include/utils/fmgroids.h');
574 if (IsNewer(
575 'src/include/utils/fmgrprotos.h',
576 'src/backend/utils/fmgrprotos.h'))
578 copyFile(
579 'src/backend/utils/fmgrprotos.h',
580 'src/include/utils/fmgrprotos.h');
583 if (IsNewer(
584 'src/include/storage/lwlocknames.h',
585 'src/backend/storage/lmgr/lwlocknames.txt'))
587 print "Generating lwlocknames.c and lwlocknames.h...\n";
588 my $lmgr = 'src/backend/storage/lmgr';
589 system("perl $lmgr/generate-lwlocknames.pl --outdir $lmgr $lmgr/lwlocknames.txt");
591 if (IsNewer(
592 'src/include/storage/lwlocknames.h',
593 'src/backend/storage/lmgr/lwlocknames.h'))
595 copyFile(
596 'src/backend/storage/lmgr/lwlocknames.h',
597 'src/include/storage/lwlocknames.h');
600 if (IsNewer('src/include/utils/probes.h', 'src/backend/utils/probes.d'))
602 print "Generating probes.h...\n";
603 system(
604 'perl src/backend/utils/Gen_dummy_probes.pl src/backend/utils/probes.d > src/include/utils/probes.h'
608 if ($self->{options}->{python}
609 && IsNewer(
610 'src/pl/plpython/spiexceptions.h',
611 'src/backend/utils/errcodes.txt'))
613 print "Generating spiexceptions.h...\n";
614 system(
615 'perl src/pl/plpython/generate-spiexceptions.pl src/backend/utils/errcodes.txt > src/pl/plpython/spiexceptions.h'
619 if (IsNewer(
620 'src/include/utils/errcodes.h',
621 'src/backend/utils/errcodes.txt'))
623 print "Generating errcodes.h...\n";
624 system(
625 'perl src/backend/utils/generate-errcodes.pl --outfile src/backend/utils/errcodes.h src/backend/utils/errcodes.txt'
627 copyFile('src/backend/utils/errcodes.h',
628 'src/include/utils/errcodes.h');
631 if (IsNewer(
632 'src/pl/plpgsql/src/plerrcodes.h',
633 'src/backend/utils/errcodes.txt'))
635 print "Generating plerrcodes.h...\n";
636 system(
637 'perl src/pl/plpgsql/src/generate-plerrcodes.pl src/backend/utils/errcodes.txt > src/pl/plpgsql/src/plerrcodes.h'
641 if ($self->{options}->{tcl}
642 && IsNewer(
643 'src/pl/tcl/pltclerrcodes.h', 'src/backend/utils/errcodes.txt'))
645 print "Generating pltclerrcodes.h...\n";
646 system(
647 'perl src/pl/tcl/generate-pltclerrcodes.pl src/backend/utils/errcodes.txt > src/pl/tcl/pltclerrcodes.h'
651 if (IsNewer('src/bin/psql/sql_help.h', 'src/bin/psql/create_help.pl'))
653 print "Generating sql_help.h...\n";
654 my $psql = 'src/bin/psql';
655 system("perl $psql/create_help.pl --docdir doc/src/sgml/ref --outdir $psql --basename sql_help");
658 if (IsNewer('src/common/kwlist_d.h', 'src/include/parser/kwlist.h'))
660 print "Generating kwlist_d.h...\n";
661 system(
662 'perl -I src/tools src/tools/gen_keywordlist.pl --extern -o src/common src/include/parser/kwlist.h'
666 if (IsNewer(
667 'src/pl/plpgsql/src/pl_reserved_kwlist_d.h',
668 'src/pl/plpgsql/src/pl_reserved_kwlist.h')
669 || IsNewer(
670 'src/pl/plpgsql/src/pl_unreserved_kwlist_d.h',
671 'src/pl/plpgsql/src/pl_unreserved_kwlist.h'))
673 print
674 "Generating pl_reserved_kwlist_d.h and pl_unreserved_kwlist_d.h...\n";
675 chdir('src/pl/plpgsql/src');
676 system(
677 'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname ReservedPLKeywords pl_reserved_kwlist.h'
679 system(
680 'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname UnreservedPLKeywords pl_unreserved_kwlist.h'
682 chdir('../../../..');
685 if (IsNewer(
686 'src/interfaces/ecpg/preproc/c_kwlist_d.h',
687 'src/interfaces/ecpg/preproc/c_kwlist.h')
688 || IsNewer(
689 'src/interfaces/ecpg/preproc/ecpg_kwlist_d.h',
690 'src/interfaces/ecpg/preproc/ecpg_kwlist.h'))
692 print "Generating c_kwlist_d.h and ecpg_kwlist_d.h...\n";
693 chdir('src/interfaces/ecpg/preproc');
694 system(
695 'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname ScanCKeywords --no-case-fold c_kwlist.h'
697 system(
698 'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname ScanECPGKeywords ecpg_kwlist.h'
700 chdir('../../../..');
703 if (IsNewer(
704 'src/interfaces/ecpg/preproc/preproc.y',
705 'src/backend/parser/gram.y'))
707 print "Generating preproc.y...\n";
708 my $ecpg = 'src/interfaces/ecpg';
709 system("perl $ecpg/preproc/parse.pl --srcdir $ecpg/preproc --parser src/backend/parser/gram.y --output $ecpg/preproc/preproc.y");
712 unless (-f "src/port/pg_config_paths.h")
714 print "Generating pg_config_paths.h...\n";
715 open(my $o, '>', 'src/port/pg_config_paths.h')
716 || confess "Could not open pg_config_paths.h";
717 print $o <<EOF;
718 #define PGBINDIR "/bin"
719 #define PGSHAREDIR "/share"
720 #define SYSCONFDIR "/etc"
721 #define INCLUDEDIR "/include"
722 #define PKGINCLUDEDIR "/include"
723 #define INCLUDEDIRSERVER "/include/server"
724 #define LIBDIR "/lib"
725 #define PKGLIBDIR "/lib"
726 #define LOCALEDIR "/share/locale"
727 #define DOCDIR "/doc"
728 #define HTMLDIR "/doc"
729 #define MANDIR "/man"
731 close($o);
734 my $mf = Project::read_file('src/backend/catalog/Makefile');
735 $mf =~ s{\\\r?\n}{}g;
736 $mf =~ /^CATALOG_HEADERS\s*:?=(.*)$/gm
737 || croak "Could not find CATALOG_HEADERS in Makefile\n";
738 my @bki_srcs = split /\s+/, $1;
739 $mf =~ /^POSTGRES_BKI_DATA\s*:?=[^,]+,(.*)\)$/gm
740 || croak "Could not find POSTGRES_BKI_DATA in Makefile\n";
741 my @bki_data = split /\s+/, $1;
743 my $need_genbki = 0;
744 foreach my $bki (@bki_srcs, @bki_data)
746 next if $bki eq "";
747 if (IsNewer(
748 'src/backend/catalog/bki-stamp',
749 "src/include/catalog/$bki"))
751 $need_genbki = 1;
752 last;
755 $need_genbki = 1
756 if IsNewer('src/backend/catalog/bki-stamp',
757 'src/backend/catalog/genbki.pl');
758 $need_genbki = 1
759 if IsNewer('src/backend/catalog/bki-stamp',
760 'src/backend/catalog/Catalog.pm');
761 if ($need_genbki)
763 chdir('src/backend/catalog');
764 my $bki_srcs = join(' ../../../src/include/catalog/', @bki_srcs);
765 system(
766 "perl genbki.pl --include-path ../../../src/include/ --set-version=$majorver $bki_srcs"
768 open(my $f, '>', 'bki-stamp')
769 || confess "Could not touch bki-stamp";
770 close($f);
771 chdir('../../..');
774 if (IsNewer(
775 'src/include/catalog/header-stamp',
776 'src/backend/catalog/bki-stamp'))
778 # Copy generated headers to include directory.
779 opendir(my $dh, 'src/backend/catalog/')
780 || die "Can't opendir src/backend/catalog/ $!";
781 my @def_headers = grep { /pg_\w+_d\.h$/ } readdir($dh);
782 closedir $dh;
783 foreach my $def_header (@def_headers)
785 copyFile(
786 "src/backend/catalog/$def_header",
787 "src/include/catalog/$def_header");
789 copyFile(
790 'src/backend/catalog/schemapg.h',
791 'src/include/catalog/schemapg.h');
792 copyFile(
793 'src/backend/catalog/system_fk_info.h',
794 'src/include/catalog/system_fk_info.h');
795 open(my $chs, '>', 'src/include/catalog/header-stamp')
796 || confess "Could not touch header-stamp";
797 close($chs);
800 my $nmf = Project::read_file('src/backend/nodes/Makefile');
801 $nmf =~ s{\\\r?\n}{}g;
802 $nmf =~ /^node_headers\s*:?=(.*)$/gm
803 || croak "Could not find node_headers in Makefile\n";
804 my @node_headers = split /\s+/, $1;
805 @node_headers = grep { $_ ne '' } @node_headers;
806 my @node_files = map { "src/include/$_" } @node_headers;
808 my $need_node_support = 0;
809 foreach my $nodefile (@node_files)
811 if (IsNewer('src/backend/nodes/node-support-stamp', $nodefile))
813 $need_node_support = 1;
814 last;
817 $need_node_support = 1
818 if IsNewer(
819 'src/backend/nodes/node-support-stamp',
820 'src/backend/nodes/gen_node_support.pl');
822 if ($need_node_support)
824 system("perl src/backend/nodes/gen_node_support.pl --outdir src/backend/nodes @node_files");
825 open(my $f, '>', 'src/backend/nodes/node-support-stamp')
826 || confess "Could not touch node-support-stamp";
827 close($f);
830 if (IsNewer(
831 'src/include/nodes/nodetags.h',
832 'src/backend/nodes/nodetags.h'))
834 copyFile('src/backend/nodes/nodetags.h',
835 'src/include/nodes/nodetags.h');
838 open(my $o, '>', "doc/src/sgml/version.sgml")
839 || croak "Could not write to version.sgml\n";
840 print $o <<EOF;
841 <!ENTITY version "$package_version">
842 <!ENTITY majorversion "$majorver">
844 close($o);
845 return;
848 # Read lines from input file and substitute symbols using the same
849 # logic that config.status uses. There should be one call of this for
850 # each AC_CONFIG_HEADERS call in configure.ac.
852 # If the "required" argument is true, we also keep track which of our
853 # defines have been found and error out if any are left unused at the
854 # end. That way we avoid accumulating defines in this file that are
855 # no longer used by configure.
856 sub GenerateConfigHeader
858 my ($self, $config_header, $defines, $required) = @_;
860 my $config_header_in = $config_header . '.in';
862 if ( IsNewer($config_header, $config_header_in)
863 || IsNewer($config_header, __FILE__))
865 my %defines_copy = %$defines;
867 open(my $i, '<', $config_header_in)
868 || confess "Could not open $config_header_in\n";
869 open(my $o, '>', $config_header)
870 || confess "Could not write to $config_header\n";
872 print $o
873 "/* $config_header. Generated from $config_header_in by src/tools/msvc/Solution.pm. */\n";
875 while (<$i>)
877 if (m/^#(\s*)undef\s+(\w+)/)
879 my $ws = $1;
880 my $macro = $2;
881 if (exists $defines->{$macro})
883 if (defined $defines->{$macro})
885 print $o "#${ws}define $macro ", $defines->{$macro},
886 "\n";
888 else
890 print $o "/* #${ws}undef $macro */\n";
892 delete $defines_copy{$macro};
894 else
896 croak
897 "undefined symbol: $macro at $config_header line $.";
900 else
902 print $o $_;
905 close($o);
906 close($i);
908 if ($required && scalar(keys %defines_copy) > 0)
910 croak "unused defines: " . join(' ', keys %defines_copy);
915 sub GenerateDefFile
917 my ($self, $deffile, $txtfile, $libname) = @_;
919 if (IsNewer($deffile, $txtfile))
921 print "Generating $deffile...\n";
922 open(my $if, '<', $txtfile) || confess("Could not open $txtfile\n");
923 open(my $of, '>', $deffile) || confess("Could not open $deffile\n");
924 print $of "LIBRARY $libname\nEXPORTS\n";
925 while (<$if>)
927 next if (/^#/);
928 next if (/^\s*$/);
929 my ($f, $o) = split;
930 print $of " $f @ $o\n";
932 close($of);
933 close($if);
935 return;
938 sub AddProject
940 my ($self, $name, $type, $folder, $initialdir) = @_;
942 my $proj =
943 VSObjectFactory::CreateProject($self->{vcver}, $name, $type, $self);
944 push @{ $self->{projects}->{$folder} }, $proj;
945 $proj->AddDir($initialdir) if ($initialdir);
946 if ($self->{options}->{zlib})
948 $proj->AddIncludeDir($self->{options}->{zlib} . '\include');
949 $proj->AddLibrary($self->{options}->{zlib} . '\lib\zdll.lib');
951 if ($self->{options}->{openssl})
953 $proj->AddIncludeDir($self->{options}->{openssl} . '\include');
954 my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
956 # Starting at version 1.1.0 the OpenSSL installers have
957 # changed their library names from:
958 # - libeay to libcrypto
959 # - ssleay to libssl
960 if ( ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
961 || ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
963 my $dbgsuffix;
964 my $libsslpath;
965 my $libcryptopath;
967 # The format name of the libraries is slightly
968 # different between the Win32 and Win64 platform, so
969 # adapt.
970 if (-e "$self->{options}->{openssl}/lib/VC/sslcrypto32MD.lib")
972 # Win32 here, with a debugging library set.
973 $dbgsuffix = 1;
974 $libsslpath = '\lib\VC\libssl32.lib';
975 $libcryptopath = '\lib\VC\libcrypto32.lib';
977 elsif (-e "$self->{options}->{openssl}/lib/VC/sslcrypto64MD.lib")
979 # Win64 here, with a debugging library set.
980 $dbgsuffix = 1;
981 $libsslpath = '\lib\VC\libssl64.lib';
982 $libcryptopath = '\lib\VC\libcrypto64.lib';
984 else
986 # On both Win32 and Win64 the same library
987 # names are used without a debugging context.
988 $dbgsuffix = 0;
989 $libsslpath = '\lib\libssl.lib';
990 $libcryptopath = '\lib\libcrypto.lib';
993 $proj->AddLibrary($self->{options}->{openssl} . $libsslpath,
994 $dbgsuffix);
995 $proj->AddLibrary($self->{options}->{openssl} . $libcryptopath,
996 $dbgsuffix);
998 else
1000 # Choose which set of libraries to use depending on if
1001 # debugging libraries are in place in the installer.
1002 if (-e "$self->{options}->{openssl}/lib/VC/ssleay32MD.lib")
1004 $proj->AddLibrary(
1005 $self->{options}->{openssl} . '\lib\VC\ssleay32.lib', 1);
1006 $proj->AddLibrary(
1007 $self->{options}->{openssl} . '\lib\VC\libeay32.lib', 1);
1009 else
1011 # We don't expect the config-specific library
1012 # to be here, so don't ask for it in last
1013 # parameter.
1014 $proj->AddLibrary(
1015 $self->{options}->{openssl} . '\lib\ssleay32.lib', 0);
1016 $proj->AddLibrary(
1017 $self->{options}->{openssl} . '\lib\libeay32.lib', 0);
1021 if ($self->{options}->{nls})
1023 $proj->AddIncludeDir($self->{options}->{nls} . '\include');
1024 $proj->AddLibrary($self->{options}->{nls} . '\lib\libintl.lib');
1026 if ($self->{options}->{gss})
1028 $proj->AddIncludeDir($self->{options}->{gss} . '\include');
1029 $proj->AddIncludeDir($self->{options}->{gss} . '\include\krb5');
1030 if ($self->{platform} eq 'Win32')
1032 $proj->AddLibrary(
1033 $self->{options}->{gss} . '\lib\i386\krb5_32.lib');
1034 $proj->AddLibrary(
1035 $self->{options}->{gss} . '\lib\i386\comerr32.lib');
1036 $proj->AddLibrary(
1037 $self->{options}->{gss} . '\lib\i386\gssapi32.lib');
1039 else
1041 $proj->AddLibrary(
1042 $self->{options}->{gss} . '\lib\amd64\krb5_64.lib');
1043 $proj->AddLibrary(
1044 $self->{options}->{gss} . '\lib\amd64\comerr64.lib');
1045 $proj->AddLibrary(
1046 $self->{options}->{gss} . '\lib\amd64\gssapi64.lib');
1049 if ($self->{options}->{iconv})
1051 $proj->AddIncludeDir($self->{options}->{iconv} . '\include');
1052 $proj->AddLibrary($self->{options}->{iconv} . '\lib\iconv.lib');
1054 if ($self->{options}->{icu})
1056 $proj->AddIncludeDir($self->{options}->{icu} . '\include');
1057 if ($self->{platform} eq 'Win32')
1059 $proj->AddLibrary($self->{options}->{icu} . '\lib\icuin.lib');
1060 $proj->AddLibrary($self->{options}->{icu} . '\lib\icuuc.lib');
1061 $proj->AddLibrary($self->{options}->{icu} . '\lib\icudt.lib');
1063 else
1065 $proj->AddLibrary($self->{options}->{icu} . '\lib64\icuin.lib');
1066 $proj->AddLibrary($self->{options}->{icu} . '\lib64\icuuc.lib');
1067 $proj->AddLibrary($self->{options}->{icu} . '\lib64\icudt.lib');
1070 if ($self->{options}->{xml})
1072 $proj->AddIncludeDir($self->{options}->{xml} . '\include');
1073 $proj->AddIncludeDir($self->{options}->{xml} . '\include\libxml2');
1074 $proj->AddLibrary($self->{options}->{xml} . '\lib\libxml2.lib');
1076 if ($self->{options}->{xslt})
1078 $proj->AddIncludeDir($self->{options}->{xslt} . '\include');
1079 $proj->AddLibrary($self->{options}->{xslt} . '\lib\libxslt.lib');
1081 if ($self->{options}->{lz4})
1083 $proj->AddIncludeDir($self->{options}->{lz4} . '\include');
1084 $proj->AddLibrary($self->{options}->{lz4} . '\lib\liblz4.lib');
1086 if ($self->{options}->{zstd})
1088 $proj->AddIncludeDir($self->{options}->{zstd} . '\include');
1089 $proj->AddLibrary($self->{options}->{zstd} . '\lib\libzstd.lib');
1091 if ($self->{options}->{uuid})
1093 $proj->AddIncludeDir($self->{options}->{uuid} . '\include');
1094 $proj->AddLibrary($self->{options}->{uuid} . '\lib\uuid.lib');
1096 return $proj;
1099 sub Save
1101 my ($self) = @_;
1102 my %flduid;
1104 $self->GenerateFiles();
1105 foreach my $fld (keys %{ $self->{projects} })
1107 foreach my $proj (@{ $self->{projects}->{$fld} })
1109 $proj->Save();
1113 open(my $sln, '>', "pgsql.sln") || croak "Could not write to pgsql.sln\n";
1114 print $sln <<EOF;
1115 Microsoft Visual Studio Solution File, Format Version $self->{solutionFileVersion}
1116 # $self->{visualStudioName}
1119 print $sln $self->GetAdditionalHeaders();
1121 foreach my $fld (keys %{ $self->{projects} })
1123 foreach my $proj (@{ $self->{projects}->{$fld} })
1125 print $sln <<EOF;
1126 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "$proj->{name}", "$proj->{name}$proj->{filenameExtension}", "$proj->{guid}"
1127 EndProject
1130 if ($fld ne "")
1132 $flduid{$fld} = $^O eq "MSWin32" ? Win32::GuidGen() : 'FAKE';
1133 print $sln <<EOF;
1134 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "$fld", "$fld", "$flduid{$fld}"
1135 EndProject
1140 print $sln <<EOF;
1141 Global
1142 GlobalSection(SolutionConfigurationPlatforms) = preSolution
1143 Debug|$self->{platform}= Debug|$self->{platform}
1144 Release|$self->{platform} = Release|$self->{platform}
1145 EndGlobalSection
1146 GlobalSection(ProjectConfigurationPlatforms) = postSolution
1149 foreach my $fld (keys %{ $self->{projects} })
1151 foreach my $proj (@{ $self->{projects}->{$fld} })
1153 print $sln <<EOF;
1154 $proj->{guid}.Debug|$self->{platform}.ActiveCfg = Debug|$self->{platform}
1155 $proj->{guid}.Debug|$self->{platform}.Build.0 = Debug|$self->{platform}
1156 $proj->{guid}.Release|$self->{platform}.ActiveCfg = Release|$self->{platform}
1157 $proj->{guid}.Release|$self->{platform}.Build.0 = Release|$self->{platform}
1162 print $sln <<EOF;
1163 EndGlobalSection
1164 GlobalSection(SolutionProperties) = preSolution
1165 HideSolutionNode = FALSE
1166 EndGlobalSection
1167 GlobalSection(NestedProjects) = preSolution
1170 foreach my $fld (keys %{ $self->{projects} })
1172 next if ($fld eq "");
1173 foreach my $proj (@{ $self->{projects}->{$fld} })
1175 print $sln "\t\t$proj->{guid} = $flduid{$fld}\n";
1179 print $sln <<EOF;
1180 EndGlobalSection
1181 EndGlobal
1183 close($sln);
1184 return;
1187 sub GetFakeConfigure
1189 my $self = shift;
1191 my $cfg = '--enable-thread-safety';
1192 $cfg .= ' --enable-cassert' if ($self->{options}->{asserts});
1193 $cfg .= ' --enable-nls' if ($self->{options}->{nls});
1194 $cfg .= ' --enable-tap-tests' if ($self->{options}->{tap_tests});
1195 $cfg .= ' --with-ldap' if ($self->{options}->{ldap});
1196 $cfg .= ' --without-zlib' unless ($self->{options}->{zlib});
1197 $cfg .= ' --with-extra-version' if ($self->{options}->{extraver});
1198 $cfg .= ' --with-ssl=openssl' if ($self->{options}->{openssl});
1199 $cfg .= ' --with-uuid' if ($self->{options}->{uuid});
1200 $cfg .= ' --with-libxml' if ($self->{options}->{xml});
1201 $cfg .= ' --with-libxslt' if ($self->{options}->{xslt});
1202 $cfg .= ' --with-lz4' if ($self->{options}->{lz4});
1203 $cfg .= ' --with-zstd' if ($self->{options}->{zstd});
1204 $cfg .= ' --with-gssapi' if ($self->{options}->{gss});
1205 $cfg .= ' --with-icu' if ($self->{options}->{icu});
1206 $cfg .= ' --with-tcl' if ($self->{options}->{tcl});
1207 $cfg .= ' --with-perl' if ($self->{options}->{perl});
1208 $cfg .= ' --with-python' if ($self->{options}->{python});
1209 my $port = $self->{options}->{'--with-pgport'};
1210 $cfg .= " --with-pgport=$port" if defined($port);
1212 return $cfg;
1215 package VS2015Solution;
1218 # Package that encapsulates a Visual Studio 2015 solution file
1221 use Carp;
1222 use strict;
1223 use warnings;
1224 use base qw(Solution);
1226 no warnings qw(redefine); ## no critic
1228 sub new
1230 my $classname = shift;
1231 my $self = $classname->SUPER::_new(@_);
1232 bless($self, $classname);
1234 $self->{solutionFileVersion} = '12.00';
1235 $self->{vcver} = '14.00';
1236 $self->{visualStudioName} = 'Visual Studio 2015';
1237 $self->{VisualStudioVersion} = '14.0.24730.2';
1238 $self->{MinimumVisualStudioVersion} = '10.0.40219.1';
1240 return $self;
1243 package VS2017Solution;
1246 # Package that encapsulates a Visual Studio 2017 solution file
1249 use Carp;
1250 use strict;
1251 use warnings;
1252 use base qw(Solution);
1254 no warnings qw(redefine); ## no critic
1256 sub new
1258 my $classname = shift;
1259 my $self = $classname->SUPER::_new(@_);
1260 bless($self, $classname);
1262 $self->{solutionFileVersion} = '12.00';
1263 $self->{vcver} = '15.00';
1264 $self->{visualStudioName} = 'Visual Studio 2017';
1265 $self->{VisualStudioVersion} = '15.0.26730.3';
1266 $self->{MinimumVisualStudioVersion} = '10.0.40219.1';
1268 return $self;
1271 package VS2019Solution;
1274 # Package that encapsulates a Visual Studio 2019 solution file
1277 use Carp;
1278 use strict;
1279 use warnings;
1280 use base qw(Solution);
1282 no warnings qw(redefine); ## no critic
1284 sub new
1286 my $classname = shift;
1287 my $self = $classname->SUPER::_new(@_);
1288 bless($self, $classname);
1290 $self->{solutionFileVersion} = '12.00';
1291 $self->{vcver} = '16.00';
1292 $self->{visualStudioName} = 'Visual Studio 2019';
1293 $self->{VisualStudioVersion} = '16.0.28729.10';
1294 $self->{MinimumVisualStudioVersion} = '10.0.40219.1';
1296 return $self;
1299 package VS2022Solution;
1302 # Package that encapsulates a Visual Studio 2022 solution file
1305 use Carp;
1306 use strict;
1307 use warnings;
1308 use base qw(Solution);
1310 no warnings qw(redefine); ## no critic
1312 sub new
1314 my $classname = shift;
1315 my $self = $classname->SUPER::_new(@_);
1316 bless($self, $classname);
1318 $self->{solutionFileVersion} = '12.00';
1319 $self->{vcver} = '17.00';
1320 $self->{visualStudioName} = 'Visual Studio 2022';
1321 $self->{VisualStudioVersion} = '17.0.31903.59';
1322 $self->{MinimumVisualStudioVersion} = '10.0.40219.1';
1324 return $self;
1327 sub GetAdditionalHeaders
1329 my ($self, $f) = @_;
1331 return qq|VisualStudioVersion = $self->{VisualStudioVersion}
1332 MinimumVisualStudioVersion = $self->{MinimumVisualStudioVersion}