PageRenderTime 59ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/src/tools/msvc/Mkvcbuild.pm

https://bitbucket.org/robins/postgresql
Perl | 794 lines | 715 code | 59 blank | 20 comment | 44 complexity | 0cf101ee2bd49140b246372c68201166 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 File::Basename;
  16. use Config;
  17. use VSObjectFactory;
  18. use List::Util qw(first);
  19. use Exporter;
  20. our (@ISA, @EXPORT_OK);
  21. @ISA = qw(Exporter);
  22. @EXPORT_OK = qw(Mkvcbuild);
  23. my $solution;
  24. my $libpgport;
  25. my $libpgcommon;
  26. my $postgres;
  27. my $libpq;
  28. my $contrib_defines = { 'refint' => 'REFINT_VERBOSE' };
  29. my @contrib_uselibpq =
  30. ('dblink', 'oid2name', 'pgbench', 'pg_upgrade', 'postgres_fdw', 'vacuumlo');
  31. my @contrib_uselibpgport = (
  32. 'oid2name', 'pgbench',
  33. 'pg_standby', 'pg_archivecleanup',
  34. 'pg_test_fsync', 'pg_test_timing',
  35. 'pg_upgrade', 'pg_xlogdump',
  36. 'vacuumlo');
  37. my @contrib_uselibpgcommon = (
  38. 'oid2name', 'pgbench',
  39. 'pg_standby', 'pg_archivecleanup',
  40. 'pg_test_fsync', 'pg_test_timing',
  41. 'pg_upgrade', 'pg_xlogdump',
  42. 'vacuumlo');
  43. my $contrib_extralibs = { 'pgbench' => ['wsock32.lib'] };
  44. my $contrib_extraincludes =
  45. { 'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend'] };
  46. my $contrib_extrasource = {
  47. 'cube' => [ 'cubescan.l', 'cubeparse.y' ],
  48. 'seg' => [ 'segscan.l', 'segparse.y' ],
  49. };
  50. my @contrib_excludes = ('pgcrypto', 'intagg', 'sepgsql');
  51. sub mkvcbuild
  52. {
  53. our $config = shift;
  54. chdir('..\..\..') if (-d '..\msvc' && -d '..\..\..\src');
  55. die 'Must run from root or msvc directory'
  56. unless (-d 'src\tools\msvc' && -d 'src');
  57. my $vsVersion = DetermineVisualStudioVersion();
  58. $solution = CreateSolution($vsVersion, $config);
  59. our @pgportfiles = qw(
  60. chklocale.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c random.c
  61. srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
  62. erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c exec.c noblock.c path.c
  63. pgcheckdir.c pg_crc.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
  64. qsort.c qsort_arg.c quotes.c
  65. sprompt.c tar.c thread.c wait_error.c getopt.c getopt_long.c dirent.c rint.c win32env.c
  66. win32error.c win32setlocale.c);
  67. our @pgcommonallfiles = qw(
  68. relpath.c);
  69. our @pgcommonfrontendfiles = (@pgcommonallfiles,
  70. qw(fe_memutils.c));
  71. our @pgcommonbkndfiles = @pgcommonallfiles;
  72. $libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
  73. $libpgport->AddDefine('FRONTEND');
  74. $libpgport->AddFiles('src\port', @pgportfiles);
  75. $libpgcommon = $solution->AddProject('libpgcommon', 'lib', 'misc');
  76. $libpgcommon->AddDefine('FRONTEND');
  77. $libpgcommon->AddFiles('src\common', @pgcommonfrontendfiles);
  78. $postgres = $solution->AddProject('postgres', 'exe', '', 'src\backend');
  79. $postgres->AddIncludeDir('src\backend');
  80. $postgres->AddDir('src\backend\port\win32');
  81. $postgres->AddFile('src\backend\utils\fmgrtab.c');
  82. $postgres->ReplaceFile(
  83. 'src\backend\port\dynloader.c',
  84. 'src\backend\port\dynloader\win32.c');
  85. $postgres->ReplaceFile('src\backend\port\pg_sema.c',
  86. 'src\backend\port\win32_sema.c');
  87. $postgres->ReplaceFile('src\backend\port\pg_shmem.c',
  88. 'src\backend\port\win32_shmem.c');
  89. $postgres->ReplaceFile('src\backend\port\pg_latch.c',
  90. 'src\backend\port\win32_latch.c');
  91. $postgres->AddFiles('src\port', @pgportfiles);
  92. $postgres->AddFiles('src\common', @pgcommonbkndfiles);
  93. $postgres->AddDir('src\timezone');
  94. $postgres->AddFiles('src\backend\parser', 'scan.l', 'gram.y');
  95. $postgres->AddFiles('src\backend\bootstrap', 'bootscanner.l',
  96. 'bootparse.y');
  97. $postgres->AddFiles('src\backend\utils\misc', 'guc-file.l');
  98. $postgres->AddFiles('src\backend\replication', 'repl_scanner.l',
  99. 'repl_gram.y');
  100. $postgres->AddDefine('BUILDING_DLL');
  101. $postgres->AddLibrary('wsock32.lib');
  102. $postgres->AddLibrary('ws2_32.lib');
  103. $postgres->AddLibrary('secur32.lib');
  104. $postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
  105. $postgres->FullExportDLL('postgres.lib');
  106. my $snowball = $solution->AddProject('dict_snowball', 'dll', '',
  107. 'src\backend\snowball');
  108. $snowball->RelocateFiles(
  109. 'src\backend\snowball\libstemmer',
  110. sub {
  111. return shift !~ /dict_snowball.c$/;
  112. });
  113. $snowball->AddIncludeDir('src\include\snowball');
  114. $snowball->AddReference($postgres);
  115. my $plpgsql =
  116. $solution->AddProject('plpgsql', 'dll', 'PLs', 'src\pl\plpgsql\src');
  117. $plpgsql->AddFiles('src\pl\plpgsql\src', 'pl_gram.y');
  118. $plpgsql->AddReference($postgres);
  119. if ($solution->{options}->{perl})
  120. {
  121. my $plperlsrc = "src\\pl\\plperl\\";
  122. my $plperl =
  123. $solution->AddProject('plperl', 'dll', 'PLs', 'src\pl\plperl');
  124. $plperl->AddIncludeDir($solution->{options}->{perl} . '/lib/CORE');
  125. $plperl->AddDefine('PLPERL_HAVE_UID_GID');
  126. foreach my $xs ('SPI.xs', 'Util.xs')
  127. {
  128. (my $xsc = $xs) =~ s/\.xs/.c/;
  129. if (Solution::IsNewer("$plperlsrc$xsc", "$plperlsrc$xs"))
  130. {
  131. my $xsubppdir = first { -e "$_\\ExtUtils\\xsubpp" } @INC;
  132. print "Building $plperlsrc$xsc...\n";
  133. system( $solution->{options}->{perl}
  134. . '/bin/perl '
  135. . "$xsubppdir/ExtUtils/xsubpp -typemap "
  136. . $solution->{options}->{perl}
  137. . '/lib/ExtUtils/typemap '
  138. . "$plperlsrc$xs "
  139. . ">$plperlsrc$xsc");
  140. if ((!(-f "$plperlsrc$xsc")) || -z "$plperlsrc$xsc")
  141. {
  142. unlink("$plperlsrc$xsc"); # if zero size
  143. die "Failed to create $xsc.\n";
  144. }
  145. }
  146. }
  147. if (Solution::IsNewer(
  148. 'src\pl\plperl\perlchunks.h',
  149. 'src\pl\plperl\plc_perlboot.pl')
  150. || Solution::IsNewer(
  151. 'src\pl\plperl\perlchunks.h',
  152. 'src\pl\plperl\plc_trusted.pl'))
  153. {
  154. print 'Building src\pl\plperl\perlchunks.h ...' . "\n";
  155. my $basedir = getcwd;
  156. chdir 'src\pl\plperl';
  157. system( $solution->{options}->{perl}
  158. . '/bin/perl '
  159. . 'text2macro.pl '
  160. . '--strip="^(\#.*|\s*)$$" '
  161. . 'plc_perlboot.pl plc_trusted.pl '
  162. . '>perlchunks.h');
  163. chdir $basedir;
  164. if ((!(-f 'src\pl\plperl\perlchunks.h'))
  165. || -z 'src\pl\plperl\perlchunks.h')
  166. {
  167. unlink('src\pl\plperl\perlchunks.h'); # if zero size
  168. die 'Failed to create perlchunks.h' . "\n";
  169. }
  170. }
  171. if (Solution::IsNewer(
  172. 'src\pl\plperl\plperl_opmask.h',
  173. 'src\pl\plperl\plperl_opmask.pl'))
  174. {
  175. print 'Building src\pl\plperl\plperl_opmask.h ...' . "\n";
  176. my $basedir = getcwd;
  177. chdir 'src\pl\plperl';
  178. system( $solution->{options}->{perl}
  179. . '/bin/perl '
  180. . 'plperl_opmask.pl '
  181. . 'plperl_opmask.h');
  182. chdir $basedir;
  183. if ((!(-f 'src\pl\plperl\plperl_opmask.h'))
  184. || -z 'src\pl\plperl\plperl_opmask.h')
  185. {
  186. unlink('src\pl\plperl\plperl_opmask.h'); # if zero size
  187. die 'Failed to create plperl_opmask.h' . "\n";
  188. }
  189. }
  190. $plperl->AddReference($postgres);
  191. my @perl_libs =
  192. grep { /perl\d+.lib$/ }
  193. glob($solution->{options}->{perl} . '\lib\CORE\perl*.lib');
  194. if (@perl_libs == 1)
  195. {
  196. $plperl->AddLibrary($perl_libs[0]);
  197. }
  198. else
  199. {
  200. die "could not identify perl library version";
  201. }
  202. }
  203. if ($solution->{options}->{python})
  204. {
  205. # Attempt to get python version and location.
  206. # Assume python.exe in specified dir.
  207. open(P,
  208. $solution->{options}->{python}
  209. . "\\python -c \"import sys;print(sys.prefix);print(str(sys.version_info[0])+str(sys.version_info[1]))\" |"
  210. ) || die "Could not query for python version!\n";
  211. my $pyprefix = <P>;
  212. chomp($pyprefix);
  213. my $pyver = <P>;
  214. chomp($pyver);
  215. close(P);
  216. # Sometimes (always?) if python is not present, the execution
  217. # appears to work, but gives no data...
  218. die "Failed to query python for version information\n"
  219. if (!(defined($pyprefix) && defined($pyver)));
  220. my $pymajorver = substr($pyver, 0, 1);
  221. my $plpython = $solution->AddProject('plpython' . $pymajorver,
  222. 'dll', 'PLs', 'src\pl\plpython');
  223. $plpython->AddIncludeDir($pyprefix . '\include');
  224. $plpython->AddLibrary($pyprefix . "\\Libs\\python$pyver.lib");
  225. $plpython->AddReference($postgres);
  226. }
  227. if ($solution->{options}->{tcl})
  228. {
  229. my $pltcl =
  230. $solution->AddProject('pltcl', 'dll', 'PLs', 'src\pl\tcl');
  231. $pltcl->AddIncludeDir($solution->{options}->{tcl} . '\include');
  232. $pltcl->AddReference($postgres);
  233. if (-e $solution->{options}->{tcl} . '\lib\tcl85.lib')
  234. {
  235. $pltcl->AddLibrary(
  236. $solution->{options}->{tcl} . '\lib\tcl85.lib');
  237. }
  238. else
  239. {
  240. $pltcl->AddLibrary(
  241. $solution->{options}->{tcl} . '\lib\tcl84.lib');
  242. }
  243. }
  244. $libpq = $solution->AddProject('libpq', 'dll', 'interfaces',
  245. 'src\interfaces\libpq');
  246. $libpq->AddDefine('FRONTEND');
  247. $libpq->AddDefine('UNSAFE_STAT_OK');
  248. $libpq->AddIncludeDir('src\port');
  249. $libpq->AddLibrary('wsock32.lib');
  250. $libpq->AddLibrary('secur32.lib');
  251. $libpq->AddLibrary('ws2_32.lib');
  252. $libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
  253. $libpq->UseDef('src\interfaces\libpq\libpqdll.def');
  254. $libpq->ReplaceFile('src\interfaces\libpq\libpqrc.c',
  255. 'src\interfaces\libpq\libpq.rc');
  256. $libpq->AddReference($libpgport);
  257. my $libpqwalreceiver =
  258. $solution->AddProject('libpqwalreceiver', 'dll', '',
  259. 'src\backend\replication\libpqwalreceiver');
  260. $libpqwalreceiver->AddIncludeDir('src\interfaces\libpq');
  261. $libpqwalreceiver->AddReference($postgres, $libpq);
  262. my $pgtypes = $solution->AddProject(
  263. 'libpgtypes', 'dll',
  264. 'interfaces', 'src\interfaces\ecpg\pgtypeslib');
  265. $pgtypes->AddDefine('FRONTEND');
  266. $pgtypes->AddReference($libpgport);
  267. $pgtypes->UseDef('src\interfaces\ecpg\pgtypeslib\pgtypeslib.def');
  268. $pgtypes->AddIncludeDir('src\interfaces\ecpg\include');
  269. my $libecpg = $solution->AddProject('libecpg', 'dll', 'interfaces',
  270. 'src\interfaces\ecpg\ecpglib');
  271. $libecpg->AddDefine('FRONTEND');
  272. $libecpg->AddIncludeDir('src\interfaces\ecpg\include');
  273. $libecpg->AddIncludeDir('src\interfaces\libpq');
  274. $libecpg->AddIncludeDir('src\port');
  275. $libecpg->UseDef('src\interfaces\ecpg\ecpglib\ecpglib.def');
  276. $libecpg->AddLibrary('wsock32.lib');
  277. $libecpg->AddReference($libpq, $pgtypes, $libpgport);
  278. my $libecpgcompat = $solution->AddProject(
  279. 'libecpg_compat', 'dll',
  280. 'interfaces', 'src\interfaces\ecpg\compatlib');
  281. $libecpgcompat->AddIncludeDir('src\interfaces\ecpg\include');
  282. $libecpgcompat->AddIncludeDir('src\interfaces\libpq');
  283. $libecpgcompat->UseDef('src\interfaces\ecpg\compatlib\compatlib.def');
  284. $libecpgcompat->AddReference($pgtypes, $libecpg, $libpgport);
  285. my $ecpg = $solution->AddProject('ecpg', 'exe', 'interfaces',
  286. 'src\interfaces\ecpg\preproc');
  287. $ecpg->AddIncludeDir('src\interfaces\ecpg\include');
  288. $ecpg->AddIncludeDir('src\interfaces\libpq');
  289. $ecpg->AddPrefixInclude('src\interfaces\ecpg\preproc');
  290. $ecpg->AddFiles('src\interfaces\ecpg\preproc', 'pgc.l', 'preproc.y');
  291. $ecpg->AddDefine('MAJOR_VERSION=4');
  292. $ecpg->AddDefine('MINOR_VERSION=9');
  293. $ecpg->AddDefine('PATCHLEVEL=0');
  294. $ecpg->AddDefine('ECPG_COMPILE');
  295. $ecpg->AddReference($libpgport, $libpgcommon);
  296. my $pgregress_ecpg =
  297. $solution->AddProject('pg_regress_ecpg', 'exe', 'misc');
  298. $pgregress_ecpg->AddFile('src\interfaces\ecpg\test\pg_regress_ecpg.c');
  299. $pgregress_ecpg->AddFile('src\test\regress\pg_regress.c');
  300. $pgregress_ecpg->AddIncludeDir('src\port');
  301. $pgregress_ecpg->AddIncludeDir('src\test\regress');
  302. $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
  303. $pgregress_ecpg->AddDefine('FRONTEND');
  304. $pgregress_ecpg->AddReference($libpgport, $libpgcommon);
  305. my $isolation_tester =
  306. $solution->AddProject('isolationtester', 'exe', 'misc');
  307. $isolation_tester->AddFile('src\test\isolation\isolationtester.c');
  308. $isolation_tester->AddFile('src\test\isolation\specparse.y');
  309. $isolation_tester->AddFile('src\test\isolation\specscanner.l');
  310. $isolation_tester->AddFile('src\test\isolation\specparse.c');
  311. $isolation_tester->AddIncludeDir('src\test\isolation');
  312. $isolation_tester->AddIncludeDir('src\port');
  313. $isolation_tester->AddIncludeDir('src\test\regress');
  314. $isolation_tester->AddIncludeDir('src\interfaces\libpq');
  315. $isolation_tester->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
  316. $isolation_tester->AddDefine('FRONTEND');
  317. $isolation_tester->AddLibrary('wsock32.lib');
  318. $isolation_tester->AddReference($libpq, $libpgport);
  319. my $pgregress_isolation =
  320. $solution->AddProject('pg_isolation_regress', 'exe', 'misc');
  321. $pgregress_isolation->AddFile('src\test\isolation\isolation_main.c');
  322. $pgregress_isolation->AddFile('src\test\regress\pg_regress.c');
  323. $pgregress_isolation->AddIncludeDir('src\port');
  324. $pgregress_isolation->AddIncludeDir('src\test\regress');
  325. $pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
  326. $pgregress_isolation->AddDefine('FRONTEND');
  327. $pgregress_isolation->AddReference($libpgport, $libpgcommon);
  328. # src/bin
  329. my $initdb = AddSimpleFrontend('initdb');
  330. $initdb->AddIncludeDir('src\interfaces\libpq');
  331. $initdb->AddIncludeDir('src\timezone');
  332. $initdb->AddDefine('FRONTEND');
  333. $initdb->AddLibrary('wsock32.lib');
  334. $initdb->AddLibrary('ws2_32.lib');
  335. my $pgbasebackup = AddSimpleFrontend('pg_basebackup', 1);
  336. $pgbasebackup->AddFile('src\bin\pg_basebackup\pg_basebackup.c');
  337. $pgbasebackup->AddLibrary('ws2_32.lib');
  338. my $pgreceivexlog = AddSimpleFrontend('pg_basebackup', 1);
  339. $pgreceivexlog->{name} = 'pg_receivexlog';
  340. $pgreceivexlog->AddFile('src\bin\pg_basebackup\pg_receivexlog.c');
  341. $pgreceivexlog->AddLibrary('ws2_32.lib');
  342. my $pgconfig = AddSimpleFrontend('pg_config');
  343. my $pgcontrol = AddSimpleFrontend('pg_controldata');
  344. my $pgctl = AddSimpleFrontend('pg_ctl', 1);
  345. my $pgreset = AddSimpleFrontend('pg_resetxlog');
  346. my $pgevent = $solution->AddProject('pgevent', 'dll', 'bin');
  347. $pgevent->AddFiles('src\bin\pgevent', 'pgevent.c', 'pgmsgevent.rc');
  348. $pgevent->AddResourceFile('src\bin\pgevent',
  349. 'Eventlog message formatter');
  350. $pgevent->RemoveFile('src\bin\pgevent\win32ver.rc');
  351. $pgevent->UseDef('src\bin\pgevent\pgevent.def');
  352. $pgevent->DisableLinkerWarnings('4104');
  353. my $psql = AddSimpleFrontend('psql', 1);
  354. $psql->AddIncludeDir('src\bin\pg_dump');
  355. $psql->AddIncludeDir('src\backend');
  356. $psql->AddFile('src\bin\psql\psqlscan.l');
  357. my $pgdump = AddSimpleFrontend('pg_dump', 1);
  358. $pgdump->AddIncludeDir('src\backend');
  359. $pgdump->AddFile('src\bin\pg_dump\pg_dump.c');
  360. $pgdump->AddFile('src\bin\pg_dump\common.c');
  361. $pgdump->AddFile('src\bin\pg_dump\pg_dump_sort.c');
  362. $pgdump->AddFile('src\bin\pg_dump\keywords.c');
  363. $pgdump->AddFile('src\backend\parser\kwlookup.c');
  364. my $pgdumpall = AddSimpleFrontend('pg_dump', 1);
  365. # pg_dumpall doesn't use the files in the Makefile's $(OBJS), unlike
  366. # pg_dump and pg_restore.
  367. # So remove their sources from the object, keeping the other setup that
  368. # AddSimpleFrontend() has done.
  369. my @nodumpall = grep { m/src\\bin\\pg_dump\\.*\.c$/ }
  370. keys %{ $pgdumpall->{files} };
  371. delete @{ $pgdumpall->{files} }{@nodumpall};
  372. $pgdumpall->{name} = 'pg_dumpall';
  373. $pgdumpall->AddIncludeDir('src\backend');
  374. $pgdumpall->AddFile('src\bin\pg_dump\pg_dumpall.c');
  375. $pgdumpall->AddFile('src\bin\pg_dump\dumputils.c');
  376. $pgdumpall->AddFile('src\bin\pg_dump\keywords.c');
  377. $pgdumpall->AddFile('src\backend\parser\kwlookup.c');
  378. my $pgrestore = AddSimpleFrontend('pg_dump', 1);
  379. $pgrestore->{name} = 'pg_restore';
  380. $pgrestore->AddIncludeDir('src\backend');
  381. $pgrestore->AddFile('src\bin\pg_dump\pg_restore.c');
  382. $pgrestore->AddFile('src\bin\pg_dump\keywords.c');
  383. $pgrestore->AddFile('src\backend\parser\kwlookup.c');
  384. my $zic = $solution->AddProject('zic', 'exe', 'utils');
  385. $zic->AddFiles('src\timezone', 'zic.c', 'ialloc.c', 'scheck.c',
  386. 'localtime.c');
  387. $zic->AddReference($libpgport, $libpgcommon);
  388. if ($solution->{options}->{xml})
  389. {
  390. $contrib_extraincludes->{'pgxml'} = [
  391. $solution->{options}->{xml} . '\include',
  392. $solution->{options}->{xslt} . '\include',
  393. $solution->{options}->{iconv} . '\include' ];
  394. $contrib_extralibs->{'pgxml'} = [
  395. $solution->{options}->{xml} . '\lib\libxml2.lib',
  396. $solution->{options}->{xslt} . '\lib\libxslt.lib' ];
  397. }
  398. else
  399. {
  400. push @contrib_excludes, 'xml2';
  401. }
  402. if (!$solution->{options}->{openssl})
  403. {
  404. push @contrib_excludes, 'sslinfo';
  405. }
  406. if ($solution->{options}->{uuid})
  407. {
  408. $contrib_extraincludes->{'uuid-ossp'} =
  409. [ $solution->{options}->{uuid} . '\include' ];
  410. $contrib_extralibs->{'uuid-ossp'} =
  411. [ $solution->{options}->{uuid} . '\lib\uuid.lib' ];
  412. }
  413. else
  414. {
  415. push @contrib_excludes, 'uuid-ossp';
  416. }
  417. # Pgcrypto makefile too complex to parse....
  418. my $pgcrypto = $solution->AddProject('pgcrypto', 'dll', 'crypto');
  419. $pgcrypto->AddFiles(
  420. 'contrib\pgcrypto', 'pgcrypto.c',
  421. 'px.c', 'px-hmac.c',
  422. 'px-crypt.c', 'crypt-gensalt.c',
  423. 'crypt-blowfish.c', 'crypt-des.c',
  424. 'crypt-md5.c', 'mbuf.c',
  425. 'pgp.c', 'pgp-armor.c',
  426. 'pgp-cfb.c', 'pgp-compress.c',
  427. 'pgp-decrypt.c', 'pgp-encrypt.c',
  428. 'pgp-info.c', 'pgp-mpi.c',
  429. 'pgp-pubdec.c', 'pgp-pubenc.c',
  430. 'pgp-pubkey.c', 'pgp-s2k.c',
  431. 'pgp-pgsql.c');
  432. if ($solution->{options}->{openssl})
  433. {
  434. $pgcrypto->AddFiles('contrib\pgcrypto', 'openssl.c',
  435. 'pgp-mpi-openssl.c');
  436. }
  437. else
  438. {
  439. $pgcrypto->AddFiles(
  440. 'contrib\pgcrypto', 'md5.c',
  441. 'sha1.c', 'sha2.c',
  442. 'internal.c', 'internal-sha2.c',
  443. 'blf.c', 'rijndael.c',
  444. 'fortuna.c', 'random.c',
  445. 'pgp-mpi-internal.c', 'imath.c');
  446. }
  447. $pgcrypto->AddReference($postgres);
  448. $pgcrypto->AddLibrary('wsock32.lib');
  449. my $mf = Project::read_file('contrib/pgcrypto/Makefile');
  450. GenerateContribSqlFiles('pgcrypto', $mf);
  451. my $D;
  452. opendir($D, 'contrib') || croak "Could not opendir on contrib!\n";
  453. while (my $d = readdir($D))
  454. {
  455. next if ($d =~ /^\./);
  456. next unless (-f "contrib/$d/Makefile");
  457. next if (grep { /^$d$/ } @contrib_excludes);
  458. AddContrib($d);
  459. }
  460. closedir($D);
  461. $mf =
  462. Project::read_file('src\backend\utils\mb\conversion_procs\Makefile');
  463. $mf =~ s{\\s*[\r\n]+}{}mg;
  464. $mf =~ m{SUBDIRS\s*=\s*(.*)$}m
  465. || die 'Could not match in conversion makefile' . "\n";
  466. foreach my $sub (split /\s+/, $1)
  467. {
  468. my $mf = Project::read_file(
  469. 'src\backend\utils\mb\conversion_procs\\' . $sub . '\Makefile');
  470. my $p = $solution->AddProject($sub, 'dll', 'conversion procs');
  471. $p->AddFile('src\backend\utils\mb\conversion_procs\\'
  472. . $sub . '\\'
  473. . $sub
  474. . '.c');
  475. if ($mf =~ m{^SRCS\s*\+=\s*(.*)$}m)
  476. {
  477. $p->AddFile(
  478. 'src\backend\utils\mb\conversion_procs\\' . $sub . '\\' . $1);
  479. }
  480. $p->AddReference($postgres);
  481. }
  482. $mf = Project::read_file('src\bin\scripts\Makefile');
  483. $mf =~ s{\\s*[\r\n]+}{}mg;
  484. $mf =~ m{PROGRAMS\s*=\s*(.*)$}m
  485. || die 'Could not match in bin\scripts\Makefile' . "\n";
  486. foreach my $prg (split /\s+/, $1)
  487. {
  488. my $proj = $solution->AddProject($prg, 'exe', 'bin');
  489. $mf =~ m{$prg\s*:\s*(.*)$}m
  490. || die 'Could not find script define for $prg' . "\n";
  491. my @files = split /\s+/, $1;
  492. foreach my $f (@files)
  493. {
  494. $f =~ s/\.o$/\.c/;
  495. if ($f eq 'keywords.c')
  496. {
  497. $proj->AddFile('src\bin\pg_dump\keywords.c');
  498. }
  499. elsif ($f eq 'kwlookup.c')
  500. {
  501. $proj->AddFile('src\backend\parser\kwlookup.c');
  502. }
  503. elsif ($f eq 'dumputils.c')
  504. {
  505. $proj->AddFile('src\bin\pg_dump\dumputils.c');
  506. }
  507. elsif ($f =~ /print\.c$/)
  508. { # Also catches mbprint.c
  509. $proj->AddFile('src\bin\psql\\' . $f);
  510. }
  511. elsif ($f =~ /\.c$/)
  512. {
  513. $proj->AddFile('src\bin\scripts\\' . $f);
  514. }
  515. }
  516. $proj->AddIncludeDir('src\interfaces\libpq');
  517. $proj->AddIncludeDir('src\bin\pg_dump');
  518. $proj->AddIncludeDir('src\bin\psql');
  519. $proj->AddReference($libpq, $libpgport, $libpgcommon);
  520. $proj->AddResourceFile('src\bin\scripts', 'PostgreSQL Utility');
  521. }
  522. # Regression DLL and EXE
  523. my $regress = $solution->AddProject('regress', 'dll', 'misc');
  524. $regress->AddFile('src\test\regress\regress.c');
  525. $regress->AddReference($postgres);
  526. my $pgregress = $solution->AddProject('pg_regress', 'exe', 'misc');
  527. $pgregress->AddFile('src\test\regress\pg_regress.c');
  528. $pgregress->AddFile('src\test\regress\pg_regress_main.c');
  529. $pgregress->AddIncludeDir('src\port');
  530. $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
  531. $pgregress->AddReference($libpgport, $libpgcommon);
  532. # fix up pg_xlogdump once it's been set up
  533. # files symlinked on Unix are copied on windows
  534. my $pg_xlogdump = (grep {$_->{name} eq 'pg_xlogdump'}
  535. @{$solution->{projects}->{contrib}} )[0];
  536. $pg_xlogdump->AddDefine('FRONTEND');
  537. foreach my $xf (glob('src/backend/access/rmgrdesc/*desc.c') )
  538. {
  539. my $bf = basename $xf;
  540. copy($xf,"contrib/pg_xlogdump/$bf");
  541. $pg_xlogdump->AddFile("contrib\\pg_xlogdump\\$bf");
  542. }
  543. copy('src/backend/access/transam/xlogreader.c',
  544. 'contrib/pg_xlogdump/xlogreader.c');
  545. $solution->Save();
  546. return $solution->{vcver};
  547. }
  548. #####################
  549. # Utility functions #
  550. #####################
  551. # Add a simple frontend project (exe)
  552. sub AddSimpleFrontend
  553. {
  554. my $n = shift;
  555. my $uselibpq = shift;
  556. my $p = $solution->AddProject($n, 'exe', 'bin');
  557. $p->AddDir('src\bin\\' . $n);
  558. $p->AddReference($libpgport, $libpgcommon);
  559. if ($uselibpq)
  560. {
  561. $p->AddIncludeDir('src\interfaces\libpq');
  562. $p->AddReference($libpq);
  563. }
  564. return $p;
  565. }
  566. # Add a simple contrib project
  567. sub AddContrib
  568. {
  569. my $n = shift;
  570. my $mf = Project::read_file('contrib\\' . $n . '\Makefile');
  571. if ($mf =~ /^MODULE_big\s*=\s*(.*)$/mg)
  572. {
  573. my $dn = $1;
  574. $mf =~ s{\\\s*[\r\n]+}{}mg;
  575. my $proj = $solution->AddProject($dn, 'dll', 'contrib');
  576. $mf =~ /^OBJS\s*=\s*(.*)$/gm
  577. || croak "Could not find objects in MODULE_big for $n\n";
  578. my $objs = $1;
  579. while ($objs =~ /\b([\w-]+\.o)\b/g)
  580. {
  581. my $o = $1;
  582. $o =~ s/\.o$/.c/;
  583. $proj->AddFile('contrib\\' . $n . '\\' . $o);
  584. }
  585. $proj->AddReference($postgres);
  586. if ($mf =~ /^SUBDIRS\s*:?=\s*(.*)$/mg)
  587. {
  588. foreach my $d (split /\s+/, $1)
  589. {
  590. my $mf2 = Project::read_file(
  591. 'contrib\\' . $n . '\\' . $d . '\Makefile');
  592. $mf2 =~ s{\\\s*[\r\n]+}{}mg;
  593. $mf2 =~ /^SUBOBJS\s*=\s*(.*)$/gm
  594. || croak
  595. "Could not find objects in MODULE_big for $n, subdir $d\n";
  596. $objs = $1;
  597. while ($objs =~ /\b([\w-]+\.o)\b/g)
  598. {
  599. my $o = $1;
  600. $o =~ s/\.o$/.c/;
  601. $proj->AddFile('contrib\\' . $n . '\\' . $d . '\\' . $o);
  602. }
  603. }
  604. }
  605. AdjustContribProj($proj);
  606. }
  607. elsif ($mf =~ /^MODULES\s*=\s*(.*)$/mg)
  608. {
  609. foreach my $mod (split /\s+/, $1)
  610. {
  611. my $proj = $solution->AddProject($mod, 'dll', 'contrib');
  612. $proj->AddFile('contrib\\' . $n . '\\' . $mod . '.c');
  613. $proj->AddReference($postgres);
  614. AdjustContribProj($proj);
  615. }
  616. }
  617. elsif ($mf =~ /^PROGRAM\s*=\s*(.*)$/mg)
  618. {
  619. my $proj = $solution->AddProject($1, 'exe', 'contrib');
  620. $mf =~ s{\\\s*[\r\n]+}{}mg;
  621. $mf =~ /^OBJS\s*=\s*(.*)$/gm
  622. || croak "Could not find objects in PROGRAM for $n\n";
  623. my $objs = $1;
  624. while ($objs =~ /\b([\w-]+\.o)\b/g)
  625. {
  626. my $o = $1;
  627. $o =~ s/\.o$/.c/;
  628. $proj->AddFile('contrib\\' . $n . '\\' . $o);
  629. }
  630. AdjustContribProj($proj);
  631. }
  632. else
  633. {
  634. croak "Could not determine contrib module type for $n\n";
  635. }
  636. # Are there any output data files to build?
  637. GenerateContribSqlFiles($n, $mf);
  638. }
  639. sub GenerateContribSqlFiles
  640. {
  641. my $n = shift;
  642. my $mf = shift;
  643. if ($mf =~ /^DATA_built\s*=\s*(.*)$/mg)
  644. {
  645. my $l = $1;
  646. # Strip out $(addsuffix) rules
  647. if (index($l, '$(addsuffix ') >= 0)
  648. {
  649. my $pcount = 0;
  650. my $i;
  651. for ($i = index($l, '$(addsuffix ') + 12; $i < length($l); $i++)
  652. {
  653. $pcount++ if (substr($l, $i, 1) eq '(');
  654. $pcount-- if (substr($l, $i, 1) eq ')');
  655. last if ($pcount < 0);
  656. }
  657. $l =
  658. substr($l, 0, index($l, '$(addsuffix ')) . substr($l, $i + 1);
  659. }
  660. foreach my $d (split /\s+/, $l)
  661. {
  662. my $in = "$d.in";
  663. my $out = "$d";
  664. if (Solution::IsNewer("contrib/$n/$out", "contrib/$n/$in"))
  665. {
  666. print "Building $out from $in (contrib/$n)...\n";
  667. my $cont = Project::read_file("contrib/$n/$in");
  668. my $dn = $out;
  669. $dn =~ s/\.sql$//;
  670. $cont =~ s/MODULE_PATHNAME/\$libdir\/$dn/g;
  671. my $o;
  672. open($o, ">contrib/$n/$out")
  673. || croak "Could not write to contrib/$n/$d";
  674. print $o $cont;
  675. close($o);
  676. }
  677. }
  678. }
  679. }
  680. sub AdjustContribProj
  681. {
  682. my $proj = shift;
  683. my $n = $proj->{name};
  684. if ($contrib_defines->{$n})
  685. {
  686. foreach my $d ($contrib_defines->{$n})
  687. {
  688. $proj->AddDefine($d);
  689. }
  690. }
  691. if (grep { /^$n$/ } @contrib_uselibpq)
  692. {
  693. $proj->AddIncludeDir('src\interfaces\libpq');
  694. $proj->AddReference($libpq);
  695. }
  696. if (grep { /^$n$/ } @contrib_uselibpgport)
  697. {
  698. $proj->AddReference($libpgport);
  699. }
  700. if (grep { /^$n$/ } @contrib_uselibpgcommon)
  701. {
  702. $proj->AddReference($libpgcommon);
  703. }
  704. if ($contrib_extralibs->{$n})
  705. {
  706. foreach my $l (@{ $contrib_extralibs->{$n} })
  707. {
  708. $proj->AddLibrary($l);
  709. }
  710. }
  711. if ($contrib_extraincludes->{$n})
  712. {
  713. foreach my $i (@{ $contrib_extraincludes->{$n} })
  714. {
  715. $proj->AddIncludeDir($i);
  716. }
  717. }
  718. if ($contrib_extrasource->{$n})
  719. {
  720. $proj->AddFiles('contrib\\' . $n, @{ $contrib_extrasource->{$n} });
  721. }
  722. }
  723. 1;