On Sat Aug 30, 2025 at 9:55 AM CDT, Andres Freund wrote:
> Hi,
>
> On 2025-08-30 04:18:05 +0000, Elliot Haisley wrote:
>> While working on another project which needed libpq, I tried building 
>> postgres
>> as a subproject to consume a recent version of libpq, and noticed it failed.
>> I've put together a small patch that updates build files to not use
>> the global source root, which allows postgres to be built as a meson 
>> subproject.
>
> That makes sense.  I however can't apply it just now, the PG 18 code is frozen
> until mid of the next week due to the release of 18rc1, and I think this
> should be backpatched.

I also was working on a project that wanted to use libpq as a subproject 
and came up with this independent but similar patch. I chose to develop 
it against master.

I think that if we aim to support this workflow that we should add 
a test in the tree somewhere. I am happy to develop one if someone 
can direct me to a place where they would like it to live. In theory, 
the test could even live as a meson test() in the source tree.

-- 
Tristan Partin
Databricks (https://databricks.com)
From 48c665854e1b1aa8cf8bd2d34ff7a00e21892e8c Mon Sep 17 00:00:00 2001
From: Tristan Partin <[email protected]>
Date: Fri, 2 Jan 2026 22:16:26 -0600
Subject: [PATCH v1] Add subproject support to the meson build

Meson subprojects[0] are a way for projects to build a dependency that
may not exist on the system.

libpq is a popular library to depend on for other projects, whether
they are Postgres applications or client libraries. Exposing subproject
support can help projects that depend on libpq to build more easily on
systems which would not have libpq installed. It can also be useful if
the project requires a newer version of libpq, but the system has an
older version.

Using @BUILD_ROOT@ and @SOURCE_ROOT@ is problematic because they point
to the global build and source roots.

Link: https://mesonbuild.com/Subprojects.html [0]
Signed-off-by: Tristan Partin <[email protected]>
---
 meson.build                          | 8 +++-----
 src/backend/jit/llvm/meson.build     | 6 +++---
 src/bin/psql/meson.build             | 2 +-
 src/common/unicode/meson.build       | 2 +-
 src/include/catalog/meson.build      | 2 +-
 src/include/utils/meson.build        | 5 ++++-
 src/interfaces/ecpg/test/meson.build | 2 +-
 src/interfaces/libpq/meson.build     | 2 ++
 src/tools/pgflex                     | 2 --
 9 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/meson.build b/meson.build
index 467f7f005a6..dbbead2bd88 100644
--- a/meson.build
+++ b/meson.build
@@ -375,8 +375,6 @@ if flex.found()
 endif
 flex_wrapper = files('src/tools/pgflex')
 flex_cmd = [python, flex_wrapper,
-  '--builddir', '@BUILD_ROOT@',
-  '--srcdir', '@SOURCE_ROOT@',
   '--privatedir', '@PRIVATE_DIR@',
   '--flex', flex, '--perl', perl,
   '-i', '@INPUT@', '-o', '@OUTPUT0@',
@@ -3149,7 +3147,7 @@ catalog_pm = files('src/backend/catalog/Catalog.pm')
 perfect_hash_pm = files('src/tools/PerfectHash.pm')
 gen_kwlist_deps = [perfect_hash_pm]
 gen_kwlist_cmd = [
-  perl, '-I', '@SOURCE_ROOT@/src/tools',
+  perl, '-I', '@0@/src/tools'.format(meson.project_source_root()),
   files('src/tools/gen_keywordlist.pl'),
   '--output', '@OUTDIR@', '@INPUT@']
 
@@ -3864,7 +3862,7 @@ pg_git_revision = get_option('PG_GIT_REVISION')
 
 tar_gz = custom_target('tar.gz',
   build_always_stale: true,
-  command: [git, '-C', '@SOURCE_ROOT@',
+  command: [git, '-C', meson.project_source_root(),
             '-c', 'core.autocrlf=false',
             'archive',
             '--format', 'tar.gz',
@@ -3878,7 +3876,7 @@ tar_gz = custom_target('tar.gz',
 if bzip2.found()
   tar_bz2 = custom_target('tar.bz2',
     build_always_stale: true,
-    command: [git, '-C', '@SOURCE_ROOT@',
+    command: [git, '-C', meson.project_source_root(),
               '-c', 'core.autocrlf=false',
               '-c', 'tar.tar.bz2.command="@0@" -c'.format(bzip2.full_path()),
               'archive',
diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
index 7df8453ad6f..27e47000b11 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -65,9 +65,9 @@ bitcode_cflags += get_option('c_args')
 bitcode_cflags += cppflags
 
 # XXX: Worth improving on the logic to find directories here
-bitcode_cflags += '-I@BUILD_ROOT@/src/include'
-bitcode_cflags += '-I@BUILD_ROOT@/src/backend/utils/misc'
-bitcode_cflags += '-I@SOURCE_ROOT@/src/include'
+bitcode_cflags += '-I@0@src/include'.format(meson.project_build_root())
+bitcode_cflags += '-I@0@src/backend/utils/misc'.format(meson.project_build_root())
+bitcode_cflags += '-I@0@src/include'.format(meson.project_source_root())
 
 
 # Note this is intentionally not installed to bitcodedir, as it's not for
diff --git a/src/bin/psql/meson.build b/src/bin/psql/meson.build
index 922b2845267..ef660e8c3d4 100644
--- a/src/bin/psql/meson.build
+++ b/src/bin/psql/meson.build
@@ -39,7 +39,7 @@ sql_help = custom_target('psql_help',
   depfile: 'sql_help.dep',
   command: [
     perl, files('create_help.pl'),
-    '--docdir', '@SOURCE_ROOT@/doc/src/sgml/ref',
+    '--docdir', join_paths(meson.project_source_root(), 'doc/src/sgml/ref'),
     '--depfile', '@DEPFILE@',
     '--outdir', '@OUTDIR@',
     '--basename', 'sql_help',
diff --git a/src/common/unicode/meson.build b/src/common/unicode/meson.build
index f650dd95b5c..a34912a95bb 100644
--- a/src/common/unicode/meson.build
+++ b/src/common/unicode/meson.build
@@ -174,7 +174,7 @@ update_unicode = custom_target('update-unicode',
   depends: update_unicode_dep,
   output: ['dont-exist'],
   input: update_unicode_targets,
-  command: [cp, '@INPUT@', '@SOURCE_ROOT@/src/include/common/'],
+  command: [cp, '@INPUT@', join_paths(meson.project_source_root(), 'src/include/common/')],
   build_by_default: false,
   build_always_stale: true,
 )
diff --git a/src/include/catalog/meson.build b/src/include/catalog/meson.build
index b63cd584068..bea387b98bc 100644
--- a/src/include/catalog/meson.build
+++ b/src/include/catalog/meson.build
@@ -136,7 +136,7 @@ generated_catalog_headers = custom_target('generated_catalog_headers',
   command: [
     perl,
     files('../../backend/catalog/genbki.pl'),
-    '--include-path=@SOURCE_ROOT@/src/include',
+    '--include-path=@0@/src/include'.format(meson.project_source_root()),
     '--set-version=' + pg_version_major.to_string(),
     '--output=@OUTDIR@', '@INPUT@'
   ],
diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build
index 318a6aec0d0..8db68322b86 100644
--- a/src/include/utils/meson.build
+++ b/src/include/utils/meson.build
@@ -69,7 +69,10 @@ fmgrtab_target = custom_target('fmgrtab',
   input: '../catalog/pg_proc.dat',
   output : fmgrtab_output,
   depend_files: catalog_pm,
-  command: [perl, '-I', '@SOURCE_ROOT@/src/backend/catalog/', files('../../backend/utils/Gen_fmgrtab.pl'), '--include-path=@SOURCE_ROOT@/src/include', '--output=@OUTDIR@', '@INPUT@'],
+  command: [perl, '-I', '@0@/src/backend/catalog/'.format(meson.project_source_root()),
+    files('../../backend/utils/Gen_fmgrtab.pl'),
+    '--include-path=@0@/src/include'.format(meson.project_source_root()),
+    '--output=@OUTDIR@', '@INPUT@'],
   install: true,
   install_dir: [dir_include_server / 'utils', dir_include_server / 'utils', false],
 )
diff --git a/src/interfaces/ecpg/test/meson.build b/src/interfaces/ecpg/test/meson.build
index 7f5b950c186..4b2d49a4b78 100644
--- a/src/interfaces/ecpg/test/meson.build
+++ b/src/interfaces/ecpg/test/meson.build
@@ -47,7 +47,7 @@ ecpg_preproc_test_command_start = [
   ecpg_exe,
   '--regression',
   '-I@CURRENT_SOURCE_DIR@',
-  '-I@SOURCE_ROOT@' + '/src/interfaces/ecpg/include/',
+  '-I@0@/src/interfaces/ecpg/include/'.format(meson.project_build_root()),
 ]
 ecpg_preproc_test_command_end = [
   '-o', '@OUTPUT@', '@INPUT@'
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index c5ecd9c3a87..4aea220cd38 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -85,6 +85,8 @@ libpq = declare_dependency(
   include_directories: [include_directories('.')]
 )
 
+meson.override_dependency('libpq', libpq)
+
 # Check for functions that libpq must not call.  See libpq_check.pl for the
 # full set of platform rules.  Skip the test when profiling, as gcc may
 # insert exit() calls for that.
diff --git a/src/tools/pgflex b/src/tools/pgflex
index b8d9aa0086f..a1b471ee487 100755
--- a/src/tools/pgflex
+++ b/src/tools/pgflex
@@ -17,8 +17,6 @@ parser = argparse.ArgumentParser()
 
 parser.add_argument('--flex', type=abspath, required=True)
 parser.add_argument('--perl', type=abspath, required=True)
-parser.add_argument('--builddir', type=abspath, required=True)
-parser.add_argument('--srcdir', type=abspath, required=True)
 parser.add_argument('--privatedir', type=abspath, required=True,
                     help='private directory for target')
 
-- 
Tristan Partin
https://tristan.partin.io

Reply via email to