4 # Package that generates build files for msvc build
6 # src/tools/msvc/Mkvcbuild.pm
17 use List::Util qw(first);
20 our (@ISA, @EXPORT_OK);
22 @EXPORT_OK = qw(Mkvcbuild);
29 my $contrib_defines = {'refint' => 'REFINT_VERBOSE'};
30 my @contrib_uselibpq = ('dblink', 'oid2name', 'pgbench', 'pg_upgrade','vacuumlo');
31 my @contrib_uselibpgport =(
32 'oid2name', 'pgbench', 'pg_standby','pg_archivecleanup',
33 'pg_test_fsync', 'pg_upgrade', 'vacuumlo'
35 my $contrib_extralibs = {'pgbench' => ['wsock32.lib']};
36 my $contrib_extraincludes = {'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend']};
37 my $contrib_extrasource = {
38 'cube' => ['cubescan.l','cubeparse.y'],
39 'seg' => ['segscan.l','segparse.y']
41 my @contrib_excludes = ('pgcrypto','intagg','sepgsql');
47 chdir('..\..\..') if (-d '..\msvc' && -d '..\..\..\src');
48 die 'Must run from root or msvc directory' unless (-d 'src\tools\msvc' && -d 'src');
50 $solution = new Solution($config);
52 our @pgportfiles = qw(
53 chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c
54 getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c erand48.c
55 snprintf.c strlcat.c strlcpy.c dirmod.c exec.c noblock.c path.c
56 pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c
57 sprompt.c thread.c getopt.c getopt_long.c dirent.c rint.c win32env.c
58 win32error.c win32setlocale.c);
60 $libpgport = $solution->AddProject('libpgport','lib','misc');
61 $libpgport->AddDefine('FRONTEND');
62 $libpgport->AddFiles('src\port',@pgportfiles);
64 $postgres = $solution->AddProject('postgres','exe','','src\backend');
65 $postgres->AddIncludeDir('src\backend');
66 $postgres->AddDir('src\backend\port\win32');
67 $postgres->AddFile('src\backend\utils\fmgrtab.c');
68 $postgres->ReplaceFile('src\backend\port\dynloader.c','src\backend\port\dynloader\win32.c');
69 $postgres->ReplaceFile('src\backend\port\pg_sema.c','src\backend\port\win32_sema.c');
70 $postgres->ReplaceFile('src\backend\port\pg_shmem.c','src\backend\port\win32_shmem.c');
71 $postgres->ReplaceFile('src\backend\port\pg_latch.c','src\backend\port\win32_latch.c');
72 $postgres->AddFiles('src\port',@pgportfiles);
73 $postgres->AddFile('src\backend\port\pipe.c');
74 $postgres->AddDir('src\timezone');
75 $postgres->AddFiles('src\backend\parser','scan.l','gram.y');
76 $postgres->AddFiles('src\backend\bootstrap','bootscanner.l','bootparse.y');
77 $postgres->AddFiles('src\backend\utils\misc','guc-file.l');
78 $postgres->AddFiles('src\backend\replication', 'repl_scanner.l', 'repl_gram.y');
79 $postgres->AddDefine('BUILDING_DLL');
80 $postgres->AddLibrary('wsock32.lib');
81 $postgres->AddLibrary('ws2_32.lib');
82 $postgres->AddLibrary('secur32.lib');
83 $postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
84 $postgres->FullExportDLL('postgres.lib');
86 my $snowball = $solution->AddProject('dict_snowball','dll','','src\backend\snowball');
87 $snowball->RelocateFiles(
88 'src\backend\snowball\libstemmer',
90 return shift !~ /dict_snowball.c$/;
93 $snowball->AddIncludeDir('src\include\snowball');
94 $snowball->AddReference($postgres);
96 my $plpgsql = $solution->AddProject('plpgsql','dll','PLs','src\pl\plpgsql\src');
97 $plpgsql->AddFiles('src\pl\plpgsql\src', 'gram.y');
98 $plpgsql->AddReference($postgres);
100 if ($solution->{options}->{perl})
102 my $plperlsrc = "src\\pl\\plperl\\";
103 my $plperl = $solution->AddProject('plperl','dll','PLs','src\pl\plperl');
104 $plperl->AddIncludeDir($solution->{options}->{perl} . '/lib/CORE');
105 $plperl->AddDefine('PLPERL_HAVE_UID_GID');
106 foreach my $xs ('SPI.xs', 'Util.xs')
108 (my $xsc = $xs) =~ s/\.xs/.c/;
109 if (Solution::IsNewer("$plperlsrc$xsc","$plperlsrc$xs"))
111 my $xsubppdir = first { -e "$_\\ExtUtils\\xsubpp.BAT" } @INC;
112 print "Building $plperlsrc$xsc...\n";
113 system( $solution->{options}->{perl}
115 . $solution->{options}->{perl}
116 . "$xsubppdir/ExtUtils/xsubpp -typemap "
117 . $solution->{options}->{perl}
118 . '/lib/ExtUtils/typemap '
120 . ">$plperlsrc$xsc");
121 if ((!(-f "$plperlsrc$xsc")) || -z "$plperlsrc$xsc")
123 unlink("$plperlsrc$xsc"); # if zero size
124 die "Failed to create $xsc.\n";
128 if ( Solution::IsNewer('src\pl\plperl\perlchunks.h','src\pl\plperl\plc_perlboot.pl')
129 ||Solution::IsNewer('src\pl\plperl\perlchunks.h','src\pl\plperl\plc_trusted.pl'))
131 print 'Building src\pl\plperl\perlchunks.h ...' . "\n";
132 my $basedir = getcwd;
133 chdir 'src\pl\plperl';
134 system( $solution->{options}->{perl}
137 . '--strip="^(\#.*|\s*)$$" '
138 . 'plc_perlboot.pl plc_trusted.pl '
141 if ((!(-f 'src\pl\plperl\perlchunks.h')) || -z 'src\pl\plperl\perlchunks.h')
143 unlink('src\pl\plperl\perlchunks.h'); # if zero size
144 die 'Failed to create perlchunks.h' . "\n";
147 if ( Solution::IsNewer('src\pl\plperl\plperl_opmask.h','src\pl\plperl\plperl_opmask.pl'))
149 print 'Building src\pl\plperl\plperl_opmask.h ...' . "\n";
150 my $basedir = getcwd;
151 chdir 'src\pl\plperl';
152 system( $solution->{options}->{perl}
154 . 'plperl_opmask.pl '
155 . 'plperl_opmask.h');
157 if ((!(-f 'src\pl\plperl\plperl_opmask.h')) || -z 'src\pl\plperl\plperl_opmask.h')
159 unlink('src\pl\plperl\plperl_opmask.h'); # if zero size
160 die 'Failed to create plperl_opmask.h' . "\n";
163 $plperl->AddReference($postgres);
165 grep {/perl\d+.lib$/ }glob($solution->{options}->{perl} . '\lib\CORE\perl*.lib');
168 $plperl->AddLibrary($perl_libs[0]);
172 die "could not identify perl library version";
176 if ($solution->{options}->{python})
179 # Attempt to get python version and location.
180 # Assume python.exe in specified dir.
182 $solution->{options}->{python}
183 . "\\python -c \"import sys;print(sys.prefix);print(str(sys.version_info[0])+str(sys.version_info[1]))\" |"
184 ) || die "Could not query for python version!\n";
191 # Sometimes (always?) if python is not present, the execution
192 # appears to work, but gives no data...
193 die "Failed to query python for version information\n"
194 if (!(defined($pyprefix) && defined($pyver)));
196 my $pymajorver = substr($pyver, 0, 1);
198 $solution->AddProject('plpython' . $pymajorver, 'dll','PLs', 'src\pl\plpython');
199 $plpython->AddIncludeDir($pyprefix . '\include');
200 $plpython->AddLibrary($pyprefix . "\\Libs\\python$pyver.lib");
201 $plpython->AddReference($postgres);
204 if ($solution->{options}->{tcl})
206 my $pltcl = $solution->AddProject('pltcl','dll','PLs','src\pl\tcl');
207 $pltcl->AddIncludeDir($solution->{options}->{tcl} . '\include');
208 $pltcl->AddReference($postgres);
209 if (-e $solution->{options}->{tcl} . '\lib\tcl85.lib')
211 $pltcl->AddLibrary($solution->{options}->{tcl} . '\lib\tcl85.lib');
215 $pltcl->AddLibrary($solution->{options}->{tcl} . '\lib\tcl84.lib');
219 $libpq = $solution->AddProject('libpq','dll','interfaces','src\interfaces\libpq');
220 $libpq->AddDefine('FRONTEND');
221 $libpq->AddDefine('UNSAFE_STAT_OK');
222 $libpq->AddIncludeDir('src\port');
223 $libpq->AddLibrary('wsock32.lib');
224 $libpq->AddLibrary('secur32.lib');
225 $libpq->AddLibrary('ws2_32.lib');
226 $libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
227 $libpq->UseDef('src\interfaces\libpq\libpqdll.def');
228 $libpq->ReplaceFile('src\interfaces\libpq\libpqrc.c','src\interfaces\libpq\libpq.rc');
229 $libpq->AddReference($libpgport);
231 my $libpqwalreceiver = $solution->AddProject('libpqwalreceiver', 'dll', '',
232 'src\backend\replication\libpqwalreceiver');
233 $libpqwalreceiver->AddIncludeDir('src\interfaces\libpq');
234 $libpqwalreceiver->AddReference($postgres,$libpq);
237 $solution->AddProject('libpgtypes','dll','interfaces','src\interfaces\ecpg\pgtypeslib');
238 $pgtypes->AddDefine('FRONTEND');
239 $pgtypes->AddReference($libpgport);
240 $pgtypes->UseDef('src\interfaces\ecpg\pgtypeslib\pgtypeslib.def');
241 $pgtypes->AddIncludeDir('src\interfaces\ecpg\include');
243 my $libecpg =$solution->AddProject('libecpg','dll','interfaces','src\interfaces\ecpg\ecpglib');
244 $libecpg->AddDefine('FRONTEND');
245 $libecpg->AddIncludeDir('src\interfaces\ecpg\include');
246 $libecpg->AddIncludeDir('src\interfaces\libpq');
247 $libecpg->AddIncludeDir('src\port');
248 $libecpg->UseDef('src\interfaces\ecpg\ecpglib\ecpglib.def');
249 $libecpg->AddLibrary('wsock32.lib');
250 $libecpg->AddReference($libpq,$pgtypes,$libpgport);
253 $solution->AddProject('libecpg_compat','dll','interfaces','src\interfaces\ecpg\compatlib');
254 $libecpgcompat->AddIncludeDir('src\interfaces\ecpg\include');
255 $libecpgcompat->AddIncludeDir('src\interfaces\libpq');
256 $libecpgcompat->UseDef('src\interfaces\ecpg\compatlib\compatlib.def');
257 $libecpgcompat->AddReference($pgtypes,$libecpg,$libpgport);
259 my $ecpg = $solution->AddProject('ecpg','exe','interfaces','src\interfaces\ecpg\preproc');
260 $ecpg->AddIncludeDir('src\interfaces\ecpg\include');
261 $ecpg->AddIncludeDir('src\interfaces\libpq');
262 $ecpg->AddPrefixInclude('src\interfaces\ecpg\preproc');
263 $ecpg->AddFiles('src\interfaces\ecpg\preproc','pgc.l','preproc.y');
264 $ecpg->AddDefine('MAJOR_VERSION=4');
265 $ecpg->AddDefine('MINOR_VERSION=2');
266 $ecpg->AddDefine('PATCHLEVEL=1');
267 $ecpg->AddDefine('ECPG_COMPILE');
268 $ecpg->AddReference($libpgport);
270 my $pgregress_ecpg = $solution->AddProject('pg_regress_ecpg','exe','misc');
271 $pgregress_ecpg->AddFile('src\interfaces\ecpg\test\pg_regress_ecpg.c');
272 $pgregress_ecpg->AddFile('src\test\regress\pg_regress.c');
273 $pgregress_ecpg->AddIncludeDir('src\port');
274 $pgregress_ecpg->AddIncludeDir('src\test\regress');
275 $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
276 $pgregress_ecpg->AddDefine('FRONTEND');
277 $pgregress_ecpg->AddReference($libpgport);
279 my $isolation_tester = $solution->AddProject('isolationtester','exe','misc');
280 $isolation_tester->AddFile('src\test\isolation\isolationtester.c');
281 $isolation_tester->AddFile('src\test\isolation\specparse.y');
282 $isolation_tester->AddFile('src\test\isolation\specscanner.l');
283 $isolation_tester->AddFile('src\test\isolation\specparse.c');
284 $isolation_tester->AddIncludeDir('src\test\isolation');
285 $isolation_tester->AddIncludeDir('src\port');
286 $isolation_tester->AddIncludeDir('src\test\regress');
287 $isolation_tester->AddIncludeDir('src\interfaces\libpq');
288 $isolation_tester->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
289 $isolation_tester->AddDefine('FRONTEND');
290 $isolation_tester->AddLibrary('wsock32.lib');
291 $isolation_tester->AddReference($libpq, $libpgport);
293 my $pgregress_isolation = $solution->AddProject('pg_isolation_regress','exe','misc');
294 $pgregress_isolation->AddFile('src\test\isolation\isolation_main.c');
295 $pgregress_isolation->AddFile('src\test\regress\pg_regress.c');
296 $pgregress_isolation->AddIncludeDir('src\port');
297 $pgregress_isolation->AddIncludeDir('src\test\regress');
298 $pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
299 $pgregress_isolation->AddDefine('FRONTEND');
300 $pgregress_isolation->AddReference($libpgport);
303 my $initdb = AddSimpleFrontend('initdb');
304 $initdb->AddIncludeDir('src\interfaces\libpq');
305 $initdb->AddIncludeDir('src\timezone');
306 $initdb->AddDefine('FRONTEND');
307 $initdb->AddLibrary('wsock32.lib');
308 $initdb->AddLibrary('ws2_32.lib');
310 my $pgbasebackup = AddSimpleFrontend('pg_basebackup', 1);
311 $pgbasebackup->AddFile('src\bin\pg_basebackup\pg_basebackup.c');
312 $pgbasebackup->AddLibrary('ws2_32.lib');
314 my $pgreceivexlog = AddSimpleFrontend('pg_basebackup', 1);
315 $pgreceivexlog->{name} = 'pg_receivexlog';
316 $pgreceivexlog->AddFile('src\bin\pg_basebackup\pg_receivexlog.c');
317 $pgreceivexlog->AddLibrary('ws2_32.lib');
319 my $pgconfig = AddSimpleFrontend('pg_config');
321 my $pgcontrol = AddSimpleFrontend('pg_controldata');
323 my $pgctl = AddSimpleFrontend('pg_ctl', 1);
325 my $pgreset = AddSimpleFrontend('pg_resetxlog');
327 my $pgevent = $solution->AddProject('pgevent','dll','bin');
328 $pgevent->AddFiles('src\bin\pgevent','pgevent.c','pgmsgevent.rc');
329 $pgevent->AddResourceFile('src\bin\pgevent','Eventlog message formatter');
330 $pgevent->RemoveFile('src\bin\pgevent\win32ver.rc');
331 $pgevent->UseDef('src\bin\pgevent\pgevent.def');
332 $pgevent->DisableLinkerWarnings('4104');
334 my $psql = AddSimpleFrontend('psql', 1);
335 $psql->AddIncludeDir('src\bin\pg_dump');
336 $psql->AddIncludeDir('src\backend');
337 $psql->AddFile('src\bin\psql\psqlscan.l');
339 my $pgdump = AddSimpleFrontend('pg_dump', 1);
340 $pgdump->AddIncludeDir('src\backend');
341 $pgdump->AddFile('src\bin\pg_dump\pg_dump.c');
342 $pgdump->AddFile('src\bin\pg_dump\common.c');
343 $pgdump->AddFile('src\bin\pg_dump\pg_dump_sort.c');
344 $pgdump->AddFile('src\bin\pg_dump\keywords.c');
345 $pgdump->AddFile('src\backend\parser\kwlookup.c');
347 my $pgdumpall = AddSimpleFrontend('pg_dump', 1);
348 $pgdumpall->{name} = 'pg_dumpall';
349 $pgdumpall->AddIncludeDir('src\backend');
350 $pgdumpall->AddFile('src\bin\pg_dump\pg_dumpall.c');
351 $pgdumpall->AddFile('src\bin\pg_dump\keywords.c');
352 $pgdumpall->AddFile('src\backend\parser\kwlookup.c');
354 my $pgrestore = AddSimpleFrontend('pg_dump', 1);
355 $pgrestore->{name} = 'pg_restore';
356 $pgrestore->AddIncludeDir('src\backend');
357 $pgrestore->AddFile('src\bin\pg_dump\pg_restore.c');
358 $pgrestore->AddFile('src\bin\pg_dump\keywords.c');
359 $pgrestore->AddFile('src\backend\parser\kwlookup.c');
361 my $zic = $solution->AddProject('zic','exe','utils');
362 $zic->AddFiles('src\timezone','zic.c','ialloc.c','scheck.c','localtime.c');
363 $zic->AddReference($libpgport);
365 if ($solution->{options}->{xml})
367 $contrib_extraincludes->{'pgxml'} = [
368 $solution->{options}->{xml} . '\include',
369 $solution->{options}->{xslt} . '\include',
370 $solution->{options}->{iconv} . '\include'
373 $contrib_extralibs->{'pgxml'} = [
374 $solution->{options}->{xml} . '\lib\libxml2.lib',
375 $solution->{options}->{xslt} . '\lib\libxslt.lib'
380 push @contrib_excludes,'xml2';
383 if (!$solution->{options}->{openssl})
385 push @contrib_excludes,'sslinfo';
388 if ($solution->{options}->{uuid})
390 $contrib_extraincludes->{'uuid-ossp'} = [ $solution->{options}->{uuid} . '\include' ];
391 $contrib_extralibs->{'uuid-ossp'} = [ $solution->{options}->{uuid} . '\lib\uuid.lib' ];
395 push @contrib_excludes,'uuid-ossp';
398 # Pgcrypto makefile too complex to parse....
399 my $pgcrypto = $solution->AddProject('pgcrypto','dll','crypto');
401 'contrib\pgcrypto','pgcrypto.c','px.c','px-hmac.c',
402 'px-crypt.c','crypt-gensalt.c','crypt-blowfish.c','crypt-des.c',
403 'crypt-md5.c','mbuf.c','pgp.c','pgp-armor.c',
404 'pgp-cfb.c','pgp-compress.c','pgp-decrypt.c','pgp-encrypt.c',
405 'pgp-info.c','pgp-mpi.c','pgp-pubdec.c','pgp-pubenc.c',
406 'pgp-pubkey.c','pgp-s2k.c','pgp-pgsql.c'
408 if ($solution->{options}->{openssl})
410 $pgcrypto->AddFiles('contrib\pgcrypto', 'openssl.c','pgp-mpi-openssl.c');
415 'contrib\pgcrypto', 'md5.c','sha1.c','sha2.c',
416 'internal.c','internal-sha2.c','blf.c','rijndael.c',
417 'fortuna.c','random.c','pgp-mpi-internal.c','imath.c'
420 $pgcrypto->AddReference($postgres);
421 $pgcrypto->AddLibrary('wsock32.lib');
422 my $mf = Project::read_file('contrib/pgcrypto/Makefile');
423 GenerateContribSqlFiles('pgcrypto', $mf);
426 opendir($D, 'contrib') || croak "Could not opendir on contrib!\n";
427 while (my $d = readdir($D))
429 next if ($d =~ /^\./);
430 next unless (-f "contrib/$d/Makefile");
431 next if (grep {/^$d$/} @contrib_excludes);
436 $mf = Project::read_file('src\backend\utils\mb\conversion_procs\Makefile');
437 $mf =~ s{\\s*[\r\n]+}{}mg;
438 $mf =~ m{SUBDIRS\s*=\s*(.*)$}m || die 'Could not match in conversion makefile' . "\n";
439 foreach my $sub (split /\s+/,$1)
441 my $mf = Project::read_file('src\backend\utils\mb\conversion_procs\\' . $sub . '\Makefile');
442 my $p = $solution->AddProject($sub, 'dll', 'conversion procs');
443 $p->AddFile('src\backend\utils\mb\conversion_procs\\' . $sub . '\\' . $sub . '.c');
444 if ($mf =~ m{^SRCS\s*\+=\s*(.*)$}m)
446 $p->AddFile('src\backend\utils\mb\conversion_procs\\' . $sub . '\\' . $1);
448 $p->AddReference($postgres);
451 $mf = Project::read_file('src\bin\scripts\Makefile');
452 $mf =~ s{\\s*[\r\n]+}{}mg;
453 $mf =~ m{PROGRAMS\s*=\s*(.*)$}m || die 'Could not match in bin\scripts\Makefile' . "\n";
454 foreach my $prg (split /\s+/,$1)
456 my $proj = $solution->AddProject($prg,'exe','bin');
457 $mf =~ m{$prg\s*:\s*(.*)$}m || die 'Could not find script define for $prg' . "\n";
458 my @files = split /\s+/,$1;
459 foreach my $f (@files)
462 if ($f eq 'keywords.c')
464 $proj->AddFile('src\bin\pg_dump\keywords.c');
466 elsif ($f eq 'kwlookup.c')
468 $proj->AddFile('src\backend\parser\kwlookup.c');
470 elsif ($f eq 'dumputils.c')
472 $proj->AddFile('src\bin\pg_dump\dumputils.c');
474 elsif ($f =~ /print\.c$/)
475 { # Also catches mbprint.c
476 $proj->AddFile('src\bin\psql\\' . $f);
480 $proj->AddFile('src\bin\scripts\\' . $f);
483 $proj->AddIncludeDir('src\interfaces\libpq');
484 $proj->AddIncludeDir('src\bin\pg_dump');
485 $proj->AddIncludeDir('src\bin\psql');
486 $proj->AddReference($libpq,$libpgport);
487 $proj->AddResourceFile('src\bin\scripts','PostgreSQL Utility');
490 # Regression DLL and EXE
491 my $regress = $solution->AddProject('regress','dll','misc');
492 $regress->AddFile('src\test\regress\regress.c');
493 $regress->AddReference($postgres);
495 my $pgregress = $solution->AddProject('pg_regress','exe','misc');
496 $pgregress->AddFile('src\test\regress\pg_regress.c');
497 $pgregress->AddFile('src\test\regress\pg_regress_main.c');
498 $pgregress->AddIncludeDir('src\port');
499 $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
500 $pgregress->AddReference($libpgport);
505 #####################
506 # Utility functions #
507 #####################
509 # Add a simple frontend project (exe)
510 sub AddSimpleFrontend
515 my $p = $solution->AddProject($n,'exe','bin');
516 $p->AddDir('src\bin\\' . $n);
517 $p->AddReference($libpgport);
520 $p->AddIncludeDir('src\interfaces\libpq');
521 $p->AddReference($libpq);
526 # Add a simple contrib project
530 my $mf = Project::read_file('contrib\\' . $n . '\Makefile');
532 if ($mf =~ /^MODULE_big\s*=\s*(.*)$/mg)
535 $mf =~ s{\\\s*[\r\n]+}{}mg;
536 my $proj = $solution->AddProject($dn, 'dll', 'contrib');
537 $mf =~ /^OBJS\s*=\s*(.*)$/gm || croak "Could not find objects in MODULE_big for $n\n";
539 while ($objs =~ /\b([\w-]+\.o)\b/g)
543 $proj->AddFile('contrib\\' . $n . '\\' . $o);
545 $proj->AddReference($postgres);
546 if ($mf =~ /^SUBDIRS\s*:?=\s*(.*)$/mg)
548 foreach my $d (split /\s+/, $1)
550 my $mf2 = Project::read_file('contrib\\' . $n . '\\' . $d . '\Makefile');
551 $mf2 =~ s{\\\s*[\r\n]+}{}mg;
552 $mf2 =~ /^SUBOBJS\s*=\s*(.*)$/gm
553 || croak "Could not find objects in MODULE_big for $n, subdir $d\n";
555 while ($objs =~ /\b([\w-]+\.o)\b/g)
559 $proj->AddFile('contrib\\' . $n . '\\' . $d . '\\' . $o);
563 AdjustContribProj($proj);
565 elsif ($mf =~ /^MODULES\s*=\s*(.*)$/mg)
567 foreach my $mod (split /\s+/, $1)
569 my $proj = $solution->AddProject($mod, 'dll', 'contrib');
570 $proj->AddFile('contrib\\' . $n . '\\' . $mod . '.c');
571 $proj->AddReference($postgres);
572 AdjustContribProj($proj);
575 elsif ($mf =~ /^PROGRAM\s*=\s*(.*)$/mg)
577 my $proj = $solution->AddProject($1, 'exe', 'contrib');
578 $mf =~ s{\\\s*[\r\n]+}{}mg;
579 $mf =~ /^OBJS\s*=\s*(.*)$/gm || croak "Could not find objects in PROGRAM for $n\n";
581 while ($objs =~ /\b([\w-]+\.o)\b/g)
585 $proj->AddFile('contrib\\' . $n . '\\' . $o);
587 AdjustContribProj($proj);
591 croak "Could not determine contrib module type for $n\n";
594 # Are there any output data files to build?
595 GenerateContribSqlFiles($n, $mf);
598 sub GenerateContribSqlFiles
602 if ($mf =~ /^DATA_built\s*=\s*(.*)$/mg)
606 # Strip out $(addsuffix) rules
607 if (index($l, '$(addsuffix ') >= 0)
611 for ($i = index($l, '$(addsuffix ') + 12; $i < length($l); $i++)
613 $pcount++ if (substr($l, $i, 1) eq '(');
614 $pcount-- if (substr($l, $i, 1) eq ')');
615 last if ($pcount < 0);
617 $l = substr($l, 0, index($l, '$(addsuffix ')) . substr($l, $i+1);
620 foreach my $d (split /\s+/, $l)
625 if (Solution::IsNewer("contrib/$n/$out", "contrib/$n/$in"))
627 print "Building $out from $in (contrib/$n)...\n";
628 my $cont = Project::read_file("contrib/$n/$in");
631 $cont =~ s/MODULE_PATHNAME/\$libdir\/$dn/g;
633 open($o,">contrib/$n/$out") || croak "Could not write to contrib/$n/$d";
641 sub AdjustContribProj
644 my $n = $proj->{name};
646 if ($contrib_defines->{$n})
648 foreach my $d ($contrib_defines->{$n})
650 $proj->AddDefine($d);
653 if (grep {/^$n$/} @contrib_uselibpq)
655 $proj->AddIncludeDir('src\interfaces\libpq');
656 $proj->AddReference($libpq);
658 if (grep {/^$n$/} @contrib_uselibpgport)
660 $proj->AddReference($libpgport);
662 if ($contrib_extralibs->{$n})
664 foreach my $l (@{$contrib_extralibs->{$n}})
666 $proj->AddLibrary($l);
669 if ($contrib_extraincludes->{$n})
671 foreach my $i (@{$contrib_extraincludes->{$n}})
673 $proj->AddIncludeDir($i);
676 if ($contrib_extrasource->{$n})
678 $proj->AddFiles('contrib\\' . $n, @{$contrib_extrasource->{$n}});