On Mon, Nov 3, 2025 at 7:14 PM Tom Lane <[email protected]> wrote:
> "Tristan Partin" <[email protected]> writes:
> > What is the benefit of -Dextra_include_dirs when you could use -Dc_flags
> > or CFLAGS to specify extra include directories? If you tried either of
> > those as an alternative, would they fix the issue? The existence of the
> > option goes all the way back to the initial commit of the meson port, so
> > I presume it exists to mirror --with-includes, but why does that exist?

Good questions.  Sounds plausible and probably more conventional.  It
doesn't work right now but probably only for superficial reasons.  But
I also worry about hiding current or future problems and generally
being too blunt.  But that's also true of -Dextra_XXX.

> --with-includes, and likewise --with-libs, exist because there are
> platforms that require it.  For example, on pretty much any
> BSD-derived system, the core /usr/include and /usr/lib files are very
> limited and you'll need to point at places like /usr/pkg/include or
> /opt/local/include or whatever to pull in non-core packages.

Yeah.  I for one cargo-culted that configure habit across to the new
world, but you can actually build without -Dextra_XXX on FreeBSD and
maybe macOS + MacPorts too with -Dnls=disabled, as long as your $PATH
contains pkg-config (FreeBSD: yes by default, macOS: probably yes if
you can type "meson").  NetBSD handles even -Dnls=enabled thanks to
its built-in libintl, as CI already demonstrates.  So I wonder if we
have this only because out-of-libc libintl and pkg-config have some
unresolved beef[1][2]...?  Know of any other complications in our
universe or libraries that I might be overlooking?

If that really is the last reason we need this on typical
package-managed non-Linux environments (not sure!)... here's an
experimental patch that probes the conventional paths relative to
msgfmt to hunt for them.  They were all compiled from the same source
package by the same packaging pipeline so I think it has pretty good
odds.  It's not quite $PATH -> pkg-config -> .pc -> exact results, but
it's ... well, something vaguely similar, instead of nothing.  Too
crazy an overreaching assumption, or friendly out-of-the-box support
for lots of common systems including Macs?  It passes on all CI OSes.
No loss if it guesses wrong on your DeathStation 9000: you can still
supply -Dextra_XXX as before.

On the flip side, if you stop using a "catch-all" include path, you
have to declare dependencies accurately or some combinations might
break, for example that gssapi I had to add, because the CI macOS task
found Apple's base system OpenSSL and then didn't think it needed any
extra includes, because we forgot to say that libpq_oauth_st also
depends on gssapi.  That's an example of a "broad"
-Dextra_include_dirs hiding something that is technically incorrect,
or being forgiving depending on your perspective...

First two patches as before, except for a couple of unnecessary hunks
I deleted based on an off-list review from Bilal.

[1] https://lists.gnu.org/archive/html/bug-gettext/2012-03/msg00022.html
[2] https://lists.nongnu.org/archive/html/bug-gettext/2019-10/msg00003.html
From 172ebde3ea93a9c9bd3db8a134cd873ca3daedda Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Mon, 14 Jul 2025 11:54:00 +1200
Subject: [PATCH v4 1/4] meson: Fix libpq header include order.

Don't allow external copies of libpq-fe.h to hide the in-tree libpq's
headers.  libpq is now always declared as the first dependency, so that
it can arrange for libpq_inc to be searched before extra_include_dirs,
c_flags or system/ports include directory discovered by Meson.

This is mostly a mechanical change to multiple dependency lists.  A
separate commit will add a CI check to prevent future mistakes.

This clearly didn't affect many people, maybe just me (Thomas), but it
could have broken on basically any non-Linux system that happened to
install a libpq-with-headers package.

Back-patch to 16, where meson arrived.

