Hi!

Thank you for looking into this!

On Thu, 19 Mar 2026 at 01:23, Zsolt Parragi <[email protected]> wrote:
> +      bitcode_targets += custom_target(
> +        targetname,
> +        depends: [bitcode_obj],
> +        input: [srcfile],
> +        output: targetname,
> +        command: [llvm_irgen_command, bitcode_cflags_gen_local],
> +        install: true,
> +        install_dir: dir_bitcode,
> +      )
>
> This seems overeager to rebuild to me. If I touch a single header
> file, it rebuilds all bc files because bitcode_obj (postgres_lib)
> changes.

bitcode_obj is equal to postgres_lib only for postgres.index.bc.


> Wouldn't something like the following work?
>
> bitcode_targets += custom_target(
>   targetname,
>   depends: [generated_backend_headers_stamp],  # instead of [postgres_lib]
>   input: [srcfile],
>   output: targetname,
>   command: [llvm_irgen_command, llvm_irgen_dep_args,
> bitcode_cflags_local],  # added llvm_irgen_dep_args

Could you mean 'bitcode_cflags_gen_local' instead of
'bitcode_cflags_local' here? Otherwise code doesn't compile.


>   depfile: targetname + '.d',  # added
>   install: true,
>   install_dir: dir_bitcode,
> )
>
> It seems to work in my testing, and results in less rebuilds. But I
> also have a fairly recent meson version, there might be some
> issues/limitations with earlier versions?

I couldn't reproduce this. There are 43 .bc files and header change (I
changed simd.h) triggers a recompilation of only 'postgres.index.bc'
on my end. This behavior seems correct to me. Could you please share
steps to reproduce the behavior you saw?


> +bitcode_modules += {
> +  'target': hstore_plpython,
> +  'srcfiles': hstore_plpython_sources,
> +  'additional_flags': [
> +    '-I@0@'.format(hstore_dir_up),
> +    '-DPLPYTHON_LIBNAME="plpython3"',
> +    '-I@0@'.format(python3_incdir),
> +    '-I@0@'.format(plpython_dir),
> +    perl_ccflags,
> +  ]
> +}
>
> Do we need perl_ccflags for python?

No, it seems I mixed plpython and plperl. Fixed.


> +meson_args = ' '.join(args.meson_args)
> ...
> +    if meson_args:
> +        meson_setup_command = [meson_bin, meson_args, 'setup',
> test_args, test_out_dir]
> +    else:
>
> Will this properly work with multiple args?

Updated. Previous version was merging all args into one string, now
each argument is one string.


> +
> +project('auth_delay', 'c')
> +
>
> Seems like a copy paste mistake, this is in postgres_fdw

Fixed.


> +    if meson_args:
> +        meson_setup_command = [meson_bin, meson_args, 'setup',
> test_args, test_out_dir]
> +    else:
> +        meson_setup_command = [meson_bin, 'setup', test_args, test_out_dir]
> +
> +    meson_compile_command = ['meson', 'compile', '-C', test_out_dir, '-v']
>
> last one should also be meson_bin

Fixed.


> +
> +exit_code = 0
> +
>
> This is an unused variable

Removed.


> src/makefiles/meson.build contains the following, this should be
> updated with this patch?
>
> # TODO: requires bitcode generation to be implemented for meson
> 'BITCODE_CFLAGS': '',
> 'BITCODE_CXXFLAGS': '',

You are right, done.


-- 
Regards,
Nazir Bilal Yavuz
Microsoft
From 194b030e40e5210bb6b2c7730075dc07d15bc091 Mon Sep 17 00:00:00 2001
From: Andres Freund <[email protected]>
Date: Sat, 27 Aug 2022 09:52:03 -0700
Subject: [PATCH v11 1/7] meson: Add postgresql-extension.pc for building
 extension libraries

This should work with several other buildsystems.

Author: Andres Freund <[email protected]>
Author: Nazir Bilal Yavuz <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
---
 src/backend/meson.build | 114 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 113 insertions(+), 1 deletion(-)

diff --git a/src/backend/meson.build b/src/backend/meson.build
index 4f5292d8f88..30a77f45fe9 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -213,9 +213,121 @@ pg_test_mod_args = pg_mod_args + {
 
 
 
+###############################################################
+# Define a .pc file that can be used to build server extensions
+###############################################################
+
+pg_ext_vars = []
+pg_ext_vars_inst = []
+pg_ext_vars_uninst = []
+
+pg_ext_cflags = pg_mod_c_args + cppflags
+pg_ext_libs = [backend_mod_deps, thread_dep, ldflags, ldflags_mod]
+pg_ext_subdirs = ['']
+
+# Compute directories to add include directories to the .pc files for.
+# This is a bit more complicated due to port/win32 etc.
+i = 0
+foreach incdir : postgres_inc_d
+  if fs.is_absolute(incdir)
+    # an absolute path from -Dextra_include_dirs
+    pg_ext_cflags += '-I@0@'.format(incdir)
+    continue
+  elif incdir.startswith('src/include')
+    subincdir = dir_include_pkg_rel / 'server' / incdir.split('src/include/').get(1, '')
+  else
+    subincdir = ''
+  endif
+  pg_ext_subdirs += subincdir
+
+  # Add directories in source / build dir containing headers to cflags for the
+  # -uninstalled.pc. Older versions of pkg-config complain if a referenced
+  # variable is not defined, so we emit an empty one for the installed .pc
+  # file.
+  pg_ext_vars += [
+    'build_inc@0@=""'.format(i),
+    'src_inc@0@=""'.format(i),
+  ]
+  pg_ext_vars_uninst += [
+    'build_inc@0@=-I${prefix}/@1@'.format(i, incdir),
+    'src_inc@0@=-I${srcdir}/@1@'.format(i, incdir),
+  ]
+  pg_ext_cflags += [
+    '${build_inc@0@}'.format(i),
+    '${src_inc@0@}'.format(i)
+  ]
+
+  i += 1
+endforeach
+
+
+# Extension modules should likely also use -fwrapv etc. But it's a bit odd to
+# expose it to a .pc file?
+pg_ext_cflags_warn = pg_ext_cflags + cflags_warn
+pg_ext_cflags += cflags
+
+# Directories for extensions to install into
+# XXX: more needed
+pg_ext_vars += 'pkglibdir=${prefix}/@0@'.format(dir_lib_pkg)
+pg_ext_vars += 'dir_mod=${pkglibdir}'
+pg_ext_vars += 'dir_data=${prefix}/@0@'.format(dir_data_extension)
+pg_ext_vars += 'dir_include=${prefix}/@0@'.format(dir_include_extension)
+pg_ext_vars += 'dir_doc=${prefix}/@0@'.format(dir_doc_extension)
+pg_ext_vars += 'dir_bitcode=${prefix}/@0@'.format(dir_bitcode)
+# referenced on some platforms, via mod_link_with_dir
+pg_ext_vars += 'bindir=${prefix}/@0@'.format(dir_bin)
+
+# XXX: Define variables making it easy to define tests, too
+
+# Some platforms need linker flags to link with binary, they are the same
+# between building with meson and .pc file, except that we have have to
+# reference a variable to make it work for both normal and -uninstalled .pc
+# files.
+if mod_link_args_fmt.length() != 0
+  assert(link_with_inst != '')
+  assert(link_with_uninst != '')
+
+  # We define mod_link_with_dir as bindir in MacOS but there is already bindir
+  # variable in pg_ext_vars, meson gives warning if we define it again.
+  if not link_with_inst.startswith('${bindir}')
+    pg_ext_vars_inst += 'mod_link_with=@0@'.format(link_with_inst)
+  endif
+  pg_ext_vars_uninst += 'mod_link_with=@0@'.format(link_with_uninst)
+
+  foreach el : mod_link_args_fmt
+    pg_ext_libs += el.format('${mod_link_with}')
+  endforeach
+endif
+
+# main .pc to build extensions
+pkgconfig.generate(
+  name: 'postgresql-extension',
+  description: 'PostgreSQL Extension Support',
+  url: pg_url,
+
+  subdirs: pg_ext_subdirs,
+  libraries: pg_ext_libs,
+  extra_cflags: pg_ext_cflags,
+
+  variables: pg_ext_vars + pg_ext_vars_inst,
+  uninstalled_variables: pg_ext_vars + pg_ext_vars_uninst,
+)
+
+# a .pc depending on the above, but with all our warnings enabled
+pkgconfig.generate(
+  name: 'postgresql-extension-warnings',
+  description: 'PostgreSQL Extension Support with compiler warnings the same as core code',
+  requires: 'postgresql-extension',
+  url: pg_url,
+  extra_cflags: pg_ext_cflags_warn,
+
+  variables: pg_ext_vars + pg_ext_vars_inst,
+  uninstalled_variables: pg_ext_vars + pg_ext_vars_uninst,
+)
+
+
 # Shared modules that, on some system, link against the server binary. Only
 # enter these after we defined the server build.
-
 subdir('jit/llvm')
 subdir('replication/libpqwalreceiver')
 subdir('replication/pgoutput')
-- 
2.47.3

From cf71b23240a76450b3268f0abfbd1c2227f64723 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <[email protected]>
Date: Thu, 27 Feb 2025 17:45:31 +0300
Subject: [PATCH v11 2/7] meson: Test building extensions by using
 postgresql-extension.pc

The 'test_meson_extensions' pyton wrapper is added to run these tests.
It compiles and builds extensions at
${build}/testrun/meson_extensions/${extension_name} path.

The tests for building amcheck, auth_delay and postgres_fdw extensions
are added. These are also examples of how to build extensions by using
postgresql-extension.pc.

Author: Andres Freund <[email protected]>
Author: Nazir Bilal Yavuz <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Reviewed-by: Zsolt Parragi <[email protected]>
Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
---
 contrib/amcheck/meson-test.build      | 31 +++++++++++
 contrib/amcheck/meson.build           |  7 +++
 contrib/auth_delay/meson-test.build   | 20 +++++++
 contrib/auth_delay/meson.build        |  7 +++
 contrib/postgres_fdw/meson-test.build | 33 +++++++++++
 contrib/postgres_fdw/meson.build      |  7 +++
 meson.build                           | 36 ++++++++++++
 src/tools/test_meson_extensions       | 80 +++++++++++++++++++++++++++
 8 files changed, 221 insertions(+)
 create mode 100644 contrib/amcheck/meson-test.build
 create mode 100644 contrib/auth_delay/meson-test.build
 create mode 100644 contrib/postgres_fdw/meson-test.build
 create mode 100644 src/tools/test_meson_extensions

diff --git a/contrib/amcheck/meson-test.build b/contrib/amcheck/meson-test.build
new file mode 100644
index 00000000000..d3aed6b4bc1
--- /dev/null
+++ b/contrib/amcheck/meson-test.build
@@ -0,0 +1,31 @@
+# Copyright (c) 2022-2026, PostgreSQL Global Development Group
+
+project('amcheck', 'c')
+
+# This file will be moved to another directory during testing. By using
+# 'meson_source_dir', we ensure that the correct Meson source directory is
+# used.
+amcheck_path = get_option('meson_source_dir')
+
+amcheck_sources = files(
+  amcheck_path / 'verify_heapam.c',
+  amcheck_path / 'verify_nbtree.c',
+)
+
+pg_ext = dependency('postgresql-extension-warnings')
+
+amcheck = shared_module('amcheck',
+  amcheck_sources,
+  dependencies: pg_ext,
+  install_dir: pg_ext.get_variable(pkgconfig: 'dir_mod'),
+)
+
+install_data(
+  amcheck_path / 'amcheck.control',
+  amcheck_path / 'amcheck--1.0.sql',
+  amcheck_path / 'amcheck--1.0--1.1.sql',
+  amcheck_path / 'amcheck--1.1--1.2.sql',
+  amcheck_path / 'amcheck--1.2--1.3.sql',
+  amcheck_path / 'amcheck--1.3--1.4.sql',
+  install_dir: pg_ext.get_variable(pkgconfig: 'dir_data'),
+)
diff --git a/contrib/amcheck/meson.build b/contrib/amcheck/meson.build
index d5137ef691d..4952feebb8c 100644
--- a/contrib/amcheck/meson.build
+++ b/contrib/amcheck/meson.build
@@ -53,3 +53,10 @@ tests += {
     ],
   },
 }
