From b41aabee7aa54ec2f8e0c1fd770c0ee52b09ca12 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 10 Sep 2021 09:51:51 -0700
Subject: [PATCH v3 16/17] meson: Add draft of a meson based buildsystem.

Author: Andres Freund
Author: Thomas Munro
---
 contrib/adminpack/meson.build                 |   20 +
 contrib/amcheck/meson.build                   |   35 +
 contrib/auth_delay/meson.build                |    4 +
 contrib/auto_explain/meson.build              |   13 +
 contrib/bloom/meson.build                     |   38 +
 contrib/bool_plperl/meson.build               |   37 +
 contrib/btree_gin/meson.build                 |   51 +
 contrib/btree_gist/meson.build                |   79 +
 contrib/citext/meson.build                    |   29 +
 contrib/cube/meson.build                      |   42 +
 contrib/dblink/meson.build                    |   29 +
 contrib/dict_int/meson.build                  |   19 +
 contrib/dict_xsyn/meson.build                 |   26 +
 contrib/earthdistance/meson.build             |   20 +
 contrib/file_fdw/meson.build                  |   19 +
 contrib/fuzzystrmatch/meson.build             |   23 +
 contrib/hstore/meson.build                    |   36 +
 contrib/hstore_plperl/meson.build             |   38 +
 contrib/hstore_plpython/expected/meson.build  |   15 +
 contrib/hstore_plpython/meson.build           |   44 +
 contrib/hstore_plpython/sql/meson.build       |   17 +
 contrib/jsonb_plperl/meson.build              |   37 +
 contrib/jsonb_plpython/expected/meson.build   |   15 +
 contrib/jsonb_plpython/meson.build            |   44 +
 contrib/jsonb_plpython/sql/meson.build        |   17 +
 contrib/meson.build                           |   63 +
 contrib/oid2name/meson.build                  |   14 +
 contrib/pageinspect/meson.build               |   45 +
 contrib/pg_prewarm/meson.build                |   16 +
 contrib/pg_stat_statements/meson.build        |   31 +
 contrib/pg_trgm/meson.build                   |   33 +
 contrib/pg_visibility/meson.build             |   25 +
 contrib/postgres_fdw/meson.build              |   31 +
 contrib/spi/meson.build                       |   43 +
 contrib/test_decoding/meson.build             |   69 +
 contrib/tsm_system_rows/meson.build           |   22 +
 contrib/tsm_system_time/meson.build           |   22 +
 contrib/unaccent/meson.build                  |   30 +
 contrib/vacuumlo/meson.build                  |   14 +
 contrib/xml2/meson.build                      |   30 +
 conversion_helpers.txt                        |    6 +
 meson.build                                   | 1901 +++++++++++++++++
 meson_options.txt                             |   81 +
 src/backend/access/brin/meson.build           |   12 +
 src/backend/access/common/meson.build         |   18 +
 src/backend/access/gin/meson.build            |   17 +
 src/backend/access/gist/meson.build           |   13 +
 src/backend/access/hash/meson.build           |   12 +
 src/backend/access/heap/meson.build           |   11 +
 src/backend/access/index/meson.build          |    6 +
 src/backend/access/meson.build                |   13 +
 src/backend/access/nbtree/meson.build         |   13 +
 src/backend/access/rmgrdesc/meson.build       |   26 +
 src/backend/access/spgist/meson.build         |   13 +
 src/backend/access/table/meson.build          |    6 +
 src/backend/access/tablesample/meson.build    |    5 +
 src/backend/access/transam/meson.build        |   28 +
 src/backend/bootstrap/meson.build             |   12 +
 src/backend/catalog/meson.build               |   41 +
 src/backend/commands/meson.build              |   50 +
 src/backend/executor/meson.build              |   67 +
 src/backend/foreign/meson.build               |    3 +
 src/backend/jit/llvm/meson.build              |   41 +
 src/backend/jit/meson.build                   |    3 +
 src/backend/lib/meson.build                   |   12 +
 src/backend/libpq/meson.build                 |   28 +
 src/backend/main/meson.build                  |    2 +
 src/backend/meson.build                       |  191 ++
 src/backend/nodes/meson.build                 |   17 +
 src/backend/optimizer/geqo/meson.build        |   17 +
 src/backend/optimizer/meson.build             |    5 +
 src/backend/optimizer/path/meson.build        |   11 +
 src/backend/optimizer/plan/meson.build        |   10 +
 src/backend/optimizer/prep/meson.build        |    7 +
 src/backend/optimizer/util/meson.build        |   16 +
 src/backend/parser/meson.build                |   43 +
 src/backend/partitioning/meson.build          |    5 +
 src/backend/port/meson.build                  |   28 +
 src/backend/port/win32/meson.build            |    6 +
 src/backend/postmaster/meson.build            |   15 +
 src/backend/regex/meson.build                 |   15 +
 .../replication/libpqwalreceiver/meson.build  |   13 +
 src/backend/replication/logical/meson.build   |   14 +
 src/backend/replication/meson.build           |   42 +
 src/backend/replication/pgoutput/meson.build  |   11 +
 src/backend/rewrite/meson.build               |    9 +
 src/backend/snowball/meson.build              |   83 +
 src/backend/statistics/meson.build            |    6 +
 src/backend/storage/buffer/meson.build        |    7 +
 src/backend/storage/file/meson.build          |    8 +
 src/backend/storage/freespace/meson.build     |    5 +
 src/backend/storage/ipc/meson.build           |   20 +
 src/backend/storage/large_object/meson.build  |    3 +
 src/backend/storage/lmgr/meson.build          |   18 +
 src/backend/storage/meson.build               |    9 +
 src/backend/storage/page/meson.build          |    5 +
 src/backend/storage/smgr/meson.build          |    4 +
 src/backend/storage/sync/meson.build          |    4 +
 src/backend/tcop/meson.build                  |    8 +
 src/backend/tsearch/meson.build               |   21 +
 src/backend/utils/activity/meson.build        |    5 +
 src/backend/utils/adt/meson.build             |  118 +
 src/backend/utils/cache/meson.build           |   16 +
 src/backend/utils/error/meson.build           |    4 +
 src/backend/utils/fmgr/meson.build            |    8 +
 src/backend/utils/hash/meson.build            |    4 +
 src/backend/utils/init/meson.build            |    4 +
 .../utils/mb/conversion_procs/meson.build     |   38 +
 src/backend/utils/mb/meson.build              |    9 +
 src/backend/utils/meson.build                 |   13 +
 src/backend/utils/misc/meson.build            |   28 +
 src/backend/utils/mmgr/meson.build            |   10 +
 src/backend/utils/mmgr/proxy.c                |  217 ++
 src/backend/utils/resowner/meson.build        |    3 +
 src/backend/utils/sort/meson.build            |    7 +
 src/backend/utils/time/meson.build            |    4 +
 src/bin/initdb/meson.build                    |   24 +
 src/bin/meson.build                           |   20 +
 src/bin/pg_amcheck/meson.build                |   22 +
 src/bin/pg_archivecleanup/meson.build         |   14 +
 src/bin/pg_basebackup/meson.build             |   44 +
 src/bin/pg_checksums/meson.build              |   16 +
 src/bin/pg_config/meson.build                 |   14 +
 src/bin/pg_controldata/meson.build            |   14 +
 src/bin/pg_ctl/meson.build                    |   17 +
 src/bin/pg_dump/meson.build                   |   69 +
 src/bin/pg_resetwal/meson.build               |   15 +
 src/bin/pg_rewind/meson.build                 |   34 +
 src/bin/pg_test_fsync/meson.build             |   14 +
 src/bin/pg_test_timing/meson.build            |   14 +
 src/bin/pg_upgrade/meson.build                |   26 +
 src/bin/pg_verifybackup/meson.build           |   25 +
 src/bin/pg_waldump/meson.build                |   23 +
 src/bin/pgbench/meson.build                   |   38 +
 src/bin/pgevent/meson.build                   |    1 +
 src/bin/psql/meson.build                      |   46 +
 src/bin/scripts/meson.build                   |   46 +
 src/common/meson.build                        |  140 ++
 src/fe_utils/meson.build                      |   27 +
 src/include/catalog/meson.build               |  113 +
 src/include/meson.build                       |   50 +
 src/include/parser/meson.build                |   10 +
 src/include/pch/c_pch.h                       |    1 +
 src/include/pch/postgres_pch.h                |    1 +
 src/include/pg_config_ext.h.meson             |    7 +
 src/include/storage/meson.build               |   15 +
 src/include/utils/meson.build                 |   22 +
 src/interfaces/libpq/meson.build              |   99 +
 src/meson.build                               |   10 +
 src/pl/meson.build                            |    4 +
 src/pl/plperl/meson.build                     |   81 +
 src/pl/plpgsql/meson.build                    |    1 +
 src/pl/plpgsql/src/meson.build                |   67 +
 src/pl/plpython/expected/meson.build          |   14 +
 src/pl/plpython/meson.build                   |  100 +
 src/pl/plpython/sql/meson.build               |   15 +
 src/port/meson.build                          |  146 ++
 src/test/authentication/meson.build           |    9 +
 src/test/isolation/meson.build                |   49 +
 src/test/kerberos/meson.build                 |   12 +
 src/test/ldap/meson.build                     |    9 +
 src/test/meson.build                          |   19 +
 src/test/modules/brin/meson.build             |   19 +
 src/test/modules/commit_ts/meson.build        |   20 +
 src/test/modules/delay_execution/meson.build  |   15 +
 src/test/modules/dummy_index_am/meson.build   |   20 +
 src/test/modules/dummy_seclabel/meson.build   |   20 +
 src/test/modules/libpq_pipeline/meson.build   |   21 +
 src/test/modules/meson.build                  |   25 +
 src/test/modules/plsample/meson.build         |   20 +
 src/test/modules/snapshot_too_old/meson.build |   11 +
 src/test/modules/spgist_name_ops/meson.build  |   20 +
 .../ssl_passphrase_callback/meson.build       |   45 +
 src/test/modules/test_bloomfilter/meson.build |   20 +
 src/test/modules/test_ddl_deparse/meson.build |   40 +
 src/test/modules/test_extensions/meson.build  |   38 +
 .../modules/test_ginpostinglist/meson.build   |   20 +
 src/test/modules/test_integerset/meson.build  |   20 +
 src/test/modules/test_misc/meson.build        |    8 +
 src/test/modules/test_parser/meson.build      |   20 +
 src/test/modules/test_pg_dump/meson.build     |   24 +
 src/test/modules/test_predtest/meson.build    |   20 +
 src/test/modules/test_rbtree/meson.build      |   20 +
 src/test/modules/test_regex/meson.build       |   21 +
 src/test/modules/test_rls_hooks/meson.build   |   19 +
 src/test/modules/test_shm_mq/meson.build      |   24 +
 src/test/modules/unsafe_tests/meson.build     |    9 +
 src/test/modules/worker_spi/meson.build       |   23 +
 src/test/recovery/meson.build                 |   33 +
 src/test/regress/meson.build                  |   57 +
 src/test/ssl/meson.build                      |   10 +
 src/test/subscription/meson.build             |   33 +
 src/timezone/meson.build                      |   50 +
 src/timezone/tznames/meson.build              |   20 +
 src/tools/find_meson                          |   20 +
 src/tools/irlink                              |   28 +
 src/tools/msvc/export2def.pl                  |   22 +
 src/tools/msvc/gendef2.pl                     |  177 ++
 src/tools/testwrap                            |   22 +
 199 files changed, 7430 insertions(+)
 create mode 100644 contrib/adminpack/meson.build
 create mode 100644 contrib/amcheck/meson.build
 create mode 100644 contrib/auth_delay/meson.build
 create mode 100644 contrib/auto_explain/meson.build
 create mode 100644 contrib/bloom/meson.build
 create mode 100644 contrib/bool_plperl/meson.build
 create mode 100644 contrib/btree_gin/meson.build
 create mode 100644 contrib/btree_gist/meson.build
 create mode 100644 contrib/citext/meson.build
 create mode 100644 contrib/cube/meson.build
 create mode 100644 contrib/dblink/meson.build
 create mode 100644 contrib/dict_int/meson.build
 create mode 100644 contrib/dict_xsyn/meson.build
 create mode 100644 contrib/earthdistance/meson.build
 create mode 100644 contrib/file_fdw/meson.build
 create mode 100644 contrib/fuzzystrmatch/meson.build
 create mode 100644 contrib/hstore/meson.build
 create mode 100644 contrib/hstore_plperl/meson.build
 create mode 100644 contrib/hstore_plpython/expected/meson.build
 create mode 100644 contrib/hstore_plpython/meson.build
 create mode 100644 contrib/hstore_plpython/sql/meson.build
 create mode 100644 contrib/jsonb_plperl/meson.build
 create mode 100644 contrib/jsonb_plpython/expected/meson.build
 create mode 100644 contrib/jsonb_plpython/meson.build
 create mode 100644 contrib/jsonb_plpython/sql/meson.build
 create mode 100644 contrib/meson.build
 create mode 100644 contrib/oid2name/meson.build
 create mode 100644 contrib/pageinspect/meson.build
 create mode 100644 contrib/pg_prewarm/meson.build
 create mode 100644 contrib/pg_stat_statements/meson.build
 create mode 100644 contrib/pg_trgm/meson.build
 create mode 100644 contrib/pg_visibility/meson.build
 create mode 100644 contrib/postgres_fdw/meson.build
 create mode 100644 contrib/spi/meson.build
 create mode 100644 contrib/test_decoding/meson.build
 create mode 100644 contrib/tsm_system_rows/meson.build
 create mode 100644 contrib/tsm_system_time/meson.build
 create mode 100644 contrib/unaccent/meson.build
 create mode 100644 contrib/vacuumlo/meson.build
 create mode 100644 contrib/xml2/meson.build
 create mode 100644 conversion_helpers.txt
 create mode 100644 meson.build
 create mode 100644 meson_options.txt
 create mode 100644 src/backend/access/brin/meson.build
 create mode 100644 src/backend/access/common/meson.build
 create mode 100644 src/backend/access/gin/meson.build
 create mode 100644 src/backend/access/gist/meson.build
 create mode 100644 src/backend/access/hash/meson.build
 create mode 100644 src/backend/access/heap/meson.build
 create mode 100644 src/backend/access/index/meson.build
 create mode 100644 src/backend/access/meson.build
 create mode 100644 src/backend/access/nbtree/meson.build
 create mode 100644 src/backend/access/rmgrdesc/meson.build
 create mode 100644 src/backend/access/spgist/meson.build
 create mode 100644 src/backend/access/table/meson.build
 create mode 100644 src/backend/access/tablesample/meson.build
 create mode 100644 src/backend/access/transam/meson.build
 create mode 100644 src/backend/bootstrap/meson.build
 create mode 100644 src/backend/catalog/meson.build
 create mode 100644 src/backend/commands/meson.build
 create mode 100644 src/backend/executor/meson.build
 create mode 100644 src/backend/foreign/meson.build
 create mode 100644 src/backend/jit/llvm/meson.build
 create mode 100644 src/backend/jit/meson.build
 create mode 100644 src/backend/lib/meson.build
 create mode 100644 src/backend/libpq/meson.build
 create mode 100644 src/backend/main/meson.build
 create mode 100644 src/backend/meson.build
 create mode 100644 src/backend/nodes/meson.build
 create mode 100644 src/backend/optimizer/geqo/meson.build
 create mode 100644 src/backend/optimizer/meson.build
 create mode 100644 src/backend/optimizer/path/meson.build
 create mode 100644 src/backend/optimizer/plan/meson.build
 create mode 100644 src/backend/optimizer/prep/meson.build
 create mode 100644 src/backend/optimizer/util/meson.build
 create mode 100644 src/backend/parser/meson.build
 create mode 100644 src/backend/partitioning/meson.build
 create mode 100644 src/backend/port/meson.build
 create mode 100644 src/backend/port/win32/meson.build
 create mode 100644 src/backend/postmaster/meson.build
 create mode 100644 src/backend/regex/meson.build
 create mode 100644 src/backend/replication/libpqwalreceiver/meson.build
 create mode 100644 src/backend/replication/logical/meson.build
 create mode 100644 src/backend/replication/meson.build
 create mode 100644 src/backend/replication/pgoutput/meson.build
 create mode 100644 src/backend/rewrite/meson.build
 create mode 100644 src/backend/snowball/meson.build
 create mode 100644 src/backend/statistics/meson.build
 create mode 100644 src/backend/storage/buffer/meson.build
 create mode 100644 src/backend/storage/file/meson.build
 create mode 100644 src/backend/storage/freespace/meson.build
 create mode 100644 src/backend/storage/ipc/meson.build
 create mode 100644 src/backend/storage/large_object/meson.build
 create mode 100644 src/backend/storage/lmgr/meson.build
 create mode 100644 src/backend/storage/meson.build
 create mode 100644 src/backend/storage/page/meson.build
 create mode 100644 src/backend/storage/smgr/meson.build
 create mode 100644 src/backend/storage/sync/meson.build
 create mode 100644 src/backend/tcop/meson.build
 create mode 100644 src/backend/tsearch/meson.build
 create mode 100644 src/backend/utils/activity/meson.build
 create mode 100644 src/backend/utils/adt/meson.build
 create mode 100644 src/backend/utils/cache/meson.build
 create mode 100644 src/backend/utils/error/meson.build
 create mode 100644 src/backend/utils/fmgr/meson.build
 create mode 100644 src/backend/utils/hash/meson.build
 create mode 100644 src/backend/utils/init/meson.build
 create mode 100644 src/backend/utils/mb/conversion_procs/meson.build
 create mode 100644 src/backend/utils/mb/meson.build
 create mode 100644 src/backend/utils/meson.build
 create mode 100644 src/backend/utils/misc/meson.build
 create mode 100644 src/backend/utils/mmgr/meson.build
 create mode 100644 src/backend/utils/mmgr/proxy.c
 create mode 100644 src/backend/utils/resowner/meson.build
 create mode 100644 src/backend/utils/sort/meson.build
 create mode 100644 src/backend/utils/time/meson.build
 create mode 100644 src/bin/initdb/meson.build
 create mode 100644 src/bin/meson.build
 create mode 100644 src/bin/pg_amcheck/meson.build
 create mode 100644 src/bin/pg_archivecleanup/meson.build
 create mode 100644 src/bin/pg_basebackup/meson.build
 create mode 100644 src/bin/pg_checksums/meson.build
 create mode 100644 src/bin/pg_config/meson.build
 create mode 100644 src/bin/pg_controldata/meson.build
 create mode 100644 src/bin/pg_ctl/meson.build
 create mode 100644 src/bin/pg_dump/meson.build
 create mode 100644 src/bin/pg_resetwal/meson.build
 create mode 100644 src/bin/pg_rewind/meson.build
 create mode 100644 src/bin/pg_test_fsync/meson.build
 create mode 100644 src/bin/pg_test_timing/meson.build
 create mode 100644 src/bin/pg_upgrade/meson.build
 create mode 100644 src/bin/pg_verifybackup/meson.build
 create mode 100644 src/bin/pg_waldump/meson.build
 create mode 100644 src/bin/pgbench/meson.build
 create mode 100644 src/bin/pgevent/meson.build
 create mode 100644 src/bin/psql/meson.build
 create mode 100644 src/bin/scripts/meson.build
 create mode 100644 src/common/meson.build
 create mode 100644 src/fe_utils/meson.build
 create mode 100644 src/include/catalog/meson.build
 create mode 100644 src/include/meson.build
 create mode 100644 src/include/parser/meson.build
 create mode 100644 src/include/pch/c_pch.h
 create mode 100644 src/include/pch/postgres_pch.h
 create mode 100644 src/include/pg_config_ext.h.meson
 create mode 100644 src/include/storage/meson.build
 create mode 100644 src/include/utils/meson.build
 create mode 100644 src/interfaces/libpq/meson.build
 create mode 100644 src/meson.build
 create mode 100644 src/pl/meson.build
 create mode 100644 src/pl/plperl/meson.build
 create mode 100644 src/pl/plpgsql/meson.build
 create mode 100644 src/pl/plpgsql/src/meson.build
 create mode 100644 src/pl/plpython/expected/meson.build
 create mode 100644 src/pl/plpython/meson.build
 create mode 100644 src/pl/plpython/sql/meson.build
 create mode 100644 src/port/meson.build
 create mode 100644 src/test/authentication/meson.build
 create mode 100644 src/test/isolation/meson.build
 create mode 100644 src/test/kerberos/meson.build
 create mode 100644 src/test/ldap/meson.build
 create mode 100644 src/test/meson.build
 create mode 100644 src/test/modules/brin/meson.build
 create mode 100644 src/test/modules/commit_ts/meson.build
 create mode 100644 src/test/modules/delay_execution/meson.build
 create mode 100644 src/test/modules/dummy_index_am/meson.build
 create mode 100644 src/test/modules/dummy_seclabel/meson.build
 create mode 100644 src/test/modules/libpq_pipeline/meson.build
 create mode 100644 src/test/modules/meson.build
 create mode 100644 src/test/modules/plsample/meson.build
 create mode 100644 src/test/modules/snapshot_too_old/meson.build
 create mode 100644 src/test/modules/spgist_name_ops/meson.build
 create mode 100644 src/test/modules/ssl_passphrase_callback/meson.build
 create mode 100644 src/test/modules/test_bloomfilter/meson.build
 create mode 100644 src/test/modules/test_ddl_deparse/meson.build
 create mode 100644 src/test/modules/test_extensions/meson.build
 create mode 100644 src/test/modules/test_ginpostinglist/meson.build
 create mode 100644 src/test/modules/test_integerset/meson.build
 create mode 100644 src/test/modules/test_misc/meson.build
 create mode 100644 src/test/modules/test_parser/meson.build
 create mode 100644 src/test/modules/test_pg_dump/meson.build
 create mode 100644 src/test/modules/test_predtest/meson.build
 create mode 100644 src/test/modules/test_rbtree/meson.build
 create mode 100644 src/test/modules/test_regex/meson.build
 create mode 100644 src/test/modules/test_rls_hooks/meson.build
 create mode 100644 src/test/modules/test_shm_mq/meson.build
 create mode 100644 src/test/modules/unsafe_tests/meson.build
 create mode 100644 src/test/modules/worker_spi/meson.build
 create mode 100644 src/test/recovery/meson.build
 create mode 100644 src/test/regress/meson.build
 create mode 100644 src/test/ssl/meson.build
 create mode 100644 src/test/subscription/meson.build
 create mode 100644 src/timezone/meson.build
 create mode 100644 src/timezone/tznames/meson.build
 create mode 100755 src/tools/find_meson
 create mode 100644 src/tools/irlink
 create mode 100644 src/tools/msvc/export2def.pl
 create mode 100644 src/tools/msvc/gendef2.pl
 create mode 100755 src/tools/testwrap

