diff --git a/.cirrus.yml b/.cirrus.yml
index d260f15c4e292..2dd1e95004b50 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -221,6 +221,92 @@ task:
     cores_script: src/tools/ci/cores_backtrace.sh freebsd /tmp/cores
 
 
+task:
+  depends_on: SanityCheck
+
+  env:
+    CPUS: 2
+    BUILD_JOBS: 3
+    TEST_JOBS: 3
+
+    CIRRUS_WORKING_DIR: /home/postgres/postgres
+    CCACHE_DIR: /tmp/ccache_dir
+
+    PATH: /usr/sbin:$PATH
+
+    # Postgres interprets LANG as a 'en_US.UTF-8' but it is 'C', then
+    # Postgres tries to set 'LC_COLLATE' to 'en_US.UTF-8' but it is not
+    # changeable. Initdb fails because of that. So, LANG is forced to be 'C'.
+    LANG: "C"
+    LC_ALL: "C"
+
+  matrix:
+    - name: NetBSD - 9 - Meson
+      only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*netbsd.*'
+      env:
+        IMAGE_NAME: pg-ci-netbsd-postgres-9-3
+        PLATFORM: netbsd
+        INCLUDE_DIRS: -Dextra_lib_dirs=/usr/pkg/lib -Dextra_include_dirs=/usr/pkg/include
+
+    - name: OpenBSD - 7 - Meson
+      only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*openbsd.*'
+      env:
+        IMAGE_NAME: pg-ci-openbsd-postgres-7-3
+        PLATFORM: openbsd
+        INCLUDE_DIRS: -Dextra_include_dirs=/usr/local/include -Dextra_lib_dirs=/usr/local/lib
+        UUID: -Duuid=e2fs
+
+  compute_engine_instance:
+    image_project: $IMAGE_PROJECT
+    image: family/${IMAGE_NAME}
+    platform: ${PLATFORM}
+    cpu: $CPUS
+    memory: 4G
+    disk: 25
+
+  sysinfo_script: |
+    locale
+    id
+    uname -a
+    ulimit -a -H && ulimit -a -S
+    export
+
+  ccache_cache:
+    folder: $CCACHE_DIR
+
+  create_user_script: |
+    useradd postgres
+    chown -R postgres:users /home/postgres
+    mkdir -p ${CCACHE_DIR}
+    chown -R postgres:users ${CCACHE_DIR}
+
+  # -Duuid=bsd is not set since 'bsd' uuid option
+  # is not working on netBSD & openBSD. See
+  # https://www.postgresql.org/message-id/17358-89806e7420797025@postgresql.org
+  # And other uuid options are not available on netBSD
+  configure_script: |
+    su postgres <<-EOF
+      meson setup \
+        --buildtype debug \
+        -Dcassert=true -Dssl=openssl ${UUID} \
+        -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \
+        ${INCLUDE_DIRS} \
+        build
+    EOF
+
+  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS}'
+  upload_caches: ccache
+
+  test_world_script: |
+    su postgres <<-EOF
+      ulimit -c unlimited
+      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
+    EOF
+
+  on_failure:
+    <<: *on_failure_meson
+
+
 # configure feature flags, shared between the task running the linux tests and
 # the CompilerWarnings task
 LINUX_CONFIGURE_FEATURES: &LINUX_CONFIGURE_FEATURES >-
@@ -246,6 +332,22 @@ LINUX_MESON_FEATURES: &LINUX_MESON_FEATURES >-
   -Duuid=e2fs
 
 
+# configure preparation scripts, shared between tasks running the linux tests
+linux_preparation_scripts_template: &linux_preparation_scripts_template
+  sysinfo_script: |
+    id
+    uname -a
+    cat /proc/cmdline
+    ulimit -a -H && ulimit -a -S
+    export
+  create_user_script: |
+    useradd -m -U postgres
+    chown -R postgres:postgres .
+    mkdir -p ${CCACHE_DIR}
+    chown -R postgres:postgres ${CCACHE_DIR}
+    su postgres -c "ulimit -l -H && ulimit -l -S"
+
+
 task:
   env:
     CPUS: 4
@@ -296,19 +398,9 @@ task:
   ccache_cache:
     folder: ${CCACHE_DIR}
 
-  sysinfo_script: |
-    id
-    uname -a
-    cat /proc/cmdline
-    ulimit -a -H && ulimit -a -S
-    export
-  create_user_script: |
-    useradd -m postgres
-    chown -R postgres:postgres .
-    mkdir -p ${CCACHE_DIR}
-    chown -R postgres:postgres ${CCACHE_DIR}
+  set_limits_script: |
     echo '* - memlock 134217728' > /etc/security/limits.d/postgres.conf
-    su postgres -c "ulimit -l -H && ulimit -l -S"
+  <<: *linux_preparation_scripts_template
   setup_core_files_script: |
     mkdir -m 770 /tmp/cores
     chown root:postgres /tmp/cores
@@ -354,7 +446,13 @@ task:
       on_failure:
         <<: *on_failure_ac
 
-    - name: Linux - Debian Bullseye - Meson
+    - matrix:
+        - name: Linux - Debian Bullseye - Meson
+        - name: Linux - Debian Sid - Meson
+          trigger_type: manual
+
+          compute_engine_instance:
+            image: family/pg-ci-sid
 
       env:
         CCACHE_MAXSIZE: "400M" # tests two different builds
@@ -381,7 +479,7 @@ task:
             ${LINUX_MESON_FEATURES} \
             -Dllvm=disabled \
             --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \
-            -DPERL=perl5.32-i386-linux-gnu \
+            -DPERL=$(echo /usr/bin/perl*i386-linux-gnu) \
             -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \
             build-32
         EOF
@@ -416,6 +514,82 @@ task:
     cores_script: src/tools/ci/cores_backtrace.sh linux /tmp/cores
 
 