+
+meson_extension_tests += {
+  'name': 'amcheck',
+  'kind': 'pkg_config',
+  'sd': meson.current_source_dir(),
+  'input': files('meson-test.build'),
+}
diff --git a/contrib/auth_delay/meson-test.build b/contrib/auth_delay/meson-test.build
new file mode 100644
index 00000000000..5d5bc4d740e
--- /dev/null
+++ b/contrib/auth_delay/meson-test.build
@@ -0,0 +1,20 @@
+# Copyright (c) 2022-2026, PostgreSQL Global Development Group
+
+project('auth_delay', 'c')
+
+# This file will be moved to another directory during testing. By using
+# 'meson_source_dir', we ensure that the correct Meson source directory is
+# used.
+auth_delay_path = get_option('meson_source_dir')
+
+auth_delay_sources = files(
+  auth_delay_path / 'auth_delay.c',
+)
+
+pg_ext = dependency('postgresql-extension-warnings')
+
+auth_delay = shared_module('auth_delay',
+  auth_delay_sources,
+  dependencies: pg_ext,
+  install_dir: pg_ext.get_variable(pkgconfig: 'dir_mod'),
+)
diff --git a/contrib/auth_delay/meson.build b/contrib/auth_delay/meson.build
index 21192992a84..a3286bcf3ff 100644
--- a/contrib/auth_delay/meson.build
+++ b/contrib/auth_delay/meson.build
@@ -15,3 +15,10 @@ auth_delay = shared_module('auth_delay',
   kwargs: contrib_mod_args,
 )
 contrib_targets += auth_delay
+
+meson_extension_tests += {
+  'name': 'auth_delay',
+  'kind': 'pkg_config',
+  'sd': meson.current_source_dir(),
+  'input': files('meson-test.build'),
+}
\ No newline at end of file
diff --git a/contrib/postgres_fdw/meson-test.build b/contrib/postgres_fdw/meson-test.build
new file mode 100644
index 00000000000..230c4ec4f50
--- /dev/null
+++ b/contrib/postgres_fdw/meson-test.build
@@ -0,0 +1,33 @@
+# Copyright (c) 2022-2026, PostgreSQL Global Development Group
+
+project('postgres_fdw', 'c')
+
+# This file will be moved to another directory during testing. By using
+# 'meson_source_dir', we ensure that the correct Meson source directory is
+# used.
+postgres_fdw_path = get_option('meson_source_dir')
+
+postgres_fdw_sources = files(
+  postgres_fdw_path / 'connection.c',
+  postgres_fdw_path / 'deparse.c',
+  postgres_fdw_path / 'option.c',
+  postgres_fdw_path / 'postgres_fdw.c',
+  postgres_fdw_path / 'shippable.c',
+)
+
+pg_ext = dependency('postgresql-extension-warnings')
+libpq = dependency('libpq')
+
+postgres_fdw = shared_module('postgres_fdw',
+  postgres_fdw_sources,
+  dependencies: [pg_ext, libpq],
+  install_dir: pg_ext.get_variable(pkgconfig: 'dir_mod'),
+)
+
+install_data(
+  postgres_fdw_path / 'postgres_fdw.control',
+  postgres_fdw_path / 'postgres_fdw--1.0.sql',
+  postgres_fdw_path / 'postgres_fdw--1.0--1.1.sql',
+  postgres_fdw_path / 'postgres_fdw--1.1--1.2.sql',
+  install_dir: pg_ext.get_variable(pkgconfig: 'dir_data'),
+)
diff --git a/contrib/postgres_fdw/meson.build b/contrib/postgres_fdw/meson.build
index 3e2ed06b766..9a50aaba07a 100644
--- a/contrib/postgres_fdw/meson.build
+++ b/contrib/postgres_fdw/meson.build
@@ -55,3 +55,10 @@ tests += {
     ],
   },
 }
+
+meson_extension_tests += {
+  'name': 'postgres_fdw',
+  'kind': 'pkg_config',
+  'sd': meson.current_source_dir(),
+  'input': files('meson-test.build'),
+}
diff --git a/meson.build b/meson.build
index 0a181909fab..8cc87a9dbf5 100644
--- a/meson.build
+++ b/meson.build
@@ -3271,6 +3271,7 @@ update_unicode_targets = []
 # Define the tests to distribute them to the correct test styles later
 test_deps = []
 tests = []
+meson_extension_tests = []
 
 
 # Default options for targets
@@ -3827,6 +3828,41 @@ sys.exit(sp.returncode)
      suite: ['setup'])
 
 
+# pkgconfig is not available on Windows, so skip it.
+if host_machine.system() != 'windows'
+  # it seems freebsd doesn't use libdir for pkgconfig path
+  if host_system == 'freebsd'
+    pkgconf_installdir =  dir_prefix / 'libdata' / 'pkgconfig'
+  else
+    pkgconf_installdir = dir_prefix / dir_lib / 'pkgconfig'
+  endif
+  test_pkg_conf_file = files('src/tools/test_meson_extensions')
+
+  foreach test : meson_extension_tests
+    if test['kind'] not in ['pkg_config']
+      error('unknown kind @0@ of test in @1@'.format(test['kind'], test['sd']))
+    endif
+
+    test_group = 'meson_@0@_extensions'.format(test['kind'])
+
+    test(test_group / test['name'],
+        test_pkg_conf_file,
+        args: [
+          '--meson', meson_bin.full_path(),
+          '--meson_args', meson_args,
+          '--input', test['input'],
+          '--test_source_dir', test['sd'],
+          '--test_dir', test_result_dir / 'meson_extensions' / test['name'],
+          '--builddir', meson.project_build_root(),
+          '--pkg_conf_path', get_option('pkg_config_path'),
+          '--',
+            cc.cmd_array(),
+          ],
+          suite: test_group,
+        )
+
+  endforeach
+endif
 
 ###############################################################
 # Test Generation
diff --git a/src/tools/test_meson_extensions b/src/tools/test_meson_extensions
new file mode 100644
index 00000000000..d0306b04b5a
--- /dev/null
+++ b/src/tools/test_meson_extensions
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import shutil
+import subprocess
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument('--meson', help='path to meson binary',
+                    type=str, required=True)
+parser.add_argument('--meson_args', help='args of meson binary',
+                    type=str, nargs='*', required=False)
+parser.add_argument('--input', help='input meson-test.build file',
+                    type=str, required=True)
+parser.add_argument('--test_dir', help='test directory',
+                    type=str, required=True)
+parser.add_argument('--test_source_dir', help='test source directory',
+                    type=str, required=True)
+parser.add_argument('--builddir', help='meson build directory',
+                    type=str, required=True)
+parser.add_argument('--pkg_conf_path',
+                    help='PKG_CONF_PATH from surrounding meson build',
+                    type=str, nargs='?', const='', required=False)
+parser.add_argument('c_args', help='c_args from surrounding meson build',
+                     nargs='*')
+
+args = parser.parse_args()
+
+meson_bin = args.meson
+meson_args = args.meson_args or []
+input = args.input
+test_dir = args.test_dir
+test_source_dir = args.test_source_dir
+build_dir = args.builddir
+pkg_conf_path = args.pkg_conf_path
+c_args = ' '.join(args.c_args)
+
+def remove_duplicates(duplicate_str):
+    # Remove duplicates based on basename as there could be a mix of both full
+    # paths and bare binary names.
+    words = [os.path.basename(word) for word in duplicate_str.split()]
+    return ' '.join(sorted(set(words), key=words.index))
+
+
+def run_tests(pkg_conf_path_local, message):
+    print('\n{}\n{}\n'.format('#' * 60, message), flush=True)
+
+    test_out_dir = 'build'
+    test_args = f'-Dmeson_source_dir={test_source_dir}'
+
+    env = {**os.environ, }
+    env['PKG_CONFIG_PATH'] = '{}:{}:{}'.format(
+      pkg_conf_path_local, pkg_conf_path, env.get('PKG_CONFIG_PATH', ''),
+    ).strip(': ')
+    env['CC'] = '{} {}'.format(
+      c_args, env.get('CC', ''),
+    )
+    env['CC'] = remove_duplicates(env['CC'])
+
+    # Copy input file to test directory and rename it as a meson.build
+    if os.path.exists(test_dir):
+        shutil.rmtree(test_dir)
+    os.makedirs(test_dir)
+    shutil.copyfile(input, os.path.join(test_dir, 'meson.build'))
+
+    # Put meson_options.txt to the test_dir so that we can pass
+    # meson_source_dir argument
+    with open(os.path.join(test_dir, 'meson_options.txt'), 'w') as f:
+        f.write("option('meson_source_dir', type: 'string', value: '',\n"
+                "  description: 'Actual source directory of the meson-test.build file')\n")
+
+    meson_setup_command = [meson_bin, *meson_args, 'setup', test_args, test_out_dir]
+    meson_compile_command = [meson_bin, 'compile', '-C', test_out_dir, '-v']
+
+    subprocess.run(meson_setup_command, env=env, cwd=test_dir, check=True)
+    subprocess.run(meson_compile_command, cwd=test_dir, check=True)
+
+run_tests(os.path.join(build_dir, 'meson-uninstalled'),
+          message='Testing postgresql-extension-warnings-uninstalled')
-- 
2.47.3

