meson: Add support for building with precompiled headers
authorAndres Freund <andres@anarazel.de>
Fri, 7 Oct 2022 00:19:30 +0000 (17:19 -0700)
committerAndres Freund <andres@anarazel.de>
Fri, 7 Oct 2022 00:19:30 +0000 (17:19 -0700)
This substantially speeds up building for windows, due to the vast amount of
headers included via windows.h. A cross build from linux targetting mingw goes
from

994.11user 136.43system 0:31.58elapsed 3579%CPU
to
422.41user 89.05system 0:14.35elapsed 3562%CPU

The wins on windows are similar-ish (but I don't have a system at hand just
now for actual numbers). Targetting other operating systems the wins are far
smaller (tested linux, macOS, FreeBSD).

For now precompiled headers are disabled by default, it's not clear how well
they work on all platforms. E.g. on FreeBSD gcc doesn't seem to have working
support, but clang does.

When doing a full build precompiled headers are only beneficial for targets
with multiple .c files, as meson builds a separate precompiled header for each
target (so that different compilation options take effect). This commit
therefore only changes target with at least two .c files to use precompiled
headers.

Because this commit adds b_pch=false to the default_options new build
directories will have precompiled headers disabled by default, however
existing build directories will continue use the default value of b_pch, which
is true.

Note that using precompiled headers with ccache requires setting
CCACHE_SLOPPINESS=pch_defines,time_macros to get hits.

Reviewed-by: Peter Eisentraut <peter.eisentraut@enterprisedb.com>
Reviewed-by: Justin Pryzby <pryzby@telsasoft.com>
Discussion: https://postgr.es/m/CA+hUKG+50eOUbN++ocDc0Qnp9Pvmou23DSXu=ZA6fepOcftKqA@mail.gmail.com
Discussion: https://postgr.es/m/c5736f70-bb6d-8d25-e35c-e3d886e4e905@enterprisedb.com
Discussion: https://postgr.es/m/20190826054000.GE7005%40paquier.xyz

32 files changed:
.cirrus.yml
contrib/bloom/meson.build
contrib/btree_gist/meson.build
contrib/hstore/meson.build
contrib/pg_trgm/meson.build
contrib/pgcrypto/meson.build
contrib/pgstattuple/meson.build
contrib/sepgsql/meson.build
contrib/xml2/meson.build
meson.build
src/backend/meson.build
src/backend/snowball/meson.build
src/bin/pg_dump/meson.build
src/bin/pg_upgrade/meson.build
src/bin/pgbench/meson.build
src/bin/psql/meson.build
src/common/meson.build
src/fe_utils/meson.build
src/include/meson.build
src/include/pch/c_pch.h [new file with mode: 0644]
src/include/pch/meson.build [new file with mode: 0644]
src/include/pch/postgres_fe_pch.h [new file with mode: 0644]
src/include/pch/postgres_pch.h [new file with mode: 0644]
src/interfaces/ecpg/ecpglib/meson.build
src/interfaces/ecpg/pgtypeslib/meson.build
src/interfaces/ecpg/preproc/meson.build
src/interfaces/libpq/meson.build
src/pl/plperl/meson.build
src/pl/plpgsql/src/meson.build
src/pl/plpython/meson.build
src/pl/tcl/meson.build
src/port/meson.build

index 531cfe96f658f5eb6a13c061d5436fe41bafb8b6..9f2282471a9290d29e3ed7feb5790c3f1b471a2d 100644 (file)
@@ -447,7 +447,7 @@ task:
   # Use /DEBUG:FASTLINK to avoid high memory usage during linking
   configure_script: |
     vcvarsall x64
-    meson setup --backend ninja --buildtype debug -Dc_link_args=/DEBUG:FASTLINK -Dcassert=true -Dssl=openssl -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe -DPG_TEST_EXTRA="%PG_TEST_EXTRA%" build
+    meson setup --backend ninja --buildtype debug -Dc_link_args=/DEBUG:FASTLINK -Dcassert=true -Db_pch=true -Dssl=openssl -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe -DPG_TEST_EXTRA="%PG_TEST_EXTRA%" build
 
   build_script: |
     vcvarsall x64