Reviewed-by: Heikki Linnakangas <[email protected]>
Reviewed-by: Bilal Yavuz <[email protected]>
Reviewed-by: Tristan Partin <[email protected]>
Discussion: https://postgr.es/m/CA+hUKGKispvxLyrBn3=3mp0BB1N+RBYR5eE2guCOksnwEoOcPQ@mail.gmail.com
---
 contrib/dblink/meson.build                           | 2 +-
 contrib/oid2name/meson.build                         | 2 +-
 contrib/postgres_fdw/meson.build                     | 2 +-
 contrib/vacuumlo/meson.build                         | 2 +-
 src/backend/replication/libpqwalreceiver/meson.build | 2 +-
 src/bin/initdb/meson.build                           | 2 +-
 src/bin/pg_amcheck/meson.build                       | 2 +-
 src/bin/pg_basebackup/meson.build                    | 4 ++--
 src/bin/pg_ctl/meson.build                           | 2 +-
 src/bin/pg_dump/meson.build                          | 8 ++++----
 src/bin/pg_rewind/meson.build                        | 2 +-
 src/bin/pg_upgrade/meson.build                       | 2 +-
 src/bin/pg_verifybackup/meson.build                  | 2 +-
 src/bin/pgbench/meson.build                          | 2 +-
 src/bin/psql/meson.build                             | 2 +-
 src/bin/scripts/meson.build                          | 8 ++++----
 src/fe_utils/meson.build                             | 2 +-
 src/interfaces/ecpg/ecpglib/meson.build              | 6 +++---
 src/interfaces/ecpg/include/meson.build              | 2 +-
 src/interfaces/ecpg/test/meson.build                 | 4 ++--
 src/interfaces/ecpg/test/thread/meson.build          | 2 +-
 src/interfaces/libpq/test/meson.build                | 4 ++--
 src/test/isolation/meson.build                       | 4 ++--
 src/test/modules/libpq_pipeline/meson.build          | 2 +-
 src/test/modules/oauth_validator/meson.build         | 2 +-
 src/test/modules/test_escape/meson.build             | 2 +-
 src/test/modules/test_int128/meson.build             | 2 +-
 src/test/modules/test_json_parser/meson.build        | 2 +-
 src/test/regress/meson.build                         | 2 +-
 29 files changed, 41 insertions(+), 41 deletions(-)

diff --git a/contrib/dblink/meson.build b/contrib/dblink/meson.build
index a19ce6cf4b9..28da26d3d45 100644
--- a/contrib/dblink/meson.build
+++ b/contrib/dblink/meson.build
@@ -13,7 +13,7 @@ endif
 dblink = shared_module('dblink',
   dblink_sources,
   kwargs: contrib_mod_args + {
-    'dependencies': contrib_mod_args['dependencies'] + [libpq],
+    'dependencies': [libpq] + contrib_mod_args['dependencies'],
   },
 )
 contrib_targets += dblink