From e668a8658105dee2da525a0318b830970377b83a Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <[email protected]>
Date: Thu, 6 Mar 2025 17:46:57 +0300
Subject: [PATCH v11 3/7] meson: Add docs for postgresql-extension.pc

Author: Andres Freund <[email protected]>
Author: Nazir Bilal Yavuz <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
---
 doc/src/sgml/acronyms.sgml |   2 +-
 doc/src/sgml/extend.sgml   | 130 ++++++++++++++++++++++++++-----------
 doc/src/sgml/jit.sgml      |   2 +-
 3 files changed, 95 insertions(+), 39 deletions(-)

diff --git a/doc/src/sgml/acronyms.sgml b/doc/src/sgml/acronyms.sgml
index 2f906e9f018..57f49c06a19 100644
--- a/doc/src/sgml/acronyms.sgml
+++ b/doc/src/sgml/acronyms.sgml
@@ -579,7 +579,7 @@
     <term><acronym>PGXS</acronym></term>
     <listitem>
      <para>
-      <link linkend="extend-pgxs"><productname>PostgreSQL</productname> Extension System</link>
+      <link linkend="extend-postgres-pgxs"><productname>PostgreSQL</productname> Extension System</link>
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml
index 63c5ec6d1eb..ffc1df0459c 100644
--- a/doc/src/sgml/extend.sgml
+++ b/doc/src/sgml/extend.sgml
@@ -1426,7 +1426,7 @@ include $(PGXS)
 </programlisting>
 
      This makefile relies on <acronym>PGXS</acronym>, which is described
-     in <xref linkend="extend-pgxs"/>.  The command <literal>make install</literal>
+     in <xref linkend="extend-postgres-pgxs"/>.  The command <literal>make install</literal>
      will install the control and script files into the correct
      directory as reported by <application>pg_config</application>.
     </para>
@@ -1439,21 +1439,26 @@ include $(PGXS)
    </sect2>
   </sect1>
 
-  <sect1 id="extend-pgxs">
+  <sect1 id="extend-postgres">
    <title>Extension Building Infrastructure</title>
 
-   <indexterm zone="extend-pgxs">
-    <primary>pgxs</primary>
-   </indexterm>
-
    <para>
     If you are thinking about distributing your
     <productname>PostgreSQL</productname> extension modules, setting up a
     portable build system for them can be fairly difficult.  Therefore
     the <productname>PostgreSQL</productname> installation provides a build
-    infrastructure for extensions, called <acronym>PGXS</acronym>, so
-    that simple extension modules can be built simply against an
-    already installed server.  <acronym>PGXS</acronym> is mainly intended
+    infrastructure for extensions, called <literal>PGXS</literal>
+    (<xref linkend="extend-postgres-pgxs"/>) and
+    its meson counterpart <literal>postgresql-extension.pc</literal>
+    (<xref linkend="extend-postgres-meson"/>).
+   </para>
+
+  </sect1>
+
+  <sect1 id="extend-postgres-pgxs">
+   <title>PGXS</title>
+
+   <para>  <acronym>PGXS</acronym> is mainly intended
     for extensions that include C code, although it can be used for
     pure-SQL extensions too.  Note that <acronym>PGXS</acronym> is not
     intended to be a universal build system framework that can be used
@@ -1493,7 +1498,7 @@ include $(PGXS)
     Set one of these three variables to specify what is built:
 
     <variablelist>
-     <varlistentry id="extend-pgxs-modules">
+     <varlistentry id="extend-postgres-pgxs-modules">
       <term><varname>MODULES</varname></term>
       <listitem>
        <para>
@@ -1503,7 +1508,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-module-big">
+     <varlistentry id="extend-postgres-pgxs-module-big">
       <term><varname>MODULE_big</varname></term>
       <listitem>
        <para>
@@ -1513,7 +1518,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-program">
+     <varlistentry id="extend-postgres-pgxs-program">
       <term><varname>PROGRAM</varname></term>
       <listitem>
        <para>
@@ -1527,7 +1532,7 @@ include $(PGXS)
     The following variables can also be set:
 
     <variablelist>
-     <varlistentry id="extend-pgxs-extension">
+     <varlistentry id="extend-postgres-pgxs-extension">
       <term><varname>EXTENSION</varname></term>
       <listitem>
        <para>
@@ -1539,7 +1544,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-moduledir">
+     <varlistentry id="extend-postgres-pgxs-moduledir">
       <term><varname>MODULEDIR</varname></term>
       <listitem>
        <para>
@@ -1552,7 +1557,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-data">
+     <varlistentry id="extend-postgres-pgxs-data">
       <term><varname>DATA</varname></term>
       <listitem>
        <para>
@@ -1561,7 +1566,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-data-built">
+     <varlistentry id="extend-postgres-pgxs-data-built">
       <term><varname>DATA_built</varname></term>
       <listitem>
        <para>
@@ -1572,7 +1577,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-data-tsearch">
+     <varlistentry id="extend-postgres-pgxs-data-tsearch">
       <term><varname>DATA_TSEARCH</varname></term>
       <listitem>
        <para>
@@ -1582,7 +1587,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-docs">
+     <varlistentry id="extend-postgres-pgxs-docs">
       <term><varname>DOCS</varname></term>
       <listitem>
        <para>
@@ -1592,7 +1597,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-headers">
+     <varlistentry id="extend-postgres-pgxs-headers">
       <term><varname>HEADERS</varname></term>
       <term><varname>HEADERS_built</varname></term>
       <listitem>
@@ -1608,7 +1613,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-headers-module">
+     <varlistentry id="extend-postgres-pgxs-headers-module">
       <term><varname>HEADERS_$MODULE</varname></term>
       <term><varname>HEADERS_built_$MODULE</varname></term>
       <listitem>
@@ -1634,7 +1639,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-scripts">
+     <varlistentry id="extend-postgres-pgxs-scripts">
       <term><varname>SCRIPTS</varname></term>
       <listitem>
        <para>
@@ -1644,7 +1649,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-scripts-built">
+     <varlistentry id="extend-postgres-pgxs-scripts-built">
       <term><varname>SCRIPTS_built</varname></term>
       <listitem>
        <para>
@@ -1655,7 +1660,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-regress">
+     <varlistentry id="extend-postgres-pgxs-regress">
       <term><varname>REGRESS</varname></term>
       <listitem>
        <para>
@@ -1664,7 +1669,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-regress-opts">
+     <varlistentry id="extend-postgres-pgxs-regress-opts">
       <term><varname>REGRESS_OPTS</varname></term>
       <listitem>
        <para>
@@ -1673,7 +1678,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-isolation">
+     <varlistentry id="extend-postgres-pgxs-isolation">
       <term><varname>ISOLATION</varname></term>
       <listitem>
        <para>
@@ -1682,7 +1687,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-isolation-opts">
+     <varlistentry id="extend-postgres-pgxs-isolation-opts">
       <term><varname>ISOLATION_OPTS</varname></term>
       <listitem>
        <para>
@@ -1692,7 +1697,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-tap-tests">
+     <varlistentry id="extend-postgres-pgxs-tap-tests">
       <term><varname>TAP_TESTS</varname></term>
       <listitem>
        <para>
@@ -1701,7 +1706,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-no-install">
+     <varlistentry id="extend-postgres-pgxs-no-install">
       <term><varname>NO_INSTALL</varname></term>
       <listitem>
        <para>
@@ -1711,7 +1716,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-no-installcheck">
+     <varlistentry id="extend-postgres-pgxs-no-installcheck">
       <term><varname>NO_INSTALLCHECK</varname></term>
       <listitem>
        <para>
@@ -1720,7 +1725,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-extra-clean">
+     <varlistentry id="extend-postgres-pgxs-extra-clean">
       <term><varname>EXTRA_CLEAN</varname></term>
       <listitem>
        <para>
@@ -1729,7 +1734,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-pg-cppflags">
+     <varlistentry id="extend-postgres-pgxs-pg-cppflags">
       <term><varname>PG_CPPFLAGS</varname></term>
       <listitem>
        <para>
@@ -1738,7 +1743,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-pg-cflags">
+     <varlistentry id="extend-postgres-pgxs-pg-cflags">
       <term><varname>PG_CFLAGS</varname></term>
       <listitem>
        <para>
@@ -1747,7 +1752,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-pg-cxxflags">
+     <varlistentry id="extend-postgres-pgxs-pg-cxxflags">
       <term><varname>PG_CXXFLAGS</varname></term>
       <listitem>
        <para>
@@ -1756,7 +1761,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-pg-ldflags">
+     <varlistentry id="extend-postgres-pgxs-pg-ldflags">
       <term><varname>PG_LDFLAGS</varname></term>
       <listitem>
        <para>
@@ -1765,7 +1770,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-pg-libs">
+     <varlistentry id="extend-postgres-pgxs-pg-libs">
       <term><varname>PG_LIBS</varname></term>
       <listitem>
        <para>
@@ -1774,7 +1779,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-shlib-link">
+     <varlistentry id="extend-postgres-pgxs-shlib-link">
       <term><varname>SHLIB_LINK</varname></term>
       <listitem>
        <para>
@@ -1783,7 +1788,7 @@ include $(PGXS)
       </listitem>
      </varlistentry>
 
-     <varlistentry id="extend-pgxs-pg-config">
+     <varlistentry id="extend-postgres-pgxs-pg-config">
       <term><varname>PG_CONFIG</varname></term>
       <listitem>
        <para>
@@ -1929,4 +1934,55 @@ make VPATH=/path/to/extension/source/tree install
    </tip>
   </sect1>
 
+  <sect1 id="extend-postgres-meson">
+   <title>postgresql-extension.pc</title>
+
+   <para>
+    When Postgres is built by using meson, it generates
+    <literal>postgresql-extension.pc</literal> pkg-config file. Extension
+    libraries can use this file like <literal>PGXS</literal>
+    (<xref linkend="extend-postgres-pgxs"/>).
+
+    To use the <literal>postgresql-extension.pc</literal> infrastructure for
+    your extension, you must write a simple meson.build file. In the
+    meson.build file, you need to include the
+    <literal>postgresql-extension.pc</literal> pkg-config file. Here is an
+    example that builds an extension module named isbn_issn, consisting of a
+    shared library containing some C code, an extension control file, an SQL
+    script, an include file (only needed if other modules might need to access
+    the extension functions without going via SQL), and a documentation text
+    file:
+<programlisting>
+project('isbn_issn', 'c')
+
+pg_ext = dependency('postgresql-extension-warnings')
+
+isbn_issn_sources = files('isbn_issn.c')
+
+isbn_issn = shared_module('isbn_issn',
+  isbn_issn_sources,
+  dependencies: pg_ext,
+  install_dir: pg_ext.get_variable(pkgconfig: 'dir_mod'),
+)
+
+install_data(
+     'isbn_issn.control',
+     'isbn_issn--1.0.sql',
+     install_dir: pg_ext.get_variable(pkgconfig: 'dir_data'),
+)
+
+install_headers(
+     'isbn_issn.h',
+     install_dir: pg_ext.get_variable(pkgconfig: 'dir_include'),
+)
+
+install_data(
+     'README.isbn_issn',
+     install_dir: pg_ext.get_variable(pkgconfig: 'dir_doc'),
+)
+</programlisting>
+   </para>
+
+  </sect1>
+
  </chapter>
