From 641af4be44511dfde8df858faf952030821e8536 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 27 Aug 2022 09:49:53 -0700
Subject: [PATCH v12 15/15] meson: Add support for building with precompiled
 headers

This substantially speeds up building for windows. A cross build with mingw
goes from

real	0m29.884s
user	15m41.900s
sys	1m58.257s

to

real	0m13.196s
user	6m52.330s
sys	1m15.140s

The wins on windows are similar-ish (but I don't have a system at hand just
now for actual numbers).
---
 src/include/meson.build           | 1 +
 src/include/pch/c_pch.h           | 1 +
 src/include/pch/meson.build       | 4 ++++
 src/include/pch/postgres_fe_pch.h | 1 +
 src/include/pch/postgres_pch.h    | 1 +
 src/common/meson.build            | 2 ++
 src/port/meson.build              | 2 ++
 src/backend/meson.build           | 5 +++++
 src/backend/snowball/meson.build  | 1 +
 src/fe_utils/meson.build          | 1 +
 src/bin/pg_dump/meson.build       | 1 +
 src/bin/pg_upgrade/meson.build    | 1 +
 src/bin/psql/meson.build          | 1 +
 src/pl/plperl/meson.build         | 1 +
 src/pl/plpgsql/src/meson.build    | 1 +
 src/pl/plpython/meson.build       | 1 +
 src/pl/tcl/meson.build            | 1 +
 contrib/bloom/meson.build         | 1 +
 contrib/btree_gist/meson.build    | 1 +
 contrib/hstore/meson.build        | 1 +
 contrib/pg_trgm/meson.build       | 1 +
 contrib/pgcrypto/meson.build      | 1 +
 contrib/pgstattuple/meson.build   | 1 +
 contrib/sepgsql/meson.build       | 1 +
 contrib/xml2/meson.build          | 1 +
 .cirrus.yml                       | 4 ++--
 meson.build                       | 8 ++++++++
 27 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 src/include/pch/c_pch.h
 create mode 100644 src/include/pch/meson.build
 create mode 100644 src/include/pch/postgres_fe_pch.h
 create mode 100644 src/include/pch/postgres_pch.h

