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