diff --git a/contrib/adminpack/meson.build b/contrib/adminpack/meson.build
new file mode 100644
index 00000000000..457a6089445
--- /dev/null
+++ b/contrib/adminpack/meson.build
@@ -0,0 +1,20 @@
+autoinc = shared_module('adminpack',
+  ['adminpack.c'],
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'adminpack.control',
+  'adminpack--1.0.sql',
+  'adminpack--1.0--1.1.sql',
+  'adminpack--1.1--2.0.sql',
+  'adminpack--2.0--2.1.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'adminpack',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': ['adminpack'],
+}
diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build
new file mode 100644
index 00000000000..7d6a7bc8385
--- /dev/null
+++ b/contrib/amcheck/meson.build
@@ -0,0 +1,35 @@
+amcheck = shared_module('amcheck', [
+    'verify_heapam.c',
+    'verify_nbtree.c',
+  ],
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'amcheck.control',
+  'amcheck--1.0.sql',
+  'amcheck--1.0--1.1.sql',
+  'amcheck--1.1--1.2.sql',
+  'amcheck--1.2--1.3.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'amcheck',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'check',
+    'check_btree',
+    'check_heap'
+  ],
+}
+
+tap_tests += {
+  'name': 'amcheck',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_verify_heapam.pl',
+  ],
+}
diff --git a/contrib/auth_delay/meson.build b/contrib/auth_delay/meson.build
new file mode 100644
index 00000000000..941bb6f39a4
--- /dev/null
+++ b/contrib/auth_delay/meson.build
@@ -0,0 +1,4 @@
+autoinc = shared_module('auth_delay',
+  ['auth_delay.c'],
+  kwargs: contrib_mod_args,
+)
diff --git a/contrib/auto_explain/meson.build b/contrib/auto_explain/meson.build
new file mode 100644
index 00000000000..321896efa2c
--- /dev/null
+++ b/contrib/auto_explain/meson.build
@@ -0,0 +1,13 @@
+auto_explain = shared_module('auto_explain',
+  files('auto_explain.c'),
+  kwargs: contrib_mod_args,
+)
+
+tap_tests += {
+  'name': 'auto_explain',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_auto_explain.pl',
+  ]
+}
diff --git a/contrib/bloom/meson.build b/contrib/bloom/meson.build
new file mode 100644
index 00000000000..5c5d33c7f7a
--- /dev/null
+++ b/contrib/bloom/meson.build
@@ -0,0 +1,38 @@
+bloom_sources = files(
+  'blcost.c',
+  'blinsert.c',
+  'blscan.c',
+  'blutils.c',
+  'blvacuum.c',
+  'blvalidate.c',
+)
+
+bloom = shared_module('bloom',
+  bloom_sources,
+  c_pch: '../../src/include/pch/c_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'bloom.control',
+  'bloom--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'bloom',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'bloom'
+  ],
+}
+
+tap_tests += {
+  'name': 'bloom',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_wal.pl',
+  ],
+}
diff --git a/contrib/bool_plperl/meson.build b/contrib/bool_plperl/meson.build
new file mode 100644
index 00000000000..e15dc5285eb
--- /dev/null
+++ b/contrib/bool_plperl/meson.build
@@ -0,0 +1,37 @@
+if not perl_dep.found()
+  subdir_done()
+endif
+
+bool_plperl_sources = files(
+  'bool_plperl.c',
+)
+
+bool_plperl = shared_module('bool_plperl',
+  bool_plperl_sources,
+  include_directories: [plperl_inc, include_directories('.')],
+  kwargs: pg_mod_args + {
+    'dependencies': [perl_dep, contrib_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'bool_plperl.control',
+  'bool_plperl--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+install_data(
+  'bool_plperlu.control',
+  'bool_plperlu--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'bool_plperl',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'bool_plperl',
+    'bool_plperlu',
+  ],
+}
diff --git a/contrib/btree_gin/meson.build b/contrib/btree_gin/meson.build
new file mode 100644
index 00000000000..d25ece7500e
--- /dev/null
+++ b/contrib/btree_gin/meson.build
@@ -0,0 +1,51 @@
+btree_gin = shared_module('btree_gin',
+  files('btree_gin.c'),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'btree_gin.control',
+  'btree_gin--1.0.sql',
+  'btree_gin--1.0--1.1.sql',
+  'btree_gin--1.1--1.2.sql',
+  'btree_gin--1.2--1.3.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'btree_gin',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'install_btree_gin',
+    'int2',
+    'int4',
+    'int8',
+    'float4',
+    'float8',
+    'money',
+    'oid',
+    'timestamp',
+    'timestamptz',
+    'time',
+    'timetz',
+    'date',
+    'interval',
+    'macaddr',
+    'macaddr8',
+    'inet',
+    'cidr',
+    'text',
+    'varchar',
+    'char',
+    'bytea',
+    'bit',
+    'varbit',
+    'numeric',
+    'enum',
+    'uuid',
+    'name',
+    'bool',
+    'bpchar',
+  ],
+}
diff --git a/contrib/btree_gist/meson.build b/contrib/btree_gist/meson.build
new file mode 100644
index 00000000000..8ee0faea401
--- /dev/null
+++ b/contrib/btree_gist/meson.build
@@ -0,0 +1,79 @@
+btree_gist_sources = files(
+  'btree_bit.c',
+  'btree_bytea.c',
+  'btree_cash.c',
+  'btree_date.c',
+  'btree_enum.c',
+  'btree_float4.c',
+  'btree_float8.c',
+  'btree_gist.c',
+  'btree_inet.c',
+  'btree_int2.c',
+  'btree_int4.c',
+  'btree_int8.c',
+  'btree_interval.c',
+  'btree_macaddr.c',
+  'btree_macaddr8.c',
+  'btree_numeric.c',
+  'btree_oid.c',
+  'btree_text.c',
+  'btree_time.c',
+  'btree_ts.c',
+  'btree_utils_num.c',
+  'btree_utils_var.c',
+  'btree_uuid.c',
+)
+
+btree_gist = shared_module('btree_gist',
+  btree_gist_sources,
+  c_pch: '../../src/include/pch/c_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'btree_gist.control',
+  'btree_gist--1.0--1.1.sql',
+  'btree_gist--1.1--1.2.sql',
+  'btree_gist--1.2.sql',
+  'btree_gist--1.2--1.3.sql',
+  'btree_gist--1.3--1.4.sql',
+  'btree_gist--1.4--1.5.sql',
+  'btree_gist--1.5--1.6.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'btree_gist',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'init',
+    'int2',
+    'int4',
+    'int8',
+    'float4',
+    'float8',
+    'cash',
+    'oid',
+    'timestamp',
+    'timestamptz',
+    'time',
+    'timetz',
+    'date',
+    'interval',
+    'macaddr',
+    'macaddr8',
+    'inet',
+    'cidr',
+    'text',
+    'varchar',
+    'char',
+    'bytea',
+    'bit',
+    'varbit',
+    'numeric',
+    'uuid',
+    'not_equal',
+    'enum',
+  ],
+}
diff --git a/contrib/citext/meson.build b/contrib/citext/meson.build
new file mode 100644
index 00000000000..f2e9ff2117d
--- /dev/null
+++ b/contrib/citext/meson.build
@@ -0,0 +1,29 @@
+citext_sources = files(
+  'citext.c',
+)
+
+citext = shared_module('citext',
+  citext_sources,
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'citext.control',
+  'citext--1.0--1.1.sql',
+  'citext--1.1--1.2.sql',
+  'citext--1.2--1.3.sql',
+  'citext--1.3--1.4.sql',
+  'citext--1.4.sql',
+  'citext--1.4--1.5.sql',
+  'citext--1.5--1.6.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'citext',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'citext'
+  ],
+}
diff --git a/contrib/cube/meson.build b/contrib/cube/meson.build
new file mode 100644
index 00000000000..49276aed644
--- /dev/null
+++ b/contrib/cube/meson.build
@@ -0,0 +1,42 @@
+cube_sources = files(
+  'cube.c',
+)
+
+# cubescan is compiled as part of cubeparse
+cubescan = custom_target('cubescan',
+  input: ['cubescan.l'],
+  output: ['cubescan.c'],
+  command: [flex, '-CFe', '-p', '-p', '-o', '@OUTPUT@', '@INPUT@'])
+
+cube_sources += custom_target('cubeparse',
+  input: 'cubeparse.y',
+  output: 'cubeparse.c',
+  depends: cubescan,
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
+
+cube = shared_module('cube',
+  cube_sources,
+  include_directories: include_directories('.'),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'cube.control',
+  'cube--1.0--1.1.sql',
+  'cube--1.1--1.2.sql',
+  'cube--1.2.sql',
+  'cube--1.2--1.3.sql',
+  'cube--1.3--1.4.sql',
+  'cube--1.4--1.5.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'cube',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'cube',
+    'cube_sci',
+  ],
+}
diff --git a/contrib/dblink/meson.build b/contrib/dblink/meson.build
new file mode 100644
index 00000000000..7ac253700c9
--- /dev/null
+++ b/contrib/dblink/meson.build
@@ -0,0 +1,29 @@
+dblink_sources = files(
+  'dblink.c',
+)
+
+dblink = shared_module('dblink',
+  dblink_sources,
+  kwargs: contrib_mod_args + {
+      'dependencies': pg_mod_args['dependencies'] + [libpq],
+  },
+)
+
+install_data(
+  'dblink.control',
+  'dblink--1.0--1.1.sql',
+  'dblink--1.1--1.2.sql',
+  'dblink--1.2.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'dblink',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'paths',
+    'dblink'
+  ],
+  'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'],
+}
diff --git a/contrib/dict_int/meson.build b/contrib/dict_int/meson.build
new file mode 100644
index 00000000000..7c23b275c5a
--- /dev/null
+++ b/contrib/dict_int/meson.build
@@ -0,0 +1,19 @@
+dict_int = shared_module('dict_int',
+  files('dict_int.c'),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'dict_int.control',
+  'dict_int--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'dict_int',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'dict_int'
+  ],
+}
diff --git a/contrib/dict_xsyn/meson.build b/contrib/dict_xsyn/meson.build
new file mode 100644
index 00000000000..7cbabba02f1
--- /dev/null
+++ b/contrib/dict_xsyn/meson.build
@@ -0,0 +1,26 @@
+dict_xsyn = shared_module('dict_xsyn',
+  files('dict_xsyn.c'),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'dict_xsyn.control',
+  'dict_xsyn--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+install_data(
+  'xsyn_sample.rules',
+  kwargs: contrib_data_args + {
+    'install_dir': get_option('datadir') / 'tsearch_data'
+  }
+)
+
+regress_tests += {
+  'name': 'dict_xsyn',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'dict_xsyn'
+  ],
+}
diff --git a/contrib/earthdistance/meson.build b/contrib/earthdistance/meson.build
new file mode 100644
index 00000000000..d56abf4f260
--- /dev/null
+++ b/contrib/earthdistance/meson.build
@@ -0,0 +1,20 @@
+earthdistance = shared_module('earthdistance',
+  files('earthdistance.c'),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'earthdistance.control',
+  'earthdistance--1.0--1.1.sql',
+  'earthdistance--1.1.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'earthdistance',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'earthdistance'
+  ],
+}
diff --git a/contrib/file_fdw/meson.build b/contrib/file_fdw/meson.build
new file mode 100644
index 00000000000..0cd3348dfd0
--- /dev/null
+++ b/contrib/file_fdw/meson.build
@@ -0,0 +1,19 @@
+file_fdw = shared_module('file_fdw',
+  files('file_fdw.c'),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'file_fdw.control',
+  'file_fdw--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'file_fdw',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'file_fdw'
+  ],
+}
diff --git a/contrib/fuzzystrmatch/meson.build b/contrib/fuzzystrmatch/meson.build
new file mode 100644
index 00000000000..d1e75479668
--- /dev/null
+++ b/contrib/fuzzystrmatch/meson.build
@@ -0,0 +1,23 @@
+fuzzystrmatch = shared_module('fuzzystrmatch',
+  files(
+    'fuzzystrmatch.c',
+    'dmetaphone.c'
+  ),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'fuzzystrmatch.control',
+  'fuzzystrmatch--1.0--1.1.sql',
+  'fuzzystrmatch--1.1.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'fuzzystrmatch',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'fuzzystrmatch'
+  ],
+}
diff --git a/contrib/hstore/meson.build b/contrib/hstore/meson.build
new file mode 100644
index 00000000000..661e61f9692
--- /dev/null
+++ b/contrib/hstore/meson.build
@@ -0,0 +1,36 @@
+# .. so that includes of hstore/hstore.h work
+hstore_inc = include_directories('.', '../')
+
+hstore = shared_module('hstore',
+  files(
+    'hstore_compat.c',
+    'hstore_gin.c',
+    'hstore_gist.c',
+    'hstore_io.c',
+    'hstore_op.c',
+    'hstore_subs.c',
+  ),
+  c_pch: '../../src/include/pch/c_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'hstore.control',
+  'hstore--1.1--1.2.sql',
+  'hstore--1.3--1.4.sql',
+  'hstore--1.4.sql',
+  'hstore--1.4--1.5.sql',
+  'hstore--1.5--1.6.sql',
+  'hstore--1.6--1.7.sql',
+  'hstore--1.7--1.8.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'hstore',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'hstore'
+  ],
+}
diff --git a/contrib/hstore_plperl/meson.build b/contrib/hstore_plperl/meson.build
new file mode 100644
index 00000000000..48231cb1c9e
--- /dev/null
+++ b/contrib/hstore_plperl/meson.build
@@ -0,0 +1,38 @@
+if not perl_dep.found()
+  subdir_done()
+endif
+
+hstore_plperl_sources = files(
+  'hstore_plperl.c',
+)
+
+hstore_plperl = shared_module('hstore_plperl',
+  hstore_plperl_sources,
+  include_directories: [plperl_inc, hstore_inc],
+  kwargs: pg_mod_args + {
+    'dependencies': [perl_dep, contrib_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'hstore_plperl.control',
+  'hstore_plperl--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+install_data(
+  'hstore_plperlu.control',
+  'hstore_plperlu--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'hstore_plperl',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'hstore_plperl',
+    'hstore_plperlu',
+    'create_transform',
+  ],
+}
diff --git a/contrib/hstore_plpython/expected/meson.build b/contrib/hstore_plpython/expected/meson.build
new file mode 100644
index 00000000000..5a33c3752ef
--- /dev/null
+++ b/contrib/hstore_plpython/expected/meson.build
@@ -0,0 +1,15 @@
+foreach r2 : hstore_plpython_regress
+  # string.replace is only in meson 0.58
+  r3 = 'plpython3' + r2.split('plpython')[1]
+
+  s2 = '@0@.out'.format(r2)
+  s3 = '@0@.out'.format(r3)
+  hstore_plpython3_deps += custom_target(s3,
+    input: '@0@.out'.format(r2),
+    output: '@0@.out'.format(r3),
+    capture: true,
+    command: plpython_regress_cmd,
+    build_by_default: false,
+    install: false,
+  )
+endforeach
diff --git a/contrib/hstore_plpython/meson.build b/contrib/hstore_plpython/meson.build
new file mode 100644
index 00000000000..3c47a71e430
--- /dev/null
+++ b/contrib/hstore_plpython/meson.build
@@ -0,0 +1,44 @@
+if not python3.found()
+  subdir_done()
+endif
+
+hstore_plpython_sources = files(
+  'hstore_plpython.c',
+)
+
+hstore_plpython = shared_module('hstore_plpython3',
+  hstore_plpython_sources,
+  include_directories: [plpython_inc, hstore_inc, ],
+  kwargs: pg_mod_args + {
+    'c_args': ['-DPLPYTHON_LIBNAME="plpython3"'] + contrib_mod_args['c_args'],
+    'dependencies': [python3, contrib_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'hstore_plpythonu.control',
+  'hstore_plpython2u.control',
+  'hstore_plpython3u.control',
+  'hstore_plpythonu--1.0.sql',
+  'hstore_plpython2u--1.0.sql',
+  'hstore_plpython3u--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+hstore_plpython_regress = ['hstore_plpython']
+
+hstore_plpython3_regress = []
+hstore_plpython3_deps = []
+
+# FIXME: this is an abysmal hack
+subdir('sql')
+subdir('expected')
+
+regress_tests += {
+  'name': 'hstore_plpython',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': hstore_plpython3_regress,
+  'deps': hstore_plpython3_deps,
+  'regress_args': ['--inputdir', meson.current_build_dir(), '--load-extension=hstore'],
+}
diff --git a/contrib/hstore_plpython/sql/meson.build b/contrib/hstore_plpython/sql/meson.build
new file mode 100644
index 00000000000..612980fd37c
--- /dev/null
+++ b/contrib/hstore_plpython/sql/meson.build
@@ -0,0 +1,17 @@
+# Convert plpython2 regression tests to plpython3 ones
+foreach r2 : hstore_plpython_regress
+  # string.replace is only in meson 0.58
+  r3 = 'plpython3' + r2.split('plpython')[1]
+  hstore_plpython3_regress += r3
+
+  s2 = '@0@.sql'.format(r2)
+  s3 = '@0@.sql'.format(r3)
+  hstore_plpython3_deps += custom_target(s3,
+    input: '@0@.sql'.format(r2),
+    output: '@0@.sql'.format(r3),
+    capture: true,
+    command: plpython_regress_cmd,
+    build_by_default: false,
+    install: false,
+  )
+endforeach
diff --git a/contrib/jsonb_plperl/meson.build b/contrib/jsonb_plperl/meson.build
new file mode 100644
index 00000000000..c34090e5f5c
--- /dev/null
+++ b/contrib/jsonb_plperl/meson.build
@@ -0,0 +1,37 @@
+if not perl_dep.found()
+  subdir_done()
+endif
+
+jsonb_plperl_sources = files(
+  'jsonb_plperl.c',
+)
+
+jsonb_plperl = shared_module('jsonb_plperl',
+  jsonb_plperl_sources,
+  include_directories: [plperl_inc],
+  kwargs: pg_mod_args + {
+    'dependencies': [perl_dep, contrib_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'jsonb_plperl.control',
+  'jsonb_plperl--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+install_data(
+  'jsonb_plperlu.control',
+  'jsonb_plperlu--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'jsonb_plperl',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'jsonb_plperl',
+    'jsonb_plperlu',
+  ],
+}
diff --git a/contrib/jsonb_plpython/expected/meson.build b/contrib/jsonb_plpython/expected/meson.build
new file mode 100644
index 00000000000..3840bdd92e5
--- /dev/null
+++ b/contrib/jsonb_plpython/expected/meson.build
@@ -0,0 +1,15 @@
+foreach r2 : jsonb_plpython_regress
+  # string.replace is only in meson 0.58
+  r3 = 'plpython3' + r2.split('plpython')[1]
+
+  s2 = '@0@.out'.format(r2)
+  s3 = '@0@.out'.format(r3)
+  jsonb_plpython3_deps += custom_target(s3,
+    input: '@0@.out'.format(r2),
+    output: '@0@.out'.format(r3),
+    capture: true,
+    command: plpython_regress_cmd,
+    build_by_default: false,
+    install: false,
+  )
+endforeach
diff --git a/contrib/jsonb_plpython/meson.build b/contrib/jsonb_plpython/meson.build
new file mode 100644
index 00000000000..21abebf41b7
--- /dev/null
+++ b/contrib/jsonb_plpython/meson.build
@@ -0,0 +1,44 @@
+if not python3.found()
+  subdir_done()
+endif
+
+jsonb_plpython_sources = files(
+  'jsonb_plpython.c',
+)
+
+jsonb_plpython = shared_module('jsonb_plpython3',
+  jsonb_plpython_sources,
+  include_directories: [plpython_inc],
+  kwargs: pg_mod_args + {
+    'c_args': ['-DPLPYTHON_LIBNAME="plpython3"'] + contrib_mod_args['c_args'],
+    'dependencies': [python3, contrib_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'jsonb_plpythonu.control',
+  'jsonb_plpython2u.control',
+  'jsonb_plpython3u.control',
+  'jsonb_plpythonu--1.0.sql',
+  'jsonb_plpython2u--1.0.sql',
+  'jsonb_plpython3u--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+jsonb_plpython_regress = ['jsonb_plpython']
+
+jsonb_plpython3_regress = []
+jsonb_plpython3_deps = []
+
+# FIXME: this is an abysmal hack
+subdir('sql')
+subdir('expected')
+
+regress_tests += {
+  'name': 'jsonb_plpython',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': jsonb_plpython3_regress,
+  'deps': jsonb_plpython3_deps,
+  'regress_args': ['--inputdir', meson.current_build_dir()],
+}
diff --git a/contrib/jsonb_plpython/sql/meson.build b/contrib/jsonb_plpython/sql/meson.build
new file mode 100644
index 00000000000..4b29029192a
--- /dev/null
+++ b/contrib/jsonb_plpython/sql/meson.build
@@ -0,0 +1,17 @@
+# Convert plpython2 regression tests to plpython3 ones
+foreach r2 : jsonb_plpython_regress
+  # string.replace is only in meson 0.58
+  r3 = 'plpython3' + r2.split('plpython')[1]
+  jsonb_plpython3_regress += r3
+
+  s2 = '@0@.sql'.format(r2)
+  s3 = '@0@.sql'.format(r3)
+  jsonb_plpython3_deps += custom_target(s3,
+    input: '@0@.sql'.format(r2),
+    output: '@0@.sql'.format(r3),
+    capture: true,
+    command: plpython_regress_cmd,
+    build_by_default: false,
+    install: false,
+  )
+endforeach
diff --git a/contrib/meson.build b/contrib/meson.build
new file mode 100644
index 00000000000..0d5f7315ebb
--- /dev/null
+++ b/contrib/meson.build
@@ -0,0 +1,63 @@
+contrib_mod_args = pg_mod_args
+
+contrib_data_dir = get_option('datadir') / 'extension'
+contrib_data_args = {
+  'install_dir': contrib_data_dir
+}
+
+subdir('adminpack')
+subdir('amcheck')
+subdir('auth_delay')
+subdir('auto_explain')
+subdir('bloom')
+subdir('bool_plperl')
+subdir('btree_gin')
+subdir('btree_gist')
+subdir('citext')
+subdir('cube')
+subdir('dblink')
+subdir('dict_int')
+subdir('dict_xsyn')
+subdir('earthdistance')
+subdir('file_fdw')
+subdir('fuzzystrmatch')
+subdir('hstore')
+subdir('hstore_plperl')
+subdir('hstore_plpython')
+# TODO: intagg
+# TODO: intarray
+# TODO: isn
+subdir('jsonb_plperl')
+subdir('jsonb_plpython')
+# TODO: lo
+# TODO: ltree
+# TODO: ltree_plpython
+subdir('oid2name')
+# TODO: old_snapshot
+subdir('pageinspect')
+# TODO: passwordcheck
+# TODO: pg_buffercache
+# TODO: pgcrypto
+# TODO: pg_freespacemap
+subdir('pg_prewarm')
+# TODO: pgrowlocks
+subdir('pg_stat_statements')
+# TODO: pgstattuple
+# TODO: pg_surgery
+subdir('pg_trgm')
+subdir('pg_visibility')
+subdir('postgres_fdw')
+# TODO: seg
+# TODO: sepgsql
+subdir('spi')
+# TODO: sslinfo
+# TODO: start-scripts
+# TODO: tablefunc
+# TODO: tcn
+subdir('test_decoding')
+subdir('tsm_system_rows')
+subdir('tsm_system_time')
+subdir('unaccent')
+# TODO: uuid-ossp
+subdir('vacuumlo')
+subdir('xml2')
diff --git a/contrib/oid2name/meson.build b/contrib/oid2name/meson.build
new file mode 100644
index 00000000000..bee34d2137c
--- /dev/null
+++ b/contrib/oid2name/meson.build
@@ -0,0 +1,14 @@
+executable('oid2name',
+  ['oid2name.c'],
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name' : 'oid2name',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests' :[
+    't/001_basic.pl',
+  ]
+}
diff --git a/contrib/pageinspect/meson.build b/contrib/pageinspect/meson.build
new file mode 100644
index 00000000000..4bd5b1784e0
--- /dev/null
+++ b/contrib/pageinspect/meson.build
@@ -0,0 +1,45 @@
+pageinspect = shared_module('pageinspect',
+  files(
+    'brinfuncs.c',
+    'btreefuncs.c',
+    'fsmfuncs.c',
+    'ginfuncs.c',
+    'gistfuncs.c',
+    'hashfuncs.c',
+    'heapfuncs.c',
+    'rawpage.c',
+  ),
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'pageinspect--1.0--1.1.sql',
+  'pageinspect--1.1--1.2.sql',
+  'pageinspect--1.2--1.3.sql',
+  'pageinspect--1.3--1.4.sql',
+  'pageinspect--1.4--1.5.sql',
+  'pageinspect--1.5--1.6.sql',
+  'pageinspect--1.5.sql',
+  'pageinspect--1.6--1.7.sql',
+  'pageinspect--1.7--1.8.sql',
+  'pageinspect--1.8--1.9.sql',
+  'pageinspect--1.9--1.10.sql',
+  'pageinspect.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'pageinspect',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'page',
+    'btree',
+    'brin',
+    'gin',
+    'gist',
+    'hash',
+    'checksum',
+    'oldextversions',
+  ],
+}
diff --git a/contrib/pg_prewarm/meson.build b/contrib/pg_prewarm/meson.build
new file mode 100644
index 00000000000..c93ccc2db6d
--- /dev/null
+++ b/contrib/pg_prewarm/meson.build
@@ -0,0 +1,16 @@
+pg_prewarm = shared_module('pg_prewarm',
+  files(
+    'autoprewarm.c',
+    'pg_prewarm.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'pg_prewarm--1.0--1.1.sql',
+  'pg_prewarm--1.1--1.2.sql',
+  'pg_prewarm--1.1.sql',
+  'pg_prewarm.control',
+  kwargs: contrib_data_args,
+)
diff --git a/contrib/pg_stat_statements/meson.build b/contrib/pg_stat_statements/meson.build
new file mode 100644
index 00000000000..6ed70ac0f18
--- /dev/null
+++ b/contrib/pg_stat_statements/meson.build
@@ -0,0 +1,31 @@
+pg_stat_statements = shared_module('pg_stat_statements',
+  files('pg_stat_statements.c'),
+  kwargs: contrib_mod_args + {
+      'dependencies': contrib_mod_args['dependencies'],
+  },
+)
+
+install_data(
+  'pg_stat_statements.control',
+  'pg_stat_statements--1.4.sql',
+  'pg_stat_statements--1.8--1.9.sql',
+  'pg_stat_statements--1.7--1.8.sql',
+  'pg_stat_statements--1.6--1.7.sql',
+  'pg_stat_statements--1.5--1.6.sql',
+  'pg_stat_statements--1.4--1.5.sql',
+  'pg_stat_statements--1.3--1.4.sql',
+  'pg_stat_statements--1.2--1.3.sql',
+  'pg_stat_statements--1.1--1.2.sql',
+  'pg_stat_statements--1.0--1.1.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'pg_stat_statements',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'pg_stat_statements'
+  ],
+  'regress_args': ['--temp-config', files('pg_stat_statements.conf')],
+}
diff --git a/contrib/pg_trgm/meson.build b/contrib/pg_trgm/meson.build
new file mode 100644
index 00000000000..0a56926ad6b
--- /dev/null
+++ b/contrib/pg_trgm/meson.build
@@ -0,0 +1,33 @@
+pg_trgm = shared_module('pg_trgm',
+  files(
+    'trgm_gin.c',
+    'trgm_gist.c',
+    'trgm_op.c',
+    'trgm_regexp.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'pg_trgm--1.0--1.1.sql',
+  'pg_trgm--1.1--1.2.sql',
+  'pg_trgm--1.2--1.3.sql',
+  'pg_trgm--1.3--1.4.sql',
+  'pg_trgm--1.3.sql',
+  'pg_trgm--1.4--1.5.sql',
+  'pg_trgm--1.5--1.6.sql',
+  'pg_trgm.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'pg_trgm',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'pg_trgm',
+    'pg_word_trgm',
+    'pg_strict_word_trgm',
+  ],
+}
diff --git a/contrib/pg_visibility/meson.build b/contrib/pg_visibility/meson.build
new file mode 100644
index 00000000000..68a7e1cf28c
--- /dev/null
+++ b/contrib/pg_visibility/meson.build
@@ -0,0 +1,25 @@
+pg_visibility = shared_module('pg_visibility',
+  files(
+    'pg_visibility.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'pg_visibility--1.0--1.1.sql',
+  'pg_visibility--1.1.sql',
+  'pg_visibility--1.1--1.2.sql',
+  'pg_visibility.control',
+  kwargs: contrib_data_args,
+)
+
+
+regress_tests += {
+  'name': 'pg_visibility',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'pg_visibility'
+  ],
+}
diff --git a/contrib/postgres_fdw/meson.build b/contrib/postgres_fdw/meson.build
new file mode 100644
index 00000000000..507d01448b1
--- /dev/null
+++ b/contrib/postgres_fdw/meson.build
@@ -0,0 +1,31 @@
+postgres_fdw_sources = files(
+  'connection.c',
+  'deparse.c',
+  'option.c',
+  'postgres_fdw.c',
+  'shippable.c',
+)
+
+postgres_fdw = shared_module('postgres_fdw',
+  postgres_fdw_sources,
+  kwargs: contrib_mod_args + {
+      'dependencies': pg_mod_args['dependencies'] + [libpq],
+  },
+)
+
+install_data(
+  'postgres_fdw.control',
+  'postgres_fdw--1.0.sql',
+  'postgres_fdw--1.0--1.1.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'postgres_fdw',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'postgres_fdw'
+  ],
+  'regress_args': ['--dlpath', meson.build_root() / 'src/test/regress'],
+}
diff --git a/contrib/spi/meson.build b/contrib/spi/meson.build
new file mode 100644
index 00000000000..51bc96ea657
--- /dev/null
+++ b/contrib/spi/meson.build
@@ -0,0 +1,43 @@
+autoinc = shared_module('autoinc',
+  ['autoinc.c'],
+  kwargs: contrib_mod_args,
+)
+
+install_data('autoinc.control', 'autoinc--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+
+insert_username = shared_module('insert_username',
+  ['insert_username.c'],
+  kwargs: contrib_mod_args,
+)
+
+install_data('insert_username.control', 'insert_username--1.0.sql',
+  install_dir: get_option('datadir') / 'extension'
+)
+
+
+moddatetime = shared_module('moddatetime',
+  ['moddatetime.c'],
+  kwargs: contrib_mod_args,
+)
+
+install_data('moddatetime.control', 'moddatetime--1.0.sql',
+  install_dir: get_option('datadir') / 'extension'
+)
+
+# this is needed for the regression tests;
+# comment out if you want a quieter refint package for other uses
+refint_cflags = ['-DREFINT_VERBOSE']
+
+refint = shared_module('refint',
+  ['refint.c'],
+  kwargs: contrib_mod_args + {
+    'c_args': refint_cflags + contrib_mod_args['c_args'],
+  },
+)
+
+install_data('refint.control', 'refint--1.0.sql',
+  kwargs: contrib_data_args,
+)
diff --git a/contrib/test_decoding/meson.build b/contrib/test_decoding/meson.build
new file mode 100644
index 00000000000..d26b43cbe79
--- /dev/null
+++ b/contrib/test_decoding/meson.build
@@ -0,0 +1,69 @@
+test_decoding_sources = files(
+  'test_decoding.c',
+)
+
+test_decoding = shared_module('test_decoding',
+  test_decoding_sources,
+  kwargs: contrib_mod_args,
+)
+
+
+regress_tests += {
+  'name': 'test_decoding',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'ddl',
+    'xact',
+    'rewrite',
+    'toast',
+    'permissions',
+    'decoding_in_xact',
+    'decoding_into_rel',
+    'binary',
+    'prepared',
+    'replorigin',
+    'time',
+    'messages',
+    'spill',
+    'slot',
+    'truncate',
+    'stream',
+    'stats',
+    'twophase',
+    'twophase_stream',
+  ],
+  'regress_args': [
+    '--temp-config', files('logical.conf')
+  ]
+}
+
+isolation_tests += {
+  'name': 'test_decoding',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'specs': [
+    'mxact',
+    'delayed_startup',
+    'ondisk_startup',
+    'concurrent_ddl_dml',
+    'oldest_xmin',
+    'snapshot_transfer',
+    'subxact_without_top',
+    'concurrent_stream',
+    'twophase_snapshot',
+  ],
+  'regress_args': [
+    '--temp-config', files('logical.conf')
+  ]
+}
+
+
+tap_tests += {
+  'name': 'test_decoding',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_repl_stats.pl',
+  ],
+}
diff --git a/contrib/tsm_system_rows/meson.build b/contrib/tsm_system_rows/meson.build
new file mode 100644
index 00000000000..2c8f4487f8d
--- /dev/null
+++ b/contrib/tsm_system_rows/meson.build
@@ -0,0 +1,22 @@
+tsm_system_rows = shared_module('tsm_system_rows',
+  files(
+    'tsm_system_rows.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'tsm_system_rows--1.0.sql',
+  'tsm_system_rows.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'tsm_system_rows',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'tsm_system_rows',
+  ],
+}
diff --git a/contrib/tsm_system_time/meson.build b/contrib/tsm_system_time/meson.build
new file mode 100644
index 00000000000..df9c4aa4b51
--- /dev/null
+++ b/contrib/tsm_system_time/meson.build
@@ -0,0 +1,22 @@
+tsm_system_time = shared_module('tsm_system_time',
+  files(
+    'tsm_system_time.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'tsm_system_time--1.0.sql',
+  'tsm_system_time.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'tsm_system_time',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'tsm_system_time',
+  ],
+}
diff --git a/contrib/unaccent/meson.build b/contrib/unaccent/meson.build
new file mode 100644
index 00000000000..e77bf790d8c
--- /dev/null
+++ b/contrib/unaccent/meson.build
@@ -0,0 +1,30 @@
+unaccent = shared_module('unaccent',
+  files(
+    'unaccent.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args,
+)
+
+install_data(
+  'unaccent--1.0--1.1.sql',
+  'unaccent--1.1.sql',
+  'unaccent.control',
+  kwargs: contrib_data_args,
+)
+
+install_data(
+  'unaccent.rules',
+   install_dir: get_option('datadir') / 'tsearch_data'
+)
+
+# XXX: Implement downlo
+regress_tests += {
+  'name': 'unaccent',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'unaccent',
+  ],
+  'regress_args': ['--encoding=UTF8'],
+}
diff --git a/contrib/vacuumlo/meson.build b/contrib/vacuumlo/meson.build
new file mode 100644
index 00000000000..99e76daacf9
--- /dev/null
+++ b/contrib/vacuumlo/meson.build
@@ -0,0 +1,14 @@
+executable('vacuumlo',
+  ['vacuumlo.c'],
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name' : 'vacuumlo',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests' :[
+    't/001_basic.pl',
+  ]
+}
diff --git a/contrib/xml2/meson.build b/contrib/xml2/meson.build
new file mode 100644
index 00000000000..6f8a26e4f0a
--- /dev/null
+++ b/contrib/xml2/meson.build
@@ -0,0 +1,30 @@
+if not libxml.found()
+  subdir_done()
+endif
+
+xml2 = shared_module('pgxml',
+  files(
+    'xpath.c',
+    'xslt_proc.c',
+  ),
+  c_pch: '../../src/include/pch/postgres_pch.h',
+  kwargs: contrib_mod_args + {
+    'dependencies': [libxml, libxslt, contrib_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'xml2--1.0--1.1.sql',
+  'xml2--1.1.sql',
+  'xml2.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'xml2',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'xml2',
+  ],
+}
diff --git a/conversion_helpers.txt b/conversion_helpers.txt
new file mode 100644
index 00000000000..e5879b4fe77
--- /dev/null
+++ b/conversion_helpers.txt
@@ -0,0 +1,6 @@
+convert list of files to quoted-one-per-line:
+
+	?\b\(\(?:\w\|\d\|_\|-\)+\)\.o ?\(?:\\
+\)? →   '\1.c',
+
+
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000000..c9d123bdac3
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,1901 @@
+project('postgresql',
+  ['c'],
+  version: '15devel',
+  license: 'PostgreSQL',
+  meson_version: '>=0.54',
+  default_options: [
+    'warning_level=2',
+    'b_pie=true',
+    'b_pch=false',
+    'buildtype=release',
+  ]
+)
+
+
+
+###############################################################
+# Basic prep
+###############################################################
+
+fs = import('fs')
+
+thread_dep = dependency('threads')
+
+
+
+###############################################################
+# Version and other metadata
+###############################################################
+
+pg_version = meson.project_version()
+
+if pg_version.endswith('devel')
+  pg_version_arr = [pg_version.split('devel')[0], '0']
+elif pg_version.contains('beta')
+  pg_version_arr = pg_version.split('beta')
+elif pg_version.contains('rc')
+  pg_version_arr = pg_version.split('rc')
+else
+  pg_version_arr = pg_version.split('.')
+endif
+
+pg_version_major = pg_version_arr[0].to_int()
+pg_version_minor = pg_version_arr[1].to_int()
+
+cc = meson.get_compiler('c')
+
+cdata = configuration_data()
+
+
+cdata.set_quoted('PACKAGE_NAME', 'PostgreSQL')
+cdata.set_quoted('PACKAGE_BUGREPORT', 'pgsql-bugs@lists.postgresql.org')
+cdata.set_quoted('PACKAGE_URL', 'https://www.postgresql.org/')
+
+cdata.set_quoted('PG_VERSION', pg_version)
+cdata.set_quoted('PG_VERSION_STR', 'PostgreSQL @0@ on @1@, compiled by @2@-@3@'.format(
+  pg_version, target_machine.cpu_family(), cc.get_id(), cc.version()))
+cdata.set_quoted('PG_MAJORVERSION', pg_version_major.to_string())
+cdata.set('PG_MAJORVERSION_NUM', pg_version_major)
+cdata.set('PG_VERSION_NUM', (pg_version_major*10000)+pg_version_minor)
+cdata.set_quoted('CONFIGURE_ARGS', '')
+
+
+
+###############################################################
+# Search paths
+#
+# NB: Arguments added globally (via the below, or CFLAGS etc) are not taken
+# into account for configuration-time checks (so they are more
+# isolated). Flags that have to be taken into account for configure checks
+# have to be explicitly specified in configure tests.
+###############################################################
+
+g_inc = []
+g_c_args = []
+g_l_args = []
+
+if host_machine.system() == 'darwin'
+  # XXX, should this be required?
+  xcrun = find_program('xcrun', native: true, required: true)
+
+  sysroot = run_command(xcrun, '--show-sdk-path', check: true).stdout().strip()
+  message('sysroot is >@0@<'.format(sysroot))
+
+  g_c_args += ['-isysroot', sysroot]
+  g_l_args += ['-isysroot', sysroot]
+endif
+
+if host_machine.system() == 'linux' or host_machine.system() == 'cygwin'
+  g_c_args += '-D_GNU_SOURCE'
+endif
+
+g_c_inc = []
+
+g_c_inc += include_directories(get_option('extra_include_dirs'))
+g_c_lib = get_option('extra_lib_dirs')
+
+add_project_arguments(g_c_args, language: ['c', 'cpp'])
+add_project_link_arguments(g_l_args, language: ['c', 'cpp'])
+
+
+
+###############################################################
+# Program paths
+###############################################################
+
+# External programs
+perl = find_program(get_option('PERL'), required: true)
+flex = find_program(get_option('FLEX'), native: true)
+bison = find_program(get_option('BISON'), native: true, version: '>= 1.875')
+sed = find_program(get_option('SED'), 'sed', native: true)
+prove = find_program(get_option('PROVE'))
+tar = find_program(get_option('TAR'), native: true)
+gzip = find_program(get_option('GZIP'), native: true)
+touch = find_program('touch', native: true)
+
+# Internal programs
+find_meson = find_program('src/tools/find_meson', native: true)
+testwrap = find_program('src/tools/testwrap', native: true)
+
+bisonflags = []
+if bison.found()
+  bison_version_c = run_command(bison, '--version', check: true)
+  # bison version string helpfully is something like
+  # >>bison (GNU bison) 3.8.1<<
+  bison_version = bison_version_c.stdout().split(' ')[3].split('\n')[0]
+  if bison_version.version_compare('>=3.0')
+    bisonflags += ['-Wno-deprecated']
+  endif
+endif
+
+
+
+###############################################################
+# Path to meson (for tests etc)
+###############################################################
+
+# FIXME: this should really be part of meson, see
+# https://github.com/mesonbuild/meson/issues/8511
+meson_binpath_r = run_command(find_meson)
+
+if meson_binpath_r.returncode() != 0 or meson_binpath_r.stdout() == ''
+  error('huh, could not run find_meson.\nerrcode: @0@\nstdout: @1@\nstderr: @2@'.format(
+    meson_binpath_r.returncode(),
+    meson_binpath_r.stdout(),
+    meson_binpath_r.stderr()))
+endif
+
+meson_binpath_s = meson_binpath_r.stdout().split('\n')
+meson_binpath_len = meson_binpath_s.length()
+
+if meson_binpath_len < 1
+  error('unexpected introspect line @0@'.format(meson_binpath_r.stdout()))
+endif
+
+i = 0
+meson_binpath = ''
+meson_args = []
+foreach e : meson_binpath_s
+  if i == 0
+    meson_binpath = e
+  else
+    meson_args += e
+  endif
+  i += 1
+endforeach
+
+meson_bin = find_program(meson_binpath, native: true)
+
+
+
+###############################################################
+# Option Handling
+###############################################################
+
+cdata.set('USE_ASSERT_CHECKING', get_option('cassert'))
+
+cdata.set('BLCKSZ', 8192, description: '''
+ Size of a disk block --- this also limits the size of a tuple.  You
+ can set it bigger if you need bigger tuples (although TOAST should
+ reduce the need to have large tuples, since fields can be spread
+ across multiple tuples).
+
+ BLCKSZ must be a power of 2.  The maximum possible value of BLCKSZ
+ is currently 2^15 (32768).  This is determined by the 15-bit widths
+ of the lp_off and lp_len fields in ItemIdData (see
+ include/storage/itemid.h).
+
+ Changing BLCKSZ requires an initdb.
+''')
+
+cdata.set('XLOG_BLCKSZ', 8192)
+cdata.set('RELSEG_SIZE', 131072)
+cdata.set('DEF_PGPORT', 5432)
+cdata.set_quoted('DEF_PGPORT_STR', '5432')
+cdata.set_quoted('PG_KRB_SRVNAM', 'postgres')
+
+
+
+###############################################################
+# Library: GSSAPI
+###############################################################
+
+gssapiopt = get_option('gssapi')
+if not gssapiopt.disabled()
+  gssapi = dependency('krb5-gssapi', required: gssapiopt)
+
+  if gssapi.found() and \
+    cc.check_header('gssapi/gssapi.h', args: g_c_args, dependencies: gssapi, required: gssapiopt)
+
+    if not cc.has_function('gss_init_sec_context', args: g_c_args, dependencies: gssapi)
+      error('''could not find function 'gss_init_sec_context' required for GSSAPI''')
+    endif
+    cdata.set('ENABLE_GSS', 1)
+  endif
+
+else
+  gssapi = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: ldap
+###############################################################
+
+ldapopt = get_option('ldap')
+if not ldapopt.disabled()
+
+  if host_machine.system() == 'windows'
+    ldap = cc.find_library('wldap32')
+    ldap_r = ldap
+  else
+    ldap = dependency('ldap', required: false)
+
+    # Before 2.5 openldap didn't have a pkg-config file..
+    if ldap.found()
+      ldap_r = ldap
+    else
+      ldap = cc.find_library('ldap', required: ldapopt)
+      ldap_r = cc.find_library('ldap_r', required: ldapopt)
+
+      # Use ldap_r for FE if available, else assume ldap is thread-safe.
+      # On some platforms ldap_r fails to link without PTHREAD_LIBS.
+      if ldap.found() and not ldap_r.found()
+        ldap_r = ldap
+      endif
+    endif
+
+    if ldap.found() and cc.has_function('ldap_initialize', args: g_c_args, dependencies: [ldap, thread_dep])
+      cdata.set('HAVE_LDAP_INITIALIZE', 1)
+    endif
+  endif
+
+  if ldap.found()
+    cdata.set('USE_LDAP', 1)
+  endif
+
+else
+  ldap_r = ldap = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: LLVM
+###############################################################
+
+llvmopt = get_option('llvm')
+if not llvmopt.disabled()
+  llvm = dependency('llvm', version : '>=3.9', method: 'config-tool', required: llvmopt)
+
+  if llvm.found()
+
+    cdata.set('USE_LLVM', 1)
+
+    add_languages('cpp', required : true, native: false)
+    cpp = meson.get_compiler('cpp')
+
+    llvm_binpath = llvm.get_variable(configtool: 'bindir')
+
+    ccache = find_program('ccache', required: false)
+    clang = find_program(llvm_binpath / 'clang', required: true)
+    llvm_lto = find_program(llvm_binpath / 'llvm-lto', required: true)
+
+    # FIXME: the includes hardcoded here suck
+    llvm_irgen_args = [
+      '-c', '-o', '@OUTPUT@', '@INPUT@',
+      '-flto=thin', '-emit-llvm',
+      '-MD', '-MQ', '@OUTPUT@', '-MF', '@DEPFILE@',
+      '-I', '@SOURCE_ROOT@/src/include',
+      '-I', '@BUILD_ROOT@/src/include',
+      '-I', '@BUILD_ROOT@/src/backend/utils/misc',
+      '-I', '@CURRENT_SOURCE_DIR@',
+      '-O2',
+      '-Wno-ignored-attributes',
+      '-Wno-empty-body',
+    ]
+
+    if ccache.found()
+      llvm_irgen_command = ccache
+      llvm_irgen_args = [clang.path()] + llvm_irgen_args
+    else
+      llvm_irgen_command = clang
+    endif
+
+    llvm_irgen_kw = {
+      'command': [llvm_irgen_command] + llvm_irgen_args,
+      'depfile': '@BASENAME@.c.bc.d',
+    }
+
+    irlink = find_program('src/tools/irlink', native: true)
+
+    llvm_irlink_kw = {
+      'command':[
+        irlink,
+        '@SOURCE_ROOT@',
+        '@BUILD_ROOT@',
+        llvm_lto,
+        '-o', '@OUTPUT0@',
+        '@PRIVATE_DIR@',
+        '@INPUT@',
+      ],
+      'install': true,
+      'install_dir': get_option('libdir'),
+    }
+
+  endif
+else
+  llvm = dependency('', required: false)
+endif
+
+
+
+###############################################################
+# Library: icu
+###############################################################
+
+if not get_option('icu').disabled()
+  icu = dependency('icu-uc', required: get_option('icu').enabled())
+  icu_i18n = dependency('icu-i18n', required: get_option('icu').enabled())
+
+  if icu.found()
+    cdata.set('USE_ICU', 1)
+  endif
+
+else
+  icu = dependency('', required : false)
+  icu_i18n = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: libxml
+###############################################################
+
+libxmlopt = get_option('libxml')
+if not libxmlopt.disabled()
+  libxml = dependency('libxml-2.0', required: libxmlopt, version: '>= 2.6.23')
+
+  if libxml.found()
+    cdata.set('USE_LIBXML', 1)
+  endif
+else
+  libxml = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: libxslt
+###############################################################
+
+libxsltopt = get_option('libxslt')
+if not libxsltopt.disabled()
+  libxslt = dependency('libxslt', required: libxsltopt)
+
+  if libxslt.found()
+    cdata.set('USE_LIBXSLT', 1)
+  endif
+else
+  libxslt = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: lz4
+###############################################################
+
+lz4opt = get_option('lz4')
+if not lz4opt.disabled()
+  lz4 = dependency('liblz4', required: lz4opt)
+
+  if lz4.found()
+    cdata.set('USE_LZ4', 1)
+    cdata.set('HAVE_LIBLZ4', 1)
+  endif
+
+else
+  lz4 = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: Perl (for plperl)
+###############################################################
+
+perlopt = get_option('perl')
+perl_dep = dependency('', required: false)
+
+if perlopt.disabled()
+  perl_may_work = false
+else
+  perl_may_work = true
+
+  perl_conf_cmd = [perl, '-MConfig', '-e', 'print $Config{$ARGV[0]}']
+
+  # FIXME: include copy-edited comments from perl.m4
+
+  perlversion = run_command(perl_conf_cmd, 'api_versionstring', check: true).stdout()
+  archlibexp = run_command(perl_conf_cmd, 'archlibexp', check: true).stdout()
+  privlibexp = run_command(perl_conf_cmd, 'privlibexp', check: true).stdout()
+  useshrplib = run_command(perl_conf_cmd, 'useshrplib', check: true).stdout()
+  libperl = run_command(perl_conf_cmd, 'libperl', check: true).stdout()
+
+  perl_inc = include_directories('@0@/CORE'.format(archlibexp))
+
+  perl_ccflags = []
+
+  if useshrplib != 'true'
+    if perlopt.enabled()
+      warning('need a shared perl')
+      perl_may_work = false
+    else
+      error('need a shared perl')
+    endif
+  endif
+
+  message('perl libperl: @0@'.format(libperl))
+
+  if host_machine.system() == 'darwin'
+    perl_ccflags += ['-iwithsysroot', '@0@/CORE'.format(archlibexp)]
+  endif
+
+  # FIXME macOS may need sysroot muckery
+
+  # XXX: On my system the cc.find_library() is actually enough to get a working
+  # plperl. Would be nice to get rid of the nasty stuff below.
+  if perl_may_work and \
+      cc.has_header('perl.h', args: g_c_args + perl_ccflags,
+                    include_directories: perl_inc, required: perlopt)
+    foreach p : ['perl', 'libperl', libperl, libperl.strip('lib'), fs.stem(libperl), fs.stem(libperl).strip('lib')]
+      perl_dep_int = cc.find_library(p,
+        dirs: ['@0@/CORE'.format(archlibexp)],
+        required: false)
+      if perl_dep_int.found()
+        break
+      endif
+    endforeach
+
+    if not perl_dep_int.found()
+      perl_may_work = false
+    endif
+  else
+    perl_may_work = false
+  endif
+
+  if perl_may_work
+    perl_ccflags_r = run_command(perl_conf_cmd, 'ccflags', check: true).stdout()
+    message('CCFLAGS recommended by Perl: @0@'.format(perl_ccflags_r))
+
+    foreach flag : perl_ccflags_r.split(' ')
+      if flag.startswith('-D') and \
+        (not flag.startswith('-D_') or flag == '_USE_32BIT_TIME_T')
+        perl_ccflags += flag
+      endif
+    endforeach
+
+    if host_machine.system() == 'windows'
+      perl_ccflags += ['-DPLPERL_HAVE_UID_GID']
+    endif
+
+    message('CCFLAGS for embedding perl: @0@'.format(' '.join(perl_ccflags)))
+
+    # perl.m4 sayeth:
+    #
+    # We are after Embed's ldopts, but without the subset mentioned in
+    # Config's ccdlflags;
+    #
+    # FIXME: andres sayeth: But why?
+
+    ldopts = run_command(perl, '-MExtUtils::Embed', '-e', 'ldopts', check: true).stdout().strip()
+    ccdlflags = run_command(perl_conf_cmd, 'ccdlflags', check: true).stdout().strip()
+
+    ccdlflags_dict = {}
+
+    foreach ccdlflag : ccdlflags.split(' ')
+      ccdlflags_dict += {ccdlflag: 1}
+    endforeach
+
+    perl_ldopts = []
+    foreach ldopt : ldopts.split(' ')
+      if ldopt == ''
+        continue
+      elif ccdlflags_dict.has_key(ldopt)
+        continue
+      # strawberry perl unhelpfully has that in ldopts
+      elif ldopt == '-s'
+        continue
+      endif
+
+      perl_ldopts += ldopt.strip('"')
+    endforeach
+
+    # FIXME: check if windows handling is necessary
+
+    message('LDFLAGS for embedding perl: "@0@" (ccdlflags: "@1@", ldopts: "@2@")'.format(
+      ' '.join(perl_ldopts), ccdlflags, ldopts))
+
+    if perl_dep_int.found()
+      perl_dep = declare_dependency(
+        include_directories: perl_inc,
+        compile_args: perl_ccflags,
+        link_args: perl_ldopts,
+        version: perlversion,
+      )
+    endif
+  endif # perl_may_work
+
+  if perlopt.enabled() and not perl_may_work
+    error('could not find working perl')
+  endif
+endif
+
+
+
+###############################################################
+# Library: Python (for plpython)
+###############################################################
+
+pyopt = get_option('python')
+if not pyopt.disabled()
+  pm = import('python')
+  python3_inst = pm.find_installation(required: pyopt.enabled())
+  python3 = python3_inst.dependency(embed: true, required: pyopt.enabled())
+else
+  python3 = dependency('', required: false)
+endif
+
+
+
+###############################################################
+# Library: Readline
+#
+# FIXME: editline support
+###############################################################
+
+if not get_option('readline').disabled()
+  readline = dependency('readline', required: false)
+  if not readline.found()
+    readline = cc.find_library('readline',
+      required: get_option('readline').enabled())
+  endif
+
+  if readline.found()
+    cdata.set('HAVE_LIBREADLINE', 1)
+
+    if cc.has_header('readline/history.h', args: g_c_args, dependencies: [readline], required: false)
+      history_h = 'readline/history.h'
+      cdata.set('HAVE_READLINE_HISTORY_H', 1)
+      cdata.set('HAVE_READLINE_H', false)
+    elif cc.has_header('history.h', args: g_c_args, dependencies: [readline], required: false)
+      history_h = 'history.h'
+      cdata.set('HAVE_READLINE_HISTORY_H', false)
+      cdata.set('HAVE_HISTORY_H', 1)
+    else
+      error('''readline header not found
+If you have readline already installed, see see meson-log/meson-log.txt for details on the
+failure.  It is possible the compiler isn't looking in the proper directory.
+Use -Dreadline=false to disable readline support.''')
+    endif
+
+    if cc.has_header('readline/readline.h', args: g_c_args, dependencies: [readline], required: false)
+      readline_h = 'readline/readline.h'
+      cdata.set('HAVE_READLINE_READLINE_H', 1)
+    elif cc.has_header('readline.h', args: g_c_args, dependencies: [readline], required: false)
+      readline_h = 'readline.h'
+      cdata.set('HAVE_READLINE_H', 1)
+    else
+      error('''readline header not found
+If you have readline already installed, see see meson-log/meson-log.txt for details on the
+failure.  It is possible the compiler isn't looking in the proper directory.
+Use -Dreadline=false to disable readline support.''')
+    endif
+
+    check_funcs = [
+      'rl_completion_matches',
+      'rl_filename_completion_function',
+      'rl_reset_screen_size',
+      'append_history',
+      'history_truncate_file',
+    ]
+
+    foreach func : check_funcs
+      cdata.set('HAVE_'+func.to_upper(),
+        cc.has_function(func, args: g_c_args, dependencies: [readline]) ? 1 : false)
+    endforeach
+
+    check_vars = [
+      'rl_completion_append_character',
+      'rl_completion_suppress_quote',
+      'rl_filename_quote_characters',
+      'rl_filename_quoting_function',
+    ]
+
+    foreach var : check_vars
+      cdata.set('HAVE_'+var.to_upper(),
+        cc.has_header_symbol(readline_h, var, args: g_c_args, dependencies: [readline]) ? 1 : false)
+    endforeach
+  endif
+else
+  readline = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: SSL
+###############################################################
+
+if get_option('ssl') == 'openssl'
+
+  # Try to find openssl via pkg-config et al, if that doesn't work, look for
+  # the library names that we know about.
+
+  # via pkg-config et al
+  ssl = dependency('openssl', required: false)
+
+  # via library + headers
+  if not ssl.found()
+    ssl_lib = cc.find_library('ssl',
+      dirs: g_c_lib,
+      header_include_directories: g_c_inc,
+      has_headers: ['openssl/ssl.h', 'openssl/err.h'])
+    crypto_lib = cc.find_library('crypto',
+      dirs: g_c_lib,
+      header_include_directories: g_c_inc)
+    ssl_int = [ssl_lib, crypto_lib]
+
+    ssl = declare_dependency(dependencies: ssl_int,
+                             include_directories: g_c_inc)
+  else
+    cc.has_header('openssl/ssl.h', args: g_c_args, dependencies: ssl, required: true)
+    cc.has_header('openssl/err.h', args: g_c_args, dependencies: ssl, required: true)
+
+    ssl_int = [ssl]
+  endif
+
+  cdata.set_quoted('WITH_SSL', get_option('ssl'))
+
+  check_funcs = [
+    ['CRYPTO_new_ex_data', {'required': true}],
+    ['SSL_new', {'required': true}],
+
+    # Function introduced in OpenSSL 1.0.2.
+    ['X509_get_signature_nid'],
+
+    # Functions introduced in OpenSSL 1.1.0. We used to check for
+    # OPENSSL_VERSION_NUMBER, but that didn't work with 1.1.0, because LibreSSL
+    # defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
+    # doesn't have these OpenSSL 1.1.0 functions. So check for individual
+    # functions.
+    ['OPENSSL_init_ssl'],
+    ['BIO_get_data'],
+    ['BIO_meth_new'],
+    ['ASN1_STRING_get0_data'],
+    ['HMAC_CTX_new'],
+    ['HMAC_CTX_free'],
+
+    # OpenSSL versions before 1.1.0 required setting callback functions, for
+    # thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
+    # function was removed.
+    ['CRYPTO_lock'],
+  ]
+
+  foreach c : check_funcs
+    func = c.get(0)
+    val = cc.has_function(func, args: g_c_args, dependencies: ssl_int)
+    if not val and c.get(1, {}).get('required', false)
+      error('openssl function @0@ is required'.format(func))
+    endif
+    cdata.set('HAVE_'+func.to_upper(), val ? 1 : false)
+  endforeach
+
+  cdata.set('USE_OPENSSL', 1,
+            description: 'Define to 1 to build with OpenSSL support. (-Dssl=openssl)')
+
+  cdata.set('OPENSSL_API_COMPAT', 0x10001000,
+            description: 'Define to the OpenSSL API version in use. This avoids deprecation warnings from newer OpenSSL versions.')
+else
+  ssl = dependency('', required : false)
+endif
+
+
+
+###############################################################
+# Library: zlib
+###############################################################
+
+zlibopt = get_option('zlib')
+zlib = dependency('', required : false)
+if not zlibopt.disabled()
+  zlib_t = dependency('zlib', required: zlibopt)
+
+  if zlib_t.type_name() == 'internal'
+    # if fallback was used, we don't need to test if headers are present (they
+    # aren't built yet, so we can't test)
+    zlib = zlib_t
+  elif not zlib_t.found()
+    warning('did not find zlib')
+  elif not cc.has_header('zlib.h', args: g_c_args, dependencies: [zlib_t], required: zlibopt.enabled())
+    warning('zlib header not found')
+  elif not cc.has_type('z_streamp', args: g_c_args, dependencies: [zlib_t], prefix: '#include <zlib.h>')
+    if zlibopt.enabled()
+      error('zlib version is too old')
+    else
+      warning('zlib version is too old')
+    endif
+  else
+    zlib = zlib_t
+  endif
+
+  if zlib.found()
+    cdata.set('HAVE_LIBZ', 1)
+  endif
+endif
+
+
+
+###############################################################
+# Compiler tests
+###############################################################
+
+sizeof_long = cc.sizeof('long', args: g_c_args)
+if sizeof_long == 8
+  cdata.set('HAVE_LONG_INT_64', 1)
+  cdata.set('PG_INT64_TYPE', 'long int')
+  cdata.set_quoted('INT64_MODIFIER', 'l')
+elif sizeof_long == 4 and cc.sizeof('long long', args: g_c_args) == 8
+  cdata.set('HAVE_LONG_LONG_INT_64', 1)
+  cdata.set('PG_INT64_TYPE', 'long long int')
+  cdata.set_quoted('INT64_MODIFIER', 'll')
+elif
+  error('do not know how to get a 64bit int')
+endif
+
+
+cdata.set('MAXIMUM_ALIGNOF', 8)
+cdata.set('ALIGNOF_SHORT', cc.alignment('short', args: g_c_args))
+cdata.set('ALIGNOF_INT', cc.alignment('int', args: g_c_args))
+cdata.set('ALIGNOF_LONG', cc.alignment('long', args: g_c_args))
+cdata.set('ALIGNOF_DOUBLE', cc.alignment('double', args: g_c_args))
+cdata.set('SIZEOF_VOID_P', cc.sizeof('void *', args: g_c_args))
+
+# Check if the C compiler knows computed gotos (gcc extension, also
+# available in at least clang).  If so, define HAVE_COMPUTED_GOTO.
+#
+# Checking whether computed gotos are supported syntax-wise ought to
+# be enough, as the syntax is otherwise illegal.
+if cc.compiles('''
+    static inline int foo(void)
+    {
+      void *labeladdrs[] = {&&my_label};
+      goto *labeladdrs[0];
+      my_label:
+      return 1;
+    }''',
+    args: g_c_args)
+  cdata.set('HAVE_COMPUTED_GOTO', 1)
+endif
+
+
+# XXX: for now just assume that compiler knows __func__ - it's C99 after all.
+cdata.set('HAVE_FUNCNAME__FUNC', 1)
+
+# Check if the C compiler understands _Static_assert(),
+# and define HAVE__STATIC_ASSERT if so.
+#
+# We actually check the syntax ({ _Static_assert(...) }), because we need
+# gcc-style compound expressions to be able to wrap the thing into macros.
+if cc.compiles('''
+    int main(int arg, char **argv)
+    {
+        ({ _Static_assert(1, "foo"); })
+    }
+    ''',
+    args: g_c_args)
+  cdata.set('HAVE__STATIC_ASSERT', 1)
+endif
+
+# We use <stdbool.h> if we have it and it declares type bool as having
+# size 1.  Otherwise, c.h will fall back to declaring bool as unsigned char.
+if cc.has_type('_Bool', args: g_c_args) \
+  and cc.has_type('bool', prefix: '#include <stdbool.h>', args: g_c_args) \
+  and cc.sizeof('bool', prefix: '#include <stdbool.h>', args: g_c_args) == 1
+  cdata.set('HAVE__BOOL', 1)
+  cdata.set('PG_USE_STDBOOL', 1)
+endif
+
+
+printf_attributes = ['gnu_printf', '__syslog__', 'printf']
+testsrc = 'extern void pgac_write(int ignore, const char *fmt,...) __attribute__((format(@0@, 2,3)));'
+foreach a : printf_attributes
+  if cc.compiles(testsrc.format(a), args: g_c_args + ['-Werror'], name: 'format ' + a)
+    cdata.set('PG_PRINTF_ATTRIBUTE', a)
+    break
+  endif
+endforeach
+
+if cc.has_function_attribute('visibility:default') and \
+  cc.has_function_attribute('visibility:hidden')
+  cdata.set('HAVE_VISIBILITY_ATTRIBUTE', 1)
+endif
+
+
+if cc.has_function('__builtin_unreachable', args: g_c_args)
+  cdata.set('HAVE__BUILTIN_UNREACHABLE', 1)
+endif
+
+if cc.has_function('__builtin_constant_p', args: g_c_args)
+  cdata.set('HAVE__BUILTIN_CONSTANT_P', 1)
+
+  if host_machine.cpu_family() == 'ppc' or host_machine.cpu_family() == 'ppc64'
+    # Check if compiler accepts "i"(x) when __builtin_constant_p(x).
+    if cc.compiles('''
+      static inline int
+      addi(int ra, int si)
+      {
+          int res = 0;
+          if (__builtin_constant_p(si))
+              __asm__ __volatile__(
+                  " addi %0,%1,%2\n" : "=r"(res) : "b"(ra), "i"(si));
+          return res;
+      }
+      int test_adds(int x) { return addi(3, x) + addi(x, 5); }
+      ''',
+      args: g_c_args)
+      cdata.set('HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P', 1)
+    endif
+  endif
+endif
+
+
+
+# XXX: The configure.ac check for __cpuid() is broken, we don't copy that
+# here. To prevent problems due to two detection methods working, stop
+# checking after one.
+if cc.links('''
+    #include <cpuid.h>
+    int main(int arg, char **argv)
+    {
+        unsigned int exx[4] = {0, 0, 0, 0};
+        __get_cpuid(1, &exx[0], &exx[1], &exx[2], &exx[3]);
+    }
+    ''', name: '__get_cpuid',
+    args: g_c_args)
+  cdata.set('HAVE__GET_CPUID', 1)
+elif cc.links('''
+    #include <intrin.h>
+    int main(int arg, char **argv)
+    {
+        unsigned int exx[4] = {0, 0, 0, 0};
+        __cpuid(exx, 1);
+    }
+    ''', name: '__cpuid',
+    args: g_c_args)
+  cdata.set('HAVE__CPUID', 1)
+endif
+
+
+
+###############################################################
+# Compiler flags
+###############################################################
+
+common_functional_flags = [
+  # Disable strict-aliasing rules; needed for gcc 3.3+
+  '-fno-strict-aliasing',
+  # Disable optimizations that assume no overflow; needed for gcc 4.3+
+  '-fwrapv',
+  '-fexcess-precision=standard'
+]
+
+add_project_arguments(cc.get_supported_arguments(common_functional_flags), language: 'c')
+
+vectorize_cflags = cc.get_supported_arguments(['-ftree-vectorize'])
+unroll_loops_cflags = cc.get_supported_arguments(['-funroll-loops'])
+
+
+common_warning_flags = [
+  '-Wmissing-prototypes',
+  '-Wpointer-arith',
+  '-Werror=vla',
+  '-Wendif-labels',
+  '-Wmissing-format-attribute',
+  '-Wimplicit-fallthrough=3',
+  '-Wcast-function-type',
+  '-Wformat-security',
+]
+
+add_project_arguments(cc.get_supported_arguments(common_warning_flags), language: 'c')
+
+if llvm.found()
+  add_project_arguments(cpp.get_supported_arguments(common_warning_flags), language: 'cpp')
+endif
+
+# A few places with imported code get a pass on -Wdeclaration-after-statement, remember
+# the result for them
+if cc.has_argument('-Wdeclaration-after-statement')
+  add_project_arguments('-Wdeclaration-after-statement', language: 'c')
+  using_declaration_after_statement_warning = true
+else
+  using_declaration_after_statement_warning = false
+endif
+
+
+# We want to suppress a few unhelpful warnings - but gcc won't
+# complain about unrecognized -Wno-foo switches, so we have to test
+# for the positive form and if that works, add the negative form
+
+negative_warning_flags = [
+  'unused-command-line-argument',
+  'format-truncation',
+  'stringop-truncation',
+
+  # FIXME: from andres's local config
+  'clobbered',
+  'missing-field-initializers',
+  'sign-compare',
+  'unused-parameter',
+]
+
+foreach w : negative_warning_flags
+  if cc.has_argument('-W'+w)
+    add_project_arguments('-Wno-'+w, language: 'c')
+  endif
+
+  if llvm.found() and cpp.has_argument('-W'+w)
+    add_project_arguments('-Wno-'+w, language: 'cpp')
+  endif
+endforeach
+
+
+# From Project.pm
+if cc.get_id() == 'msvc'
+  add_project_arguments('/wd4018', '/wd4244', '/wd4273', '/wd4102', '/wd4090', '/wd4267',
+    language: 'c')
+  add_project_arguments('/DWIN32', '/DWINDOWS', '/D__WINDOWS__', '/D__WIN32__',
+    '/DWIN32_STACK_RLIMIT=4194304', '/D_CRT_SECURE_NO_DEPRECATE', '/D_CRT_NONSTDC_NO_DEPRECATE',
+        language: 'c')
+endif
+
+
+###############################################################
+# Atomics
+###############################################################
+
+cdata.set('HAVE_SPINLOCKS', 1)
+
+if get_option('atomics')
+  cdata.set('HAVE_ATOMICS', 1)
+
+  atomic_checks = [
+    {'name': 'HAVE_GCC__SYNC_CHAR_TAS',
+     'desc': '__sync_lock_test_and_set(char)',
+     'test': '''
+char lock = 0;
+__sync_lock_test_and_set(&lock, 1);
+__sync_lock_release(&lock);'''},
+
+    {'name': 'HAVE_GCC__SYNC_INT32_TAS',
+     'desc': '__sync_lock_test_and_set(int32)',
+     'test': '''
+int lock = 0;
+__sync_lock_test_and_set(&lock, 1);
+__sync_lock_release(&lock);'''},
+
+    {'name': 'HAVE_GCC__SYNC_INT32_CAS',
+     'desc': '__sync_val_compare_and_swap(int32)',
+     'test': '''
+int val = 0;
+__sync_val_compare_and_swap(&val, 0, 37);'''},
+
+# FIXME: int64 reference
+    {'name': 'HAVE_GCC__SYNC_INT64_CAS',
+     'desc': '__sync_val_compare_and_swap(int64)',
+     'test': '''
+long val = 0;
+__sync_val_compare_and_swap(&val, 0, 37);'''},
+
+    {'name': 'HAVE_GCC__ATOMIC_INT32_CAS',
+     'desc': ' __atomic_compare_exchange_n(int32)',
+     'test': '''
+int val = 0;
+int expect = 0;
+__atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
+
+# FIXME: int64 reference
+    {'name': 'HAVE_GCC__ATOMIC_INT64_CAS',
+     'desc': ' __atomic_compare_exchange_n(int64)',
+     'test': '''
+long val = 0;
+int expect = 0;
+__atomic_compare_exchange_n(&val, &expect, 37, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);'''},
+  ]
+
+  foreach check : atomic_checks
+    test = '''
+int main(void)
+{
+@0@
+}'''.format(check['test'])
+
+    cdata.set(check['name'],
+      cc.links(test, name: check['desc'], args: g_c_args))
+  endforeach
+
+endif
+
+
+
+###############################################################
+# Library / OS tests
+###############################################################
+
+header_checks = [
+  ['atomic.h'],
+  ['stdbool.h'],
+  ['copyfile.h'],
+  ['execinfo.h'],
+  ['getopt.h'],
+  ['ifaddrs.h'],
+  ['langinfo.h'],
+  ['mbarrier.h'],
+  ['poll.h'],
+  ['sys/epoll.h'],
+  ['sys/event.h'],
+  ['sys/ipc.h'],
+  ['sys/prctl.h'],
+  ['sys/procctl.h'],
+  ['sys/pstat.h'],
+  ['sys/resource.h'],
+  ['sys/select.h'],
+  ['sys/sem.h'],
+  ['sys/shm.h'],
+  ['sys/sockio.h'],
+  ['sys/tas.h'],
+  ['sys/uio.h'],
+  ['sys/un.h'],
+  ['termios.h'],
+  ['ucred.h'],
+  # FIXME: openbsd workaround
+  ['sys/ucred.h'],
+  ['wctype.h'],
+  ['netinet/tcp.h'],
+  ['net/if.h'],
+  ['crtdefs.h'],
+]
+
+foreach c : header_checks
+  varname = 'HAVE_'+c.get(0).underscorify().to_upper()
+
+  # Emulate autoconf behaviour of not-found->undef, found->1
+  found = cc.has_header(c.get(0), include_directories: g_inc, args: g_c_args)
+  cdata.set(varname, found ? 1 : false,
+            description: 'Define to 1 if you have the <@0@> header file.'.format(c))
+endforeach
+
+
+
+decl_checks = [
+  ['F_FULLFSYNC', 'fcntl.h'],
+  ['RTLD_GLOBAL', 'dlfcn.h'],
+  ['RTLD_NOW', 'dlfcn.h'],
+  ['fdatasync', 'unistd.h'],
+  ['posix_fadvise', 'fcntl.h'],
+  ['sigwait', 'signal.h'],
+  ['strlcat', 'string.h'],
+  ['strlcpy', 'string.h'],
+  ['strnlen', 'string.h'],
+  ['strsignal', 'string.h'],
+  ['strtoll', 'stdlib.h'], ['strtoull', 'stdlib.h'], # strto[u]ll may exist but not be declared
+]
+
+# Need to check for function declarations for these functions, because
+# checking for library symbols wouldn't handle deployment target
+# restrictions on macOS
+decl_checks += [
+  ['preadv', 'sys/uio.h'],
+  ['pwritev', 'sys/uio.h'],
+]
+
+foreach c : decl_checks
+  varname = 'HAVE_DECL_'+c.get(0).underscorify().to_upper()
+
+  found = cc.has_header_symbol(c.get(1), c.get(0), args: g_c_args, kwargs: c.get(2, {}))
+  cdata.set10(varname, found, description:
+'''Define to 1 if you have the declaration of `@0@\', and to 0 if you
+  don't.'''.format(c))
+endforeach
+
+
+
+# XXX: this is borked, HAVE_SYS_UCRED_H not defined
+if cc.has_type('struct cmsgcred',
+    include_directories: g_inc,
+    args: g_c_args + ['@0@'.format(cdata.get('HAVE_SYS_UCRED_H')) == 'false' ? '-DHAVE_SYS_UCRED_H' : ''],
+    prefix: '''
+#include <sys/socket.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif''')
+  cdata.set('HAVE_STRUCT_CMSGCRED', 1)
+else
+  cdata.set('HAVE_STRUCT_CMSGCRED', false)
+endif
+
+if cc.has_function('getopt', args: g_c_args) and \
+   cc.has_function('getopt_long', args: g_c_args) and \
+   cc.has_type('struct option', args: g_c_args, prefix: '#include <getopt.h>')
+  cdata.set('HAVE_GETOPT', 1)
+  cdata.set('HAVE_GETOPT_LONG', 1)
+  cdata.set('HAVE_STRUCT_OPTION', 1)
+else
+  warning('not yet implemented')
+endif
+
+
+foreach c : ['opterr', 'optreset']
+  varname = 'HAVE_INT_'+c.underscorify().to_upper()
+
+  if cc.links('''
+#include <unistd.h>
+int main(void)
+{
+    extern int @0@;
+    @0@ = 1;
+}
+'''.format(c), name: c, args: g_c_args)
+    cdata.set(varname, 1)
+  else
+    cdata.set(varname, false)
+  endif
+endforeach
+
+
+if cc.has_type('struct sockaddr_storage', args: g_c_args, prefix: '''
+#include <sys/types.h>
+#include <sys/socket.h>''')
+  cdata.set('HAVE_STRUCT_SOCKADDR_STORAGE', 1)
+endif
+
+if cc.has_member('struct sockaddr_storage', 'ss_family', args: g_c_args,
+  prefix: '''#include <sys/types.h>
+#include <sys/socket.h>''')
+  cdata.set('HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY', 1)
+endif
+
+if cc.has_member('struct sockaddr_storage', '__ss_family', args: g_c_args,
+  prefix: '''
+#include <sys/types.h>
+#include <sys/socket.h>''')
+  cdata.set('HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY', 1)
+endif
+
+if cc.has_type('struct sockaddr_un', args: g_c_args, prefix: '''
+#include <sys/types.h>
+#include <sys/un.h>''')
+  cdata.set('HAVE_STRUCT_SOCKADDR_UN', 1)
+endif
+
+if cc.has_type('struct addrinfo', args: g_c_args, prefix: '''
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+''')
+  cdata.set('HAVE_STRUCT_ADDRINFO', 1)
+endif
+
+if host_machine.system() == 'windows'
+  cdata.set('HAVE_STRUCT_SOCKADDR_STORAGE', 1)
+  cdata.set('HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY', 1)
+endif
+
+if cc.has_type('struct sockaddr_in6', args: g_c_args, prefix: '''
+#include <netinet/in.h>''')
+  cdata.set('HAVE_IPV6', 1)
+endif
+
+
+if cc.has_member('struct tm', 'tm_zone', args: g_c_args, prefix: '''
+#include <sys/types.h>
+#include <time.h>
+''')
+  cdata.set('HAVE_STRUCT_TM_TM_ZONE', 1)
+endif
+
+if cc.compiles('''
+#include <time.h>
+extern int foo(void);
+int foo(void)
+{
+    return timezone / 60;
+}
+''', name: 'Check if the global variable `timezone\' exists', args: g_c_args,)
+  cdata.set('HAVE_INT_TIMEZONE', 1)
+else
+  cdata.set('HAVE_INT_TIMEZONE', false)
+endif
+
+# FIXME: sys/ipc.h, sys/sem.h includes were conditional
+if cc.has_type('union semun', args: g_c_args, prefix: '''
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+''')
+  cdata.set('HAVE_UNION_SEMUN', 1)
+endif
+
+if cc.compiles('''
+#include <string.h>
+int main(void)
+{
+  char buf[100];
+  switch (strerror_r(1, buf, sizeof(buf)))
+  { case 0: break; default: break; }
+}''', args: g_c_args)
+  cdata.set('STRERROR_R_INT', 1)
+else
+  cdata.set('STRERROR_R_INT', false)
+endif
+
+# FIXME
+cdata.set('pg_restrict', '__restrict')
+
+# FIXME
+if host_machine.system() == 'windows'
+  cdata.set('ACCEPT_TYPE_ARG1', 'unsigned int')
+  cdata.set('ACCEPT_TYPE_ARG2', 'struct sockaddr *')
+  cdata.set('ACCEPT_TYPE_ARG3', 'int')
+  cdata.set('ACCEPT_TYPE_RETURN', 'unsigned int PASCAL')
+else
+  cdata.set('ACCEPT_TYPE_ARG1', 'int')
+  cdata.set('ACCEPT_TYPE_ARG2', 'struct sockaddr')
+  cdata.set('ACCEPT_TYPE_ARG3', 'socklen_t')
+  cdata.set('ACCEPT_TYPE_RETURN', 'int')
+endif
+
+cdata.set('HAVE_STRUCT_ADDRINFO', 1)
+
+
+cdata.set('MEMSET_LOOP_LIMIT', 1024)
+
+
+if cc.links('''
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+
+int main(void)
+{
+    PS_STRINGS->ps_nargvstr = 1;
+    PS_STRINGS->ps_argvstr = "foo";
+}
+''',
+  name: 'PS_STRINGS', args: g_c_args)
+  cdata.set('HAVE_PS_STRINGS', 1)
+else
+  cdata.set('HAVE_PS_STRINGS', false)
+endif
+
+
+# FIXME: this clearly needs to be cleaned up.
+if cc.get_id() != 'msvc'
+  # FIXME: Need to actually test
+  add_project_arguments('-msse4.2', language: 'c')
+  cdata.set('USE_SSE42_CRC32C', false)
+  cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
+else
+  cdata.set('USE_SSE42_CRC32C', false)
+  cdata.set('USE_SSE42_CRC32C_WITH_RUNTIME_CHECK', 1)
+endif
+
+
+m_dep = cc.find_library('m', required : false)
+
+# Most libraries are included only if they demonstrably provide a function we
+# need, but libm is an exception: always include it, because there are too
+# many compilers that play cute optimization games that will break probes for
+# standard functions such as pow().
+os_deps = [m_dep]
+
+rt_dep = cc.find_library('rt', required : false)
+
+dl_dep = cc.find_library('dl', required : false)
+
+util_dep = cc.find_library('util', required : false)
+posix4_dep = cc.find_library('posix4', required : false)
+
+getopt_dep = cc.find_library('getopt', required : false)
+gnugetopt_dep = cc.find_library('gnugetopt', required : false)
+
+execinfo_dep = cc.find_library('execinfo', required : false)
+
+func_checks = [
+  ['_configthreadlocale'],
+  ['backtrace_symbols', {'dependencies': [execinfo_dep]}],
+  ['clock_gettime', {'dependencies': [rt_dep, posix4_dep]}],
+  ['copyfile'],
+  ['dlopen', {'dependencies': [dl_dep]}],
+  ['explicit_bzero'],
+  ['fdatasync', {'dependencies': [rt_dep, posix4_dep]}],
+  ['fls'],
+  ['getaddrinfo'],
+  ['gethostbyname_r', {'dependencies': [thread_dep]}],
+  ['getifaddrs'],
+  ['getopt', {'dependencies': [getopt_dep, gnugetopt_dep]}],
+  ['getopt_long',{'dependencies': [getopt_dep, gnugetopt_dep]}],
+  ['getpeereid'],
+  ['getpeerucred'],
+  ['getpwuid_r', {'dependencies': [thread_dep]}],
+  ['getrlimit'],
+  ['getrusage'],
+  ['gettimeofday'], # XXX: This seems to be in the autoconf case
+  ['inet_aton'],
+  ['kqueue'],
+  ['link'],
+  ['mbstowcs_l'],
+  ['memset_s'],
+  ['mkdtemp'],
+  ['poll'],
+  ['posix_fadvise'],
+  ['posix_fallocate'],
+  ['ppoll'],
+  ['pread'],
+  ['pstat'],
+  ['pthread_is_threaded_np'],
+  ['pwrite'],
+  ['random'],
+  ['readlink'],
+  ['readv'],
+  ['setenv'], # FIXME: windows handling
+  ['setproctitle', {'dependencies': [util_dep]}],
+  ['setproctitle_fast'],
+  ['setsid'],
+  ['shm_open', {'dependencies': [rt_dep]}],
+  ['shm_unlink', {'dependencies': [rt_dep]}],
+  ['srandom'],
+  ['strchrnul'],
+  ['strerror_r', {'dependencies': [thread_dep]}],
+  ['strlcat'],
+  ['strlcpy'],
+  ['strnlen'],
+  ['strsignal'],
+  ['strtof'], # strsignal is checked separately
+  ['strtoll'], ['__strtoll'], ['strtoq'],
+  ['strtoull'], ['__strtoull'], ['strtouq'],
+  ['symlink'],
+  ['sync_file_range'],
+  ['syncfs'],
+  ['unsetenv'],
+  ['uselocale'],
+  ['wcstombs_l'],
+  ['writev'],
+]
+
+foreach c : func_checks
+  func = c.get(0)
+  kwargs = c.get(1, {})
+  deps = kwargs.get('dependencies', [])
+
+  varname = 'HAVE_'+func.underscorify().to_upper()
+
+  found = cc.has_function(func, args: g_c_args,
+                          kwargs: kwargs + {'dependencies': []})
+
+  if not found
+    foreach dep : deps
+      if not dep.found()
+        continue
+      endif
+      found = cc.has_function(func, args: g_c_args,
+                              kwargs: kwargs + {'dependencies': [dep]})
+      if found
+        os_deps += dep
+        break
+      endif
+    endforeach
+  endif
+
+  # Emulate autoconf behaviour of not-found->undef, found->1
+  cdata.set(varname, found  ? 1 : false,
+            description: 'Define to 1 if you have the `@0@\' function.'.format(c))
+endforeach
+
+
+
+
+
+if host_machine.system() == 'linux' or host_machine.system() == 'freebsd'
+  dlsuffix = '.so'
+elif host_machine.system() == 'darwin'
+  dlsuffix = '.dylib'
+elif host_machine.system() == 'windows'
+  dlsuffix = '.dll'
+else
+  error('not yet')
+endif
+
+cdata.set_quoted('DLSUFFIX', dlsuffix)
+
+if host_machine.system() == 'windows'
+   cdata.set('USE_WIN32_SEMAPHORES', 1)
+   cdata.set('USE_WIN32_SHARED_MEMORY', 1)
+elif host_machine.system() == 'darwin'
+   cdata.set('USE_SYSV_SEMAPHORES', 1)
+   cdata.set('USE_SYSV_SHARED_MEMORY', 1)
+else
+   cdata.set('USE_UNNAMED_POSIX_SEMAPHORES', 1)
+   cdata.set('USE_SYSV_SHARED_MEMORY', 1)
+endif
+
+
+if host_machine.system() == 'windows'
+  cdata.set('HAVE_IPV6', 1)
+  cdata.set('HAVE_SYMLINK', 1)
+  cdata.set('WIN32_STACK_RLIMIT', 4194304)
+  cdata.set('HAVE__CONFIGTHREADLOCALE', 1)
+endif
+
+if cc.get_id() == 'msvc'
+  add_project_link_arguments(
+    '/fixed:no',
+    '/dynamicbase',
+    '/nxcompat',
+    language : ['c', 'cpp'],
+  )
+endif
+
+if host_machine.system() == 'windows'
+  os_deps += cc.find_library('ws2_32', required: true)
+endif
+
+
+###############################################################
+# Threading
+###############################################################
+
+# Probably not worth implementing other cases anymore
+cdata.set('ENABLE_THREAD_SAFETY', 1)
+
+if thread_dep.found()
+  if cc.has_function('pthread_is_threaded_np', args: g_c_args, dependencies: [thread_dep])
+    cdata.set('HAVE_PTHREAD_IS_THREADED_NP', 1)
+  endif
+  if cc.has_function('pthread_barrier_wait', args: g_c_args, dependencies: [thread_dep])
+    cdata.set('HAVE_PTHREAD_BARRIER_WAIT', 1)
+  endif
+endif
+
+
+###############################################################
+# Build
+###############################################################
+
+# Collect a number of lists of things while recursing through the source
+# tree. Later steps then can use those.
+
+test_deps = []
+backend_targets = []
+
+
+# List of tap tests we later generate test() invocations for. The main
+# reason for doing it that way instead of having test() invocations
+# everywhere is that they end up being too large. A second benefit is
+# that it'd make it easier to generate data for another runner.
+tap_tests = []
+isolation_tests = []
+regress_tests = []
+
+
+# Default options for targets
+
+default_target_args = {
+  'implicit_include_directories': false,
+  'install': true,
+}
+
+default_lib_args = default_target_args + {
+  'name_prefix': 'lib',
+}
+
+internal_lib_args = default_lib_args + {
+  'build_by_default': false,
+  'install': false,
+}
+
+default_mod_args = default_lib_args + {
+  'name_prefix': '',
+}
+
+default_bin_args = default_target_args + {
+}
+
+
+# First visit src/include - all targets creating headers are defined
+# within. That makes it easy to add the necessary dependencies for the
+# subsequent build steps.
+
+generated_headers = []
+generated_backend_headers = []
+
+postgres_inc = [include_directories('src/include')]
+
+if host_machine.system() == 'windows'
+  postgres_inc += include_directories('src/include/port/win32')
+
+  if cc.get_id() == 'msvc'
+    postgres_inc += include_directories('src/include/port/win32_msvc')
+  endif
+endif
+
+subdir('src/include')
+
+
+# Then through src/port and src/common, as most other things depend on them
+
+frontend_port_code = declare_dependency(
+  compile_args: ['-DFRONTEND'],
+  include_directories: [postgres_inc],
+  sources: [errcodes],
+  dependencies: os_deps,
+)
+
+backend_port_code = declare_dependency(
+  compile_args: ['-DBUILDING_DLL'],
+  include_directories: [postgres_inc],
+  sources: [errcodes],
+  dependencies: os_deps,
+)
+
+subdir('src/port')
+
+frontend_common_code = declare_dependency(
+  compile_args: ['-DFRONTEND'],
+  include_directories: [postgres_inc],
+  sources: generated_headers,
+  dependencies: os_deps,
+)
+
+backend_common_code = declare_dependency(
+  compile_args: ['-DBUILDING_DLL'],
+  include_directories: [postgres_inc],
+  sources: generated_headers,
+)
+
+subdir('src/common')
+
+frontend_shlib_code = declare_dependency(
+  compile_args: ['-DFRONTEND'],
+  include_directories: [postgres_inc],
+  link_with: [pgport_shlib, common_shlib],
+  sources: generated_headers,
+  dependencies: os_deps,
+)
+
+subdir('src/interfaces/libpq')
+subdir('src/fe_utils')
+
+frontend_code = declare_dependency(
+  compile_args: ['-DFRONTEND'],
+  include_directories: [postgres_inc],
+  link_with: [pgport_static, common_static, fe_utils],
+  sources: generated_headers,
+  dependencies: os_deps,
+)
+
+backend_code = declare_dependency(
+  compile_args: ['-DBUILDING_DLL'],
+  include_directories: [postgres_inc],
+  link_with: [],
+  sources: generated_headers + generated_backend_headers,
+  dependencies: [os_deps, ssl, lz4, icu, icu_i18n, ldap, gssapi, libxml],
+)
+
+# Note there's intentionally no dependency on pgport/common here - we want the
+# symbols from the main binary for extension modules, rather than the
+# extension linking separately to pgport/common.
+backend_mod_code = declare_dependency(
+  compile_args: [],
+  include_directories: [postgres_inc],
+  link_with: [],
+  sources: generated_headers + generated_backend_headers,
+  dependencies: [os_deps, ssl, lz4, icu, icu_i18n, ldap, gssapi, libxml],
+)
+
+# Then through the main sources. That way contrib can have dependencies on
+# main sources. Note that this explicitly doesn't enter src/test, right now a
+# few regression tests depend on contrib files.
+
+subdir('src')
+
+subdir('contrib')
+
+subdir('src/test')
+
+
+###############################################################
+# Test prep
+###############################################################
+
+# The determination of where a DESTDIR install points to is ugly, it's somewhat hard
+# to combine two absolute paths portably...
+
+prefix = get_option('prefix')
+
+test_prefix = prefix
+
+if fs.is_absolute(get_option('prefix'))
+  if host_machine.system() == 'windows'
+    if prefix.split(':\\').length() == 1
+        # just a drive
+        test_prefix = ''
+    else
+        test_prefix = prefix.split(':\\')[1]
+    endif
+  else
+    test_prefix = prefix.substring(1)
+  endif
+endif
+
+# DESTDIR for the installation used to run tests in
+test_install_destdir = meson.build_root() / 'tmp_install/'
+# DESTDIR + prefix appropriately munged
+test_install_location = test_install_destdir / test_prefix
+
+
+test('tmp_install',
+    meson_bin, args: meson_args + ['install', '--quiet', '--only-changed', '--no-rebuild'],
+    env: {'DESTDIR':test_install_destdir},
+    priority: 100,
+    is_parallel: false,
+    suite: ['setup'])
+
+test_result_dir = meson.build_root() / 'testrun'
+
+
+# XXX: pg_regress doesn't assign unique ports on windows. To avoid the
+# inevitable conflicts from running tests in parallel, hackishly assign
+# different ports for different tests.
+
+testport=40000
+
+test_env = environment()
+
+if host_machine.system() == 'darwin'
+  library_path_var = 'DYLD_LIBRARY_PATH'
+elif host_machine.system() == 'aix'
+  library_path_var = 'LIBPATH'
+else
+  library_path_var = 'LD_LIBRARY_PATH'
+endif
+
+test_env.prepend('PATH', test_install_location / get_option('bindir'))
+test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
+test_env.set('PG_REGRESS', meson.build_root() / 'src/test/regress/pg_regress')
+test_env.set('REGRESS_SHLIB', regress_module.full_path())
+
+
+###############################################################
+# Test Generation
+###############################################################
+
+# Define all 'pg_regress' style tests
+foreach t : regress_tests
+  test_command = [
+    pg_regress,
+    '--temp-instance', test_result_dir / t['name'] / 'pg_regress' / 'tmp_check',
+    '--inputdir', t['sd'],
+    '--outputdir', test_result_dir / t['name'] / 'pg_regress',
+    '--bindir', '',
+    '--dlpath', t['bd'],
+    '--max-concurrent-tests=20',
+    '--port=@0@'.format(testport),
+  ]
+
+  if t.has_key('regress_args')
+     test_command += t['regress_args']
+  endif
+
+  if t.has_key('schedule')
+     test_command += ['--schedule', t['schedule'],]
+  else
+     test_command += t['sql']
+  endif
+
+  test_kwargs = {
+    'suite': ['pg_regress', t['name']],
+    'priority': 10,
+    'timeout': 300,
+    'depends': test_deps + t.get('deps', []),
+    'env': test_env,
+    'workdir': t['sd'],
+    'args': [
+      meson.build_root(),
+      t['bd'],
+      t['name'],
+      'pg_regress',
+      test_command,
+    ]
+  }
+
+  # Allow test definition to override arguments
+  if t.has_key('test_kwargs')
+     test_kwargs += t['test_kwargs']
+  endif
+
+  test(t['name'] / 'pg_regress',
+    testwrap,
+    kwargs: test_kwargs,
+  )
+
+  testport = testport + 1
+endforeach
+
+
+# Define all 'isolationtester' style tests
+foreach t : isolation_tests
+  test_command = [
+    pg_isolation_regress,
+    '--temp-instance', test_result_dir / t['name'] / 'isolation' / 'tmp_check',
+    '--inputdir', t['sd'],
+    '--outputdir', test_result_dir / t['name'] / 'isolation',
+    '--bindir', '',
+    '--dlpath', t['bd'],
+    '--max-concurrent-tests=20',
+    '--port=@0@'.format(testport),
+  ]
+
+  if t.has_key('regress_args')
+     test_command += t['regress_args']
+  endif
+
+  if t.has_key('schedule')
+     test_command += ['--schedule', t['schedule'],]
+  else
+     test_command += t['specs']
+  endif
+
+  test_kwargs = {
+    'suite': ['isolation', t['name']],
+    'priority': 20,
+    'timeout': 300,
+    'depends': test_deps + t.get('deps', []),
+    'workdir': t['sd'],
+    'env': test_env,
+    'args': [
+      meson.build_root(),
+      t['bd'],
+      t['name'],
+      'isolation',
+      test_command,
+    ]
+  }
+
+  # Allow test definition to override arguments
+  if t.has_key('test_kwargs')
+     test_kwargs += t['test_kwargs']
+  endif
+
+  test(t['name'] / 'isolation',
+    testwrap,
+    kwargs: test_kwargs,
+  )
+
+  testport = testport + 1
+endforeach
+
+
+# Define all 'tap' style tests
+# FIXME: dependencies for each test
+foreach t : tap_tests
+  env = test_env
+
+  foreach name, value : t.get('env', {})
+    if name == 'PATH'
+      # FIXME: manually setting PATH again, because repeated prepend didn't work
+      # before meson 0.58.
+      env.prepend('PATH', value, test_install_location / get_option('bindir'))
+    else
+      env.set(name, value)
+    endif
+  endforeach
+
+  foreach onetap : t['tests']
+    test(t['name'] / onetap,
+      testwrap,
+      workdir: t['sd'],
+      args: [
+        meson.build_root(),
+        t['bd'],
+        t['name'],
+        onetap,
+        'perl',
+        '-I', meson.source_root() / 'src/test/perl',
+        '-I', t['sd'],
+        t['sd'] / onetap
+      ],
+      protocol: 'tap',
+      suite: ['tap', t['name']],
+      env: env,
+      depends: test_deps + t.get('deps', []),
+      timeout: 300,
+      )
+  endforeach
+endforeach
+
+
+
+###############################################################
+# Pseudo targets
+###############################################################
+
+alias_target('backend', backend_targets)
+
+
+
+###############################################################
+# The End, The End, My Friend
+###############################################################
+
+if meson.version().version_compare('>=0.57')
+
+  summary({
+    'Data Block Size' : cdata.get('BLCKSZ'),
+    'WAL Block Size' : cdata.get('XLOG_BLCKSZ')
+    }, section: 'Data Layout'
+  )
+
+  summary(
+    {
+      'host system' : '@0@ @1@'.format(host_machine.system(), host_machine.cpu_family()),
+      'build system' : '@0@ @1@'.format(build_machine.system(), build_machine.cpu_family()),
+    },
+    section: 'System'
+  )
+
+  summary(
+    {
+      'linker': '@0@'.format(cc.get_linker_id()),
+      'C compiler': '@0@ @1@'.format(cc.get_id(), cc.version()),
+    },
+    section: 'Compiler'
+  )
+
+  if llvm.found()
+    summary(
+      {
+        'C++ compiler': '@0@ @1@'.format(cpp.get_id(), cpp.version())
+      },
+      section: 'Compiler')
+  endif
+
+  summary(
+    {
+      'bison' : '@0@ @1@'.format(bison.full_path(), bison_version),
+    },
+    section: 'Programs'
+  )
+
+  summary(
+    {
+      'GSS': gssapi,
+      'LDAP': ldap,
+      'LLVM': llvm,
+      'icu': icu,
+      'libxml': libxml,
+      'libxslt': libxslt,
+      'lz4': lz4,
+      'perl': perl_dep,
+      'python3': python3,
+      'readline': readline,
+      'ssl': ssl,
+      'zlib': zlib,
+    },
+    section: 'External Libraries'
+  )
+
+endif
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000000..d4c7f717ff8
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,81 @@
+# Data layout influencing options
+option('BLCKSZ', type : 'combo', choices : ['1', '2', '4', '8', '16', '32'], value : '8',
+  description: 'set table block size in kB')
+
+
+# You get it
+option('cassert', type : 'boolean', value: false,
+  description: 'enable assertion checks (for debugging)')
+
+option('atomics', type : 'boolean', value: true,
+  description: 'whether to use atomic operations')
+
+
+# Compilation options
+
+option('extra_include_dirs', type : 'array',
+  description: 'non-default directories to be searched for headers')
+option('extra_lib_dirs', type : 'array',
+  description: 'non-default directories to be searched for libs')
+
+
+# External dependencies
+
+option('gssapi', type : 'feature', value: 'auto',
+  description: 'GSSAPI support')
+
+option('ldap', type : 'feature', value: 'auto',
+  description: 'LDAP support')
+
+option('llvm', type : 'feature', value: 'disabled',
+  description: 'whether to use llvm')
+
+option('icu', type : 'feature', value: 'auto',
+  description: 'ICU support')
+
+option('libxml', type : 'feature', value: 'auto',
+  description: 'XML support')
+
+option('libxslt', type : 'feature', value: 'auto',
+  description: 'XSLT support in contrib/xml2')
+
+option('lz4', type : 'feature', value: 'auto',
+  description: 'LZ4 support')
+
+option('perl', type : 'feature', value: 'auto',
+  description: 'build Perl modules (PL/Perl)')
+
+option('python', type : 'feature', value: 'auto',
+  description: 'build Python modules (PL/Python)')
+
+option('readline', type : 'feature', value : 'auto',
+  description: 'use GNU Readline or BSD Libedit for editing')
+
+option('ssl', type : 'combo', choices : ['none', 'openssl'], value : 'none',
+  description: 'use LIB for SSL/TLS support (openssl)')
+
+option('zlib', type : 'feature', value: 'auto',
+  description: 'whether to use zlib')
+
+
+# Programs
+option('BISON', type : 'string', value: 'bison',
+  description: 'path to bison binary')
+
+option('FLEX', type : 'string', value: 'flex',
+  description: 'path to flex binary')
+
+option('GZIP', type : 'string', value: 'gzip',
+  description: 'path to gzip binary')
+
+option('PERL', type : 'string', value: 'perl',
+  description: 'path to perl binary')
+
+option('PROVE', type : 'string', value: 'prove',
+  description: 'path to prove binary')
+
+option('SED', type : 'string', value: 'gsed',
+  description: 'path to sed binary')
+
+option('TAR', type : 'string', value: 'tar',
+  description: 'path to tar binary')
diff --git a/src/backend/access/brin/meson.build b/src/backend/access/brin/meson.build
new file mode 100644
index 00000000000..a54c7532927
--- /dev/null
+++ b/src/backend/access/brin/meson.build
@@ -0,0 +1,12 @@
+backend_sources += files(
+  'brin.c',
+  'brin_bloom.c',
+  'brin_inclusion.c',
+  'brin_minmax.c',
+  'brin_minmax_multi.c',
+  'brin_pageops.c',
+  'brin_revmap.c',
+  'brin_tuple.c',
+  'brin_validate.c',
+  'brin_xlog.c',
+)
diff --git a/src/backend/access/common/meson.build b/src/backend/access/common/meson.build
new file mode 100644
index 00000000000..857beaa32d3
--- /dev/null
+++ b/src/backend/access/common/meson.build
@@ -0,0 +1,18 @@
+backend_sources += files(
+  'attmap.c',
+  'bufmask.c',
+  'detoast.c',
+  'heaptuple.c',
+  'indextuple.c',
+  'printsimple.c',
+  'printtup.c',
+  'relation.c',
+  'reloptions.c',
+  'scankey.c',
+  'session.c',
+  'syncscan.c',
+  'toast_compression.c',
+  'toast_internals.c',
+  'tupconvert.c',
+  'tupdesc.c',
+)
diff --git a/src/backend/access/gin/meson.build b/src/backend/access/gin/meson.build
new file mode 100644
index 00000000000..56d6f343d54
--- /dev/null
+++ b/src/backend/access/gin/meson.build
@@ -0,0 +1,17 @@
+backend_sources += files(
+  'ginarrayproc.c',
+  'ginbtree.c',
+  'ginbulk.c',
+  'gindatapage.c',
+  'ginentrypage.c',
+  'ginfast.c',
+  'ginget.c',
+  'gininsert.c',
+  'ginlogic.c',
+  'ginpostinglist.c',
+  'ginscan.c',
+  'ginutil.c',
+  'ginvacuum.c',
+  'ginvalidate.c',
+  'ginxlog.c',
+)
diff --git a/src/backend/access/gist/meson.build b/src/backend/access/gist/meson.build
new file mode 100644
index 00000000000..1a996b5e25d
--- /dev/null
+++ b/src/backend/access/gist/meson.build
@@ -0,0 +1,13 @@
+backend_sources += files(
+  'gist.c',
+  'gistbuild.c',
+  'gistbuildbuffers.c',
+  'gistget.c',
+  'gistproc.c',
+  'gistscan.c',
+  'gistsplit.c',
+  'gistutil.c',
+  'gistvacuum.c',
+  'gistvalidate.c',
+  'gistxlog.c',
+)
diff --git a/src/backend/access/hash/meson.build b/src/backend/access/hash/meson.build
new file mode 100644
index 00000000000..22f2c691c34
--- /dev/null
+++ b/src/backend/access/hash/meson.build
@@ -0,0 +1,12 @@
+backend_sources += files(
+  'hash.c',
+  'hash_xlog.c',
+  'hashfunc.c',
+  'hashinsert.c',
+  'hashovfl.c',
+  'hashpage.c',
+  'hashsearch.c',
+  'hashsort.c',
+  'hashutil.c',
+  'hashvalidate.c',
+)
diff --git a/src/backend/access/heap/meson.build b/src/backend/access/heap/meson.build
new file mode 100644
index 00000000000..f1dca73743c
--- /dev/null
+++ b/src/backend/access/heap/meson.build
@@ -0,0 +1,11 @@
+backend_sources += files(
+  'heapam.c',
+  'heapam_handler.c',
+  'heapam_visibility.c',
+  'heaptoast.c',
+  'hio.c',
+  'pruneheap.c',
+  'rewriteheap.c',
+  'vacuumlazy.c',
+  'visibilitymap.c',
+)
diff --git a/src/backend/access/index/meson.build b/src/backend/access/index/meson.build
new file mode 100644
index 00000000000..18af5533e65
--- /dev/null
+++ b/src/backend/access/index/meson.build
@@ -0,0 +1,6 @@
+backend_sources += files(
+  'amapi.c',
+  'amvalidate.c',
+  'genam.c',
+  'indexam.c',
+)
diff --git a/src/backend/access/meson.build b/src/backend/access/meson.build
new file mode 100644
index 00000000000..9874291fc0a
--- /dev/null
+++ b/src/backend/access/meson.build
@@ -0,0 +1,13 @@
+subdir('brin')
+subdir('common')
+subdir('gin')
+subdir('gist')
+subdir('hash')
+subdir('heap')
+subdir('index')
+subdir('nbtree')
+subdir('rmgrdesc')
+subdir('spgist')
+subdir('table')
+subdir('tablesample')
+subdir('transam')
diff --git a/src/backend/access/nbtree/meson.build b/src/backend/access/nbtree/meson.build
new file mode 100644
index 00000000000..07dc29e8190
--- /dev/null
+++ b/src/backend/access/nbtree/meson.build
@@ -0,0 +1,13 @@
+backend_sources += files(
+  'nbtcompare.c',
+  'nbtdedup.c',
+  'nbtinsert.c',
+  'nbtpage.c',
+  'nbtree.c',
+  'nbtsearch.c',
+  'nbtsort.c',
+  'nbtsplitloc.c',
+  'nbtutils.c',
+  'nbtvalidate.c',
+  'nbtxlog.c',
+)
diff --git a/src/backend/access/rmgrdesc/meson.build b/src/backend/access/rmgrdesc/meson.build
new file mode 100644
index 00000000000..f3a6e0a571b
--- /dev/null
+++ b/src/backend/access/rmgrdesc/meson.build
@@ -0,0 +1,26 @@
+# used by frontend programs like pg_waldump
+rmgr_desc_sources = files(
+  'brindesc.c',
+  'clogdesc.c',
+  'committsdesc.c',
+  'dbasedesc.c',
+  'genericdesc.c',
+  'gindesc.c',
+  'gistdesc.c',
+  'hashdesc.c',
+  'heapdesc.c',
+  'logicalmsgdesc.c',
+  'mxactdesc.c',
+  'nbtdesc.c',
+  'relmapdesc.c',
+  'replorigindesc.c',
+  'seqdesc.c',
+  'smgrdesc.c',
+  'spgdesc.c',
+  'standbydesc.c',
+  'tblspcdesc.c',
+  'xactdesc.c',
+  'xlogdesc.c',
+)
+
+backend_sources += rmgr_desc_sources
diff --git a/src/backend/access/spgist/meson.build b/src/backend/access/spgist/meson.build
new file mode 100644
index 00000000000..f18d0d2e53f
--- /dev/null
+++ b/src/backend/access/spgist/meson.build
@@ -0,0 +1,13 @@
+backend_sources += files(
+  'spgdoinsert.c',
+  'spginsert.c',
+  'spgkdtreeproc.c',
+  'spgproc.c',
+  'spgquadtreeproc.c',
+  'spgscan.c',
+  'spgtextproc.c',
+  'spgutils.c',
+  'spgvacuum.c',
+  'spgvalidate.c',
+  'spgxlog.c',
+)
diff --git a/src/backend/access/table/meson.build b/src/backend/access/table/meson.build
new file mode 100644
index 00000000000..66c706d640e
--- /dev/null
+++ b/src/backend/access/table/meson.build
@@ -0,0 +1,6 @@
+backend_sources += files(
+  'table.c',
+  'tableam.c',
+  'tableamapi.c',
+  'toast_helper.c',
+)
diff --git a/src/backend/access/tablesample/meson.build b/src/backend/access/tablesample/meson.build
new file mode 100644
index 00000000000..63ee8203226
--- /dev/null
+++ b/src/backend/access/tablesample/meson.build
@@ -0,0 +1,5 @@
+backend_sources += files(
+  'bernoulli.c',
+  'system.c',
+  'tablesample.c',
+)
diff --git a/src/backend/access/transam/meson.build b/src/backend/access/transam/meson.build
new file mode 100644
index 00000000000..fe3703e0f21
--- /dev/null
+++ b/src/backend/access/transam/meson.build
@@ -0,0 +1,28 @@
+backend_sources += files(
+  'clog.c',
+  'commit_ts.c',
+  'generic_xlog.c',
+  'multixact.c',
+  'parallel.c',
+  'rmgr.c',
+  'slru.c',
+  'subtrans.c',
+  'timeline.c',
+  'transam.c',
+  'twophase.c',
+  'twophase_rmgr.c',
+  'varsup.c',
+  'xact.c',
+  'xlog.c',
+  'xlogarchive.c',
+  'xlogfuncs.c',
+  'xloginsert.c',
+  'xlogutils.c',
+)
+
+# used by frontend programs to built a frontend xlogreader
+xlogreader_sources = files(
+  'xlogreader.c',
+)
+
+backend_sources += xlogreader_sources
diff --git a/src/backend/bootstrap/meson.build b/src/backend/bootstrap/meson.build
new file mode 100644
index 00000000000..55c0be68cc4
--- /dev/null
+++ b/src/backend/bootstrap/meson.build
@@ -0,0 +1,12 @@
+backend_sources += files(
+ 'bootstrap.c')
+
+bootscanner = custom_target('bootscanner',
+  input: ['bootscanner.l'],
+  output: ['bootscanner.c'],
+  command: [flex, '-o', '@OUTPUT@', '@INPUT@'])
+
+generated_backend_sources += custom_target('bootparse',
+  input: ['bootparse.y', bootscanner[0]],
+  output: ['bootparse.c'],
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
diff --git a/src/backend/catalog/meson.build b/src/backend/catalog/meson.build
new file mode 100644
index 00000000000..2cc23582e35
--- /dev/null
+++ b/src/backend/catalog/meson.build
@@ -0,0 +1,41 @@
+backend_sources += files(
+  'aclchk.c',
+  'catalog.c',
+  'dependency.c',
+  'heap.c',
+  'index.c',
+  'indexing.c',
+  'namespace.c',
+  'objectaccess.c',
+  'objectaddress.c',
+  'partition.c',
+  'pg_aggregate.c',
+  'pg_cast.c',
+  'pg_class.c',
+  'pg_collation.c',
+  'pg_constraint.c',
+  'pg_conversion.c',
+  'pg_db_role_setting.c',
+  'pg_depend.c',
+  'pg_enum.c',
+  'pg_inherits.c',
+  'pg_largeobject.c',
+  'pg_namespace.c',
+  'pg_operator.c',
+  'pg_proc.c',
+  'pg_publication.c',
+  'pg_range.c',
+  'pg_shdepend.c',
+  'pg_subscription.c',
+  'pg_type.c',
+  'storage.c',
+  'toasting.c',
+)
+
+
+install_data(
+  'information_schema.sql',
+  'sql_features.txt',
+  'system_functions.sql',
+  'system_views.sql',
+  install_dir: 'share/')
diff --git a/src/backend/commands/meson.build b/src/backend/commands/meson.build
new file mode 100644
index 00000000000..8e73b29a263
--- /dev/null
+++ b/src/backend/commands/meson.build
@@ -0,0 +1,50 @@
+backend_sources += files(
+  'aggregatecmds.c',
+  'alter.c',
+  'amcmds.c',
+  'analyze.c',
+  'async.c',
+  'cluster.c',
+  'collationcmds.c',
+  'comment.c',
+  'constraint.c',
+  'conversioncmds.c',
+  'copy.c',
+  'copyfrom.c',
+  'copyfromparse.c',
+  'copyto.c',
+  'createas.c',
+  'dbcommands.c',
+  'define.c',
+  'discard.c',
+  'dropcmds.c',
+  'event_trigger.c',
+  'explain.c',
+  'extension.c',
+  'foreigncmds.c',
+  'functioncmds.c',
+  'indexcmds.c',
+  'lockcmds.c',
+  'matview.c',
+  'opclasscmds.c',
+  'operatorcmds.c',
+  'policy.c',
+  'portalcmds.c',
+  'prepare.c',
+  'proclang.c',
+  'publicationcmds.c',
+  'schemacmds.c',
+  'seclabel.c',
+  'sequence.c',
+  'statscmds.c',
+  'subscriptioncmds.c',
+  'tablecmds.c',
+  'tablespace.c',
+  'trigger.c',
+  'tsearchcmds.c',
+  'typecmds.c',
+  'user.c',
+  'vacuum.c',
+  'variable.c',
+  'view.c',
+)
diff --git a/src/backend/executor/meson.build b/src/backend/executor/meson.build
new file mode 100644
index 00000000000..518674cfa28
--- /dev/null
+++ b/src/backend/executor/meson.build
@@ -0,0 +1,67 @@
+backend_sources += files(
+  'execAmi.c',
+  'execAsync.c',
+  'execCurrent.c',
+  'execExpr.c',
+  'execExprInterp.c',
+  'execGrouping.c',
+  'execIndexing.c',
+  'execJunk.c',
+  'execMain.c',
+  'execParallel.c',
+  'execPartition.c',
+  'execProcnode.c',
+  'execReplication.c',
+  'execSRF.c',
+  'execScan.c',
+  'execTuples.c',
+  'execUtils.c',
+  'functions.c',
+  'instrument.c',
+  'nodeAgg.c',
+  'nodeAppend.c',
+  'nodeBitmapAnd.c',
+  'nodeBitmapHeapscan.c',
+  'nodeBitmapIndexscan.c',
+  'nodeBitmapOr.c',
+  'nodeCtescan.c',
+  'nodeCustom.c',
+  'nodeForeignscan.c',
+  'nodeFunctionscan.c',
+  'nodeGather.c',
+  'nodeGatherMerge.c',
+  'nodeGroup.c',
+  'nodeHash.c',
+  'nodeHashjoin.c',
+  'nodeIncrementalSort.c',
+  'nodeIndexonlyscan.c',
+  'nodeIndexscan.c',
+  'nodeLimit.c',
+  'nodeLockRows.c',
+  'nodeMaterial.c',
+  'nodeMemoize.c',
+  'nodeMergeAppend.c',
+  'nodeMergejoin.c',
+  'nodeModifyTable.c',
+  'nodeNamedtuplestorescan.c',
+  'nodeNestloop.c',
+  'nodeProjectSet.c',
+  'nodeRecursiveunion.c',
+  'nodeResult.c',
+  'nodeSamplescan.c',
+  'nodeSeqscan.c',
+  'nodeSetOp.c',
+  'nodeSort.c',
+  'nodeSubplan.c',
+  'nodeSubqueryscan.c',
+  'nodeTableFuncscan.c',
+  'nodeTidrangescan.c',
+  'nodeTidscan.c',
+  'nodeUnique.c',
+  'nodeValuesscan.c',
+  'nodeWindowAgg.c',
+  'nodeWorktablescan.c',
+  'spi.c',
+  'tqueue.c',
+  'tstoreReceiver.c',
+)
diff --git a/src/backend/foreign/meson.build b/src/backend/foreign/meson.build
new file mode 100644
index 00000000000..57463db92c1
--- /dev/null
+++ b/src/backend/foreign/meson.build
@@ -0,0 +1,3 @@
+backend_sources += files(
+  'foreign.c'
+)
diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
new file mode 100644
index 00000000000..83a90770bca
--- /dev/null
+++ b/src/backend/jit/llvm/meson.build
@@ -0,0 +1,41 @@
+if llvm.found()
+
+  llvmjit_sources = []
+
+  # Infrastructure
+  llvmjit_sources += files(
+    'llvmjit.c',
+    'llvmjit_error.cpp',
+    'llvmjit_inline.cpp',
+    'llvmjit_wrap.cpp',
+  )
+
+  # Code generation
+  llvmjit_sources += files(
+    'llvmjit_deform.c',
+    'llvmjit_expr.c',
+  )
+
+  llvmjit = shared_module('llvmjit',
+    llvmjit_sources,
+    kwargs: pg_mod_args + {
+      'dependencies': pg_mod_args['dependencies'] + [llvm],
+    }
+  )
+
+  backend_targets += llvmjit
+
+  # Note this is intentionally is not installed to bitcodedir, as it's not
+  # for inlining
+  llvmjit_types = custom_target('llvmjit_types.bc',
+    kwargs: llvm_irgen_kw + {
+      'input': 'llvmjit_types.c',
+      'output': 'llvmjit_types.bc',
+      'depends': [postgres],
+      'install': true,
+      'install_dir': get_option('libdir')
+    }
+  )
+  backend_targets += llvmjit_types
+
+endif
diff --git a/src/backend/jit/meson.build b/src/backend/jit/meson.build
new file mode 100644
index 00000000000..63cd33a4bed
--- /dev/null
+++ b/src/backend/jit/meson.build
@@ -0,0 +1,3 @@
+backend_sources += files(
+  'jit.c'
+)
diff --git a/src/backend/lib/meson.build b/src/backend/lib/meson.build
new file mode 100644
index 00000000000..53292563d34
--- /dev/null
+++ b/src/backend/lib/meson.build
@@ -0,0 +1,12 @@
+backend_sources += files(
+  'binaryheap.c',
+  'bipartite_match.c',
+  'bloomfilter.c',
+  'dshash.c',
+  'hyperloglog.c',
+  'ilist.c',
+  'integerset.c',
+  'knapsack.c',
+  'pairingheap.c',
+  'rbtree.c'
+)
diff --git a/src/backend/libpq/meson.build b/src/backend/libpq/meson.build
new file mode 100644
index 00000000000..49867647155
--- /dev/null
+++ b/src/backend/libpq/meson.build
@@ -0,0 +1,28 @@
+backend_sources += files(
+  'auth-sasl.c',
+  'auth-scram.c',
+  'auth.c',
+  'be-fsstubs.c',
+  'be-secure-common.c',
+  'be-secure.c',
+  'crypt.c',
+  'hba.c',
+  'ifaddr.c',
+  'pqcomm.c',
+  'pqformat.c',
+  'pqmq.c',
+  'pqsignal.c',
+)
+
+if ssl.found()
+  backend_sources += files('be-secure-openssl.c')
+endif
+
+if gssapi.found()
+  backend_sources += files(
+    'be-secure-gssapi.c',
+    'be-gssapi-common.c'
+  )
+endif
+
+install_data('pg_hba.conf.sample', 'pg_ident.conf.sample', install_dir: 'share/')
diff --git a/src/backend/main/meson.build b/src/backend/main/meson.build
new file mode 100644
index 00000000000..241e125f089
--- /dev/null
+++ b/src/backend/main/meson.build
@@ -0,0 +1,2 @@
+main_file = files('main.c')
+backend_sources += main_file
diff --git a/src/backend/meson.build b/src/backend/meson.build
new file mode 100644
index 00000000000..b84f947bc7e
--- /dev/null
+++ b/src/backend/meson.build
@@ -0,0 +1,191 @@
+backend_build_deps = [backend_code]
+backend_deps = [dl_dep, thread_dep]
+backend_sources = []
+backend_link_with = [pgport_srv, common_srv]
+backend_c_args = []
+
+generated_backend_sources = []
+
+subdir('access')
+subdir('bootstrap')
+subdir('catalog')
+subdir('commands')
+subdir('executor')
+subdir('foreign')
+subdir('jit')
+subdir('lib')
+subdir('libpq')
+subdir('main')
+subdir('nodes')
+subdir('optimizer')
+subdir('parser')
+subdir('partitioning')
+subdir('port')
+subdir('postmaster')
+subdir('regex')
+subdir('replication')
+subdir('rewrite')
+subdir('statistics')
+subdir('storage')
+subdir('tcop')
+subdir('tsearch')
+subdir('utils')
+
+
+if host_machine.system() == 'windows'
+  backend_deps += cc.find_library('secur32', required: true)
+endif
+
+
+postgres_link_args = []
+postgres_link_depends = []
+
+# On windows when compiling with msvc we need to make postgres export all its
+# symbols so that extension libraries can use them. For that we need to scan
+# the constituting objects and generate a file specifying all the functions as
+# exported (variables need an "import" declaration in the header, hence
+# PGDLLEXPORT, but functions work without that, due to import libraries
+# basically being trampolines).
+#
+#
+# On meson there's currently no easy way to do this that I found. So we build
+# a static library with all the input objects, run our script to generate
+# exports, and build the final executable using that static library
+#
+#
+# XXX: This needs to be improved.
+#
+
+# NB: There's an outer and inner layer of == windows checks, to allow to
+# exercise most of this on !windows, by widening the outer "layer".
+
+if cc.get_id() == 'msvc' # or true
+
+  postgres_lib = static_library('postgres_lib',
+    backend_sources + timezone_sources + generated_backend_sources,
+    link_whole: backend_link_with,
+    c_pch: '../include/pch/postgres_pch.h',
+    c_args: backend_c_args,
+    implicit_include_directories: false,
+    dependencies: backend_build_deps,
+    build_by_default: false,
+    install: false,
+  )
+
+  postgres_def = custom_target('postgres.def',
+    command: [perl, files('../tools/msvc/gendef2.pl'), 'x64', '@OUTPUT@', '@PRIVATE_DIR@', '@INPUT@'],
+    input: [postgres_lib, common_srv, pgport_srv],
+    output: 'postgres.def',
+    depends: [postgres_lib, common_srv, pgport_srv],
+    install: false,
+  )
+
+  if cc.get_id() == 'msvc'
+    postgres_link_args += '/DEF:@0@'.format(postgres_def.full_path())
+    postgres_link_args += '/STACK:@0@'.format(cdata.get('WIN32_STACK_RLIMIT'))
+    postgres_link_depends += postgres_def
+  endif
+
+  # Unfortunately the msvc linker whines when building an executable with just
+  # libraries, hence the reuse of the 'main' object directly.
+
+  postgres = executable('postgres',
+    objects: [postgres_lib.extract_objects(main_file)],
+    link_with: [postgres_lib],
+    link_args: postgres_link_args,
+    link_depends: postgres_link_depends,
+    dependencies: backend_deps,
+    export_dynamic: true,
+    implib: true,
+    kwargs: default_bin_args,
+  )
+
+else
+
+  postgres = executable('postgres',
+    backend_sources + generated_backend_sources + timezone_sources,
+    c_pch: '../include/pch/postgres_pch.h',
+    c_args: backend_c_args,
+    link_with: backend_link_with,
+    export_dynamic: true,
+    dependencies: [backend_build_deps, backend_deps],
+    kwargs: default_bin_args,
+  )
+
+endif
+
+backend_targets += postgres
+
+pg_mod_args = default_mod_args + {
+  'dependencies': [backend_mod_code],
+  'c_args': [],
+  'cpp_args': [],
+ }
+
+if cdata.has('HAVE_VISIBILITY_ATTRIBUTE')
+  pg_mod_args = pg_mod_args + {
+    'c_args': pg_mod_args['c_args'] + ['-fvisibility=hidden'],
+    'cpp_args': pg_mod_args['c_args'] + ['-fvisibility=hidden', '-fvisibility-inlines-hidden'],
+  }
+endif
+
+# Windows / MacOs link shared modules against postgres. To avoid unnecessary
+# build-time dependencies on other operating systems, only add it when
+# necessary.
+if host_machine.system() == 'windows' or host_machine.system() == 'darwin'
+   pg_mod_args = pg_mod_args + {'link_with': [postgres]}
+endif
+if host_machine.system() == 'darwin'
+   pg_mod_args = pg_mod_args + {'link_args': ['-bundle_loader', '@0@'.format(postgres.full_path())]}
+endif
+
+
+# Shared modules that, on some OSs, link against the server binary. Only enter
+# these after we defined the server build.
+
+subdir('jit/llvm')
+subdir('replication/libpqwalreceiver')
+subdir('replication/pgoutput')
+subdir('snowball')
+subdir('utils/mb/conversion_procs')
+
+
+if llvm.found()
+
+  # custom_target() insists on targetting files into the current
+  # directory. But we have files with the same name in different
+  # subdirectories.  generators() don't have that problem, but their results
+  # are not installable. The irlink command copies the files for us.
+  #
+  # FIXME: this needs to be in a central place
+  #
+  # generator and custom_'t accept CustomTargetIndex as 'depends', nor do they
+  # like targets with more than one output. However, a custom target accepts
+  # them as input without a problem. So we have the below transitive target :(
+
+  transitive_depend_target = custom_target('stamp',
+    input: generated_headers + generated_backend_headers + generated_backend_sources,
+    output: 'stamp',
+    command: [touch, '@OUTPUT@'],
+    install: false)
+
+  llvm_gen = generator(llvm_irgen_command,
+    arguments: llvm_irgen_args + g_c_args,
+    depends: transitive_depend_target,
+    depfile: '@BASENAME@.c.bc.d',
+    output: ['@PLAINNAME@.bc']
+  )
+
+  bc_backend_sources = llvm_gen.process(backend_sources,
+    preserve_path_from: meson.current_source_dir())
+
+  postgres_llvm = custom_target('postgres.index.bc',
+    kwargs: llvm_irlink_kw + {
+      'input': bc_backend_sources,
+      'output': ['bitcode'],
+      },
+  )
+
+  backend_targets += postgres_llvm
+
+endif
diff --git a/src/backend/nodes/meson.build b/src/backend/nodes/meson.build
new file mode 100644
index 00000000000..9fca83fba44
--- /dev/null
+++ b/src/backend/nodes/meson.build
@@ -0,0 +1,17 @@
+backend_sources += files(
+  'bitmapset.c',
+  'copyfuncs.c',
+  'equalfuncs.c',
+  'extensible.c',
+  'list.c',
+  'makefuncs.c',
+  'nodeFuncs.c',
+  'nodes.c',
+  'outfuncs.c',
+  'params.c',
+  'print.c',
+  'read.c',
+  'readfuncs.c',
+  'tidbitmap.c',
+  'value.c',
+)
diff --git a/src/backend/optimizer/geqo/meson.build b/src/backend/optimizer/geqo/meson.build
new file mode 100644
index 00000000000..c04f1dc2dfd
--- /dev/null
+++ b/src/backend/optimizer/geqo/meson.build
@@ -0,0 +1,17 @@
+backend_sources += files(
+  'geqo_copy.c',
+  'geqo_cx.c',
+  'geqo_erx.c',
+  'geqo_eval.c',
+  'geqo_main.c',
+  'geqo_misc.c',
+  'geqo_mutation.c',
+  'geqo_ox1.c',
+  'geqo_ox2.c',
+  'geqo_pmx.c',
+  'geqo_pool.c',
+  'geqo_px.c',
+  'geqo_random.c',
+  'geqo_recombination.c',
+  'geqo_selection.c',
+)
diff --git a/src/backend/optimizer/meson.build b/src/backend/optimizer/meson.build
new file mode 100644
index 00000000000..1ab1d9934ae
--- /dev/null
+++ b/src/backend/optimizer/meson.build
@@ -0,0 +1,5 @@
+subdir('geqo')
+subdir('path')
+subdir('plan')
+subdir('prep')
+subdir('util')
diff --git a/src/backend/optimizer/path/meson.build b/src/backend/optimizer/path/meson.build
new file mode 100644
index 00000000000..310042e7aee
--- /dev/null
+++ b/src/backend/optimizer/path/meson.build
@@ -0,0 +1,11 @@
+backend_sources += files(
+  'allpaths.c',
+  'clausesel.c',
+  'costsize.c',
+  'equivclass.c',
+  'indxpath.c',
+  'joinpath.c',
+  'joinrels.c',
+  'pathkeys.c',
+  'tidpath.c',
+)
diff --git a/src/backend/optimizer/plan/meson.build b/src/backend/optimizer/plan/meson.build
new file mode 100644
index 00000000000..22ec65a3845
--- /dev/null
+++ b/src/backend/optimizer/plan/meson.build
@@ -0,0 +1,10 @@
+backend_sources += files(
+  'analyzejoins.c',
+  'createplan.c',
+  'initsplan.c',
+  'planagg.c',
+  'planmain.c',
+  'planner.c',
+  'setrefs.c',
+  'subselect.c',
+)
diff --git a/src/backend/optimizer/prep/meson.build b/src/backend/optimizer/prep/meson.build
new file mode 100644
index 00000000000..4549a5b0e79
--- /dev/null
+++ b/src/backend/optimizer/prep/meson.build
@@ -0,0 +1,7 @@
+backend_sources += files(
+  'prepagg.c',
+  'prepjointree.c',
+  'prepqual.c',
+  'preptlist.c',
+  'prepunion.c',
+)
diff --git a/src/backend/optimizer/util/meson.build b/src/backend/optimizer/util/meson.build
new file mode 100644
index 00000000000..e7ceaf566b5
--- /dev/null
+++ b/src/backend/optimizer/util/meson.build
@@ -0,0 +1,16 @@
+backend_sources += files(
+  'appendinfo.c',
+  'clauses.c',
+  'inherit.c',
+  'joininfo.c',
+  'orclauses.c',
+  'paramassign.c',
+  'pathnode.c',
+  'placeholder.c',
+  'plancat.c',
+  'predtest.c',
+  'relnode.c',
+  'restrictinfo.c',
+  'tlist.c',
+  'var.c',
+)
diff --git a/src/backend/parser/meson.build b/src/backend/parser/meson.build
new file mode 100644
index 00000000000..491eacf20bb
--- /dev/null
+++ b/src/backend/parser/meson.build
@@ -0,0 +1,43 @@
+backend_sources += files(
+  'analyze.c',
+  'parse_agg.c',
+  'parse_clause.c',
+  'parse_coerce.c',
+  'parse_collate.c',
+  'parse_cte.c',
+  'parse_enr.c',
+  'parse_expr.c',
+  'parse_func.c',
+  'parse_node.c',
+  'parse_oper.c',
+  'parse_param.c',
+  'parse_relation.c',
+  'parse_target.c',
+  'parse_type.c',
+  'parse_utilcmd.c',
+  'scansup.c',
+)
+
+# Build a small utility static lib for the parser. This makes it easier to not
+# depend on gram.h already having been generated for most of the other code
+# (which depends on generated headers having been generated). The generation
+# of the parser is slow...
+
+parser_sources = [files('parser.c')]
+
+backend_scanner = custom_target('scan',
+  input: ['scan.l'],
+  output: ['scan.c'],
+  command: [flex, '-CF', '-p', '-p', '-o', '@OUTPUT@', '@INPUT0@'])
+parser_sources += backend_scanner[0]
+
+parser_sources += backend_parser_header[0]
+parser_sources += backend_parser_header[1]
+
+parser = static_library('parser',
+  parser_sources + generated_headers,
+  c_pch: '../../include/pch/c_pch.h',
+  dependencies: [backend_code],
+  kwargs: default_lib_args + {'install': false},
+)
+backend_link_with += parser
diff --git a/src/backend/partitioning/meson.build b/src/backend/partitioning/meson.build
new file mode 100644
index 00000000000..e5e3806a0cc
--- /dev/null
+++ b/src/backend/partitioning/meson.build
@@ -0,0 +1,5 @@
+backend_sources += files(
+  'partbounds.c',
+  'partdesc.c',
+  'partprune.c',
+)
diff --git a/src/backend/port/meson.build b/src/backend/port/meson.build
new file mode 100644
index 00000000000..f1bf7f6d929
--- /dev/null
+++ b/src/backend/port/meson.build
@@ -0,0 +1,28 @@
+backend_sources += files(
+  'atomics.c',
+)
+
+
+if cdata.has('USE_UNNAMED_POSIX_SEMAPHORES') or cdata.has('USE_NAMED_POSIX_SEMAPHORES')
+   backend_sources += files('posix_sema.c')
+endif
+
+if cdata.has('USE_SYSV_SEMAPHORES')
+   backend_sources += files('sysv_sema.c')
+endif
+
+if cdata.has('USE_WIN32_SEMAPHORES')
+   backend_sources += files('win32_sema.c')
+endif
+
+if cdata.has('USE_SYSV_SHARED_MEMORY')
+   backend_sources += files('sysv_shmem.c')
+endif
+
+if cdata.has('USE_WIN32_SHARED_MEMORY')
+   backend_sources += files('win32_shmem.c')
+endif
+
+if host_machine.system() == 'windows'
+  subdir('win32')
+endif
diff --git a/src/backend/port/win32/meson.build b/src/backend/port/win32/meson.build
new file mode 100644
index 00000000000..68fe4cc3cd0
--- /dev/null
+++ b/src/backend/port/win32/meson.build
@@ -0,0 +1,6 @@
+backend_sources += files(
+  'crashdump.c',
+  'signal.c',
+  'socket.c',
+  'timer.c',
+)
diff --git a/src/backend/postmaster/meson.build b/src/backend/postmaster/meson.build
new file mode 100644
index 00000000000..803405683e2
--- /dev/null
+++ b/src/backend/postmaster/meson.build
@@ -0,0 +1,15 @@
+backend_sources += files(
+  'autovacuum.c',
+  'auxprocess.c',
+  'bgworker.c',
+  'bgwriter.c',
+  'checkpointer.c',
+  'fork_process.c',
+  'interrupt.c',
+  'pgarch.c',
+  'pgstat.c',
+  'postmaster.c',
+  'startup.c',
+  'syslogger.c',
+  'walwriter.c',
+)
diff --git a/src/backend/regex/meson.build b/src/backend/regex/meson.build
new file mode 100644
index 00000000000..d08e21cd6d6
--- /dev/null
+++ b/src/backend/regex/meson.build
@@ -0,0 +1,15 @@
+backend_sources += files(
+  'regcomp.c',
+  'regerror.c',
+  'regexec.c',
+  'regexport.c',
+  'regfree.c',
+  'regprefix.c'
+)
+
+#FIXME
+# mark inclusion dependencies between .c files explicitly
+#regcomp.o: regcomp.c regc_lex.c regc_color.c regc_nfa.c regc_cvec.c \
+#        regc_locale.c regc_pg_locale.c
+#
+#regexec.o: regexec.c rege_dfa.c
diff --git a/src/backend/replication/libpqwalreceiver/meson.build b/src/backend/replication/libpqwalreceiver/meson.build
new file mode 100644
index 00000000000..3fc786c80a0
--- /dev/null
+++ b/src/backend/replication/libpqwalreceiver/meson.build
@@ -0,0 +1,13 @@
+libpqwalreceiver_sources = files(
+  'libpqwalreceiver.c',
+)
+
+libpqwalreceiver = shared_module('pqwalreceiver',
+  libpqwalreceiver_sources,
+  kwargs: pg_mod_args + {
+    'name_prefix': 'lib',
+    'dependencies': pg_mod_args['dependencies'] + [libpq],
+  }
+)
+
+backend_targets += libpqwalreceiver
diff --git a/src/backend/replication/logical/meson.build b/src/backend/replication/logical/meson.build
new file mode 100644
index 00000000000..773583a12ba
--- /dev/null
+++ b/src/backend/replication/logical/meson.build
@@ -0,0 +1,14 @@
+backend_sources += files(
+  'decode.c',
+  'launcher.c',
+  'logical.c',
+  'logicalfuncs.c',
+  'message.c',
+  'origin.c',
+  'proto.c',
+  'relation.c',
+  'reorderbuffer.c',
+  'snapbuild.c',
+  'tablesync.c',
+  'worker.c',
+)
diff --git a/src/backend/replication/meson.build b/src/backend/replication/meson.build
new file mode 100644
index 00000000000..2573f166d79
--- /dev/null
+++ b/src/backend/replication/meson.build
@@ -0,0 +1,42 @@
+backend_sources += files(
+  'backup_manifest.c',
+  'basebackup.c',
+  'slot.c',
+  'slotfuncs.c',
+  'syncrep.c',
+  'walreceiver.c',
+  'walreceiverfuncs.c',
+  'walsender.c',
+)
+
+# [sync]repl_scanner is compiled as part of [sync]repl_gram. The
+# ordering is enforced by making the generation of grammar depend on
+# the scanner generation. That's unnecessarily strict, but overall
+# harmless.
+
+repl_scanner = custom_target('repl_scanner',
+  input : files('repl_scanner.l'),
+  output : ['repl_scanner.c'],
+  command : [flex, '-CF', '-p', '-p', '-o', '@OUTPUT0@', '@INPUT@']
+)
+
+generated_backend_sources += custom_target('repl_gram',
+  input: 'repl_gram.y',
+  output: 'repl_gram.c',
+  depends: repl_scanner,
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
+
+
+syncrep_scanner = custom_target('syncrep_scanner',
+  input: 'syncrep_scanner.l',
+  output: 'syncrep_scanner.c',
+  command: [flex, '-CF', '-p', '-p', '-o', '@OUTPUT0@', '@INPUT@'])
+
+generated_backend_sources += custom_target('syncrep_gram',
+  input: 'syncrep_gram.y',
+  output: 'syncrep_gram.c',
+  depends: syncrep_scanner,
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
+
+
+subdir('logical')
diff --git a/src/backend/replication/pgoutput/meson.build b/src/backend/replication/pgoutput/meson.build
new file mode 100644
index 00000000000..8ff0a0c6133
--- /dev/null
+++ b/src/backend/replication/pgoutput/meson.build
@@ -0,0 +1,11 @@
+pgoutput_sources = files(
+  'pgoutput.c',
+)
+
+pgoutput = shared_module('pgoutput',
+  pgoutput_sources,
+  kwargs: pg_mod_args + {
+  }
+)
+
+backend_targets += pgoutput
diff --git a/src/backend/rewrite/meson.build b/src/backend/rewrite/meson.build
new file mode 100644
index 00000000000..032e2e409b5
--- /dev/null
+++ b/src/backend/rewrite/meson.build
@@ -0,0 +1,9 @@
+backend_sources += files(
+  'rewriteDefine.c',
+  'rewriteHandler.c',
+  'rewriteManip.c',
+  'rewriteRemove.c',
+  'rewriteSearchCycle.c',
+  'rewriteSupport.c',
+  'rowsecurity.c'
+)
diff --git a/src/backend/snowball/meson.build b/src/backend/snowball/meson.build
new file mode 100644
index 00000000000..b1e52e9a0c3
--- /dev/null
+++ b/src/backend/snowball/meson.build
@@ -0,0 +1,83 @@
+dict_snowball_sources = files(
+  'dict_snowball.c',
+  'libstemmer/api.c',
+  'libstemmer/utilities.c',
+)
+
+dict_snowball_sources += files(
+  'libstemmer/stem_ISO_8859_1_basque.c',
+  'libstemmer/stem_ISO_8859_1_catalan.c',
+  'libstemmer/stem_ISO_8859_1_danish.c',
+  'libstemmer/stem_ISO_8859_1_dutch.c',
+  'libstemmer/stem_ISO_8859_1_english.c',
+  'libstemmer/stem_ISO_8859_1_finnish.c',
+  'libstemmer/stem_ISO_8859_1_french.c',
+  'libstemmer/stem_ISO_8859_1_german.c',
+  'libstemmer/stem_ISO_8859_1_indonesian.c',
+  'libstemmer/stem_ISO_8859_1_irish.c',
+  'libstemmer/stem_ISO_8859_1_italian.c',
+  'libstemmer/stem_ISO_8859_1_norwegian.c',
+  'libstemmer/stem_ISO_8859_1_porter.c',
+  'libstemmer/stem_ISO_8859_1_portuguese.c',
+  'libstemmer/stem_ISO_8859_1_spanish.c',
+  'libstemmer/stem_ISO_8859_1_swedish.c',
+  'libstemmer/stem_ISO_8859_2_hungarian.c',
+  'libstemmer/stem_ISO_8859_2_romanian.c',
+  'libstemmer/stem_KOI8_R_russian.c',
+  'libstemmer/stem_UTF_8_arabic.c',
+  'libstemmer/stem_UTF_8_armenian.c',
+  'libstemmer/stem_UTF_8_basque.c',
+  'libstemmer/stem_UTF_8_catalan.c',
+  'libstemmer/stem_UTF_8_danish.c',
+  'libstemmer/stem_UTF_8_dutch.c',
+  'libstemmer/stem_UTF_8_english.c',
+  'libstemmer/stem_UTF_8_finnish.c',
+  'libstemmer/stem_UTF_8_french.c',
+  'libstemmer/stem_UTF_8_german.c',
+  'libstemmer/stem_UTF_8_greek.c',
+  'libstemmer/stem_UTF_8_hindi.c',
+  'libstemmer/stem_UTF_8_hungarian.c',
+  'libstemmer/stem_UTF_8_indonesian.c',
+  'libstemmer/stem_UTF_8_irish.c',
+  'libstemmer/stem_UTF_8_italian.c',
+  'libstemmer/stem_UTF_8_lithuanian.c',
+  'libstemmer/stem_UTF_8_nepali.c',
+  'libstemmer/stem_UTF_8_norwegian.c',
+  'libstemmer/stem_UTF_8_porter.c',
+  'libstemmer/stem_UTF_8_portuguese.c',
+  'libstemmer/stem_UTF_8_romanian.c',
+  'libstemmer/stem_UTF_8_russian.c',
+  'libstemmer/stem_UTF_8_serbian.c',
+  'libstemmer/stem_UTF_8_spanish.c',
+  'libstemmer/stem_UTF_8_swedish.c',
+  'libstemmer/stem_UTF_8_tamil.c',
+  'libstemmer/stem_UTF_8_turkish.c',
+  'libstemmer/stem_UTF_8_yiddish.c',
+)
+
+# see comment in src/include/snowball/header.h
+stemmer_inc = include_directories('../../include/snowball')
+
+dict_snowball = shared_module('dict_snowball',
+  dict_snowball_sources,
+  c_pch: '../../include/pch/postgres_pch.h',
+  kwargs: pg_mod_args + {
+    'include_directories': [stemmer_inc],
+  }
+)
+
+snowball_create = custom_target('snowball_create',
+  input: ['snowball_create.pl'],
+  output: ['snowball_create.sql'],
+  depfile: 'snowball_create.dep',
+  command: [perl, '@INPUT0@', '--input', '@CURRENT_SOURCE_DIR@', '--output', '@OUTDIR@'],
+  install: true,
+  install_dir: get_option('datadir'))
+
+# FIXME: check whether the logic to select languages currently in Makefile is needed
+install_subdir('stopwords',
+  install_dir: get_option('datadir') / 'tsearch_data',
+  strip_directory: true)
+
+backend_targets += dict_snowball
+backend_targets += snowball_create
diff --git a/src/backend/statistics/meson.build b/src/backend/statistics/meson.build
new file mode 100644
index 00000000000..8530c55f73c
--- /dev/null
+++ b/src/backend/statistics/meson.build
@@ -0,0 +1,6 @@
+backend_sources += files(
+  'dependencies.c',
+  'extended_stats.c',
+  'mcv.c',
+  'mvdistinct.c',
+)
diff --git a/src/backend/storage/buffer/meson.build b/src/backend/storage/buffer/meson.build
new file mode 100644
index 00000000000..56a59b52484
--- /dev/null
+++ b/src/backend/storage/buffer/meson.build
@@ -0,0 +1,7 @@
+backend_sources += files(
+  'buf_init.c',
+  'buf_table.c',
+  'bufmgr.c',
+  'freelist.c',
+  'localbuf.c',
+)
diff --git a/src/backend/storage/file/meson.build b/src/backend/storage/file/meson.build
new file mode 100644
index 00000000000..e1d5047d4aa
--- /dev/null
+++ b/src/backend/storage/file/meson.build
@@ -0,0 +1,8 @@
+backend_sources += files(
+  'buffile.c',
+  'copydir.c',
+  'fd.c',
+  'fileset.c',
+  'reinit.c',
+  'sharedfileset.c',
+)
diff --git a/src/backend/storage/freespace/meson.build b/src/backend/storage/freespace/meson.build
new file mode 100644
index 00000000000..e4200ea6527
--- /dev/null
+++ b/src/backend/storage/freespace/meson.build
@@ -0,0 +1,5 @@
+backend_sources += files(
+  'freespace.c',
+  'fsmpage.c',
+  'indexfsm.c',
+)
diff --git a/src/backend/storage/ipc/meson.build b/src/backend/storage/ipc/meson.build
new file mode 100644
index 00000000000..516bc1d0193
--- /dev/null
+++ b/src/backend/storage/ipc/meson.build
@@ -0,0 +1,20 @@
+backend_sources += files(
+  'barrier.c',
+  'dsm.c',
+  'dsm_impl.c',
+  'ipc.c',
+  'ipci.c',
+  'latch.c',
+  'pmsignal.c',
+  'procarray.c',
+  'procsignal.c',
+  'shm_mq.c',
+  'shm_toc.c',
+  'shmem.c',
+  'shmqueue.c',
+  'signalfuncs.c',
+  'sinval.c',
+  'sinvaladt.c',
+  'standby.c',
+
+)
diff --git a/src/backend/storage/large_object/meson.build b/src/backend/storage/large_object/meson.build
new file mode 100644
index 00000000000..8a181ab9b34
--- /dev/null
+++ b/src/backend/storage/large_object/meson.build
@@ -0,0 +1,3 @@
+backend_sources += files(
+  'inv_api.c',
+)
diff --git a/src/backend/storage/lmgr/meson.build b/src/backend/storage/lmgr/meson.build
new file mode 100644
index 00000000000..938e7f89894
--- /dev/null
+++ b/src/backend/storage/lmgr/meson.build
@@ -0,0 +1,18 @@
+backend_sources += files(
+  'condition_variable.c',
+  'deadlock.c',
+  'lmgr.c',
+  'lock.c',
+  'lwlock.c',
+  'predicate.c',
+  'proc.c',
+  's_lock.c',
+  'spin.c',
+)
+
+lwlocknames_backend = custom_target('lwlocknames',
+  input : files('lwlocknames.txt'),
+  output : ['lwlocknames.c', 'lwlocknames.h'],
+  command : [perl, files('generate-lwlocknames.pl'), '-o', '@OUTDIR@', '@INPUT@']
+)
+generated_backend_sources += lwlocknames_backend[0]
diff --git a/src/backend/storage/meson.build b/src/backend/storage/meson.build
new file mode 100644
index 00000000000..daad628d74c
--- /dev/null
+++ b/src/backend/storage/meson.build
@@ -0,0 +1,9 @@
+subdir('buffer')
+subdir('file')
+subdir('freespace')
+subdir('ipc')
+subdir('large_object')
+subdir('lmgr')
+subdir('page')
+subdir('smgr')
+subdir('sync')
diff --git a/src/backend/storage/page/meson.build b/src/backend/storage/page/meson.build
new file mode 100644
index 00000000000..2ecd16c952c
--- /dev/null
+++ b/src/backend/storage/page/meson.build
@@ -0,0 +1,5 @@
+backend_sources += files(
+  'bufpage.c',
+  'checksum.c',
+  'itemptr.c',
+)
diff --git a/src/backend/storage/smgr/meson.build b/src/backend/storage/smgr/meson.build
new file mode 100644
index 00000000000..fdeb1223b32
--- /dev/null
+++ b/src/backend/storage/smgr/meson.build
@@ -0,0 +1,4 @@
+backend_sources += files(
+  'md.c',
+  'smgr.c',
+)
diff --git a/src/backend/storage/sync/meson.build b/src/backend/storage/sync/meson.build
new file mode 100644
index 00000000000..05148b91a8e
--- /dev/null
+++ b/src/backend/storage/sync/meson.build
@@ -0,0 +1,4 @@
+backend_sources += files(
+  'sync.c',
+
+)
diff --git a/src/backend/tcop/meson.build b/src/backend/tcop/meson.build
new file mode 100644
index 00000000000..fb54aae8122
--- /dev/null
+++ b/src/backend/tcop/meson.build
@@ -0,0 +1,8 @@
+backend_sources += files(
+  'cmdtag.c',
+  'dest.c',
+  'fastpath.c',
+  'postgres.c',
+  'pquery.c',
+  'utility.c',
+)
diff --git a/src/backend/tsearch/meson.build b/src/backend/tsearch/meson.build
new file mode 100644
index 00000000000..460036b6d4c
--- /dev/null
+++ b/src/backend/tsearch/meson.build
@@ -0,0 +1,21 @@
+backend_sources += files(
+  'dict.c',
+  'dict_ispell.c',
+  'dict_simple.c',
+  'dict_synonym.c',
+  'dict_thesaurus.c',
+  'regis.c',
+  'spell.c',
+  'to_tsany.c',
+  'ts_locale.c',
+  'ts_parse.c',
+  'ts_selfuncs.c',
+  'ts_typanalyze.c',
+  'ts_utils.c',
+  'wparser.c',
+  'wparser_def.c',
+)
+
+install_subdir('dicts',
+  install_dir: get_option('datadir') / 'tsearch_data',
+  strip_directory: true)
diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build
new file mode 100644
index 00000000000..cef26eb564b
--- /dev/null
+++ b/src/backend/utils/activity/meson.build
@@ -0,0 +1,5 @@
+backend_sources += files(
+  'backend_progress.c',
+  'backend_status.c',
+  'wait_event.c',
+)
diff --git a/src/backend/utils/adt/meson.build b/src/backend/utils/adt/meson.build
new file mode 100644
index 00000000000..086fde8ff09
--- /dev/null
+++ b/src/backend/utils/adt/meson.build
@@ -0,0 +1,118 @@
+backend_sources += files(
+  'acl.c',
+  'amutils.c',
+  'array_expanded.c',
+  'array_selfuncs.c',
+  'array_typanalyze.c',
+  'array_userfuncs.c',
+  'arrayfuncs.c',
+  'arraysubs.c',
+  'arrayutils.c',
+  'ascii.c',
+  'bool.c',
+  'cash.c',
+  'char.c',
+  'cryptohashfuncs.c',
+  'date.c',
+  'datetime.c',
+  'datum.c',
+  'dbsize.c',
+  'domains.c',
+  'encode.c',
+  'enum.c',
+  'expandeddatum.c',
+  'expandedrecord.c',
+  'float.c',
+  'format_type.c',
+  'formatting.c',
+  'genfile.c',
+  'geo_ops.c',
+  'geo_selfuncs.c',
+  'geo_spgist.c',
+  'inet_cidr_ntop.c',
+  'inet_net_pton.c',
+  'int.c',
+  'int8.c',
+  'json.c',
+  'jsonb.c',
+  'jsonb_gin.c',
+  'jsonb_op.c',
+  'jsonb_util.c',
+  'jsonfuncs.c',
+  'jsonbsubs.c',
+  'jsonpath.c',
+  'jsonpath_exec.c',
+  'like.c',
+  'like_support.c',
+  'lockfuncs.c',
+  'mac.c',
+  'mac8.c',
+  'mcxtfuncs.c',
+  'misc.c',
+  'multirangetypes.c',
+  'multirangetypes_selfuncs.c',
+  'name.c',
+  'network.c',
+  'network_gist.c',
+  'network_selfuncs.c',
+  'network_spgist.c',
+  'numeric.c',
+  'numutils.c',
+  'oid.c',
+  'oracle_compat.c',
+  'orderedsetaggs.c',
+  'partitionfuncs.c',
+  'pg_locale.c',
+  'pg_lsn.c',
+  'pg_upgrade_support.c',
+  'pgstatfuncs.c',
+  'pseudotypes.c',
+  'quote.c',
+  'rangetypes.c',
+  'rangetypes_gist.c',
+  'rangetypes_selfuncs.c',
+  'rangetypes_spgist.c',
+  'rangetypes_typanalyze.c',
+  'regexp.c',
+  'regproc.c',
+  'ri_triggers.c',
+  'rowtypes.c',
+  'ruleutils.c',
+  'selfuncs.c',
+  'tid.c',
+  'timestamp.c',
+  'trigfuncs.c',
+  'tsginidx.c',
+  'tsgistidx.c',
+  'tsquery.c',
+  'tsquery_cleanup.c',
+  'tsquery_gist.c',
+  'tsquery_op.c',
+  'tsquery_rewrite.c',
+  'tsquery_util.c',
+  'tsrank.c',
+  'tsvector.c',
+  'tsvector_op.c',
+  'tsvector_parser.c',
+  'uuid.c',
+  'varbit.c',
+  'varchar.c',
+  'varlena.c',
+  'version.c',
+  'windowfuncs.c',
+  'xid.c',
+  'xid8funcs.c',
+  'xml.c',
+)
+
+
+jsonpath_scan = custom_target('jsonpath_scan',
+  input: ['jsonpath_scan.l'],
+  output: ['jsonpath_scan.c'],
+  command: [flex, '-CF', '-p', '-p', '-o', '@OUTPUT@', '@INPUT@'])
+
+# jsonpath_scan is compiled as part of jsonpath_gram
+generated_backend_sources += custom_target('jsonpath_parse',
+  input: ['jsonpath_gram.y', jsonpath_scan[0]],
+  output: ['jsonpath_gram.c'],
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
diff --git a/src/backend/utils/cache/meson.build b/src/backend/utils/cache/meson.build
new file mode 100644
index 00000000000..92972db52ad
--- /dev/null
+++ b/src/backend/utils/cache/meson.build
@@ -0,0 +1,16 @@
+backend_sources += files(
+  'attoptcache.c',
+  'catcache.c',
+  'evtcache.c',
+  'inval.c',
+  'lsyscache.c',
+  'partcache.c',
+  'plancache.c',
+  'relcache.c',
+  'relfilenodemap.c',
+  'relmapper.c',
+  'spccache.c',
+  'syscache.c',
+  'ts_cache.c',
+  'typcache.c',
+)
diff --git a/src/backend/utils/error/meson.build b/src/backend/utils/error/meson.build
new file mode 100644
index 00000000000..ff0ae388263
--- /dev/null
+++ b/src/backend/utils/error/meson.build
@@ -0,0 +1,4 @@
+backend_sources += files(
+  'assert.c',
+  'elog.c',
+  )
diff --git a/src/backend/utils/fmgr/meson.build b/src/backend/utils/fmgr/meson.build
new file mode 100644
index 00000000000..e545b424fd2
--- /dev/null
+++ b/src/backend/utils/fmgr/meson.build
@@ -0,0 +1,8 @@
+backend_sources += files(
+  'dfmgr.c',
+  'fmgr.c',
+  'funcapi.c',
+)
+
+# fmgrtab.c
+generated_backend_sources += fmgrtab_target[2]
diff --git a/src/backend/utils/hash/meson.build b/src/backend/utils/hash/meson.build
new file mode 100644
index 00000000000..242e2f0ecdf
--- /dev/null
+++ b/src/backend/utils/hash/meson.build
@@ -0,0 +1,4 @@
+backend_sources += files(
+  'dynahash.c',
+  'pg_crc.c'
+)
diff --git a/src/backend/utils/init/meson.build b/src/backend/utils/init/meson.build
new file mode 100644
index 00000000000..ec9d72c3df1
--- /dev/null
+++ b/src/backend/utils/init/meson.build
@@ -0,0 +1,4 @@
+backend_sources += files(
+  'globals.c',
+  'miscinit.c',
+  'postinit.c')
diff --git a/src/backend/utils/mb/conversion_procs/meson.build b/src/backend/utils/mb/conversion_procs/meson.build
new file mode 100644
index 00000000000..b84a78b6318
--- /dev/null
+++ b/src/backend/utils/mb/conversion_procs/meson.build
@@ -0,0 +1,38 @@
+encodings = {
+  'cyrillic_and_mic': ['cyrillic_and_mic/cyrillic_and_mic.c'],
+  'euc2004_sjis2004': ['euc2004_sjis2004/euc2004_sjis2004.c'],
+  'euc_cn_and_mic': ['euc_cn_and_mic/euc_cn_and_mic.c'],
+  'euc_jp_and_sjis': ['euc_jp_and_sjis/euc_jp_and_sjis.c'],
+  'euc_kr_and_mic': ['euc_kr_and_mic/euc_kr_and_mic.c'],
+  'euc_tw_and_big5': [
+    'euc_tw_and_big5/euc_tw_and_big5.c',
+    'euc_tw_and_big5/big5.c',
+  ],
+  'latin2_and_win1250': ['latin2_and_win1250/latin2_and_win1250.c'],
+  'latin_and_mic': ['latin_and_mic/latin_and_mic.c'],
+  'utf8_and_big5': ['utf8_and_big5/utf8_and_big5.c'],
+  'utf8_and_cyrillic': ['utf8_and_cyrillic/utf8_and_cyrillic.c'],
+  'utf8_and_euc2004': ['utf8_and_euc2004/utf8_and_euc2004.c'],
+  'utf8_and_euc_cn': ['utf8_and_euc_cn/utf8_and_euc_cn.c'],
+  'utf8_and_euc_jp': ['utf8_and_euc_jp/utf8_and_euc_jp.c'],
+  'utf8_and_euc_kr': ['utf8_and_euc_kr/utf8_and_euc_kr.c'],
+  'utf8_and_euc_tw': ['utf8_and_euc_tw/utf8_and_euc_tw.c'],
+  'utf8_and_gb18030': ['utf8_and_gb18030/utf8_and_gb18030.c'],
+  'utf8_and_gbk': ['utf8_and_gbk/utf8_and_gbk.c'],
+  'utf8_and_iso8859': ['utf8_and_iso8859/utf8_and_iso8859.c'],
+  'utf8_and_iso8859_1': ['utf8_and_iso8859_1/utf8_and_iso8859_1.c'],
+  'utf8_and_johab': ['utf8_and_johab/utf8_and_johab.c'],
+  'utf8_and_sjis': ['utf8_and_sjis/utf8_and_sjis.c'],
+  'utf8_and_sjis2004': ['utf8_and_sjis2004/utf8_and_sjis2004.c'],
+  'utf8_and_uhc': ['utf8_and_uhc/utf8_and_uhc.c'],
+  'utf8_and_win': ['utf8_and_win/utf8_and_win.c'],
+}
+
+foreach encoding, sources : encodings
+  backend_targets += shared_module(encoding,
+    sources,
+    kwargs: pg_mod_args + {
+    }
+  )
+
+endforeach
diff --git a/src/backend/utils/mb/meson.build b/src/backend/utils/mb/meson.build
new file mode 100644
index 00000000000..39e45638db0
--- /dev/null
+++ b/src/backend/utils/mb/meson.build
@@ -0,0 +1,9 @@
+backend_sources += files(
+  'conv.c',
+  'mbutils.c',
+  'stringinfo_mb.c',
+  'wstrcmp.c',
+  'wstrncmp.c',
+)
+
+# Note we only enter conversion_procs once the backend build is defined
diff --git a/src/backend/utils/meson.build b/src/backend/utils/meson.build
new file mode 100644
index 00000000000..afb1c0346ba
--- /dev/null
+++ b/src/backend/utils/meson.build
@@ -0,0 +1,13 @@
+subdir('activity')
+subdir('adt')
+subdir('cache')
+subdir('error')
+subdir('fmgr')
+subdir('hash')
+subdir('init')
+subdir('mb')
+subdir('misc')
+subdir('mmgr')
+subdir('resowner')
+subdir('sort')
+subdir('time')
diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build
new file mode 100644
index 00000000000..5274c8aa1ae
--- /dev/null
+++ b/src/backend/utils/misc/meson.build
@@ -0,0 +1,28 @@
+backend_sources += files(
+  'help_config.c',
+  'pg_config.c',
+  'pg_controldata.c',
+  'pg_rusage.c',
+  'ps_status.c',
+  'queryenvironment.c',
+  'queryjumble.c',
+  'rls.c',
+  'sampling.c',
+  'superuser.c',
+  'timeout.c',
+  'tzparser.c',
+  'guc.c',
+)
+
+# guc-file.c.h is compiled as part of guc.c
+guc_scan = custom_target('guc_scan',
+  input: ['guc-file.l'],
+  output: ['guc-file.c.h'],
+  command: [flex, '-CF', '-p', '-p', '-o', '@OUTPUT@', '@INPUT@'])
+
+generated_backend_sources += guc_scan
+
+backend_build_deps += declare_dependency(sources: [guc_scan],
+  include_directories: include_directories('.'))
+
+install_data('postgresql.conf.sample', install_dir: 'share/')
diff --git a/src/backend/utils/mmgr/meson.build b/src/backend/utils/mmgr/meson.build
new file mode 100644
index 00000000000..641bb181ba1
--- /dev/null
+++ b/src/backend/utils/mmgr/meson.build
@@ -0,0 +1,10 @@
+backend_sources += files(
+  'aset.c',
+  'dsa.c',
+  'freepage.c',
+  'generation.c',
+  'mcxt.c',
+  'memdebug.c',
+  'portalmem.c',
+  'slab.c',
+)
diff --git a/src/backend/utils/mmgr/proxy.c b/src/backend/utils/mmgr/proxy.c
new file mode 100644
index 00000000000..6e68fa9a557
--- /dev/null
+++ b/src/backend/utils/mmgr/proxy.c
@@ -0,0 +1,217 @@
+#include "postgres.h"
+
+#include "utils/memdebug.h"
+#include "utils/memutils.h"
+#include "lib/ilist.h"
+
+typedef struct ProxyContext
+{
+	MemoryContextData header;	/* Standard memory-context fields */
+	MemoryContext alloc_parent;
+	dlist_head allocations;
+} ProxyContext;
+
+typedef struct ProxyChunk
+{
+	dlist_node node;
+	void *context;
+} ProxyChunk;
+
+static void *ProxyContextAlloc(MemoryContext context, Size size);
+static void ProxyContextFree(MemoryContext context, void *pointer);
+static void *ProxyContextRealloc(MemoryContext context, void *pointer, Size size);
+static void ProxyContextReset(MemoryContext context);
+static void ProxyContextDelete(MemoryContext context);
+static Size ProxyContextGetChunkSpace(MemoryContext context, void *pointer);
+static bool ProxyContextIsEmpty(MemoryContext context);
+static void ProxyContextStats(MemoryContext context,
+						  MemoryStatsPrintFunc printfunc, void *passthru,
+						  MemoryContextCounters *totals);
+
+#ifdef MEMORY_CONTEXT_CHECKING
+static void ProxyContextCheck(MemoryContext context);
+#endif
+
+/*
+ * This is the virtual function table for ProxyContext contexts.
+ */
+static const MemoryContextMethods ProxyContextMethods = {
+	ProxyContextAlloc,
+	ProxyContextFree,
+	ProxyContextRealloc,
+	ProxyContextReset,
+	ProxyContextDelete,
+	ProxyContextGetChunkSpace,
+	ProxyContextIsEmpty,
+	ProxyContextStats
+#ifdef MEMORY_CONTEXT_CHECKING
+	,ProxyContextCheck
+#endif
+};
+
+MemoryContext
+ProxyContextCreate(MemoryContext parent,
+				   const char *name)
+{
+	ProxyContext *proxy;
+	MemoryContext alloc_parent;
+
+	proxy = (ProxyContext *) malloc(sizeof(ProxyContext));
+	if (proxy == NULL)
+	{
+		MemoryContextStats(TopMemoryContext);
+		ereport(ERROR,
+				(errcode(ERRCODE_OUT_OF_MEMORY),
+				 errmsg("out of memory"),
+				 errdetail("Failed while creating memory context \"%s\".",
+						   name)));
+	}
+
+	/* find node we can actually allocate in */
+	alloc_parent = parent;
+	while (alloc_parent != NULL && IsA(alloc_parent, ProxyContext))
+		alloc_parent = alloc_parent->parent;
+	if (alloc_parent == NULL)
+		elog(ERROR, "can't proxy forever");
+	proxy->alloc_parent = parent;
+
+	dlist_init(&proxy->allocations);
+
+	/* Finally, do the type-independent part of context creation */
+	MemoryContextCreate((MemoryContext) proxy,
+						T_ProxyContext,
+						&ProxyContextMethods,
+						parent,
+						name);
+
+	return (MemoryContext) proxy;
+}
+
+static void *
+ProxyContextAlloc(MemoryContext context, Size size)
+{
+	ProxyContext *proxy = castNode(ProxyContext, context);
+	ProxyChunk *chunk;
+	Size alloc_size;
+
+	alloc_size = size + MAXALIGN(sizeof(ProxyChunk));
+
+	chunk = MemoryContextAlloc(proxy->alloc_parent, alloc_size);
+
+	dlist_push_tail(&proxy->allocations, &chunk->node);
+	chunk->context = context;
+
+	return (char *) chunk + MAXALIGN(sizeof(ProxyChunk));
+}
+
+static void
+ProxyContextFree(MemoryContext context, void *pointer)
+{
+	ProxyChunk *chunk = (ProxyChunk *) ((char *) pointer - MAXALIGN(sizeof(ProxyChunk)));
+
+	dlist_delete(&chunk->node);
+
+	pfree(chunk);
+}
+
+static void *
+ProxyContextRealloc(MemoryContext context, void *pointer, Size size)
+{
+	ProxyContext *proxy = castNode(ProxyContext, context);
+	ProxyChunk *chunk = (ProxyChunk *) ((char *) pointer - MAXALIGN(sizeof(ProxyChunk)));
+
+	dlist_delete(&chunk->node);
+
+	chunk =repalloc ((char *) chunk, size + MAXALIGN(sizeof(ProxyChunk)));
+
+	dlist_push_tail(&proxy->allocations, &chunk->node);
+	chunk->context = context;
+
+	return (char *) chunk + MAXALIGN(sizeof(ProxyChunk));
+}
+
+static void
+ProxyContextReset(MemoryContext context)
+{
+	ProxyContext *proxy = castNode(ProxyContext, context);
+	dlist_mutable_iter iter;
+
+	dlist_foreach_modify(iter, &proxy->allocations)
+	{
+		ProxyChunk *ptr = dlist_container(ProxyChunk, node, iter.cur);
+
+		dlist_delete(iter.cur);
+		pfree(ptr);
+	}
+}
+
+static void
+ProxyContextDelete(MemoryContext context)
+{
+	ProxyContextReset(context);
+	free(context);
+}
+
+static Size
+ProxyContextGetChunkSpace(MemoryContext context, void *pointer)
+{
+	ProxyChunk *chunk = (ProxyChunk *) ((char *) pointer - MAXALIGN(sizeof(ProxyChunk)));
+
+	return GetMemoryChunkSpace(chunk);
+}
+
+static bool
+ProxyContextIsEmpty(MemoryContext context)
+{
+	ProxyContext *proxy = castNode(ProxyContext, context);
+
+	return dlist_is_empty(&proxy->allocations);
+}
+
+static void
+ProxyContextStats(MemoryContext context,
+				  MemoryStatsPrintFunc printfunc, void *passthru,
+				  MemoryContextCounters *totals)
+{
+	ProxyContext *proxy = castNode(ProxyContext, context);
+	Size		nblocks = 0;
+	Size		freechunks = 0;
+	Size		totalspace = 0;
+	Size		freespace = 0;
+	Size		chunks = 0;
+	dlist_iter iter;
+
+	dlist_foreach(iter, &proxy->allocations)
+	{
+		ProxyChunk *chunk = dlist_container(ProxyChunk, node, iter.cur);
+
+		totalspace += GetMemoryChunkSpace((void *) chunk);
+		chunks++;
+	}
+
+	if (printfunc)
+	{
+		char		stats_string[200];
+
+		snprintf(stats_string, sizeof(stats_string),
+				 "%zu chunks proxied to parent, totaling %zu bytes",
+				 chunks, totalspace);
+		printfunc(context, passthru, stats_string);
+	}
+
+	if (totals)
+	{
+		totals->nblocks += nblocks;
+		totals->freechunks += freechunks;
+		totals->totalspace += totalspace;
+		totals->freespace += freespace;
+	}
+}
+
+#ifdef MEMORY_CONTEXT_CHECKING
+static void
+ProxyContextCheck(MemoryContext context)
+{
+	/* FIXME */
+}
+#endif
diff --git a/src/backend/utils/resowner/meson.build b/src/backend/utils/resowner/meson.build
new file mode 100644
index 00000000000..d30891ca027
--- /dev/null
+++ b/src/backend/utils/resowner/meson.build
@@ -0,0 +1,3 @@
+backend_sources += files(
+  'resowner.c'
+)
diff --git a/src/backend/utils/sort/meson.build b/src/backend/utils/sort/meson.build
new file mode 100644
index 00000000000..b626bdc9d96
--- /dev/null
+++ b/src/backend/utils/sort/meson.build
@@ -0,0 +1,7 @@
+backend_sources += files(
+  'logtape.c',
+  'sharedtuplestore.c',
+  'sortsupport.c',
+  'tuplesort.c',
+  'tuplestore.c',
+)
diff --git a/src/backend/utils/time/meson.build b/src/backend/utils/time/meson.build
new file mode 100644
index 00000000000..6fff8792bb0
--- /dev/null
+++ b/src/backend/utils/time/meson.build
@@ -0,0 +1,4 @@
+backend_sources += files(
+  'combocid.c',
+  'snapmgr.c',
+)
diff --git a/src/bin/initdb/meson.build b/src/bin/initdb/meson.build
new file mode 100644
index 00000000000..52f679e3116
--- /dev/null
+++ b/src/bin/initdb/meson.build
@@ -0,0 +1,24 @@
+initdb_sources = files(
+  'findtimezone.c',
+  'initdb.c'
+)
+
+initdb_sources += timezone_localtime_source
+
+#fixme: reimplement libpq_pgport logic
+
+executable('initdb',
+  initdb_sources,
+  include_directories: [timezone_inc],
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'initdb',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_initdb.pl'
+  ]
+}
diff --git a/src/bin/meson.build b/src/bin/meson.build
new file mode 100644
index 00000000000..3718fd0759a
--- /dev/null
+++ b/src/bin/meson.build
@@ -0,0 +1,20 @@
+subdir('initdb')
+subdir('pg_amcheck')
+subdir('pg_archivecleanup')
+subdir('pg_basebackup')
+subdir('pg_checksums')
+subdir('pg_config')
+subdir('pg_controldata')
+subdir('pg_ctl')
+subdir('pg_dump')
+subdir('pg_resetwal')
+subdir('pg_rewind')
+subdir('pg_test_fsync')
+subdir('pg_test_timing')
+subdir('pg_upgrade')
+subdir('pg_verifybackup')
+subdir('pg_waldump')
+subdir('pgbench')
+#TODO subdir('pgevent')
+subdir('psql')
+subdir('scripts')
diff --git a/src/bin/pg_amcheck/meson.build b/src/bin/pg_amcheck/meson.build
new file mode 100644
index 00000000000..69eaef8f141
--- /dev/null
+++ b/src/bin/pg_amcheck/meson.build
@@ -0,0 +1,22 @@
+pg_amcheck_sources = files(
+  'pg_amcheck.c'
+)
+
+pg_amcheck = executable('pg_amcheck',
+  pg_amcheck_sources,
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_amcheck',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+    't/002_nonesuch.pl',
+    't/003_check.pl',
+    't/004_verify_heapam.pl',
+    't/005_opclass_damage.pl',
+  ]
+}
diff --git a/src/bin/pg_archivecleanup/meson.build b/src/bin/pg_archivecleanup/meson.build
new file mode 100644
index 00000000000..27742fafab7
--- /dev/null
+++ b/src/bin/pg_archivecleanup/meson.build
@@ -0,0 +1,14 @@
+pg_archivecleanup = executable('pg_archivecleanup',
+  ['pg_archivecleanup.c'],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_archivecleanup',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/010_pg_archivecleanup.pl'
+  ]
+}
diff --git a/src/bin/pg_basebackup/meson.build b/src/bin/pg_basebackup/meson.build
new file mode 100644
index 00000000000..a629b8b02f5
--- /dev/null
+++ b/src/bin/pg_basebackup/meson.build
@@ -0,0 +1,44 @@
+common_sources = files(
+  'receivelog.c',
+  'streamutil.c',
+  'walmethods.c',
+)
+
+pg_basebackup_common = static_library('pg_basebackup_common',
+  common_sources,
+  dependencies: [frontend_code, libpq, zlib],
+  kwargs: internal_lib_args,
+)
+
+executable('pg_basebackup',
+  'pg_basebackup.c',
+  link_with: [pg_basebackup_common],
+  dependencies: [frontend_code, libpq, zlib],
+  kwargs: default_bin_args,
+)
+
+executable('pg_receivewal',
+  'pg_receivewal.c',
+  link_with: [pg_basebackup_common],
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+executable('pg_recvlogical',
+  'pg_recvlogical.c',
+  link_with: [pg_basebackup_common],
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name' : 'pg_basebackup',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'env': {'GZIP_PROGRAM': gzip.path(), 'TAR': tar.path()},
+  'tests': [
+    't/010_pg_basebackup.pl',
+    't/020_pg_receivewal.pl',
+    't/030_pg_recvlogical.pl',
+  ]
+}
diff --git a/src/bin/pg_checksums/meson.build b/src/bin/pg_checksums/meson.build
new file mode 100644
index 00000000000..bbf9582b904
--- /dev/null
+++ b/src/bin/pg_checksums/meson.build
@@ -0,0 +1,16 @@
+executable('pg_checksums',
+  ['pg_checksums.c'],
+  include_directories: [timezone_inc],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_checksums',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+    't/002_actions.pl'
+  ]
+}
diff --git a/src/bin/pg_config/meson.build b/src/bin/pg_config/meson.build
new file mode 100644
index 00000000000..df0eb13f636
--- /dev/null
+++ b/src/bin/pg_config/meson.build
@@ -0,0 +1,14 @@
+executable('pg_config',
+  ['pg_config.c'],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_config',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_pg_config.pl',
+  ]
+}
diff --git a/src/bin/pg_controldata/meson.build b/src/bin/pg_controldata/meson.build
new file mode 100644
index 00000000000..fa6057afa54
--- /dev/null
+++ b/src/bin/pg_controldata/meson.build
@@ -0,0 +1,14 @@
+executable('pg_controldata',
+  ['pg_controldata.c'],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_controldata',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_pg_controldata.pl'
+  ]
+}
diff --git a/src/bin/pg_ctl/meson.build b/src/bin/pg_ctl/meson.build
new file mode 100644
index 00000000000..ac0d4f18192
--- /dev/null
+++ b/src/bin/pg_ctl/meson.build
@@ -0,0 +1,17 @@
+executable('pg_ctl',
+  ['pg_ctl.c'],
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_ctl',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_start_stop.pl',
+    't/002_status.pl',
+    't/003_promote.pl',
+    't/004_logrotate.pl'
+  ]
+}
diff --git a/src/bin/pg_dump/meson.build b/src/bin/pg_dump/meson.build
new file mode 100644
index 00000000000..ce5ef11eaeb
--- /dev/null
+++ b/src/bin/pg_dump/meson.build
@@ -0,0 +1,69 @@
+pg_dump_common_sources = files(
+  'compress_io.c',
+  'dumputils.c',
+  'parallel.c',
+  'pg_backup_archiver.c',
+  'pg_backup_custom.c',
+  'pg_backup_db.c',
+  'pg_backup_directory.c',
+  'pg_backup_null.c',
+  'pg_backup_tar.c',
+  'pg_backup_utils.c',
+)
+
+pg_dump_common = static_library('pg_dump_common',
+  pg_dump_common_sources,
+  c_pch: '../../include/pch/c_pch.h',
+  dependencies: [frontend_code, libpq, zlib],
+  kwargs: internal_lib_args,
+)
+
+pg_dump_sources = files(
+  'pg_dump.c',
+  'common.c',
+  'pg_dump_sort.c',
+)
+
+executable('pg_dump',
+  pg_dump_sources,
+  link_with: [pg_dump_common],
+  dependencies: [frontend_code, libpq, zlib],
+  kwargs: default_bin_args,
+)
+
+
+pg_dumpall_sources = files(
+  'pg_dumpall.c',
+)
+
+executable('pg_dumpall',
+  pg_dumpall_sources,
+  link_with: [pg_dump_common],
+  dependencies: [frontend_code, libpq, zlib],
+  kwargs: default_bin_args,
+)
+
+
+pg_restore_sources = files(
+  'pg_restore.c',
+)
+
+executable('pg_restore',
+  pg_restore_sources,
+  link_with: [pg_dump_common],
+  dependencies: [frontend_code, libpq, zlib],
+  kwargs: default_bin_args,
+)
+
+
+tap_tests += {
+  'name': 'pg_dump',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+    't/002_pg_dump.pl',
+    't/003_pg_dump_with_server.pl',
+    't/010_dump_connstr.pl',
+  ]
+}
diff --git a/src/bin/pg_resetwal/meson.build b/src/bin/pg_resetwal/meson.build
new file mode 100644
index 00000000000..7450c0f6432
--- /dev/null
+++ b/src/bin/pg_resetwal/meson.build
@@ -0,0 +1,15 @@
+executable('pg_resetwal',
+  files('pg_resetwal.c'),
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_resetwal',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+    't/002_corrupted.pl'
+  ]
+}
diff --git a/src/bin/pg_rewind/meson.build b/src/bin/pg_rewind/meson.build
new file mode 100644
index 00000000000..c7c59e9e523
--- /dev/null
+++ b/src/bin/pg_rewind/meson.build
@@ -0,0 +1,34 @@
+pg_rewind_sources = files(
+  'datapagemap.c',
+  'file_ops.c',
+  'filemap.c',
+  'libpq_source.c',
+  'local_source.c',
+  'parsexlog.c',
+  'pg_rewind.c',
+  'timeline.c',
+  '../../backend/access/transam/xlogreader.c',
+)
+
+pg_rewind = executable('pg_rewind',
+  pg_rewind_sources,
+  dependencies: [frontend_code, libpq, lz4],
+  kwargs: default_bin_args,
+)
+
+
+tap_tests += {
+  'name': 'pg_rewind',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+    't/002_databases.pl',
+    't/003_extrafiles.pl',
+    't/004_pg_xlog_symlink.pl',
+    't/005_same_timeline.pl',
+    't/006_options.pl',
+    't/007_standby_source.pl',
+    't/008_min_recovery_point.pl',
+  ]
+}
diff --git a/src/bin/pg_test_fsync/meson.build b/src/bin/pg_test_fsync/meson.build
new file mode 100644
index 00000000000..527be88d125
--- /dev/null
+++ b/src/bin/pg_test_fsync/meson.build
@@ -0,0 +1,14 @@
+executable('pg_test_fsync',
+  ['pg_test_fsync.c'],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name' : 'pg_test_fsync',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests' :[
+    't/001_basic.pl',
+  ]
+}
diff --git a/src/bin/pg_test_timing/meson.build b/src/bin/pg_test_timing/meson.build
new file mode 100644
index 00000000000..c74577df493
--- /dev/null
+++ b/src/bin/pg_test_timing/meson.build
@@ -0,0 +1,14 @@
+pg_test_timing = executable('pg_test_timing',
+  ['pg_test_timing.c'],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_test_timing',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl'
+  ]
+}
diff --git a/src/bin/pg_upgrade/meson.build b/src/bin/pg_upgrade/meson.build
new file mode 100644
index 00000000000..88d0e03446b
--- /dev/null
+++ b/src/bin/pg_upgrade/meson.build
@@ -0,0 +1,26 @@
+pg_upgrade_sources = files(
+  'check.c',
+  'controldata.c',
+  'dump.c',
+  'exec.c',
+  'file.c',
+  'function.c',
+  'info.c',
+  'option.c',
+  'parallel.c',
+  'pg_upgrade.c',
+  'relfilenode.c',
+  'server.c',
+  'tablespace.c',
+  'util.c',
+  'version.c',
+)
+
+pg_upgrade = executable('pg_upgrade',
+  pg_upgrade_sources,
+  c_pch: '../../include/pch/c_pch.h',
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+# FIXME: add test
diff --git a/src/bin/pg_verifybackup/meson.build b/src/bin/pg_verifybackup/meson.build
new file mode 100644
index 00000000000..c7039ddcc49
--- /dev/null
+++ b/src/bin/pg_verifybackup/meson.build
@@ -0,0 +1,25 @@
+pg_verifybackup_sources = files(
+  'parse_manifest.c',
+  'pg_verifybackup.c'
+)
+
+pg_verifybackup = executable('pg_verifybackup',
+  pg_verifybackup_sources,
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_verifybackup',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+    't/002_algorithm.pl',
+    't/003_corruption.pl',
+    't/004_options.pl',
+    't/005_bad_manifest.pl',
+    't/006_encoding.pl',
+    't/007_wal.pl',
+  ]
+}
diff --git a/src/bin/pg_waldump/meson.build b/src/bin/pg_waldump/meson.build
new file mode 100644
index 00000000000..f89139f89f5
--- /dev/null
+++ b/src/bin/pg_waldump/meson.build
@@ -0,0 +1,23 @@
+pg_waldump_sources = files(
+  'compat.c',
+  'pg_waldump.c',
+  'rmgrdesc.c',
+)
+
+pg_waldump_sources += rmgr_desc_sources
+pg_waldump_sources += xlogreader_sources
+
+pg_waldump = executable('pg_waldump',
+  pg_waldump_sources,
+  dependencies: [frontend_code, lz4],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'pg_waldump',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_basic.pl',
+  ]
+}
diff --git a/src/bin/pgbench/meson.build b/src/bin/pgbench/meson.build
new file mode 100644
index 00000000000..5c4a778ff32
--- /dev/null
+++ b/src/bin/pgbench/meson.build
@@ -0,0 +1,38 @@
+pgbench_sources = files(
+  'pgbench.c',
+)
+
+# exprscan is compiled as part ofexprparse. The ordering is enforced by making
+# the generation of grammar depend on the scanner generation. That's
+# unnecessarily strict, but overall harmless.
+
+exprscan = custom_target('exprscan',
+  input : files('exprscan.l'),
+  output : ['exprscan.c'],
+  command : [flex, '-CF', '-p', '-p', '-o', '@OUTPUT0@', '@INPUT@']
+)
+
+exprparse = custom_target('exprparse',
+  input: 'exprparse.y',
+  output: 'exprparse.c',
+  depends: exprscan,
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
+pgbench_sources += exprparse
+
+executable('pgbench',
+  pgbench_sources,
+  dependencies: [frontend_code, libpq, thread_dep],
+  include_directories: include_directories('.'),
+  kwargs: default_bin_args,
+)
+
+
+tap_tests += {
+  'name' : 'pgbench',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests' :[
+    't/001_pgbench_with_server.pl',
+    't/002_pgbench_no_server.pl'
+  ]
+}
diff --git a/src/bin/pgevent/meson.build b/src/bin/pgevent/meson.build
new file mode 100644
index 00000000000..9b4642a69d0
--- /dev/null
+++ b/src/bin/pgevent/meson.build
@@ -0,0 +1 @@
+# FIXME: implement when I can test
diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build
new file mode 100644
index 00000000000..98921f801d7
--- /dev/null
+++ b/src/bin/psql/meson.build
@@ -0,0 +1,46 @@
+psql_sources = files(
+  'command.c',
+  'common.c',
+  'copy.c',
+  'crosstabview.c',
+  'describe.c',
+  'help.c',
+  'input.c',
+  'large_obj.c',
+  'mainloop.c',
+  'prompt.c',
+  'startup.c',
+  'stringutils.c',
+  'tab-complete.c',
+  'variables.c',
+)
+
+psql_sources += custom_target('psqlscanslash',
+  input: ['psqlscanslash.l'],
+  output: ['psqlscanslash.c'],
+  command: [flex, '-CFe', '-p', '-p', '-o', '@OUTPUT@', '@INPUT@'])
+
+psql_sources += custom_target('psql_help',
+  input: ['create_help.pl'],
+  output: ['sql_help.c', 'sql_help.h'],
+  depfile: 'sql_help.dep',
+  command: [perl, '@INPUT0@', '@SOURCE_ROOT@/doc/src/sgml/ref', '@OUTDIR@', 'sql_help'])
+
+executable('psql',
+  psql_sources,
+  c_pch: '../../include/pch/c_pch.h',
+  include_directories: include_directories('.'),
+  dependencies : [frontend_code, libpq, readline],
+  kwargs: default_bin_args,
+)
+
+tap_tests += {
+  'name': 'psql',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'env': {'with_readline': readline.found() ? 'yes' : 'no'},
+  'tests': [
+    't/010_tab_completion.pl',
+    't/020_cancel.pl',
+  ],
+}
diff --git a/src/bin/scripts/meson.build b/src/bin/scripts/meson.build
new file mode 100644
index 00000000000..547a53500a4
--- /dev/null
+++ b/src/bin/scripts/meson.build
@@ -0,0 +1,46 @@
+scripts_common = static_library('scripts_common',
+  files('common.c'),
+  dependencies: [frontend_code, libpq],
+  kwargs: internal_lib_args,
+)
+
+binaries = [
+  'createdb',
+  'dropdb',
+  'createuser',
+  'dropuser',
+  'clusterdb',
+  'vacuumdb',
+  'reindexdb',
+  'pg_isready',
+]
+
+foreach binary : binaries
+  executable(binary,
+    files(binary + '.c'),
+    link_with: [scripts_common],
+    dependencies: [frontend_code, libpq],
+    kwargs: default_bin_args,
+  )
+endforeach
+
+tap_tests += {
+  'name': 'scripts',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/010_clusterdb.pl',
+    't/011_clusterdb_all.pl',
+    't/020_createdb.pl',
+    't/040_createuser.pl',
+    't/050_dropdb.pl',
+    't/070_dropuser.pl',
+    't/080_pg_isready.pl',
+    't/090_reindexdb.pl',
+    't/091_reindexdb_all.pl',
+    't/100_vacuumdb.pl',
+    't/101_vacuumdb_all.pl',
+    't/102_vacuumdb_stages.pl',
+    't/200_connstr.pl',
+  ]
+}
diff --git a/src/common/meson.build b/src/common/meson.build
new file mode 100644
index 00000000000..6be70b0c5b3
--- /dev/null
+++ b/src/common/meson.build
@@ -0,0 +1,140 @@
+common_sources = files(
+  'archive.c',
+  'base64.c',
+  'checksum_helper.c',
+  'config_info.c',
+  'controldata_utils.c',
+  'encnames.c',
+  'exec.c',
+  'file_perm.c',
+  'file_utils.c',
+  'hashfn.c',
+  'ip.c',
+  'jsonapi.c',
+  'keywords.c',
+  'kwlookup.c',
+  'link-canary.c',
+  'md5_common.c',
+  'pg_get_line.c',
+  'pg_lzcompress.c',
+  'pgfnames.c',
+  'psprintf.c',
+  'relpath.c',
+  'rmtree.c',
+  'saslprep.c',
+  'scram-common.c',
+  'string.c',
+  'stringinfo.c',
+  'unicode_norm.c',
+  'username.c',
+  'wait_error.c',
+  'wchar.c',
+)
+
+# FIXME: implement openssl
+if ssl.found()
+  common_sources += files(
+    'cryptohash_openssl.c',
+    'hmac_openssl.c',
+    'protocol_openssl.c',
+  )
+else
+  common_sources += files(
+    'cryptohash.c',
+    'hmac.c',
+    'md5.c',
+    'sha1.c',
+    'sha2.c',
+  )
+endif
+
+common_sources += custom_target('kwlist',
+  input: files('../include/parser/kwlist.h'),
+  output: 'kwlist_d.h',
+  command: [perl, '-I', '@SOURCE_ROOT@/src/tools', files('../tools/gen_keywordlist.pl'),
+      '--extern', '--output', '@OUTDIR@', '@INPUT@'])
+
+
+# The code imported from Ryu gets a pass on declaration-after-statement,
+# in order to keep it more closely aligned with its upstream.
+ryu_sources = files(
+  'd2s.c',
+  'f2s.c',
+)
+ryu_cflags = []
+
+if using_declaration_after_statement_warning
+  ryu_cflags += ['-Wno-declaration-after-statement']
+endif
+
+ryu_srv = static_library('ryu_srv',
+  ryu_sources,
+  dependencies: [backend_port_code],
+  c_args: ryu_cflags,
+  kwargs: internal_lib_args
+)
+
+ryu_shlib = static_library('ryu_shlib',
+  ryu_sources,
+  dependencies: [frontend_port_code],
+  c_args: ryu_cflags,
+  pic: true,
+  kwargs: internal_lib_args
+)
+
+ryu_static = static_library('ryu_static',
+  ryu_sources,
+  dependencies: [frontend_port_code],
+  c_args: ryu_cflags,
+  kwargs: internal_lib_args
+)
+
+
+# A few files are currently only built for frontend, not server
+# (Mkvcbuild.pm has a copy of this list, too).  logging.c is excluded
+# from OBJS_FRONTEND_SHLIB (shared library) as a matter of policy,
+# because it is not appropriate for general purpose libraries such
+# as libpq to report errors directly.
+
+common_sources_frontend_shlib = common_sources
+common_sources_frontend_shlib += files(
+  'fe_memutils.c',
+  'restricted_token.c',
+  'sprompt.c',
+)
+
+common_sources_frontend_static = common_sources_frontend_shlib
+common_sources_frontend_static += files(
+  'logging.c',
+)
+
+# XXX: in most environments we could probably link_whole pgcommon_shlib
+# against pgcommon_static, instead of compiling twice.
+
+common_srv = static_library('pgcommon_srv',
+  common_sources,
+  c_pch: '../include/pch/c_pch.h',
+  link_with: [ryu_srv],
+  dependencies: [backend_common_code, ssl],
+  include_directories: include_directories('.'),
+  kwargs: internal_lib_args,
+)
+
+common_shlib = static_library('pgcommon_shlib',
+  common_sources_frontend_shlib,
+  c_pch: '../include/pch/c_pch.h',
+  pic: true,
+  link_with: [ryu_shlib],
+  dependencies: [frontend_common_code, ssl],
+  include_directories: include_directories('.'),
+  kwargs: default_lib_args,
+)
+
+common_static = static_library('pgcommon_static',
+  common_sources_frontend_static,
+  c_pch: '../include/pch/c_pch.h',
+  link_with: [ryu_static],
+  dependencies: [frontend_common_code, ssl],
+  include_directories: include_directories('.'),
+  kwargs: default_lib_args,
+)
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
new file mode 100644
index 00000000000..b305727d967
--- /dev/null
+++ b/src/fe_utils/meson.build
@@ -0,0 +1,27 @@
+fe_utils_sources = files(
+  'archive.c',
+  'cancel.c',
+  'conditional.c',
+  'connect_utils.c',
+  'mbprint.c',
+  'option_utils.c',
+  'parallel_slot.c',
+  'print.c',
+  'query_utils.c',
+  'recovery_gen.c',
+  'simple_list.c',
+  'string_utils.c',
+)
+
+fe_utils_sources += custom_target('psqlscan',
+  input: ['psqlscan.l'],
+  output: ['psqlscan.c'],
+  command: [flex, '-Cfe', '-p', '-p', '-o', '@OUTPUT@', '@INPUT@'])
+
+fe_utils = static_library('fe_utils',
+  fe_utils_sources + generated_headers,
+  c_pch: '../include/pch/c_pch.h',
+  include_directories :  [postgres_inc, libpq_inc],
+  c_args: ['-DFRONTEND'],
+  kwargs: default_lib_args,
+)
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
new file mode 100644
index 00000000000..a86ac67eada
--- /dev/null
+++ b/src/include/catalog/meson.build
@@ -0,0 +1,113 @@
+catalog_headers = [
+  'pg_proc.h',
+  'pg_type.h',
+  'pg_attribute.h',
+  'pg_class.h',
+  'pg_attrdef.h',
+  'pg_constraint.h',
+  'pg_inherits.h',
+  'pg_index.h',
+  'pg_operator.h',
+  'pg_opfamily.h',
+  'pg_opclass.h',
+  'pg_am.h',
+  'pg_amop.h',
+  'pg_amproc.h',
+  'pg_language.h',
+  'pg_largeobject_metadata.h',
+  'pg_largeobject.h',
+  'pg_aggregate.h',
+  'pg_statistic.h',
+  'pg_statistic_ext.h',
+  'pg_statistic_ext_data.h',
+  'pg_rewrite.h',
+  'pg_trigger.h',
+  'pg_event_trigger.h',
+  'pg_description.h',
+  'pg_cast.h',
+  'pg_enum.h',
+  'pg_namespace.h',
+  'pg_conversion.h',
+  'pg_depend.h',
+  'pg_database.h',
+  'pg_db_role_setting.h',
+  'pg_tablespace.h',
+  'pg_authid.h',
+  'pg_auth_members.h',
+  'pg_shdepend.h',
+  'pg_shdescription.h',
+  'pg_ts_config.h',
+  'pg_ts_config_map.h',
+  'pg_ts_dict.h',
+  'pg_ts_parser.h',
+  'pg_ts_template.h',
+  'pg_extension.h',
+  'pg_foreign_data_wrapper.h',
+  'pg_foreign_server.h',
+  'pg_user_mapping.h',
+  'pg_foreign_table.h',
+  'pg_policy.h',
+  'pg_replication_origin.h',
+  'pg_default_acl.h',
+  'pg_init_privs.h',
+  'pg_seclabel.h',
+  'pg_shseclabel.h',
+  'pg_collation.h',
+  'pg_partitioned_table.h',
+  'pg_range.h',
+  'pg_transform.h',
+  'pg_sequence.h',
+  'pg_publication.h',
+  'pg_publication_rel.h',
+  'pg_subscription.h',
+  'pg_subscription_rel.h',
+]
+
+bki_data = files(
+  'pg_aggregate.dat',
+  'pg_am.dat',
+  'pg_amop.dat',
+  'pg_amproc.dat',
+  'pg_authid.dat',
+  'pg_cast.dat',
+  'pg_class.dat',
+  'pg_collation.dat',
+  'pg_conversion.dat',
+  'pg_database.dat',
+  'pg_language.dat',
+  'pg_namespace.dat',
+  'pg_opclass.dat',
+  'pg_operator.dat',
+  'pg_opfamily.dat',
+  'pg_proc.dat',
+  'pg_range.dat',
+  'pg_tablespace.dat',
+  'pg_ts_config.dat',
+  'pg_ts_config_map.dat',
+  'pg_ts_dict.dat',
+  'pg_ts_parser.dat',
+  'pg_ts_template.dat',
+  'pg_type.dat',
+  )
+
+
+input = []
+output_files = ['postgres.bki', 'schemapg.h', 'system_fk_info.h', 'system_constraints.sql']
+output_install = [get_option('datadir'), get_option('includedir'), get_option('includedir'), get_option('datadir')]
+
+foreach h : catalog_headers
+  fname = h.split('.h')[0]+'_d.h'
+  input += files(h)
+  output_files += fname
+  output_install += get_option('includedir')
+endforeach
+
+generated_headers += custom_target('generated_catalog_headers',
+    input: input,
+    depend_files: bki_data,
+    build_by_default: true,
+    install: true,
+    output: output_files,
+    install_dir: output_install,
+    command: [perl, files('../../backend/catalog/genbki.pl'), '--include-path=@SOURCE_ROOT@/src/include', '--set-version='+pg_version_major.to_string(), '--output=@OUTDIR@', '@INPUT@']
+    )
diff --git a/src/include/meson.build b/src/include/meson.build
new file mode 100644
index 00000000000..c3af4a2574f
--- /dev/null
+++ b/src/include/meson.build
@@ -0,0 +1,50 @@
+configure_file(input : 'pg_config_ext.h.meson',
+  output : 'pg_config_ext.h',
+  configuration : cdata)
+
+system = host_machine.system()
+if system == 'windows'
+  system = 'win32'
+endif
+
+configure_file(
+  output : 'pg_config_os.h',
+  input: files('port/@0@.h'.format(system)),
+  install: true,
+  install_dir : get_option('includedir'),
+  copy : true)
+
+configure_file(
+  output : 'pg_config.h',
+  install : true,
+  install_dir : get_option('includedir'),
+  configuration : cdata)
+
+
+config_paths_data = configuration_data()
+config_paths_data.set_quoted('PGBINDIR', get_option('prefix') / get_option('bindir'))
+config_paths_data.set_quoted('PGSHAREDIR', get_option('prefix') / get_option('datadir'))
+config_paths_data.set_quoted('SYSCONFDIR', get_option('prefix') / get_option('sysconfdir'))
+config_paths_data.set_quoted('INCLUDEDIR', get_option('prefix') / get_option('includedir'))
+# FIXME: shouldn't be the same
+config_paths_data.set_quoted('PKGINCLUDEDIR', get_option('prefix') / get_option('includedir'))
+config_paths_data.set_quoted('INCLUDEDIRSERVER', get_option('prefix') / get_option('includedir'))
+config_paths_data.set_quoted('LIBDIR', get_option('prefix') / get_option('libdir'))
+# FIXME: figure out logic for pkglibdir
+config_paths_data.set_quoted('PKGLIBDIR', get_option('prefix') / get_option('libdir'))
+config_paths_data.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
+config_paths_data.set_quoted('DOCDIR', get_option('prefix') / get_option('datadir') / 'doc/postgresql')
+config_paths_data.set_quoted('HTMLDIR', get_option('prefix') / get_option('datadir') / 'doc/postgresql')
+config_paths_data.set_quoted('MANDIR', get_option('prefix') / get_option('datadir') / 'doc/postgresql')
+
+configure_file(
+  output: 'pg_config_paths.h',
+  configuration: config_paths_data,
+  install: false
+)
+
+
+subdir('utils')
+subdir('storage')
+subdir('catalog')
+subdir('parser')
diff --git a/src/include/parser/meson.build b/src/include/parser/meson.build
new file mode 100644
index 00000000000..caf4c092909
--- /dev/null
+++ b/src/include/parser/meson.build
@@ -0,0 +1,10 @@
+backend_parser_header = custom_target('gram',
+  input: [files('../../backend/parser/gram.y')],
+  output: ['gram.c', 'gram.h'],
+  command: [bison, bisonflags, '-d', '-o', '@OUTPUT0@', '@INPUT0@'],
+  install: true,
+  # Only install gram.h, not gram.c
+  install_dir: [false, get_option('includedir')]
+)
+
+#generated_backend_headers += backend_parser[1]
diff --git a/src/include/pch/c_pch.h b/src/include/pch/c_pch.h
new file mode 100644
index 00000000000..f40c757ca62
--- /dev/null
+++ b/src/include/pch/c_pch.h
@@ -0,0 +1 @@
+#include "c.h"
diff --git a/src/include/pch/postgres_pch.h b/src/include/pch/postgres_pch.h
new file mode 100644
index 00000000000..71b2f35f76b
--- /dev/null
+++ b/src/include/pch/postgres_pch.h
@@ -0,0 +1 @@
+#include "postgres.h"
diff --git a/src/include/pg_config_ext.h.meson b/src/include/pg_config_ext.h.meson
new file mode 100644
index 00000000000..57cdfca0cfd
--- /dev/null
+++ b/src/include/pg_config_ext.h.meson
@@ -0,0 +1,7 @@
+/*
+ * src/include/pg_config_ext.h.in.  This is generated manually, not by
+ * autoheader, since we want to limit which symbols get defined here.
+ */
+
+/* Define to the name of a signed 64-bit integer type. */
+#mesondefine PG_INT64_TYPE
diff --git a/src/include/storage/meson.build b/src/include/storage/meson.build
new file mode 100644
index 00000000000..ce749169442
--- /dev/null
+++ b/src/include/storage/meson.build
@@ -0,0 +1,15 @@
+# FIXME: this creates an unnecessary lwlocknames.c - but it's not
+# obvious how to avoid that: meson insist on output files being in the
+# current dir.
+
+# FIXME: this leads to lwlocknames.c being installed. Bad.
+lwlocknames = custom_target('lwlocknames',
+  input : files('../../backend/storage/lmgr/lwlocknames.txt'),
+  output : ['lwlocknames.h', 'lwlocknames.c'],
+  command : [perl, files('../../backend/storage/lmgr/generate-lwlocknames.pl'), '-o', '@OUTDIR@', '@INPUT@'],
+  build_by_default: true,
+  install: true,
+  install_dir: get_option('includedir')
+)
+
+generated_backend_headers += lwlocknames[0]
diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build
new file mode 100644
index 00000000000..b9c959b474d
--- /dev/null
+++ b/src/include/utils/meson.build
@@ -0,0 +1,22 @@
+errcodes = custom_target('errcodes',
+  input : files('../../backend/utils/errcodes.txt'),
+  output : ['errcodes.h'],
+  command : [perl, files('../../backend/utils/generate-errcodes.pl'), '@INPUT@', '@OUTPUT@']
+)
+generated_headers += errcodes
+
+generated_backend_headers += custom_target('probes.d',
+  input: files('../../backend/utils/probes.d'),
+  output : 'probes.h',
+  capture: true,
+  command : [sed, '-f', files('../../backend/utils/Gen_dummy_probes.sed'), '@INPUT@']
+)
+
+fmgrtab_target = custom_target('fmgrtab',
+  input: '../catalog/pg_proc.dat',
+  output : ['fmgroids.h', 'fmgrprotos.h', 'fmgrtab.c'],
+  command: [perl, '-I', '@SOURCE_ROOT@/src/backend/catalog/', files('../../backend/utils/Gen_fmgrtab.pl'), '--include-path=@SOURCE_ROOT@/src/include', '--output=@OUTDIR@', '@INPUT@']
+)
+
+generated_backend_headers += fmgrtab_target[0]
+generated_backend_headers += fmgrtab_target[1]
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
new file mode 100644
index 00000000000..4b716f0e89d
--- /dev/null
+++ b/src/interfaces/libpq/meson.build
@@ -0,0 +1,99 @@
+libpq_sources = files(
+  'fe-auth-scram.c',
+  'fe-connect.c',
+  'fe-exec.c',
+  'fe-lobj.c',
+  'fe-misc.c',
+  'fe-print.c',
+  'fe-protocol3.c',
+  'fe-secure.c',
+  'fe-trace.c',
+  'legacy-pqsignal.c',
+  'libpq-events.c',
+  'pqexpbuffer.c',
+  'fe-auth.c',
+)
+
+if host_machine.system() == 'windows'
+  libpq_sources += files('win32.c', 'pthread-win32.c')
+endif
+
+if ssl.found()
+  libpq_sources += files('fe-secure-common.c')
+  libpq_sources += files('fe-secure-openssl.c')
+endif
+
+if gssapi.found()
+  libpq_sources += files(
+    'fe-secure-gssapi.c',
+    'fe-gssapi-common.c'
+  )
+endif
+
+export_file = custom_target('libpq_exports.list',
+  input: [files('exports.txt')],
+  output: ['@BASENAME@.list'],
+  command: [perl, files('../../tools/gen_versioning_script.pl'),
+    host_machine.system() == 'darwin' ? 'darwin' : 'gnu',
+    '@INPUT0@', '@OUTPUT0@'],
+  build_by_default: false,
+  install: false,
+)
+
+libpq_def = custom_target('libpq.def',
+  command: [perl, files('../../tools/msvc/export2def.pl'), '@OUTPUT@', '@INPUT0@', 'libpq'],
+  input: files('exports.txt'),
+  output: 'libpq.def',
+  build_by_default: false,
+  install: false,
+)
+
+# port needs to be in include path due to pthread-win32.h
+libpq_inc = include_directories('.', '../../port')
+libpq_deps = [frontend_shlib_code, thread_dep, ssl, ldap, gssapi]
+libpq_link_depends = []
+
+libpq_kwargs = default_lib_args + {
+  'version': '5.'+pg_version_major.to_string(),
+}
+
+
+if host_machine.system() == 'darwin'
+  libpq_kwargs = libpq_kwargs + {
+    'link_args': ['-exported_symbols_list', export_file.full_path()],
+    'link_depends': export_file,
+    'soversion': '5',
+  }
+elif host_machine.system() == 'windows'
+  libpq_deps += cc.find_library('secur32', required: true)
+
+  libpq_kwargs = libpq_kwargs + {
+    'vs_module_defs': libpq_def,
+    'soversion': '',
+  }
+else
+  libpq_kwargs = libpq_kwargs + {
+    'link_args': '-Wl,--version-script=' + export_file.full_path(),
+    'link_depends': export_file,
+    'soversion': '5',
+  }
+endif
+
+libpq_so = shared_library('pq',
+  libpq_sources,
+  include_directories : [libpq_inc, postgres_inc],
+  c_args: ['-DFRONTEND'],
+  c_pch: '../../include/pch/c_pch.h',
+  dependencies: libpq_deps,
+  kwargs: libpq_kwargs,
+)
+
+libpq = declare_dependency(
+  link_with: [libpq_so],
+  include_directories: [include_directories('.')]
+)
+
+install_headers('libpq-fe.h', 'libpq-events.h')
+# FIXME: adjust path
+install_headers('libpq-int.h', 'pqexpbuffer.h')
+install_data('pg_service.conf.sample', install_dir: get_option('datadir'))
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 00000000000..414be1db419
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,10 @@
+# libraries that other subsystems might depend uppon first, in their
+# respective dependency order
+
+subdir('timezone')
+
+subdir('backend')
+
+subdir('bin')
+
+subdir('pl')
diff --git a/src/pl/meson.build b/src/pl/meson.build
new file mode 100644
index 00000000000..b720e922093
--- /dev/null
+++ b/src/pl/meson.build
@@ -0,0 +1,4 @@
+subdir('plpgsql')
+
+subdir('plperl')
+subdir('plpython')
diff --git a/src/pl/plperl/meson.build b/src/pl/plperl/meson.build
new file mode 100644
index 00000000000..a5a994e845f
--- /dev/null
+++ b/src/pl/plperl/meson.build
@@ -0,0 +1,81 @@
+if not perl_dep.found()
+  subdir_done()
+endif
+
+plperl_sources = files(
+  'plperl.c',
+)
+
+subppdir = run_command(perl, '-e', 'use List::Util qw(first); print first { -r "$_/ExtUtils/xsubpp" } @INC',
+  check: true).stdout()
+xsubpp = '@0@/ExtUtils/xsubpp'.format(subppdir)
+typemap = '@0@/ExtUtils/typemap'.format(subppdir)
+
+plperl_sources += custom_target('perlchunks.h',
+  input: files('plc_perlboot.pl', 'plc_trusted.pl'),
+  output: 'perlchunks.h',
+  capture: true,
+  command: [perl, files('text2macro.pl'), '--strip=^(\#.*|\s*)$', '@INPUT@']
+)
+
+plperl_sources += custom_target('plperl_opmask.h',
+  input: files('plperl_opmask.pl'),
+  output: 'plperl_opmask.h',
+  command: [perl, '@INPUT@', '@OUTPUT@']
+)
+
+foreach n : ['SPI', 'Util']
+  xs = files(n+'.xs')
+  xs_c_name = n+'.c'
+
+  # FIXME: -output option is only available in perl 5.9.3 - but that's
+  # probably a fine minimum requirement?
+  xs_c = custom_target(xs_c_name,
+    input: xs,
+    output: xs_c_name,
+    command: [perl, xsubpp, '-typemap', typemap, '-output', '@OUTPUT@', '@INPUT@']
+  )
+  plperl_sources += xs_c
+endforeach
+
+plperl_inc = include_directories('.')
+shared_module('plperl',
+  plperl_sources,
+  c_pch: '../../include/pch/postgres_pch.h',
+  include_directories: [plperl_inc, postgres_inc],
+  kwargs: pg_mod_args + {
+    'dependencies': [perl_dep, pg_mod_args['dependencies']],
+  },
+)
+
+install_data(
+  'plperl.control',
+  'plperl--1.0.sql',
+  install_dir: get_option('datadir') / 'extension'
+)
+
+install_data(
+  'plperlu.control',
+  'plperlu--1.0.sql',
+  install_dir: get_option('datadir') / 'extension'
+)
+
+regress_tests += {
+  'name': 'plperl',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'plperl_setup',
+    'plperl',
+    'plperl_lc',
+    'plperl_trigger',
+    'plperl_shared',
+    'plperl_elog',
+    'plperl_util',
+    'plperl_init',
+    'plperlu',
+    'plperl_array',
+    'plperl_call',
+    'plperl_transaction',
+   ],
+}
diff --git a/src/pl/plpgsql/meson.build b/src/pl/plpgsql/meson.build
new file mode 100644
index 00000000000..9537275d67c
--- /dev/null
+++ b/src/pl/plpgsql/meson.build
@@ -0,0 +1 @@
+subdir('src')
diff --git a/src/pl/plpgsql/src/meson.build b/src/pl/plpgsql/src/meson.build
new file mode 100644
index 00000000000..b040e5e8507
--- /dev/null
+++ b/src/pl/plpgsql/src/meson.build
@@ -0,0 +1,67 @@
+plpgsql_sources = files(
+  'pl_comp.c',
+  'pl_exec.c',
+  'pl_funcs.c',
+  'pl_handler.c',
+  'pl_scanner.c',
+)
+
+plpgsql_sources += custom_target('gram',
+  input: ['pl_gram.y'],
+  output: ['pl_gram.c', 'pl_gram.h'],
+  command: [bison, bisonflags, '-d', '-o', '@OUTPUT0@', '@INPUT0@'])
+
+gen_plerrcodes = files('generate-plerrcodes.pl')
+plpgsql_sources += custom_target('plerrcodes',
+  input: ['../../../../src/backend/utils/errcodes.txt'],
+  output: ['plerrcodes.h'],
+  command: [perl, gen_plerrcodes, '@INPUT0@'],
+  capture: true)
+
+gen_keywordlist = files('../../../../src/tools/gen_keywordlist.pl')
+plpgsql_sources += custom_target('pl_reserved_kwlist',
+  input: ['pl_reserved_kwlist.h'],
+  output: ['pl_reserved_kwlist_d.h'],
+  command: [perl, '-I', '@SOURCE_ROOT@/src/tools', gen_keywordlist, '--output', '@OUTDIR@', '--varname', 'ReservedPLKeywords', '@INPUT@']
+)
+
+plpgsql_sources += custom_target('pl_unreserved_kwlist',
+  input: ['pl_unreserved_kwlist.h'],
+  output: ['pl_unreserved_kwlist_d.h'],
+  command: [perl, '-I', '@SOURCE_ROOT@/src/tools', gen_keywordlist, '--output', '@OUTDIR@', '--varname', 'UnreservedPLKeywords', '@INPUT@']
+)
+
+shared_module('plpgsql',
+  plpgsql_sources,
+  c_pch: '../../../include/pch/postgres_pch.h',
+  include_directories: include_directories('.'),
+  kwargs: pg_mod_args,
+)
+
+install_data('plpgsql.control', 'plpgsql--1.0.sql',
+  install_dir: get_option('datadir') / 'extension'
+)
+
+install_headers('plpgsql.h',
+  install_dir: get_option('includedir') / 'server')
+
+
+regress_tests += {
+  'name': 'plpgsql',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+     'plpgsql_array',
+     'plpgsql_call',
+     'plpgsql_control',
+     'plpgsql_copy',
+     'plpgsql_domain',
+     'plpgsql_record',
+     'plpgsql_cache',
+     'plpgsql_simple',
+     'plpgsql_transaction',
+     'plpgsql_trap',
+     'plpgsql_trigger',
+     'plpgsql_varprops',
+  ],
+}
diff --git a/src/pl/plpython/expected/meson.build b/src/pl/plpython/expected/meson.build
new file mode 100644
index 00000000000..4172ced2208
--- /dev/null
+++ b/src/pl/plpython/expected/meson.build
@@ -0,0 +1,14 @@
+# FIXME: adding the variant files like this is an abysmal hack in an abysmal hack
+foreach r2 : plpython_regress + ['plpython_error_5', 'plpython_types_3']
+  # string.replace is only in meson 0.58
+  r3 = 'plpython3' + r2.split('plpython')[1]
+
+  s2 = '@0@.out'.format(r2)
+  s3 = '@0@.out'.format(r3)
+  plpython3_test_deps += custom_target(s3,
+    input: '@0@.out'.format(r2),
+    output: '@0@.out'.format(r3),
+    capture: true,
+    command: plpython_regress_cmd,
+  )
+endforeach
diff --git a/src/pl/plpython/meson.build b/src/pl/plpython/meson.build
new file mode 100644
index 00000000000..14fe8bd7c7f
--- /dev/null
+++ b/src/pl/plpython/meson.build
@@ -0,0 +1,100 @@
+if not python3.found()
+  subdir_done()
+endif
+
+plpython_sources = files(
+  'plpy_cursorobject.c',
+  'plpy_elog.c',
+  'plpy_exec.c',
+  'plpy_main.c',
+  'plpy_planobject.c',
+  'plpy_plpymodule.c',
+  'plpy_procedure.c',
+  'plpy_resultobject.c',
+  'plpy_spi.c',
+  'plpy_subxactobject.c',
+  'plpy_typeio.c',
+  'plpy_util.c',
+)
+
+plpython_sources += custom_target('spiexceptions.h',
+    input: files('../../backend/utils/errcodes.txt'),
+    output: 'spiexceptions.h',
+    command: [perl, files('generate-spiexceptions.pl'), '@INPUT@'],
+    capture: true
+  )
+
+
+# FIXME: need to duplicate import library ugliness?
+plpython_inc = include_directories('.')
+
+shared_module('plpython3',
+  plpython_sources,
+  c_pch: '../../include/pch/postgres_pch.h',
+  include_directories: [plpython_inc, postgres_inc],
+  kwargs: pg_mod_args + {
+    'dependencies': [python3, pg_mod_args['dependencies']],
+  },
+)
+
+# FIXME: Only install the relevant versions
+install_data(
+  'plpythonu.control',
+  'plpython2u.control',
+  'plpython3u.control',
+  'plpythonu--1.0.sql',
+  'plpython2u--1.0.sql',
+  'plpython3u--1.0.sql',
+  install_dir: get_option('datadir') / 'extension'
+)
+
+# FIXME: Think about python2
+
+
+plpython_regress_cmd = [
+  sed,
+  '-f', files('regress-python3-mangle.sed'),
+  '@INPUT0@'
+]
+
+plpython_regress = [
+  'plpython_schema',
+  'plpython_populate',
+  'plpython_test',
+  'plpython_do',
+  'plpython_global',
+  'plpython_import',
+  'plpython_spi',
+  'plpython_newline',
+  'plpython_void',
+  'plpython_call',
+  'plpython_params',
+  'plpython_setof',
+  'plpython_record',
+  'plpython_trigger',
+  'plpython_types',
+  'plpython_error',
+  'plpython_ereport',
+  'plpython_unicode',
+  'plpython_quote',
+  'plpython_composite',
+  'plpython_subtransaction',
+  'plpython_transaction',
+  'plpython_drop',
+]
+
+plpython3_regress = []
+plpython3_test_deps = []
+
+# FIXME: this is an abysmal hack
+subdir('sql')
+subdir('expected')
+
+regress_tests += {
+  'name': 'plpython',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': plpython3_regress,
+  'deps': plpython3_test_deps,
+  'regress_args': ['--inputdir', meson.current_build_dir()],
+}
diff --git a/src/pl/plpython/sql/meson.build b/src/pl/plpython/sql/meson.build
new file mode 100644
index 00000000000..9923425e5ff
--- /dev/null
+++ b/src/pl/plpython/sql/meson.build
@@ -0,0 +1,15 @@
+# Convert plpython2 regression tests to plpython3 ones
+foreach r2 : plpython_regress
+  # string.replace is only in meson 0.58
+  r3 = 'plpython3' + r2.split('plpython')[1]
+  plpython3_regress += r3
+
+  s2 = '@0@.sql'.format(r2)
+  s3 = '@0@.sql'.format(r3)
+  plpython3_test_deps += custom_target(s3,
+    input: '@0@.sql'.format(r2),
+    output: '@0@.sql'.format(r3),
+    capture: true,
+    command: plpython_regress_cmd,
+  )
+endforeach
diff --git a/src/port/meson.build b/src/port/meson.build
new file mode 100644
index 00000000000..c6e4c788052
--- /dev/null
+++ b/src/port/meson.build
@@ -0,0 +1,146 @@
+pgport_sources = [
+  'bsearch_arg.c',
+  'chklocale.c',
+  'erand48.c',
+  'inet_net_ntop.c',
+  'noblock.c',
+  'path.c',
+  'pg_bitutils.c',
+  'pg_strong_random.c',
+  'pgcheckdir.c',
+  'pgmkdirp.c',
+  'pgsleep.c',
+  'pgstrcasecmp.c',
+  'pgstrsignal.c',
+  'pqsignal.c',
+  'qsort.c',
+  'qsort_arg.c',
+  'quotes.c',
+  'snprintf.c',
+  'strerror.c',
+  'tar.c',
+  'thread.c',
+]
+
+if host_machine.system() == 'windows'
+  pgport_sources += files(
+    'dirmod.c',
+    'kill.c',
+    'open.c',
+    'system.c',
+    'win32env.c',
+    'win32error.c',
+    'win32security.c',
+    'win32setlocale.c',
+    'win32stat.c',
+  )
+endif
+
+if cc.get_id() == 'msvc'
+  pgport_sources += files(
+    'dirent.c',
+  )
+endif
+
+# Replacement functionality to be built if corresponding configure symbol
+# is false
+replace_funcs_neg = [
+    ['dlopen'],
+    ['explicit_bzero'],
+    ['fls'],
+    ['getaddrinfo'],
+    ['getopt'],
+    ['getopt_long'],
+    ['getpeereid'],
+    ['getpeereid'],
+    ['getrusage'],
+    ['gettimeofday'],
+    ['inet_aton'],
+    ['link'],
+    ['mkdtemp'],
+    ['pread'],
+    ['preadv', 'HAVE_DECL_PREADV'],
+    ['pwrite'],
+    ['pwritev', 'HAVE_DECL_PWRITEV'],
+    ['random'],
+    ['srandom'],
+    ['strlcat'],
+    ['strlcpy'],
+    ['strnlen'],
+]
+
+# Replacement functionality to be built if corresponding configure symbol
+# is true
+replace_funcs_pos = [
+  ['pg_crc32c_sse42', 'USE_SSE42_CRC32C'],
+  ['pg_crc32c_sse42', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK'],
+  ['pg_crc32c_sse42_choose', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK'],
+  ['pg_crc32c_sb8', 'USE_SSE42_CRC32C_WITH_RUNTIME_CHECK'],
+  ['pg_crc32c_armv8', 'USE_ARMV8_CRC32C'],
+  ['pg_crc32c_sb8', 'USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK'],
+  ['pg_crc32c_armv8_choose', 'USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK'],
+]
+
+foreach f : replace_funcs_neg
+  func = f.get(0)
+  varname = f.get(1, 'HAVE_@0@'.format(func.to_upper()))
+  filename = '@0@.c'.format(func)
+
+  val = '@0@'.format(cdata.get(varname, 'false'))
+  if val == 'false' or val == '0'
+    pgport_sources += files(filename)
+  endif
+endforeach
+
+foreach f : replace_funcs_pos
+  func = f.get(0)
+  varname = f.get(1, 'HAVE_@0@'.format(func.to_upper()))
+  filename = '@0@.c'.format(func)
+
+  val = '@0@'.format(cdata.get(varname, 'false'))
+  if val == 'true' or val == '1'
+    pgport_sources += files(filename)
+  endif
+endforeach
+
+
+if (host_machine.system() == 'windows' or host_machine.system() == 'cygwin') and \
+  (cc.get_id() != 'msvc' or cc.version().version_compare('<14.0'))
+
+  # Cygwin and (apparently, based on test results) Mingw both
+  # have a broken strtof(), so substitute the same replacement
+  # code we use with VS2013. That's not a perfect fix, since
+  # (unlike with VS2013) it doesn't avoid double-rounding, but
+  # we have no better options. To get that, though, we have to
+  # force the file to be compiled despite HAVE_STRTOF.
+  pgport_sources += files('strtof.c')
+  message('On @0@ with compiler @1@ @2@ we will use our strtof wrapper.'.format(
+    host_machine.system(), cc.get_id(), cc.version()))
+endif
+
+if not cdata.has('HAVE_PTHREAD_BARRIER_WAIT') and host_machine.system() != 'windows'
+   pgport_sources += files('pthread_barrier_wait.c')
+endif
+
+
+pgport_srv = static_library('pgport_srv',
+  pgport_sources,
+  c_pch: '../include/pch/c_pch.h',
+  dependencies: [ssl, backend_port_code],
+  kwargs: internal_lib_args,
+)
+
+pgport_static = static_library('pgport',
+  pgport_sources,
+  c_pch: '../include/pch/c_pch.h',
+  dependencies: [ssl, frontend_port_code],
+  kwargs: default_lib_args,
+)
+
+pgport_shlib = static_library('pgport_shlib',
+  pgport_sources,
+  c_pch: '../include/pch/c_pch.h',
+  pic: true,
+  dependencies: [ssl, frontend_port_code],
+  kwargs: default_lib_args,
+)
diff --git a/src/test/authentication/meson.build b/src/test/authentication/meson.build
new file mode 100644
index 00000000000..be41fb314a5
--- /dev/null
+++ b/src/test/authentication/meson.build
@@ -0,0 +1,9 @@
+tap_tests += {
+  'name': 'authentication',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_password.pl',
+    't/002_saslprep.pl',
+  ],
+}
diff --git a/src/test/isolation/meson.build b/src/test/isolation/meson.build
new file mode 100644
index 00000000000..637b4807550
--- /dev/null
+++ b/src/test/isolation/meson.build
@@ -0,0 +1,49 @@
+# pg_regress_c helpfully provided by regress/meson.build
+
+isolation_sources = pg_regress_c + files(
+  'isolation_main.c',
+)
+
+# see src/backend/replication/meson.build for depend logic
+spec_scanner = custom_target('specscanner',
+  input : files('specscanner.l'),
+  output : ['specscanner.c'],
+  command : [flex, '-CF', '-p', '-p', '-o', '@OUTPUT0@', '@INPUT@']
+)
+
+isolationtester_sources = files('isolationtester.c')
+isolationtester_sources += custom_target('specparse',
+  input: 'specparse.y',
+  output: 'specparse.c',
+  depends: spec_scanner,
+  command: [bison, bisonflags, '-o', '@OUTPUT@', '@INPUT0@'])
+
+pg_isolation_regress = executable('pg_isolation_regress',
+  isolation_sources,
+  c_args: pg_regress_cflags,
+  include_directories: [pg_regress_inc],
+  dependencies: [frontend_code],
+  kwargs: default_bin_args + {
+    'install': false
+  },
+)
+
+isolationtester = executable('isolationtester',
+  isolationtester_sources,
+  include_directories: include_directories('.'),
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args + {
+    'install': false
+  },
+)
+
+isolation_tests += {
+  'name': 'main',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'schedule': files('isolation_schedule'),
+  'test_kwargs': {
+    'priority': 40,
+    'timeout': 1000,
+  },
+}
diff --git a/src/test/kerberos/meson.build b/src/test/kerberos/meson.build
new file mode 100644
index 00000000000..9f9957a3b4c
--- /dev/null
+++ b/src/test/kerberos/meson.build
@@ -0,0 +1,12 @@
+tap_tests += {
+  'name': 'kerberos',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_auth.pl',
+  ],
+  'env' : {
+    'with_gssapi': gssapi.found() ? 'yes' : 'no',
+    'with_krb_srvnam': 'postgres',
+  },
+}
diff --git a/src/test/ldap/meson.build b/src/test/ldap/meson.build
new file mode 100644
index 00000000000..58eb9adc6f5
--- /dev/null
+++ b/src/test/ldap/meson.build
@@ -0,0 +1,9 @@
+tap_tests += {
+  'name': 'ldap',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_auth.pl',
+  ],
+  'env' : {'with_ldap': ldap.found() ? 'yes' : 'no'},
+}
diff --git a/src/test/meson.build b/src/test/meson.build
new file mode 100644
index 00000000000..f0b0d3d3b5e
--- /dev/null
+++ b/src/test/meson.build
@@ -0,0 +1,19 @@
+subdir('regress')
+subdir('isolation')
+
+subdir('authentication')
+subdir('recovery')
+subdir('subscription')
+subdir('modules')
+
+if ssl.found()
+   subdir('ssl')
+endif
+
+if ldap.found()
+   subdir('ldap')
+endif
+
+if gssapi.found()
+   subdir('kerberos')
+endif
diff --git a/src/test/modules/brin/meson.build b/src/test/modules/brin/meson.build
new file mode 100644
index 00000000000..99ccaac5b38
--- /dev/null
+++ b/src/test/modules/brin/meson.build
@@ -0,0 +1,19 @@
+isolation_tests += {
+  'name': 'brin',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'specs': [
+    'summarization-and-inprogress-insertion',
+  ]
+}
+
+
+tap_tests += {
+  'name': 'brin',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/01_workitems.pl',
+  ],
+}
+
diff --git a/src/test/modules/commit_ts/meson.build b/src/test/modules/commit_ts/meson.build
new file mode 100644
index 00000000000..2794d837c35
--- /dev/null
+++ b/src/test/modules/commit_ts/meson.build
@@ -0,0 +1,20 @@
+regress_tests += {
+  'name': 'commit_ts',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'commit_timestamp',
+  ]
+}
+
+tap_tests += {
+  'name': 'commit_ts',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_base.pl',
+    't/002_standby.pl',
+    't/003_standby_2.pl',
+    't/004_restart.pl',
+  ],
+}
diff --git a/src/test/modules/delay_execution/meson.build b/src/test/modules/delay_execution/meson.build
new file mode 100644
index 00000000000..58fe5a1a21d
--- /dev/null
+++ b/src/test/modules/delay_execution/meson.build
@@ -0,0 +1,15 @@
+# FIXME: prevent install during main install, but not during test :/
+delay_execution = shared_module('delay_execution',
+  ['delay_execution.c'],
+  kwargs: pg_mod_args,
+)
+
+isolation_tests += {
+  'name': 'delay_execution',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'specs': [
+    'partition-addition',
+    'partition-removal-1',
+  ]
+}
diff --git a/src/test/modules/dummy_index_am/meson.build b/src/test/modules/dummy_index_am/meson.build
new file mode 100644
index 00000000000..a9c49bd9554
--- /dev/null
+++ b/src/test/modules/dummy_index_am/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+dummy_index_am = shared_module('dummy_index_am',
+  ['dummy_index_am.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'dummy_index_am.control',
+  'dummy_index_am--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'dummy_index_am',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'reloptions',
+  ]
+}
diff --git a/src/test/modules/dummy_seclabel/meson.build b/src/test/modules/dummy_seclabel/meson.build
new file mode 100644
index 00000000000..ed31d8f9530
--- /dev/null
+++ b/src/test/modules/dummy_seclabel/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+dummy_seclabel = shared_module('dummy_seclabel',
+  ['dummy_seclabel.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'dummy_seclabel.control',
+  'dummy_seclabel--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'dummy_seclabel',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'dummy_seclabel',
+  ]
+}
diff --git a/src/test/modules/libpq_pipeline/meson.build b/src/test/modules/libpq_pipeline/meson.build
new file mode 100644
index 00000000000..2f850215a6f
--- /dev/null
+++ b/src/test/modules/libpq_pipeline/meson.build
@@ -0,0 +1,21 @@
+libpq_pipeline = executable('libpq_pipeline',
+  files(
+    'libpq_pipeline.c',
+  ),
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args + {
+    'install': false,
+  },
+)
+
+tap_tests += {
+  'name': 'libpq_pipeline',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'env': {
+    'PATH': meson.current_build_dir(),
+  },
+  'tests': [
+    't/001_libpq_pipeline.pl',
+  ]
+}
diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build
new file mode 100644
index 00000000000..c98225c6e7b
--- /dev/null
+++ b/src/test/modules/meson.build
@@ -0,0 +1,25 @@
+subdir('brin')
+subdir('commit_ts')
+subdir('delay_execution')
+subdir('dummy_index_am')
+subdir('dummy_seclabel')
+subdir('libpq_pipeline')
+subdir('plsample')
+subdir('snapshot_too_old')
+subdir('spgist_name_ops')
+subdir('ssl_passphrase_callback')
+subdir('test_bloomfilter')
+subdir('test_ddl_deparse')
+subdir('test_extensions')
+subdir('test_ginpostinglist')
+subdir('test_integerset')
+subdir('test_misc')
+subdir('test_parser')
+subdir('test_pg_dump')
+subdir('test_predtest')
+subdir('test_rbtree')
+subdir('test_regex')
+subdir('test_rls_hooks')
+subdir('test_shm_mq')
+subdir('unsafe_tests')
+subdir('worker_spi')
diff --git a/src/test/modules/plsample/meson.build b/src/test/modules/plsample/meson.build
new file mode 100644
index 00000000000..3f70688fb89
--- /dev/null
+++ b/src/test/modules/plsample/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+plsample = shared_module('plsample',
+  ['plsample.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'plsample.control',
+  'plsample--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'plsample',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'plsample',
+  ]
+}
diff --git a/src/test/modules/snapshot_too_old/meson.build b/src/test/modules/snapshot_too_old/meson.build
new file mode 100644
index 00000000000..cdf4afd18b8
--- /dev/null
+++ b/src/test/modules/snapshot_too_old/meson.build
@@ -0,0 +1,11 @@
+isolation_tests += {
+  'name': 'snapshot_too_old',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'specs': [
+    'sto_using_cursor',
+    'sto_using_select',
+    'sto_using_hash_index',
+  ],
+  'regress_args': ['--temp-config', files('sto.conf')],
+}
diff --git a/src/test/modules/spgist_name_ops/meson.build b/src/test/modules/spgist_name_ops/meson.build
new file mode 100644
index 00000000000..19aa00892f1
--- /dev/null
+++ b/src/test/modules/spgist_name_ops/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+spgist_name_ops = shared_module('spgist_name_ops',
+  ['spgist_name_ops.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'spgist_name_ops.control',
+  'spgist_name_ops--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'spgist_name_ops',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'spgist_name_ops',
+  ]
+}
diff --git a/src/test/modules/ssl_passphrase_callback/meson.build b/src/test/modules/ssl_passphrase_callback/meson.build
new file mode 100644
index 00000000000..b9fa5ee1cdc
--- /dev/null
+++ b/src/test/modules/ssl_passphrase_callback/meson.build
@@ -0,0 +1,45 @@
+if not ssl.found()
+  subdir_done()
+endif
+
+# FIXME: prevent install during main install, but not during test :/
+ssl_passphrase_callback = shared_module('ssl_passphrase_func',
+  ['ssl_passphrase_func.c'],
+  kwargs: pg_mod_args + {
+    'dependencies': [ssl, pg_mod_args['dependencies']],
+  }
+)
+
+# Targets to generate or remove the ssl certificate and key. Need to be copied
+# to the source afterwards. Normally not needed.
+
+openssl = find_program('openssl', native: true, required: false)
+
+if openssl.found()
+  cert = custom_target('server.crt',
+    output: ['server.crt', 'server.ckey'],
+    command: [openssl, 'req', '-new', '-x509', '-days', '10000', '-nodes', '-out', '@OUTPUT0@',
+      '-keyout', '@OUTPUT1@', '-subj', '/CN=localhost'],
+    build_by_default: false,
+    install: false,
+  )
+
+  # needs to agree with what's in the test script
+  pass = 'FooBaR1'
+
+  enccert = custom_target('server.key',
+    input: [cert[1]],
+    output: ['server.key'],
+    command: [openssl, 'rsa', '-aes256', '-in', '@INPUT0@', '-out', '@OUTPUT0@', '-passout', 'pass:@0@'.format(pass)]
+  )
+endif
+
+tap_tests += {
+  'name': 'ssl_passphrase_callback',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_testfunc.pl',
+  ],
+  'env': {'with_ssl': 'openssl'},
+}
diff --git a/src/test/modules/test_bloomfilter/meson.build b/src/test/modules/test_bloomfilter/meson.build
new file mode 100644
index 00000000000..2e995310876
--- /dev/null
+++ b/src/test/modules/test_bloomfilter/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+test_bloomfilter = shared_module('test_bloomfilter',
+  ['test_bloomfilter.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_bloomfilter.control',
+  'test_bloomfilter--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_bloomfilter',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_bloomfilter',
+  ]
+}
diff --git a/src/test/modules/test_ddl_deparse/meson.build b/src/test/modules/test_ddl_deparse/meson.build
new file mode 100644
index 00000000000..3618229594d
--- /dev/null
+++ b/src/test/modules/test_ddl_deparse/meson.build
@@ -0,0 +1,40 @@
+# FIXME: prevent install during main install, but not during test :/
+test_ddl_deparse = shared_module('test_ddl_deparse',
+  ['test_ddl_deparse.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_ddl_deparse.control',
+  'test_ddl_deparse--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_ddl_deparse',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_ddl_deparse',
+    'create_extension',
+    'create_schema',
+    'create_type',
+    'create_conversion',
+    'create_domain',
+    'create_sequence_1',
+    'create_table',
+    'create_transform',
+    'alter_table',
+    'create_view',
+    'create_trigger',
+    'create_rule',
+    'comment_on',
+    'alter_function',
+    'alter_sequence',
+    'alter_ts_config',
+    'alter_type_enum',
+    'opfamily',
+    'defprivs',
+    'matviews',
+  ]
+}
diff --git a/src/test/modules/test_extensions/meson.build b/src/test/modules/test_extensions/meson.build
new file mode 100644
index 00000000000..2ca504f8588
--- /dev/null
+++ b/src/test/modules/test_extensions/meson.build
@@ -0,0 +1,38 @@
+# FIXME: prevent install during main install, but not during test :/
+install_data(
+  'test_ext1--1.0.sql',
+  'test_ext1.control',
+  'test_ext2--1.0.sql',
+  'test_ext2.control',
+  'test_ext3--1.0.sql',
+  'test_ext3.control',
+  'test_ext4--1.0.sql',
+  'test_ext4.control',
+  'test_ext5--1.0.sql',
+  'test_ext5.control',
+  'test_ext6--1.0.sql',
+  'test_ext6.control',
+  'test_ext7--1.0--2.0.sql',
+  'test_ext7--1.0.sql',
+  'test_ext7.control',
+  'test_ext8--1.0.sql',
+  'test_ext8.control',
+  'test_ext_cyclic1--1.0.sql',
+  'test_ext_cyclic1.control',
+  'test_ext_cyclic2--1.0.sql',
+  'test_ext_cyclic2.control',
+  'test_ext_evttrig--1.0--2.0.sql',
+  'test_ext_evttrig--1.0.sql',
+  'test_ext_evttrig.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_extensions',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_extensions',
+    'test_extdepend',
+  ]
+}
diff --git a/src/test/modules/test_ginpostinglist/meson.build b/src/test/modules/test_ginpostinglist/meson.build
new file mode 100644
index 00000000000..e177e90019f
--- /dev/null
+++ b/src/test/modules/test_ginpostinglist/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+test_ginpostinglist = shared_module('test_ginpostinglist',
+  ['test_ginpostinglist.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_ginpostinglist.control',
+  'test_ginpostinglist--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_ginpostinglist',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_ginpostinglist',
+  ]
+}
diff --git a/src/test/modules/test_integerset/meson.build b/src/test/modules/test_integerset/meson.build
new file mode 100644
index 00000000000..ccb8db725e5
--- /dev/null
+++ b/src/test/modules/test_integerset/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+test_integerset = shared_module('test_integerset',
+  ['test_integerset.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_integerset.control',
+  'test_integerset--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_integerset',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_integerset',
+  ]
+}
diff --git a/src/test/modules/test_misc/meson.build b/src/test/modules/test_misc/meson.build
new file mode 100644
index 00000000000..4ee8c562ac0
--- /dev/null
+++ b/src/test/modules/test_misc/meson.build
@@ -0,0 +1,8 @@
+tap_tests += {
+  'name': 'misc',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_constraint_validation.pl',
+  ],
+}
diff --git a/src/test/modules/test_parser/meson.build b/src/test/modules/test_parser/meson.build
new file mode 100644
index 00000000000..c43ae95cf2c
--- /dev/null
+++ b/src/test/modules/test_parser/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+test_parser = shared_module('test_parser',
+  ['test_parser.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_parser.control',
+  'test_parser--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_parser',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_parser',
+  ]
+}
diff --git a/src/test/modules/test_pg_dump/meson.build b/src/test/modules/test_pg_dump/meson.build
new file mode 100644
index 00000000000..110b3876832
--- /dev/null
+++ b/src/test/modules/test_pg_dump/meson.build
@@ -0,0 +1,24 @@
+# FIXME: prevent install during main install, but not during test :/
+install_data(
+  'test_pg_dump.control',
+  'test_pg_dump--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_pg_dump',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_pg_dump',
+  ]
+}
+
+tap_tests += {
+  'name': 'test_pg_dump',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests': [
+    't/001_base.pl',
+  ]
+}
diff --git a/src/test/modules/test_predtest/meson.build b/src/test/modules/test_predtest/meson.build
new file mode 100644
index 00000000000..9f9a9475c8b
--- /dev/null
+++ b/src/test/modules/test_predtest/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+test_predtest = shared_module('test_predtest',
+  ['test_predtest.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_predtest.control',
+  'test_predtest--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_predtest',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_predtest',
+  ]
+}
diff --git a/src/test/modules/test_rbtree/meson.build b/src/test/modules/test_rbtree/meson.build
new file mode 100644
index 00000000000..6bbeca39ec9
--- /dev/null
+++ b/src/test/modules/test_rbtree/meson.build
@@ -0,0 +1,20 @@
+# FIXME: prevent install during main install, but not during test :/
+test_rbtree = shared_module('test_rbtree',
+  ['test_rbtree.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_rbtree.control',
+  'test_rbtree--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_rbtree',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_rbtree',
+  ]
+}
diff --git a/src/test/modules/test_regex/meson.build b/src/test/modules/test_regex/meson.build
new file mode 100644
index 00000000000..c5fd92ee1c6
--- /dev/null
+++ b/src/test/modules/test_regex/meson.build
@@ -0,0 +1,21 @@
+# FIXME: prevent install during main install, but not during test :/
+test_regex = shared_module('test_regex',
+  ['test_regex.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_regex.control',
+  'test_regex--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_regex',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_regex',
+    'test_regex_utf8',
+  ]
+}
diff --git a/src/test/modules/test_rls_hooks/meson.build b/src/test/modules/test_rls_hooks/meson.build
new file mode 100644
index 00000000000..fb8b697e160
--- /dev/null
+++ b/src/test/modules/test_rls_hooks/meson.build
@@ -0,0 +1,19 @@
+# FIXME: prevent install during main install, but not during test :/
+test_rls_hooks = shared_module('test_rls_hooks',
+  ['test_rls_hooks.c'],
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_rls_hooks.control',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_rls_hooks',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_rls_hooks',
+  ]
+}
diff --git a/src/test/modules/test_shm_mq/meson.build b/src/test/modules/test_shm_mq/meson.build
new file mode 100644
index 00000000000..159943f861e
--- /dev/null
+++ b/src/test/modules/test_shm_mq/meson.build
@@ -0,0 +1,24 @@
+# FIXME: prevent install during main install, but not during test :/
+test_shm_mq = shared_module('test_shm_mq',
+  files(
+    'setup.c',
+    'test.c',
+    'worker.c',
+  ),
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'test_shm_mq.control',
+  'test_shm_mq--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'test_shm_mq',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'test_shm_mq',
+  ]
+}
diff --git a/src/test/modules/unsafe_tests/meson.build b/src/test/modules/unsafe_tests/meson.build
new file mode 100644
index 00000000000..9ed4d587721
--- /dev/null
+++ b/src/test/modules/unsafe_tests/meson.build
@@ -0,0 +1,9 @@
+regress_tests += {
+  'name': 'unsafe_tests',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'rolenames',
+    'alter_system_table',
+  ],
+}
diff --git a/src/test/modules/worker_spi/meson.build b/src/test/modules/worker_spi/meson.build
new file mode 100644
index 00000000000..a80bd493ea7
--- /dev/null
+++ b/src/test/modules/worker_spi/meson.build
@@ -0,0 +1,23 @@
+# FIXME: prevent install during main install, but not during test :/
+test_worker_spi = shared_module('worker_spi',
+  files(
+    'worker_spi.c',
+  ),
+  kwargs: pg_mod_args,
+)
+
+install_data(
+  'worker_spi.control',
+  'worker_spi--1.0.sql',
+  kwargs: contrib_data_args,
+)
+
+regress_tests += {
+  'name': 'worker_spi',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'sql': [
+    'worker_spi',
+  ],
+  'regress_args': ['--temp-config', files('dynamic.conf'), '--dbname=contrib_regression'],
+}
diff --git a/src/test/recovery/meson.build b/src/test/recovery/meson.build
new file mode 100644
index 00000000000..5678e1d27ae
--- /dev/null
+++ b/src/test/recovery/meson.build
@@ -0,0 +1,33 @@
+tap_tests += {
+  'name': 'recovery',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'tests' : [
+    't/001_stream_rep.pl',
+    't/002_archiving.pl',
+    't/003_recovery_targets.pl',
+    't/004_timeline_switch.pl',
+    't/005_replay_delay.pl',
+    't/006_logical_decoding.pl',
+    't/007_sync_rep.pl',
+    't/008_fsm_truncation.pl',
+    't/009_twophase.pl',
+    't/010_logical_decoding_timelines.pl',
+    't/011_crash_recovery.pl',
+    't/012_subtransactions.pl',
+    't/013_crash_restart.pl',
+    't/014_unlogged_reinit.pl',
+    't/015_promotion_pages.pl',
+    't/016_min_consistency.pl',
+    't/017_shm.pl',
+    't/018_wal_optimize.pl',
+    't/019_replslot_limit.pl',
+    't/020_archive_status.pl',
+    't/021_row_visibility.pl',
+    't/022_crash_temp_files.pl',
+    't/023_pitr_prepared_xact.pl',
+    't/024_archive_recovery.pl',
+    't/025_stuck_on_old_timeline.pl',
+    't/026_overwrite_contrecord.pl',
+  ]
+}
diff --git a/src/test/regress/meson.build b/src/test/regress/meson.build
new file mode 100644
index 00000000000..1a2f7675e87
--- /dev/null
+++ b/src/test/regress/meson.build
@@ -0,0 +1,57 @@
+# also used by isolationtester
+pg_regress_c = files('pg_regress.c')
+pg_regress_inc = include_directories('.')
+
+regress_sources = pg_regress_c + files(
+  'pg_regress_main.c'
+)
+
+pg_regress_cflags = ['-DHOST_TUPLE="frak"', '-DSHELLPROG="/bin/sh"']
+
+pg_regress = executable('pg_regress',
+  regress_sources,
+  c_args: pg_regress_cflags,
+  dependencies: [frontend_code, libpq],
+  kwargs: default_bin_args + {
+    'install': false
+  },
+)
+
+regress_module = shared_module('regress',
+  ['regress.c'],
+  kwargs: pg_mod_args + {
+    'install': false,
+  },
+)
+
+# Get some extra C modules from contrib/spi but mark them as not to be
+# installed.
+# FIXME: avoid the duplication.
+
+shared_module('autoinc',
+  ['../../../contrib/spi/autoinc.c'],
+  kwargs: pg_mod_args + {
+    'install': false,
+  },
+)
+
+shared_module('refint',
+  ['../../../contrib/spi/refint.c'],
+  kwargs: pg_mod_args + {
+    'c_args': refint_cflags + contrib_mod_args['c_args'],
+    'install': false,
+  },
+)
+
+
+regress_tests += {
+  'name': 'main',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'schedule': files('parallel_schedule'),
+  'regress_args': ['--make-testtablespace-dir'],
+  'test_kwargs': {
+    'priority': 50,
+    'timeout': 1000,
+  },
+}
diff --git a/src/test/ssl/meson.build b/src/test/ssl/meson.build
new file mode 100644
index 00000000000..42e34c9f632
--- /dev/null
+++ b/src/test/ssl/meson.build
@@ -0,0 +1,10 @@
+tap_tests += {
+  'name': 'ssl',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'env' : {'with_ssl': get_option('ssl')},
+  'tests': [
+    't/001_ssltests.pl',
+    't/002_scram.pl'
+  ],
+}
diff --git a/src/test/subscription/meson.build b/src/test/subscription/meson.build
new file mode 100644
index 00000000000..31580edd3d3
--- /dev/null
+++ b/src/test/subscription/meson.build
@@ -0,0 +1,33 @@
+tap_tests += {
+  'name': 'subscription',
+  'sd': meson.current_source_dir(),
+  'bd': meson.current_build_dir(),
+  'env' : {'with_icu': icu.found() ? 'yes' : 'no'},
+  'tests': [
+    't/001_rep_changes.pl',
+    't/002_types.pl',
+    't/003_constraints.pl',
+    't/004_sync.pl',
+    't/005_encoding.pl',
+    't/006_rewrite.pl',
+    't/007_ddl.pl',
+    't/008_diff_schema.pl',
+    't/009_matviews.pl',
+    't/010_truncate.pl',
+    't/011_generated.pl',
+    't/012_collation.pl',
+    't/013_partition.pl',
+    't/014_binary.pl',
+    't/015_stream.pl',
+    't/016_stream_subxact.pl',
+    't/017_stream_ddl.pl',
+    't/018_stream_subxact_abort.pl',
+    't/019_stream_subxact_ddl_abort.pl',
+    't/020_messages.pl',
+    't/021_twophase.pl',
+    't/022_twophase_cascade.pl',
+    't/023_twophase_stream.pl',
+    't/024_add_drop_pub.pl',
+    't/100_bugs.pl',
+  ],
+}
diff --git a/src/timezone/meson.build b/src/timezone/meson.build
new file mode 100644
index 00000000000..c3703a5ec7d
--- /dev/null
+++ b/src/timezone/meson.build
@@ -0,0 +1,50 @@
+# files to build into backend
+timezone_sources = files(
+  'localtime.c',
+  'pgtz.c',
+  'strftime.c',
+)
+
+
+timezone_inc = include_directories('.')
+
+timezone_localtime_source = files('localtime.c')
+
+# files needed to build zic utility program
+zic_sources = files(
+   'zic.c'
+)
+
+# we now distribute the timezone data as a single file
+tzdata = files(
+  'data/tzdata.zi'
+)
+
+
+# FIXME: For cross builds, it would need a native built libpgport/pgcommon to
+# build our zic. But for that we'd need to run a good chunk of the configure
+# tests both natively and cross. Unclear if it's worth it.
+if meson.is_cross_build()
+  zic = find_program('zic', native: true, required: false)
+else
+  zic = executable('zic', zic_sources,
+    dependencies: [frontend_code],
+    kwargs: default_bin_args + {'install': false}
+  )
+endif
+
+# FIXME: this used to be sorted - but also isn't actually used
+abbrevs_txt = custom_target('abbrevs.txt',
+  input: tzdata,
+  output: ['abbrevs.txt'],
+  command: [zic, '-P', '-b', 'fat', 'junkdir', '@INPUT@'],
+  capture: true)
+
+tzdata = custom_target('tzdata',
+  input: tzdata,
+  output: ['timezone'],
+  command: [zic, '-d', '@OUTPUT@', '@INPUT@'],
+  install: true,
+  install_dir: get_option('datadir'))
+
+subdir('tznames')
diff --git a/src/timezone/tznames/meson.build b/src/timezone/tznames/meson.build
new file mode 100644
index 00000000000..effd2880ce7
--- /dev/null
+++ b/src/timezone/tznames/meson.build
@@ -0,0 +1,20 @@
+tznames = files(
+  'Africa.txt',
+  'America.txt',
+  'Antarctica.txt',
+  'Asia.txt',
+  'Atlantic.txt',
+  'Australia.txt',
+  'Etc.txt',
+  'Europe.txt',
+  'Indian.txt',
+  'Pacific.txt',
+)
+
+tznames_sets = files(
+  'Default',
+  'Australia',
+  'India')
+
+install_data(tznames, install_dir: get_option('datadir') / 'timezonesets')
+install_data(tznames_sets, install_dir: get_option('datadir') / 'timezonesets')
diff --git a/src/tools/find_meson b/src/tools/find_meson
new file mode 100755
index 00000000000..2d75537374e
--- /dev/null
+++ b/src/tools/find_meson
@@ -0,0 +1,20 @@
+#!/usr/bin/env python3
+
+import os
+import shlex
+import sys
+
+mesonintrospect = os.environ['MESONINTROSPECT']
+components = shlex.split(mesonintrospect)
+
+if len(components) < 2:
+    print(f'expected more, got: {components}')
+    sys.exit(1)
+
+if components[-1] != 'introspect':
+    print('expected introspection at the end')
+    sys.exit(1)
+
+print('\n'.join(components[:-1]), end='')
+
+sys.exit(0)
diff --git a/src/tools/irlink b/src/tools/irlink
new file mode 100644
index 00000000000..efc2c700277
--- /dev/null
+++ b/src/tools/irlink
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+set -e
+
+srcdir="$1"
+builddir="$2"
+llvm_lto="$3"
+outputdir=$(realpath "$5")
+index="$outputdir/postgres.index.bc"
+priv="$6"
+shift 6
+numinput=$#
+
+if [ ! -d "$outputdir" ];then
+    mkdir -p "$outputdir/postgres"
+fi
+
+cd $priv
+
+# fixme, remove old contents"
+cp -r . "$outputdir/postgres"
+
+cd "$outputdir"
+
+filenames=$(for f in "$@";do echo "postgres/${f#$priv/}";done)
+"$llvm_lto" -thinlto -thinlto-action=thinlink -o "$index" $filenames
+
+exit 0
diff --git a/src/tools/msvc/export2def.pl b/src/tools/msvc/export2def.pl
new file mode 100644
index 00000000000..fb88e8b8ab9
--- /dev/null
+++ b/src/tools/msvc/export2def.pl
@@ -0,0 +1,22 @@
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+use 5.8.0;
+use List::Util qw(max);
+
+my ($deffile, $txtfile, $libname) = @ARGV;
+
+print STDERR "Generating $deffile...\n";
+open(my $if, '<', $txtfile) || die("Could not open $txtfile\n");
+open(my $of, '>', $deffile) || die("Could not open $deffile for writing\n");
+print $of "LIBRARY $libname\nEXPORTS\n";
+while (<$if>)
+{
+	next if (/^#/);
+	next if (/^\s*$/);
+	my ($f, $o) = split;
+	print $of " $f @ $o\n";
+}
+close($of);
+close($if);
diff --git a/src/tools/msvc/gendef2.pl b/src/tools/msvc/gendef2.pl
new file mode 100644
index 00000000000..3b905d6f5da
--- /dev/null
+++ b/src/tools/msvc/gendef2.pl
@@ -0,0 +1,177 @@
+
+# Copyright (c) 2021, PostgreSQL Global Development Group
+
+use strict;
+use warnings;
+use 5.8.0;
+use List::Util qw(max);
+
+my @def;
+
+#
+# Script that generates a .DEF file for all objects in a directory
+#
+# src/tools/msvc/gendef.pl
+#
+
+# Given a symbol file path, loops over its contents
+# and returns a list of symbols of interest as a dictionary
+# of 'symbolname' -> symtype, where symtype is:
+#
+#     0    a CODE symbol, left undecorated in the .DEF
+#     1    A DATA symbol, i.e. global var export
+#
+sub extract_syms
+{
+	my ($symfile, $def) = @_;
+	open(my $f, '<', $symfile) || die "Could not open $symfile: $!\n";
+	while (<$f>)
+	{
+
+		# Expected symbol lines look like:
+		#
+		# 0   1        2      3            4            5 6
+		# IDX SYMBOL   SECT   SYMTYPE      SYMSTATIC      SYMNAME
+		# ------------------------------------------------------------------------
+		# 02E 00000130 SECTA  notype       External     | _standbyState
+		# 02F 00000009 SECT9  notype       Static       | _LocalRecoveryInProgress
+		# 064 00000020 SECTC  notype ()    Static       | _XLogCheckBuffer
+		# 065 00000000 UNDEF  notype ()    External     | _BufferGetTag
+		#
+		# See http://msdn.microsoft.com/en-us/library/b842y285.aspx
+		#
+		# We're not interested in the symbol index or offset.
+		#
+		# SECT[ION] is only examined to see whether the symbol is defined in a
+		# COFF section of the local object file; if UNDEF, it's a symbol to be
+		# resolved at link time from another object so we can't export it.
+		#
+		# SYMTYPE is always notype for C symbols as there's no typeinfo and no
+		# way to get the symbol type from name (de)mangling. However, we care
+		# if "notype" is suffixed by "()" or not. The presence of () means the
+		# symbol is a function, the absence means it isn't.
+		#
+		# SYMSTATIC indicates whether it's a compilation-unit local "static"
+		# symbol ("Static"), or whether it's available for use from other
+		# compilation units ("External"). We export all symbols that aren't
+		# static as part of the whole program DLL interface to produce UNIX-like
+		# default linkage.
+		#
+		# SYMNAME is, obviously, the symbol name. The leading underscore
+		# indicates that the _cdecl calling convention is used. See
+		# http://www.unixwiz.net/techtips/win32-callconv.html
+		# http://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
+		#
+		s/notype \(\)/func/g;
+		s/notype/data/g;
+
+		my @pieces = split;
+
+		# Skip file and section headers and other non-symbol entries
+		next unless defined($pieces[0]) and $pieces[0] =~ /^[A-F0-9]{3,}$/;
+
+		# Skip blank symbol names
+		next unless $pieces[6];
+
+		# Skip externs used from another compilation unit
+		next if ($pieces[2] eq "UNDEF");
+
+		# Skip static symbols
+		next unless ($pieces[4] eq "External");
+
+		# Skip some more MSVC-generated crud
+		next if $pieces[6] =~ /^@/;
+		next if $pieces[6] =~ /^\(/;
+
+		# __real and __xmm are out-of-line floating point literals and
+		# (for __xmm) their SIMD equivalents. They shouldn't be part
+		# of the DLL interface.
+		next if $pieces[6] =~ /^__real/;
+		next if $pieces[6] =~ /^__xmm/;
+
+		# __imp entries are imports from other DLLs, eg __imp__malloc .
+		# (We should never have one of these that hasn't already been skipped
+		# by the UNDEF test above, though).
+		next if $pieces[6] =~ /^__imp/;
+
+		# More under-documented internal crud
+		next if $pieces[6] =~ /NULL_THUNK_DATA$/;
+		next if $pieces[6] =~ /^__IMPORT_DESCRIPTOR/;
+		next if $pieces[6] =~ /^__NULL_IMPORT/;
+
+		# Skip string literals
+		next if $pieces[6] =~ /^\?\?_C/;
+
+		# We assume that if a symbol is defined as data, then as a function,
+		# the linker will reject the binary anyway. So it's OK to just pick
+		# whatever came last.
+		$def->{ $pieces[6] } = $pieces[3];
+	}
+	close($f);
+	return;
+}
+
+sub writedef
+{
+	my ($deffile, $platform, $def) = @_;
+	open(my $fh, '>', $deffile) || die "Could not write to $deffile\n";
+	print $fh "EXPORTS\n";
+	foreach my $f (sort keys %{$def})
+	{
+		my $isdata = $def->{$f} eq 'data';
+
+		# Strip the leading underscore for win32, but not x64
+		$f =~ s/^_//
+		  unless ($platform eq "x64");
+
+		# Emit just the name if it's a function symbol, or emit the name
+		# decorated with the DATA option for variables.
+		if ($isdata)
+		{
+			print $fh "  $f DATA\n";
+		}
+		else
+		{
+			print $fh "  $f\n";
+		}
+	}
+	close($fh);
+	return;
+}
+
+
+sub usage
+{
+	die(    "Usage: gendef.pl platform outputfile tempdir sourcelib\n"
+		  . "    modulepath: path to dir with obj files, no trailing slash"
+		  . "    platform: Win32 | x64");
+}
+
+usage()
+  unless scalar(@ARGV) >= 4;
+
+my $platform  = $ARGV[0];
+shift;
+my $deffile  = $ARGV[0];
+shift;
+my $tempdir  = $ARGV[0];
+shift;
+
+print STDERR "Generating $deffile in tmp dir $tempdir from ".join(' ', @ARGV)."\n";
+
+my %def = ();
+
+my $symfile = "$tempdir/all.sym";
+my $tmpfile = "$tempdir/tmp.sym";
+mkdir($tempdir);
+print STDERR "dumpbin /symbols /out:$tmpfile ".join(' ', @ARGV)."\n";
+system("dumpbin /symbols /out:$tmpfile ".join(' ', @ARGV))
+  && die "Could not call dumpbin";
+rename($tmpfile, $symfile);
+print "generated symfile to $symfile (via $tmpfile)\n";
+extract_syms($symfile, \%def);
+print "\n";
+
+writedef($deffile, $platform, \%def);
+
+print "Generated " . scalar(keys(%def)) . " symbols\n";
diff --git a/src/tools/testwrap b/src/tools/testwrap
new file mode 100755
index 00000000000..aeb2019b099
--- /dev/null
+++ b/src/tools/testwrap
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# FIXME: I should probably be a perl or python script
+#
+
+# FIXME: argument parsing
+
+basedir=$1
+builddir=$2
+testgroup=$3
+testname=$(basename -s .pl $4)
+shift 4
+
+testdir="$basedir/testrun/$testgroup/$testname"
+echo "# executing test in $testdir group $testgroup test $testname, builddir $builddir"
+rm -rf "$testdir/"
+mkdir -p "$testdir"
+
+export TESTOUTDIR="$testdir"
+export TESTDIR="$builddir"
+
+exec "$@"
-- 
2.23.0.385.gbc12974a89