diff --git a/doc/src/sgml/jit.sgml b/doc/src/sgml/jit.sgml
index 44e18bf1a6f..81a4644a97d 100644
--- a/doc/src/sgml/jit.sgml
+++ b/doc/src/sgml/jit.sgml
@@ -223,7 +223,7 @@ SET
     of types <literal>C</literal> and <literal>internal</literal>, as well as
     operators based on such functions.  To do so for functions in extensions,
     the definitions of those functions need to be made available.
-    When using <link linkend="extend-pgxs">PGXS</link> to build an extension
+    When using <link linkend="extend-postgres-pgxs">PGXS</link> to build an extension
     against a server that has been compiled with LLVM JIT support, the
     relevant files will be built and installed automatically.
    </para>
-- 
2.47.3

From 7e2faca825dca493c28c760d4d0717597516da1c Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <[email protected]>
Date: Fri, 7 Mar 2025 12:10:58 +0300
Subject: [PATCH v11 4/7] meson: Add architecture for LLVM bitcode emission

This commit adds suport for bitcode emission for both normal and
generated source files (processed by bison, flex, etc). These bitcode
files are installed into $pkglibdir/bitcode/ directory if the LLVM is
found.

New variable `bitcode_modules` is introduced to generate bitcode files.
All required information is gathered in this variable. Then, this
variable is processed by the main meson LLVM bitcode emission scripts:
src/backend/jit/llvm/bitcode/meson.build -> src/tools/irlink.

An example of a possible structure of bitcode_modules is:
```
bitcode_modules = [
  {
    'name': '...',
    'target': ...,
    'srcfiles': [
      '...',
      '...',
    ],
    'additional_flags': [
      '-I...',
      '-I...',
    ],
    'gen_srcfiles': [
      {
        'srcfiles': [
          <custom_target for ...>,
          <custom_target for ...>,
        ],
        'additional_flags': [
          '-I...',
          '-I...',
        ]
      }
    ]
  }
]
```

Author: Andres Freund <[email protected]>
Author: Nazir Bilal Yavuz <[email protected]>
Author: Diego Fronza <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Reviewed-by: Diego Fronza <[email protected]>
Reviewed-by: Zsolt Parragi <[email protected]>
Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
---
 meson.build                              | 21 ++++++++
 src/backend/jit/llvm/bitcode/meson.build | 69 ++++++++++++++++++++++++
 src/backend/jit/llvm/meson.build         | 40 +++++++++-----
 src/backend/meson.build                  |  9 ++++
 src/makefiles/meson.build                |  5 +-
 src/tools/irlink                         | 25 +++++++++
 6 files changed, 152 insertions(+), 17 deletions(-)
 create mode 100644 src/backend/jit/llvm/bitcode/meson.build
 create mode 100644 src/tools/irlink

diff --git a/meson.build b/meson.build
index 8cc87a9dbf5..021e6096e40 100644
--- a/meson.build
+++ b/meson.build
@@ -942,6 +942,8 @@ if have_cxx
     # Some distros put LLVM and clang in different paths, so fallback to
     # find via PATH, too.
     clang = find_program(llvm_binpath / 'clang', 'clang', required: true)
+    llvm_lto = find_program(llvm_binpath / 'llvm-lto', required: true)
+    irlink = find_program('src/tools/irlink', native: true)
   endif
 else
   msg = 'llvm requires a C++ compiler'
@@ -3273,6 +3275,11 @@ test_deps = []
 tests = []
 meson_extension_tests = []
 
+# List of object files + source files to generated LLVM IR for inlining.
+# Each element is a hash of:
+# {'target': target, 'srcfiles': ..., 'additional_flags': ...}.
+bitcode_modules = []
+
 
 # Default options for targets
 
@@ -3596,6 +3603,11 @@ subdir('src/interfaces/ecpg/test')
 
 subdir('doc/src/sgml')
 
+# generate bitcode for JIT inlining after giving contrib modules etc a chance
+# to add themselves to bitcode_modules[]
+subdir('src/backend/jit/llvm/bitcode', if_found: llvm)
+
+
 generated_sources_ac += {'': ['GNUmakefile']}
 
 # After processing src/test, add test_install_libs to the testprep_targets
@@ -4241,6 +4253,15 @@ summary(
   section: 'Programs',
 )
 