+task:
+  env:
+    CPUS: 4
+    BUILD_JOBS: 4
+    TEST_JOBS: 8 # experimentally derived to be a decent choice
+
+    CCACHE_DIR: /tmp/ccache_dir
+    DEBUGINFOD_URLS: ${DEBUGINFO}
+
+    TCL_DIR: /usr/lib64/
+    UUID: e2fs
+
+    CFLAGS: "-Og -ggdb"
+    CXXFLAGS: "-Og -ggdb"
+
+    LINUX_CONFIGURE_FEATURES: *LINUX_CONFIGURE_FEATURES
+
+  depends_on: SanityCheck
+  only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*linux.*'
+
+  container:
+    dockerfile: ${DOCKERFILE_PATH}
+    cpu: $CPUS
+    memory: 4G
+
+  ccache_cache:
+    folder: ${CCACHE_DIR}
+
+  <<: *linux_preparation_scripts_template
+
+  matrix:
+    - name: Linux - OpenSuse Tumbleweed (LLVM) - Meson
+      env:
+        DOCKERFILE_PATH: src/tools/ci/docker/linux_opensuse_tumbleweed
+        DEBUGINFO: "https://debuginfod.opensuse.org/"
+        LLVM: -Dllvm=enabled
+
+    - trigger_type: manual
+      matrix:
+        - name: Linux - Fedora Rawhide - Meson
+          env:
+            DOCKERFILE_PATH: src/tools/ci/docker/linux_fedora_rawhide
+            DEBUGINFO: "https://debuginfod.fedoraproject.org/"
+
+        - name: Linux - Centos 8 - Meson
+          env:
+            DOCKERFILE_PATH: src/tools/ci/docker/linux_centos8
+            DEBUGINFO: "http://debuginfo.centos.org/"
+
+        - name: Linux - Centos 7 - Meson
+          env:
+            DOCKERFILE_PATH: src/tools/ci/docker/linux_centos7
+            DEBUGINFO: "http://debuginfo.centos.org/"
+
+  configure_script: |
+    su postgres <<-EOF
+      meson setup \
+        --buildtype debug \
+        -Dcassert=true -Dssl=openssl -Duuid=e2fs ${LLVM} \
+        -DPG_TEST_EXTRA="$PG_TEST_EXTRA" \
+        build
+    EOF
+
+  build_script: su postgres -c 'ninja -C build -j${BUILD_JOBS}'
+  upload_caches: ccache
+
+  test_world_script: |
+    su postgres <<-EOF
+      ulimit -c unlimited
+      meson test $MTEST_ARGS --num-processes ${TEST_JOBS}
+    EOF
+
+  on_failure:
+    <<: *on_failure_meson
+
+
 task:
   name: macOS - Ventura - Meson
 
@@ -535,6 +709,27 @@ WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
     # Avoids port conflicts between concurrent tap test runs
     PG_TEST_USE_UNIX_SOCKETS: 1
     PG_REGRESS_SOCK_DIR: "c:/cirrus/"
+    # -m enables parallelism
+    # verbosity:minimal + Summary reduce verbosity, while keeping a summary of
+    #   errors/warnings
+    # ForceNoAlign prevents msbuild from introducing line-breaks for long lines
+    # disable file tracker, we're never going to rebuild, and it slows down the
+    #   build
+    MSBFLAGS: -m -verbosity:minimal "-consoleLoggerParameters:Summary;ForceNoAlign" /p:TrackFileAccess=false -nologo
+
+    # If tests hang forever, cirrus eventually times out. In that case log
+    # output etc is not uploaded, making the problem hard to debug. Of course
+    # tests internally should have shorter timeouts, but that's proven to not
+    # be sufficient. 15min currently is fast enough to finish individual test
+    # "suites".
+    T_C: "\"C:/Program Files/Git/usr/bin/timeout.exe\" -v -k60s 15m"
+
+  compute_engine_instance:
+    image_project: $IMAGE_PROJECT
+    image: family/pg-ci-windows-ci
+    platform: windows
+    cpu: $CPUS
+    memory: 4G
 
   sysinfo_script: |
     chcp
@@ -542,10 +737,9 @@ WINDOWS_ENVIRONMENT_BASE: &WINDOWS_ENVIRONMENT_BASE
     powershell -Command get-psdrive -psprovider filesystem
     set
 
-
 task:
   name: Windows - Server 2019, VS 2019 - Meson & ninja
-  << : *WINDOWS_ENVIRONMENT_BASE
+  <<: *WINDOWS_ENVIRONMENT_BASE
 
   env:
     TEST_JOBS: 8 # wild guess, data based value welcome
@@ -562,13 +756,6 @@ task:
   depends_on: SanityCheck
   only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*windows.*'
 
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/pg-ci-windows-ci-vs-2019
-    platform: windows
-    cpu: $CPUS
-    memory: 4G
-
   setup_additional_packages_script: |
     REM choco install -y --no-progress ...
 
@@ -578,10 +765,15 @@ task:
     echo 127.0.0.3 pg-loadbalancetest >> c:\Windows\System32\Drivers\etc\hosts
     type c:\Windows\System32\Drivers\etc\hosts
 
+  meson_install_wraps_script: |
+    mkdir subprojects
+    meson wrap install lz4
+    meson wrap install zlib
+
   # Use /DEBUG:FASTLINK to avoid high memory usage during linking
   configure_script: |
     vcvarsall x64
-    meson setup --backend ninja --buildtype debug -Dc_link_args=/DEBUG:FASTLINK -Dcassert=true -Db_pch=true -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% -DPG_TEST_EXTRA="%PG_TEST_EXTRA%" build
+    meson setup --backend ninja --buildtype debug -Dc_link_args=/DEBUG:FASTLINK -Dcassert=true -Db_pch=true -Dlz4=enabled -Dzlib=enabled -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=%TAR% -DPG_TEST_EXTRA="%PG_TEST_EXTRA%" build
 
   build_script: |
     vcvarsall x64
@@ -599,7 +791,46 @@ task:
 
 
 task:
