PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/tools/msvc/Mkvcbuild.pm

https://github.com/gurjeet/postgres
Perl | 643 lines | 578 code | 52 blank | 13 comment | 56 complexity | f0d9794c1671c1e382168b0cdd9e06df MD5 | raw file
  1. package Mkvcbuild;
  2. #
  3. # Package that generates build files for msvc build
  4. #
  5. # src/tools/msvc/Mkvcbuild.pm
  6. #
  7. use Carp;
  8. use Win32;
  9. use strict;
  10. use warnings;
  11. use Project;
  12. use Solution;
  13. use Cwd;
  14. use File::Copy;
  15. use Exporter;
  16. our (@ISA, @EXPORT_OK);
  17. @ISA = qw(Exporter);
  18. @EXPORT_OK = qw(Mkvcbuild);
  19. my $solution;
  20. my $libpgport;
  21. my $postgres;
  22. my $libpq;
  23. my $contrib_defines = {'refint' => 'REFINT_VERBOSE'};
  24. my @contrib_uselibpq = ('dblink', 'oid2name', 'pgbench', 'pg_upgrade','vacuumlo');
  25. my @contrib_uselibpgport =
  26. ('oid2name', 'pgbench', 'pg_standby','pg_archivecleanup', 'pg_upgrade', 'vacuumlo');
  27. my $contrib_extralibs = {'pgbench' => ['wsock32.lib']};
  28. my $contrib_extraincludes = {'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend']};
  29. my $contrib_extrasource = {
  30. 'cube' => ['cubescan.l','cubeparse.y'],
  31. 'seg' => ['segscan.l','segparse.y']
  32. };
  33. my @contrib_excludes = ('pgcrypto','intagg');
  34. sub mkvcbuild
  35. {
  36. our $config = shift;
  37. chdir('..\..\..') if (-d '..\msvc' && -d '..\..\..\src');
  38. die 'Must run from root or msvc directory' unless (-d 'src\tools\msvc' && -d 'src');
  39. $solution = new Solution($config);
  40. our @pgportfiles = qw(
  41. chklocale.c crypt.c fseeko.c getrusage.c inet_aton.c random.c srandom.c
  42. getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c erand48.c
  43. snprintf.c strlcat.c strlcpy.c dirmod.c exec.c noblock.c path.c pipe.c
  44. pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c qsort.c qsort_arg.c
  45. sprompt.c thread.c getopt.c getopt_long.c dirent.c rint.c win32env.c
  46. win32error.c);
  47. $libpgport = $solution->AddProject('libpgport','lib','misc');
  48. $libpgport->AddDefine('FRONTEND');
  49. $libpgport->AddFiles('src\port',@pgportfiles);
  50. $postgres = $solution->AddProject('postgres','exe','','src\backend');
  51. $postgres->AddIncludeDir('src\backend');
  52. $postgres->AddDir('src\backend\port\win32');
  53. $postgres->AddFile('src\backend\utils\fmgrtab.c');
  54. $postgres->ReplaceFile('src\backend\port\dynloader.c','src\backend\port\dynloader\win32.c');
  55. $postgres->ReplaceFile('src\backend\port\pg_sema.c','src\backend\port\win32_sema.c');
  56. $postgres->ReplaceFile('src\backend\port\pg_shmem.c','src\backend\port\win32_shmem.c');
  57. $postgres->ReplaceFile('src\backend\port\pg_latch.c','src\backend\port\win32_latch.c');
  58. $postgres->AddFiles('src\port',@pgportfiles);
  59. $postgres->AddDir('src\timezone');
  60. $postgres->AddFiles('src\backend\parser','scan.l','gram.y');
  61. $postgres->AddFiles('src\backend\bootstrap','bootscanner.l','bootparse.y');
  62. $postgres->AddFiles('src\backend\utils\misc','guc-file.l');
  63. $postgres->AddDefine('BUILDING_DLL');
  64. $postgres->AddLibrary('wsock32.lib');
  65. $postgres->AddLibrary('ws2_32.lib');
  66. $postgres->AddLibrary('secur32.lib');
  67. $postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
  68. $postgres->FullExportDLL('postgres.lib');
  69. my $snowball = $solution->AddProject('dict_snowball','dll','','src\backend\snowball');
  70. $snowball->RelocateFiles(
  71. 'src\backend\snowball\libstemmer',
  72. sub {
  73. return shift !~ /dict_snowball.c$/;
  74. }
  75. );
  76. $snowball->AddIncludeDir('src\include\snowball');
  77. $snowball->AddReference($postgres);
  78. my $plpgsql = $solution->AddProject('plpgsql','dll','PLs','src\pl\plpgsql\src');
  79. $plpgsql->AddFiles('src\pl\plpgsql\src', 'gram.y');
  80. $plpgsql->AddReference($postgres);
  81. if ($solution->{options}->{perl})
  82. {
  83. my $plperlsrc = "src\\pl\\plperl\\";
  84. my $plperl = $solution->AddProject('plperl','dll','PLs','src\pl\plperl');
  85. $plperl->AddIncludeDir($solution->{options}->{perl} . '/lib/CORE');
  86. $plperl->AddDefine('PLPERL_HAVE_UID_GID');
  87. foreach my $xs ('SPI.xs', 'Util.xs')
  88. {
  89. (my $xsc = $xs) =~ s/\.xs/.c/;
  90. if (Solution::IsNewer("$plperlsrc$xsc","$plperlsrc$xs"))
  91. {
  92. print "Building $plperlsrc$xsc...\n";
  93. system( $solution->{options}->{perl}
  94. . '/bin/perl '
  95. . $solution->{options}->{perl}
  96. . '/lib/ExtUtils/xsubpp -typemap '
  97. . $solution->{options}->{perl}
  98. . '/lib/ExtUtils/typemap '
  99. . "$plperlsrc$xs "
  100. . ">$plperlsrc$xsc");
  101. if ((!(-f "$plperlsrc$xsc")) || -z "$plperlsrc$xsc")
  102. {
  103. unlink("$plperlsrc$xsc"); # if zero size
  104. die "Failed to create $xsc.\n";
  105. }
  106. }
  107. }
  108. if ( Solution::IsNewer('src\pl\plperl\perlchunks.h','src\pl\plperl\plc_perlboot.pl')
  109. ||Solution::IsNewer('src\pl\plperl\perlchunks.h','src\pl\plperl\plc_trusted.pl'))
  110. {
  111. print 'Building src\pl\plperl\perlchunks.h ...' . "\n";
  112. my $basedir = getcwd;
  113. chdir 'src\pl\plperl';
  114. system( $solution->{options}->{perl}
  115. . '/bin/perl '
  116. . 'text2macro.pl '
  117. . '--strip="^(\#.*|\s*)$$" '
  118. . 'plc_perlboot.pl plc_trusted.pl '
  119. . '>perlchunks.h');
  120. chdir $basedir;
  121. if ((!(-f 'src\pl\plperl\perlchunks.h')) || -z 'src\pl\plperl\perlchunks.h')
  122. {
  123. unlink('src\pl\plperl\perlchunks.h'); # if zero size
  124. die 'Failed to create perlchunks.h' . "\n";
  125. }
  126. }
  127. if ( Solution::IsNewer('src\pl\plperl\plperl_opmask.h','src\pl\plperl\plperl_opmask.pl'))
  128. {
  129. print 'Building src\pl\plperl\plperl_opmask.h ...' . "\n";
  130. my $basedir = getcwd;
  131. chdir 'src\pl\plperl';
  132. system( $solution->{options}->{perl}
  133. . '/bin/perl '
  134. . 'plperl_opmask.pl '
  135. . 'plperl_opmask.h');
  136. chdir $basedir;
  137. if ((!(-f 'src\pl\plperl\plperl_opmask.h')) || -z 'src\pl\plperl\plperl_opmask.h')
  138. {
  139. unlink('src\pl\plperl\plperl_opmask.h'); # if zero size
  140. die 'Failed to create plperl_opmask.h' . "\n";
  141. }
  142. }
  143. $plperl->AddReference($postgres);
  144. my @perl_libs =
  145. grep {/perl\d+.lib$/ }glob($solution->{options}->{perl} . '\lib\CORE\perl*.lib');
  146. if (@perl_libs == 1)
  147. {
  148. $plperl->AddLibrary($perl_libs[0]);
  149. }
  150. else
  151. {
  152. die "could not identify perl library version";
  153. }
  154. }
  155. if ($solution->{options}->{python})
  156. {
  157. # Attempt to get python version and location. Assume python.exe in specified dir.
  158. open(P,
  159. $solution->{options}->{python}
  160. . "\\python -c \"import sys;print(sys.prefix);print(str(sys.version_info[0])+str(sys.version_info[1]))\" |"
  161. ) || die "Could not query for python version!\n";
  162. my $pyprefix = <P>;
  163. chomp($pyprefix);
  164. my $pyver = <P>;
  165. chomp($pyver);
  166. close(P);
  167. # Sometimes (always?) if python is not present, the execution actually works, but gives no data...
  168. die "Failed to query python for version information\n"
  169. if (!(defined($pyprefix) && defined($pyver)));
  170. my $plpython = $solution->AddProject('plpython','dll','PLs','src\pl\plpython');
  171. $plpython->AddIncludeDir($pyprefix . '\include');
  172. $plpython->AddLibrary($pyprefix . "\\Libs\\python$pyver.lib");
  173. $plpython->AddReference($postgres);
  174. }
  175. if ($solution->{options}->{tcl})
  176. {
  177. my $pltcl = $solution->AddProject('pltcl','dll','PLs','src\pl\tcl');
  178. $pltcl->AddIncludeDir($solution->{options}->{tcl} . '\include');
  179. $pltcl->AddReference($postgres);
  180. if (-e $solution->{options}->{tcl} . '\lib\tcl85.lib')
  181. {
  182. $pltcl->AddLibrary($solution->{options}->{tcl} . '\lib\tcl85.lib');
  183. }
  184. else
  185. {
  186. $pltcl->AddLibrary($solution->{options}->{tcl} . '\lib\tcl84.lib');
  187. }
  188. }
  189. $libpq = $solution->AddProject('libpq','dll','interfaces','src\interfaces\libpq');
  190. $libpq->AddDefine('FRONTEND');
  191. $libpq->AddDefine('UNSAFE_STAT_OK');
  192. $libpq->AddIncludeDir('src\port');
  193. $libpq->AddLibrary('wsock32.lib');
  194. $libpq->AddLibrary('secur32.lib');
  195. $libpq->AddLibrary('ws2_32.lib');
  196. $libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
  197. $libpq->UseDef('src\interfaces\libpq\libpqdll.def');
  198. $libpq->ReplaceFile('src\interfaces\libpq\libpqrc.c','src\interfaces\libpq\libpq.rc');
  199. $libpq->AddReference($libpgport);
  200. my $libpqwalreceiver = $solution->AddProject('libpqwalreceiver', 'dll', '',
  201. 'src\backend\replication\libpqwalreceiver');
  202. $libpqwalreceiver->AddIncludeDir('src\interfaces\libpq');
  203. $libpqwalreceiver->AddReference($postgres,$libpq);
  204. my $pgtypes =
  205. $solution->AddProject('libpgtypes','dll','interfaces','src\interfaces\ecpg\pgtypeslib');
  206. $pgtypes->AddDefine('FRONTEND');
  207. $pgtypes->AddReference($libpgport);
  208. $pgtypes->UseDef('src\interfaces\ecpg\pgtypeslib\pgtypeslib.def');
  209. $pgtypes->AddIncludeDir('src\interfaces\ecpg\include');
  210. my $libecpg =$solution->AddProject('libecpg','dll','interfaces','src\interfaces\ecpg\ecpglib');
  211. $libecpg->AddDefine('FRONTEND');
  212. $libecpg->AddIncludeDir('src\interfaces\ecpg\include');
  213. $libecpg->AddIncludeDir('src\interfaces\libpq');
  214. $libecpg->AddIncludeDir('src\port');
  215. $libecpg->UseDef('src\interfaces\ecpg\ecpglib\ecpglib.def');
  216. $libecpg->AddLibrary('wsock32.lib');
  217. $libecpg->AddReference($libpq,$pgtypes,$libpgport);
  218. my $libecpgcompat =
  219. $solution->AddProject('libecpg_compat','dll','interfaces','src\interfaces\ecpg\compatlib');
  220. $libecpgcompat->AddIncludeDir('src\interfaces\ecpg\include');
  221. $libecpgcompat->AddIncludeDir('src\interfaces\libpq');
  222. $libecpgcompat->UseDef('src\interfaces\ecpg\compatlib\compatlib.def');
  223. $libecpgcompat->AddReference($pgtypes,$libecpg,$libpgport);
  224. my $ecpg = $solution->AddProject('ecpg','exe','interfaces','src\interfaces\ecpg\preproc');
  225. $ecpg->AddIncludeDir('src\interfaces\ecpg\include');
  226. $ecpg->AddIncludeDir('src\interfaces\libpq');
  227. $ecpg->AddPrefixInclude('src\interfaces\ecpg\preproc');
  228. $ecpg->AddFiles('src\interfaces\ecpg\preproc','pgc.l','preproc.y');
  229. $ecpg->AddDefine('MAJOR_VERSION=4');
  230. $ecpg->AddDefine('MINOR_VERSION=2');
  231. $ecpg->AddDefine('PATCHLEVEL=1');
  232. $ecpg->AddDefine('ECPG_COMPILE');
  233. $ecpg->AddReference($libpgport);
  234. my $pgregress_ecpg = $solution->AddProject('pg_regress_ecpg','exe','misc');
  235. $pgregress_ecpg->AddFile('src\interfaces\ecpg\test\pg_regress_ecpg.c');
  236. $pgregress_ecpg->AddFile('src\test\regress\pg_regress.c');
  237. $pgregress_ecpg->AddIncludeDir('src\port');
  238. $pgregress_ecpg->AddIncludeDir('src\test\regress');
  239. $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
  240. $pgregress_ecpg->AddDefine('FRONTEND');
  241. $pgregress_ecpg->AddReference($libpgport);
  242. # src/bin
  243. my $initdb = AddSimpleFrontend('initdb');
  244. $initdb->AddIncludeDir('src\interfaces\libpq');
  245. $initdb->AddDefine('FRONTEND');
  246. $initdb->AddLibrary('wsock32.lib');
  247. $initdb->AddLibrary('ws2_32.lib');
  248. my $pgconfig = AddSimpleFrontend('pg_config');
  249. my $pgcontrol = AddSimpleFrontend('pg_controldata');
  250. my $pgctl = AddSimpleFrontend('pg_ctl', 1);
  251. my $pgreset = AddSimpleFrontend('pg_resetxlog');
  252. my $pgevent = $solution->AddProject('pgevent','dll','bin');
  253. $pgevent->AddFiles('src\bin\pgevent','pgevent.c','pgmsgevent.rc');
  254. $pgevent->AddResourceFile('src\bin\pgevent','Eventlog message formatter');
  255. $pgevent->RemoveFile('src\bin\pgevent\win32ver.rc');
  256. $pgevent->UseDef('src\bin\pgevent\pgevent.def');
  257. $pgevent->DisableLinkerWarnings('4104');
  258. my $psql = AddSimpleFrontend('psql', 1);
  259. $psql->AddIncludeDir('src\bin\pg_dump');
  260. $psql->AddIncludeDir('src\backend');
  261. $psql->AddFile('src\bin\psql\psqlscan.l');
  262. my $pgdump = AddSimpleFrontend('pg_dump', 1);
  263. $pgdump->AddIncludeDir('src\backend');
  264. $pgdump->AddFile('src\bin\pg_dump\pg_dump.c');
  265. $pgdump->AddFile('src\bin\pg_dump\common.c');
  266. $pgdump->AddFile('src\bin\pg_dump\pg_dump_sort.c');
  267. $pgdump->AddFile('src\bin\pg_dump\keywords.c');
  268. $pgdump->AddFile('src\backend\parser\kwlookup.c');
  269. my $pgdumpall = AddSimpleFrontend('pg_dump', 1);
  270. $pgdumpall->{name} = 'pg_dumpall';
  271. $pgdumpall->AddIncludeDir('src\backend');
  272. $pgdumpall->AddFile('src\bin\pg_dump\pg_dumpall.c');
  273. $pgdumpall->AddFile('src\bin\pg_dump\keywords.c');
  274. $pgdumpall->AddFile('src\backend\parser\kwlookup.c');
  275. my $pgrestore = AddSimpleFrontend('pg_dump', 1);
  276. $pgrestore->{name} = 'pg_restore';
  277. $pgrestore->AddIncludeDir('src\backend');
  278. $pgrestore->AddFile('src\bin\pg_dump\pg_restore.c');
  279. $pgrestore->AddFile('src\bin\pg_dump\keywords.c');
  280. $pgrestore->AddFile('src\backend\parser\kwlookup.c');
  281. my $zic = $solution->AddProject('zic','exe','utils');
  282. $zic->AddFiles('src\timezone','zic.c','ialloc.c','scheck.c','localtime.c');
  283. $zic->AddReference($libpgport);
  284. if ($solution->{options}->{xml})
  285. {
  286. $contrib_extraincludes->{'pgxml'} = [
  287. $solution->{options}->{xml} . '\include',
  288. $solution->{options}->{xslt} . '\include',
  289. $solution->{options}->{iconv} . '\include'
  290. ];
  291. $contrib_extralibs->{'pgxml'} = [
  292. $solution->{options}->{xml} . '\lib\libxml2.lib',
  293. $solution->{options}->{xslt} . '\lib\libxslt.lib'
  294. ];
  295. }
  296. else
  297. {
  298. push @contrib_excludes,'xml2';
  299. }
  300. if (!$solution->{options}->{openssl})
  301. {
  302. push @contrib_excludes,'sslinfo';
  303. }
  304. if ($solution->{options}->{uuid})
  305. {
  306. $contrib_extraincludes->{'uuid-ossp'} = [ $solution->{options}->{uuid} . '\include' ];
  307. $contrib_extralibs->{'uuid-ossp'} = [ $solution->{options}->{uuid} . '\lib\uuid.lib' ];
  308. }
  309. else
  310. {
  311. push @contrib_excludes,'uuid-ossp';
  312. }
  313. # Pgcrypto makefile too complex to parse....
  314. my $pgcrypto = $solution->AddProject('pgcrypto','dll','crypto');
  315. $pgcrypto->AddFiles(
  316. 'contrib\pgcrypto','pgcrypto.c','px.c','px-hmac.c',
  317. 'px-crypt.c','crypt-gensalt.c','crypt-blowfish.c','crypt-des.c',
  318. 'crypt-md5.c','mbuf.c','pgp.c','pgp-armor.c',
  319. 'pgp-cfb.c','pgp-compress.c','pgp-decrypt.c','pgp-encrypt.c',
  320. 'pgp-info.c','pgp-mpi.c','pgp-pubdec.c','pgp-pubenc.c',
  321. 'pgp-pubkey.c','pgp-s2k.c','pgp-pgsql.c'
  322. );
  323. if ($solution->{options}->{openssl})
  324. {
  325. $pgcrypto->AddFiles('contrib\pgcrypto', 'openssl.c','pgp-mpi-openssl.c');
  326. }
  327. else
  328. {
  329. $pgcrypto->AddFiles(
  330. 'contrib\pgcrypto', 'md5.c','sha1.c','sha2.c',
  331. 'internal.c','internal-sha2.c','blf.c','rijndael.c',
  332. 'fortuna.c','random.c','pgp-mpi-internal.c','imath.c'
  333. );
  334. }
  335. $pgcrypto->AddReference($postgres);
  336. $pgcrypto->AddLibrary('wsock32.lib');
  337. my $mf = Project::read_file('contrib/pgcrypto/Makefile');
  338. GenerateContribSqlFiles('pgcrypto', $mf);
  339. my $D;
  340. opendir($D, 'contrib') || croak "Could not opendir on contrib!\n";
  341. while (my $d = readdir($D))
  342. {
  343. next if ($d =~ /^\./);
  344. next unless (-f "contrib/$d/Makefile");
  345. next if (grep {/^$d$/} @contrib_excludes);
  346. AddContrib($d);
  347. }
  348. closedir($D);
  349. $mf = Project::read_file('src\backend\utils\mb\conversion_procs\Makefile');
  350. $mf =~ s{\\s*[\r\n]+}{}mg;
  351. $mf =~ m{SUBDIRS\s*=\s*(.*)$}m || die 'Could not match in conversion makefile' . "\n";
  352. foreach my $sub (split /\s+/,$1)
  353. {
  354. my $mf = Project::read_file('src\backend\utils\mb\conversion_procs\\' . $sub . '\Makefile');
  355. my $p = $solution->AddProject($sub, 'dll', 'conversion procs');
  356. $p->AddFile('src\backend\utils\mb\conversion_procs\\' . $sub . '\\' . $sub . '.c');
  357. if ($mf =~ m{^SRCS\s*\+=\s*(.*)$}m)
  358. {
  359. $p->AddFile('src\backend\utils\mb\conversion_procs\\' . $sub . '\\' . $1);
  360. }
  361. $p->AddReference($postgres);
  362. }
  363. $mf = Project::read_file('src\bin\scripts\Makefile');
  364. $mf =~ s{\\s*[\r\n]+}{}mg;
  365. $mf =~ m{PROGRAMS\s*=\s*(.*)$}m || die 'Could not match in bin\scripts\Makefile' . "\n";
  366. foreach my $prg (split /\s+/,$1)
  367. {
  368. my $proj = $solution->AddProject($prg,'exe','bin');
  369. $mf =~ m{$prg\s*:\s*(.*)$}m || die 'Could not find script define for $prg' . "\n";
  370. my @files = split /\s+/,$1;
  371. foreach my $f (@files)
  372. {
  373. $f =~ s/\.o$/\.c/;
  374. if ($f eq 'keywords.c')
  375. {
  376. $proj->AddFile('src\bin\pg_dump\keywords.c');
  377. }
  378. elsif ($f eq 'kwlookup.c')
  379. {
  380. $proj->AddFile('src\backend\parser\kwlookup.c');
  381. }
  382. elsif ($f eq 'dumputils.c')
  383. {
  384. $proj->AddFile('src\bin\pg_dump\dumputils.c');
  385. }
  386. elsif ($f =~ /print\.c$/)
  387. { # Also catches mbprint.c
  388. $proj->AddFile('src\bin\psql\\' . $f);
  389. }
  390. elsif ($f =~ /\.c$/)
  391. {
  392. $proj->AddFile('src\bin\scripts\\' . $f);
  393. }
  394. }
  395. $proj->AddIncludeDir('src\interfaces\libpq');
  396. $proj->AddIncludeDir('src\bin\pg_dump');
  397. $proj->AddIncludeDir('src\bin\psql');
  398. $proj->AddReference($libpq,$libpgport);
  399. $proj->AddResourceFile('src\bin\scripts','PostgreSQL Utility');
  400. }
  401. # Regression DLL and EXE
  402. my $regress = $solution->AddProject('regress','dll','misc');
  403. $regress->AddFile('src\test\regress\regress.c');
  404. $regress->AddReference($postgres);
  405. my $pgregress = $solution->AddProject('pg_regress','exe','misc');
  406. $pgregress->AddFile('src\test\regress\pg_regress.c');
  407. $pgregress->AddFile('src\test\regress\pg_regress_main.c');
  408. $pgregress->AddIncludeDir('src\port');
  409. $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
  410. $pgregress->AddReference($libpgport);
  411. $solution->Save();
  412. }
  413. #####################
  414. # Utility functions #
  415. #####################
  416. # Add a simple frontend project (exe)
  417. sub AddSimpleFrontend
  418. {
  419. my $n = shift;
  420. my $uselibpq= shift;
  421. my $p = $solution->AddProject($n,'exe','bin');
  422. $p->AddDir('src\bin\\' . $n);
  423. $p->AddReference($libpgport);
  424. if ($uselibpq)
  425. {
  426. $p->AddIncludeDir('src\interfaces\libpq');
  427. $p->AddReference($libpq);
  428. }
  429. return $p;
  430. }
  431. # Add a simple contrib project
  432. sub AddContrib
  433. {
  434. my $n = shift;
  435. my $mf = Project::read_file('contrib\\' . $n . '\Makefile');
  436. if ($mf =~ /^MODULE_big\s*=\s*(.*)$/mg)
  437. {
  438. my $dn = $1;
  439. $mf =~ s{\\\s*[\r\n]+}{}mg;
  440. my $proj = $solution->AddProject($dn, 'dll', 'contrib');
  441. $mf =~ /^OBJS\s*=\s*(.*)$/gm || croak "Could not find objects in MODULE_big for $n\n";
  442. my $objs = $1;
  443. while ($objs =~ /\b([\w-]+\.o)\b/g)
  444. {
  445. my $o = $1;
  446. $o =~ s/\.o$/.c/;
  447. $proj->AddFile('contrib\\' . $n . '\\' . $o);
  448. }
  449. $proj->AddReference($postgres);
  450. if ($mf =~ /^SUBDIRS\s*:?=\s*(.*)$/mg)
  451. {
  452. foreach my $d (split /\s+/, $1)
  453. {
  454. my $mf2 = Project::read_file('contrib\\' . $n . '\\' . $d . '\Makefile');
  455. $mf2 =~ s{\\\s*[\r\n]+}{}mg;
  456. $mf2 =~ /^SUBOBJS\s*=\s*(.*)$/gm
  457. || croak "Could not find objects in MODULE_big for $n, subdir $d\n";
  458. $objs = $1;
  459. while ($objs =~ /\b([\w-]+\.o)\b/g)
  460. {
  461. my $o = $1;
  462. $o =~ s/\.o$/.c/;
  463. $proj->AddFile('contrib\\' . $n . '\\' . $d . '\\' . $o);
  464. }
  465. }
  466. }
  467. AdjustContribProj($proj);
  468. }
  469. elsif ($mf =~ /^MODULES\s*=\s*(.*)$/mg)
  470. {
  471. foreach my $mod (split /\s+/, $1)
  472. {
  473. my $proj = $solution->AddProject($mod, 'dll', 'contrib');
  474. $proj->AddFile('contrib\\' . $n . '\\' . $mod . '.c');
  475. $proj->AddReference($postgres);
  476. AdjustContribProj($proj);
  477. }
  478. }
  479. elsif ($mf =~ /^PROGRAM\s*=\s*(.*)$/mg)
  480. {
  481. my $proj = $solution->AddProject($1, 'exe', 'contrib');
  482. $mf =~ s{\\\s*[\r\n]+}{}mg;
  483. $mf =~ /^OBJS\s*=\s*(.*)$/gm || croak "Could not find objects in PROGRAM for $n\n";
  484. my $objs = $1;
  485. while ($objs =~ /\b([\w-]+\.o)\b/g)
  486. {
  487. my $o = $1;
  488. $o =~ s/\.o$/.c/;
  489. $proj->AddFile('contrib\\' . $n . '\\' . $o);
  490. }
  491. AdjustContribProj($proj);
  492. }
  493. else
  494. {
  495. croak "Could not determine contrib module type for $n\n";
  496. }
  497. # Are there any output data files to build?
  498. GenerateContribSqlFiles($n, $mf);
  499. }
  500. sub GenerateContribSqlFiles
  501. {
  502. my $n = shift;
  503. my $mf = shift;
  504. if ($mf =~ /^DATA_built\s*=\s*(.*)$/mg)
  505. {
  506. my $l = $1;
  507. # Strip out $(addsuffix) rules
  508. if (index($l, '$(addsuffix ') >= 0)
  509. {
  510. my $pcount = 0;
  511. my $i;
  512. for ($i = index($l, '$(addsuffix ') + 12; $i < length($l); $i++)
  513. {
  514. $pcount++ if (substr($l, $i, 1) eq '(');
  515. $pcount-- if (substr($l, $i, 1) eq ')');
  516. last if ($pcount < 0);
  517. }
  518. $l = substr($l, 0, index($l, '$(addsuffix ')) . substr($l, $i+1);
  519. }
  520. # Special case for contrib/spi
  521. $l = "autoinc.sql insert_username.sql moddatetime.sql refint.sql timetravel.sql"
  522. if ($n eq 'spi');
  523. foreach my $d (split /\s+/, $l)
  524. {
  525. my $in = "$d.in";
  526. my $out = "$d";
  527. if (Solution::IsNewer("contrib/$n/$out", "contrib/$n/$in"))
  528. {
  529. print "Building $out from $in (contrib/$n)...\n";
  530. my $cont = Project::read_file("contrib/$n/$in");
  531. my $dn = $out;
  532. $dn =~ s/\.sql$//;
  533. if ($mf =~ /^MODULE_big\s*=\s*(.*)$/m) { $dn = $1 }
  534. $cont =~ s/MODULE_PATHNAME/\$libdir\/$dn/g;
  535. my $o;
  536. open($o,">contrib/$n/$out") || croak "Could not write to contrib/$n/$d";
  537. print $o $cont;
  538. close($o);
  539. }
  540. }
  541. }
  542. }
  543. sub AdjustContribProj
  544. {
  545. my $proj = shift;
  546. my $n = $proj->{name};
  547. if ($contrib_defines->{$n})
  548. {
  549. foreach my $d ($contrib_defines->{$n})
  550. {
  551. $proj->AddDefine($d);
  552. }
  553. }
  554. if (grep {/^$n$/} @contrib_uselibpq)
  555. {
  556. $proj->AddIncludeDir('src\interfaces\libpq');
  557. $proj->AddReference($libpq);
  558. }
  559. if (grep {/^$n$/} @contrib_uselibpgport)
  560. {
  561. $proj->AddReference($libpgport);
  562. }
  563. if ($contrib_extralibs->{$n})
  564. {
  565. foreach my $l (@{$contrib_extralibs->{$n}})
  566. {
  567. $proj->AddLibrary($l);
  568. }
  569. }
  570. if ($contrib_extraincludes->{$n})
  571. {
  572. foreach my $i (@{$contrib_extraincludes->{$n}})
  573. {
  574. $proj->AddIncludeDir($i);
  575. }
  576. }
  577. if ($contrib_extrasource->{$n})
  578. {
  579. $proj->AddFiles('contrib\\' . $n, @{$contrib_extrasource->{$n}});
  580. }
  581. }
  582. 1;