index 16f3b83e4d2f1d4f4f5c82914d5a0e07c7cd5036..163a93c98fb3697494876e161802957679bfd643 100644 (file)
@@ -15,6 +15,7 @@ endif
 
 bloom = shared_module('bloom',
   bloom_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 contrib_targets += bloom
index e98c91dacc8114c56667d2ce70a5c6a6b379e693..bfb7865d2132809c1cc9c6749151f076b63e3eb1 100644 (file)
@@ -33,6 +33,7 @@ endif
 
 btree_gist = shared_module('btree_gist',
   btree_gist_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 contrib_targets += btree_gist
index 2bb26bb772b1e30b28a9f37a1d189ff7707d1edb..a2a4ec36cb0ed2719e3c8c145c39176389b1f7c9 100644 (file)
@@ -18,6 +18,7 @@ endif
 
 hstore = shared_module('hstore',
   hstore_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 contrib_targets += hstore
index c8c7c07b308ac8f85bff0e18fade5d397717c4aa..839d6c4a7f64ea56fbaec9889410a00cafee33cc 100644 (file)
@@ -13,6 +13,7 @@ endif
 
 pg_trgm = shared_module('pg_trgm',
   pg_trgm_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 contrib_targets += pg_trgm
index 7fc7bbc7ca14279ab282ce4aff1ec89a1055e6b2..cc782578b49baae4988f685ae5a0f2e5a461c26b 100644 (file)
@@ -78,6 +78,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']]
   },
index 05e4cd46a5c71fd06455c682063add2898b05dd5..42d0b0e6ce96694fe1d594bc6fbeba1e296bd6fd 100644 (file)
@@ -12,6 +12,7 @@ endif
 
 pgstattuple = shared_module('pgstattuple',
   pgstattuple_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args,
 )
 contrib_targets += pgstattuple
index 8bef239e3c2e7f7a993793a21ce956a011dc4fb5..1ac0fa388ab1faf40d3619fe76bd3a4ddf734010 100644 (file)
@@ -22,6 +22,7 @@ endif
 
 sepgsql = shared_module('sepgsql',
   sepgsql_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args + {
     'dependencies': [selinux, contrib_mod_args['dependencies']],
   }
index 89b0d677516036e51d33842268426f0919606a31..92ab3368428caac4c00f58e942237765dcc2c1a4 100644 (file)
@@ -15,6 +15,7 @@ endif
 
 xml2 = shared_module('pgxml',
   xml2_sources,
+  c_pch: pch_postgres_h,
   kwargs: contrib_mod_args + {
     'dependencies': [libxml, libxslt, contrib_mod_args['dependencies']],
   },
index 25a6fa941ccb7390354b8076081562eb55f9136f..f0cb01c001576b226ebd983b00bcc6c18f71fd33 100644 (file)
@@ -15,6 +15,7 @@ project('postgresql',
   meson_version: '>=0.54',
   default_options: [
     'warning_level=1', #-Wall equivalent
+    'b_pch=false',
     'buildtype=release',
     # For compatibility with the autoconf build, set a default prefix. This
     # works even on windows, where it's a drive-relative path (i.e. when on
index 6f4cd6ceb09781369868cd5500bd21ee14698275..37562bae1324bb7f773cf1a1022e5573165edb08 100644 (file)
@@ -62,6 +62,7 @@ postgres_lib = static_library('postgres_lib',
   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,
 )
 
@@ -81,6 +82,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
index 974401d187ee8fe9f331cfaf029f23849ea9ac1f..72959fa29d609b3a8add08b64ed053fe4aff5f2b 100644 (file)
@@ -66,6 +66,7 @@ endif
 
 dict_snowball = shared_module('dict_snowball',
   dict_snowball_sources,
+  c_pch: pch_postgres_h,
   kwargs: pg_mod_args + {
     'include_directories': [stemmer_inc],
   }
index 3527a25c288115e3fec9bcdfb486ce54216a4365..e66f632b54e5e300035a7de16d101b7b11d54df7 100644 (file)
@@ -13,6 +13,7 @@ pg_dump_common_sources = files(
 
 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,
 )
index a7b927a45c7f333c2af57771095c1f7ca35a2d7f..212bc9ce6ef0c21bb7e3c497506eb22f5b42fa93 100644 (file)
@@ -24,6 +24,7 @@ endif
 
 pg_upgrade = executable('pg_upgrade',
   pg_upgrade_sources,
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_code, libpq],
   kwargs: default_bin_args,
 )
index 3cc393d17eacf841a01e0c30dbd74232bc763e5e..1a3ec5d12950cafb67a09490564ff70526a07146 100644 (file)
@@ -27,6 +27,7 @@ pgbench = executable('pgbench',
   pgbench_sources,
   dependencies: [frontend_code, libpq, thread_dep],
   include_directories: include_directories('.'),
+  c_pch: pch_postgres_fe_h,
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
   kwargs: default_bin_args,
 )
index 1264fc19fbd8e47f62118c1f3c00d4adbb31b263..a4c46bf5385d953211c589ba5205b549ffc820e5 100644 (file)
@@ -44,6 +44,7 @@ endif
 
 psql = executable('psql',
   psql_sources,
+  c_pch: pch_postgres_fe_h,
   include_directories: include_directories('.'),
   dependencies: [frontend_code, libpq, readline],
   kwargs: default_bin_args,
index 23842e1ffefb8efd7457207d48c15f3a601e718b..1c9b8a3a018276b3012a18efd072a803ff489467 100644 (file)
@@ -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],
index 3e226c260acd8b50172e42672d01db11bd4f5893..fe0b801387cce7eff2855f72772f0a73c03a74b9 100644 (file)
@@ -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],
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
   dependencies: frontend_common_code,
index f2f7d03ff27688d577180cb941d4d23686bf4547..35c06c4856a5928c998c78ce0504ee7e1e92b2af 100644 (file)
@@ -114,6 +114,7 @@ install_headers(
 
 subdir('catalog')
 subdir('nodes')
+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 (file)
index 0000000..f40c757
--- /dev/null
@@ -0,0 +1 @@
+#include "c.h"
diff --git a/src/include/pch/meson.build b/src/include/pch/meson.build
new file mode 100644 (file)
index 0000000..2bcec49
--- /dev/null
@@ -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 (file)
index 0000000..f3ea209
--- /dev/null
@@ -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 (file)
index 0000000..71b2f35
--- /dev/null
@@ -0,0 +1 @@
+#include "postgres.h"
index 7e6e6fbf5c0fc3281459916ea188a3891aa7e502..2d07da1ff4c69178f1f9caf22ce44fb2a7ccd42c 100644 (file)
@@ -27,6 +27,7 @@ ecpglib_st = static_library('libecpg',
   ecpglib_sources,
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_stlib_code, thread_dep, libpq],
   link_with: [ecpg_pgtypes_st],
   kwargs: default_lib_args,
@@ -37,6 +38,7 @@ ecpglib_so = shared_library('libecpg',
   ecpglib_sources + ecpglib_so_sources,
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_shlib_code, libpq, thread_dep],
   link_with: ecpg_pgtypes_so,
   soversion: host_system != 'windows' ? '6' : '',
index 530dd2c602dc4333c9748f6e9e23a692af4cd78a..d7e1a94d24d0fc3cb368f0c1445da72e6838a87b 100644 (file)
@@ -23,6 +23,7 @@ ecpg_pgtypes_st = static_library('libpgtypes',
   ecpg_pgtypes_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
+  c_pch: pch_postgres_fe_h,
   dependencies: frontend_stlib_code,
   kwargs: default_lib_args,
 )
@@ -32,6 +33,7 @@ ecpg_pgtypes_so = shared_library('libpgtypes',
   ecpg_pgtypes_sources + ecpg_pgtypes_so_sources,
   include_directories: ecpg_pgtypes_inc,
   c_args: ecpg_pgtypes_c_args,
+  c_pch: pch_postgres_fe_h,
   dependencies: frontend_shlib_code,
   version: '3.' + pg_version_major.to_string(),
   soversion: host_system != 'windows' ? '3' : '',
index 74876f039c9f0fde40fc8490405a7e6f5a4fc7fe..3d42ee439fff255099a5839b0e0155f51904a35c 100644 (file)
@@ -102,6 +102,7 @@ endif
 ecpg_exe = executable('ecpg',
   ecpg_sources,
   include_directories: ['.', ecpg_inc, postgres_inc, libpq_inc],
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_code],
   kwargs: default_bin_args,
 )
index 533b2e6f773f933aaa77a867ee8915372202a508..8e696f1183cff44061641753b1779873b92535a1 100644 (file)
@@ -58,6 +58,7 @@ libpq_st = static_library('libpq',
   libpq_sources,
   include_directories: [libpq_inc],
   c_args: libpq_c_args,
+  c_pch: pch_postgres_fe_h,
   dependencies: [frontend_stlib_code, libpq_deps],
   kwargs: default_lib_args,
 )
@@ -66,6 +67,7 @@ libpq_so = shared_library('libpq',
   libpq_sources + libpq_so_sources,
   include_directories: [libpq_inc, postgres_inc],
   c_args: libpq_c_args,
+  c_pch: pch_postgres_fe_h,
   version: '5.' + pg_version_major.to_string(),
   soversion: host_system != 'windows' ? '5' : '',
   darwin_versions: ['5', '5.' + pg_version_major.to_string()],
index 535660085dd6580d4f1033247dab59aad7202a89..cd3894e6a731c534c8c4205429cf60843fa8ca83 100644 (file)
@@ -45,6 +45,7 @@ endif
 
 plperl = 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']],
index c46c0a1da2a88bed691d9a51c35fb53c1fa67953..27b2f5ef5292845fc0d05cc99d2756e44812d3d8 100644 (file)
@@ -48,6 +48,7 @@ endif
 
 plpgsql = shared_module('plpgsql',
   plpgsql_sources,
+  c_pch: pch_postgres_h,
   include_directories: include_directories('.'),
   kwargs: pg_mod_args,
 )
index 40888386b5f13e0c1bd89e0784b15639a97497f4..7bd683580e86a8589a389ef5b5bfe59d091fdaa8 100644 (file)
@@ -36,6 +36,7 @@ endif
 
 plpython = 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']],
index f09bb14c9500e181af73bbce077775d2661be58a..7a708776c994540f02320efeaf256d646ce7b042 100644 (file)
@@ -22,6 +22,7 @@ endif
 
 pltcl = 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']],
index ced2e014db8d7baa32516ccaf93c46c8b3ee7a54..c2222696f1b1b59646d38b325efb78377e1daa97 100644 (file)
@@ -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],
       }