-  << : *WINDOWS_ENVIRONMENT_BASE
+  <<: *WINDOWS_ENVIRONMENT_BASE
+  name: Windows - Server 2019, VS 2019 - Meson & msbuild
+
+  env:
+    TEST_JOBS: 8 # wild guess, data based value welcome
+    CIRRUS_WINDOWS_ERROR_MODE: 0x8001
+
+  depends_on: SanityCheck
+  only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*windows.*'
+
+  # 1.0.1 is borked with msbuild
+  meson_downgrade_script: |
+    pip install meson!=1.0.1
+
+  meson_install_wraps_script: |
+    mkdir subprojects
+    meson wrap install lz4
+    meson wrap install zlib
+
+  configure_script: |
+    vcvarsall x64
+    meson setup --buildtype debug --backend vs -Dcassert=true -Db_pch=true -Dssl=openssl -Dlz4=enabled -Dzlib=enabled -Dextra_lib_dirs=c:\openssl\1.1\lib -Dextra_include_dirs=c:\openssl\1.1\include -DTAR=c:/windows/system32/tar.exe -DPG_TEST_EXTRA="%PG_TEST_EXTRA%" build
+
+  build_script: |
+    vcvarsall x64
+    msbuild %MSBFLAGS% build\postgresql.sln
+
+  check_world_script: |
+    vcvarsall x64
+    meson test %MTEST_ARGS% --num-processes %TEST_JOBS%
+
+  on_failure:
+    <<: *on_failure_meson
+    crashlog_artifacts:
+      path: "crashlog-*.txt"
+      type: text/plain
+
+
+task:
+  <<: *WINDOWS_ENVIRONMENT_BASE
   name: Windows - Server 2019, MinGW64 - Meson
 
   # due to resource constraints we don't run this task by default for now
@@ -610,13 +841,6 @@ task:
   # otherwise it'll be sorted before other tasks
   depends_on: SanityCheck
 
-  compute_engine_instance:
-    image_project: $IMAGE_PROJECT
-    image: family/pg-ci-windows-ci-mingw64
-    platform: windows
-    cpu: $CPUS
-    memory: 4G
-
   env:
     TEST_JOBS: 4 # higher concurrency causes occasional failures
     CCACHE_DIR: C:/msys64/ccache
@@ -657,6 +881,85 @@ task:
 
   on_failure:
     <<: *on_failure_meson
+
+
+task:
+  <<: *WINDOWS_ENVIRONMENT_BASE
+  name: Windows - Server 2019, VS 2019 - Homegrown
+
+  depends_on: SanityCheck
+  only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\nci-os-only:.*' || $CIRRUS_CHANGE_MESSAGE =~ '.*\nci-os-only:[^\n]*windows.*'
+
+  env:
+    # Our windows infrastructure doesn't have test concurrency above the level
+    # of a single vcregress test target. Due to that, it's useful to run prove
+    # with multiple jobs. For the other tasks it isn't, because two sources
+    # (make and prove) of concurrency can overload machines.
+    #
+    # The concrete choice of 10 is based on a small bit of experimentation and
+    # likely can be improved upon further.
+    PROVE_FLAGS: -j10 --timer
+
+    # Avoid re-installing over and over
+    NO_TEMP_INSTALL: 1
+
+    # startcreate_script starts a postgres instance that we don't want to get
+    # killed at the end of that script (it's stopped in stop_script). Can't
+    # trivially use background_scripts because a) need pg_ctl's dropping of
+    # permissions b) need to wait for startup to have finished, and we don't
+    # currently have a tool for that...
+    CIRRUS_ESCAPING_PROCESSES: 1
+
+  configure_script:
+    # copy errors out when using forward slashes
+    - copy src\tools\ci\windows_build_config.pl src\tools\msvc\config.pl
+    - vcvarsall x64
+    - perl src/tools/msvc/mkvcbuild.pl
+  build_script:
+    - vcvarsall x64
+    - msbuild %MSBFLAGS% pgsql.sln
+  tempinstall_script:
+    # Installation on windows currently only completely works from src/tools/msvc
+    - cd src/tools/msvc && perl install.pl %CIRRUS_WORKING_DIR%/tmp_install
+
+  test_regress_parallel_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl check parallel
+  startcreate_script: |
+    rem paths to binaries need backslashes
+    tmp_install\bin\pg_ctl.exe initdb -D tmp_check/db -l tmp_check/initdb.log --options=--no-sync
+    echo include '%TEMP_CONFIG%' >> tmp_check/db/postgresql.conf
+    tmp_install\bin\pg_ctl.exe start -D tmp_check/db -l tmp_check/postmaster.log
+
+  test_pl_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl plcheck
+  test_isolation_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl isolationcheck
+  test_modules_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl modulescheck
+  test_contrib_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl contribcheck
+  stop_script: |
+    tmp_install\bin\pg_ctl.exe stop -D tmp_check/db -l tmp_check/postmaster.log
+  test_ssl_script: |
+    set with_ssl=openssl
+    %T_C% perl src/tools/msvc/vcregress.pl taptest ./src/test/ssl/
+  test_subscription_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl taptest ./src/test/subscription/
+  test_authentication_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl taptest ./src/test/authentication/
+  test_recovery_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl recoverycheck
+  test_bin_script: |
+    %T_C% perl src/tools/msvc/vcregress.pl bincheck
+  test_ecpg_script: |
+    rem tries to build additional stuff
+    vcvarsall x64
+    rem References ecpg_regression.proj in the current dir
+    cd src/tools/msvc
+    %T_C% perl vcregress.pl ecpgcheck
+
+  on_failure:
+    <<: *on_failure_ac
     crashlog_artifacts:
       path: "crashlog-*.txt"
       type: text/plain
@@ -700,6 +1003,10 @@ task:
   ccache_cache:
     folder: $CCACHE_DIR
 
+  ccache_stats_start_script:
+    ccache -s
+    ccache -z
+
   setup_additional_packages_script: |
     #apt-get update
     #DEBIAN_FRONTEND=noninteractive apt-get -y install ...
@@ -708,8 +1015,6 @@ task:
   # Test that code can be built with gcc/clang without warnings
   ###
 
-  setup_script: echo "COPT=-Werror" > src/Makefile.custom
-
   # Trace probes have a history of getting accidentally broken. Use the
   # different compilers to build with different combinations of dtrace on/off
   # and cassert on/off.
@@ -717,58 +1022,57 @@ task:
   # gcc, cassert off, dtrace on
   always:
     gcc_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
+      mkdir build-gcc && cd build-gcc
+      CC="ccache gcc" CXX="ccache g++" \
+        meson setup \
+          -Dwerror=true \
+          -Dcassert=false \
+          -Ddtrace=enabled \
+          ${LINUX_MESON_FEATURES} \
+          ..
+      time ninja -j${BUILD_JOBS}
 
   # gcc, cassert on, dtrace off
   always:
     gcc_a_warning_script: |