+if llvm.found()
+  summary(
+    {
+      'clang': clang,
+    },
+    section: 'Programs',
+  )
+endif
+
 summary(
   {
     'bonjour': bonjour,
diff --git a/src/backend/jit/llvm/bitcode/meson.build b/src/backend/jit/llvm/bitcode/meson.build
new file mode 100644
index 00000000000..570f8abefa4
--- /dev/null
+++ b/src/backend/jit/llvm/bitcode/meson.build
@@ -0,0 +1,69 @@
+# Copyright (c) 2022-2024, PostgreSQL Global Development Group
+#
+# emit LLVM bitcode for JIT inlining
+
+assert(llvm.found())
+
+foreach bitcode_module : bitcode_modules
+  bitcode_targets = []
+  bitcode_obj = bitcode_module['target']
+  bitcode_cflags_local = bitcode_cflags + bitcode_module.get('additional_flags', [])
+  bitcode_name = bitcode_module.get('name', bitcode_obj.name())
+
+  foreach srcfile : bitcode_module['srcfiles']
+    if meson.version().version_compare('>=0.59')
+      srcfilename = fs.parent(srcfile) / fs.name(srcfile)
+    else
+      srcfilename = '@0@'.format(srcfile)
+    endif
+
+    targetname = '@0@_@[email protected]'.format(
+      bitcode_name,
+      srcfilename.underscorify(),
+    )
+    bitcode_targets += custom_target(
+      targetname,
+      depends: [bitcode_obj],
+      input: [srcfile],
+      output: targetname,
+      command: [llvm_irgen_command, bitcode_cflags_local],
+      install: true,
+      install_dir: dir_bitcode,
+    )
+  endforeach
+
+  # Process generated sources, which may include custom compilation flags.
+  foreach gen_sources: bitcode_module.get('gen_sources', [])
+    bitcode_cflags_gen_local = bitcode_cflags_local + gen_sources.get('additional_flags', [])
+
+    foreach srcfile: gen_sources['srcfiles']
+      # Generated sources are stored in some folder under meson.build_root()/**,
+      # remove the build prefix from the string.
+      srcfilename = srcfile.full_path().split(meson.project_build_root() + '/')[1]
+
+      targetname = '@0@_@[email protected]'.format(
+        bitcode_name,
+        srcfilename.underscorify(),
+      )
+      bitcode_targets += custom_target(
+        targetname,
+        depends: [bitcode_obj],
+        input: [srcfile],
+        output: targetname,
+        command: [llvm_irgen_command, bitcode_cflags_gen_local],
+        install: true,
+        install_dir: dir_bitcode,
+      )
+    endforeach
+  endforeach
+
+  index_name = '@[email protected]'.format(bitcode_name)
+  bitcode_index = custom_target('@0@'.format(bitcode_name),
+    output: index_name,
+    input: bitcode_targets,
+    command: [irlink, '--lto', llvm_lto, '--outdir', '@OUTDIR@', '--index', index_name, '@INPUT@'],
+    install: true,
+    install_dir: dir_bitcode,
+  )
+  backend_targets += bitcode_index
+endforeach
diff --git a/src/backend/jit/llvm/meson.build b/src/backend/jit/llvm/meson.build
index 7df8453ad6f..ceb5bc7bd88 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -42,28 +42,32 @@ backend_targets += llvmjit
 
 # Define a few bits and pieces used here and elsewhere to generate bitcode
 
-llvm_irgen_args = [
-  '-c', '-o', '@OUTPUT@', '@INPUT@',
+llvm_irgen_command = []
+if ccache.found()
+  llvm_irgen_command += ccache
+endif
+
+llvm_irgen_command += [
+  clang,
+  '-c', '-o', '@OUTPUT0@', '@INPUT0@',
   '-flto=thin', '-emit-llvm',
-  '-MD', '-MQ', '@OUTPUT@', '-MF', '@DEPFILE@',
-  '-O2',
   '-Wno-ignored-attributes',
   '-Wno-empty-body',
+  '-Wno-unknown-warning-option',
+  '-Wno-compound-token-split-by-macro',
 ]
-
-if ccache.found()
-  llvm_irgen_command = ccache
-  llvm_irgen_args = [clang.full_path()] + llvm_irgen_args
-else
-  llvm_irgen_command = clang
-endif
+llvm_irgen_dep_args = ['-MD', '-MQ', '@OUTPUT0@', '-MF', '@DEPFILE@']
 
 
 # XXX: Need to determine proper version of the function cflags for clang
-bitcode_cflags = ['-fno-strict-aliasing', '-fwrapv']
-bitcode_cflags += get_option('c_args')
+bitcode_cflags = ['-fno-strict-aliasing', '-fwrapv', '-O2']
 bitcode_cflags += cppflags
 
+var_bitcode_cxxflags = bitcode_cflags
+var_bitcode_cxxflags += get_option('cpp_args')
+bitcode_cflags += get_option('c_args')
+var_bitcode_cflags = bitcode_cflags
+
 # 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'
@@ -73,7 +77,7 @@ bitcode_cflags += '-I@SOURCE_ROOT@/src/include'
 # Note this is intentionally not installed to bitcodedir, as it's not for
 # inlining
 llvmjit_types = custom_target('llvmjit_types.bc',
-  command: [llvm_irgen_command] + llvm_irgen_args + bitcode_cflags,
+  command: llvm_irgen_command + llvm_irgen_dep_args + bitcode_cflags,
   input: 'llvmjit_types.c',
   output: 'llvmjit_types.bc',
   depends: [postgres],
@@ -82,3 +86,11 @@ llvmjit_types = custom_target('llvmjit_types.bc',
   depfile: '@[email protected]',
 )
 backend_targets += llvmjit_types
+
+# Figure out -I's needed to build all postgres code, including all its
+# dependencies
+pkg_config = find_program(['pkg-config', 'pkgconf'], required: true)
+r = run_command(pkg_config,
+  ['--cflags-only-I', meson.project_build_root() / 'meson-uninstalled/postgresql-extension-uninstalled.pc'],
+  check: true)
+bitcode_cflags += r.stdout().split()
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 30a77f45fe9..2877127954b 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -7,6 +7,9 @@ backend_link_with = [pgport_srv, common_srv]
 generated_backend_sources = []
 post_export_backend_sources = []
 
+var_bitcode_cflags = []
+var_bitcode_cxxflags = []
+
 subdir('access')
 subdir('archive')
 subdir('backup')
@@ -165,6 +168,12 @@ postgres = executable('postgres',
 
 backend_targets += postgres
 
+bitcode_modules += {
+  'name': 'postgres',
+  'target': postgres_lib,
+  'srcfiles': backend_sources,
+}
+
 pg_mod_c_args = cflags_mod
 pg_mod_cxx_args = cxxflags_mod
 pg_mod_link_args = ldflags_sl + ldflags_mod
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index 2401025d1cd..1d09aed1d86 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -113,9 +113,8 @@ pgxs_kv = {
     ' '.join(cc.get_supported_link_arguments('-Wl,--export-dynamic')),
   'LDFLAGS_SL': var_ldflags_sl,
 
-  # TODO: requires bitcode generation to be implemented for meson
-  'BITCODE_CFLAGS': '',
-  'BITCODE_CXXFLAGS': '',
+  'BITCODE_CFLAGS': ' '.join(var_bitcode_cflags),
+  'BITCODE_CXXFLAGS': ' '.join(var_bitcode_cxxflags),
 
   'BISONFLAGS': ' '.join(bison_flags),
   'FLEXFLAGS': ' '.join(flex_flags),
diff --git a/src/tools/irlink b/src/tools/irlink
new file mode 100644
index 00000000000..793c0abf91a
--- /dev/null
+++ b/src/tools/irlink
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import shutil
+import subprocess
+import sys
+
+parser = argparse.ArgumentParser(
+    description='generate PostgreSQL JIT IR module')
+
+parser.add_argument('--index', type=str, required=True)
+parser.add_argument('--lto', type=str, required=True)
+parser.add_argument('--outdir', type=str, required=True)
+parser.add_argument('INPUT', type=str, nargs='+')
+
+args = parser.parse_args()
+
+file_names = [os.path.basename(f) for f in args.INPUT]
+command = [args.lto,
+           '-thinlto', '-thinlto-action=thinlink',
+           '-o', args.index] + file_names
+res = subprocess.run(command, cwd=args.outdir)
+
+exit(res.returncode)
-- 
2.47.3

From 3b6753a236288d539ffb6bb391e80a9b8ddb18f0 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <[email protected]>
Date: Mon, 16 Mar 2026 18:15:59 +0300
Subject: [PATCH v11 5/7] meson: Add LLVM bitcode emissions for contrib
 libraries

The libraries which the bitcode files will be generated in are selected
manually.

Author: Andres Freund <[email protected]>
Author: Nazir Bilal Yavuz <[email protected]>
Author: Diego Fronza <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Reviewed-by: Diego Fronza <[email protected]>
Reviewed-by: Zsolt Parragi <[email protected]>
Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
---
 contrib/bloom/meson.build             |  5 +++++
 contrib/bool_plperl/meson.build       |  9 +++++++++
 contrib/btree_gin/meson.build         |  5 +++++
 contrib/btree_gist/meson.build        |  5 +++++
 contrib/citext/meson.build            |  5 +++++
 contrib/cube/meson.build              | 13 +++++++++++++
 contrib/dict_int/meson.build          |  5 +++++
 contrib/dict_xsyn/meson.build         |  5 +++++
 contrib/earthdistance/meson.build     |  6 ++++++
 contrib/fuzzystrmatch/meson.build     |  9 +++++++++
 contrib/hstore/meson.build            |  7 +++++++
 contrib/hstore_plperl/meson.build     | 10 ++++++++++
 contrib/hstore_plpython/meson.build   | 11 +++++++++++
 contrib/intarray/meson.build          |  5 +++++
 contrib/isn/meson.build               |  5 +++++
 contrib/jsonb_plperl/meson.build      |  8 ++++++++
 contrib/jsonb_plpython/meson.build    | 10 ++++++++++
 contrib/lo/meson.build                |  5 +++++
 contrib/ltree/meson.build             | 10 ++++++++++
 contrib/ltree_plpython/meson.build    | 11 +++++++++++
 contrib/pg_buffercache/meson.build    |  5 +++++
 contrib/pg_freespacemap/meson.build   |  5 +++++
 contrib/pg_logicalinspect/meson.build |  5 +++++
 contrib/pg_surgery/meson.build        |  4 ++++
 contrib/pg_trgm/meson.build           |  5 +++++
 contrib/pgcrypto/meson.build          |  4 ++++
 contrib/seg/meson.build               | 12 ++++++++++++
 contrib/spi/meson.build               | 20 ++++++++++++++++++++
 contrib/sslinfo/meson.build           |  5 +++++
 contrib/tablefunc/meson.build         |  5 +++++
 contrib/tcn/meson.build               |  5 +++++
 contrib/tsm_system_rows/meson.build   |  5 +++++
 contrib/tsm_system_time/meson.build   |  5 +++++
 contrib/unaccent/meson.build          |  5 +++++
 contrib/uuid-ossp/meson.build         |  5 +++++
 contrib/xml2/meson.build              |  5 +++++
 meson.build                           |  1 +
 src/interfaces/libpq/meson.build      |  3 +++
 src/pl/plperl/meson.build             |  1 +
 src/pl/plpython/meson.build           |  1 +
 40 files changed, 255 insertions(+)

diff --git a/contrib/bloom/meson.build b/contrib/bloom/meson.build
index fa4f4ea796b..780bb494d54 100644
--- a/contrib/bloom/meson.build
+++ b/contrib/bloom/meson.build
@@ -28,6 +28,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': bloom,
+  'srcfiles': bloom_sources,
+}
+
 tests += {
   'name': 'bloom',
   'sd': meson.current_source_dir(),
diff --git a/contrib/bool_plperl/meson.build b/contrib/bool_plperl/meson.build
index d19abf0dd6d..cd1ab595ee9 100644
--- a/contrib/bool_plperl/meson.build
+++ b/contrib/bool_plperl/meson.build
@@ -37,6 +37,15 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': bool_plperl,
+  'srcfiles': bool_plperl_sources,
+  'additional_flags': [
+    '-I@0@'.format(plperl_dir),
+    perl_ccflags
+  ]
+}
+
 tests += {
   'name': 'bool_plperl',
   'sd': meson.current_source_dir(),
diff --git a/contrib/btree_gin/meson.build b/contrib/btree_gin/meson.build
index 039cfc52c86..4406f9f998d 100644
--- a/contrib/btree_gin/meson.build
+++ b/contrib/btree_gin/meson.build
@@ -26,6 +26,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': btree_gin,
+  'srcfiles': btree_gin_sources,
+}
+
 tests += {
   'name': 'btree_gin',
   'sd': meson.current_source_dir(),
diff --git a/contrib/btree_gist/meson.build b/contrib/btree_gist/meson.build
index 2b1a5463289..9fae0eb7289 100644
--- a/contrib/btree_gist/meson.build
+++ b/contrib/btree_gist/meson.build
@@ -55,6 +55,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': btree_gist,
+  'srcfiles': btree_gist_sources,
+}
+
 tests += {
   'name': 'btree_gist',
   'sd': meson.current_source_dir(),
diff --git a/contrib/citext/meson.build b/contrib/citext/meson.build
index 1cc49fc999f..fc29fc843f5 100644
--- a/contrib/citext/meson.build
+++ b/contrib/citext/meson.build
@@ -30,6 +30,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': citext,
+  'srcfiles': citext_sources,
+}
+
 tests += {
   'name': 'citext',
   'sd': meson.current_source_dir(),
diff --git a/contrib/cube/meson.build b/contrib/cube/meson.build
index 6526091c688..694f6335c3c 100644
--- a/contrib/cube/meson.build
+++ b/contrib/cube/meson.build
@@ -3,6 +3,7 @@
 cube_sources = files(
   'cube.c',
 )
+bc_cube_sources = cube_sources
 
 cube_scan = custom_target('cubescan',
   input: 'cubescan.l',
@@ -11,6 +12,7 @@ cube_scan = custom_target('cubescan',
 )
 generated_sources += cube_scan
 cube_sources += cube_scan
+bc_cube_gen_sources = [{'srcfiles': [cube_scan]}]
 
 cube_parse = custom_target('cubeparse',
   input: 'cubeparse.y',
@@ -18,6 +20,7 @@ cube_parse = custom_target('cubeparse',
 )
 generated_sources += cube_parse.to_list()
 cube_sources += cube_parse
+bc_cube_gen_sources += {'srcfiles': [cube_parse[0]]}
 
 if host_system == 'windows'
   cube_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
@@ -48,6 +51,16 @@ install_headers(
   install_dir: dir_include_extension / 'cube',
 )
 
+cube_dir = meson.current_source_dir()
+bitcode_modules += {
+  'target': cube,
+  'srcfiles': bc_cube_sources,
+  'gen_sources': bc_cube_gen_sources,
+  'additional_flags': [
+    '-I@0@'.format(cube_dir),
+  ]
+}
+
 tests += {
   'name': 'cube',
   'sd': meson.current_source_dir(),
diff --git a/contrib/dict_int/meson.build b/contrib/dict_int/meson.build
index 938647f45fd..98203012edc 100644
--- a/contrib/dict_int/meson.build
+++ b/contrib/dict_int/meson.build
@@ -22,6 +22,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': dict_int,
+  'srcfiles': dict_int_sources,
+}
+
 tests += {
   'name': 'dict_int',
   'sd': meson.current_source_dir(),
diff --git a/contrib/dict_xsyn/meson.build b/contrib/dict_xsyn/meson.build
index 1485e9e9797..c908920152b 100644
--- a/contrib/dict_xsyn/meson.build
+++ b/contrib/dict_xsyn/meson.build
@@ -29,6 +29,11 @@ install_data(
   }
 )
 
+bitcode_modules += {
+  'target': dict_xsyn,
+  'srcfiles': dict_xsyn_sources,
+}
+
 tests += {
   'name': 'dict_xsyn',
   'sd': meson.current_source_dir(),
diff --git a/contrib/earthdistance/meson.build b/contrib/earthdistance/meson.build
index 41fb5065afa..de47c4a4f42 100644
--- a/contrib/earthdistance/meson.build
+++ b/contrib/earthdistance/meson.build
@@ -24,6 +24,12 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': earthdistance,
+  'srcfiles': earthdistance_sources,
+}
+
+
 tests += {
   'name': 'earthdistance',
   'sd': meson.current_source_dir(),
diff --git a/contrib/fuzzystrmatch/meson.build b/contrib/fuzzystrmatch/meson.build
index e21a4e2e62b..554ba4ebd76 100644
--- a/contrib/fuzzystrmatch/meson.build
+++ b/contrib/fuzzystrmatch/meson.build
@@ -5,6 +5,7 @@ fuzzystrmatch_sources = files(
   'dmetaphone.c',
   'fuzzystrmatch.c',
 )
+bc_fuzzystrmatch_sources = fuzzystrmatch_sources
 
 daitch_mokotoff_h = custom_target('daitch_mokotoff',
   input: 'daitch_mokotoff_header.pl',
@@ -35,6 +36,14 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': fuzzystrmatch,
+  'srcfiles': bc_fuzzystrmatch_sources,
+  'additional_flags': [
+    '-I@0@'.format(meson.current_build_dir())
+  ]
+}
+
 tests += {
   'name': 'fuzzystrmatch',
   'sd': meson.current_source_dir(),
diff --git a/contrib/hstore/meson.build b/contrib/hstore/meson.build
index 6175abc708e..cf21195f3b8 100644
--- a/contrib/hstore/meson.build
+++ b/contrib/hstore/meson.build
@@ -43,6 +43,13 @@ install_headers(
   install_dir: dir_include_extension / 'hstore',
 )
 
+# Files outside of the current directory include hstore as "hstore/hstore.h"
+hstore_dir_up = join_paths(meson.current_source_dir(), '..')
+bitcode_modules += {
+  'target': hstore,
+  'srcfiles': hstore_sources,
+}
+
 tests += {
   'name': 'hstore',
   'sd': meson.current_source_dir(),
diff --git a/contrib/hstore_plperl/meson.build b/contrib/hstore_plperl/meson.build
index 705dbe69a46..1c9d2f57f2a 100644
--- a/contrib/hstore_plperl/meson.build
+++ b/contrib/hstore_plperl/meson.build
@@ -37,6 +37,16 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': hstore_plperl,
+  'srcfiles': hstore_plperl_sources,
+  'additional_flags': [
+    '-I@0@'.format(hstore_dir_up),
+    '-I@0@'.format(plperl_dir),
+    perl_ccflags,
+  ]
+}
+
 tests += {
   'name': 'hstore_plperl',
   'sd': meson.current_source_dir(),
diff --git a/contrib/hstore_plpython/meson.build b/contrib/hstore_plpython/meson.build
index 555811b25b9..0878f2507ad 100644
--- a/contrib/hstore_plpython/meson.build
+++ b/contrib/hstore_plpython/meson.build
@@ -30,6 +30,17 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': hstore_plpython,
+  'srcfiles': hstore_plpython_sources,
+  'additional_flags': [
+    '-I@0@'.format(hstore_dir_up),
+    '-DPLPYTHON_LIBNAME="plpython3"',
+    '-I@0@'.format(python3_incdir),
+    '-I@0@'.format(plpython_dir),
+  ]
+}
+
 hstore_plpython_regress = [
   'hstore_plpython'
 ]
diff --git a/contrib/intarray/meson.build b/contrib/intarray/meson.build
index e49ff77f167..24ba3110371 100644
--- a/contrib/intarray/meson.build
+++ b/contrib/intarray/meson.build
@@ -33,6 +33,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': intarray,
+  'srcfiles': intarray_sources,
+}
+
 tests += {
   'name': 'intarray',
   'sd': meson.current_source_dir(),
diff --git a/contrib/isn/meson.build b/contrib/isn/meson.build
index cecd70043c8..ddfe24eaaab 100644
--- a/contrib/isn/meson.build
+++ b/contrib/isn/meson.build
@@ -30,6 +30,11 @@ install_headers(
   install_dir: dir_include_extension / 'isn',
 )
 
+bitcode_modules += {
+  'target': isn,
+  'srcfiles': isn_sources,
+}
+
 tests += {
   'name': 'isn',
   'sd': meson.current_source_dir(),
diff --git a/contrib/jsonb_plperl/meson.build b/contrib/jsonb_plperl/meson.build
index 8bfabee5455..8ce0b6bd0bb 100644
--- a/contrib/jsonb_plperl/meson.build
+++ b/contrib/jsonb_plperl/meson.build
@@ -37,6 +37,14 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': jsonb_plperl,
+  'srcfiles': jsonb_plperl_sources,
+  'additional_flags': [
+    '-I@0@'.format(plperl_dir),
+    perl_ccflags,
+  ]
+}
 
 tests += {
   'name': 'jsonb_plperl',
diff --git a/contrib/jsonb_plpython/meson.build b/contrib/jsonb_plpython/meson.build
index 71299707418..e3588527012 100644
--- a/contrib/jsonb_plpython/meson.build
+++ b/contrib/jsonb_plpython/meson.build
@@ -30,6 +30,16 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': jsonb_plpython,
+  'srcfiles': jsonb_plpython_sources,
+  'additional_flags': [
+    '-DPLPYTHON_LIBNAME="plpython3"',
+    '-I@0@'.format(python3_incdir),
+    '-I@0@'.format(plpython_dir),
+  ]
+}
+
 jsonb_plpython_regress = [
   'jsonb_plpython'
 ]
diff --git a/contrib/lo/meson.build b/contrib/lo/meson.build
index e43eb9b2d28..1e6fbed6695 100644
--- a/contrib/lo/meson.build
+++ b/contrib/lo/meson.build
@@ -24,6 +24,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': lo,
+  'srcfiles': lo_sources,
+}
+
 tests += {
   'name': 'lo',
   'sd': meson.current_source_dir(),
diff --git a/contrib/ltree/meson.build b/contrib/ltree/meson.build
index f78521bfe55..539e1ed32a3 100644
--- a/contrib/ltree/meson.build
+++ b/contrib/ltree/meson.build
@@ -41,6 +41,16 @@ install_headers(
   install_dir: dir_include_extension / 'ltree',
 )
 
+ltree_dir = meson.current_source_dir()
+ltree_dir_up = join_paths(ltree_dir, '..')
+bitcode_modules += {
+  'target': ltree,
+  'srcfiles': ltree_sources,
+  'additional_flags': [
+    '-I@0@'.format(ltree_dir)
+  ]
+}
+
 tests += {
   'name': 'ltree',
   'sd': meson.current_source_dir(),
diff --git a/contrib/ltree_plpython/meson.build b/contrib/ltree_plpython/meson.build
index b72ee5a780a..e5a96286305 100644
--- a/contrib/ltree_plpython/meson.build
+++ b/contrib/ltree_plpython/meson.build
@@ -30,6 +30,17 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': ltree_plpython,
+  'srcfiles': ltree_plpython_sources,
+  'additional_flags': [
+    '-I@0@'.format(ltree_dir_up),
+    '-DPLPYTHON_LIBNAME="plpython3"',
+    '-I@0@'.format(python3_incdir),
+    '-I@0@'.format(plpython_dir),
+  ]
+}
+
 ltree_plpython_regress = [
   'ltree_plpython'
 ]
diff --git a/contrib/pg_buffercache/meson.build b/contrib/pg_buffercache/meson.build
index e681205abb2..3435221e90d 100644
--- a/contrib/pg_buffercache/meson.build
+++ b/contrib/pg_buffercache/meson.build
@@ -29,6 +29,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': pg_buffercache,
+  'srcfiles': pg_buffercache_sources,
+}
+
 tests += {
   'name': 'pg_buffercache',
   'sd': meson.current_source_dir(),
diff --git a/contrib/pg_freespacemap/meson.build b/contrib/pg_freespacemap/meson.build
index 67b46c77ff3..673bd6ff2a4 100644
--- a/contrib/pg_freespacemap/meson.build
+++ b/contrib/pg_freespacemap/meson.build
@@ -25,6 +25,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': pg_freespacemap,
+  'srcfiles': pg_freespacemap_sources,
+}
+
 tests += {
   'name': 'pg_freespacemap',
   'sd': meson.current_source_dir(),
diff --git a/contrib/pg_logicalinspect/meson.build b/contrib/pg_logicalinspect/meson.build
index 3e284986e3b..7ce9b2cafc2 100644
--- a/contrib/pg_logicalinspect/meson.build
+++ b/contrib/pg_logicalinspect/meson.build
@@ -22,6 +22,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': pg_logicalinspect,
+  'srcfiles': pg_logicalinspect_sources,
+}
+
 tests += {
   'name': 'pg_logicalinspect',
   'sd': meson.current_source_dir(),
diff --git a/contrib/pg_surgery/meson.build b/contrib/pg_surgery/meson.build
index 88e16dcc1b2..cabba37ed66 100644
--- a/contrib/pg_surgery/meson.build
+++ b/contrib/pg_surgery/meson.build
@@ -22,6 +22,10 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': pg_surgery,
+  'srcfiles': pg_surgery_sources,
+}
 
 tests += {
   'name': 'pg_surgery',
diff --git a/contrib/pg_trgm/meson.build b/contrib/pg_trgm/meson.build
index 3ecf95ba862..31b79db7c57 100644
--- a/contrib/pg_trgm/meson.build
+++ b/contrib/pg_trgm/meson.build
@@ -32,6 +32,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': pg_trgm,
+  'srcfiles': pg_trgm_sources,
+}
+
 tests += {
   'name': 'pg_trgm',
   'sd': meson.current_source_dir(),
diff --git a/contrib/pgcrypto/meson.build b/contrib/pgcrypto/meson.build
index 4f255c8cb05..3fe3fa2bfdf 100644
--- a/contrib/pgcrypto/meson.build
+++ b/contrib/pgcrypto/meson.build
@@ -101,6 +101,10 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': pgcrypto,
+  'srcfiles': pgcrypto_sources,
+}
 
 tests += {
   'name': 'pgcrypto',
diff --git a/contrib/seg/meson.build b/contrib/seg/meson.build
index fa3de266bb5..f8f5f1db8ec 100644
--- a/contrib/seg/meson.build
+++ b/contrib/seg/meson.build
@@ -3,6 +3,7 @@
 seg_sources = files(
   'seg.c',
 )
+bc_seg_sources = seg_sources
 
 seg_scan = custom_target('segscan',
   input: 'segscan.l',
@@ -11,6 +12,7 @@ seg_scan = custom_target('segscan',
 )
 generated_sources += seg_scan
 seg_sources += seg_scan
+bc_seg_gen_sources = [{'srcfiles': [seg_scan]}]
 
 seg_parse = custom_target('segparse',
   input: 'segparse.y',
@@ -18,6 +20,7 @@ seg_parse = custom_target('segparse',
 )
 generated_sources += seg_parse.to_list()
 seg_sources += seg_parse
+bc_seg_gen_sources += {'srcfiles': [seg_parse[0]]}
 
 if host_system == 'windows'
   seg_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
@@ -47,6 +50,15 @@ install_headers(
   install_dir: dir_include_extension / 'seg',
 )
 
+bitcode_modules += {
+  'target': seg,
+  'srcfiles': bc_seg_sources,
+  'gen_sources': bc_seg_gen_sources,
+  'additional_flags': [
+    '-I@0@'.format(meson.current_source_dir()),
+  ]
+}
+
 tests += {
   'name': 'seg',
   'sd': meson.current_source_dir(),
diff --git a/contrib/spi/meson.build b/contrib/spi/meson.build
index 4a9a2bef0a5..e695ec6c487 100644
--- a/contrib/spi/meson.build
+++ b/contrib/spi/meson.build
@@ -24,6 +24,11 @@ install_data('autoinc.example',
   kwargs: contrib_doc_args,
 )
 
+bitcode_modules += {
+  'target': autoinc,
+  'srcfiles': autoinc_sources,
+}
+
 
 insert_username_sources = files(
   'insert_username.c',
@@ -51,6 +56,11 @@ install_data('insert_username.example',
   kwargs: contrib_doc_args,
 )
 
+bitcode_modules += {
+  'target': insert_username,
+  'srcfiles': insert_username_sources,
+}
+
 
 moddatetime_sources = files(
   'moddatetime.c',
@@ -78,6 +88,11 @@ install_data('moddatetime.example',
   kwargs: contrib_doc_args,
 )
 
+bitcode_modules += {
+  'target': moddatetime,
+  'srcfiles': moddatetime_sources,
+}
+
 
 # this is needed for the regression tests;
 # comment out if you want a quieter refint package for other uses
@@ -108,6 +123,11 @@ install_data('refint.example',
   kwargs: contrib_doc_args,
 )
 
+bitcode_modules += {
+  'target': refint,
+  'srcfiles': refint_sources,
+}
+
 tests += {
   'name': 'spi',
   'sd': meson.current_source_dir(),
diff --git a/contrib/sslinfo/meson.build b/contrib/sslinfo/meson.build
index 6e9cb96430a..a5445c13a2b 100644
--- a/contrib/sslinfo/meson.build
+++ b/contrib/sslinfo/meson.build
@@ -29,3 +29,8 @@ install_data(
   'sslinfo.control',
   kwargs: contrib_data_args,
 )
+
+bitcode_modules += {
+  'target': sslinfo,
+  'srcfiles': sslinfo_sources,
+}
diff --git a/contrib/tablefunc/meson.build b/contrib/tablefunc/meson.build
index 1bebb926229..c1e5335e0ae 100644
--- a/contrib/tablefunc/meson.build
+++ b/contrib/tablefunc/meson.build
@@ -22,6 +22,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': tablefunc,
+  'srcfiles': tablefunc_sources,
+}
+
 tests += {
   'name': 'tablefunc',
   'sd': meson.current_source_dir(),
diff --git a/contrib/tcn/meson.build b/contrib/tcn/meson.build
index f7a9b9a505f..049ffc3f135 100644
--- a/contrib/tcn/meson.build
+++ b/contrib/tcn/meson.build
@@ -22,6 +22,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': tcn,
+  'srcfiles': tcn_sources,
+}
+
 tests += {
   'name': 'tcn',
   'sd': meson.current_source_dir(),
diff --git a/contrib/tsm_system_rows/meson.build b/contrib/tsm_system_rows/meson.build
index 19f6f5f6bf5..5bac8299ec7 100644
--- a/contrib/tsm_system_rows/meson.build
+++ b/contrib/tsm_system_rows/meson.build
@@ -22,6 +22,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': tsm_system_rows,
+  'srcfiles': tsm_system_rows_sources,
+}
+
 tests += {
   'name': 'tsm_system_rows',
   'sd': meson.current_source_dir(),
diff --git a/contrib/tsm_system_time/meson.build b/contrib/tsm_system_time/meson.build
index c5404b266ab..02ae53bbb9f 100644
--- a/contrib/tsm_system_time/meson.build
+++ b/contrib/tsm_system_time/meson.build
@@ -22,6 +22,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': tsm_system_time,
+  'srcfiles': tsm_system_time_sources,
+}
+
 tests += {
   'name': 'tsm_system_time',
   'sd': meson.current_source_dir(),
diff --git a/contrib/unaccent/meson.build b/contrib/unaccent/meson.build
index 938d9522da3..20a04c1f4c0 100644
--- a/contrib/unaccent/meson.build
+++ b/contrib/unaccent/meson.build
@@ -28,6 +28,11 @@ install_data(
   install_dir: dir_data / 'tsearch_data'
 )
 
+bitcode_modules += {
+  'target': unaccent,
+  'srcfiles': unaccent_sources,
+}
+
 tests += {
   'name': 'unaccent',
   'sd': meson.current_source_dir(),
diff --git a/contrib/uuid-ossp/meson.build b/contrib/uuid-ossp/meson.build
index b074900dd16..1d806bdb164 100644
--- a/contrib/uuid-ossp/meson.build
+++ b/contrib/uuid-ossp/meson.build
@@ -29,6 +29,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': uuid_ossp,
+  'srcfiles': uuid_ossp_sources,
+}
+
 tests += {
   'name': 'uuid-ossp',
   'sd': meson.current_source_dir(),
diff --git a/contrib/xml2/meson.build b/contrib/xml2/meson.build
index faae5e5e428..6e81ea6ad72 100644
--- a/contrib/xml2/meson.build
+++ b/contrib/xml2/meson.build
@@ -32,6 +32,11 @@ install_data(
   kwargs: contrib_data_args,
 )
 
+bitcode_modules += {
+  'target': xml2,
+  'srcfiles': xml2_sources,
+}
+
 tests += {
   'name': 'xml2',
   'sd': meson.current_source_dir(),
diff --git a/meson.build b/meson.build
index 021e6096e40..15b73d57d93 100644
--- a/meson.build
+++ b/meson.build
@@ -1448,6 +1448,7 @@ if not pyopt.disabled()
       python3_header_check_args = ['/I' + python3_incdir]
     else
       python3_dep = python3_inst.dependency(embed: true, required: pyopt)
+      python3_incdir = python3_inst.get_variable('INCLUDEPY')
       python3_header_check_args = []
     endif
     # Remove this check after we depend on Meson >= 1.1.0
diff --git a/src/interfaces/libpq/meson.build b/src/interfaces/libpq/meson.build
index b0ae72167a1..f0644294e6b 100644
--- a/src/interfaces/libpq/meson.build
+++ b/src/interfaces/libpq/meson.build
@@ -49,6 +49,9 @@ libpq_c_args = ['-DSO_MAJOR_VERSION=5']
 # The OAuth implementation differs depending on the type of library being built.
 libpq_so_c_args = ['-DUSE_DYNAMIC_OAUTH']
 
+# libpq-fe.h is needed to generate bitcode for some extensions
+libpq_dir = meson.current_source_dir()
+
 # Not using both_libraries() here as
 # 1) resource files should only be in the shared library
 # 2) we want the .pc file to include a dependency to {pgport,common}_static for
diff --git a/src/pl/plperl/meson.build b/src/pl/plperl/meson.build
index ff41812ca46..51f804804ba 100644
--- a/src/pl/plperl/meson.build
+++ b/src/pl/plperl/meson.build
@@ -37,6 +37,7 @@ foreach n : ['SPI', 'Util']
   plperl_sources += xs_c
 endforeach
 
+plperl_dir = meson.current_source_dir()
 plperl_inc = include_directories('.')
 
 if host_system == 'windows'
diff --git a/src/pl/plpython/meson.build b/src/pl/plpython/meson.build
index ef8aba56539..0e8ea5beda0 100644
--- a/src/pl/plpython/meson.build
+++ b/src/pl/plpython/meson.build
@@ -29,6 +29,7 @@ plpython_sources += custom_target('spiexceptions.h',
 
 # FIXME: need to duplicate import library ugliness?
 plpython_inc = include_directories('.')
+plpython_dir = meson.current_source_dir()
 
 if host_system == 'windows'
   plpython_sources += rc_lib_gen.process(win32ver_rc, extra_args: [
-- 
2.47.3

From bb7fe17a98b0fbe8980e2b67787b4918ad81b560 Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <[email protected]>
Date: Wed, 12 Mar 2025 10:44:46 +0300
Subject: [PATCH v11 6/7] meson: Add LLVM bitcode emission for backend sources

Since generated backend sources may have their own compilation flags and
must also be included in the postgres.index.bc, the way to make it work
with current code was to create a new variable, called
`bc_generated_backend_sources`, which is a list of dictionaries, each
one having an optional 'additional_flags' and a `srclist` pointing to
the list of custom_target generated sources.

An example of a possible structure of bitcode_modules which is processed
by the main meson llvm bitcode emission file
src/backend/jit/llvm/bitcode/meson.build:
```
bitcode_modules = [
  {
    'name': 'postgres',
    'target': postgres_lib,
    'src_file': backend_sources,
    'gen_srcfiles': [
      {
        'additional_flags': [
          '-I/path/postgresl/src/backend/parser',
          '-I/path/postgresl/build/src/backend/parser',
        ],
        'srcfiles': [
                <custom_target for scan.c>,
                <custom_target for gram.c>
        ]
      }
    ]
  }
]
```

Author: Diego Fronza <[email protected]>
Author: Nazir Bilal Yavuz <[email protected]>
Reviewed-by: Peter Eisentraut <[email protected]>
Discussion: https://postgr.es/m/206b001d-1884-4081-bd02-bed5c92f02ba%40eisentraut.org
---
 src/backend/bootstrap/meson.build   | 2 ++
 src/backend/meson.build             | 2 ++
 src/backend/parser/meson.build      | 8 ++++++++
 src/backend/replication/meson.build | 4 ++++
 src/backend/utils/fmgr/meson.build  | 1 +
 5 files changed, 17 insertions(+)

diff --git a/src/backend/bootstrap/meson.build b/src/backend/bootstrap/meson.build
index 2f9115fc97c..f49e27f3889 100644
--- a/src/backend/bootstrap/meson.build
+++ b/src/backend/bootstrap/meson.build
@@ -13,6 +13,7 @@ bootscanner = custom_target('bootscanner',
 )
 generated_sources += bootscanner
 boot_parser_sources += bootscanner
+bc_generated_backend_sources += {'srcfiles': [bootscanner]}
 
 bootparse = custom_target('bootparse',
   input: 'bootparse.y',
@@ -20,6 +21,7 @@ bootparse = custom_target('bootparse',
 )
 generated_sources += bootparse.to_list()
 boot_parser_sources += bootparse
+bc_generated_backend_sources += {'srcfiles': [bootparse[0]]}
 
 boot_parser = static_library('boot_parser',
   boot_parser_sources,
diff --git a/src/backend/meson.build b/src/backend/meson.build
index 2877127954b..102006ccd35 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -5,6 +5,7 @@ backend_sources = []
 backend_link_with = [pgport_srv, common_srv]
 
 generated_backend_sources = []
+bc_generated_backend_sources = []
 post_export_backend_sources = []
 
 var_bitcode_cflags = []
@@ -172,6 +173,7 @@ bitcode_modules += {
   'name': 'postgres',
   'target': postgres_lib,
   'srcfiles': backend_sources,
+  'gen_sources': bc_generated_backend_sources,
 }
 
 pg_mod_c_args = cflags_mod
diff --git a/src/backend/parser/meson.build b/src/backend/parser/meson.build
index 86c09b29ec2..a8d65eb1898 100644
--- a/src/backend/parser/meson.build
+++ b/src/backend/parser/meson.build
@@ -43,6 +43,14 @@ backend_parser = custom_target('gram',
 generated_sources += backend_parser.to_list()
 parser_sources += backend_parser
 
+bc_generated_backend_sources += {
+  'additional_flags': [
+    '-I@0@'.format(meson.current_build_dir()),
+    '-I@0@'.format(meson.current_source_dir()),
+  ],
+  'srcfiles': [backend_scanner, backend_parser[0]],
+}
+
 parser = static_library('parser',
   parser_sources,
   dependencies: [backend_code],
diff --git a/src/backend/replication/meson.build b/src/backend/replication/meson.build
index ce9be4117ad..a4789f1f86f 100644
--- a/src/backend/replication/meson.build
+++ b/src/backend/replication/meson.build
@@ -19,6 +19,7 @@ repl_scanner = custom_target('repl_scanner',
 )
 generated_sources += repl_scanner
 repl_parser_sources += repl_scanner
+bc_generated_backend_sources += {'srcfiles': [repl_scanner]}
 
 repl_gram = custom_target('repl_gram',
   input: 'repl_gram.y',
@@ -26,6 +27,7 @@ repl_gram = custom_target('repl_gram',
 )
 generated_sources += repl_gram.to_list()
 repl_parser_sources += repl_gram
+bc_generated_backend_sources += {'srcfiles': [repl_gram[0]]}
 
 syncrep_scanner = custom_target('syncrep_scanner',
   input: 'syncrep_scanner.l',
@@ -34,6 +36,7 @@ syncrep_scanner = custom_target('syncrep_scanner',
 )
 generated_sources += syncrep_scanner
 repl_parser_sources += syncrep_scanner
+bc_generated_backend_sources += {'srcfiles': [syncrep_scanner]}
 
 syncrep_gram = custom_target('syncrep_gram',
   input: 'syncrep_gram.y',
@@ -41,6 +44,7 @@ syncrep_gram = custom_target('syncrep_gram',
 )
 generated_sources += syncrep_gram.to_list()
 repl_parser_sources += syncrep_gram
+bc_generated_backend_sources += {'srcfiles': [syncrep_gram[0]]}
 
 repl_parser = static_library('repl_parser',
   repl_parser_sources,
diff --git a/src/backend/utils/fmgr/meson.build b/src/backend/utils/fmgr/meson.build
index 3a90deba979..71dad370d1d 100644
--- a/src/backend/utils/fmgr/meson.build
+++ b/src/backend/utils/fmgr/meson.build
@@ -8,3 +8,4 @@ backend_sources += files(
 
 # fmgrtab.c
 generated_backend_sources += fmgrtab_target[2]
+bc_generated_backend_sources += {'srcfiles': [fmgrtab_target[2]]}
-- 
2.47.3

From 7c8fba38bb884a91cf7bf45f3a3715db7a30279e Mon Sep 17 00:00:00 2001
From: Nazir Bilal Yavuz <[email protected]>
Date: Mon, 23 Mar 2026 16:03:25 +0300
Subject: [PATCH v11 7/7] [WIP] Generate postgresql-extension.pc in autoconf
 builds

---
 src/backend/Makefile | 59 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/backend/Makefile b/src/backend/Makefile
index 162d3f1f2a9..fe9e8f249b4 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -81,7 +81,59 @@ override LDFLAGS := $(LDFLAGS) $(LDFLAGS_EX) $(LDFLAGS_EX_BE)
 
 ##########################################################################
 
+##########
+# Generate pkg-config files for building server extensions.  These provide
+# an alternative to PGXS for extension authors who prefer pkg-config.
+
+pkgconfigdir = $(libdir)/pkgconfig
+
+PG_EXT_CFLAGS = -I$${includedir} -I$${includedir}/server $(CFLAGS_SL_MODULE) $(CPPFLAGS)
+PG_EXT_LIBS =  $(LIBS) $(LDFLAGS) $(PTHREAD_LIBS)
+
 all: submake-libpgport submake-catalog-headers submake-utils-headers postgres $(POSTGRES_IMP)
+all: postgresql-extension.pc postgresql-extension-warnings.pc
+
+postgresql-extension.pc: $(MAKEFILE_LIST)
+	echo 'prefix=$(prefix)' >$@
+	echo 'includedir=$(patsubst $(prefix)/%,$${prefix}/%,$(includedir))' >>$@
+	echo 'libdir=$(patsubst $(prefix)/%,$${prefix}/%,$(libdir))' >>$@
+	echo >>$@
+	echo 'pkglibdir=$(patsubst $(prefix)/%,$${prefix}/%,$(pkglibdir))' >>$@
+	echo 'dir_mod=$${pkglibdir}' >>$@
+	echo 'dir_data=$(patsubst $(prefix)/%,$${prefix}/%,$(datadir))/extension' >>$@
+	echo 'dir_include=$(patsubst $(prefix)/%,$${prefix}/%,$(includedir_server))/extension' >>$@
+	echo 'dir_doc=$(patsubst $(prefix)/%,$${prefix}/%,$(docdir))/extension' >>$@
+	echo 'dir_bitcode=$(patsubst $(prefix)/%,$${prefix}/%,$(bitcodedir))' >>$@
+	echo 'bindir=$(patsubst $(prefix)/%,$${prefix}/%,$(bindir))' >>$@
+	echo >>$@
+	echo 'Name: postgresql-extension' >>$@
+	echo 'Description: PostgreSQL Extension Support' >>$@
+	echo 'URL: $(PACKAGE_URL)' >>$@
+	echo 'Version: $(VERSION)' >>$@
+	echo 'Requires: ' >>$@
+	echo 'Cflags: $(PG_EXT_CFLAGS)' >>$@
+	echo 'Libs: $(PG_EXT_LIBS)' >>$@
+
+postgresql-extension-warnings.pc: $(MAKEFILE_LIST)
+	echo 'prefix=$(prefix)' >$@
+	echo 'includedir=$(patsubst $(prefix)/%,$${prefix}/%,$(includedir))' >>$@
+	echo >>$@
+	echo 'pkglibdir=$(patsubst $(prefix)/%,$${prefix}/%,$(pkglibdir))' >>$@
+	echo 'dir_mod=$${pkglibdir}' >>$@
+	echo 'dir_data=$(patsubst $(prefix)/%,$${prefix}/%,$(datadir))/extension' >>$@
+	echo 'dir_include=$(patsubst $(prefix)/%,$${prefix}/%,$(includedir_server))/extension' >>$@
+	echo 'dir_doc=$(patsubst $(prefix)/%,$${prefix}/%,$(docdir))/extension' >>$@
+	echo 'dir_bitcode=$(patsubst $(prefix)/%,$${prefix}/%,$(bitcodedir))' >>$@
+	echo 'bindir=$(patsubst $(prefix)/%,$${prefix}/%,$(bindir))' >>$@
+	echo >>$@
+	echo 'Name: postgresql-extension-warnings' >>$@
+	echo 'Description: PostgreSQL Extension Support with compiler warnings the same as core code' >>$@
+	echo 'URL: $(PACKAGE_URL)' >>$@
+	echo 'Version: $(VERSION)' >>$@
+	echo 'Requires: postgresql-extension' >>$@
+	echo 'Cflags: $(CFLAGS)' >>$@
+	echo 'Libs: ' >>$@
+##########
 
 ifneq ($(PORTNAME), cygwin)
 ifneq ($(PORTNAME), win32)
@@ -206,6 +258,8 @@ generated-parser-sources:
 ##########################################################################
 
 install: all installdirs install-bin
+	$(INSTALL_DATA) postgresql-extension.pc '$(DESTDIR)$(pkgconfigdir)/postgresql-extension.pc'
+	$(INSTALL_DATA) postgresql-extension-warnings.pc '$(DESTDIR)$(pkgconfigdir)/postgresql-extension-warnings.pc'
 ifeq ($(PORTNAME), cygwin)
 ifeq ($(MAKE_DLL), true)
 	$(INSTALL_DATA) libpostgres.a '$(DESTDIR)$(libdir)/libpostgres.a'
@@ -241,7 +295,7 @@ endif
 .PHONY: install-bin
 
 installdirs:
-	$(MKDIR_P) '$(DESTDIR)$(bindir)' '$(DESTDIR)$(datadir)'
+	$(MKDIR_P) '$(DESTDIR)$(bindir)' '$(DESTDIR)$(datadir)' '$(DESTDIR)$(pkgconfigdir)'
 ifeq ($(PORTNAME), cygwin)
 ifeq ($(MAKE_DLL), true)
 	$(MKDIR_P) '$(DESTDIR)$(libdir)'
@@ -262,6 +316,8 @@ endif
 
 uninstall:
 	rm -f '$(DESTDIR)$(bindir)/postgres$(X)'
+	rm -f '$(DESTDIR)$(pkgconfigdir)/postgresql-extension.pc'
+	rm -f '$(DESTDIR)$(pkgconfigdir)/postgresql-extension-warnings.pc'
 ifeq ($(MAKE_EXPORTS), true)
 	rm -f '$(DESTDIR)$(pkglibdir)/$(POSTGRES_IMP)'
 	rm -f '$(DESTDIR)$(pgxsdir)/$(MKLDEXPORT_DIR)/mkldexport.sh'
@@ -292,6 +348,7 @@ endif
 
 clean:
 	rm -f $(LOCALOBJS) postgres$(X) $(POSTGRES_IMP)
+	rm -f postgresql-extension.pc postgresql-extension-warnings.pc
 ifeq ($(PORTNAME), cygwin)
 	rm -f postgres.dll libpostgres.a
 endif
-- 
2.47.3

Reply via email to