PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/tools/msvc/Mkvcbuild.pm

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