-      time ./configure \
-        --cache gcc.cache \
-        --enable-cassert \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
+      cd build-gcc
+      meson configure \
+        -Dcassert=true \
+        -Ddtrace=disabled
+      time ninja -j${BUILD_JOBS}
 
   # clang, cassert off, dtrace off
   always:
     clang_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
+      mkdir build-clang && cd build-clang
+      CC="ccache clang" CXX="ccache clang++" \
+        meson setup \
+          -Dwerror=true \
+          -Dcassert=false \
+          -Ddtrace=disabled \
+          ${LINUX_MESON_FEATURES} \
+          ..
+      time ninja -j${BUILD_JOBS}
 
   # clang, cassert on, dtrace on
   always:
     clang_a_warning_script: |
-      time ./configure \
-        --cache clang.cache \
-        --enable-cassert \
-        --enable-dtrace \
-        ${LINUX_CONFIGURE_FEATURES} \
-        CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
+      cd build-clang
+      meson configure \
+        -Dcassert=true \
+        -Ddtrace=enabled
+      time ninja -j${BUILD_JOBS}
 
   # cross-compile to windows
   always:
     mingw_cross_warning_script: |
-      time ./configure \
-        --host=x86_64-w64-mingw32 \
-        --enable-cassert \
-        --without-icu \
-        CC="ccache x86_64-w64-mingw32-gcc" \
-        CXX="ccache x86_64-w64-mingw32-g++"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} world-bin
+      mkdir build-w64 && cd build-w64
+      meson setup \
+        --cross-file=../src/tools/ci/linux-mingw-w64-64bit.txt \
+        -Dwerror=true \
+        -Dcassert=true \
+        ..
+      time ninja -j${BUILD_JOBS}
 
   ###
   # Verify docs can be built
@@ -776,13 +1080,8 @@ task:
   # XXX: Only do this if there have been changes in doc/ since last build
   always:
     docs_build_script: |
-      time ./configure \
-        --cache gcc.cache \
-        CC="ccache gcc" \
-        CXX="ccache g++" \
-        CLANG="ccache clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s -j${BUILD_JOBS} -C doc
+      cd build-gcc
+      time ninja docs
 
   ###
   # Verify headerscheck / cpluspluscheck succeed
@@ -795,15 +1094,12 @@ task:
   ###
   always:
     headers_headerscheck_script: |
-      time ./configure \
-        ${LINUX_CONFIGURE_FEATURES} \
-        --without-icu \
-        --quiet \
-        CC="gcc" CXX"=g++" CLANG="clang"
-      make -s -j${BUILD_JOBS} clean
-      time make -s headerscheck EXTRAFLAGS='-fmax-errors=10'
+      CC=gcc meson setup build-headerscheck -Dicu=disabled
+      ninja -C build-headerscheck headerscheck
     headers_cpluspluscheck_script: |
-      time make -s cpluspluscheck EXTRAFLAGS='-fmax-errors=10'
+      ninja -C build-headerscheck cpluspluscheck
 
   always:
+    ccache_stats_end_script:
+      ccache -s
     upload_caches: ccache
diff --git a/contrib/citext/meson.build b/contrib/citext/meson.build
index b9bc2437344ea..fe11601a7505d 100644
--- a/contrib/citext/meson.build
+++ b/contrib/citext/meson.build
@@ -40,3 +40,8 @@ tests += {
     ],
   },
 }
+
+bitcode_modules += {
+  'target': citext,
+  'srcfiles': citext_sources,
+}
diff --git a/meson.build b/meson.build
index 04ea34885226a..17b03e6eca5c1 100644
--- a/meson.build
+++ b/meson.build
@@ -167,6 +167,7 @@ portname = host_system
 
 exesuffix = '' # overridden below where necessary
 dlsuffix = '.so' # overridden below where necessary
+rpath_origin = '$ORIGIN'
 library_path_var = 'LD_LIBRARY_PATH'
 
 # Format of file to control exports from libraries, and how to pass them to
@@ -222,6 +223,7 @@ elif host_system == 'cygwin'
 elif host_system == 'darwin'
   dlsuffix = '.dylib'
   library_path_var = 'DYLD_LIBRARY_PATH'
+  rpath_origin = '@loader_path'
 
   export_file_format = 'darwin'
   export_fmt = '-exported_symbols_list=@0@'
@@ -260,8 +262,16 @@ elif host_system == 'netbsd'
   # LDFLAGS.
   ldflags += ['-Wl,-z,now', '-Wl,-z,relro']
 
+  # netbsd patched their meson in a broken way:
+  # https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=56959
+  # until there's a way out of that, disable rpath_origin
+  rpath_origin = ''
+
 elif host_system == 'openbsd'
-  # you're ok
+  # openbsd's $ORIGIN doesn't use an absolute path to the binary, but argv[0]
+  # (i.e. absolute when invoked with an absolute name, but e.g. not absolute
+  # when invoked via PATH search).
+  rpath_origin = ''
 
 elif host_system == 'sunos'
   portname = 'solaris'
@@ -273,6 +283,7 @@ elif host_system == 'windows'
   exesuffix = '.exe'
   dlsuffix = '.dll'
   library_path_var = ''
+  rpath_origin = ''
 
   export_file_format = 'win'
   export_file_suffix = 'def'
@@ -760,6 +771,8 @@ if add_languages('cpp', required: llvmopt, native: false)
 
     ccache = find_program('ccache', native: true, required: false)
     clang = find_program(llvm_binpath / 'clang', required: true)
+    llvm_lto = find_program(llvm_binpath / 'llvm-lto', required: true)
+    irlink = find_program('src/tools/irlink', native: true)
   endif
 elif llvmopt.auto()
   message('llvm requires a C++ compiler')
@@ -2576,6 +2589,10 @@ nls_targets = []
 test_deps = []
 tests = []
 
+# List of object files + source files to generated LLVM IR for inlining.
+# Each element is a hash of {'target': target, 'srcfiles': ...}.
+bitcode_modules = []
+
 
 # Default options for targets
 
@@ -2584,25 +2601,41 @@ bin_install_rpaths = []
 lib_install_rpaths = []
 mod_install_rpaths = []
 
