4 # Package that generates build files for msvc build
6 # src/tools/msvc/Mkvcbuild.pm
18 use List::Util qw(first);
21 our (@ISA, @EXPORT_OK);
23 @EXPORT_OK = qw(Mkvcbuild);
32 # Set of variables for modules in contrib/ and src/test/modules/
33 my $contrib_defines = { 'refint' => 'REFINT_VERBOSE' };
34 my @contrib_uselibpq = ('dblink', 'oid2name', 'postgres_fdw', 'vacuumlo');
35 my @contrib_uselibpgport = ('oid2name', 'pg_standby', 'vacuumlo');
36 my @contrib_uselibpgcommon = ('oid2name', 'pg_standby', 'vacuumlo');
37 my $contrib_extralibs = undef;
38 my $contrib_extraincludes =
39 { 'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend'] };
40 my $contrib_extrasource = {
41 'cube' => [ 'contrib/cube/cubescan.l', 'contrib/cube/cubeparse.y' ],
42 'seg' => [ 'contrib/seg/segscan.l', 'contrib/seg/segparse.y' ], };
43 my @contrib_excludes = (
44 'commit_ts', 'hstore_plperl', 'hstore_plpython', 'intagg',
45 'ltree_plpython', 'pgcrypto', 'sepgsql', 'brin',
48 # Set of variables for frontend modules
49 my $frontend_defines = { 'initdb' => 'FRONTEND' };
50 my @frontend_uselibpq = ('pg_ctl', 'pg_upgrade', 'pgbench', 'psql');
51 my @frontend_uselibpgport = (
52 'pg_archivecleanup', 'pg_test_fsync',
53 'pg_test_timing', 'pg_upgrade',
54 'pg_xlogdump', 'pgbench');
55 my @frontend_uselibpgcommon = (
56 'pg_archivecleanup', 'pg_test_fsync',
57 'pg_test_timing', 'pg_upgrade',
58 'pg_xlogdump', 'pgbench');
59 my $frontend_extralibs = {
60 'initdb' => ['ws2_32.lib'],
61 'pg_restore' => ['ws2_32.lib'],
62 'pgbench' => ['ws2_32.lib'],
63 'psql' => ['ws2_32.lib'] };
64 my $frontend_extraincludes = {
65 'initdb' => ['src/timezone'],
66 'psql' => [ 'src/backend' ],
67 'pgbench' => [ 'src/bin/psql' ] };
68 my $frontend_extrasource = {
69 'psql' => ['src/bin/psql/psqlscan.l', 'src/bin/psql/psqlscanslash.l'],
71 [ 'src/bin/pgbench/exprscan.l', 'src/bin/pgbench/exprparse.y',
72 'src/bin/psql/psqlscan.l' ] };
73 my @frontend_excludes = (
74 'pgevent', 'pg_basebackup', 'pg_rewind', 'pg_dump',
75 'pg_xlogdump', 'scripts', 'pgbench');
81 chdir('../../..') if (-d '../msvc' && -d '../../../src');
82 die 'Must run from root or msvc directory'
83 unless (-d 'src/tools/msvc' && -d 'src');
85 my $vsVersion = DetermineVisualStudioVersion();
87 $solution = CreateSolution($vsVersion, $config);
89 our @pgportfiles = qw(
90 chklocale.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c random.c
91 srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
92 erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
93 pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
94 mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
95 sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c
96 win32env.c win32error.c win32security.c win32setlocale.c);
98 push(@pgportfiles, 'rint.c') if ($vsVersion < '12.00');
100 if ($vsVersion >= '9.00')
102 push(@pgportfiles, 'pg_crc32c_choose.c');
103 push(@pgportfiles, 'pg_crc32c_sse42.c');
104 push(@pgportfiles, 'pg_crc32c_sb8.c');
108 push(@pgportfiles, 'pg_crc32c_sb8.c');
111 our @pgcommonallfiles = qw(
112 config_info.c controldata_utils.c exec.c keywords.c
113 pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
114 string.c username.c wait_error.c);
116 our @pgcommonfrontendfiles = (
117 @pgcommonallfiles, qw(fe_memutils.c
118 restricted_token.c));
120 our @pgcommonbkndfiles = @pgcommonallfiles;
122 our @pgfeutilsfiles = qw(
123 mbprint.c print.c simple_list.c string_utils.c);
125 $libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
126 $libpgport->AddDefine('FRONTEND');
127 $libpgport->AddFiles('src/port', @pgportfiles);
129 $libpgcommon = $solution->AddProject('libpgcommon', 'lib', 'misc');
130 $libpgcommon->AddDefine('FRONTEND');
131 $libpgcommon->AddFiles('src/common', @pgcommonfrontendfiles);
133 $libpgfeutils = $solution->AddProject('libpgfeutils', 'lib', 'misc');
134 $libpgfeutils->AddDefine('FRONTEND');
135 $libpgfeutils->AddIncludeDir('src/interfaces/libpq');
136 $libpgfeutils->AddFiles('src/fe_utils', @pgfeutilsfiles);
138 $postgres = $solution->AddProject('postgres', 'exe', '', 'src/backend');
139 $postgres->AddIncludeDir('src/backend');
140 $postgres->AddDir('src/backend/port/win32');
141 $postgres->AddFile('src/backend/utils/fmgrtab.c');
142 $postgres->ReplaceFile(
143 'src/backend/port/dynloader.c',
144 'src/backend/port/dynloader/win32.c');
145 $postgres->ReplaceFile('src/backend/port/pg_sema.c',
146 'src/backend/port/win32_sema.c');
147 $postgres->ReplaceFile('src/backend/port/pg_shmem.c',
148 'src/backend/port/win32_shmem.c');
149 $postgres->AddFiles('src/port', @pgportfiles);
150 $postgres->AddFiles('src/common', @pgcommonbkndfiles);
151 $postgres->AddDir('src/timezone');
153 # We need source files from src/timezone, but that directory's resource
154 # file pertains to "zic", not to the backend.
155 $postgres->RemoveFile('src/timezone/win32ver.rc');
156 $postgres->AddFiles('src/backend/parser', 'scan.l', 'gram.y');
157 $postgres->AddFiles('src/backend/bootstrap', 'bootscanner.l',
159 $postgres->AddFiles('src/backend/utils/misc', 'guc-file.l');
160 $postgres->AddFiles('src/backend/replication', 'repl_scanner.l',
162 $postgres->AddDefine('BUILDING_DLL');
163 $postgres->AddLibrary('secur32.lib');
164 $postgres->AddLibrary('ws2_32.lib');
165 $postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
166 $postgres->FullExportDLL('postgres.lib');
168 # The OBJS scraper doesn't know about ifdefs, so remove be-secure-openssl.c
169 # if building without OpenSSL
170 if (!$solution->{options}->{openssl})
172 $postgres->RemoveFile('src/backend/libpq/be-secure-openssl.c');
175 my $snowball = $solution->AddProject('dict_snowball', 'dll', '',
176 'src/backend/snowball');
178 # This Makefile uses VPATH to find most source files in a subdirectory.
179 $snowball->RelocateFiles(
180 'src/backend/snowball/libstemmer',
182 return shift !~ /(dict_snowball.c|win32ver.rc)$/;
184 $snowball->AddIncludeDir('src/include/snowball');
185 $snowball->AddReference($postgres);
188 $solution->AddProject('plpgsql', 'dll', 'PLs', 'src/pl/plpgsql/src');
189 $plpgsql->AddFiles('src/pl/plpgsql/src', 'pl_gram.y');
190 $plpgsql->AddReference($postgres);
192 if ($solution->{options}->{tcl})
195 $solution->AddProject('pltcl', 'dll', 'PLs', 'src/pl/tcl');
196 $pltcl->AddIncludeDir($solution->{options}->{tcl} . '/include');
197 $pltcl->AddReference($postgres);
198 if (-e $solution->{options}->{tcl} . '/lib/tcl85.lib')
201 $solution->{options}->{tcl} . '/lib/tcl85.lib');
206 $solution->{options}->{tcl} . '/lib/tcl84.lib');
210 $libpq = $solution->AddProject('libpq', 'dll', 'interfaces',
211 'src/interfaces/libpq');
212 $libpq->AddDefine('FRONTEND');
213 $libpq->AddDefine('UNSAFE_STAT_OK');
214 $libpq->AddIncludeDir('src/port');
215 $libpq->AddLibrary('secur32.lib');
216 $libpq->AddLibrary('ws2_32.lib');
217 $libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
218 $libpq->UseDef('src/interfaces/libpq/libpqdll.def');
219 $libpq->ReplaceFile('src/interfaces/libpq/libpqrc.c',
220 'src/interfaces/libpq/libpq.rc');
221 $libpq->AddReference($libpgport);
223 # The OBJS scraper doesn't know about ifdefs, so remove fe-secure-openssl.c
224 # if building without OpenSSL
225 if (!$solution->{options}->{openssl})
227 $libpq->RemoveFile('src/interfaces/libpq/fe-secure-openssl.c');
230 my $libpqwalreceiver =
231 $solution->AddProject('libpqwalreceiver', 'dll', '',
232 'src/backend/replication/libpqwalreceiver');
233 $libpqwalreceiver->AddIncludeDir('src/interfaces/libpq');
234 $libpqwalreceiver->AddReference($postgres, $libpq);
236 my $pgtypes = $solution->AddProject(
238 'interfaces', 'src/interfaces/ecpg/pgtypeslib');
239 $pgtypes->AddDefine('FRONTEND');
240 $pgtypes->AddReference($libpgport);
241 $pgtypes->UseDef('src/interfaces/ecpg/pgtypeslib/pgtypeslib.def');
242 $pgtypes->AddIncludeDir('src/interfaces/ecpg/include');
244 my $libecpg = $solution->AddProject('libecpg', 'dll', 'interfaces',
245 'src/interfaces/ecpg/ecpglib');
246 $libecpg->AddDefine('FRONTEND');
247 $libecpg->AddIncludeDir('src/interfaces/ecpg/include');
248 $libecpg->AddIncludeDir('src/interfaces/libpq');
249 $libecpg->AddIncludeDir('src/port');
250 $libecpg->UseDef('src/interfaces/ecpg/ecpglib/ecpglib.def');
251 $libecpg->AddLibrary('ws2_32.lib');
252 $libecpg->AddReference($libpq, $pgtypes, $libpgport);
254 my $libecpgcompat = $solution->AddProject(
255 'libecpg_compat', 'dll',
256 'interfaces', 'src/interfaces/ecpg/compatlib');
257 $libecpgcompat->AddDefine('FRONTEND');
258 $libecpgcompat->AddIncludeDir('src/interfaces/ecpg/include');
259 $libecpgcompat->AddIncludeDir('src/interfaces/libpq');
260 $libecpgcompat->UseDef('src/interfaces/ecpg/compatlib/compatlib.def');
261 $libecpgcompat->AddReference($pgtypes, $libecpg, $libpgport);
263 my $ecpg = $solution->AddProject('ecpg', 'exe', 'interfaces',
264 'src/interfaces/ecpg/preproc');
265 $ecpg->AddIncludeDir('src/interfaces/ecpg/include');
266 $ecpg->AddIncludeDir('src/interfaces/libpq');
267 $ecpg->AddPrefixInclude('src/interfaces/ecpg/preproc');
268 $ecpg->AddFiles('src/interfaces/ecpg/preproc', 'pgc.l', 'preproc.y');
269 $ecpg->AddDefine('MAJOR_VERSION=4');
270 $ecpg->AddDefine('MINOR_VERSION=12');
271 $ecpg->AddDefine('PATCHLEVEL=0');
272 $ecpg->AddDefine('ECPG_COMPILE');
273 $ecpg->AddReference($libpgcommon, $libpgport);
276 $solution->AddProject('pg_regress_ecpg', 'exe', 'misc');
277 $pgregress_ecpg->AddFile('src/interfaces/ecpg/test/pg_regress_ecpg.c');
278 $pgregress_ecpg->AddFile('src/test/regress/pg_regress.c');
279 $pgregress_ecpg->AddIncludeDir('src/port');
280 $pgregress_ecpg->AddIncludeDir('src/test/regress');
281 $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
282 $pgregress_ecpg->AddLibrary('ws2_32.lib');
283 $pgregress_ecpg->AddDirResourceFile('src/interfaces/ecpg/test');
284 $pgregress_ecpg->AddReference($libpgcommon, $libpgport);
286 my $isolation_tester =
287 $solution->AddProject('isolationtester', 'exe', 'misc');
288 $isolation_tester->AddFile('src/test/isolation/isolationtester.c');
289 $isolation_tester->AddFile('src/test/isolation/specparse.y');
290 $isolation_tester->AddFile('src/test/isolation/specscanner.l');
291 $isolation_tester->AddFile('src/test/isolation/specparse.c');
292 $isolation_tester->AddIncludeDir('src/test/isolation');
293 $isolation_tester->AddIncludeDir('src/port');
294 $isolation_tester->AddIncludeDir('src/test/regress');
295 $isolation_tester->AddIncludeDir('src/interfaces/libpq');
296 $isolation_tester->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
297 $isolation_tester->AddLibrary('ws2_32.lib');
298 $isolation_tester->AddDirResourceFile('src/test/isolation');
299 $isolation_tester->AddReference($libpq, $libpgcommon, $libpgport);
301 my $pgregress_isolation =
302 $solution->AddProject('pg_isolation_regress', 'exe', 'misc');
303 $pgregress_isolation->AddFile('src/test/isolation/isolation_main.c');
304 $pgregress_isolation->AddFile('src/test/regress/pg_regress.c');
305 $pgregress_isolation->AddIncludeDir('src/port');
306 $pgregress_isolation->AddIncludeDir('src/test/regress');
307 $pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
308 $pgregress_isolation->AddLibrary('ws2_32.lib');
309 $pgregress_isolation->AddDirResourceFile('src/test/isolation');
310 $pgregress_isolation->AddReference($libpgcommon, $libpgport);
314 opendir($D, 'src/bin') || croak "Could not opendir on src/bin!\n";
315 while (my $d = readdir($D))
317 next if ($d =~ /^\./);
318 next unless (-f "src/bin/$d/Makefile");
319 next if (grep { /^$d$/ } @frontend_excludes);
320 AddSimpleFrontend($d);
323 my $pgbasebackup = AddSimpleFrontend('pg_basebackup', 1);
324 $pgbasebackup->AddFile('src/bin/pg_basebackup/pg_basebackup.c');
325 $pgbasebackup->AddLibrary('ws2_32.lib');
327 my $pgreceivexlog = AddSimpleFrontend('pg_basebackup', 1);
328 $pgreceivexlog->{name} = 'pg_receivexlog';
329 $pgreceivexlog->AddFile('src/bin/pg_basebackup/pg_receivexlog.c');
330 $pgreceivexlog->AddLibrary('ws2_32.lib');
332 my $pgrecvlogical = AddSimpleFrontend('pg_basebackup', 1);
333 $pgrecvlogical->{name} = 'pg_recvlogical';
334 $pgrecvlogical->AddFile('src/bin/pg_basebackup/pg_recvlogical.c');
335 $pgrecvlogical->AddLibrary('ws2_32.lib');
337 my $pgrewind = AddSimpleFrontend('pg_rewind', 1);
338 $pgrewind->{name} = 'pg_rewind';
339 $pgrewind->AddFile('src/backend/access/transam/xlogreader.c');
340 $pgrewind->AddLibrary('ws2_32.lib');
341 $pgrewind->AddDefine('FRONTEND');
343 my $pgevent = $solution->AddProject('pgevent', 'dll', 'bin');
344 $pgevent->AddFiles('src/bin/pgevent', 'pgevent.c', 'pgmsgevent.rc');
345 $pgevent->AddResourceFile('src/bin/pgevent', 'Eventlog message formatter',
347 $pgevent->RemoveFile('src/bin/pgevent/win32ver.rc');
348 $pgevent->UseDef('src/bin/pgevent/pgevent.def');
349 $pgevent->DisableLinkerWarnings('4104');
351 my $pgdump = AddSimpleFrontend('pg_dump', 1);
352 $pgdump->AddIncludeDir('src/backend');
353 $pgdump->AddFile('src/bin/pg_dump/pg_dump.c');
354 $pgdump->AddFile('src/bin/pg_dump/common.c');
355 $pgdump->AddFile('src/bin/pg_dump/pg_dump_sort.c');
356 $pgdump->AddLibrary('ws2_32.lib');
358 my $pgdumpall = AddSimpleFrontend('pg_dump', 1);
360 # pg_dumpall doesn't use the files in the Makefile's $(OBJS), unlike
361 # pg_dump and pg_restore.
362 # So remove their sources from the object, keeping the other setup that
363 # AddSimpleFrontend() has done.
364 my @nodumpall = grep { m!src/bin/pg_dump/.*\.c$! }
365 keys %{ $pgdumpall->{files} };
366 delete @{ $pgdumpall->{files} }{@nodumpall};
367 $pgdumpall->{name} = 'pg_dumpall';
368 $pgdumpall->AddIncludeDir('src/backend');
369 $pgdumpall->AddFile('src/bin/pg_dump/pg_dumpall.c');
370 $pgdumpall->AddFile('src/bin/pg_dump/dumputils.c');
371 $pgdumpall->AddLibrary('ws2_32.lib');
373 my $pgrestore = AddSimpleFrontend('pg_dump', 1);
374 $pgrestore->{name} = 'pg_restore';
375 $pgrestore->AddIncludeDir('src/backend');
376 $pgrestore->AddFile('src/bin/pg_dump/pg_restore.c');
377 $pgrestore->AddLibrary('ws2_32.lib');
379 my $zic = $solution->AddProject('zic', 'exe', 'utils');
380 $zic->AddFiles('src/timezone', 'zic.c', 'ialloc.c', 'scheck.c',
382 $zic->AddDirResourceFile('src/timezone');
383 $zic->AddReference($libpgcommon, $libpgport);
385 if ($solution->{options}->{xml})
387 $contrib_extraincludes->{'pgxml'} = [
388 $solution->{options}->{xml} . '/include',
389 $solution->{options}->{xslt} . '/include',
390 $solution->{options}->{iconv} . '/include' ];
392 $contrib_extralibs->{'pgxml'} = [
393 $solution->{options}->{xml} . '/lib/libxml2.lib',
394 $solution->{options}->{xslt} . '/lib/libxslt.lib' ];
398 push @contrib_excludes, 'xml2';
401 if (!$solution->{options}->{openssl})
403 push @contrib_excludes, 'sslinfo';
406 if ($solution->{options}->{uuid})
408 $contrib_extraincludes->{'uuid-ossp'} =
409 [ $solution->{options}->{uuid} . '/include' ];
410 $contrib_extralibs->{'uuid-ossp'} =
411 [ $solution->{options}->{uuid} . '/lib/uuid.lib' ];
415 push @contrib_excludes, 'uuid-ossp';
418 # AddProject() does not recognize the constructs used to populate OBJS in
419 # the pgcrypto Makefile, so it will discover no files.
421 $solution->AddProject('pgcrypto', 'dll', 'crypto', 'contrib/pgcrypto');
423 'contrib/pgcrypto', 'pgcrypto.c',
425 'px-crypt.c', 'crypt-gensalt.c',
426 'crypt-blowfish.c', 'crypt-des.c',
427 'crypt-md5.c', 'mbuf.c',
428 'pgp.c', 'pgp-armor.c',
429 'pgp-cfb.c', 'pgp-compress.c',
430 'pgp-decrypt.c', 'pgp-encrypt.c',
431 'pgp-info.c', 'pgp-mpi.c',
432 'pgp-pubdec.c', 'pgp-pubenc.c',
433 'pgp-pubkey.c', 'pgp-s2k.c',
435 if ($solution->{options}->{openssl})
437 $pgcrypto->AddFiles('contrib/pgcrypto', 'openssl.c',
438 'pgp-mpi-openssl.c');
443 'contrib/pgcrypto', 'md5.c',
445 'internal.c', 'internal-sha2.c',
446 'blf.c', 'rijndael.c',
447 'fortuna.c', 'random.c',
448 'pgp-mpi-internal.c', 'imath.c');
450 $pgcrypto->AddReference($postgres);
451 $pgcrypto->AddLibrary('ws2_32.lib');
452 my $mf = Project::read_file('contrib/pgcrypto/Makefile');
453 GenerateContribSqlFiles('pgcrypto', $mf);
455 foreach my $subdir ('contrib', 'src/test/modules')
457 opendir($D, $subdir) || croak "Could not opendir on $subdir!\n";
458 while (my $d = readdir($D))
460 next if ($d =~ /^\./);
461 next unless (-f "$subdir/$d/Makefile");
462 next if (grep { /^$d$/ } @contrib_excludes);
463 AddContrib($subdir, $d);
468 # Build Perl and Python modules after contrib/ modules to satisfy some
469 # dependencies with transform contrib modules, like hstore_plpython
470 # ltree_plpython and hstore_plperl.
471 if ($solution->{options}->{python})
474 # Attempt to get python version and location.
475 # Assume python.exe in specified dir.
476 my $pythonprog = "import sys;print(sys.prefix);"
477 . "print(str(sys.version_info[0])+str(sys.version_info[1]))";
479 $solution->{options}->{python} . "\\python -c \"$pythonprog\"";
480 my $pyout = `$prefixcmd`;
481 die "Could not query for python version!\n" if $?;
482 my ($pyprefix, $pyver) = split(/\r?\n/, $pyout);
484 # Sometimes (always?) if python is not present, the execution
485 # appears to work, but gives no data...
486 die "Failed to query python for version information\n"
487 if (!(defined($pyprefix) && defined($pyver)));
489 my $pymajorver = substr($pyver, 0, 1);
490 my $plpython = $solution->AddProject('plpython' . $pymajorver,
491 'dll', 'PLs', 'src/pl/plpython');
492 $plpython->AddIncludeDir($pyprefix . '/include');
493 $plpython->AddLibrary($pyprefix . "/Libs/python$pyver.lib");
494 $plpython->AddReference($postgres);
496 # Add transform modules dependent on plpython
498 'hstore_plpython' . $pymajorver, 'contrib/hstore_plpython',
499 'plpython' . $pymajorver, 'src/pl/plpython',
500 'hstore', 'contrib/hstore');
502 'ltree_plpython' . $pymajorver, 'contrib/ltree_plpython',
503 'plpython' . $pymajorver, 'src/pl/plpython',
504 'ltree', 'contrib/ltree');
507 if ($solution->{options}->{perl})
509 my $plperlsrc = "src/pl/plperl/";
511 $solution->AddProject('plperl', 'dll', 'PLs', 'src/pl/plperl');
512 $plperl->AddIncludeDir($solution->{options}->{perl} . '/lib/CORE');
513 $plperl->AddDefine('PLPERL_HAVE_UID_GID');
514 foreach my $xs ('SPI.xs', 'Util.xs')
516 (my $xsc = $xs) =~ s/\.xs/.c/;
517 if (Solution::IsNewer("$plperlsrc$xsc", "$plperlsrc$xs"))
519 my $xsubppdir = first { -e "$_/ExtUtils/xsubpp" } @INC;
520 print "Building $plperlsrc$xsc...\n";
521 system( $solution->{options}->{perl}
523 . "$xsubppdir/ExtUtils/xsubpp -typemap "
524 . $solution->{options}->{perl}
525 . '/lib/ExtUtils/typemap '
527 . ">$plperlsrc$xsc");
528 if ((!(-f "$plperlsrc$xsc")) || -z "$plperlsrc$xsc")
530 unlink("$plperlsrc$xsc"); # if zero size
531 die "Failed to create $xsc.\n";
535 if (Solution::IsNewer(
536 'src/pl/plperl/perlchunks.h',
537 'src/pl/plperl/plc_perlboot.pl')
538 || Solution::IsNewer(
539 'src/pl/plperl/perlchunks.h',
540 'src/pl/plperl/plc_trusted.pl'))
542 print 'Building src/pl/plperl/perlchunks.h ...' . "\n";
543 my $basedir = getcwd;
544 chdir 'src/pl/plperl';
545 system( $solution->{options}->{perl}
548 . '--strip="^(\#.*|\s*)$$" '
549 . 'plc_perlboot.pl plc_trusted.pl '
552 if ((!(-f 'src/pl/plperl/perlchunks.h'))
553 || -z 'src/pl/plperl/perlchunks.h')
555 unlink('src/pl/plperl/perlchunks.h'); # if zero size
556 die 'Failed to create perlchunks.h' . "\n";
559 if (Solution::IsNewer(
560 'src/pl/plperl/plperl_opmask.h',
561 'src/pl/plperl/plperl_opmask.pl'))
563 print 'Building src/pl/plperl/plperl_opmask.h ...' . "\n";
564 my $basedir = getcwd;
565 chdir 'src/pl/plperl';
566 system( $solution->{options}->{perl}
568 . 'plperl_opmask.pl '
569 . 'plperl_opmask.h');
571 if ((!(-f 'src/pl/plperl/plperl_opmask.h'))
572 || -z 'src/pl/plperl/plperl_opmask.h')
574 unlink('src/pl/plperl/plperl_opmask.h'); # if zero size
575 die 'Failed to create plperl_opmask.h' . "\n";
578 $plperl->AddReference($postgres);
580 grep { /perl\d+.lib$/ }
581 glob($solution->{options}->{perl} . '\lib\CORE\perl*.lib');
584 $plperl->AddLibrary($perl_libs[0]);
588 die "could not identify perl library version";
591 # Add transform module dependent on plperl
592 my $hstore_plperl = AddTransformModule(
593 'hstore_plperl', 'contrib/hstore_plperl',
594 'plperl', 'src/pl/plperl',
595 'hstore', 'contrib/hstore');
596 $hstore_plperl->AddDefine('PLPERL_HAVE_UID_GID');
600 Project::read_file('src/backend/utils/mb/conversion_procs/Makefile');
601 $mf =~ s{\\\r?\n}{}g;
602 $mf =~ m{SUBDIRS\s*=\s*(.*)$}m
603 || die 'Could not match in conversion makefile' . "\n";
604 foreach my $sub (split /\s+/, $1)
606 my $dir = 'src/backend/utils/mb/conversion_procs/' . $sub;
607 my $p = $solution->AddProject($sub, 'dll', 'conversion procs', $dir);
608 $p->AddFile("$dir/$sub.c"); # implicit source file
609 $p->AddReference($postgres);
612 $mf = Project::read_file('src/bin/scripts/Makefile');
613 $mf =~ s{\\\r?\n}{}g;
614 $mf =~ m{PROGRAMS\s*=\s*(.*)$}m
615 || die 'Could not match in bin/scripts/Makefile' . "\n";
616 foreach my $prg (split /\s+/, $1)
618 my $proj = $solution->AddProject($prg, 'exe', 'bin');
619 $mf =~ m{$prg\s*:\s*(.*)$}m
620 || die 'Could not find script define for $prg' . "\n";
621 my @files = split /\s+/, $1;
622 foreach my $f (@files)
627 $proj->AddFile('src/bin/scripts/' . $f);
630 $proj->AddIncludeDir('src/interfaces/libpq');
631 $proj->AddReference($libpq, $libpgfeutils, $libpgcommon,
633 $proj->AddDirResourceFile('src/bin/scripts');
634 $proj->AddLibrary('ws2_32.lib');
637 # Regression DLL and EXE
638 my $regress = $solution->AddProject('regress', 'dll', 'misc');
639 $regress->AddFile('src/test/regress/regress.c');
640 $regress->AddDirResourceFile('src/test/regress');
641 $regress->AddReference($postgres);
643 my $pgregress = $solution->AddProject('pg_regress', 'exe', 'misc');
644 $pgregress->AddFile('src/test/regress/pg_regress.c');
645 $pgregress->AddFile('src/test/regress/pg_regress_main.c');
646 $pgregress->AddIncludeDir('src/port');
647 $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
648 $pgregress->AddLibrary('ws2_32.lib');
649 $pgregress->AddDirResourceFile('src/test/regress');
650 $pgregress->AddReference($libpgcommon, $libpgport);
652 # fix up pg_xlogdump once it's been set up
653 # files symlinked on Unix are copied on windows
654 my $pg_xlogdump = AddSimpleFrontend('pg_xlogdump');
655 $pg_xlogdump->AddDefine('FRONTEND');
656 foreach my $xf (glob('src/backend/access/rmgrdesc/*desc.c'))
658 $pg_xlogdump->AddFile($xf);
660 $pg_xlogdump->AddFile('src/backend/access/transam/xlogreader.c');
662 # fix up pgbench once it's been set up
663 # we're borrowing psqlscan.c from psql, so grab it from the correct place
664 my $pgbench = AddSimpleFrontend('pgbench');
665 $pgbench->ReplaceFile('src/bin/pgbench/psqlscan.c', 'src/bin/psql/psqlscan.c');
668 return $solution->{vcver};
671 #####################
672 # Utility functions #
673 #####################
675 # Add a simple frontend project (exe)
676 sub AddSimpleFrontend
679 my $uselibpq = shift;
681 my $p = $solution->AddProject($n, 'exe', 'bin');
682 $p->AddDir('src/bin/' . $n);
683 $p->AddReference($libpgfeutils, $libpgcommon, $libpgport);
686 $p->AddIncludeDir('src/interfaces/libpq');
687 $p->AddReference($libpq);
690 # Adjust module definition using frontend variables
691 AdjustFrontendProj($p);
696 # Add a simple transform module
697 sub AddTransformModule
701 my $pl_proj_name = shift;
703 my $transform_name = shift;
704 my $transform_src = shift;
706 my $transform_proj = undef;
707 foreach my $proj (@{ $solution->{projects}->{'contrib'} })
709 if ($proj->{name} eq $transform_name)
711 $transform_proj = $proj;
715 die "could not find base module $transform_name for transform module $n"
716 if (!defined($transform_proj));
719 foreach my $proj (@{ $solution->{projects}->{'PLs'} })
721 if ($proj->{name} eq $pl_proj_name)
727 die "could not find PL $pl_proj_name for transform module $n"
728 if (!defined($pl_proj));
730 my $p = $solution->AddProject($n, 'dll', 'contrib', $n_src);
731 for my $file (glob("$n_src/*.c"))
735 $p->AddReference($postgres);
737 # Add PL dependencies
738 $p->AddIncludeDir($pl_src);
739 $p->AddReference($pl_proj);
740 $p->AddIncludeDir($pl_proj->{includes});
741 foreach my $pl_lib (@{ $pl_proj->{libraries} })
743 $p->AddLibrary($pl_lib);
746 # Add base module dependencies
747 $p->AddIncludeDir($transform_src);
748 $p->AddIncludeDir($transform_proj->{includes});
749 foreach my $trans_lib (@{ $transform_proj->{libraries} })
751 $p->AddLibrary($trans_lib);
753 $p->AddReference($transform_proj);
758 # Add a simple contrib project
763 my $mf = Project::read_file("$subdir/$n/Makefile");
765 if ($mf =~ /^MODULE_big\s*=\s*(.*)$/mg)
768 my $proj = $solution->AddProject($dn, 'dll', 'contrib', "$subdir/$n");
769 $proj->AddReference($postgres);
770 AdjustContribProj($proj);
772 elsif ($mf =~ /^MODULES\s*=\s*(.*)$/mg)
774 foreach my $mod (split /\s+/, $1)
777 $solution->AddProject($mod, 'dll', 'contrib', "$subdir/$n");
778 my $filename = $mod . '.c';
779 $proj->AddFile("$subdir/$n/$filename");
780 $proj->AddReference($postgres);
781 AdjustContribProj($proj);
784 elsif ($mf =~ /^PROGRAM\s*=\s*(.*)$/mg)
786 my $proj = $solution->AddProject($1, 'exe', 'contrib', "$subdir/$n");
787 AdjustContribProj($proj);
791 croak "Could not determine contrib module type for $n\n";
794 # Are there any output data files to build?
795 GenerateContribSqlFiles($n, $mf);
798 sub GenerateContribSqlFiles
802 $mf =~ s{\\\r?\n}{}g;
803 if ($mf =~ /^DATA_built\s*=\s*(.*)$/mg)
807 # Strip out $(addsuffix) rules
808 if (index($l, '$(addsuffix ') >= 0)
812 for ($i = index($l, '$(addsuffix ') + 12; $i < length($l); $i++)
814 $pcount++ if (substr($l, $i, 1) eq '(');
815 $pcount-- if (substr($l, $i, 1) eq ')');
816 last if ($pcount < 0);
819 substr($l, 0, index($l, '$(addsuffix ')) . substr($l, $i + 1);
822 foreach my $d (split /\s+/, $l)
827 if (Solution::IsNewer("contrib/$n/$out", "contrib/$n/$in"))
829 print "Building $out from $in (contrib/$n)...\n";
830 my $cont = Project::read_file("contrib/$n/$in");
833 $cont =~ s/MODULE_PATHNAME/\$libdir\/$dn/g;
835 open($o, ">contrib/$n/$out")
836 || croak "Could not write to contrib/$n/$d";
844 sub AdjustContribProj
848 $proj, $contrib_defines,
849 \@contrib_uselibpq, \@contrib_uselibpgport,
850 \@contrib_uselibpgcommon, $contrib_extralibs,
851 $contrib_extrasource, $contrib_extraincludes);
854 sub AdjustFrontendProj
858 $proj, $frontend_defines,
859 \@frontend_uselibpq, \@frontend_uselibpgport,
860 \@frontend_uselibpgcommon, $frontend_extralibs,
861 $frontend_extrasource, $frontend_extraincludes);
867 my $module_defines = shift;
868 my $module_uselibpq = shift;
869 my $module_uselibpgport = shift;
870 my $module_uselibpgcommon = shift;
871 my $module_extralibs = shift;
872 my $module_extrasource = shift;
873 my $module_extraincludes = shift;
874 my $n = $proj->{name};
876 if ($module_defines->{$n})
878 foreach my $d ($module_defines->{$n})
880 $proj->AddDefine($d);
883 if (grep { /^$n$/ } @{$module_uselibpq})
885 $proj->AddIncludeDir('src\interfaces\libpq');
886 $proj->AddReference($libpq);
888 if (grep { /^$n$/ } @{$module_uselibpgport})
890 $proj->AddReference($libpgport);
892 if (grep { /^$n$/ } @{$module_uselibpgcommon})
894 $proj->AddReference($libpgcommon);
896 if ($module_extralibs->{$n})
898 foreach my $l (@{ $module_extralibs->{$n} })
900 $proj->AddLibrary($l);
903 if ($module_extraincludes->{$n})
905 foreach my $i (@{ $module_extraincludes->{$n} })
907 $proj->AddIncludeDir($i);
910 if ($module_extrasource->{$n})
912 foreach my $i (@{ $module_extrasource->{$n} })