On Sat, Nov 1, 2025 at 7:14 AM Heikki Linnakangas <[email protected]> wrote:
> The patch seems harmless enough to me, no objections to committing it.
> However, I'm worried that we'll soon break it again. The new rule is
> apparently "include libpq first", but we have no way of enforcing it.

Here's a new version of the original approach with fixes for some
copy-and-pastes I'd missed, and a new patch to check the search order
in CI.  It adds a "poisoned" libpq-fe.h header into the search path to
break the build step if you get it wrong in meson or configure (cf
commit 4300d8b6 which fixed a case of this there).  It fails like
this:

[01:45:21.825] In file included from ../src/include/fe_utils/connect_utils.h:15,
[01:45:21.825]                  from ../src/bin/scripts/common.h:13,
[01:45:21.825]                  from ../src/bin/scripts/vacuumdb.c:17:
[01:45:21.825] /tmp/poisoned_headers/libpq-fe.h:1:2: error: #error
"external header hides in-tree header"
[01:45:21.825]     1 | #error "external header hides in-tree header"
[01:45:21.825]       |  ^~~~~

There must surely be a more mesonic way to do this with declarations
rather than the order in a flimsy list that is copied all over the
place (I guess that is probably supposed to be thought of as an
unordered set...?), but I'm not sure I was on the right path with my
v2 as mentioned and it didn't survive this test.  This approach is OK
for now, I think... if someone ever shows up with a patch to tackle it
more fundamentally, the order will presumably become more flexible, so
the new order will still be valid but unimportant.

Will wait another day for a better idea or objection to show up, and
otherwise commit these to 16+.
From aa390e77bedf25c7bf53f8dc5c05b6e826ccbc88 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Mon, 14 Jul 2025 11:54:00 +1200
Subject: [PATCH v3 1/2] meson: Fix libpq header include order.

On systems using -Dextra_include_dir that happen to have a copy of libpq
installed there, it's important to put the libpq header search path
ahead of -Dextra_include_dir.  Reorder the dependencies to achieve that.
This matches the order used by configure.

There is probably a better way to do this using declarations rather than
adjusting the order of many lists, but this works for now until someone
shows up with a patch for that.

Back-patch to 16, where meson arrived.

Reviewed-by: Heikki Linnakangas <[email protected]>
Discussion: https://postgr.es/m/CA+hUKGKispvxLyrBn3=3mp0bb1n+rbyr5ee2gucoksnweoo...@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_combinebackup/meson.build                 | 2 +-
 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/modules/test_oat_hooks/meson.build          | 4 +++-
 src/test/regress/meson.build                         | 4 ++--
 31 files changed, 46 insertions(+), 44 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_combinebackup/meson.build b/src/bin/pg_combinebackup/meson.build
index e80a4756a7f..04e09162d9b 100644
--- a/src/bin/pg_combinebackup/meson.build
+++ b/src/bin/pg_combinebackup/meson.build
@@ -17,7 +17,7 @@ endif
 
 pg_combinebackup = executable('pg_combinebackup',
   pg_combinebackup_sources,
-  dependencies: [frontend_code],
+  dependencies: [libpq, frontend_code],
   kwargs: default_bin_args,
 )
 bin_targets += pg_combinebackup
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/modules/test_oat_hooks/meson.build b/src/test/modules/test_oat_hooks/meson.build
index 1e600b0f4c7..6f0c4afd433 100644
--- a/src/test/modules/test_oat_hooks/meson.build
+++ b/src/test/modules/test_oat_hooks/meson.build
@@ -12,7 +12,9 @@ endif
 
 test_oat_hooks = shared_module('test_oat_hooks',
   test_oat_hooks_sources,
-  kwargs: pg_test_mod_args,
+  kwargs: pg_test_mod_args + {
+	'dependencies': [libpq] + pg_test_mod_args['dependencies'],
+  }
 )
 test_install_libs += test_oat_hooks
 
diff --git a/src/test/regress/meson.build b/src/test/regress/meson.build
index 1da9e9462a9..99f402f49a8 100644
--- a/src/test/regress/meson.build
+++ b/src/test/regress/meson.build
@@ -2,7 +2,7 @@
 
 # also used by isolationtester and ecpg tests
 pg_regress_c = files('pg_regress.c')
-pg_regress_inc = include_directories('.')
+pg_regress_inc = [libpq_inc, include_directories('.')]
 
 regress_sources = pg_regress_c + files(
   'pg_regress_main.c'
@@ -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 23df76b10985b3624a71e9357b98a6cccf377542 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Mon, 3 Nov 2025 11:32:57 +1300
Subject: [PATCH v3 2/2] ci: Test include path order with decoy libpq-fe.h.

If the configure or meson scripts would allow headers from a copy of
libpq installed under --with-includes or -Dextra_include_dirs to be
found before the in-tree copy we need, then this canary header will
raise an error.

This problem has bitten us in both build systems, but often goes
unnoticed until libpq-fe.h changes incompatibly and someone with an
affected system notices.  This test would cause CI to fail fast.

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

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

Reply via email to