-
-# Don't add rpaths on darwin for now - as long as only absolute references to
-# libraries are needed, absolute LC_ID_DYLIB ensures libraries can be found in
-# their final destination.
+# Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
+#
+# Not needed on darwin, even if we use relative rpaths for our own libraries,
+# as the install_name of libraries in extra_lib_dirs will point to their
+# location anyway.
 if host_system != 'darwin'
+  bin_install_rpaths += postgres_lib_d
+  lib_install_rpaths += postgres_lib_d
+  mod_install_rpaths += postgres_lib_d
+endif
+
+# If the host can form relative rpaths, use that to make the installation
+# properly relocatable
+if rpath_origin != ''
+  # PG binaries might need to link to libpq, use relative path to reference
+  bin_to_lib = run_command(python, files('src/tools/relpath.py'),
+    dir_bin, dir_lib, check: true).stdout().strip()
+  bin_install_rpaths += rpath_origin / bin_to_lib
+
+  # PG extensions might need to link to libpq, use relative path to reference
+  # (often just .)
+  mod_to_lib = run_command(python, files('src/tools/relpath.py'),
+    dir_lib_pkg, dir_lib, check: true).stdout().strip()
+  mod_install_rpaths += rpath_origin / mod_to_lib
+
+  test_use_library_path_var = false
+else
+
   # Add absolute path to libdir to rpath. This ensures installed binaries /
   # libraries find our libraries (mainly libpq).
   bin_install_rpaths += dir_prefix / dir_lib
   lib_install_rpaths += dir_prefix / dir_lib
   mod_install_rpaths += dir_prefix / dir_lib
 
-  # Add extra_lib_dirs to rpath. This ensures we find libraries we depend on.
-  #
-  # Not needed on darwin even if we use relative rpaths for our own libraries,
-  # as the install_name of libraries in extra_lib_dirs will point to their
-  # location anyway.
-  bin_install_rpaths += postgres_lib_d
-  lib_install_rpaths += postgres_lib_d
-  mod_install_rpaths += postgres_lib_d
+  test_use_library_path_var = true
 endif
 
 
@@ -2657,6 +2690,8 @@ gen_export_kwargs = {
   'install': false,
 }
 
+# command to create stamp files on all OSs
+stamp_cmd = [python, '-c', 'import sys; open(sys.argv[1], "w")', '@OUTPUT0@']
 
 
 ###
@@ -2774,14 +2809,14 @@ subdir('src/port')
 frontend_common_code = declare_dependency(
   compile_args: ['-DFRONTEND'],
   include_directories: [postgres_inc],
-  sources: generated_headers,
+  sources: generated_headers_stamp,
   dependencies: [os_deps, zlib, zstd],
 )
 
 backend_common_code = declare_dependency(
   compile_args: ['-DBUILDING_DLL'],
   include_directories: [postgres_inc],
-  sources: generated_headers,
+  sources: generated_headers_stamp,
   dependencies: [os_deps, zlib, zstd],
 )
 