diff --git a/contrib/oid2name/meson.build b/contrib/oid2name/meson.build
index 074f16acd72..dd958f00bdf 100644
--- a/contrib/oid2name/meson.build
+++ b/contrib/oid2name/meson.build
@@ -12,7 +12,7 @@ endif
 
 oid2name = executable('oid2name',
   oid2name_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 contrib_targets += oid2name
diff --git a/contrib/postgres_fdw/meson.build b/contrib/postgres_fdw/meson.build
index aac89ffdde8..a2890251d69 100644
--- a/contrib/postgres_fdw/meson.build
+++ b/contrib/postgres_fdw/meson.build
@@ -17,7 +17,7 @@ endif
 postgres_fdw = shared_module('postgres_fdw',
   postgres_fdw_sources,
   kwargs: contrib_mod_args + {
-    'dependencies': contrib_mod_args['dependencies'] + [libpq],
+    'dependencies': [libpq] + contrib_mod_args['dependencies'],
   },
 )
 contrib_targets += postgres_fdw
diff --git a/contrib/vacuumlo/meson.build b/contrib/vacuumlo/meson.build
index deee1d2832d..51e8fe9a325 100644
--- a/contrib/vacuumlo/meson.build
+++ b/contrib/vacuumlo/meson.build
@@ -12,7 +12,7 @@ endif
 
 vacuumlo = executable('vacuumlo',
   vacuumlo_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 contrib_targets += vacuumlo
diff --git a/src/backend/replication/libpqwalreceiver/meson.build b/src/backend/replication/libpqwalreceiver/meson.build
index 2150f31cfa3..5318a76e29d 100644
--- a/src/backend/replication/libpqwalreceiver/meson.build
+++ b/src/backend/replication/libpqwalreceiver/meson.build
@@ -14,7 +14,7 @@ libpqwalreceiver = shared_module('pqwalreceiver',
   libpqwalreceiver_sources,
   kwargs: pg_mod_args + {
     'name_prefix': 'lib',
-    'dependencies': pg_mod_args['dependencies'] + [libpq],
+    'dependencies': [libpq] + pg_mod_args['dependencies'],
   }
 )
 
diff --git a/src/bin/initdb/meson.build b/src/bin/initdb/meson.build
index 06958e370f3..b8584fe56de 100644
--- a/src/bin/initdb/meson.build
+++ b/src/bin/initdb/meson.build
@@ -21,7 +21,7 @@ initdb = executable('initdb',
   # shared library from a different PG version.  Define
   # USE_PRIVATE_ENCODING_FUNCS to ensure that that happens.
   c_args: ['-DUSE_PRIVATE_ENCODING_FUNCS'],
-  dependencies: [frontend_code, libpq, icu, icu_i18n],
+  dependencies: [libpq, frontend_code, icu, icu_i18n],
   kwargs: default_bin_args,
 )
 bin_targets += initdb
diff --git a/src/bin/pg_amcheck/meson.build b/src/bin/pg_amcheck/meson.build
index 316ea0d40b8..c8f792ff971 100644
--- a/src/bin/pg_amcheck/meson.build
+++ b/src/bin/pg_amcheck/meson.build
@@ -12,7 +12,7 @@ endif
 
 pg_amcheck = executable('pg_amcheck',
   pg_amcheck_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 bin_targets += pg_amcheck
diff --git a/src/bin/pg_basebackup/meson.build b/src/bin/pg_basebackup/meson.build
index 3a7fc10eab0..b85ba465d47 100644
--- a/src/bin/pg_basebackup/meson.build
+++ b/src/bin/pg_basebackup/meson.build
@@ -7,7 +7,7 @@ common_sources = files(
   'walmethods.c',
 )
 
-pg_basebackup_deps = [frontend_code, libpq, lz4, zlib, zstd]
+pg_basebackup_deps = [libpq, frontend_code, lz4, zlib, zstd]
 pg_basebackup_common = static_library('libpg_basebackup_common',
   common_sources,
   dependencies: pg_basebackup_deps,
@@ -45,7 +45,7 @@ endif
 
 pg_createsubscriber = executable('pg_createsubscriber',
   pg_createsubscriber_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 bin_targets += pg_createsubscriber
diff --git a/src/bin/pg_ctl/meson.build b/src/bin/pg_ctl/meson.build
index e92ba50f8a3..4f4a977dc0f 100644
--- a/src/bin/pg_ctl/meson.build
+++ b/src/bin/pg_ctl/meson.build
@@ -12,7 +12,7 @@ endif
 
 pg_ctl = executable('pg_ctl',
   pg_ctl_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 bin_targets += pg_ctl
diff --git a/src/bin/pg_dump/meson.build b/src/bin/pg_dump/meson.build
index f3c669f484e..2264ed9faa9 100644
--- a/src/bin/pg_dump/meson.build
+++ b/src/bin/pg_dump/meson.build
@@ -22,7 +22,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, lz4, zlib, zstd],
+  dependencies: [libpq, frontend_code, lz4, zlib, zstd],
   kwargs: internal_lib_args,
 )
 
@@ -42,7 +42,7 @@ endif
 pg_dump = executable('pg_dump',
   pg_dump_sources,
   link_with: [pg_dump_common],
-  dependencies: [frontend_code, libpq, zlib],
+  dependencies: [libpq, frontend_code, zlib],
   kwargs: default_bin_args,
 )
 bin_targets += pg_dump
@@ -61,7 +61,7 @@ endif
 pg_dumpall = executable('pg_dumpall',
   pg_dumpall_sources,
   link_with: [pg_dump_common],
-  dependencies: [frontend_code, libpq, zlib],
+  dependencies: [libpq, frontend_code, zlib],
   kwargs: default_bin_args,
 )
 bin_targets += pg_dumpall
@@ -80,7 +80,7 @@ endif
 pg_restore = executable('pg_restore',
   pg_restore_sources,
   link_with: [pg_dump_common],
-  dependencies: [frontend_code, libpq, zlib],
+  dependencies: [libpq, frontend_code, zlib],
   kwargs: default_bin_args,
 )
 bin_targets += pg_restore
diff --git a/src/bin/pg_rewind/meson.build b/src/bin/pg_rewind/meson.build
index 97f001d94a5..f241f37673c 100644
--- a/src/bin/pg_rewind/meson.build
+++ b/src/bin/pg_rewind/meson.build
@@ -21,7 +21,7 @@ endif
 
 pg_rewind = executable('pg_rewind',
   pg_rewind_sources,
-  dependencies: [frontend_code, libpq, lz4, zstd],
+  dependencies: [libpq, frontend_code, lz4, zstd],
   c_args: ['-DFRONTEND'], # needed for xlogreader et al
   kwargs: default_bin_args,
 )
diff --git a/src/bin/pg_upgrade/meson.build b/src/bin/pg_upgrade/meson.build
index ac992f0d14b..8aefaeea91f 100644
--- a/src/bin/pg_upgrade/meson.build
+++ b/src/bin/pg_upgrade/meson.build
@@ -28,7 +28,7 @@ endif
 pg_upgrade = executable('pg_upgrade',
   pg_upgrade_sources,
   c_pch: pch_postgres_fe_h,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 bin_targets += pg_upgrade
diff --git a/src/bin/pg_verifybackup/meson.build b/src/bin/pg_verifybackup/meson.build
index f45ea790d8e..7aaee24bd79 100644
--- a/src/bin/pg_verifybackup/meson.build
+++ b/src/bin/pg_verifybackup/meson.build
@@ -13,7 +13,7 @@ endif
 
 pg_verifybackup = executable('pg_verifybackup',
   pg_verifybackup_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 bin_targets += pg_verifybackup
diff --git a/src/bin/pgbench/meson.build b/src/bin/pgbench/meson.build
index a2a909a8442..de013cc9827 100644
--- a/src/bin/pgbench/meson.build
+++ b/src/bin/pgbench/meson.build
@@ -27,7 +27,7 @@ endif
 
 pgbench = executable('pgbench',
   pgbench_sources,
-  dependencies: [frontend_code, libpq, thread_dep],
+  dependencies: [libpq, frontend_code, thread_dep],
   include_directories: include_directories('.'),
   c_pch: pch_postgres_fe_h,
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build
index d344053c23b..4749d751aa8 100644
--- a/src/bin/psql/meson.build
+++ b/src/bin/psql/meson.build
@@ -58,7 +58,7 @@ psql = executable('psql',
   psql_sources,
   c_pch: pch_postgres_fe_h,
   include_directories: include_directories('.'),
-  dependencies: [frontend_code, libpq, readline],
+  dependencies: [libpq, frontend_code, readline],
   kwargs: default_bin_args,
 )
 bin_targets += psql
diff --git a/src/bin/scripts/meson.build b/src/bin/scripts/meson.build
index a4fed59d1c9..d422ca542f9 100644
--- a/src/bin/scripts/meson.build
+++ b/src/bin/scripts/meson.build
@@ -2,7 +2,7 @@
 
 scripts_common = static_library('libscripts_common',
   files('common.c'),
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: internal_lib_args,
 )
 
@@ -28,7 +28,7 @@ foreach binary : binaries
   binary = executable(binary,
     binary_sources,
     link_with: [scripts_common],
-    dependencies: [frontend_code, libpq],
+    dependencies: [libpq, frontend_code],
     kwargs: default_bin_args,
   )
   bin_targets += binary
@@ -36,7 +36,7 @@ endforeach
 
 vacuuming_common = static_library('libvacuuming_common',
   files('common.c', 'vacuuming.c'),
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: internal_lib_args,
 )
 
@@ -55,7 +55,7 @@ foreach binary : binaries
   binary = executable(binary,
     binary_sources,
     link_with: [vacuuming_common],
-    dependencies: [frontend_code, libpq],
+    dependencies: [libpq, frontend_code],
     kwargs: default_bin_args,
   )
   bin_targets += binary
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index ddac3c3a658..0a65b973779 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -32,7 +32,7 @@ fe_utils_sources += psqlscan
 fe_utils = static_library('libpgfeutils',
   fe_utils_sources,
   c_pch: pch_postgres_fe_h,
-  include_directories: [postgres_inc, libpq_inc],
+  include_directories: [libpq_inc, postgres_inc],
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
   dependencies: frontend_common_code,
   kwargs: default_lib_args,
diff --git a/src/interfaces/ecpg/ecpglib/meson.build b/src/interfaces/ecpg/ecpglib/meson.build
index 8f478c6a73e..fb7d33d2a0e 100644
--- a/src/interfaces/ecpg/ecpglib/meson.build
+++ b/src/interfaces/ecpg/ecpglib/meson.build
@@ -30,7 +30,7 @@ ecpglib_st = static_library('libecpg',
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: [frontend_stlib_code, thread_dep, libpq],
+  dependencies: [libpq, frontend_stlib_code, thread_dep],
   link_with: [ecpg_pgtypes_st],
   kwargs: default_lib_args,
 )
@@ -41,7 +41,7 @@ ecpglib_so = shared_library('libecpg',
   include_directories: ecpglib_inc,
   c_args: ecpglib_c_args,
   c_pch: pch_postgres_fe_h,
-  dependencies: [frontend_shlib_code, libpq, thread_dep],
+  dependencies: [libpq, frontend_shlib_code, thread_dep],
   link_with: ecpg_pgtypes_so,
   soversion: host_system != 'windows' ? '6' : '',
   darwin_versions: ['6', '6.' + pg_version_major.to_string()],
@@ -58,7 +58,7 @@ pkgconfig.generate(
   url: pg_url,
   libraries: ecpglib_so,
   libraries_private: [frontend_stlib_code, thread_dep],
-  requires_private: ['libpgtypes', 'libpq'],
+  requires_private: ['libpq', 'libpgtypes'],
 )
 
 subdir('po', if_found: libintl)
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index a6541e1a686..133ebe2f11f 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -1,6 +1,6 @@
 # Copyright (c) 2022-2025, PostgreSQL Global Development Group
 
-ecpg_inc = include_directories('.')
+ecpg_inc = [libpq_inc, include_directories('.')]
 
 ecpg_conf_keys = [
   'SIZEOF_LONG',
diff --git a/src/interfaces/ecpg/test/meson.build b/src/interfaces/ecpg/test/meson.build
index 4ccdf9d295a..0d48e035e5a 100644
--- a/src/interfaces/ecpg/test/meson.build
+++ b/src/interfaces/ecpg/test/meson.build
@@ -20,7 +20,7 @@ pg_regress_ecpg = executable('pg_regress_ecpg',
   pg_regress_ecpg_sources,
   c_args: pg_regress_cflags,
   include_directories: [pg_regress_inc, include_directories('.')],
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install': false
   },
@@ -30,7 +30,7 @@ ecpg_test_dependencies += pg_regress_ecpg
 # create .c files and executables from .pgc files
 ecpg_test_exec_kw = {
   'c_args': cflags_no_missing_var_decls,
-  'dependencies': [frontend_code, libpq],
+  'dependencies': [libpq, frontend_code],
   'include_directories': [ecpg_inc],
   'link_with': [ecpglib_so, ecpg_compat_so, ecpg_pgtypes_so],
   'build_by_default': false,
diff --git a/src/interfaces/ecpg/test/thread/meson.build b/src/interfaces/ecpg/test/thread/meson.build
index 6a6745ce0fc..2c34a611898 100644
--- a/src/interfaces/ecpg/test/thread/meson.build
+++ b/src/interfaces/ecpg/test/thread/meson.build
@@ -18,6 +18,6 @@ foreach pgc_file : pgc_files
 
   ecpg_test_dependencies += executable(pgc_file,
     exe_input,
-    kwargs: ecpg_test_exec_kw + {'dependencies': [frontend_code, libpq, thread_dep,]},
+    kwargs: ecpg_test_exec_kw + {'dependencies': [libpq, frontend_code, thread_dep,]},
   )
 endforeach
diff --git a/src/interfaces/libpq/test/meson.build b/src/interfaces/libpq/test/meson.build
index 07a5facc321..75d2012ba17 100644
--- a/src/interfaces/libpq/test/meson.build
+++ b/src/interfaces/libpq/test/meson.build
@@ -14,7 +14,7 @@ endif
 
 libpq_test_deps += executable('libpq_uri_regress',
   libpq_uri_regress_sources,
-  dependencies: [frontend_no_fe_utils_code, libpq],
+  dependencies: [libpq, frontend_no_fe_utils_code],
   kwargs: default_bin_args + {
     'install': false,
   }
@@ -33,7 +33,7 @@ endif
 
 libpq_test_deps += executable('libpq_testclient',
   libpq_testclient_sources,
-  dependencies: [frontend_no_fe_utils_code, libpq],
+  dependencies: [libpq, frontend_no_fe_utils_code],
   kwargs: default_bin_args + {
     'install': false,
   }
diff --git a/src/test/isolation/meson.build b/src/test/isolation/meson.build
index a180e4e2741..660b11eff8b 100644
--- a/src/test/isolation/meson.build
+++ b/src/test/isolation/meson.build
@@ -35,7 +35,7 @@ pg_isolation_regress = executable('pg_isolation_regress',
   isolation_sources,
   c_args: pg_regress_cflags,
   include_directories: pg_regress_inc,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install_dir': dir_pgxs / 'src/test/isolation',
   },
@@ -52,7 +52,7 @@ endif
 isolationtester = executable('isolationtester',
   isolationtester_sources,
   include_directories: include_directories('.'),
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install_dir': dir_pgxs / 'src/test/isolation',
   },
diff --git a/src/test/modules/libpq_pipeline/meson.build b/src/test/modules/libpq_pipeline/meson.build
index 3fd70a04a38..83201111ca3 100644
--- a/src/test/modules/libpq_pipeline/meson.build
+++ b/src/test/modules/libpq_pipeline/meson.build
@@ -12,7 +12,7 @@ endif
 
 libpq_pipeline = executable('libpq_pipeline',
   libpq_pipeline_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install': false,
   },
diff --git a/src/test/modules/oauth_validator/meson.build b/src/test/modules/oauth_validator/meson.build
index a6f937fd7d7..2cd5c4cd537 100644
--- a/src/test/modules/oauth_validator/meson.build
+++ b/src/test/modules/oauth_validator/meson.build
@@ -60,7 +60,7 @@ endif
 
 oauth_hook_client = executable('oauth_hook_client',
   oauth_hook_client_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install': false,
   },
diff --git a/src/test/modules/test_escape/meson.build b/src/test/modules/test_escape/meson.build
index a21341d5067..04fd0be0889 100644
--- a/src/test/modules/test_escape/meson.build
+++ b/src/test/modules/test_escape/meson.build
@@ -10,7 +10,7 @@ endif
 
 test_escape = executable('test_escape',
   test_escape_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install': false,
   }
diff --git a/src/test/modules/test_int128/meson.build b/src/test/modules/test_int128/meson.build
index 4c2be7a0326..94bca2edc5c 100644
--- a/src/test/modules/test_int128/meson.build
+++ b/src/test/modules/test_int128/meson.build
@@ -12,7 +12,7 @@ endif
 
 test_int128 = executable('test_int128',
   test_int128_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install': false,
   },
diff --git a/src/test/modules/test_json_parser/meson.build b/src/test/modules/test_json_parser/meson.build
index 5672045f496..2c6031a14df 100644
--- a/src/test/modules/test_json_parser/meson.build
+++ b/src/test/modules/test_json_parser/meson.build
@@ -23,7 +23,7 @@ test_json_parser_incremental = executable('test_json_parser_incremental',
 # the shared-library flavor of jsonapi.
 test_json_parser_incremental_shlib = executable('test_json_parser_incremental_shlib',
   test_json_parser_incremental_sources,
-  dependencies: [frontend_shlib_code, libpq],
+  dependencies: [libpq, frontend_shlib_code],
   c_args: ['-DJSONAPI_SHLIB_ALLOC'],
   link_with: [common_excluded_shlib],
   kwargs: default_bin_args + {
diff --git a/src/test/regress/meson.build b/src/test/regress/meson.build
index 1da9e9462a9..3fe900d5847 100644
--- a/src/test/regress/meson.build
+++ b/src/test/regress/meson.build
@@ -30,7 +30,7 @@ endif
 pg_regress = executable('pg_regress',
   regress_sources,
   c_args: pg_regress_cflags,
-  dependencies: [frontend_code, libpq],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args + {
     'install_dir': dir_pgxs / 'src/test/regress',
   },
-- 
2.51.1

From 3ed517c7904666e1f9dcf45171ffa2684126eb2f Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Mon, 3 Nov 2025 11:32:57 +1300
Subject: [PATCH v4 2/4] ci: Test include path order with canary libpq-fe.h.

If the build script would allow libpq-fe.h installed under
--with-includes (configure) or -Dextra_include_dirs (meson) to hide the
in-tree header, it will now reach an #error in contrived error on CI.
This tests that libpq is ordered correctly for all code that includes
the header.  The list of canary headers could be extended in future.

Also add missing set -e to the shell scripts run under su, since
otherwise the build step would confusingly succeed despite not
completing.

Reviewed-by: Bilal Yavuz <[email protected]>
Discussion: https://postgr.es/m/CA%2BhUKG%2Bx-cys30%3D7L2B8%3DcZ%2B-z6QDOj-oQy9O3CnkeXnrnm3OQ%40mail.gmail.com
---
 .cirrus.tasks.yml | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index f2581cfb2e5..3df6de6acd9 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -424,6 +424,8 @@ task:
     CCACHE_DIR: /tmp/ccache_dir
     DEBUGINFOD_URLS: "https://debuginfod.debian.net";
 
+    POISONED_HEADERS: /tmp/poisoned_headers
+
     # Enable a reasonable set of sanitizers. Use the linux task for that, as
     # it's one of the fastest tasks (without sanitizers). Also several of the
     # sanitizers work best on linux.
@@ -492,11 +494,24 @@ task:
     #apt-get update
     #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
 
+  # Detect mistakes that would allow unwanted headers from outside our tree be
+  # found with --with-includes or -Dextra_include_dirs.  That is primarily a
+  # risk on non-Linux systems that install packages under eg /usr/local that
+  # must be explicitly added to the header search path, but this is a
+  # convenient place to test both build systems.
+  setup_poisoned_headers_script: |
+    for header in "libpq-fe.h" "libpq/libpq-fe.h" ; do
+      mkdir -p "${POISONED_HEADERS}/$(dirname $header)"
+      echo '#error "external header hides in-tree header"' \
+      > "${POISONED_HEADERS}/$header"
+    done
+
   matrix:
     # SPECIAL:
     # - Uses address sanitizer, sanitizer failures are typically printed in
     #   the server log
     # - Configures postgres with a small segment size
+    # - Poisoned headers in search path
     - name: Linux - Debian Bookworm - Autoconf
 
       env:
@@ -517,6 +532,7 @@ task:
             --with-segsize-blocks=6 \
             --with-libnuma \
             --with-liburing \
+            --with-includes="${POISONED_HEADERS}" \
             \
             ${LINUX_CONFIGURE_FEATURES} \
             \
@@ -540,6 +556,7 @@ task:
     # - Test both 64bit and 32 bit builds
     # - uses io_method=io_uring
     # - Uses meson feature autodetection
+    # - Poisoned headers in search path
     - name: Linux - Debian Bookworm - Meson
 
       env:
@@ -552,6 +569,7 @@ task:
         su postgres <<-EOF
           meson setup \
             ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Dextra_include_dirs="${POISONED_HEADERS}" \
             --buildtype=debug \
             ${LINUX_MESON_FEATURES} -Dllvm=enabled \
             build
@@ -564,6 +582,7 @@ task:
           export CC='ccache gcc -m32'
           meson setup \
             ${MESON_COMMON_PG_CONFIG_ARGS} \
+            -Dextra_include_dirs="${POISONED_HEADERS}" \
             --buildtype=debug \
             --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
             -DPERL=perl5.36-i386-linux-gnu \
@@ -573,12 +592,14 @@ task:
 
       build_script: |
         su postgres <<-EOF
+          set -e
           ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET}
           ninja -C build -t missingdeps
         EOF
 
       build_32_script: |
         su postgres <<-EOF
+          set -e
           ninja -C build-32 -j${BUILD_JOBS} ${MBUILD_TARGET}
           ninja -C build -t missingdeps
         EOF
-- 
2.51.1

From 290bf24a89a075f3380c7e9af03d357475718887 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Tue, 4 Nov 2025 03:09:22 +1300
Subject: [PATCH v4 3/4] meson: Try to find libintl without -Dextra_XXX.

Since libintl is the only dependency that Meson can't usually find via
pkg-config on typical non-Linux Unix systems, let's try a bit harder to
find it with existing clues.

We typically find msgfmt in $PATH, so we can plausibly guess that the
library and headers are installed in the same prefix, and then try that
before giving up and requiring a manual path configuration.

This revealed some missing dependency declarations previously covered by
the catch-all extra_includes_dir, added here.

XXX Is this a terrible idea for some reason?
---
 meson.build                            | 34 +++++++++++++++++++++-----
 src/backend/jit/llvm/meson.build       |  5 +++-
 src/interfaces/libpq-oauth/meson.build |  1 +
 src/port/meson.build                   |  6 ++---
 4 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/meson.build b/meson.build
index 0f61ff6a700..2690d7a7b2b 100644
--- a/meson.build
+++ b/meson.build
@@ -2973,6 +2973,7 @@ cdata.set_quoted('PG_VERSION_STR',
 
 nlsopt = get_option('nls')
 libintl = not_found_dep
+libintl_include_dirs = []
 
 if not nlsopt.disabled()
   # otherwise there'd be lots of
@@ -2982,7 +2983,7 @@ if not nlsopt.disabled()
 
   # meson 0.59 has this wrapped in dependency('intl')
   if (msgfmt.found() and
-      cc.check_header('libintl.h', required: nlsopt,
+      cc.check_header('libintl.h',
         args: test_c_args, include_directories: postgres_inc))
 
     # in libc
@@ -2990,13 +2991,34 @@ if not nlsopt.disabled()
       libintl = declare_dependency()
     else
       libintl = cc.find_library('intl',
-        has_headers: ['libintl.h'], required: nlsopt,
+        has_headers: ['libintl.h'],
         header_include_directories: postgres_inc,
         dirs: test_lib_d)
     endif
   endif
 
+  if (msgfmt.found() and not libintl.found())
+    # libintl doesn't provide libintl.pc, but since we found its companion
+    # binary msgfmt we have a solid clue where to look, assuming standard
+    # layout within the install prefix.
+    guess_libintl_prefix = fs.parent(fs.parent(msgfmt.full_path()))
+    guess_libintl_lib_d = guess_libintl_prefix / 'lib'
+    guess_libintl_include = guess_libintl_prefix / 'include'
+    guess_libintl_include_dirs = include_directories(guess_libintl_include)
+    libintl_lib = cc.find_library('intl',
+      has_headers: ['libintl.h'],
+      header_include_directories: guess_libintl_include_dirs,
+      dirs: guess_libintl_lib_d)
+    if libintl_lib.found()
+      libintl = declare_dependency(dependencies: libintl_lib,
+                                   include_directories: guess_libintl_include_dirs)
+      libintl_include_dirs += guess_libintl_include # needed for llvmjit_types.bc
+    endif
+  endif
+
   if libintl.found()
+    cc.check_header('libintl.h', required: nlsopt,
+      args: test_c_args, include_directories: postgres_inc, dependencies: libintl)
     i18n = import('i18n')
     cdata.set('ENABLE_NLS', 1)
   endif
@@ -3220,14 +3242,14 @@ subdir('config')
 frontend_port_code = declare_dependency(
   compile_args: ['-DFRONTEND'],
   include_directories: [postgres_inc],
-  dependencies: os_deps,
+  dependencies: [os_deps, libintl]
 )
 
 backend_port_code = declare_dependency(
   compile_args: ['-DBUILDING_DLL'],
   include_directories: [postgres_inc],
   sources: [errcodes], # errcodes.h is needed due to use of ereport
-  dependencies: os_deps,
+  dependencies: [os_deps, libintl]
 )
 
 subdir('src/port')
@@ -3236,14 +3258,14 @@ frontend_common_code = declare_dependency(
   compile_args: ['-DFRONTEND'],
   include_directories: [postgres_inc],
   sources: generated_headers_stamp,
-  dependencies: [os_deps, zlib, zstd, lz4],
+  dependencies: [os_deps, libintl, zlib, zstd, lz4],
 )
 
 backend_common_code = declare_dependency(
   compile_args: ['-DBUILDING_DLL'],
   include_directories: [postgres_inc],
   sources: generated_headers_stamp,
-  dependencies: [os_deps, zlib, zstd],
+  dependencies: [os_deps, libintl, zlib, zstd],
 )
 
 subdir('src/common')
diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
index 805fbd69006..bcc5efed8a2 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -32,7 +32,7 @@ endif
 llvmjit = shared_module('llvmjit',
   llvmjit_sources,
   kwargs: pg_mod_args + {
-    'dependencies': pg_mod_args['dependencies'] + [llvm],
+    'dependencies': pg_mod_args['dependencies'] + [llvm, libintl],
     'cpp_args': pg_mod_args['cpp_args'] + llvm.get_variable(configtool: 'cxxflags').split(),
   }
 )
@@ -69,6 +69,9 @@ bitcode_cflags += '-I@BUILD_ROOT@/src/include'
 bitcode_cflags += '-I@BUILD_ROOT@/src/backend/utils/misc'
 bitcode_cflags += '-I@SOURCE_ROOT@/src/include'
 
+foreach d : libintl_include_dirs
+  bitcode_cflags += ['-I' + d]
+endforeach
 
 # Note this is intentionally not installed to bitcodedir, as it's not for
 # inlining
diff --git a/src/interfaces/libpq-oauth/meson.build b/src/interfaces/libpq-oauth/meson.build
index 505e1671b86..9d7fa1bc67c 100644
--- a/src/interfaces/libpq-oauth/meson.build
+++ b/src/interfaces/libpq-oauth/meson.build
@@ -29,6 +29,7 @@ libpq_oauth_st = static_library('libpq-oauth',
     frontend_stlib_code,
     libpq_oauth_deps,
     ssl, # libpq-int.h includes OpenSSL headers
+    gssapi, # and gssapi
   ],
   kwargs: default_lib_args,
 )
diff --git a/src/port/meson.build b/src/port/meson.build
index fc7b059fee5..9c4f5459e0a 100644
--- a/src/port/meson.build
+++ b/src/port/meson.build
@@ -154,14 +154,14 @@ endif
 pgport = {}
 pgport_variants = {
   '_srv': internal_lib_args + {
-    'dependencies': [backend_port_code],
+    'dependencies': [backend_port_code, libintl],
   },
   '': default_lib_args + {
-    'dependencies': [frontend_port_code],
+    'dependencies': [frontend_port_code, libintl],
   },
   '_shlib': default_lib_args + {
     'pic': true,
-    'dependencies': [frontend_port_code],
+    'dependencies': [frontend_port_code, libintl],
   },
 }
 
-- 
2.51.1

From e553e694574113cd0ddf9b07af7ebc8bbaa8e246 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Tue, 4 Nov 2025 12:47:41 +1300
Subject: [PATCH v4 4/4] ci: Remove -Dextra_XXX on FreeBSD and macOS.

Since FreeBSD and MacPorts install .pc files for the libraries want,
Meson can find them.  The only exception is libintl, which the previous
commit handled specially.

NetBSD has its own libintl in libc, and OpenBSD doesn't have nls
enabled, explaining why they didn't need -Dextra_include_dirs and
-Dextra_lib_dirs in the first place.  The Windows task still needs them
to find OpenSSL.
---
 .cirrus.tasks.yml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/.cirrus.tasks.yml b/.cirrus.tasks.yml
index 3df6de6acd9..31e498dc9b9 100644
--- a/.cirrus.tasks.yml
+++ b/.cirrus.tasks.yml
@@ -232,7 +232,6 @@ task:
       meson setup \
         ${MESON_COMMON_PG_CONFIG_ARGS} \
         --buildtype=debug \
-        -Dextra_lib_dirs=/usr/local/lib -Dextra_include_dirs=/usr/local/include/ \
         ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
         build
     EOF
@@ -731,8 +730,6 @@ task:
     meson setup \
       ${MESON_COMMON_PG_CONFIG_ARGS} \
       --buildtype=debug \
-      -Dextra_include_dirs=/opt/local/include \
-      -Dextra_lib_dirs=/opt/local/lib \
       ${MESON_COMMON_FEATURES} ${MESON_FEATURES} \
       build
 
-- 
2.51.1

Reply via email to