diff --git a/src/include/meson.build b/src/include/meson.build
index 66991c43d35..d1b58f14842 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -111,6 +111,7 @@ install_headers(
 subdir('catalog')
 subdir('nodes')
 subdir('parser')
+subdir('pch')
 subdir('storage')
 subdir('utils')
 
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/meson.build b/src/include/pch/meson.build
new file mode 100644
index 00000000000..2bcec49c3a2
--- /dev/null
+++ b/src/include/pch/meson.build
@@ -0,0 +1,4 @@
+# See https://github.com/mesonbuild/meson/issues/10338
+pch_c_h = meson.source_root() / meson.current_source_dir() / 'c_pch.h'
+pch_postgres_h = meson.source_root() / meson.current_source_dir() / 'postgres_pch.h'
+pch_postgres_fe_h = meson.source_root() / meson.current_source_dir() / 'postgres_fe_pch.h'
diff --git a/src/include/pch/postgres_fe_pch.h b/src/include/pch/postgres_fe_pch.h
new file mode 100644
index 00000000000..f3ea20912d3
--- /dev/null
+++ b/src/include/pch/postgres_fe_pch.h
@@ -0,0 +1 @@
+#include "postgres_fe.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/common/meson.build b/src/common/meson.build
index 23842e1ffef..1c9b8a3a018 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -147,6 +147,7 @@ foreach name, opts : pgcommon_variants
     endif
     c_args = opts.get('c_args', []) + common_cflags[cflagname]
     cflag_libs += static_library('libpgcommon@0@_@1@'.format(name, cflagname),
+      c_pch: pch_c_h,
       include_directories: include_directories('.'),
       kwargs: opts + {
         'sources': sources,
@@ -159,6 +160,7 @@ foreach name, opts : pgcommon_variants
 
   lib = static_library('libpgcommon@0@'.format(name),
       link_with: cflag_libs,
+      c_pch: pch_c_h,
       include_directories: include_directories('.'),
       kwargs: opts + {
         'dependencies': opts['dependencies'] + [ssl],
diff --git a/src/port/meson.build b/src/port/meson.build
index ced2e014db8..c2222696f1b 100644
--- a/src/port/meson.build
+++ b/src/port/meson.build
@@ -161,6 +161,7 @@ foreach name, opts : pgport_variants
     c_args = opts.get('c_args', []) + pgport_cflags[cflagname]
     cflag_libs += static_library('libpgport@0@_@1@'.format(name, cflagname),
       sources,
+      c_pch: pch_c_h,
       kwargs: opts + {
         'c_args': c_args,
         'build_by_default': false,
@@ -172,6 +173,7 @@ foreach name, opts : pgport_variants
   lib = static_library('libpgport@0@'.format(name),
       pgport_sources,
       link_with: cflag_libs,
+      c_pch: pch_c_h,
       kwargs: opts + {
         'dependencies': opts['dependencies'] + [ssl],
       }
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 3a2fc51bda3..784a8ba7072 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -59,6 +59,7 @@ postgres_lib = static_library('postgres',
   backend_sources + timezone_sources + generated_backend_sources,
   link_whole: backend_link_with,
   dependencies: backend_build_deps,
+  c_pch: pch_postgres_h,
   kwargs: internal_lib_args,
 )
 
@@ -78,6 +79,10 @@ if cc.get_id() == 'msvc'
 
   backend_link_args += '/DEF:@0@'.format(postgres_def.full_path())
   backend_link_depends += postgres_def
+  # Due to the way msvc and meson's precompiled headers implementation
+  # interact, we need to have symbols from the full library available. Could
+  # be restricted to b_pch=true.
+  backend_link_with += postgres_lib
 
 elif host_system == 'aix'
   # The '.' argument leads mkldexport.sh to emit "#! .", which refers to the
diff --git a/src/backend/snowball/meson.build b/src/backend/snowball/meson.build
index 8c6f685cb32..2747026c729 100644
--- a/src/backend/snowball/meson.build
+++ b/src/backend/snowball/meson.build
@@ -60,6 +60,7 @@ stemmer_inc = include_directories('../../include/snowball')
 
 dict_snowball = shared_module('dict_snowball',
   dict_snowball_sources,
+  c_pch: pch_postgres_h,
   kwargs: pg_mod_args + {
     'include_directories': [stemmer_inc],
   }
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index 29c24257328..6e1cce9bd0d 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -23,6 +23,7 @@ fe_utils_sources += psqlscan
 
 fe_utils = static_library('libpgfeutils',
   fe_utils_sources + generated_headers,
+  c_pch: pch_postgres_fe_h,
   include_directories: [postgres_inc, libpq_inc],
   dependencies: frontend_common_code,
   kwargs: default_lib_args,
diff --git a/src/bin/pg_dump/meson.build b/src/bin/pg_dump/meson.build
index ee8daa7d06a..9be697daef4 100644
--- a/src/bin/pg_dump/meson.build
+++ b/src/bin/pg_dump/meson.build
@@ -23,6 +23,7 @@ endif
 
 pg_dump_common = static_library('libpgdump_common',
   pg_dump_common_sources,
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_code, libpq, zlib],
   kwargs: internal_lib_args,
 )
diff --git a/src/bin/pg_upgrade/meson.build b/src/bin/pg_upgrade/meson.build
index 52324601181..59e06b761fd 100644
--- a/src/bin/pg_upgrade/meson.build
+++ b/src/bin/pg_upgrade/meson.build
@@ -18,6 +18,7 @@ pg_upgrade_sources = files(
 
 pg_upgrade = executable('pg_upgrade',
   pg_upgrade_sources,
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_code, libpq],
   kwargs: default_bin_args,
 )
diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build
index 626ac8cd105..20939b0740c 100644
--- a/src/bin/psql/meson.build
+++ b/src/bin/psql/meson.build
@@ -48,6 +48,7 @@ endif
 
 executable('psql',
   psql_sources,
+  c_pch: pch_postgres_fe_h,
   include_directories: include_directories('.'),
   dependencies: [frontend_code, libpq, readline],
   kwargs: default_bin_args,
diff --git a/src/pl/plperl/meson.build b/src/pl/plperl/meson.build
index 6831011edac..5be58ceaa19 100644
--- a/src/pl/plperl/meson.build
+++ b/src/pl/plperl/meson.build
@@ -41,6 +41,7 @@ endforeach
 plperl_inc = include_directories('.')
 shared_module('plperl',
   plperl_sources,
+  c_pch: pch_postgres_h,
   include_directories: [plperl_inc, postgres_inc],
   kwargs: pg_mod_args + {
     'dependencies': [perl_dep, pg_mod_args['dependencies']],
diff --git a/src/pl/plpgsql/src/meson.build b/src/pl/plpgsql/src/meson.build
index c4c94a312e1..39302f8d032 100644
--- a/src/pl/plpgsql/src/meson.build
+++ b/src/pl/plpgsql/src/meson.build
@@ -42,6 +42,7 @@ plpgsql_sources += pl_unreserved
 
 shared_module('plpgsql',
   plpgsql_sources,
+  c_pch: pch_postgres_h,
   include_directories: include_directories('.'),
   kwargs: pg_mod_args,
 )
diff --git a/src/pl/plpython/meson.build b/src/pl/plpython/meson.build
index e9e77ae3691..d41f30c8022 100644
--- a/src/pl/plpython/meson.build
+++ b/src/pl/plpython/meson.build
@@ -30,6 +30,7 @@ plpython_inc = include_directories('.')
 
 shared_module('plpython3',
   plpython_sources,
+  c_pch: pch_postgres_h,
   include_directories: [plpython_inc, postgres_inc],
   kwargs: pg_mod_args + {
     'dependencies': [python3_dep, pg_mod_args['dependencies']],
diff --git a/src/pl/tcl/meson.build b/src/pl/tcl/meson.build
index 1acb49f1637..16bfd7806b4 100644
--- a/src/pl/tcl/meson.build
+++ b/src/pl/tcl/meson.build
@@ -16,6 +16,7 @@ pltcl_sources += custom_target('pltclerrcodes.h',
 
 shared_module('pltcl',
   pltcl_sources,
+  c_pch: pch_postgres_h,
   include_directories: [include_directories('.'), postgres_inc],
   kwargs: pg_mod_args + {
     'dependencies': [tcl_dep, pg_mod_args['dependencies']],
diff --git a/contrib/bloom/meson.build b/contrib/bloom/meson.build
index 311cc10c557..f2a73b06667 100644
--- a/contrib/bloom/meson.build
+++ b/contrib/bloom/meson.build
@@ -9,6 +9,7 @@ bloom_sources = files(
 
 bloom = shared_module('bloom',
   bloom_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 
diff --git a/contrib/btree_gist/meson.build b/contrib/btree_gist/meson.build
index 6bd91b88fc3..f33bae7f8fe 100644
--- a/contrib/btree_gist/meson.build
+++ b/contrib/btree_gist/meson.build
@@ -27,6 +27,7 @@ btree_gist_sources = files(
 
 btree_gist = shared_module('btree_gist',
   btree_gist_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 
diff --git a/contrib/hstore/meson.build b/contrib/hstore/meson.build
index 369c60d7f40..cac6d179351 100644
--- a/contrib/hstore/meson.build
+++ b/contrib/hstore/meson.build
@@ -10,6 +10,7 @@ hstore = shared_module('hstore',
     'hstore_op.c',
     'hstore_subs.c',
   ),
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 
diff --git a/contrib/pg_trgm/meson.build b/contrib/pg_trgm/meson.build
index 37931279f65..6818cddc63f 100644
--- a/contrib/pg_trgm/meson.build
+++ b/contrib/pg_trgm/meson.build
@@ -5,6 +5,7 @@ pg_trgm = shared_module('pg_trgm',
     'trgm_op.c',
     'trgm_regexp.c',
   ),
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 
diff --git a/contrib/pgcrypto/meson.build b/contrib/pgcrypto/meson.build
index 647bea8559e..ec022096c31 100644
--- a/contrib/pgcrypto/meson.build
+++ b/contrib/pgcrypto/meson.build
@@ -72,6 +72,7 @@ endif
 pgcrypto = shared_module('pgcrypto',
   pgcrypto_sources,
   link_with: pgcrypto_link_with,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args + {
     'dependencies': [pgcrypto_deps, contrib_mod_args['dependencies']]
   },
diff --git a/contrib/pgstattuple/meson.build b/contrib/pgstattuple/meson.build
index 190f8b5d92b..8e765fc997a 100644
--- a/contrib/pgstattuple/meson.build
+++ b/contrib/pgstattuple/meson.build
@@ -4,6 +4,7 @@ pgstattuple = shared_module('pgstattuple',
     'pgstatindex.c',
     'pgstattuple.c',
   ),
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 
diff --git a/contrib/sepgsql/meson.build b/contrib/sepgsql/meson.build
index 83e74f035b1..019c31750f2 100644
--- a/contrib/sepgsql/meson.build
+++ b/contrib/sepgsql/meson.build
@@ -16,6 +16,7 @@ sepgsql_sources = files(
 
 sepgsql = shared_module('sepgsql',
   sepgsql_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args + {
     'dependencies': [selinux, contrib_mod_args['dependencies']],
   }
diff --git a/contrib/xml2/meson.build b/contrib/xml2/meson.build
index dcc7bf5bf69..d25549a1fb3 100644
--- a/contrib/xml2/meson.build
+++ b/contrib/xml2/meson.build
@@ -7,6 +7,7 @@ xml2 = shared_module('pgxml',
     'xpath.c',
     'xslt_proc.c',
   ),
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args + {
     'dependencies': [libxml, libxslt, contrib_mod_args['dependencies']],
   },
diff --git a/.cirrus.yml b/.cirrus.yml
index 37fc5b551ec..88975bb017d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1158,7 +1158,7 @@ task:
 
   configure_script:
     - vcvarsall x64
-    - meson setup --buildtype debug --backend ninja  -Dcassert=true -Dssl=openssl -Dlz4=enabled -Dzlib=enabled -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe build
+    - meson setup --buildtype debug --backend ninja  -Dcassert=true -Db_pch=true -Dssl=openssl -Dlz4=enabled -Dzlib=enabled -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe build
 
   build_script:
     - vcvarsall x64
@@ -1185,7 +1185,7 @@ task:
 
   configure_script:
     - vcvarsall x64
-    - meson setup --buildtype debug --backend vs -Dcassert=true -Dssl=openssl -Dlz4=enabled -Dzlib=enabled -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe build
+    - meson setup --buildtype debug --backend vs -Dcassert=true -Db_pch=true -Dssl=openssl -Dlz4=enabled -Dzlib=enabled -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe build
 
   build_script:
     - vcvarsall x64
diff --git a/meson.build b/meson.build
index b9eaad73628..bf4e561be89 100644
--- a/meson.build
+++ b/meson.build
@@ -9,6 +9,7 @@ project('postgresql',
   meson_version: '>=0.54',
   default_options: [
     'warning_level=2',
+    'b_pch=false',
     'buildtype=release',
   ]
 )
@@ -1716,6 +1717,13 @@ if cc.get_id() == 'msvc'
     '/wd4267',
   ]
 
+  # Dirty hack to disable warnings due to some files defining
+  # UMDF_USING_NTSTATUS before including postgres.h. We need a better fix, but
+  # for now this allows us to see "real" warnings.
+  if get_option('b_pch')
+    cflags_warn += '/wd4005'
+  endif
+
   cppflags += [
     '/DWIN32',
     '/DWINDOWS',
-- 
2.37.0.3.g30cc8d0f14