@@ -2796,7 +2831,7 @@ shlib_code = declare_dependency(
 frontend_stlib_code = declare_dependency(
   include_directories: [postgres_inc],
   link_with: [common_static, pgport_static],
-  sources: generated_headers,
+  sources: generated_headers_stamp,
   dependencies: [os_deps, libintl],
 )
 
@@ -2804,7 +2839,7 @@ frontend_stlib_code = declare_dependency(
 frontend_shlib_code = declare_dependency(
   include_directories: [postgres_inc],
   link_with: [common_shlib, pgport_shlib],
-  sources: generated_headers,
+  sources: generated_headers_stamp,
   dependencies: [shlib_code, os_deps, libintl],
 )
 
@@ -2826,7 +2861,7 @@ subdir('src/fe_utils')
 frontend_code = declare_dependency(
   include_directories: [postgres_inc],
   link_with: [fe_utils, common_static, pgport_static],
-  sources: generated_headers,
+  sources: generated_headers_stamp,
   dependencies: [os_deps, libintl],
 )
 
@@ -2854,7 +2889,7 @@ backend_code = declare_dependency(
   include_directories: [postgres_inc],
   link_args: ldflags_be,
   link_with: [],
-  sources: generated_headers + generated_backend_headers,
+  sources: [generated_backend_headers_stamp],
   dependencies: os_deps + backend_both_deps + backend_deps,
 )
 
@@ -2880,6 +2915,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
@@ -2940,6 +2980,14 @@ above, or by running configure and then make maintainer-clean.
 endif
 
 
+# To make MacOS installation work without a prior make install, even with SIP
+# enabled, make rpaths relative after installation. This also makes the
+# installation relocatable.
+if host_system == 'darwin'
+  meson.add_install_script('src/tools/relativize_shared_library_references')
+endif
+
+
 
 ###############################################################
 # Install targets
@@ -3064,10 +3112,9 @@ test_env.set('REGRESS_SHLIB', regress_module.full_path())
 # Export PG_TEST_EXTRA so it can be checked in individual tap tests.
 test_env.set('PG_TEST_EXTRA', get_option('PG_TEST_EXTRA'))
 
-# Add the temporary installation to the library search path on platforms where
-# that works (everything but windows, basically). On windows everything
-# library-like gets installed into bindir, solving that issue.
-if library_path_var != ''
+# On platforms without $ORIGIN support we need to add the temporary
+# installation to the library search path.
+if test_use_library_path_var and library_path_var != ''
   test_env.prepend(library_path_var, test_install_location / get_option('libdir'))
 endif
 
@@ -3357,6 +3404,15 @@ if meson.version().version_compare('>=0.57')
     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 0000000000000..ba45da37313f6
--- /dev/null
+++ b/src/backend/jit/llvm/bitcode/meson.build
@@ -0,0 +1,40 @@
+# Copyright (c) 2022-2023, 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']
+  if 'name' not in bitcode_module
+    bitcode_name = bitcode_obj.name()
+  else
+    bitcode_name = bitcode_module['name']
+  endif
+
+  foreach srcfile : bitcode_module['srcfiles']
+    srcfilename = '@0@'.format(srcfile)
+    targetname = '@0@_@1@_@2@.bc'.format(
+      bitcode_name,
+      fs.parent(srcfilename).underscorify(), fs.name(srcfilename))
+    bitcode_targets += custom_target(
+      targetname,
+      input: [srcfile, bitcode_obj.extract_objects(srcfile)],
+      output: targetname,
+      command: [llvm_irgen_command, bitcode_cflags],
+      install: true,
+      install_dir: dir_bitcode,
+    )
+  endforeach
+
+  index_name = '@0@.index.bc'.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 a6524c06fe3ef..225da839e0019 100644
--- a/src/backend/jit/llvm/meson.build
+++ b/src/backend/jit/llvm/meson.build
@@ -41,21 +41,20 @@ 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',
 ]
-
-if ccache.found()
-  llvm_irgen_command = ccache
-  llvm_irgen_args = [clang.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
@@ -74,7 +73,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],
@@ -83,3 +82,11 @@ llvmjit_types = custom_target('llvmjit_types.bc',
   depfile: '@BASENAME@.c.bc.d',
 )
 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.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 88a35e96763f7..5920dc91892c3 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -155,6 +155,14 @@ postgres = executable('postgres',
 
 backend_targets += postgres
 
+
+bitcode_modules += {
+  'name': 'postgres',
+  'target': postgres_lib,
+  'srcfiles': backend_sources,
+}
+
+
 pg_mod_c_args = cflags_mod
 pg_mod_cpp_args = cxxflags_mod
 pg_mod_link_args = ldflags_sl + ldflags_mod
@@ -184,7 +192,7 @@ backend_mod_code = declare_dependency(
   compile_args: pg_mod_c_args,
   include_directories: postgres_inc,
   link_args: pg_mod_link_args,
-  sources: generated_headers + generated_backend_headers,
+  sources: [generated_backend_headers_stamp],
   dependencies: backend_mod_deps,
 )
 
@@ -203,6 +211,112 @@ 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 it's a bit odd
+# to expose it to a .pc file?
+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)
+# 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 != '')
+
+  pg_ext_vars_inst += 'mod_link_with=@0@'.format(link_with_inst)
+  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 - Compiler Warnings',
+  requires: 'postgresql-extension',
+  url: pg_url,
+  extra_cflags: 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.
 
diff --git a/src/fe_utils/meson.build b/src/fe_utils/meson.build
index ea96e862adb23..406e31b5b4105 100644
--- a/src/fe_utils/meson.build
+++ b/src/fe_utils/meson.build
@@ -24,7 +24,7 @@ generated_sources += psqlscan
 fe_utils_sources += psqlscan
 
 fe_utils = static_library('libpgfeutils',
-  fe_utils_sources + generated_headers,
+  fe_utils_sources,
   c_pch: pch_postgres_fe_h,
   include_directories: [postgres_inc, libpq_inc],
   c_args: host_system == 'windows' ? ['-DFD_SETSIZE=1024'] : [],
diff --git a/src/include/meson.build b/src/include/meson.build
index d7e1ecd4c96d7..7b576945c119a 100644
--- a/src/include/meson.build
+++ b/src/include/meson.build
@@ -44,9 +44,9 @@ config_paths_data.set_quoted('MANDIR', dir_prefix / dir_man)
 
 var_cc = ' '.join(cc.cmd_array())
 var_cpp = ' '.join(cc.cmd_array() + ['-E'])
-var_cflags = ' '.join(cflags + cflags_warn + get_option('c_args'))
+var_cflags = ' '.join(cflags + cflags_warn + get_option('c_args') + ['-Wall'])
 if llvm.found()
-  var_cxxflags = ' '.join(cxxflags + cxxflags_warn + get_option('cpp_args'))
+  var_cxxflags = ' '.join(cxxflags + cxxflags_warn + get_option('cpp_args') + ['-Wall'])
 else
   var_cxxflags = ''
 endif
@@ -186,3 +186,17 @@ install_subdir('catalog',
 
 # autoconf generates the file there, ensure we get a conflict
 generated_sources_ac += {'src/include': ['stamp-h', 'stamp-ext-h']}
+
+
+generated_headers_stamp = custom_target('generated-headers-stamp.h',
+  output: 'generated-headers-stamp.h',
+  input: [generated_headers],
+  command: stamp_cmd,
+)
+
+generated_backend_headers_stamp = custom_target('generated-backend-headers-stamp.h',
+  output: 'generated-backend-headers-stamp.h',
+  input: [generated_backend_headers],
+  depends: generated_headers_stamp,
+  command: stamp_cmd,
+)
diff --git a/src/include/utils/pg_locale.h b/src/include/utils/pg_locale.h
index 6447bea8e0a6d..6f6eb84dc2822 100644
--- a/src/include/utils/pg_locale.h
+++ b/src/include/utils/pg_locale.h
@@ -16,6 +16,8 @@
 #include <xlocale.h>
 #endif
 #ifdef USE_ICU
+/* the cplusplus portion doesn't parse inside extern "C" { } */
+#define U_SHOW_CPLUSPLUS_API 0
 #include <unicode/ucol.h>
 #endif
 
diff --git a/src/makefiles/meson.build b/src/makefiles/meson.build
index be946f7b38bff..5512317f9335d 100644
--- a/src/makefiles/meson.build
+++ b/src/makefiles/meson.build
@@ -116,6 +116,10 @@ pgxs_kv = {
   'FLEXFLAGS': ' '.join(flex_flags),
 
   'LIBS': var_libs,
+
+  # Needed for headerscheck/cpluspluscheck
+  'perl_includespec': perl_dep.found() ? ' '.join(perl_ccflags) : '',
+  'python_includespec': python3_dep.found() ? '-I@0@'.format(python3_inst.get_variable('INCLUDEPY')) : '',
 }
 
 if llvm.found()
@@ -179,8 +183,8 @@ pgxs_empty = [
   'LIBOBJS', 'PG_CRC32C_OBJS', 'TAS',
   'DTRACEFLAGS', # only server has dtrace probes
 
-  'perl_archlibexp', 'perl_embed_ccflags', 'perl_embed_ldflags', 'perl_includespec', 'perl_privlibexp',
-  'python_additional_libs', 'python_includespec', 'python_libdir', 'python_libspec', 'python_majorversion', 'python_version',
+  'perl_archlibexp', 'perl_embed_ccflags', 'perl_embed_ldflags', 'perl_privlibexp',
+  'python_additional_libs', 'python_libdir', 'python_libspec', 'python_majorversion', 'python_version',
 
   # possible that some of these are referenced explicitly in pgxs makefiles?
   # For now not worth it.
diff --git a/src/meson.build b/src/meson.build
index bceeca70f90d2..c643ed672fe59 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -51,3 +51,17 @@ install_data(
 install_data(
   'makefiles/pgxs.mk',
   install_dir: dir_pgxs / 'src' / 'makefiles')
+
+
+generated_sources_stamp = custom_target('generated-sources-stamp.h',
+  output: 'generated-sources-stamp.h',
+  input: [generated_sources, generated_headers_stamp, generated_backend_headers_stamp],
+  command: stamp_cmd,
+)
+
+foreach tgt : ['headerscheck', 'cpluspluscheck']
+  run_target(tgt,
+    command: [files('tools/pginclude/@0@'.format(tgt)), meson.source_root(), meson.build_root()],
+    depends: [generated_sources_stamp, generated_headers_stamp, generated_backend_headers_stamp],
+  )
+endforeach
diff --git a/src/tools/ci/docker/linux_centos7 b/src/tools/ci/docker/linux_centos7
new file mode 100644
index 0000000000000..3742890d96177
--- /dev/null
+++ b/src/tools/ci/docker/linux_centos7
@@ -0,0 +1,57 @@
+FROM centos:centos7
+# Enable powertools, EPEL and devtoolset repository
+RUN \
+  yum -y install dnf-plugins-core \
+  epel-release \
+  centos-release-scl-rh && \
+  \
+  yum -y update && \
+  yum -y install \
+  \
+  git \
+  perl \
+  perl-ExtUtils-Embed \
+  perl-IPC-Run \
+  perl-Test-Harness \
+  perl-Test-Simple \
+  \
+  bison \
+  ccache \
+  clang \
+  devtoolset-7-make \
+  flex \
+  gcc \
+  gettext \
+  \
+  krb5-devel \
+  libicu-devel \
+  libuuid-devel \
+  libxml2-devel \
+  libxslt-devel \
+  libzstd-devel \
+  lz4-devel \
+  openldap-devel \
+  openssl-devel \
+  pam-devel \
+  python3-devel \
+  readline-devel \
+  systemd-devel \
+  tcl-devel \
+  \
+  krb5-server \
+  krb5-server-ldap \
+  krb5-workstation \
+  lz4 \
+  openldap-clients \
+  openldap-servers \
+  openssl \
+  zstd \
+  \
+  && \
+  pip3 install meson && \
+  pip3 install ninja && \
+  yum clean all
+
+# Make version is 3.82 but required is > 4, adding devtoolset-7-make to the PATH
+ENV PATH="/opt/rh/devtoolset-7/root/usr/bin/:${PATH}"
+ENV LANG=en_US.UTF-8
diff --git a/src/tools/ci/docker/linux_centos8 b/src/tools/ci/docker/linux_centos8
new file mode 100644
index 0000000000000..58f95847ef176
--- /dev/null
+++ b/src/tools/ci/docker/linux_centos8
@@ -0,0 +1,54 @@
+FROM quay.io/centos/centos:stream8
+# Enable powertools and EPEL repository
+RUN \
+  dnf -y install dnf-plugins-core && \
+  dnf config-manager --set-enabled powertools && \
+  dnf -y install epel-release && \
+  dnf -y update && \
+  dnf -y install \
+  \
+  git \
+  meson \
+  perl \
+  perl-IPC-Run \
+  \
+  bison \
+  ccache \
+  clang \
+  diffutils \
+  flex \
+  gcc \
+  gettext \
+  \
+  krb5-devel \
+  libicu-devel \
+  libuuid-devel \
+  libxml2-devel \
+  libxslt-devel \
+  libzstd-devel \
+  llvm-devel \
+  lz4-devel \
+  openldap-devel \
+  openssl-devel \
+  pam-devel \
+  python3-devel \
+  readline-devel \
+  systemd-devel \
+  tcl-devel \
+  \
+  krb5-server \
+  krb5-server-ldap \
+  krb5-workstation \
+  lz4 \
+  openldap-clients \
+  openldap-servers \
+  openssl \
+  zstd \
+  \
+  glibc-langpack-en \
+  \
+  && \
+  pip3 install ninja && \
+  yum clean all
+
+ENV LANG=en_US.UTF-8
diff --git a/src/tools/ci/docker/linux_fedora_rawhide b/src/tools/ci/docker/linux_fedora_rawhide
new file mode 100644
index 0000000000000..c95027cd6a779
--- /dev/null
+++ b/src/tools/ci/docker/linux_fedora_rawhide
@@ -0,0 +1,49 @@
+FROM fedora:rawhide
+RUN \
+  dnf -y update && \
+  dnf -y install \
+  git \
+  meson \
+  perl \
+  perl-IPC-Run \
+  \
+  bison \
+  ccache \
+  clang \
+  flex \
+  gcc \
+  gettext \
+  ninja-build \
+  \
+  krb5-devel \
+  libicu-devel \
+  libuuid-devel \
+  libxml2-devel \
+  libxslt-devel \
+  libzstd-devel \
+  llvm-devel \
+  lz4-devel \
+  openldap-devel \
+  openssl-devel \
+  pam-devel \
+  python3-devel \
+  readline-devel \
+  systemd-devel \
+  tcl-devel \
+  \
+  krb5-server \
+  krb5-server-ldap \
+  krb5-workstation \
+  lz4 \
+  openldap-clients \
+  openldap-servers \
+  openssl \
+  zstd \
+  \
+  langpacks-en \
+  glibc-langpack-en \
+  \
+  && \
+  yum clean all
+
+ENV LANG=en_US.UTF-8
diff --git a/src/tools/ci/docker/linux_opensuse_tumbleweed b/src/tools/ci/docker/linux_opensuse_tumbleweed
new file mode 100644
index 0000000000000..a89e146c6882b
--- /dev/null
+++ b/src/tools/ci/docker/linux_opensuse_tumbleweed
@@ -0,0 +1,56 @@
+FROM opensuse/tumbleweed
+RUN \
+  zypper -n clean -a && \
+  zypper -n ref && \
+  zypper -n dup && \
+  zypper -n update && \
+  zypper -n install \
+  diffutils \
+  git \
+  icu \
+  make \
+  meson \
+  perl-IPC-Run \
+  shadow \
+  systemd-devel \
+  util-linux \
+  \
+  bison \
+  ccache \
+  clang15 \
+  flex \
+  gcc \
+  gcc-c++ \
+  gettext-runtime \
+  ninja \
+  \
+  krb5-devel \
+  libicu-devel \
+  libldapcpp-devel \
+  liblz4-devel \
+  libopenssl-devel \
+  libselinux-devel \
+  libuuid-devel \
+  libxml2-devel \
+  libxslt-devel \
+  libzstd-devel \
+  llvm15-devel \
+  pam-devel \
+  python38-devel \
+  readline-devel \
+  tcl-devel \
+  \
+  openldap2 \
+  openldap2-client \
+  \
+  krb5-client \
+  krb5-plugin-kdb-ldap \
+  krb5-server \
+  lz4 \
+  zstd \
+  \
+  && \
+  zypper -n clean -a
+
+# Fixing ICU errors caused by locale being set to 'POSIX'
+ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
diff --git a/src/tools/ci/linux-mingw-w64-64bit.txt b/src/tools/ci/linux-mingw-w64-64bit.txt
new file mode 100644
index 0000000000000..9d43b6dcfbc3b
--- /dev/null
+++ b/src/tools/ci/linux-mingw-w64-64bit.txt
@@ -0,0 +1,13 @@
+[binaries]
+c = ['ccache', '/usr/bin/x86_64-w64-mingw32-gcc']
+cpp = ['ccache', '/usr/bin/x86_64-w64-mingw32-g++']
+ar = '/usr/bin/x86_64-w64-mingw32-ar'
+strip = '/usr/bin/x86_64-w64-mingw32-strip'
+pkgconfig = '/usr/bin/x86_64-w64-mingw32-pkg-config'
+windres = '/usr/bin/x86_64-w64-mingw32-windres'
+
+[host_machine]
+system = 'windows'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
diff --git a/src/tools/irlink b/src/tools/irlink
new file mode 100644
index 0000000000000..c7802097ac93e
--- /dev/null
+++ b/src/tools/irlink
@@ -0,0 +1,25 @@
+#!/usr/bin/env python3
+
+import os
+import shutil
+import subprocess
+import sys
+import argparse
+
+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)
diff --git a/src/tools/pginclude/cpluspluscheck b/src/tools/pginclude/cpluspluscheck
index 4e09c4686b30b..87adde15ad473 100755
--- a/src/tools/pginclude/cpluspluscheck
+++ b/src/tools/pginclude/cpluspluscheck
@@ -198,7 +198,7 @@ do
 	    src/pl/plperl/*)
 		EXTRAINCLUDES="$perl_includespec" ;;
 	    src/pl/plpython/*)
-		EXTRAINCLUDES="$python_includespec" ;;
+		EXTRAINCLUDES="$python_includespec"; ;;
 	    src/interfaces/ecpg/*)
 		EXTRAINCLUDES="-I $builddir/src/interfaces/ecpg/include -I $srcdir/src/interfaces/ecpg/include" ;;
 	    src/backend/parser/*)
diff --git a/src/tools/relativize_shared_library_references b/src/tools/relativize_shared_library_references
new file mode 100755
index 0000000000000..280bd48fd3227
--- /dev/null
+++ b/src/tools/relativize_shared_library_references
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+# -*-python-*-
+
+# This script updates a macos postgres installation to reference all internal
+# shared libraries using rpaths, leaving absolute install_names in the
+# libraries themselves intact.
+
+import os
+import sys
+import json
+import subprocess
+import shutil
+
+
+def installed_path(destdir, path):
+    if destdir is not None:
+        return f'{destdir}{path}'
+    else:
+        return path
+
+
+def collect_information():
+    shared_libraries = []
+    executables = []
+    shared_modules = []
+
+    meson_info_p = os.path.join(build_root, 'meson-info')
+    targets = json.load(
+        open(os.path.join(meson_info_p, 'intro-targets.json')))
+    installed = json.load(
+        open(os.path.join(meson_info_p, 'intro-installed.json')))
+
+    for target in targets:
+        if not target['installed']:
+            continue
+
+        filenames = target['filename']
+
+        if target['type'] == 'shared library':
+            assert(len(filenames) == 1)
+            filename = filenames[0]
+
+            shared_libraries.append(installed[filename])
+
+        if target['type'] == 'executable':
+            assert(len(filenames) == 1)
+            filename = filenames[0]
+            executables.append(installed[filename])
+
+        if target['type'] == 'shared module':
+            assert(len(filenames) == 1)
+            filename = filenames[0]
+            shared_modules.append(installed[filename])
+
+    return shared_libraries, executables, shared_modules
+
+
+def patch_references(destdir, shared_libraries, executables, shared_modules):
+    install_name_tool = [shutil.which('install_name_tool')]
+
+    for lib in shared_libraries:
+        libname = os.path.basename(lib)
+        libpath = installed_path(destdir, lib)
+        newref = f'@rpath/{libname}'
+
+        for patch in shared_modules + executables:
+            patchpath = installed_path(destdir, patch)
+
+            # print(f'in {patchpath} replace reference to {libpath} with {newref}')
+            if not os.path.exists(patchpath):
+                print(f"path {patchpath} doesn't exist", file=sys.stderr)
+                sys.exit(1)
+
+            cmd = install_name_tool + ['-change', lib, newref, patchpath]
+            subprocess.check_call(cmd)
+
+
+if __name__ == '__main__':
+    build_root = os.environ['MESON_BUILD_ROOT']
+    destdir = os.environ.get('DESTDIR', None)
+
+    print(f'making references to shared libraries relative, destdir is {destdir}',
+          file=sys.stderr)
+
+    shared_libraries, executables, shared_modules = collect_information()
+    patch_references(destdir, shared_libraries, executables, shared_modules)
+
+    sys.exit(0)
diff --git a/src/tools/relpath.py b/src/tools/relpath.py
new file mode 100755
index 0000000000000..87bcb496ab59c
--- /dev/null
+++ b/src/tools/relpath.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+
+print(os.path.relpath(sys.argv[2], start=sys.argv[1]))