PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/tools/msvc/Mkvcbuild.pm

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