From 5e5036ce911a20581389616bf809c9656c752533 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Fri, 17 Nov 2023 10:00:22 +0900
Subject: [PATCH v5] Remove MSVC scripts

---
 src/backend/meson.build                      |    2 +-
 src/common/Makefile                          |   11 +-
 src/common/meson.build                       |    9 +-
 src/port/Makefile                            |    2 -
 src/port/pgstrsignal.c                       |    3 -
 src/bin/pg_basebackup/Makefile               |    3 -
 src/bin/pgevent/meson.build                  |    3 +-
 src/interfaces/libpq/Makefile                |    3 -
 config/perl.m4                               |   15 +-
 doc/src/sgml/filelist.sgml                   |    1 -
 doc/src/sgml/install-windows.sgml            |  588 --------
 doc/src/sgml/installation.sgml               |  314 +++-
 doc/src/sgml/postgres.sgml                   |    1 -
 doc/src/sgml/standalone-profile.xsl          |    4 -
 meson.build                                  |    1 -
 src/tools/msvc/.gitignore                    |    3 -
 src/tools/msvc/Install.pm                    |  748 ----------
 src/tools/msvc/MSBuildProject.pm             |  508 -------
 src/tools/msvc/Mkvcbuild.pm                  | 1219 ----------------
 src/tools/msvc/Project.pm                    |  482 -------
 src/tools/msvc/README                        |   99 --
 src/tools/msvc/Solution.pm                   | 1358 ------------------
 src/tools/msvc/VSObjectFactory.pm            |  174 ---
 src/tools/msvc/build.bat                     |    6 -
 src/tools/msvc/build.pl                      |   92 --
 src/tools/msvc/clean.bat                     |  160 ---
 src/tools/msvc/config_default.pl             |   32 -
 src/tools/msvc/dummylib/README               |   13 -
 src/tools/msvc/dummylib/Win32.pm             |    7 -
 src/tools/msvc/dummylib/Win32/Registry.pm    |   16 -
 src/tools/msvc/dummylib/Win32API/File.pm     |   17 -
 src/tools/msvc/ecpg_regression.proj          |   64 -
 src/tools/msvc/install.bat                   |    6 -
 src/tools/msvc/install.pl                    |   39 -
 src/tools/msvc/mkvcbuild.pl                  |   31 -
 src/tools/msvc/pgbison.bat                   |    7 -
 src/tools/msvc/pgbison.pl                    |   55 -
 src/tools/msvc/pgflex.bat                    |    7 -
 src/tools/msvc/pgflex.pl                     |  108 --
 src/tools/msvc/vcregress.bat                 |    6 -
 src/tools/msvc/vcregress.pl                  |  664 ---------
 src/tools/{msvc/gendef.pl => msvc_gendef.pl} |    4 +-
 src/tools/perlcheck/pgperlsyncheck           |    2 +-
 43 files changed, 319 insertions(+), 6568 deletions(-)
 delete mode 100644 doc/src/sgml/install-windows.sgml
 delete mode 100644 src/tools/msvc/.gitignore
 delete mode 100644 src/tools/msvc/Install.pm
 delete mode 100644 src/tools/msvc/MSBuildProject.pm
 delete mode 100644 src/tools/msvc/Mkvcbuild.pm
 delete mode 100644 src/tools/msvc/Project.pm
 delete mode 100644 src/tools/msvc/README
 delete mode 100644 src/tools/msvc/Solution.pm
 delete mode 100644 src/tools/msvc/VSObjectFactory.pm
 delete mode 100755 src/tools/msvc/build.bat
 delete mode 100644 src/tools/msvc/build.pl
 delete mode 100755 src/tools/msvc/clean.bat
 delete mode 100644 src/tools/msvc/config_default.pl
 delete mode 100644 src/tools/msvc/dummylib/README
 delete mode 100644 src/tools/msvc/dummylib/Win32.pm
 delete mode 100644 src/tools/msvc/dummylib/Win32/Registry.pm
 delete mode 100644 src/tools/msvc/dummylib/Win32API/File.pm
 delete mode 100644 src/tools/msvc/ecpg_regression.proj
 delete mode 100644 src/tools/msvc/install.bat
 delete mode 100755 src/tools/msvc/install.pl
 delete mode 100644 src/tools/msvc/mkvcbuild.pl
 delete mode 100755 src/tools/msvc/pgbison.bat
 delete mode 100644 src/tools/msvc/pgbison.pl
 delete mode 100755 src/tools/msvc/pgflex.bat
 delete mode 100644 src/tools/msvc/pgflex.pl
 delete mode 100644 src/tools/msvc/vcregress.bat
 delete mode 100644 src/tools/msvc/vcregress.pl
 rename src/tools/{msvc/gendef.pl => msvc_gendef.pl} (97%)

diff --git a/src/backend/meson.build b/src/backend/meson.build
index 88a35e9676..fbc8a9c6aa 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -72,7 +72,7 @@ postgres_lib = static_library('postgres_lib',
 
 if cc.get_id() == 'msvc'
   postgres_def = custom_target('postgres.def',
-    command: [perl, files('../tools/msvc/gendef.pl'),
+    command: [perl, files('../tools/msvc_gendef.pl'),
               '--arch', host_cpu,
               '--tempdir', '@PRIVATE_DIR@',
               '--deffile', '@OUTPUT@',
diff --git a/src/common/Makefile b/src/common/Makefile
index ce4535d7fe..83c3490355 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -43,8 +43,6 @@ override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
 override CPPFLAGS := -DFRONTEND -I. -I$(top_srcdir)/src/common $(CPPFLAGS)
 LIBS += $(PTHREAD_LIBS)
 
-# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
-
 OBJS_COMMON = \
 	archive.o \
 	base64.o \
@@ -98,11 +96,10 @@ OBJS_COMMON += \
 	sha2.o
 endif
 
-# A few files are currently only built for frontend, not server
-# (Mkvcbuild.pm has a copy of this list, too).  logging.c is excluded
-# from OBJS_FRONTEND_SHLIB (shared library) as a matter of policy,
-# because it is not appropriate for general purpose libraries such
-# as libpq to report errors directly.
+# A few files are currently only built for frontend, not server.
+# logging.c is excluded from OBJS_FRONTEND_SHLIB (shared library) as
+# a matter of policy, because it is not appropriate for general purpose
+# libraries such as libpq to report errors directly.
 OBJS_FRONTEND_SHLIB = \
 	$(OBJS_COMMON) \
 	fe_memutils.o \
diff --git a/src/common/meson.build b/src/common/meson.build
index 8be145c0fb..0a1cae1a83 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -95,11 +95,10 @@ common_sources_cflags = {
 }
 
 
-# A few files are currently only built for frontend, not server
-# (Mkvcbuild.pm has a copy of this list, too).  logging.c is excluded
-# from OBJS_FRONTEND_SHLIB (shared library) as a matter of policy,
-# because it is not appropriate for general purpose libraries such
-# as libpq to report errors directly.
+# A few files are currently only built for frontend, not server.
+# logging.c is excluded from OBJS_FRONTEND_SHLIB (shared library) as
+# a matter of policy, because it is not appropriate for general purpose
+# libraries such as libpq to report errors directly.
 
 common_sources_frontend_shlib = common_sources
 common_sources_frontend_shlib += files(
diff --git a/src/port/Makefile b/src/port/Makefile
index 4320dee0d1..dcc8737e68 100644
--- a/src/port/Makefile
+++ b/src/port/Makefile
@@ -35,8 +35,6 @@ include $(top_builddir)/src/Makefile.global
 override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
 LIBS += $(PTHREAD_LIBS)
 
-# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
-
 OBJS = \
 	$(LIBOBJS) \
 	$(PG_CRC32C_OBJS) \
diff --git a/src/port/pgstrsignal.c b/src/port/pgstrsignal.c
index 7d76d1cca9..8c10a760c6 100644
--- a/src/port/pgstrsignal.c
+++ b/src/port/pgstrsignal.c
@@ -6,9 +6,6 @@
  * On platforms compliant with modern POSIX, this just wraps strsignal(3).
  * Elsewhere, we do the best we can.
  *
- * This file is not currently built in MSVC builds, since it's useless
- * on non-Unix platforms.
- *
  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
diff --git a/src/bin/pg_basebackup/Makefile b/src/bin/pg_basebackup/Makefile
index 74dc1ddd6d..4c1ad02bf2 100644
--- a/src/bin/pg_basebackup/Makefile
+++ b/src/bin/pg_basebackup/Makefile
@@ -35,9 +35,6 @@ OBJS = \
 	streamutil.o \
 	walmethods.o
 
-# If you add or remove files here, also update Mkvcbuild.pm, which only knows
-# about OBJS, not BBOBJS, and thus has to be manually updated to stay in sync
-# with this list.
 BBOBJS = \
 	pg_basebackup.o \
 	bbstreamer_file.o \
diff --git a/src/bin/pgevent/meson.build b/src/bin/pgevent/meson.build
index eca930ae47..8ef121a2da 100644
--- a/src/bin/pgevent/meson.build
+++ b/src/bin/pgevent/meson.build
@@ -14,7 +14,8 @@ pgevent_sources += rc_bin_gen.process(win32ver_rc, extra_args: [
 
 pgevent_sources += windows.compile_resources('pgmsgevent.rc')
 
-# FIXME: copied from Mkvcbuild.pm, but I don't think that's the right approach
+# XXX: We may want to revisit the addition of this flag and improve the
+# way symbols are exported.
 pgevent_link_args = []
 if cc.get_id() == 'msvc'
   pgevent_link_args += '/ignore:4104'
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index d0a66cfaa0..df8a1f31b2 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -27,9 +27,6 @@ ifneq ($(PORTNAME), win32)
 override CFLAGS += $(PTHREAD_CFLAGS)
 endif
 
-# The MSVC build system scrapes OBJS from this file.  If you change any of
-# the conditional additions of files to OBJS, update Mkvcbuild.pm to match.
-
 OBJS = \
 	$(WIN32RES) \
 	fe-auth-scram.o \
diff --git a/config/perl.m4 b/config/perl.m4
index 1a3bb55649..59b1a0e956 100644
--- a/config/perl.m4
+++ b/config/perl.m4
@@ -53,10 +53,17 @@ AC_DEFUN([PGAC_CHECK_PERL_CONFIGS],
 # would be fatal to try to compile PL/Perl to a different libc ABI than core
 # Postgres uses.  The available information says that most symbols that affect
 # Perl's own ABI begin with letters, so it's almost sufficient to adopt -D
-# switches for symbols not beginning with underscore.  Some exceptions are the
-# Windows-specific -D_USE_32BIT_TIME_T and -D__MINGW_USE_VC2005_COMPAT; see
-# Mkvcbuild.pm for details.  We absorb the former when Perl reports it.  Perl
-# never reports the latter, and we don't attempt to deduce when it's needed.
+# switches for symbols not beginning with underscore.
+
+# Some exceptions are the Windows-specific -D_USE_32BIT_TIME_T and
+# -D__MINGW_USE_VC2005_COMPAT. To be exact, Windows offers several 32-bit ABIs.
+# Perl is sensitive to sizeof(time_t), one of the ABI dimensions.  PostgreSQL
+# doesn't support building with pre-MSVC-2005 compilers, but it does support
+# linking to Perl built with such a compiler.  MSVC-built Perl 5.13.4 and
+# later report -D_USE_32BIT_TIME_T in $Config{ccflags} if applicable, but
+# MinGW-built Perl never reports -D_USE_32BIT_TIME_T despite typically needing
+# it.
+#
 # Consequently, we don't support using MinGW to link to MSVC-built Perl.  As
 # of 2017, all supported ActivePerl and Strawberry Perl are MinGW-built.  If
 # that changes or an MSVC-built Perl distribution becomes prominent, we can
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 4c63a7e768..5f6b58133b 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -38,7 +38,6 @@
 <!ENTITY high-availability      SYSTEM "high-availability.sgml">
 <!ENTITY installbin    SYSTEM "install-binaries.sgml">
 <!ENTITY installation  SYSTEM "installation.sgml">
-<!ENTITY installw      SYSTEM "install-windows.sgml">
 <!ENTITY maintenance   SYSTEM "maintenance.sgml">
 <!ENTITY manage-ag     SYSTEM "manage-ag.sgml">
 <!ENTITY monitoring    SYSTEM "monitoring.sgml">
diff --git a/doc/src/sgml/install-windows.sgml b/doc/src/sgml/install-windows.sgml
deleted file mode 100644
index 27cb82ba14..0000000000
--- a/doc/src/sgml/install-windows.sgml
+++ /dev/null
@@ -1,588 +0,0 @@
-<!-- doc/src/sgml/install-windows.sgml -->
-
-<chapter id="install-windows">
- <title>Installation from Source Code on <productname>Windows</productname></title>
-
- <indexterm>
-  <primary>installation</primary>
-  <secondary>on Windows</secondary>
- </indexterm>
-
- <para>
-  It is recommended that most users download the binary distribution for
-  Windows, available as a graphical installer package
-  from the <productname>PostgreSQL</productname> website at
-  <ulink url="https://www.postgresql.org/download/"></ulink>. Building from source
-  is only intended for people developing <productname>PostgreSQL</productname>
-  or extensions.
- </para>
-
- <para>
-  There are several different ways of building PostgreSQL on
-  <productname>Windows</productname>. The simplest way to build with
-  Microsoft tools is to install <productname>Visual Studio 2022</productname>
-  and use the included compiler. It is also possible to build with the full
-  <productname>Microsoft Visual C++ 2015 to 2022</productname>.
-  In some cases that requires the installation of the
-  <productname>Windows SDK</productname> in addition to the compiler.
- </para>
-
- <para>
-  It is also possible to build PostgreSQL using the GNU compiler tools
-  provided by <productname>MinGW</productname>, or using
-  <productname>Cygwin</productname> for older versions of
-  <productname>Windows</productname>.
- </para>
-
- <para>
-  Building using <productname>MinGW</productname> or
-  <productname>Cygwin</productname> uses the normal build system, see
-  <xref linkend="installation"/> and the specific notes in
-  <xref linkend="installation-notes-mingw"/> and <xref linkend="installation-notes-cygwin"/>.
-  To produce native 64 bit binaries in these environments, use the tools from
-  <productname>MinGW-w64</productname>. These tools can also be used to
-  cross-compile for 32 bit and 64 bit <productname>Windows</productname>
-  targets on other hosts, such as <productname>Linux</productname> and
-  <productname>macOS</productname>.
-  <productname>Cygwin</productname> is not recommended for running a
-  production server, and it should only be used for running on
-  older versions of <productname>Windows</productname> where
-  the native build does not work. The official
-  binaries are built using <productname>Visual Studio</productname>.
- </para>
-
- <para>
-  Native builds of <application>psql</application> don't support command
-  line editing. The <productname>Cygwin</productname> build does support
-  command line editing, so it should be used where psql is needed for
-  interactive use on  <productname>Windows</productname>.
- </para>
-
- <sect1 id="install-windows-full">
-  <title>Building with <productname>Visual C++</productname> or the
-  <productname>Microsoft Windows SDK</productname></title>
-
- <para>
-  PostgreSQL can be built using the Visual C++ compiler suite from Microsoft.
-  These compilers can be either from <productname>Visual Studio</productname>,
-  <productname>Visual Studio Express</productname> or some versions of the
-  <productname>Microsoft Windows SDK</productname>. If you do not already have a
-  <productname>Visual Studio</productname> environment set up, the easiest
-  ways are to use the compilers from
-  <productname>Visual Studio 2022</productname> or those in the
-  <productname>Windows SDK 10</productname>, which are both free downloads
-  from Microsoft.
- </para>
-
- <para>
-  Both 32-bit and 64-bit builds are possible with the Microsoft Compiler suite.
-  32-bit PostgreSQL builds are possible with
-  <productname>Visual Studio 2015</productname> to
-  <productname>Visual Studio 2022</productname>,
-  as well as standalone Windows SDK releases 10 and above.
-  64-bit PostgreSQL builds are supported with
-  <productname>Microsoft Windows SDK</productname> version 10 and above or
-  <productname>Visual Studio 2015</productname> and above.
-   <!--
-       For 2015 requirements:
-       https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2015-sysrequirements-vs
-       For 2017 requirements:
-       https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2017-system-requirements-vs
-       For 2019 requirements:
-       https://docs.microsoft.com/en-us/visualstudio/releases/2019/system-requirements
-       For 2022 requirements:
-       https://docs.microsoft.com/en-us/visualstudio/releases/2022/system-requirements
-   -->
- </para>
-
- <para>
-  The tools for building using <productname>Visual C++</productname> or
-  <productname>Platform SDK</productname> are in the
-  <filename>src\tools\msvc</filename> directory. When building, make sure
-  there are no tools from <productname>MinGW</productname> or
-  <productname>Cygwin</productname> present in your system PATH. Also, make
-  sure you have all the required Visual C++ tools available in the PATH. In
-  <productname>Visual Studio</productname>, start the
-  <application>Visual Studio Command Prompt</application>.
-  If you wish to build a 64-bit version, you must use the 64-bit version of
-  the command, and vice versa.
-  Starting with <productname>Visual Studio 2017</productname> this can be
-  done from the command line using <command>VsDevCmd.bat</command>, see
-  <command>-help</command> for the available options and their default values.
-  <command>vsvars32.bat</command> is available in
-  <productname>Visual Studio 2015</productname> and earlier versions for the
-  same purpose.
-  From the <application>Visual Studio Command Prompt</application>, you can
-  change the targeted CPU architecture, build type, and target OS by using the
-  <command>vcvarsall.bat</command> command, e.g.,
-  <command>vcvarsall.bat x64 10.0.10240.0</command> to target Windows 10
-  with a 64-bit release build. See <command>-help</command> for the other
-  options of <command>vcvarsall.bat</command>. All commands should be run from
-  the <filename>src\tools\msvc</filename> directory.
- </para>
-
- <para>
-  Before you build, you can create the file <filename>config.pl</filename>
-  to reflect any configuration options you want to change, or the paths to
-  any third party libraries to use. The complete configuration is determined
-  by first reading and parsing the file <filename>config_default.pl</filename>,
-  and then apply any changes from <filename>config.pl</filename>. For example,
-  to specify the location of your <productname>Python</productname> installation,
-  put the following in <filename>config.pl</filename>:
-<programlisting>
-$config->{python} = 'c:\python310';
-</programlisting>
-  You only need to specify those parameters that are different from what's in
-  <filename>config_default.pl</filename>.
- </para>
-
- <para>
-  If you need to set any other environment variables, create a file called
-  <filename>buildenv.pl</filename> and put the required commands there. For
-  example, to add the path for bison when it's not in the PATH, create a file
-  containing:
-<programlisting>
-$ENV{PATH}=$ENV{PATH} . ';c:\some\where\bison\bin';
-</programlisting>
- </para>
-
- <para>
-  To pass additional command line arguments to the Visual Studio build
-  command (msbuild or vcbuild):
-<programlisting>
-$ENV{MSBFLAGS}="/m";
-</programlisting>
- </para>
-
- <sect2 id="install-windows-full-requirements">
-  <title>Requirements</title>
-  <para>
-   The following additional products are required to build
-   <productname>PostgreSQL</productname>. Use the
-   <filename>config.pl</filename> file to specify which directories the libraries
-   are available in.
-
-   <variablelist>
-    <varlistentry>
-     <term><productname>Microsoft Windows SDK</productname></term>
-     <listitem><para>
-      If your build environment doesn't ship with a supported version of the
-      <productname>Microsoft Windows SDK</productname> it
-      is recommended that you upgrade to the latest version (currently
-      version 10), available for download from
-      <ulink url="https://www.microsoft.com/download"></ulink>.
-     </para>
-     <para>
-      You must always include the
-      <application>Windows Headers and Libraries</application> part of the SDK.
-      If you install a <productname>Windows SDK</productname>
-      including the <application>Visual C++ Compilers</application>,
-      you don't need <productname>Visual Studio</productname> to build.
-      Note that as of Version 8.0a the Windows SDK no longer ships with a
-      complete command-line build environment.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>ActiveState Perl</productname></term>
-     <listitem><para>
-      ActiveState Perl is required to run the build generation scripts. MinGW
-      or Cygwin Perl will not work. It must also be present in the PATH.
-      Binaries can be downloaded from
-      <ulink url="https://www.activestate.com"></ulink>
-      (Note: version 5.14 or later is required,
-      the free Standard Distribution is sufficient).
-     </para></listitem>
-    </varlistentry>
-
-   </variablelist>
-  </para>
-  <para>
-   The following additional products are not required to get started,
-   but are required to build the complete package. Use the
-   <filename>config.pl</filename> file to specify which directories the libraries
-   are available in.
-
-   <variablelist>
-    <varlistentry>
-     <term><productname>ActiveState Tcl</productname></term>
-     <listitem><para>
-      Required for building <application>PL/Tcl</application> (Note: version
-      8.4 is required, the free Standard Distribution is sufficient).
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>Bison</productname> and
-      <productname>Flex</productname></term>
-     <listitem>
-     <para>
-      <productname>Bison</productname> and <productname>Flex</productname> are
-      required.  Only <productname>Bison</productname> versions 2.3 and later
-      will work. <productname>Flex</productname> must be version 2.5.35 or later.
-     </para>
-
-     <para>
-      Both <productname>Bison</productname> and <productname>Flex</productname>
-      are included in the <productname>msys</productname> tool suite, available
-      from <ulink url="http://www.mingw.org/wiki/MSYS"></ulink> as part of the
-      <productname>MinGW</productname> compiler suite.
-     </para>
-
-     <para>
-      You will need to add the directory containing
-      <filename>flex.exe</filename> and <filename>bison.exe</filename> to the
-      PATH environment variable in <filename>buildenv.pl</filename> unless
-      they are already in PATH. In the case of MinGW, the directory is the
-      <filename>\msys\1.0\bin</filename> subdirectory of your MinGW
-      installation directory.
-     </para>
-
-     <note>
-      <para>
-        The Bison distribution from GnuWin32 appears to have a bug that
-        causes Bison to malfunction when installed in a directory with
-        spaces in the name, such as the default location on English
-        installations <filename>C:\Program Files\GnuWin32</filename>.
-        Consider installing into <filename>C:\GnuWin32</filename> or use the
-        NTFS short name path to GnuWin32 in your PATH environment setting
-        (e.g., <filename>C:\PROGRA~1\GnuWin32</filename>).
-       </para>
-     </note>
-
-     </listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>Diff</productname></term>
-     <listitem><para>
-      Diff is required to run the regression tests, and can be downloaded
-      from <ulink url="http://gnuwin32.sourceforge.net"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>Gettext</productname></term>
-     <listitem><para>
-      Gettext is required to build with NLS support, and can be downloaded
-      from <ulink url="http://gnuwin32.sourceforge.net"></ulink>. Note that binaries,
-      dependencies and developer files are all needed.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>MIT Kerberos</productname></term>
-     <listitem><para>
-      Required for GSSAPI authentication support. MIT Kerberos can be
-      downloaded from
-      <ulink url="https://web.mit.edu/Kerberos/dist/index.html"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>libxml2</productname> and
-      <productname>libxslt</productname></term>
-     <listitem><para>
-      Required for XML support. Binaries can be downloaded from
-      <ulink url="https://zlatkovic.com/pub/libxml"></ulink> or source from
-      <ulink url="http://xmlsoft.org"></ulink>. Note that libxml2 requires iconv,
-      which is available from the same download location.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>LZ4</productname></term>
-     <listitem><para>
-      Required for supporting <productname>LZ4</productname> compression.
-      Binaries and source can be downloaded from
-      <ulink url="https://github.com/lz4/lz4/releases"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>Zstandard</productname></term>
-     <listitem><para>
-      Required for supporting <productname>Zstandard</productname> compression.
-      Binaries and source can be downloaded from
-      <ulink url="https://github.com/facebook/zstd/releases"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>OpenSSL</productname></term>
-     <listitem><para>
-      Required for SSL support. Binaries can be downloaded from
-      <ulink url="https://slproweb.com/products/Win32OpenSSL.html"></ulink>
-      or source from <ulink url="https://www.openssl.org"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>ossp-uuid</productname></term>
-     <listitem><para>
-      Required for UUID-OSSP support (contrib only). Source can be
-      downloaded from
-      <ulink url="http://www.ossp.org/pkg/lib/uuid/"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>Python</productname></term>
-     <listitem><para>
-      Required for building <application>PL/Python</application>. Binaries can
-      be downloaded from <ulink url="https://www.python.org"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><productname>zlib</productname></term>
-     <listitem><para>
-      Required for compression support in <application>pg_dump</application>
-      and <application>pg_restore</application>. Binaries can be downloaded
-      from <ulink url="https://www.zlib.net"></ulink>.
-     </para></listitem>
-    </varlistentry>
-
-   </variablelist>
-  </para>
- </sect2>
-
- <sect2 id="install-windows-full-64-bit">
-  <title>Special Considerations for 64-Bit Windows</title>
-
-  <para>
-   PostgreSQL will only build for the x64 architecture on 64-bit Windows.
-  </para>
-
-  <para>
-   Mixing 32- and 64-bit versions in the same build tree is not supported.
-   The build system will automatically detect if it's running in a 32- or
-   64-bit environment, and build PostgreSQL accordingly. For this reason, it
-   is important to start the correct command prompt before building.
-  </para>
-
-  <para>
-   To use a server-side third party library such as <productname>Python</productname> or
-   <productname>OpenSSL</productname>, this library <emphasis>must</emphasis> also be
-   64-bit. There is no support for loading a 32-bit library in a 64-bit
-   server. Several of the third party libraries that PostgreSQL supports may
-   only be available in 32-bit versions, in which case they cannot be used with
-   64-bit PostgreSQL.
-  </para>
- </sect2>
-
- <sect2 id="install-windows-full-build">
-  <title>Building</title>
-
-  <para>
-   To build all of PostgreSQL in release configuration (the default), run the
-   command:
-<screen>
-<userinput>build</userinput>
-</screen>
-   To build all of PostgreSQL in debug configuration, run the command:
-<screen>
-<userinput>build DEBUG</userinput>
-</screen>
-   To build just a single project, for example psql, run the commands:
-<screen>
-<userinput>build psql</userinput>
-<userinput>build DEBUG psql</userinput>
-</screen>
-   To change the default build configuration to debug, put the following
-   in the <filename>buildenv.pl</filename> file:
-<programlisting>
-$ENV{CONFIG}="Debug";
-</programlisting>
-  </para>
-
-  <para>
-   It is also possible to build from inside the Visual Studio GUI. In this
-   case, you need to run:
-<screen>
-<userinput>perl mkvcbuild.pl</userinput>
-</screen>
-   from the command prompt, and then open the generated
-   <filename>pgsql.sln</filename> (in the root directory of the source tree)
-   in Visual Studio.
-  </para>
- </sect2>
-
- <sect2 id="install-windows-full-clean-inst">
-  <title>Cleaning and Installing</title>
-
-  <para>
-   Most of the time, the automatic dependency tracking in Visual Studio will
-   handle changed files. But if there have been large changes, you may need
-   to clean the installation. To do this, simply run the
-   <filename>clean.bat</filename> command, which will automatically clean out
-   all generated files. You can also run it with the
-   <parameter>dist</parameter> parameter, in which case it will behave like
-   <userinput>make distclean</userinput> and remove the flex/bison output files
-   as well.
-  </para>
-
-  <para>
-   By default, all files are written into a subdirectory of the
-   <filename>debug</filename> or <filename>release</filename> directories. To
-   install these files using the standard layout, and also generate the files
-   required to initialize and use the database, run the command:
-<screen>
-<userinput>install c:\destination\directory</userinput>
-</screen>
-  </para>
-
-  <para>
-   If you want to install only the client applications and
-   interface libraries, then you can use these commands:
-<screen>
-<userinput>install c:\destination\directory client</userinput>
-</screen>
-  </para>
- </sect2>
-
- <sect2 id="install-windows-full-reg-tests">
-  <title>Running the Regression Tests</title>
-
-  <para>
-   To run the regression tests, make sure you have completed the build of all
-   required parts first. Also, make sure that the DLLs required to load all
-   parts of the system (such as the Perl and Python DLLs for the procedural
-   languages) are present in the system path. If they are not, set it through
-   the <filename>buildenv.pl</filename> file. To run the tests, run one of
-   the following commands from the <filename>src\tools\msvc</filename>
-   directory:
-<screen>
-<userinput>vcregress check</userinput>
-<userinput>vcregress installcheck</userinput>
-<userinput>vcregress plcheck</userinput>
-<userinput>vcregress contribcheck</userinput>
-<userinput>vcregress modulescheck</userinput>
-<userinput>vcregress ecpgcheck</userinput>
-<userinput>vcregress isolationcheck</userinput>
-<userinput>vcregress bincheck</userinput>
-<userinput>vcregress recoverycheck</userinput>
-<userinput>vcregress taptest</userinput>
-</screen>
-
-   To change the schedule used (default is parallel), append it to the
-   command line like:
-<screen>
-<userinput>vcregress check serial</userinput>
-</screen>
-
-   <command>vcregress taptest</command> can be used to run the TAP tests
-   of a target directory, like:
-<screen>
-<userinput>vcregress taptest src\bin\initdb\</userinput>
-</screen>
-
-   For more information about the regression tests, see
-   <xref linkend="regress"/>.
-  </para>
-
-  <para>
-   Running the regression tests on client programs with
-   <command>vcregress bincheck</command>, on recovery tests with
-   <command>vcregress recoverycheck</command>, or TAP tests specified with
-   <command>vcregress taptest</command> requires an additional Perl module
-   to be installed:
-   <variablelist>
-    <varlistentry>
-     <term><productname>IPC::Run</productname></term>
-     <listitem><para>
-      As of this writing, <literal>IPC::Run</literal> is not included in the
-      ActiveState Perl installation, nor in the ActiveState Perl Package
-      Manager (PPM) library. To install, download the
-      <filename>IPC-Run-&lt;version&gt;.tar.gz</filename> source archive from
-      <acronym>CPAN</acronym>,
-      at <ulink url="https://metacpan.org/dist/IPC-Run"></ulink>, and
-      uncompress. Edit the <filename>buildenv.pl</filename> file, and add a PERL5LIB
-      variable to point to the <filename>lib</filename> subdirectory from the
-      extracted archive. For example:
-<programlisting>
-$ENV{PERL5LIB}=$ENV{PERL5LIB} . ';c:\IPC-Run-0.94\lib';
-</programlisting>
-     </para></listitem>
-    </varlistentry>
-   </variablelist>
-  </para>
-
-  <para>
-   The TAP tests run with <command>vcregress</command> support the
-   environment variables <varname>PROVE_TESTS</varname>, that is expanded
-   automatically using the name patterns given, and
-   <varname>PROVE_FLAGS</varname>. These can be set on a Windows terminal,
-   before running <command>vcregress</command>:
-<programlisting>
-set PROVE_FLAGS=--timer --jobs 2
-set PROVE_TESTS=t/020*.pl t/010*.pl
-</programlisting>
-   It is also possible to set up those parameters in
-   <filename>buildenv.pl</filename>:
-<programlisting>
-$ENV{PROVE_FLAGS}='--timer --jobs 2'
-$ENV{PROVE_TESTS}='t/020*.pl t/010*.pl'
-</programlisting>
-  </para>
-
-  <para>
-    Additionally, the behavior of TAP tests can be controlled by a set of
-    environment variables, see <xref linkend="regress-tap-vars" />.
-  </para>
-
-  <para>
-   Some of the TAP tests depend on a set of external commands that would
-   optionally trigger tests related to them. Each one of those variables
-   can be set or unset in <filename>buildenv.pl</filename>:
-   <variablelist>
-    <varlistentry>
-     <term><varname>GZIP_PROGRAM</varname></term>
-     <listitem><para>
-      Path to a <application>gzip</application> command. The default is
-      <literal>gzip</literal>, which will search for a command by that
-      name in the configured <envar>PATH</envar>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><varname>LZ4</varname></term>
-     <listitem><para>
-      Path to a <application>lz4</application> command. The default is
-      <literal>lz4</literal>, which will search for a command by that
-      name in the configured <envar>PATH</envar>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><varname>OPENSSL</varname></term>
-     <listitem><para>
-      Path to an <application>openssl</application> command. The default is
-      <literal>openssl</literal>, which will search for a command by that
-      name in the configured <envar>PATH</envar>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><varname>TAR</varname></term>
-     <listitem><para>
-      Path to a <application>tar</application> command. The default is
-      <literal>tar</literal>, which will search for a command by that
-      name in the configured <envar>PATH</envar>.
-     </para></listitem>
-    </varlistentry>
-
-    <varlistentry>
-     <term><varname>ZSTD</varname></term>
-     <listitem><para>
-      Path to a <application>zstd</application> command. The default is
-      <literal>zstd</literal>, which will search for a command by that
-      name in the configured <envar>PATH</envar>.
-     </para></listitem>
-    </varlistentry>
-   </variablelist>
-  </para>
- </sect2>
-
- </sect1>
-</chapter>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a3dc6eb855..7c07f2ed89 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -24,13 +24,6 @@ documentation.  See standalone-profile.xsl for details.
   and see <xref linkend="install-binaries" /> instead.
  </para>
 
- <para>
-  If you are building <productname>PostgreSQL</productname> for Microsoft
-  Windows, read this chapter if you intend to build with MinGW or Cygwin;
-  but if you intend to build with Microsoft's <productname>Visual
-  C++</productname>, see <xref linkend="install-windows"/> instead.
- </para>
-
  <sect1 id="install-requirements">
   <title>Requirements</title>
 
@@ -3531,8 +3524,7 @@ ERROR:  could not load library "/opt/dbs/pgsql/lib/plperl.so": Bad address
    <para>
     PostgreSQL can be built using Cygwin, a Linux-like environment for
     Windows, but that method is inferior to the native Windows build
-    <phrase condition="standalone-ignore">(see <xref linkend="install-windows"/>)</phrase> and
-    running a server under Cygwin is no longer recommended.
+    and running a server under Cygwin is no longer recommended.
    </para>
 
    <para>
@@ -3698,7 +3690,7 @@ xcrun --show-sdk-path
   </sect2>
 
   <sect2 id="installation-notes-mingw">
-   <title>MinGW/Native Windows</title>
+   <title>MinGW</title>
 
    <indexterm zone="installation-notes-mingw">
     <primary>MinGW</primary>
@@ -3707,18 +3699,13 @@ xcrun --show-sdk-path
 
    <para>
     PostgreSQL for Windows can be built using MinGW, a Unix-like build
-    environment for Microsoft operating systems, or using
-    Microsoft's <productname>Visual C++</productname> compiler suite.
+    environment for Microsoft operating systems.
     The MinGW build procedure uses the normal build system described in
-    this chapter; the Visual C++ build works completely differently
-    and is described in <xref linkend="install-windows"/>.
+    this chapter.
    </para>
 
    <para>
-    The native Windows port requires a 32 or 64-bit version of Windows
-    2000 or later. Earlier operating systems do
-    not have sufficient infrastructure (but Cygwin may be used on
-    those).  MinGW, the Unix-like build tools, and MSYS, a collection
+    MinGW, the Unix-like build tools, and MSYS, a collection
     of Unix tools required to run shell scripts
     like <command>configure</command>, can be downloaded
     from <ulink url="http://www.mingw.org/"></ulink>.  Neither is
@@ -3741,8 +3728,8 @@ xcrun --show-sdk-path
     buffering issues.
    </para>
 
-   <sect3 id="windows-crash-dumps">
-    <title>Collecting Crash Dumps on Windows</title>
+   <sect3 id="mingw-crash-dumps">
+    <title>Collecting Crash Dumps</title>
 
     <para>
      If PostgreSQL on Windows crashes, it has the ability to generate
@@ -3861,6 +3848,293 @@ make: *** [postgres] Error 1
     </para>
    </sect3>
   </sect2>
+
+  <sect2 id="installation-notes-visual">
+   <title>Visual</title>
+
+   <indexterm zone="installation-notes-visual">
+    <primary>Visual</primary>
+    <secondary>installation on</secondary>
+   </indexterm>
+
+   <para>
+    It is recommended that most users download the binary distribution for
+    Windows, available as a graphical installer package from the
+    <productname>PostgreSQL</productname> website at
+    <ulink url="https://www.postgresql.org/download/"></ulink>. Building from
+    source is only intended for people developing
+    <productname>PostgreSQL</productname> or extensions.
+   </para>
+
+   <para>
+    PostgreSQL for Windows with Visual can be built using meson, as described
+    in <xref linkend="install-meson"/>.
+    The native Windows port requires a 32 or 64-bit version of Windows
+    10 or later.
+   </para>
+
+   <para>
+    Native builds of <application>psql</application> don't support command
+    line editing. The <productname>Cygwin</productname> build does support
+    command line editing, so it should be used where psql is needed for
+    interactive use on <productname>Windows</productname>.
+   </para>
+
+   <para>
+    PostgreSQL can be built using the Visual C++ compiler suite from Microsoft.
+    These compilers can be either from <productname>Visual Studio</productname>,
+    <productname>Visual Studio Express</productname> or some versions of the
+    <productname>Microsoft Windows SDK</productname>. If you do not already have a
+    <productname>Visual Studio</productname> environment set up, the easiest
+    ways are to use the compilers from
+    <productname>Visual Studio 2022</productname> or those in the
+    <productname>Windows SDK 10</productname>, which are both free downloads
+    from Microsoft.
+   </para>
+
+   <para>
+    Both 32-bit and 64-bit builds are possible with the Microsoft Compiler suite.
+    32-bit PostgreSQL builds are possible with
+    <productname>Visual Studio 2015</productname> to
+    <productname>Visual Studio 2022</productname>,
+    as well as standalone Windows SDK releases 10 and above.
+    64-bit PostgreSQL builds are supported with
+    <productname>Microsoft Windows SDK</productname> version 10 and above or
+    <productname>Visual Studio 2015</productname> and above.
+    <!--
+        For 2015 requirements:
+        https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2015-sysrequirements-vs
+        For 2017 requirements:
+        https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2017-system-requirements-vs
+        For 2019 requirements:
+        https://docs.microsoft.com/en-us/visualstudio/releases/2019/system-requirements
+        For 2022 requirements:
+        https://docs.microsoft.com/en-us/visualstudio/releases/2022/system-requirements
+    -->
+   </para>
+
+   <para>
+    If your build environment doesn't ship with a supported version of the
+    <productname>Microsoft Windows SDK</productname> it is recommended
+    that you upgrade to the latest version (currently version 10), available
+    for download from <ulink url="https://www.microsoft.com/download"></ulink>.
+   </para>
+
+   <para>
+    You must always include the
+    <application>Windows Headers and Libraries</application> part of the SDK.
+    If you install a <productname>Windows SDK</productname>
+    including the <application>Visual C++ Compilers</application>,
+    you don't need <productname>Visual Studio</productname> to build.
+    Note that as of Version 8.0a the Windows SDK no longer ships with a
+    complete command-line build environment.
+   </para>
+
+   <sect3 id="windows-requirements">
+    <title>Requirements</title>
+    <para>
+     The following additional products are required to build
+     <productname>PostgreSQL</productname> on Windows.
+
+     <variablelist>
+      <varlistentry>
+       <term><productname>ActiveState Perl</productname></term>
+       <listitem><para>
+        ActiveState Perl is required to run the build generation scripts. MinGW
+        or Cygwin Perl will not work. It must also be present in the PATH.
+        Binaries can be downloaded from
+        <ulink url="https://www.activestate.com"></ulink>
+        (Note: version 5.14 or later is required,
+        the free Standard Distribution is sufficient).
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>Bison</productname> and
+        <productname>Flex</productname></term>
+       <listitem>
+       <para>
+        <productname>Bison</productname> and <productname>Flex</productname> are
+        required.  Only <productname>Bison</productname> versions 2.3 and later
+        will work. <productname>Flex</productname> must be version 2.5.35 or later.
+       </para>
+
+       <para>
+        Both <productname>Bison</productname> and <productname>Flex</productname>
+        are included in the <productname>msys</productname> tool suite, available
+        from <ulink url="http://www.mingw.org/wiki/MSYS"></ulink> as part of the
+        <productname>MinGW</productname> compiler suite.
+       </para>
+
+       <para>
+        You will need to add the directory containing
+        <filename>flex.exe</filename> and <filename>bison.exe</filename> to the
+        PATH environment variable. In the case of MinGW, the directory is the
+        <filename>\msys\1.0\bin</filename> subdirectory of your MinGW
+        installation directory.
+       </para>
+
+       <note>
+        <para>
+          The Bison distribution from GnuWin32 appears to have a bug that
+          causes Bison to malfunction when installed in a directory with
+          spaces in the name, such as the default location on English
+          installations <filename>C:\Program Files\GnuWin32</filename>.
+          Consider installing into <filename>C:\GnuWin32</filename> or use the
+          NTFS short name path to GnuWin32 in your PATH environment setting
+          (e.g., <filename>C:\PROGRA~1\GnuWin32</filename>).
+         </para>
+       </note>
+
+       </listitem>
+      </varlistentry>
+     </variablelist>
+    </para>
+
+    <para>
+     The following additional products are not required to get started,
+     but are required to build the complete package.
+
+     <variablelist>
+      <varlistentry>
+       <term><productname>ActiveState Tcl</productname></term>
+       <listitem><para>
+        Required for building <application>PL/Tcl</application> (Note: version
+        8.4 is required, the free Standard Distribution is sufficient).
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>Diff</productname></term>
+       <listitem><para>
+        Diff is required to run the regression tests, and can be downloaded
+        from <ulink url="http://gnuwin32.sourceforge.net"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>Gettext</productname></term>
+       <listitem><para>
+        Gettext is required to build with NLS support, and can be downloaded
+        from <ulink url="http://gnuwin32.sourceforge.net"></ulink>. Note that binaries,
+        dependencies and developer files are all needed.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>MIT Kerberos</productname></term>
+       <listitem><para>
+        Required for GSSAPI authentication support. MIT Kerberos can be
+        downloaded from
+        <ulink url="https://web.mit.edu/Kerberos/dist/index.html"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>libxml2</productname> and
+        <productname>libxslt</productname></term>
+       <listitem><para>
+        Required for XML support. Binaries can be downloaded from
+        <ulink url="https://zlatkovic.com/pub/libxml"></ulink> or source from
+        <ulink url="http://xmlsoft.org"></ulink>. Note that libxml2 requires iconv,
+        which is available from the same download location.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>LZ4</productname></term>
+       <listitem><para>
+        Required for supporting <productname>LZ4</productname> compression.
+        Binaries and source can be downloaded from
+        <ulink url="https://github.com/lz4/lz4/releases"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>Zstandard</productname></term>
+       <listitem><para>
+        Required for supporting <productname>Zstandard</productname> compression.
+        Binaries and source can be downloaded from
+        <ulink url="https://github.com/facebook/zstd/releases"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>OpenSSL</productname></term>
+       <listitem><para>
+        Required for SSL support. Binaries can be downloaded from
+        <ulink url="https://slproweb.com/products/Win32OpenSSL.html"></ulink>
+        or source from <ulink url="https://www.openssl.org"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>ossp-uuid</productname></term>
+       <listitem><para>
+        Required for UUID-OSSP support (contrib only). Source can be
+        downloaded from
+        <ulink url="http://www.ossp.org/pkg/lib/uuid/"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>Python</productname></term>
+       <listitem><para>
+        Required for building <application>PL/Python</application>. Binaries can
+        be downloaded from <ulink url="https://www.python.org"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+       <term><productname>zlib</productname></term>
+       <listitem><para>
+        Required for compression support in <application>pg_dump</application>
+        and <application>pg_restore</application>. Binaries can be downloaded
+        from <ulink url="https://www.zlib.net"></ulink>.
+       </para></listitem>
+      </varlistentry>
+
+     </variablelist>
+    </para>
+   </sect3>
+
+   <sect3 id="install-windows-full-64-bit">
+    <title>Special Considerations for 64-Bit Windows</title>
+    <para>
+     PostgreSQL will only build for the x64 architecture on 64-bit Windows.
+    </para>
+    <para>
+     Mixing 32- and 64-bit versions in the same build tree is not supported.
+     The build system will automatically detect if it's running in a 32- or
+     64-bit environment, and build PostgreSQL accordingly. For this reason, it
+     is important to start the correct command prompt before building.
+    </para>
+    <para>
+     To use a server-side third party library such as <productname>Python</productname> or
+     <productname>OpenSSL</productname>, this library <emphasis>must</emphasis> also be
+     64-bit. There is no support for loading a 32-bit library in a 64-bit
+     server. Several of the third party libraries that PostgreSQL supports may
+     only be available in 32-bit versions, in which case they cannot be used with
+     64-bit PostgreSQL.
+    </para>
+   </sect3>
+
+   <sect3 id="windows-crash-dumps">
+    <title>Collecting Crash Dumps</title>
+
+    <para>
+     If PostgreSQL on Windows crashes, it has the ability to generate
+     <productname>minidumps</productname> that can be used to track down the cause
+     for the crash, similar to core dumps on Unix. These dumps can be
+     read using the <productname>Windows Debugger Tools</productname> or using
+     <productname>Visual Studio</productname>. To enable the generation of dumps
+     on Windows, create a subdirectory named <filename>crashdumps</filename>
+     inside the cluster data directory. The dumps will then be written
+     into this directory with a unique name based on the identifier of
+     the crashing process and the current time of the crash.
+    </para>
+   </sect3>
+  </sect2>
  </sect1>
 
 </chapter>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index f31dc2094a..2c107199d3 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -152,7 +152,6 @@ break is not needed in a wider output rendering.
 
   &installbin;
   &installation;
-  &installw;
   &runtime;
   &config;
   &client-auth;
diff --git a/doc/src/sgml/standalone-profile.xsl b/doc/src/sgml/standalone-profile.xsl
index 1b3938a638..e726ee61a2 100644
--- a/doc/src/sgml/standalone-profile.xsl
+++ b/doc/src/sgml/standalone-profile.xsl
@@ -60,10 +60,6 @@ variant without links and references to the main documentation.
   <xsl:text>the configuration parameter wal_compression</xsl:text>
 </xsl:template>
 
-<xsl:template match="xref[@linkend='install-windows']">
-  <xsl:text>the documentation</xsl:text>
-</xsl:template>
-
 <xsl:template match="xref[@linkend='locale-providers']">
   <xsl:text>the documentation</xsl:text>
 </xsl:template>
diff --git a/meson.build b/meson.build
index 286d7e4269..00b3288465 100644
--- a/meson.build
+++ b/meson.build
@@ -1877,7 +1877,6 @@ foreach w : negative_warning_flags
 endforeach
 
 
-# From Project.pm
 if cc.get_id() == 'msvc'
   cflags_warn += [
     '/wd4018', # signed/unsigned mismatch
diff --git a/src/tools/msvc/.gitignore b/src/tools/msvc/.gitignore
deleted file mode 100644
index 2470e7850d..0000000000
--- a/src/tools/msvc/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Custom configuration files for MSVC build
-/config.pl
-/buildenv.pl
diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm
deleted file mode 100644
index b6dd2c3bba..0000000000
--- a/src/tools/msvc/Install.pm
+++ /dev/null
@@ -1,748 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Install;
-
-#
-# Package that provides 'make install' functionality for msvc builds
-#
-# src/tools/msvc/Install.pm
-#
-use strict;
-use warnings;
-use Carp;
-use File::Basename;
-use File::Copy;
-use File::Find ();
-
-use Exporter;
-our (@ISA, @EXPORT_OK);
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(Install);
-
-my $insttype;
-my @client_contribs = ('oid2name', 'pgbench', 'vacuumlo');
-my @client_program_files = (
-	'clusterdb', 'createdb', 'createuser', 'dropdb',
-	'dropuser', 'ecpg', 'libecpg', 'libecpg_compat',
-	'libpgtypes', 'libpq', 'pg_amcheck', 'pg_basebackup',
-	'pg_config', 'pg_dump', 'pg_dumpall', 'pg_isready',
-	'pg_receivewal', 'pg_recvlogical', 'pg_restore', 'psql',
-	'reindexdb', 'vacuumdb', @client_contribs);
-
-sub lcopy
-{
-	my $src = shift;
-	my $target = shift;
-
-	if (-f $target)
-	{
-		unlink $target || confess "Could not delete $target\n";
-	}
-
-	(my $retval = copy($src, $target))
-	  || confess "Could not copy $src to $target\n";
-
-	return $retval;
-}
-
-sub Install
-{
-	$| = 1;
-
-	my $target = shift;
-	$insttype = shift;
-	$insttype = "all" unless ($insttype);
-
-	# if called from vcregress, the config will be passed to us
-	# so no need to re-include these
-	our $config = shift;
-	unless ($config)
-	{
-
-		# suppress warning about harmless redeclaration of $config
-		no warnings 'misc';
-		do "./config_default.pl";
-		do "./config.pl" if (-f "config.pl");
-	}
-
-	# Move to the root path depending on the current location.
-	if (-f "../../../configure")
-	{
-		chdir("../../..");
-	}
-	elsif (-f "../../../../configure")
-	{
-		chdir("../../../..");
-	}
-
-	my $conf = "";
-	if (-d "debug")
-	{
-		$conf = "debug";
-	}
-	if (-d "release")
-	{
-		$conf = "release";
-	}
-	die "Could not find debug or release binaries" if ($conf eq "");
-	my $majorver = DetermineMajorVersion();
-	print "Installing version $majorver for $conf in $target\n";
-
-	my @client_dirs = ('bin', 'lib', 'share', 'symbols');
-	my @all_dirs = (
-		@client_dirs, 'doc', 'doc/contrib', 'doc/extension', 'share/contrib',
-		'share/extension', 'share/timezonesets', 'share/tsearch_data');
-	if ($insttype eq "client")
-	{
-		EnsureDirectories($target, @client_dirs);
-	}
-	else
-	{
-		EnsureDirectories($target, @all_dirs);
-	}
-
-	CopySolutionOutput($conf, $target);
-	my $sample_files = [];
-	my @top_dir = ("src");
-	@top_dir = ("src\\bin", "src\\interfaces") if ($insttype eq "client");
-	File::Find::find(
-		{
-			wanted => sub {
-				/^.*\.sample\z/s
-				  && push(@$sample_files, $File::Find::name);
-
-				# Don't find files of in-tree temporary installations.
-				$_ eq 'share' and $File::Find::prune = 1;
-			}
-		},
-		@top_dir);
-	CopySetOfFiles('config files', $sample_files, $target . '/share/');
-	CopyFiles(
-		'Import libraries',
-		$target . '/lib/',
-		"$conf\\", "postgres\\postgres.lib", "libpgcommon\\libpgcommon.lib",
-		"libpgport\\libpgport.lib");
-	CopyContribFiles($config, $target);
-	CopyIncludeFiles($target);
-
-	if ($insttype ne "client")
-	{
-		CopySetOfFiles(
-			'timezone names',
-			[ glob('src\timezone\tznames\*.txt') ],
-			$target . '/share/timezonesets/');
-		CopyFiles(
-			'timezone sets',
-			$target . '/share/timezonesets/',
-			'src/timezone/tznames/', 'Default', 'Australia', 'India');
-		CopySetOfFiles(
-			'BKI files',
-			[ glob("src\\backend\\catalog\\postgres.*") ],
-			$target . '/share/');
-		CopySetOfFiles(
-			'SQL files',
-			[ glob("src\\backend\\catalog\\*.sql") ],
-			$target . '/share/');
-		CopyFiles(
-			'Information schema data', $target . '/share/',
-			'src/backend/catalog/', 'sql_features.txt');
-		CopyFiles(
-			'Error code data', $target . '/share/',
-			'src/backend/utils/', 'errcodes.txt');
-		GenerateTimezoneFiles($target, $conf);
-		GenerateTsearchFiles($target);
-		CopySetOfFiles(
-			'Stopword files',
-			[ glob("src\\backend\\snowball\\stopwords\\*.stop") ],
-			$target . '/share/tsearch_data/');
-		CopySetOfFiles(
-			'Dictionaries sample files',
-			[ glob("src\\backend\\tsearch\\dicts\\*_sample*") ],
-			$target . '/share/tsearch_data/');
-
-		my $pl_extension_files = [];
-		my @pldirs = ('src/pl/plpgsql/src');
-		push @pldirs, "src/pl/plperl" if $config->{perl};
-		push @pldirs, "src/pl/plpython" if $config->{python};
-		push @pldirs, "src/pl/tcl" if $config->{tcl};
-		File::Find::find(
-			{
-				wanted => sub {
-					/^(.*--.*\.sql|.*\.control)\z/s
-					  && push(@$pl_extension_files, $File::Find::name);
-
-					# Don't find files of in-tree temporary installations.
-					$_ eq 'share' and $File::Find::prune = 1;
-				}
-			},
-			@pldirs);
-		CopySetOfFiles('PL Extension files',
-			$pl_extension_files, $target . '/share/extension/');
-	}
-
-	GenerateNLSFiles($target, $config->{nls}, $majorver) if ($config->{nls});
-
-	print "Installation complete.\n";
-	return;
-}
-
-sub EnsureDirectories
-{
-	my $target = shift;
-	mkdir $target unless -d ($target);
-	while (my $d = shift)
-	{
-		mkdir $target . '/' . $d unless -d ($target . '/' . $d);
-	}
-	return;
-}
-
-sub CopyFiles
-{
-	my $what = shift;
-	my $target = shift;
-	my $basedir = shift;
-
-	print "Copying $what";
-	while (my $f = shift)
-	{
-		print ".";
-		$f = $basedir . $f;
-		die "No file $f\n" if (!-f $f);
-		lcopy($f, $target . basename($f)) || croak "Could not copy $f: $!\n";
-	}
-	print "\n";
-	return;
-}
-
-sub CopySetOfFiles
-{
-	my $what = shift;
-	my $flist = shift;
-	my $target = shift;
-	print "Copying $what" if $what;
-	foreach (@$flist)
-	{
-		my $tgt = $target . basename($_);
-		print ".";
-		lcopy($_, $tgt) || croak "Could not copy $_: $!\n";
-	}
-	print "\n";
-	return;
-}
-
-sub CopySolutionOutput
-{
-	my $conf = shift;
-	my $target = shift;
-	my $rem =
-	  qr{Project\("\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942\}"\) = "([^"]+)"};
-
-	my $sln = read_file("pgsql.sln") || croak "Could not open pgsql.sln\n";
-
-	my $vcproj = 'vcproj';
-	if ($sln =~
-		/Microsoft Visual Studio Solution File, Format Version (\d+)\.\d+/
-		&& $1 >= 11)
-	{
-		$vcproj = 'vcxproj';
-	}
-
-	print "Copying build output files...";
-	while ($sln =~ $rem)
-	{
-		my $pf = $1;
-
-		# Hash-of-arrays listing where to install things.  For each
-		# subdirectory there's a hash key, and the value is an array
-		# of file extensions to install in that subdirectory.  Example:
-		# { 'bin' => [ 'dll', 'lib' ],
-		#   'lib' => [ 'lib' ] }
-		my %install_list;
-		my $is_sharedlib = 0;
-
-		$sln =~ s/$rem//;
-
-		next
-		  if ($insttype eq "client" && !grep { $_ eq $pf }
-			@client_program_files);
-
-		my $proj = read_file("$pf.$vcproj")
-		  || croak "Could not open $pf.$vcproj\n";
-
-		# Check if this project uses a shared library by looking if
-		# SO_MAJOR_VERSION is defined in its Makefile, whose path
-		# can be found using the resource file of this project.
-		if ((      $vcproj eq 'vcxproj'
-				&& $proj =~ qr{ResourceCompile\s*Include="([^"]+)"})
-			|| (   $vcproj eq 'vcproj'
-				&& $proj =~ qr{File\s*RelativePath="([^\"]+)\.rc"}))
-		{
-			my $projpath = dirname($1);
-			my $mfname =
-			  -e "$projpath/GNUmakefile"
-			  ? "$projpath/GNUmakefile"
-			  : "$projpath/Makefile";
-			my $mf = read_file($mfname) || croak "Could not open $mfname\n";
-
-			$is_sharedlib = 1 if ($mf =~ /^SO_MAJOR_VERSION\s*=\s*(.*)$/mg);
-		}
-
-		if ($vcproj eq 'vcproj' && $proj =~ qr{ConfigurationType="([^"]+)"})
-		{
-			if ($1 == 1)
-			{
-				push(@{ $install_list{'bin'} }, "exe");
-			}
-			elsif ($1 == 2)
-			{
-				push(@{ $install_list{'lib'} }, "dll");
-				if ($is_sharedlib)
-				{
-					push(@{ $install_list{'bin'} }, "dll");
-					push(@{ $install_list{'lib'} }, "lib");
-				}
-			}
-			else
-			{
-
-				# Static libraries, such as libpgport, only used internally
-				# during build, don't install.
-				next;
-			}
-		}
-		elsif ($vcproj eq 'vcxproj'
-			&& $proj =~ qr{<ConfigurationType>(\w+)</ConfigurationType>})
-		{
-			if ($1 eq 'Application')
-			{
-				push(@{ $install_list{'bin'} }, "exe");
-			}
-			elsif ($1 eq 'DynamicLibrary')
-			{
-				push(@{ $install_list{'lib'} }, "dll");
-				if ($is_sharedlib)
-				{
-					push(@{ $install_list{'bin'} }, "dll");
-					push(@{ $install_list{'lib'} }, "lib");
-				}
-			}
-			else    # 'StaticLibrary'
-			{
-
-				# Static lib, such as libpgport, only used internally
-				# during build, don't install.
-				next;
-			}
-		}
-		else
-		{
-			croak "Could not parse $pf.$vcproj\n";
-		}
-
-		# Install each element
-		foreach my $dir (keys %install_list)
-		{
-			foreach my $ext (@{ $install_list{$dir} })
-			{
-				lcopy("$conf\\$pf\\$pf.$ext", "$target\\$dir\\$pf.$ext")
-				  || croak "Could not copy $pf.$ext\n";
-			}
-		}
-		lcopy("$conf\\$pf\\$pf.pdb", "$target\\symbols\\$pf.pdb")
-		  || croak "Could not copy $pf.pdb\n";
-		print ".";
-	}
-	print "\n";
-	return;
-}
-
-sub GenerateTimezoneFiles
-{
-	my $target = shift;
-	my $conf = shift;
-	my $mf = read_file("src/timezone/Makefile");
-	$mf =~ s{\\\r?\n}{}g;
-
-	$mf =~ /^TZDATAFILES\s*:?=\s*(.*)$/m
-	  || die "Could not find TZDATAFILES line in timezone makefile\n";
-	my @tzfiles = split /\s+/, $1;
-
-	print "Generating timezone files...";
-
-	my @args = ("$conf/zic/zic", '-d', "$target/share/timezone");
-	foreach (@tzfiles)
-	{
-		my $tzfile = $_;
-		$tzfile =~ s|\$\(srcdir\)|src/timezone|;
-		push(@args, $tzfile);
-	}
-
-	system(@args);
-	print "\n";
-	return;
-}
-
-sub GenerateTsearchFiles
-{
-	my $target = shift;
-
-	print "Generating tsearch script...";
-	system(
-		'perl', 'src/backend/snowball/snowball_create.pl',
-		'--input', 'src/backend/snowball/',
-		'--outdir', "$target/share/");
-	print "\n";
-	return;
-}
-
-sub CopyContribFiles
-{
-	my $config = shift;
-	my $target = shift;
-
-	print "Copying contrib data files...";
-	foreach my $subdir ('contrib', 'src/test/modules')
-	{
-		my $D;
-		opendir($D, $subdir) || croak "Could not opendir on $subdir!\n";
-		while (my $d = readdir($D))
-		{
-			# These configuration-based exclusions must match vcregress.pl
-			next if ($d eq "uuid-ossp" && !defined($config->{uuid}));
-			next if ($d eq "sslinfo" && !defined($config->{openssl}));
-			next if ($d eq "pgcrypto" && !defined($config->{openssl}));
-			next if ($d eq "xml2" && !defined($config->{xml}));
-			next if ($d =~ /_plperl$/ && !defined($config->{perl}));
-			next if ($d =~ /_plpython$/ && !defined($config->{python}));
-			next if ($d eq "sepgsql");
-
-			CopySubdirFiles($subdir, $d, $config, $target);
-		}
-	}
-	print "\n";
-	return;
-}
-
-sub CopySubdirFiles
-{
-	my $subdir = shift;
-	my $module = shift;
-	my $config = shift;
-	my $target = shift;
-
-	return if ($module =~ /^\./);
-	return unless (-f "$subdir/$module/Makefile");
-	return
-	  if ($insttype eq "client" && !grep { $_ eq $module } @client_contribs);
-
-	my $mf = read_file("$subdir/$module/Makefile");
-	$mf =~ s{\\\r?\n}{}g;
-
-	# Note: we currently don't support setting MODULEDIR in the makefile
-	my $moduledir = 'contrib';
-
-	my $flist = '';
-	if ($mf =~ /^EXTENSION\s*=\s*(.*)$/m) { $flist .= $1 }
-	if ($flist ne '')
-	{
-		$moduledir = 'extension';
-		$flist = ParseAndCleanRule($flist, $mf);
-
-		foreach my $f (split /\s+/, $flist)
-		{
-			lcopy("$subdir/$module/$f.control",
-				"$target/share/extension/$f.control")
-			  || croak("Could not copy file $f.control in contrib $module");
-			print '.';
-		}
-	}
-
-	$flist = '';
-	if ($mf =~ /^DATA_built\s*=\s*(.*)$/m) { $flist .= $1 }
-	if ($mf =~ /^DATA\s*=\s*(.*)$/m)       { $flist .= " $1" }
-	$flist =~ s/^\s*//;    # Remove leading spaces if we had only DATA_built
-
-	if ($flist ne '')
-	{
-		$flist = ParseAndCleanRule($flist, $mf);
-
-		foreach my $f (split /\s+/, $flist)
-		{
-			lcopy("$subdir/$module/$f",
-				"$target/share/$moduledir/" . basename($f))
-			  || croak("Could not copy file $f in contrib $module");
-			print '.';
-		}
-	}
-
-	$flist = '';
-	if ($mf =~ /^DATA_TSEARCH\s*=\s*(.*)$/m) { $flist .= $1 }
-	if ($flist ne '')
-	{
-		$flist = ParseAndCleanRule($flist, $mf);
-
-		foreach my $f (split /\s+/, $flist)
-		{
-			lcopy("$subdir/$module/$f",
-				"$target/share/tsearch_data/" . basename($f))
-			  || croak("Could not copy file $f in $subdir $module");
-			print '.';
-		}
-	}
-
-	{
-		$flist = '';
-		if ($mf =~ /^HEADERS\s*=\s*(.*)$/m) { $flist .= $1 }
-		my @modlist = ();
-		my %fmodlist = ();
-		while ($mf =~ /^HEADERS_([^\s=]+)\s*=\s*(.*)$/mg)
-		{
-			$fmodlist{$1} .= $2;
-		}
-
-		if ($mf =~ /^MODULE_big\s*=\s*(.*)$/m)
-		{
-			push @modlist, $1;
-			if ($flist ne '')
-			{
-				$fmodlist{$1} = $flist;
-				$flist = '';
-			}
-		}
-		elsif ($mf =~ /^MODULES\s*=\s*(.*)$/m)
-		{
-			push @modlist, split /\s+/, $1;
-		}
-
-		croak "HEADERS requires MODULE_big in $subdir $module"
-		  if $flist ne '';
-
-		foreach my $mod (keys %fmodlist)
-		{
-			croak "HEADERS_$mod for unknown module in $subdir $module"
-			  unless grep { $_ eq $mod } @modlist;
-			$flist = ParseAndCleanRule($fmodlist{$mod}, $mf);
-			EnsureDirectories($target, "include", "include/server",
-				"include/server/$moduledir",
-				"include/server/$moduledir/$mod");
-			foreach my $f (split /\s+/, $flist)
-			{
-				lcopy("$subdir/$module/$f",
-					"$target/include/server/$moduledir/$mod/" . basename($f))
-				  || croak("Could not copy file $f in $subdir $module");
-				print '.';
-			}
-		}
-	}
-
-	$flist = '';
-	if ($mf =~ /^DOCS\s*=\s*(.*)$/mg) { $flist .= $1 }
-	if ($flist ne '')
-	{
-		$flist = ParseAndCleanRule($flist, $mf);
-
-		# Special case for contrib/spi
-		$flist =
-		  "autoinc.example insert_username.example moddatetime.example refint.example"
-		  if ($module eq 'spi');
-		foreach my $f (split /\s+/, $flist)
-		{
-			lcopy("$subdir/$module/$f", "$target/doc/$moduledir/$f")
-			  || croak("Could not copy file $f in contrib $module");
-			print '.';
-		}
-	}
-	return;
-}
-
-sub ParseAndCleanRule
-{
-	my $flist = shift;
-	my $mf = shift;
-
-	# Strip out $(addsuffix) rules
-	if (index($flist, '$(addsuffix ') >= 0)
-	{
-		my $pcount = 0;
-		my $i;
-		for (
-			$i = index($flist, '$(addsuffix ') + 12;
-			$i < length($flist);
-			$i++)
-		{
-			$pcount++ if (substr($flist, $i, 1) eq '(');
-			$pcount-- if (substr($flist, $i, 1) eq ')');
-			last if ($pcount < 0);
-		}
-		$flist =
-			substr($flist, 0, index($flist, '$(addsuffix '))
-		  . substr($flist, $i + 1);
-	}
-	return $flist;
-}
-
-sub CopyIncludeFiles
-{
-	my $target = shift;
-
-	EnsureDirectories($target, 'include', 'include/libpq', 'include/internal',
-		'include/internal/libpq', 'include/server', 'include/server/parser');
-
-	CopyFiles(
-		'Public headers', $target . '/include/',
-		'src/include/', 'postgres_ext.h',
-		'pg_config.h', 'pg_config_ext.h',
-		'pg_config_os.h', 'pg_config_manual.h');
-	lcopy('src/include/libpq/libpq-fs.h', $target . '/include/libpq/')
-	  || croak 'Could not copy libpq-fs.h';
-
-	CopyFiles(
-		'Libpq headers',
-		$target . '/include/',
-		'src/interfaces/libpq/', 'libpq-fe.h', 'libpq-events.h');
-	CopyFiles(
-		'Libpq internal headers',
-		$target . '/include/internal/',
-		'src/interfaces/libpq/', 'libpq-int.h', 'fe-auth-sasl.h',
-		'pqexpbuffer.h');
-
-	CopyFiles(
-		'Internal headers',
-		$target . '/include/internal/',
-		'src/include/', 'c.h', 'port.h', 'postgres_fe.h');
-	lcopy('src/include/libpq/pqcomm.h', $target . '/include/internal/libpq/')
-	  || croak 'Could not copy pqcomm.h';
-	lcopy('src/include/libpq/protocol.h', $target . '/include/internal/libpq/')
-	  || croak 'Could not copy protocol.h';
-
-	CopyFiles(
-		'Server headers',
-		$target . '/include/server/',
-		'src/include/', 'pg_config.h', 'pg_config_ext.h', 'pg_config_os.h');
-	CopySetOfFiles(
-		'',
-		[ glob("src\\include\\*.h") ],
-		$target . '/include/server/');
-	my $D;
-	opendir($D, 'src/include') || croak "Could not opendir on src/include!\n";
-
-	CopyFiles(
-		'PL/pgSQL header',
-		$target . '/include/server/',
-		'src/pl/plpgsql/src/', 'plpgsql.h');
-
-	# some xcopy progs don't like mixed slash style paths
-	(my $ctarget = $target) =~ s!/!\\!g;
-	while (my $d = readdir($D))
-	{
-		next if ($d =~ /^\./);
-		next if ($d eq '.git');
-		next if ($d eq 'CVS');
-		next unless (-d "src/include/$d");
-
-		EnsureDirectories("$target/include/server/$d");
-		my @args = (
-			'xcopy', '/s', '/i', '/q', '/r', '/y', "src\\include\\$d\\*.h",
-			"$ctarget\\include\\server\\$d\\");
-		system(@args) && croak("Failed to copy include directory $d\n");
-	}
-	closedir($D);
-
-	my $mf = read_file('src/interfaces/ecpg/include/Makefile');
-	$mf =~ s{\\\r?\n}{}g;
-	$mf =~ /^ecpg_headers\s*=\s*(.*)$/m
-	  || croak "Could not find ecpg_headers line\n";
-	CopyFiles(
-		'ECPG headers',
-		$target . '/include/',
-		'src/interfaces/ecpg/include/',
-		'ecpg_config.h', split /\s+/, $1);
-	$mf =~ /^informix_headers\s*=\s*(.*)$/m
-	  || croak "Could not find informix_headers line\n";
-	EnsureDirectories($target . '/include', 'informix', 'informix/esql');
-	CopyFiles(
-		'ECPG informix headers',
-		$target . '/include/informix/esql/',
-		'src/interfaces/ecpg/include/',
-		split /\s+/, $1);
-	return;
-}
-
-sub GenerateNLSFiles
-{
-	my $target = shift;
-	my $nlspath = shift;
-	my $majorver = shift;
-
-	print "Installing NLS files...";
-	EnsureDirectories($target, "share/locale");
-	my @flist;
-	File::Find::find(
-		{
-			wanted => sub {
-				/^nls\.mk\z/s
-				  && !push(@flist, $File::Find::name);
-			}
-		},
-		"src");
-	foreach (@flist)
-	{
-		my $prgm = DetermineCatalogName($_);
-		s/nls.mk/po/;
-		my $dir = $_;
-		next unless ($dir =~ /([^\/]+)\/po$/);
-		foreach (glob("$dir/*.po"))
-		{
-			my $lang;
-			next unless /([^\/]+)\.po/;
-			$lang = $1;
-
-			EnsureDirectories($target, "share/locale/$lang",
-				"share/locale/$lang/LC_MESSAGES");
-			my @args = (
-				"$nlspath\\bin\\msgfmt",
-				'-o',
-				"$target\\share\\locale\\$lang\\LC_MESSAGES\\$prgm-$majorver.mo",
-				$_);
-			system(@args) && croak("Could not run msgfmt on $dir\\$_");
-			print ".";
-		}
-	}
-	print "\n";
-	return;
-}
-
-sub DetermineMajorVersion
-{
-	my $f = read_file('src/include/pg_config.h')
-	  || croak 'Could not open pg_config.h';
-	$f =~ /^#define\s+PG_MAJORVERSION\s+"([^"]+)"/m
-	  || croak 'Could not determine major version';
-	return $1;
-}
-
-sub DetermineCatalogName
-{
-	my $filename = shift;
-
-	my $f = read_file($filename) || croak "Could not open $filename";
-	$f =~ /CATALOG_NAME\s*\:?=\s*(\S+)/m
-	  || croak "Could not determine catalog name in $filename";
-	return $1;
-}
-
-sub read_file
-{
-	my $filename = shift;
-	my $F;
-	local $/ = undef;
-	open($F, '<', $filename) || die "Could not open file $filename\n";
-	my $txt = <$F>;
-	close($F);
-
-	return $txt;
-}
-
-1;
diff --git a/src/tools/msvc/MSBuildProject.pm b/src/tools/msvc/MSBuildProject.pm
deleted file mode 100644
index 62fec1fee5..0000000000
--- a/src/tools/msvc/MSBuildProject.pm
+++ /dev/null
@@ -1,508 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package MSBuildProject;
-
-#
-# Package that encapsulates a MSBuild project file (Visual C++ 2015 or greater)
-#
-# src/tools/msvc/MSBuildProject.pm
-#
-
-use Carp;
-use strict;
-use warnings;
-use base qw(Project);
-
-no warnings qw(redefine);    ## no critic
-
-sub _new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{filenameExtension} = '.vcxproj';
-	$self->{ToolsVersion} = '4.0';
-
-	return $self;
-}
-
-sub WriteHeader
-{
-	my ($self, $f) = @_;
-
-	print $f <<EOF;
-<?xml version="1.0" encoding="Windows-1252"?>
-<Project DefaultTargets="Build" ToolsVersion="$self->{ToolsVersion}" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-EOF
-	$self->WriteConfigurationHeader($f, 'Debug');
-	$self->WriteConfigurationHeader($f, 'Release');
-	print $f <<EOF;
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>$self->{guid}</ProjectGuid>
-EOF
-	# Check whether WindowsSDKVersion env variable is present.
-	# Add WindowsTargetPlatformVersion node if so.
-	my $sdkVersion = $ENV{'WindowsSDKVersion'};
-	if (defined($sdkVersion))
-	{
-		# remove trailing backslash if necessary.
-		$sdkVersion =~ s/\\$//;
-		print $f <<EOF;
-    <WindowsTargetPlatformVersion>$sdkVersion</WindowsTargetPlatformVersion>
-EOF
-	}
-	print $f <<EOF;
-  </PropertyGroup>
-  <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
-EOF
-	$self->WriteConfigurationPropertyGroup($f, 'Release',
-		{ wholeopt => 'false' });
-	$self->WriteConfigurationPropertyGroup($f, 'Debug',
-		{ wholeopt => 'false' });
-	print $f <<EOF;
-  <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-EOF
-	$self->WritePropertySheetsPropertyGroup($f, 'Release');
-	$self->WritePropertySheetsPropertyGroup($f, 'Debug');
-	print $f <<EOF;
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-EOF
-	$self->WriteAdditionalProperties($f, 'Debug');
-	$self->WriteAdditionalProperties($f, 'Release');
-	print $f <<EOF;
-  </PropertyGroup>
-EOF
-
-	$self->WriteItemDefinitionGroup(
-		$f, 'Debug',
-		{
-			defs => "_DEBUG;DEBUG=1",
-			opt => 'Disabled',
-			strpool => 'false',
-			runtime => 'MultiThreadedDebugDLL'
-		});
-	$self->WriteItemDefinitionGroup(
-		$f,
-		'Release',
-		{
-			defs => "",
-			opt => 'Full',
-			strpool => 'true',
-			runtime => 'MultiThreadedDLL'
-		});
-	return;
-}
-
-sub AddDefine
-{
-	my ($self, $def) = @_;
-
-	$self->{defines} .= $def . ';';
-	return;
-}
-
-sub WriteReferences
-{
-	my ($self, $f) = @_;
-
-	my @references = @{ $self->{references} };
-
-	if (scalar(@references))
-	{
-		print $f <<EOF;
-  <ItemGroup>
-EOF
-		foreach my $ref (@references)
-		{
-			print $f <<EOF;
-    <ProjectReference Include="$ref->{name}$ref->{filenameExtension}">
-      <Project>$ref->{guid}</Project>
-    </ProjectReference>
-EOF
-		}
-		print $f <<EOF;
-  </ItemGroup>
-EOF
-	}
-	return;
-}
-
-sub WriteFiles
-{
-	my ($self, $f) = @_;
-	print $f <<EOF;
-  <ItemGroup>
-EOF
-	my @grammarFiles = ();
-	my @resourceFiles = ();
-	my %uniquefiles;
-	foreach my $fileNameWithPath (sort keys %{ $self->{files} })
-	{
-		confess "Bad format filename '$fileNameWithPath'\n"
-		  unless ($fileNameWithPath =~ m!^(.*)/([^/]+)\.(c|cpp|y|l|rc)$!);
-		my $dir = $1;
-		my $fileName = $2;
-		if ($fileNameWithPath =~ /\.y$/ or $fileNameWithPath =~ /\.l$/)
-		{
-			push @grammarFiles, $fileNameWithPath;
-		}
-		elsif ($fileNameWithPath =~ /\.rc$/)
-		{
-			push @resourceFiles, $fileNameWithPath;
-		}
-		elsif (defined($uniquefiles{$fileName}))
-		{
-
-			# File already exists, so fake a new name
-			my $obj = $dir;
-			$obj =~ s!/!_!g;
-
-			print $f <<EOF;
-    <ClCompile Include="$fileNameWithPath">
-      <ObjectFileName Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">.\\debug\\$self->{name}\\${obj}_$fileName.obj</ObjectFileName>
-      <ObjectFileName Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">.\\release\\$self->{name}\\${obj}_$fileName.obj</ObjectFileName>
-    </ClCompile>
-EOF
-		}
-		else
-		{
-			$uniquefiles{$fileName} = 1;
-			print $f <<EOF;
-    <ClCompile Include="$fileNameWithPath" />
-EOF
-		}
-
-	}
-	print $f <<EOF;
-  </ItemGroup>
-EOF
-	if (scalar(@grammarFiles))
-	{
-		print $f <<EOF;
-  <ItemGroup>
-EOF
-		foreach my $grammarFile (@grammarFiles)
-		{
-			(my $outputFile = $grammarFile) =~ s/\.(y|l)$/.c/;
-			if ($grammarFile =~ /\.y$/)
-			{
-				$outputFile =~
-				  s{^src\\pl\\plpgsql\\src\\gram.c$}{src\\pl\\plpgsql\\src\\pl_gram.c};
-				print $f <<EOF;
-    <CustomBuild Include="$grammarFile">
-      <Message Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">Running bison on $grammarFile</Message>
-      <Command Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">perl "src\\tools\\msvc\\pgbison.pl" "$grammarFile"</Command>
-      <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs>
-      <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">$outputFile;%(Outputs)</Outputs>
-      <Message Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">Running bison on $grammarFile</Message>
-      <Command Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">perl "src\\tools\\msvc\\pgbison.pl" "$grammarFile"</Command>
-      <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs>
-      <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">$outputFile;%(Outputs)</Outputs>
-    </CustomBuild>
-EOF
-			}
-			else    #if ($grammarFile =~ /\.l$/)
-			{
-				print $f <<EOF;
-    <CustomBuild Include="$grammarFile">
-      <Message Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">Running flex on $grammarFile</Message>
-      <Command Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">perl "src\\tools\\msvc\\pgflex.pl" "$grammarFile"</Command>
-      <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs>
-      <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">$outputFile;%(Outputs)</Outputs>
-      <Message Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">Running flex on $grammarFile</Message>
-      <Command Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">perl "src\\tools\\msvc\\pgflex.pl" "$grammarFile"</Command>
-      <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs>
-      <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">$outputFile;%(Outputs)</Outputs>
-    </CustomBuild>
-EOF
-			}
-		}
-		print $f <<EOF;
-  </ItemGroup>
-EOF
-	}
-	if (scalar(@resourceFiles))
-	{
-		print $f <<EOF;
-  <ItemGroup>
-EOF
-		foreach my $rcFile (@resourceFiles)
-		{
-			print $f <<EOF;
-    <ResourceCompile Include="$rcFile" />
-EOF
-		}
-		print $f <<EOF;
-  </ItemGroup>
-EOF
-	}
-	return;
-}
-
-sub WriteConfigurationHeader
-{
-	my ($self, $f, $cfgname) = @_;
-	print $f <<EOF;
-    <ProjectConfiguration Include="$cfgname|$self->{platform}">
-      <Configuration>$cfgname</Configuration>
-      <Platform>$self->{platform}</Platform>
-    </ProjectConfiguration>
-EOF
-	return;
-}
-
-sub WriteConfigurationPropertyGroup
-{
-	my ($self, $f, $cfgname, $p) = @_;
-	my $cfgtype =
-	  ($self->{type} eq "exe")
-	  ? 'Application'
-	  : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary');
-
-	print $f <<EOF;
-  <PropertyGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'" Label="Configuration">
-    <ConfigurationType>$cfgtype</ConfigurationType>
-    <UseOfMfc>false</UseOfMfc>
-    <CharacterSet>MultiByte</CharacterSet>
-    <WholeProgramOptimization>$p->{wholeopt}</WholeProgramOptimization>
-    <PlatformToolset>$self->{PlatformToolset}</PlatformToolset>
-  </PropertyGroup>
-EOF
-	return;
-}
-
-sub WritePropertySheetsPropertyGroup
-{
-	my ($self, $f, $cfgname) = @_;
-	print $f <<EOF;
-  <ImportGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'" Label="PropertySheets">
-    <Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-EOF
-	return;
-}
-
-sub WriteAdditionalProperties
-{
-	my ($self, $f, $cfgname) = @_;
-	print $f <<EOF;
-    <OutDir Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">.\\$cfgname\\$self->{name}\\</OutDir>
-    <IntDir Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">.\\$cfgname\\$self->{name}\\</IntDir>
-    <LinkIncremental Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">false</LinkIncremental>
-EOF
-	return;
-}
-
-sub WriteItemDefinitionGroup
-{
-	my ($self, $f, $cfgname, $p) = @_;
-	my $cfgtype =
-	  ($self->{type} eq "exe")
-	  ? 'Application'
-	  : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary');
-	my $libs = $self->GetAdditionalLinkerDependencies($cfgname, ';');
-
-	my $targetmachine =
-	  $self->{platform} eq 'Win32' ? 'MachineX86' : 'MachineX64';
-	my $arch = $self->{platform} eq 'Win32' ? 'x86' : 'x86_64';
-
-	my $includes = join ';', @{ $self->{includes} }, "";
-
-	print $f <<EOF;
-  <ItemDefinitionGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">
-    <ClCompile>
-      <Optimization>$p->{opt}</Optimization>
-      <AdditionalIncludeDirectories>$self->{prefixincludes}src/include;src/include/port/win32;src/include/port/win32_msvc;$includes\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;_WINDOWS;__WINDOWS__;__WIN32__;WIN32_STACK_RLIMIT=4194304;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE$self->{defines}$p->{defs}\%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <StringPooling>$p->{strpool}</StringPooling>
-      <RuntimeLibrary>$p->{runtime}</RuntimeLibrary>
-      <DisableSpecificWarnings>$self->{disablewarnings};\%(DisableSpecificWarnings)</DisableSpecificWarnings>
-      <AdditionalOptions>/MP \%(AdditionalOptions)</AdditionalOptions>
-      <AssemblerOutput>
-      </AssemblerOutput>
-      <AssemblerListingLocation>.\\$cfgname\\$self->{name}\\</AssemblerListingLocation>
-      <ObjectFileName>.\\$cfgname\\$self->{name}\\</ObjectFileName>
-      <ProgramDataBaseFileName>.\\$cfgname\\$self->{name}\\</ProgramDataBaseFileName>
-      <BrowseInformation>false</BrowseInformation>
-      <WarningLevel>Level3</WarningLevel>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <CompileAs>Default</CompileAs>
-    </ClCompile>
-    <Link>
-      <OutputFile>.\\$cfgname\\$self->{name}\\$self->{name}.$self->{type}</OutputFile>
-      <AdditionalDependencies>$libs;\%(AdditionalDependencies)</AdditionalDependencies>
-      <SuppressStartupBanner>true</SuppressStartupBanner>
-      <AdditionalLibraryDirectories>\%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
-      <IgnoreSpecificDefaultLibraries>libc;\%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
-      <StackReserveSize>4194304</StackReserveSize>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>.\\$cfgname\\$self->{name}\\$self->{name}.pdb</ProgramDatabaseFile>
-      <GenerateMapFile>false</GenerateMapFile>
-      <MapFileName>.\\$cfgname\\$self->{name}\\$self->{name}.map</MapFileName>
-      <!-- Permit links to MinGW-built, 32-bit DLLs (default before VS2012). -->
-      <ImageHasSafeExceptionHandlers/>
-      <SubSystem>Console</SubSystem>
-      <TargetMachine>$targetmachine</TargetMachine>
-EOF
-	if ($self->{disablelinkerwarnings})
-	{
-		print $f
-		  "      <AdditionalOptions>/ignore:$self->{disablelinkerwarnings} \%(AdditionalOptions)</AdditionalOptions>\n";
-	}
-	if ($self->{implib})
-	{
-		my $l = $self->{implib};
-		$l =~ s/__CFGNAME__/$cfgname/g;
-		print $f "      <ImportLibrary>$l</ImportLibrary>\n";
-	}
-	if ($self->{def})
-	{
-		my $d = $self->{def};
-		$d =~ s/__CFGNAME__/$cfgname/g;
-		print $f "      <ModuleDefinitionFile>$d</ModuleDefinitionFile>\n";
-	}
-	print $f <<EOF;
-    </Link>
-    <ResourceCompile>
-      <AdditionalIncludeDirectories>src\\include;\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-    </ResourceCompile>
-EOF
-	if ($self->{builddef})
-	{
-		print $f <<EOF;
-    <PreLinkEvent>
-      <Message>Generate DEF file</Message>
-      <Command>perl src\\tools\\msvc\\gendef.pl --arch $arch --deffile $cfgname\\$self->{name}\\$self->{name}.def --tempdir $cfgname\\$self->{name} $cfgname\\$self->{name}</Command>
-    </PreLinkEvent>
-EOF
-	}
-	print $f <<EOF;
-  </ItemDefinitionGroup>
-EOF
-	return;
-}
-
-sub Footer
-{
-	my ($self, $f) = @_;
-	$self->WriteReferences($f);
-
-	print $f <<EOF;
-  <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
-EOF
-	return;
-}
-
-package VC2015Project;
-
-#
-# Package that encapsulates a Visual C++ 2015 project file
-#
-
-use strict;
-use warnings;
-use base qw(MSBuildProject);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{vcver} = '14.00';
-	$self->{PlatformToolset} = 'v140';
-	$self->{ToolsVersion} = '14.0';
-
-	return $self;
-}
-
-package VC2017Project;
-
-#
-# Package that encapsulates a Visual C++ 2017 project file
-#
-
-use strict;
-use warnings;
-use base qw(MSBuildProject);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{vcver} = '15.00';
-	$self->{PlatformToolset} = 'v141';
-	$self->{ToolsVersion} = '15.0';
-
-	return $self;
-}
-
-package VC2019Project;
-
-#
-# Package that encapsulates a Visual C++ 2019 project file
-#
-
-use strict;
-use warnings;
-use base qw(MSBuildProject);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{vcver} = '16.00';
-	$self->{PlatformToolset} = 'v142';
-	$self->{ToolsVersion} = '16.0';
-
-	return $self;
-}
-
-package VC2022Project;
-
-#
-# Package that encapsulates a Visual C++ 2022 project file
-#
-
-use strict;
-use warnings;
-use base qw(MSBuildProject);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{vcver} = '17.00';
-	$self->{PlatformToolset} = 'v143';
-	$self->{ToolsVersion} = '17.0';
-
-	return $self;
-}
-
-1;
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
deleted file mode 100644
index 84f648c174..0000000000
--- a/src/tools/msvc/Mkvcbuild.pm
+++ /dev/null
@@ -1,1219 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Mkvcbuild;
-
-#
-# Package that generates build files for msvc build
-#
-# src/tools/msvc/Mkvcbuild.pm
-#
-use strict;
-use warnings;
-
-use Carp;
-use if ($^O eq "MSWin32"), 'Win32';
-use Project;
-use Solution;
-use Cwd;
-use File::Copy;
-use Config;
-use VSObjectFactory;
-use List::Util qw(first);
-
-use Exporter;
-our (@ISA, @EXPORT_OK);
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(Mkvcbuild);
-
-my $solution;
-my $libpgport;
-my $libpgcommon;
-my $libpgfeutils;
-my $postgres;
-my $libpq;
-my @unlink_on_exit;
-
-# Set of variables for modules in contrib/ and src/test/modules/
-my $contrib_defines = {};
-my @contrib_uselibpq = ();
-my @contrib_uselibpgport = ();
-my @contrib_uselibpgcommon = ();
-my $contrib_extralibs = { 'libpq_pipeline' => ['ws2_32.lib'] };
-my $contrib_extraincludes = {};
-my $contrib_extrasource = {};
-my @contrib_excludes = (
-	'bool_plperl', 'commit_ts',
-	'hstore_plperl', 'hstore_plpython',
-	'intagg', 'jsonb_plperl',
-	'jsonb_plpython', 'ltree_plpython',
-	'sepgsql', 'brin',
-	'test_extensions', 'test_misc',
-	'test_pg_dump', 'snapshot_too_old',
-	'unsafe_tests');
-
-# Set of variables for frontend modules
-my $frontend_defines = { 'pgbench' => 'FD_SETSIZE=1024' };
-my @frontend_uselibpq =
-  ('pg_amcheck', 'pg_ctl', 'pg_upgrade', 'pgbench', 'psql', 'initdb');
-my @frontend_uselibpgport = (
-	'pg_amcheck', 'pg_archivecleanup',
-	'pg_test_fsync', 'pg_test_timing',
-	'pg_upgrade', 'pg_waldump',
-	'pgbench');
-my @frontend_uselibpgcommon = (
-	'pg_amcheck', 'pg_archivecleanup',
-	'pg_test_fsync', 'pg_test_timing',
-	'pg_upgrade', 'pg_waldump',
-	'pgbench');
-my $frontend_extralibs = {
-	'initdb' => ['ws2_32.lib'],
-	'pg_amcheck' => ['ws2_32.lib'],
-	'pg_restore' => ['ws2_32.lib'],
-	'pgbench' => ['ws2_32.lib'],
-	'psql' => ['ws2_32.lib']
-};
-my $frontend_extraincludes = {
-	'initdb' => ['src/timezone'],
-	'psql' => ['src/backend']
-};
-my $frontend_extrasource = {
-	'psql' => ['src/bin/psql/psqlscanslash.l'],
-	'pgbench' =>
-	  [ 'src/bin/pgbench/exprscan.l', 'src/bin/pgbench/exprparse.y' ]
-};
-my @frontend_excludes = (
-	'pgevent', 'pg_basebackup', 'pg_rewind', 'pg_dump',
-	'pg_waldump', 'scripts');
-
-sub mkvcbuild
-{
-	our $config = shift;
-
-	chdir('../../..') if (-d '../msvc' && -d '../../../src');
-	die 'Must run from root or msvc directory'
-	  unless (-d 'src/tools/msvc' && -d 'src');
-
-	my $vsVersion = DetermineVisualStudioVersion();
-
-	$solution = CreateSolution($vsVersion, $config);
-
-	our @pgportfiles = qw(
-	  chklocale.c explicit_bzero.c
-	  getpeereid.c inet_aton.c
-	  inet_net_ntop.c kill.c open.c
-	  snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
-	  dirent.c getopt.c getopt_long.c
-	  preadv.c pwritev.c pg_bitutils.c
-	  pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
-	  pqsignal.c mkdtemp.c qsort.c qsort_arg.c bsearch_arg.c quotes.c system.c
-	  strerror.c tar.c
-	  win32common.c
-	  win32dlopen.c
-	  win32env.c win32error.c
-	  win32fdatasync.c
-	  win32fseek.c
-	  win32getrusage.c
-	  win32gettimeofday.c
-	  win32link.c
-	  win32pread.c
-	  win32pwrite.c
-	  win32ntdll.c
-	  win32security.c win32setlocale.c win32stat.c);
-
-	push(@pgportfiles, 'strtof.c') if ($vsVersion < '14.00');
-
-	if ($vsVersion >= '9.00')
-	{
-		push(@pgportfiles, 'pg_crc32c_sse42_choose.c');
-		push(@pgportfiles, 'pg_crc32c_sse42.c');
-		push(@pgportfiles, 'pg_crc32c_sb8.c');
-	}
-	else
-	{
-		push(@pgportfiles, 'pg_crc32c_sb8.c');
-	}
-
-	our @pgcommonallfiles = qw(
-	  archive.c base64.c binaryheap.c checksum_helper.c compression.c
-	  config_info.c controldata_utils.c d2s.c encnames.c exec.c
-	  f2s.c file_perm.c file_utils.c hashfn.c ip.c jsonapi.c
-	  keywords.c kwlookup.c link-canary.c md5_common.c percentrepl.c
-	  pg_get_line.c pg_lzcompress.c pg_prng.c pgfnames.c psprintf.c relpath.c
-	  rmtree.c saslprep.c scram-common.c string.c stringinfo.c
-	  unicode_category.c unicode_norm.c username.c wait_error.c wchar.c);
-
-	if ($solution->{options}->{openssl})
-	{
-		push(@pgcommonallfiles, 'cryptohash_openssl.c');
-		push(@pgcommonallfiles, 'hmac_openssl.c');
-		push(@pgcommonallfiles, 'protocol_openssl.c');
-	}
-	else
-	{
-		push(@pgcommonallfiles, 'cryptohash.c');
-		push(@pgcommonallfiles, 'hmac.c');
-		push(@pgcommonallfiles, 'md5.c');
-		push(@pgcommonallfiles, 'sha1.c');
-		push(@pgcommonallfiles, 'sha2.c');
-	}
-
-	our @pgcommonfrontendfiles = (
-		@pgcommonallfiles, qw(fe_memutils.c
-		  logging.c restricted_token.c sprompt.c));
-
-	our @pgcommonbkndfiles = @pgcommonallfiles;
-
-	our @pgfeutilsfiles = qw(
-	  archive.c cancel.c conditional.c connect_utils.c mbprint.c option_utils.c
-	  parallel_slot.c print.c psqlscan.l psqlscan.c query_utils.c simple_list.c
-	  string_utils.c recovery_gen.c);
-
-	$libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
-	$libpgport->AddDefine('FRONTEND');
-	$libpgport->AddFiles('src/port', @pgportfiles);
-
-	$libpgcommon = $solution->AddProject('libpgcommon', 'lib', 'misc');
-	$libpgcommon->AddDefine('FRONTEND');
-	$libpgcommon->AddFiles('src/common', @pgcommonfrontendfiles);
-
-	$libpgfeutils = $solution->AddProject('libpgfeutils', 'lib', 'misc');
-	$libpgfeutils->AddDefine('FRONTEND');
-	$libpgfeutils->AddDefine('FD_SETSIZE=1024');
-	$libpgfeutils->AddIncludeDir('src/interfaces/libpq');
-	$libpgfeutils->AddFiles('src/fe_utils', @pgfeutilsfiles);
-
-	$postgres = $solution->AddProject('postgres', 'exe', '', 'src/backend');
-	$postgres->AddIncludeDir('src/backend');
-	$postgres->AddDir('src/backend/port/win32');
-	$postgres->AddFile('src/backend/utils/fmgrtab.c');
-	$postgres->ReplaceFile('src/backend/port/pg_sema.c',
-		'src/backend/port/win32_sema.c');
-	$postgres->ReplaceFile('src/backend/port/pg_shmem.c',
-		'src/backend/port/win32_shmem.c');
-	$postgres->AddFiles('src/port', @pgportfiles);
-	$postgres->AddFiles('src/common', @pgcommonbkndfiles);
-	$postgres->AddDir('src/timezone');
-
-	# We need source files from src/timezone, but that directory's resource
-	# file pertains to "zic", not to the backend.
-	$postgres->RemoveFile('src/timezone/win32ver.rc');
-	$postgres->AddFiles('src/backend/parser', 'scan.l', 'gram.y');
-	$postgres->AddFiles('src/backend/bootstrap', 'bootscanner.l',
-		'bootparse.y');
-	$postgres->AddFiles('src/backend/utils/misc', 'guc-file.l');
-	$postgres->AddFiles(
-		'src/backend/replication', 'repl_scanner.l',
-		'repl_gram.y', 'syncrep_scanner.l',
-		'syncrep_gram.y');
-	$postgres->AddFiles('src/backend/utils/adt', 'jsonpath_scan.l',
-		'jsonpath_gram.y');
-	$postgres->AddDefine('BUILDING_DLL');
-	$postgres->AddLibrary('secur32.lib');
-	$postgres->AddLibrary('ws2_32.lib');
-	$postgres->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
-	$postgres->FullExportDLL('postgres.lib');
-
-	# The OBJS scraper doesn't know about ifdefs, so remove appropriate files
-	# if building without OpenSSL.
-	if (!$solution->{options}->{openssl})
-	{
-		$postgres->RemoveFile('src/backend/libpq/be-secure-common.c');
-		$postgres->RemoveFile('src/backend/libpq/be-secure-openssl.c');
-	}
-	if (!$solution->{options}->{gss})
-	{
-		$postgres->RemoveFile('src/backend/libpq/be-gssapi-common.c');
-		$postgres->RemoveFile('src/backend/libpq/be-secure-gssapi.c');
-	}
-
-	my $snowball = $solution->AddProject('dict_snowball', 'dll', '',
-		'src/backend/snowball');
-
-	# This Makefile uses VPATH to find most source files in a subdirectory.
-	$snowball->RelocateFiles(
-		'src/backend/snowball/libstemmer',
-		sub {
-			return shift !~ /(dict_snowball.c|win32ver.rc)$/;
-		});
-	$snowball->AddIncludeDir('src/include/snowball');
-	$snowball->AddReference($postgres);
-
-	my $plpgsql =
-	  $solution->AddProject('plpgsql', 'dll', 'PLs', 'src/pl/plpgsql/src');
-	$plpgsql->AddFiles('src/pl/plpgsql/src', 'pl_gram.y');
-	$plpgsql->AddReference($postgres);
-
-	if ($solution->{options}->{tcl})
-	{
-		my $found = 0;
-		my $pltcl =
-		  $solution->AddProject('pltcl', 'dll', 'PLs', 'src/pl/tcl');
-		$pltcl->AddIncludeDir($solution->{options}->{tcl} . '/include');
-		$pltcl->AddReference($postgres);
-
-		for my $tclver (qw(86t 86 85 84))
-		{
-			my $tcllib = $solution->{options}->{tcl} . "/lib/tcl$tclver.lib";
-			if (-e $tcllib)
-			{
-				$pltcl->AddLibrary($tcllib);
-				$found = 1;
-				last;
-			}
-		}
-		die "Unable to find $solution->{options}->{tcl}/lib/tcl<version>.lib"
-		  unless $found;
-	}
-
-	$libpq = $solution->AddProject('libpq', 'dll', 'interfaces',
-		'src/interfaces/libpq');
-	$libpq->AddIncludeDir('src/port');
-	$libpq->AddLibrary('secur32.lib');
-	$libpq->AddLibrary('ws2_32.lib');
-	$libpq->AddLibrary('wldap32.lib') if ($solution->{options}->{ldap});
-	$libpq->UseDef('src/interfaces/libpq/libpqdll.def');
-	$libpq->AddReference($libpgcommon, $libpgport);
-
-	# The OBJS scraper doesn't know about ifdefs, so remove appropriate files
-	# if building without OpenSSL.
-	if (!$solution->{options}->{openssl})
-	{
-		$libpq->RemoveFile('src/interfaces/libpq/fe-secure-common.c');
-		$libpq->RemoveFile('src/interfaces/libpq/fe-secure-openssl.c');
-	}
-	if (!$solution->{options}->{gss})
-	{
-		$libpq->RemoveFile('src/interfaces/libpq/fe-gssapi-common.c');
-		$libpq->RemoveFile('src/interfaces/libpq/fe-secure-gssapi.c');
-	}
-
-	my $libpqwalreceiver =
-	  $solution->AddProject('libpqwalreceiver', 'dll', '',
-		'src/backend/replication/libpqwalreceiver');
-	$libpqwalreceiver->AddIncludeDir('src/interfaces/libpq');
-	$libpqwalreceiver->AddReference($postgres, $libpq);
-
-	my $libpq_testclient =
-	  $solution->AddProject('libpq_testclient', 'exe', 'misc',
-		'src/interfaces/libpq/test');
-	$libpq_testclient->AddFile(
-		'src/interfaces/libpq/test/libpq_testclient.c');
-	$libpq_testclient->AddIncludeDir('src/interfaces/libpq');
-	$libpq_testclient->AddReference($libpgport, $libpq);
-	$libpq_testclient->AddLibrary('ws2_32.lib');
-
-	my $libpq_uri_regress =
-	  $solution->AddProject('libpq_uri_regress', 'exe', 'misc',
-		'src/interfaces/libpq/test');
-	$libpq_uri_regress->AddFile(
-		'src/interfaces/libpq/test/libpq_uri_regress.c');
-	$libpq_uri_regress->AddIncludeDir('src/interfaces/libpq');
-	$libpq_uri_regress->AddReference($libpgport, $libpq);
-	$libpq_uri_regress->AddLibrary('ws2_32.lib');
-
-	my $pgoutput = $solution->AddProject('pgoutput', 'dll', '',
-		'src/backend/replication/pgoutput');
-	$pgoutput->AddReference($postgres);
-
-	my $pgtypes = $solution->AddProject(
-		'libpgtypes', 'dll',
-		'interfaces', 'src/interfaces/ecpg/pgtypeslib');
-	$pgtypes->AddReference($libpgcommon, $libpgport);
-	$pgtypes->UseDef('src/interfaces/ecpg/pgtypeslib/pgtypeslib.def');
-	$pgtypes->AddIncludeDir('src/interfaces/ecpg/include');
-
-	my $libecpg = $solution->AddProject('libecpg', 'dll', 'interfaces',
-		'src/interfaces/ecpg/ecpglib');
-	$libecpg->AddIncludeDir('src/interfaces/ecpg/include');
-	$libecpg->AddIncludeDir('src/interfaces/libpq');
-	$libecpg->AddIncludeDir('src/port');
-	$libecpg->UseDef('src/interfaces/ecpg/ecpglib/ecpglib.def');
-	$libecpg->AddLibrary('ws2_32.lib');
-	$libecpg->AddReference($libpq, $pgtypes, $libpgport);
-
-	my $libecpgcompat = $solution->AddProject(
-		'libecpg_compat', 'dll',
-		'interfaces', 'src/interfaces/ecpg/compatlib');
-	$libecpgcompat->AddIncludeDir('src/interfaces/ecpg/include');
-	$libecpgcompat->AddIncludeDir('src/interfaces/libpq');
-	$libecpgcompat->UseDef('src/interfaces/ecpg/compatlib/compatlib.def');
-	$libecpgcompat->AddReference($pgtypes, $libecpg, $libpgport,
-		$libpgcommon);
-
-	my $ecpg = $solution->AddProject('ecpg', 'exe', 'interfaces',
-		'src/interfaces/ecpg/preproc');
-	$ecpg->AddIncludeDir('src/interfaces/ecpg/include');
-	$ecpg->AddIncludeDir('src/interfaces/ecpg/ecpglib');
-	$ecpg->AddIncludeDir('src/interfaces/libpq');
-	$ecpg->AddPrefixInclude('src/interfaces/ecpg/preproc');
-	$ecpg->AddFiles('src/interfaces/ecpg/preproc', 'pgc.l', 'preproc.y');
-	$ecpg->AddReference($libpgcommon, $libpgport);
-
-	my $pgregress_ecpg =
-	  $solution->AddProject('pg_regress_ecpg', 'exe', 'misc');
-	$pgregress_ecpg->AddFile('src/interfaces/ecpg/test/pg_regress_ecpg.c');
-	$pgregress_ecpg->AddFile('src/test/regress/pg_regress.c');
-	$pgregress_ecpg->AddIncludeDir('src/port');
-	$pgregress_ecpg->AddIncludeDir('src/test/regress');
-	$pgregress_ecpg->AddIncludeDir('src/interfaces/libpq');
-	$pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
-	$pgregress_ecpg->AddLibrary('ws2_32.lib');
-	$pgregress_ecpg->AddDirResourceFile('src/interfaces/ecpg/test');
-	$pgregress_ecpg->AddReference($libpq, $libpgcommon, $libpgport);
-
-	my $isolation_tester =
-	  $solution->AddProject('isolationtester', 'exe', 'misc');
-	$isolation_tester->AddFile('src/test/isolation/isolationtester.c');
-	$isolation_tester->AddFile('src/test/isolation/specparse.y');
-	$isolation_tester->AddFile('src/test/isolation/specscanner.l');
-	$isolation_tester->AddFile('src/test/isolation/specparse.c');
-	$isolation_tester->AddFile('src/test/isolation/specscanner.c');
-	$isolation_tester->AddIncludeDir('src/test/isolation');
-	$isolation_tester->AddIncludeDir('src/port');
-	$isolation_tester->AddIncludeDir('src/test/regress');
-	$isolation_tester->AddIncludeDir('src/interfaces/libpq');
-	$isolation_tester->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
-	$isolation_tester->AddLibrary('ws2_32.lib');
-	$isolation_tester->AddDirResourceFile('src/test/isolation');
-	$isolation_tester->AddReference($libpq, $libpgcommon, $libpgport);
-
-	my $pgregress_isolation =
-	  $solution->AddProject('pg_isolation_regress', 'exe', 'misc');
-	$pgregress_isolation->AddFile('src/test/isolation/isolation_main.c');
-	$pgregress_isolation->AddFile('src/test/regress/pg_regress.c');
-	$pgregress_isolation->AddIncludeDir('src/port');
-	$pgregress_isolation->AddIncludeDir('src/test/regress');
-	$pgregress_isolation->AddIncludeDir('src/interfaces/libpq');
-	$pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
-	$pgregress_isolation->AddLibrary('ws2_32.lib');
-	$pgregress_isolation->AddDirResourceFile('src/test/isolation');
-	$pgregress_isolation->AddReference($libpq, $libpgcommon, $libpgport);
-
-	# src/bin
-	my $D;
-	opendir($D, 'src/bin') || croak "Could not opendir on src/bin!\n";
-	while (my $d = readdir($D))
-	{
-		next if ($d =~ /^\./);
-		next unless (-f "src/bin/$d/Makefile");
-		next if (grep { /^$d$/ } @frontend_excludes);
-		AddSimpleFrontend($d);
-	}
-
-	my $pgbasebackup = AddSimpleFrontend('pg_basebackup', 1);
-	# This list of files has to match BBOBJS in pg_basebackup's Makefile.
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/pg_basebackup.c');
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/bbstreamer_file.c');
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/bbstreamer_gzip.c');
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/bbstreamer_inject.c');
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/bbstreamer_lz4.c');
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/bbstreamer_tar.c');
-	$pgbasebackup->AddFile('src/bin/pg_basebackup/bbstreamer_zstd.c');
-	$pgbasebackup->AddLibrary('ws2_32.lib');
-
-	my $pgreceivewal = AddSimpleFrontend('pg_basebackup', 1);
-	$pgreceivewal->{name} = 'pg_receivewal';
-	$pgreceivewal->AddFile('src/bin/pg_basebackup/pg_receivewal.c');
-	$pgreceivewal->AddLibrary('ws2_32.lib');
-
-	my $pgrecvlogical = AddSimpleFrontend('pg_basebackup', 1);
-	$pgrecvlogical->{name} = 'pg_recvlogical';
-	$pgrecvlogical->AddFile('src/bin/pg_basebackup/pg_recvlogical.c');
-	$pgrecvlogical->AddLibrary('ws2_32.lib');
-
-	my $pgrewind = AddSimpleFrontend('pg_rewind', 1);
-	$pgrewind->{name} = 'pg_rewind';
-	$pgrewind->AddFile('src/backend/access/transam/xlogreader.c');
-	$pgrewind->AddLibrary('ws2_32.lib');
-	$pgrewind->AddDefine('FRONTEND');
-
-	my $pgevent = $solution->AddProject('pgevent', 'dll', 'bin');
-	$pgevent->AddFiles('src/bin/pgevent', 'pgevent.c', 'pgmsgevent.rc');
-	$pgevent->AddResourceFile('src/bin/pgevent', 'Eventlog message formatter',
-		'win32');
-	$pgevent->UseDef('src/bin/pgevent/pgevent.def');
-	$pgevent->DisableLinkerWarnings('4104');
-
-	my $pgdump = AddSimpleFrontend('pg_dump', 1);
-	$pgdump->AddIncludeDir('src/backend');
-	$pgdump->AddFile('src/bin/pg_dump/pg_dump.c');
-	$pgdump->AddFile('src/bin/pg_dump/common.c');
-	$pgdump->AddFile('src/bin/pg_dump/pg_dump_sort.c');
-	$pgdump->AddLibrary('ws2_32.lib');
-
-	my $pgdumpall = AddSimpleFrontend('pg_dump', 1);
-
-	# pg_dumpall doesn't use the files in the Makefile's $(OBJS), unlike
-	# pg_dump and pg_restore.
-	# So remove their sources from the object, keeping the other setup that
-	# AddSimpleFrontend() has done.
-	my @nodumpall = grep { m!src/bin/pg_dump/.*\.c$! }
-	  keys %{ $pgdumpall->{files} };
-	delete @{ $pgdumpall->{files} }{@nodumpall};
-	$pgdumpall->{name} = 'pg_dumpall';
-	$pgdumpall->AddIncludeDir('src/backend');
-	$pgdumpall->AddFile('src/bin/pg_dump/pg_dumpall.c');
-	$pgdumpall->AddFile('src/bin/pg_dump/dumputils.c');
-	$pgdumpall->AddLibrary('ws2_32.lib');
-
-	my $pgrestore = AddSimpleFrontend('pg_dump', 1);
-	$pgrestore->{name} = 'pg_restore';
-	$pgrestore->AddIncludeDir('src/backend');
-	$pgrestore->AddFile('src/bin/pg_dump/pg_restore.c');
-	$pgrestore->AddLibrary('ws2_32.lib');
-
-	my $zic = $solution->AddProject('zic', 'exe', 'utils');
-	$zic->AddFiles('src/timezone', 'zic.c');
-	$zic->AddDirResourceFile('src/timezone');
-	$zic->AddReference($libpgcommon, $libpgport);
-
-	if (!$solution->{options}->{xml})
-	{
-		push @contrib_excludes, 'xml2';
-	}
-
-	if (!$solution->{options}->{openssl})
-	{
-		push @contrib_excludes, 'sslinfo', 'ssl_passphrase_callback',
-		  'pgcrypto';
-	}
-
-	if (!$solution->{options}->{ldap})
-	{
-		push @contrib_excludes, 'ldap_password_func';
-	}
-
-	if (!$solution->{options}->{uuid})
-	{
-		push @contrib_excludes, 'uuid-ossp';
-	}
-
-	foreach my $subdir ('contrib', 'src/test/modules')
-	{
-		opendir($D, $subdir) || croak "Could not opendir on $subdir!\n";
-		while (my $d = readdir($D))
-		{
-			next if ($d =~ /^\./);
-			next unless (-f "$subdir/$d/Makefile");
-			next if (grep { /^$d$/ } @contrib_excludes);
-			AddContrib($subdir, $d);
-		}
-		closedir($D);
-	}
-
-	# Build Perl and Python modules after contrib/ modules to satisfy some
-	# dependencies with transform contrib modules, like hstore_plpython
-	# ltree_plpython and hstore_plperl.
-	if ($solution->{options}->{python})
-	{
-
-		# Attempt to get python version and location.
-		# Assume python.exe in specified dir.
-		my $pythonprog = "import sys;print(sys.prefix);"
-		  . "print(str(sys.version_info[0])+str(sys.version_info[1]))";
-		my $prefixcmd =
-		  qq("$solution->{options}->{python}\\python" -c "$pythonprog");
-		my $pyout = `$prefixcmd`;
-		die "Could not query for python version!\n" if $?;
-		my ($pyprefix, $pyver) = split(/\r?\n/, $pyout);
-
-		# Sometimes (always?) if python is not present, the execution
-		# appears to work, but gives no data...
-		die "Failed to query python for version information\n"
-		  if (!(defined($pyprefix) && defined($pyver)));
-
-		my $pymajorver = substr($pyver, 0, 1);
-
-		die
-		  "Python version $pyver is too old (version 3 or later is required)"
-		  if int($pymajorver) < 3;
-
-		my $plpython = $solution->AddProject('plpython' . $pymajorver,
-			'dll', 'PLs', 'src/pl/plpython');
-		$plpython->AddIncludeDir($pyprefix . '/include');
-		$plpython->AddLibrary($pyprefix . "/Libs/python$pyver.lib");
-		$plpython->AddReference($postgres);
-
-		# Add transform modules dependent on plpython
-		my $hstore_plpython = AddTransformModule(
-			'hstore_plpython' . $pymajorver, 'contrib/hstore_plpython',
-			'plpython' . $pymajorver, 'src/pl/plpython',
-			'hstore', 'contrib');
-		$hstore_plpython->AddDefine(
-			'PLPYTHON_LIBNAME="plpython' . $pymajorver . '"');
-		my $jsonb_plpython = AddTransformModule(
-			'jsonb_plpython' . $pymajorver, 'contrib/jsonb_plpython',
-			'plpython' . $pymajorver, 'src/pl/plpython');
-		$jsonb_plpython->AddDefine(
-			'PLPYTHON_LIBNAME="plpython' . $pymajorver . '"');
-		my $ltree_plpython = AddTransformModule(
-			'ltree_plpython' . $pymajorver, 'contrib/ltree_plpython',
-			'plpython' . $pymajorver, 'src/pl/plpython',
-			'ltree', 'contrib');
-		$ltree_plpython->AddDefine(
-			'PLPYTHON_LIBNAME="plpython' . $pymajorver . '"');
-	}
-
-	if ($solution->{options}->{perl})
-	{
-		my $plperlsrc = "src/pl/plperl/";
-		my $plperl =
-		  $solution->AddProject('plperl', 'dll', 'PLs', 'src/pl/plperl');
-		$plperl->AddIncludeDir($solution->{options}->{perl} . '/lib/CORE');
-		$plperl->AddReference($postgres);
-
-		my $perl_path = $solution->{options}->{perl} . '\lib\CORE\*perl*';
-
-		# ActivePerl 5.16 provided perl516.lib; 5.18 provided libperl518.a
-		# Starting with ActivePerl 5.24, both  perlnn.lib and libperlnn.a are provided.
-		# In this case, prefer .lib.
-		my @perl_libs =
-		  reverse sort grep { /perl\d+\.lib$|libperl\d+\.a$/ }
-		  glob($perl_path);
-		if (@perl_libs > 0)
-		{
-			$plperl->AddLibrary($perl_libs[0]);
-		}
-		else
-		{
-			die
-			  "could not identify perl library version matching pattern $perl_path\n";
-		}
-
-		# Add defines from Perl's ccflags; see PGAC_CHECK_PERL_EMBED_CCFLAGS
-		my @perl_embed_ccflags;
-		foreach my $f (split(" ", $Config{ccflags}))
-		{
-			if ($f =~ /^-D[^_]/)
-			{
-				$f =~ s/\-D//;
-				push(@perl_embed_ccflags, $f);
-			}
-		}
-
-		# hack to prevent duplicate definitions of uid_t/gid_t
-		push(@perl_embed_ccflags, 'PLPERL_HAVE_UID_GID');
-		# prevent binary mismatch between MSVC built plperl and
-		# Strawberry or msys ucrt perl libraries
-		push(@perl_embed_ccflags, 'NO_THREAD_SAFE_LOCALE');
-
-		# Windows offers several 32-bit ABIs.  Perl is sensitive to
-		# sizeof(time_t), one of the ABI dimensions.  To get 32-bit time_t,
-		# use "cl -D_USE_32BIT_TIME_T" or plain "gcc".  For 64-bit time_t, use
-		# "gcc -D__MINGW_USE_VC2005_COMPAT" or plain "cl".  Before MSVC 2005,
-		# plain "cl" chose 32-bit time_t.  PostgreSQL doesn't support building
-		# with pre-MSVC-2005 compilers, but it does support linking to Perl
-		# built with such a compiler.  MSVC-built Perl 5.13.4 and later report
-		# -D_USE_32BIT_TIME_T in $Config{ccflags} if applicable, but
-		# MinGW-built Perl never reports -D_USE_32BIT_TIME_T despite typically
-		# needing it.  Ignore the $Config{ccflags} opinion about
-		# -D_USE_32BIT_TIME_T, and use a runtime test to deduce the ABI Perl
-		# expects.  Specifically, test use of PL_modglobal, which maps to a
-		# PerlInterpreter field whose position depends on sizeof(time_t).
-		if ($solution->{platform} eq 'Win32')
-		{
-			my $source_file = 'conftest.c';
-			my $obj = 'conftest.obj';
-			my $exe = 'conftest.exe';
-			my @conftest = ($source_file, $obj, $exe);
-			push @unlink_on_exit, @conftest;
-			unlink $source_file;
-			open my $o, '>', $source_file
-			  || croak "Could not write to $source_file";
-			print $o '
-	/* compare to plperl.h */
-	#define __inline__ __inline
-	#define PERL_NO_GET_CONTEXT
-	#include <EXTERN.h>
-	#include <perl.h>
-
-	int
-	main(int argc, char **argv)
-	{
-		int			dummy_argc = 1;
-		char	   *dummy_argv[1] = {""};
-		char	   *dummy_env[1] = {NULL};
-		static PerlInterpreter *interp;
-
-		PERL_SYS_INIT3(&dummy_argc, (char ***) &dummy_argv,
-					   (char ***) &dummy_env);
-		interp = perl_alloc();
-		perl_construct(interp);
-		{
-			dTHX;
-			const char	key[] = "dummy";
-
-			PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
-			hv_store(PL_modglobal, key, sizeof(key) - 1, newSViv(1), 0);
-			return hv_fetch(PL_modglobal, key, sizeof(key) - 1, 0) == NULL;
-		}
-	}
-';
-			close $o;
-
-			# Build $source_file with a given #define, and return a true value
-			# if a run of the resulting binary exits successfully.
-			my $try_define = sub {
-				my $define = shift;
-
-				unlink $obj, $exe;
-				my @cmd = (
-					'cl',
-					'-I' . $solution->{options}->{perl} . '/lib/CORE',
-					(map { "-D$_" } @perl_embed_ccflags, $define || ()),
-					$source_file,
-					'/link',
-					$perl_libs[0]);
-				my $compile_output = `@cmd 2>&1`;
-				-f $exe || die "Failed to build Perl test:\n$compile_output";
-
-				{
-
-					# Some builds exhibit runtime failure through Perl warning
-					# 'Can't spawn "conftest.exe"'; suppress that.
-					no warnings;
-
-					no strict 'subs';    ## no critic (ProhibitNoStrict)
-
-					# Disable error dialog boxes like we do in the postmaster.
-					# Here, we run code that triggers relevant errors.
-					use
-					  if ($^O eq "MSWin32"), 'Win32API::File',
-					  qw(SetErrorMode :SEM_);
-					my $oldmode = SetErrorMode(
-						SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
-					system(".\\$exe");
-					SetErrorMode($oldmode);
-				}
-
-				return !($? >> 8);
-			};
-
-			my $define_32bit_time = '_USE_32BIT_TIME_T';
-			my $ok_now = $try_define->(undef);
-			my $ok_32bit = $try_define->($define_32bit_time);
-			unlink @conftest;
-			if (!$ok_now && !$ok_32bit)
-			{
-
-				# Unsupported configuration.  Since we used %Config from the
-				# Perl running the build scripts, this is expected if
-				# attempting to link with some other Perl.
-				die "Perl test fails with or without -D$define_32bit_time";
-			}
-			elsif ($ok_now && $ok_32bit)
-			{
-
-				# Resulting build may work, but it's especially important to
-				# verify with "vcregress plcheck".  A refined test may avoid
-				# this outcome.
-				warn "Perl test passes with or without -D$define_32bit_time";
-			}
-			elsif ($ok_32bit)
-			{
-				push(@perl_embed_ccflags, $define_32bit_time);
-			}    # else $ok_now, hence no flag required
-		}
-
-		print "CFLAGS recommended by Perl: $Config{ccflags}\n";
-		print "CFLAGS to compile embedded Perl: ",
-		  (join ' ', map { "-D$_" } @perl_embed_ccflags), "\n";
-		foreach my $f (@perl_embed_ccflags)
-		{
-			$plperl->AddDefine($f);
-		}
-
-		foreach my $xs ('SPI.xs', 'Util.xs')
-		{
-			(my $xsc = $xs) =~ s/\.xs/.c/;
-			if (Solution::IsNewer("$plperlsrc$xsc", "$plperlsrc$xs"))
-			{
-				my $xsubppdir = first { -e "$_/ExtUtils/xsubpp" } (@INC);
-				print "Building $plperlsrc$xsc...\n";
-				system( $solution->{options}->{perl}
-					  . '/bin/perl '
-					  . "$xsubppdir/ExtUtils/xsubpp -typemap "
-					  . $solution->{options}->{perl}
-					  . '/lib/ExtUtils/typemap '
-					  . "$plperlsrc$xs "
-					  . ">$plperlsrc$xsc");
-				if ((!(-f "$plperlsrc$xsc")) || -z "$plperlsrc$xsc")
-				{
-					unlink("$plperlsrc$xsc");    # if zero size
-					die "Failed to create $xsc.\n";
-				}
-			}
-		}
-		if (Solution::IsNewer(
-				'src/pl/plperl/perlchunks.h',
-				'src/pl/plperl/plc_perlboot.pl')
-			|| Solution::IsNewer(
-				'src/pl/plperl/perlchunks.h',
-				'src/pl/plperl/plc_trusted.pl'))
-		{
-			print 'Building src/pl/plperl/perlchunks.h ...' . "\n";
-			my $basedir = getcwd;
-			chdir 'src/pl/plperl';
-			system( $solution->{options}->{perl}
-				  . '/bin/perl '
-				  . 'text2macro.pl '
-				  . '--strip="^(\#.*|\s*)$$" '
-				  . 'plc_perlboot.pl plc_trusted.pl '
-				  . '>perlchunks.h');
-			chdir $basedir;
-			if ((!(-f 'src/pl/plperl/perlchunks.h'))
-				|| -z 'src/pl/plperl/perlchunks.h')
-			{
-				unlink('src/pl/plperl/perlchunks.h');    # if zero size
-				die 'Failed to create perlchunks.h' . "\n";
-			}
-		}
-		if (Solution::IsNewer(
-				'src/pl/plperl/plperl_opmask.h',
-				'src/pl/plperl/plperl_opmask.pl'))
-		{
-			print 'Building src/pl/plperl/plperl_opmask.h ...' . "\n";
-			my $basedir = getcwd;
-			chdir 'src/pl/plperl';
-			system( $solution->{options}->{perl}
-				  . '/bin/perl '
-				  . 'plperl_opmask.pl '
-				  . 'plperl_opmask.h');
-			chdir $basedir;
-			if ((!(-f 'src/pl/plperl/plperl_opmask.h'))
-				|| -z 'src/pl/plperl/plperl_opmask.h')
-			{
-				unlink('src/pl/plperl/plperl_opmask.h');    # if zero size
-				die 'Failed to create plperl_opmask.h' . "\n";
-			}
-		}
-
-		# Add transform modules dependent on plperl
-		my $bool_plperl = AddTransformModule(
-			'bool_plperl', 'contrib/bool_plperl',
-			'plperl', 'src/pl/plperl');
-		my $hstore_plperl = AddTransformModule(
-			'hstore_plperl', 'contrib/hstore_plperl',
-			'plperl', 'src/pl/plperl',
-			'hstore', 'contrib');
-		my $jsonb_plperl = AddTransformModule(
-			'jsonb_plperl', 'contrib/jsonb_plperl',
-			'plperl', 'src/pl/plperl');
-
-		foreach my $f (@perl_embed_ccflags)
-		{
-			$bool_plperl->AddDefine($f);
-			$hstore_plperl->AddDefine($f);
-			$jsonb_plperl->AddDefine($f);
-		}
-	}
-
-	my $mf =
-	  Project::read_file('src/backend/utils/mb/conversion_procs/Makefile');
-	$mf =~ s{\\\r?\n}{}g;
-	$mf =~ m{SUBDIRS\s*=\s*(.*)$}m
-	  || die 'Could not match in conversion makefile' . "\n";
-	foreach my $sub (split /\s+/, $1)
-	{
-		my $dir = 'src/backend/utils/mb/conversion_procs/' . $sub;
-		my $p = $solution->AddProject($sub, 'dll', 'conversion procs', $dir);
-		$p->AddFile("$dir/$sub.c");    # implicit source file
-		$p->AddReference($postgres);
-	}
-
-	$mf = Project::read_file('src/bin/scripts/Makefile');
-	$mf =~ s{\\\r?\n}{}g;
-	$mf =~ m{PROGRAMS\s*=\s*(.*)$}m
-	  || die 'Could not match in bin/scripts/Makefile' . "\n";
-	foreach my $prg (split /\s+/, $1)
-	{
-		my $proj = $solution->AddProject($prg, 'exe', 'bin');
-		$mf =~ m{$prg\s*:\s*(.*)$}m
-		  || die 'Could not find script define for $prg' . "\n";
-		my @files = split /\s+/, $1;
-		foreach my $f (@files)
-		{
-			$f =~ s/\.o$/\.c/;
-			if ($f =~ /\.c$/)
-			{
-				$proj->AddFile('src/bin/scripts/' . $f);
-			}
-		}
-		$proj->AddIncludeDir('src/interfaces/libpq');
-		$proj->AddReference($libpq, $libpgfeutils, $libpgcommon, $libpgport);
-		$proj->AddDirResourceFile('src/bin/scripts');
-		$proj->AddLibrary('ws2_32.lib');
-	}
-
-	# Regression DLL and EXE
-	my $regress = $solution->AddProject('regress', 'dll', 'misc');
-	$regress->AddFile('src/test/regress/regress.c');
-	$regress->AddDirResourceFile('src/test/regress');
-	$regress->AddReference($postgres);
-
-	my $pgregress = $solution->AddProject('pg_regress', 'exe', 'misc');
-	$pgregress->AddFile('src/test/regress/pg_regress.c');
-	$pgregress->AddFile('src/test/regress/pg_regress_main.c');
-	$pgregress->AddIncludeDir('src/port');
-	$pgregress->AddIncludeDir('src/interfaces/libpq');
-	$pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
-	$pgregress->AddLibrary('ws2_32.lib');
-	$pgregress->AddDirResourceFile('src/test/regress');
-	$pgregress->AddReference($libpq, $libpgcommon, $libpgport);
-
-	# fix up pg_waldump once it's been set up
-	# files symlinked on Unix are copied on windows
-	my $pg_waldump = AddSimpleFrontend('pg_waldump');
-	$pg_waldump->AddDefine('FRONTEND');
-	foreach my $xf (glob('src/backend/access/rmgrdesc/*desc*.c'))
-	{
-		$pg_waldump->AddFile($xf);
-	}
-	$pg_waldump->AddFile('src/backend/access/transam/xlogreader.c');
-
-	$solution->Save();
-	return $solution->{vcver};
-}
-
-#####################
-# Utility functions #
-#####################
-
-# Add a simple frontend project (exe)
-sub AddSimpleFrontend
-{
-	my $n = shift;
-	my $uselibpq = shift;
-
-	my $p = $solution->AddProject($n, 'exe', 'bin');
-	$p->AddDir('src/bin/' . $n);
-	$p->AddReference($libpgfeutils, $libpgcommon, $libpgport);
-	if ($uselibpq)
-	{
-		$p->AddIncludeDir('src/interfaces/libpq');
-		$p->AddReference($libpq);
-	}
-
-	# Adjust module definition using frontend variables
-	AdjustFrontendProj($p);
-
-	return $p;
-}
-
-# Add a simple transform module
-sub AddTransformModule
-{
-	my $n = shift;
-	my $n_src = shift;
-	my $pl_proj_name = shift;
-	my $pl_src = shift;
-	my $type_name = shift;
-	my $type_src = shift;
-
-	my $type_proj = undef;
-	if ($type_name)
-	{
-		foreach my $proj (@{ $solution->{projects}->{'contrib'} })
-		{
-			if ($proj->{name} eq $type_name)
-			{
-				$type_proj = $proj;
-				last;
-			}
-		}
-		die "could not find base module $type_name for transform module $n"
-		  if (!defined($type_proj));
-	}
-
-	my $pl_proj = undef;
-	foreach my $proj (@{ $solution->{projects}->{'PLs'} })
-	{
-		if ($proj->{name} eq $pl_proj_name)
-		{
-			$pl_proj = $proj;
-			last;
-		}
-	}
-	die "could not find PL $pl_proj_name for transform module $n"
-	  if (!defined($pl_proj));
-
-	my $p = $solution->AddProject($n, 'dll', 'contrib', $n_src);
-	for my $file (glob("$n_src/*.c"))
-	{
-		$p->AddFile($file);
-	}
-	$p->AddReference($postgres);
-
-	# Add PL dependencies
-	$p->AddIncludeDir($pl_src);
-	$p->AddReference($pl_proj);
-	$p->AddIncludeDir($_) for @{ $pl_proj->{includes} };
-	foreach my $pl_lib (@{ $pl_proj->{libraries} })
-	{
-		$p->AddLibrary($pl_lib);
-	}
-
-	# Add base module dependencies
-	if ($type_proj)
-	{
-		$p->AddIncludeDir($type_src);
-		$p->AddIncludeDir($_) for @{ $type_proj->{includes} };
-		foreach my $type_lib (@{ $type_proj->{libraries} })
-		{
-			$p->AddLibrary($type_lib);
-		}
-		$p->AddReference($type_proj);
-	}
-
-	return $p;
-}
-
-# Add a simple contrib project
-sub AddContrib
-{
-	my $subdir = shift;
-	my $n = shift;
-	my $mf = Project::read_file("$subdir/$n/Makefile");
-	my @projects = ();
-
-	if ($mf =~ /^MODULE_big\s*=\s*(.*)$/mg)
-	{
-		my $dn = $1;
-		my $proj = $solution->AddProject($dn, 'dll', 'contrib', "$subdir/$n");
-		$proj->AddReference($postgres);
-		AdjustContribProj($proj);
-		push @projects, $proj;
-	}
-	elsif ($mf =~ /^MODULES\s*=\s*(.*)$/mg)
-	{
-		foreach my $mod (split /\s+/, $1)
-		{
-			my $proj =
-			  $solution->AddProject($mod, 'dll', 'contrib', "$subdir/$n");
-			my $filename = $mod . '.c';
-			$proj->AddFile("$subdir/$n/$filename");
-			$proj->AddReference($postgres);
-			AdjustContribProj($proj);
-			push @projects, $proj;
-		}
-	}
-	elsif ($mf =~ /^PROGRAM\s*=\s*(.*)$/mg)
-	{
-		my $proj = $solution->AddProject($1, 'exe', 'contrib', "$subdir/$n");
-		AdjustContribProj($proj);
-		push @projects, $proj;
-	}
-	else
-	{
-		croak "Could not determine contrib module type for $n\n";
-	}
-
-	# Process custom compiler flags
-	if (   $mf =~ /^PG_CPPFLAGS\s*=\s*(.*)$/mg
-		|| $mf =~ /^override\s*CPPFLAGS\s*[+:]?=\s*(.*)$/mg)
-	{
-		foreach my $flag (split /\s+/, $1)
-		{
-			if ($flag =~ /^-D(.*)$/)
-			{
-				foreach my $proj (@projects)
-				{
-					$proj->AddDefine($1);
-				}
-			}
-			elsif ($flag =~ /^-I(.*)$/)
-			{
-				if ($1 eq '$(libpq_srcdir)')
-				{
-					foreach my $proj (@projects)
-					{
-						$proj->AddIncludeDir('src/interfaces/libpq');
-						$proj->AddReference($libpq);
-					}
-				}
-			}
-		}
-	}
-
-	if ($mf =~ /^SHLIB_LINK_INTERNAL\s*[+:]?=\s*(.*)$/mg)
-	{
-		foreach my $lib (split /\s+/, $1)
-		{
-			if ($lib eq '$(libpq)')
-			{
-				foreach my $proj (@projects)
-				{
-					$proj->AddIncludeDir('src/interfaces/libpq');
-					$proj->AddReference($libpq);
-				}
-			}
-		}
-	}
-
-	if ($mf =~ /^PG_LIBS_INTERNAL\s*[+:]?=\s*(.*)$/mg)
-	{
-		foreach my $lib (split /\s+/, $1)
-		{
-			if ($lib eq '$(libpq_pgport)')
-			{
-				foreach my $proj (@projects)
-				{
-					$proj->AddReference($libpgport);
-					$proj->AddReference($libpgcommon);
-				}
-			}
-		}
-	}
-
-	foreach my $line (split /\n/, $mf)
-	{
-		if ($line =~ /^[A-Za-z0-9_]*\.o:\s(.*)/)
-		{
-			foreach my $file (split /\s+/, $1)
-			{
-				foreach my $proj (@projects)
-				{
-					$proj->AddDependantFiles("$subdir/$n/$file");
-				}
-			}
-		}
-	}
-
-	# Are there any output data files to build?
-	GenerateContribSqlFiles($n, $mf);
-	return;
-}
-
-sub GenerateContribSqlFiles
-{
-	my $n = shift;
-	my $mf = shift;
-	$mf =~ s{\\\r?\n}{}g;
-	if ($mf =~ /^DATA_built\s*=\s*(.*)$/mg)
-	{
-		my $l = $1;
-
-		# Strip out $(addsuffix) rules
-		if (index($l, '$(addsuffix ') >= 0)
-		{
-			my $pcount = 0;
-			my $i;
-			for ($i = index($l, '$(addsuffix ') + 12; $i < length($l); $i++)
-			{
-				$pcount++ if (substr($l, $i, 1) eq '(');
-				$pcount-- if (substr($l, $i, 1) eq ')');
-				last if ($pcount < 0);
-			}
-			$l =
-			  substr($l, 0, index($l, '$(addsuffix ')) . substr($l, $i + 1);
-		}
-
-		foreach my $d (split /\s+/, $l)
-		{
-			my $in = "$d.in";
-			my $out = "$d";
-
-			if (Solution::IsNewer("contrib/$n/$out", "contrib/$n/$in"))
-			{
-				print "Building $out from $in (contrib/$n)...\n";
-				my $cont = Project::read_file("contrib/$n/$in");
-				my $dn = $out;
-				$dn =~ s/\.sql$//;
-				$cont =~ s/MODULE_PATHNAME/\$libdir\/$dn/g;
-				my $o;
-				open($o, '>', "contrib/$n/$out")
-				  || croak "Could not write to contrib/$n/$d";
-				print $o $cont;
-				close($o);
-			}
-		}
-	}
-	return;
-}
-
-sub AdjustContribProj
-{
-	my $proj = shift;
-	AdjustModule(
-		$proj, $contrib_defines,
-		\@contrib_uselibpq, \@contrib_uselibpgport,
-		\@contrib_uselibpgcommon, $contrib_extralibs,
-		$contrib_extrasource, $contrib_extraincludes);
-	return;
-}
-
-sub AdjustFrontendProj
-{
-	my $proj = shift;
-	AdjustModule(
-		$proj, $frontend_defines,
-		\@frontend_uselibpq, \@frontend_uselibpgport,
-		\@frontend_uselibpgcommon, $frontend_extralibs,
-		$frontend_extrasource, $frontend_extraincludes);
-	return;
-}
-
-sub AdjustModule
-{
-	my $proj = shift;
-	my $module_defines = shift;
-	my $module_uselibpq = shift;
-	my $module_uselibpgport = shift;
-	my $module_uselibpgcommon = shift;
-	my $module_extralibs = shift;
-	my $module_extrasource = shift;
-	my $module_extraincludes = shift;
-	my $n = $proj->{name};
-
-	if ($module_defines->{$n})
-	{
-		foreach my $d ($module_defines->{$n})
-		{
-			$proj->AddDefine($d);
-		}
-	}
-	if (grep { /^$n$/ } @{$module_uselibpq})
-	{
-		$proj->AddIncludeDir('src\interfaces\libpq');
-		$proj->AddReference($libpq);
-	}
-	if (grep { /^$n$/ } @{$module_uselibpgport})
-	{
-		$proj->AddReference($libpgport);
-	}
-	if (grep { /^$n$/ } @{$module_uselibpgcommon})
-	{
-		$proj->AddReference($libpgcommon);
-	}
-	if ($module_extralibs->{$n})
-	{
-		foreach my $l (@{ $module_extralibs->{$n} })
-		{
-			$proj->AddLibrary($l);
-		}
-	}
-	if ($module_extraincludes->{$n})
-	{
-		foreach my $i (@{ $module_extraincludes->{$n} })
-		{
-			$proj->AddIncludeDir($i);
-		}
-	}
-	if ($module_extrasource->{$n})
-	{
-		foreach my $i (@{ $module_extrasource->{$n} })
-		{
-			print "Files $i\n";
-			$proj->AddFile($i);
-		}
-	}
-	return;
-}
-
-END
-{
-	unlink @unlink_on_exit;
-}
-
-1;
diff --git a/src/tools/msvc/Project.pm b/src/tools/msvc/Project.pm
deleted file mode 100644
index 0507ad08c5..0000000000
--- a/src/tools/msvc/Project.pm
+++ /dev/null
@@ -1,482 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Project;
-
-#
-# Package that encapsulates a Visual C++ project file generation
-#
-# src/tools/msvc/Project.pm
-#
-use Carp;
-use strict;
-use warnings;
-use File::Basename;
-
-sub _new
-{
-	my ($classname, $name, $type, $solution) = @_;
-	my $good_types = {
-		lib => 1,
-		exe => 1,
-		dll => 1,
-	};
-	confess("Bad project type: $type\n") unless exists $good_types->{$type};
-	my $self = {
-		name => $name,
-		type => $type,
-		guid => $^O eq "MSWin32" ? Win32::GuidGen() : 'FAKE',
-		files => {},
-		references => [],
-		libraries => [],
-		suffixlib => [],
-		includes => [],
-		prefixincludes => '',
-		defines => ';',
-		solution => $solution,
-		disablewarnings => '4018;4244;4273;4101;4102;4090;4267',
-		disablelinkerwarnings => '',
-		platform => $solution->{platform},
-	};
-
-	bless($self, $classname);
-	return $self;
-}
-
-sub AddFile
-{
-	my ($self, $filename) = @_;
-
-	$self->FindAndAddAdditionalFiles($filename);
-	$self->{files}->{$filename} = 1;
-	return;
-}
-
-sub AddDependantFiles
-{
-	my ($self, $filename) = @_;
-
-	$self->FindAndAddAdditionalFiles($filename);
-	return;
-}
-
-sub AddFiles
-{
-	my $self = shift;
-	my $dir = shift;
-
-	while (my $f = shift)
-	{
-		$self->AddFile($dir . "/" . $f, 1);
-	}
-	return;
-}
-
-# Handle Makefile rules by searching for other files which exist with the same
-# name but a different file extension and add those files too.
-sub FindAndAddAdditionalFiles
-{
-	my $self = shift;
-	my $fname = shift;
-	$fname =~ /(.*)(\.[^.]+)$/;
-	my $filenoext = $1;
-	my $fileext = $2;
-
-	# For .c files, check if either a .l or .y file of the same name
-	# exists and add that too.
-	if ($fileext eq ".c")
-	{
-		my $file = $filenoext . ".l";
-		if (-e $file)
-		{
-			$self->AddFile($file);
-		}
-
-		$file = $filenoext . ".y";
-		if (-e $file)
-		{
-			$self->AddFile($file);
-		}
-	}
-}
-
-sub ReplaceFile
-{
-	my ($self, $filename, $newname) = @_;
-	my $re = "\\/$filename\$";
-
-	foreach my $file (keys %{ $self->{files} })
-	{
-
-		# Match complete filename
-		if ($filename =~ m!/!)
-		{
-			if ($file eq $filename)
-			{
-				delete $self->{files}{$file};
-				$self->AddFile($newname);
-				return;
-			}
-		}
-		elsif ($file =~ m/($re)/)
-		{
-			delete $self->{files}{$file};
-			$self->AddFile("$newname/$filename");
-			return;
-		}
-	}
-	confess("Could not find file $filename to replace\n");
-}
-
-sub RemoveFile
-{
-	my ($self, $filename) = @_;
-	my $orig = scalar keys %{ $self->{files} };
-	delete $self->{files}->{$filename};
-	if ($orig > scalar keys %{ $self->{files} })
-	{
-		return;
-	}
-	confess("Could not find file $filename to remove\n");
-}
-
-sub RelocateFiles
-{
-	my ($self, $targetdir, $proc) = @_;
-	foreach my $f (keys %{ $self->{files} })
-	{
-		my $r = &$proc($f);
-		if ($r)
-		{
-			$self->RemoveFile($f);
-			$self->AddFile($targetdir . '/' . basename($f));
-		}
-	}
-	return;
-}
-
-sub AddReference
-{
-	my $self = shift;
-
-	while (my $ref = shift)
-	{
-		if (!grep { $_ eq $ref } @{ $self->{references} })
-		{
-			push @{ $self->{references} }, $ref;
-		}
-		$self->AddLibrary(
-			"__CFGNAME__/" . $ref->{name} . "/" . $ref->{name} . ".lib");
-	}
-	return;
-}
-
-sub AddLibrary
-{
-	my ($self, $lib, $dbgsuffix) = @_;
-
-	# quote lib name if it has spaces and isn't already quoted
-	if ($lib =~ m/\s/ && $lib !~ m/^[&]quot;/)
-	{
-		$lib = '&quot;' . $lib . "&quot;";
-	}
-
-	if (!grep { $_ eq $lib } @{ $self->{libraries} })
-	{
-		push @{ $self->{libraries} }, $lib;
-	}
-
-	if ($dbgsuffix)
-	{
-		push @{ $self->{suffixlib} }, $lib;
-	}
-	return;
-}
-
-sub AddIncludeDir
-{
-	my ($self, $incstr) = @_;
-
-	foreach my $inc (split(/;/, $incstr))
-	{
-		if (!grep { $_ eq $inc } @{ $self->{includes} })
-		{
-			push @{ $self->{includes} }, $inc;
-		}
-	}
-	return;
-}
-
-sub AddPrefixInclude
-{
-	my ($self, $inc) = @_;
-
-	$self->{prefixincludes} = $inc . ';' . $self->{prefixincludes};
-	return;
-}
-
-sub AddDefine
-{
-	my ($self, $def) = @_;
-
-	$def =~ s/"/&quot;&quot;/g;
-	$self->{defines} .= $def . ';';
-	return;
-}
-
-sub FullExportDLL
-{
-	my ($self, $libname) = @_;
-
-	$self->{builddef} = 1;
-	$self->{def} = "./__CFGNAME__/$self->{name}/$self->{name}.def";
-	$self->{implib} = "__CFGNAME__/$self->{name}/$libname";
-	return;
-}
-
-sub UseDef
-{
-	my ($self, $def) = @_;
-
-	$self->{def} = $def;
-	return;
-}
-
-sub AddDir
-{
-	my ($self, $reldir) = @_;
-	my $mf = read_makefile($reldir);
-
-	$mf =~ s{\\\r?\n}{}g;
-	if ($mf =~ m{^(?:SUB)?DIRS[^=]*=\s*(.*)$}mg)
-	{
-		foreach my $subdir (split /\s+/, $1)
-		{
-			next
-			  if $subdir eq "\$(top_builddir)/src/timezone"
-			  ;    #special case for non-standard include
-			next
-			  if $reldir . "/" . $subdir eq "src/backend/port/darwin";
-
-			$self->AddDir($reldir . "/" . $subdir);
-		}
-	}
-	while ($mf =~ m{^(?:EXTRA_)?OBJS[^=]*=\s*(.*)$}m)
-	{
-		my $s = $1;
-		my $filter_re = qr{\$\(filter ([^,]+),\s+\$\(([^\)]+)\)\)};
-		while ($s =~ /$filter_re/)
-		{
-
-			# Process $(filter a b c, $(VAR)) expressions
-			my $list = $1;
-			my $filter = $2;
-			$list =~ s/\.o/\.c/g;
-			my @pieces = split /\s+/, $list;
-			my $matches = "";
-			foreach my $p (@pieces)
-			{
-
-				if ($filter eq "LIBOBJS")
-				{
-					no warnings qw(once);
-					if (grep(/$p/, @main::pgportfiles) == 1)
-					{
-						$p =~ s/\.c/\.o/;
-						$matches .= $p . " ";
-					}
-				}
-				else
-				{
-					confess "Unknown filter $filter\n";
-				}
-			}
-			$s =~ s/$filter_re/$matches/;
-		}
-		foreach my $f (split /\s+/, $s)
-		{
-			next if $f =~ /^\s*$/;
-			next if $f eq "\\";
-			next if $f =~ /\/SUBSYS.o$/;
-			$f =~ s/,$//
-			  ;    # Remove trailing comma that can show up from filter stuff
-			next unless $f =~ /.*\.o$/;
-			$f =~ s/\.o$/\.c/;
-			if ($f =~ /^\$\(top_builddir\)\/(.*)/)
-			{
-				$f = $1;
-				$self->AddFile($f);
-			}
-			else
-			{
-				$self->AddFile("$reldir/$f");
-			}
-		}
-		$mf =~ s{OBJS[^=]*=\s*(.*)$}{}m;
-	}
-
-	# Match rules that pull in source files from different directories, eg
-	# pgstrcasecmp.c rint.c snprintf.c: % : $(top_srcdir)/src/port/%
-	my $replace_re =
-	  qr{^([^:\n\$]+\.c)\s*:\s*(?:%\s*: )?\$(\([^\)]+\))\/(.*)\/[^\/]+\n}m;
-	while ($mf =~ m{$replace_re}m)
-	{
-		my $match = $1;
-		my $top = $2;
-		my $target = $3;
-		my @pieces = split /\s+/, $match;
-		foreach my $fn (@pieces)
-		{
-			if ($top eq "(top_srcdir)")
-			{
-				eval { $self->ReplaceFile($fn, $target) };
-			}
-			elsif ($top eq "(backend_src)")
-			{
-				eval { $self->ReplaceFile($fn, "src/backend/$target") };
-			}
-			else
-			{
-				confess "Bad replacement top: $top, on line $_\n";
-			}
-		}
-		$mf =~ s{$replace_re}{}m;
-	}
-
-	$self->AddDirResourceFile($reldir);
-	return;
-}
-
-# If the directory's Makefile bears a description string, add a resource file.
-sub AddDirResourceFile
-{
-	my ($self, $reldir) = @_;
-	my $mf = read_makefile($reldir);
-
-	if ($mf =~ /^PGFILEDESC\s*=\s*\"([^\"]+)\"/m)
-	{
-		my $desc = $1;
-		my $ico;
-		if ($mf =~ /^PGAPPICON\s*=\s*(.*)$/m) { $ico = $1; }
-		$self->AddResourceFile($reldir, $desc, $ico);
-	}
-	return;
-}
-
-sub AddResourceFile
-{
-	my ($self, $dir, $desc, $ico) = @_;
-
-	if (Solution::IsNewer("$dir/win32ver.rc", 'src/port/win32ver.rc'))
-	{
-		print "Generating win32ver.rc for $dir\n";
-		open(my $i, '<', 'src/port/win32ver.rc')
-		  || confess "Could not open win32ver.rc";
-		open(my $o, '>', "$dir/win32ver.rc")
-		  || confess "Could not write win32ver.rc";
-		my $icostr = $ico ? "IDI_ICON ICON \"src/port/$ico.ico\"" : "";
-		while (<$i>)
-		{
-			s/FILEDESC/"$desc"/gm;
-			s/_ICO_/$icostr/gm;
-			if ($self->{type} eq "dll")
-			{
-				s/VFT_APP/VFT_DLL/gm;
-				my $name = $self->{name};
-				s/_INTERNAL_NAME_/"$name"/;
-				s/_ORIGINAL_NAME_/"$name.dll"/;
-			}
-			else
-			{
-				/_INTERNAL_NAME_/ && next;
-				/_ORIGINAL_NAME_/ && next;
-			}
-			print $o $_;
-		}
-		close($o);
-		close($i);
-	}
-	$self->AddFile("$dir/win32ver.rc");
-	return;
-}
-
-sub DisableLinkerWarnings
-{
-	my ($self, $warnings) = @_;
-
-	$self->{disablelinkerwarnings} .= ','
-	  unless ($self->{disablelinkerwarnings} eq '');
-	$self->{disablelinkerwarnings} .= $warnings;
-	return;
-}
-
-sub Save
-{
-	my ($self) = @_;
-
-	# Warning 4197 is about double exporting, disable this per
-	# http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99193
-	$self->DisableLinkerWarnings('4197') if ($self->{platform} eq 'x64');
-
-	# Dump the project
-	open(my $f, '>', "$self->{name}$self->{filenameExtension}")
-	  || croak(
-		"Could not write to $self->{name}$self->{filenameExtension}\n");
-	$self->WriteHeader($f);
-	$self->WriteFiles($f);
-	$self->Footer($f);
-	close($f);
-	return;
-}
-
-sub GetAdditionalLinkerDependencies
-{
-	my ($self, $cfgname, $separator) = @_;
-	my $libcfg = (uc $cfgname eq "RELEASE") ? "MD" : "MDd";
-	my $libs = '';
-	foreach my $lib (@{ $self->{libraries} })
-	{
-		my $xlib = $lib;
-		foreach my $slib (@{ $self->{suffixlib} })
-		{
-			if ($slib eq $lib)
-			{
-				$xlib =~ s/\.lib$/$libcfg.lib/;
-				last;
-			}
-		}
-		$libs .= $xlib . $separator;
-	}
-	$libs =~ s/.$//;
-	$libs =~ s/__CFGNAME__/$cfgname/g;
-	return $libs;
-}
-
-# Utility function that loads a complete file
-sub read_file
-{
-	my $filename = shift;
-	my $F;
-	local $/ = undef;
-	open($F, '<', $filename) || croak "Could not open file $filename\n";
-	my $txt = <$F>;
-	close($F);
-
-	return $txt;
-}
-
-sub read_makefile
-{
-	my $reldir = shift;
-	my $F;
-	local $/ = undef;
-	open($F, '<', "$reldir/GNUmakefile")
-	  || open($F, '<', "$reldir/Makefile")
-	  || confess "Could not open $reldir/Makefile\n";
-	my $txt = <$F>;
-	close($F);
-
-	return $txt;
-}
-
-1;
diff --git a/src/tools/msvc/README b/src/tools/msvc/README
deleted file mode 100644
index 1c36925258..0000000000
--- a/src/tools/msvc/README
+++ /dev/null
@@ -1,99 +0,0 @@
-src/tools/msvc/README
-
-MSVC build
-==========
-
-This directory contains the tools required to build PostgreSQL using
-Microsoft Visual Studio 2015 - 2022. This builds the whole backend, not just
-the libpq frontend library. For more information, see the documentation
-chapter "Installation on Windows" and the description below.
-
-
-Notes about Visual Studio Express
----------------------------------
-To build PostgreSQL using Visual Studio Express, the Microsoft Windows SDK
-has to be installed. Since this is not included in the product
-originally, extra steps are needed to make it work.
-
-First, download and install a supported version of the Microsoft Windows SDK
-from www.microsoft.com (v8.1a or greater).
-
-Locate the files vcprojectengine.dll.express.config and
-vcprojectengine.dll.config in the vc\vcpackages directory of
-the Visual C++ Express installation. In these files, add the paths
-to the Platform SDK to the Include, Library and Path tags. Be sure
-to add them to the beginning of the list.
-
-This should work for both GUI and commandline builds, but a restart
-may be necessary.
-
-If you are using a recent version of the Microsoft Windows SDK that includes
-the compilers and build tools you probably don't even need Visual Studio
-Express to build PostgreSQL.
-
-
-Structure of the build tools
-----------------------------
-The tools for building PostgreSQL using Microsoft Visual Studio currently
-consist of the following files:
-
-- Configuration files -
-config_default.pl      default configuration arguments
-
-A typical build environment has two more files, buildenv.pl and config.pl
-that contain the user's build environment settings and configuration
-arguments.
-
-
-- User tools -
-build.pl               tool to build the binaries
-clean.bat              batch file for cleaning up generated files
-install.pl             tool to install the generated files
-mkvcbuild.pl           tool to generate the Visual Studio build files
-vcregress.pl           tool to run the regression tests
-
-
-- Internal tools -
-gendef.pl              internal tool to generate .DEF files
-pgbison.pl             internal tool to process .y files using bison
-pgflex.pl              internal tool to process .l files using flex
-
-Many of those .pl files also have a corresponding .bat-wrapper that doesn't
-contain any additional logic.
-
-
-- Internal modules -
-Install.pm             module containing the install logic
-Mkvcbuild.pm           module containing the code to generate the Visual
-                       Studio build (project/solution) files
-MSBuildProject.pm      module containing the code to generate MSBuild based
-                       project files (Visual Studio 2015 or greater)
-Project.pm             module containing the common code to generate the
-                       Visual Studio project files. Also provides the
-                       common interface of all project file generators
-Solution.pm            module containing the code to generate the Visual
-                       Studio solution files.
-VSObjectFactory.pm     factory module providing the code to create the
-                       appropriate project/solution files for the current
-                       environment
-
-
-Description of the internals of the Visual Studio build process
----------------------------------------------------------------
-By typing 'build' the user starts the build.bat wrapper which simply passes
-its arguments to build.pl.
-In build.pl the user's buildenv.pl is used to set up the build environment
-(i. e. path to bison and flex). In addition his config.pl file is merged into
-config_default.pl to create the configuration arguments.
-These configuration arguments are passed over to Mkvcbuild::mkvcbuild
-(Mkvcbuild.pm) which creates the Visual Studio project and solution files.
-It does this by using VSObjectFactory::CreateSolution to create an object
-implementing the Solution interface (this could be either
-VS2015Solution, VS2017Solution, VS2019Solution or VS2022Solution, all in
-Solution.pm, depending on the user's build environment) and adding objects
-implementing the corresponding Project interface (
-VC2015Project, VC2017Project, VC2019Project or VC2022Project from
-MSBuildProject.pm) to it. When Solution::Save is called, the implementations
-of Solution and Project save their content in the appropriate format.
-The final step of starting the appropriate build program (msbuild) is
-performed in build.pl again.
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
deleted file mode 100644
index 98a5b5d872..0000000000
--- a/src/tools/msvc/Solution.pm
+++ /dev/null
@@ -1,1358 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Solution;
-
-#
-# Package that encapsulates a Visual C++ solution file generation
-#
-# src/tools/msvc/Solution.pm
-#
-use Carp;
-use strict;
-use warnings;
-use VSObjectFactory;
-
-no warnings qw(redefine);    ## no critic
-
-sub _new
-{
-	my $classname = shift;
-	my $options = shift;
-	my $self = {
-		projects => {},
-		options => $options,
-		VisualStudioVersion => undef,
-		MinimumVisualStudioVersion => undef,
-		vcver => undef,
-		platform => undef,
-	};
-	bless($self, $classname);
-
-	$self->DeterminePlatform();
-
-	if ($options->{xslt} && !$options->{xml})
-	{
-		die "XSLT requires XML\n";
-	}
-	$options->{blocksize} = 8
-	  unless $options->{blocksize};    # undef or 0 means default
-	die "Bad blocksize $options->{blocksize}"
-	  unless grep { $_ == $options->{blocksize} } (1, 2, 4, 8, 16, 32);
-	$options->{segsize} = 1
-	  unless $options->{segsize};      # undef or 0 means default
-	 # only allow segsize 1 for now, as we can't do large files yet in windows
-	die "Bad segsize $options->{segsize}"
-	  unless $options->{segsize} == 1;
-	$options->{wal_blocksize} = 8
-	  unless $options->{wal_blocksize};    # undef or 0 means default
-	die "Bad wal_blocksize $options->{wal_blocksize}"
-	  unless grep { $_ == $options->{wal_blocksize} }
-	  (1, 2, 4, 8, 16, 32, 64);
-
-	return $self;
-}
-
-sub GetAdditionalHeaders
-{
-	return '';
-}
-
-sub DeterminePlatform
-{
-	my $self = shift;
-
-	if ($^O eq "MSWin32")
-	{
-		# Examine CL help output to determine if we are in 32 or 64-bit mode.
-		my $output = `cl /help 2>&1`;
-		$? >> 8 == 0 or die "cl command not found";
-		$self->{platform} =
-		  ($output =~ /^\/favor:<.+AMD64/m) ? 'x64' : 'Win32';
-	}
-	else
-	{
-		$self->{platform} = 'FAKE';
-	}
-	print "Detected hardware platform: $self->{platform}\n";
-	return;
-}
-
-# Return 1 if $oldfile is newer than $newfile, or if $newfile doesn't exist.
-# Special case - if config.pl has changed, always return 1
-sub IsNewer
-{
-	my ($newfile, $oldfile) = @_;
-	-e $oldfile or warn "source file \"$oldfile\" does not exist";
-	if (   $oldfile ne 'src/tools/msvc/config.pl'
-		&& $oldfile ne 'src/tools/msvc/config_default.pl')
-	{
-		return 1
-		  if (-f 'src/tools/msvc/config.pl')
-		  && IsNewer($newfile, 'src/tools/msvc/config.pl');
-		return 1
-		  if (-f 'src/tools/msvc/config_default.pl')
-		  && IsNewer($newfile, 'src/tools/msvc/config_default.pl');
-	}
-	return 1 if (!(-e $newfile));
-	my @nstat = stat($newfile);
-	my @ostat = stat($oldfile);
-	return 1 if ($nstat[9] < $ostat[9]);
-	return 0;
-}
-
-# Copy a file, *not* preserving date. Only works for text files.
-sub copyFile
-{
-	my ($src, $dest) = @_;
-	open(my $i, '<', $src) || croak "Could not open $src";
-	open(my $o, '>', $dest) || croak "Could not open $dest";
-	while (<$i>)
-	{
-		print $o $_;
-	}
-	close($i);
-	close($o);
-	return;
-}
-
-# Fetch version of OpenSSL based on a parsing of the command shipped with
-# the installer this build is linking to.  This returns as result an array
-# made of the three first digits of the OpenSSL version, which is enough
-# to decide which options to apply depending on the version of OpenSSL
-# linking with.
-sub GetOpenSSLVersion
-{
-	my $self = shift;
-
-	# Attempt to get OpenSSL version and location.  This assumes that
-	# openssl.exe is in the specified directory.
-	# Quote the .exe name in case it has spaces
-	my $opensslcmd =
-	  qq("$self->{options}->{openssl}\\bin\\openssl.exe" version 2>&1);
-	my $sslout = `$opensslcmd`;
-
-	$? >> 8 == 0
-	  or croak
-	  "Unable to determine OpenSSL version: The openssl.exe command wasn't found.";
-
-	if ($sslout =~ /(\d+)\.(\d+)\.(\d+)(\D)/m)
-	{
-		return ($1, $2, $3);
-	}
-
-	croak
-	  "Unable to determine OpenSSL version: The openssl.exe version could not be determined.";
-}
-
-sub GenerateFiles
-{
-	my $self = shift;
-	my $bits = $self->{platform} eq 'Win32' ? 32 : 64;
-	my $ac_init_found = 0;
-	my $package_name;
-	my $package_version;
-	my $package_bugreport;
-	my $package_url;
-	my ($majorver, $minorver);
-	my $ac_define_openssl_api_compat_found = 0;
-	my $openssl_api_compat;
-
-	# Parse configure.ac to get version numbers
-	open(my $c, '<', "configure.ac")
-	  || confess("Could not open configure.ac for reading\n");
-	while (<$c>)
-	{
-		if (/^AC_INIT\(\[([^\]]+)\], \[([^\]]+)\], \[([^\]]+)\], \[([^\]]*)\], \[([^\]]+)\]/
-		  )
-		{
-			$ac_init_found = 1;
-
-			$package_name = $1;
-			$package_version = $2;
-			$package_bugreport = $3;
-			#$package_tarname   = $4;
-			$package_url = $5;
-
-			if ($package_version !~ /^(\d+)(?:\.(\d+))?/)
-			{
-				confess "Bad format of version: $package_version\n";
-			}
-			$majorver = sprintf("%d", $1);
-			$minorver = sprintf("%d", $2 ? $2 : 0);
-		}
-		elsif (/\bAC_DEFINE\(OPENSSL_API_COMPAT, \[([0-9xL]+)\]/)
-		{
-			$ac_define_openssl_api_compat_found = 1;
-			$openssl_api_compat = $1;
-		}
-	}
-	close($c);
-	confess "Unable to parse configure.ac for all variables!"
-	  unless $ac_init_found && $ac_define_openssl_api_compat_found;
-
-	if (IsNewer("src/include/pg_config_os.h", "src/include/port/win32.h"))
-	{
-		print "Copying pg_config_os.h...\n";
-		copyFile("src/include/port/win32.h", "src/include/pg_config_os.h");
-	}
-
-	print "Generating configuration headers...\n";
-	my $extraver = $self->{options}->{extraver};
-	$extraver = '' unless defined $extraver;
-	my $port = $self->{options}->{"--with-pgport"} || 5432;
-
-	# Every symbol in pg_config.h.in must be accounted for here.  Set
-	# to undef if the symbol should not be defined.
-	my %define = (
-		ALIGNOF_DOUBLE => 8,
-		ALIGNOF_INT => 4,
-		ALIGNOF_LONG => 4,
-		ALIGNOF_LONG_LONG_INT => 8,
-		ALIGNOF_PG_INT128_TYPE => undef,
-		ALIGNOF_SHORT => 2,
-		AC_APPLE_UNIVERSAL_BUILD => undef,
-		BLCKSZ => 1024 * $self->{options}->{blocksize},
-		CONFIGURE_ARGS => '"' . $self->GetFakeConfigure() . '"',
-		DEF_PGPORT => $port,
-		DEF_PGPORT_STR => qq{"$port"},
-		DLSUFFIX => '".dll"',
-		ENABLE_GSS => $self->{options}->{gss} ? 1 : undef,
-		ENABLE_NLS => $self->{options}->{nls} ? 1 : undef,
-		HAVE_APPEND_HISTORY => undef,
-		HAVE_ASN1_STRING_GET0_DATA => undef,
-		HAVE_ATOMICS => 1,
-		HAVE_ATOMIC_H => undef,
-		HAVE_BACKTRACE_SYMBOLS => undef,
-		HAVE_BIO_GET_DATA => undef,
-		HAVE_BIO_METH_NEW => undef,
-		HAVE_COMPUTED_GOTO => undef,
-		HAVE_COPYFILE => undef,
-		HAVE_COPYFILE_H => undef,
-		HAVE_CRTDEFS_H => undef,
-		HAVE_CRYPTO_LOCK => undef,
-		HAVE_DECL_FDATASYNC => 0,
-		HAVE_DECL_F_FULLFSYNC => 0,
-		HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER => 0,
-		HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER => 0,
-		HAVE_DECL_LLVMGETHOSTCPUNAME => 0,
-		HAVE_DECL_LLVMGETHOSTCPUFEATURES => 0,
-		HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN => 0,
-		HAVE_DECL_POSIX_FADVISE => 0,
-		HAVE_DECL_PREADV => 0,
-		HAVE_DECL_PWRITEV => 0,
-		HAVE_DECL_STRLCAT => 0,
-		HAVE_DECL_STRLCPY => 0,
-		HAVE_DECL_STRNLEN => 1,
-		HAVE_EDITLINE_HISTORY_H => undef,
-		HAVE_EDITLINE_READLINE_H => undef,
-		HAVE_EXECINFO_H => undef,
-		HAVE_EXPLICIT_BZERO => undef,
-		HAVE_FSEEKO => 1,
-		HAVE_GCC__ATOMIC_INT32_CAS => undef,
-		HAVE_GCC__ATOMIC_INT64_CAS => undef,
-		HAVE_GCC__SYNC_CHAR_TAS => undef,
-		HAVE_GCC__SYNC_INT32_CAS => undef,
-		HAVE_GCC__SYNC_INT32_TAS => undef,
-		HAVE_GCC__SYNC_INT64_CAS => undef,
-		HAVE_GETIFADDRS => undef,
-		HAVE_GETOPT => undef,
-		HAVE_GETOPT_H => undef,
-		HAVE_GETOPT_LONG => undef,
-		HAVE_GETPEEREID => undef,
-		HAVE_GETPEERUCRED => undef,
-		HAVE_GSSAPI_EXT_H => undef,
-		HAVE_GSSAPI_GSSAPI_EXT_H => undef,
-		HAVE_GSSAPI_GSSAPI_H => undef,
-		HAVE_GSSAPI_H => undef,
-		HAVE_HMAC_CTX_FREE => undef,
-		HAVE_HMAC_CTX_NEW => undef,
-		HAVE_HISTORY_H => undef,
-		HAVE_HISTORY_TRUNCATE_FILE => undef,
-		HAVE_IFADDRS_H => undef,
-		HAVE_INET_ATON => undef,
-		HAVE_INET_PTON => 1,
-		HAVE_INT_TIMEZONE => 1,
-		HAVE_INT64 => undef,
-		HAVE_INT8 => undef,
-		HAVE_INTTYPES_H => undef,
-		HAVE_INT_OPTERR => undef,
-		HAVE_INT_OPTRESET => undef,
-		HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P => undef,
-		HAVE_KQUEUE => undef,
-		HAVE_LANGINFO_H => undef,
-		HAVE_LDAP_INITIALIZE => undef,
-		HAVE_LIBCRYPTO => undef,
-		HAVE_LIBLDAP => undef,
-		HAVE_LIBLZ4 => undef,
-		HAVE_LIBM => undef,
-		HAVE_LIBPAM => undef,
-		HAVE_LIBREADLINE => undef,
-		HAVE_LIBSELINUX => undef,
-		HAVE_LIBSSL => undef,
-		HAVE_LIBWLDAP32 => undef,
-		HAVE_LIBXML2 => undef,
-		HAVE_LIBXSLT => undef,
-		HAVE_LIBZ => $self->{options}->{zlib} ? 1 : undef,
-		HAVE_LIBZSTD => undef,
-		HAVE_LONG_INT_64 => undef,
-		HAVE_LONG_LONG_INT_64 => 1,
-		HAVE_MBARRIER_H => undef,
-		HAVE_MBSTOWCS_L => undef,
-		HAVE_MEMORY_H => 1,
-		HAVE_MEMSET_S => undef,
-		HAVE_MKDTEMP => undef,
-		HAVE_OPENSSL_INIT_SSL => undef,
-		HAVE_OSSP_UUID_H => undef,
-		HAVE_PAM_PAM_APPL_H => undef,
-		HAVE_POSIX_FADVISE => undef,
-		HAVE_POSIX_FALLOCATE => undef,
-		HAVE_PPOLL => undef,
-		HAVE_PTHREAD => undef,
-		HAVE_PTHREAD_BARRIER_WAIT => undef,
-		HAVE_PTHREAD_IS_THREADED_NP => undef,
-		HAVE_PTHREAD_PRIO_INHERIT => undef,
-		HAVE_READLINE_H => undef,
-		HAVE_READLINE_HISTORY_H => undef,
-		HAVE_READLINE_READLINE_H => undef,
-		HAVE_RL_COMPLETION_MATCHES => undef,
-		HAVE_RL_COMPLETION_SUPPRESS_QUOTE => undef,
-		HAVE_RL_FILENAME_COMPLETION_FUNCTION => undef,
-		HAVE_RL_FILENAME_QUOTE_CHARACTERS => undef,
-		HAVE_RL_FILENAME_QUOTING_FUNCTION => undef,
-		HAVE_RL_RESET_SCREEN_SIZE => undef,
-		HAVE_RL_VARIABLE_BIND => undef,
-		HAVE_SECURITY_PAM_APPL_H => undef,
-		HAVE_SETPROCTITLE => undef,
-		HAVE_SETPROCTITLE_FAST => undef,
-		HAVE_SOCKLEN_T => 1,
-		HAVE_SPINLOCKS => 1,
-		HAVE_SSL_CTX_SET_CERT_CB => undef,
-		HAVE_STDBOOL_H => 1,
-		HAVE_STDINT_H => 1,
-		HAVE_STDLIB_H => 1,
-		HAVE_STRCHRNUL => undef,
-		HAVE_STRERROR_R => undef,
-		HAVE_STRINGS_H => undef,
-		HAVE_STRING_H => 1,
-		HAVE_STRLCAT => undef,
-		HAVE_STRLCPY => undef,
-		HAVE_STRNLEN => 1,
-		HAVE_STRSIGNAL => undef,
-		HAVE_STRUCT_OPTION => undef,
-		HAVE_STRUCT_SOCKADDR_SA_LEN => undef,
-		HAVE_STRUCT_TM_TM_ZONE => undef,
-		HAVE_SYNC_FILE_RANGE => undef,
-		HAVE_SYNCFS => undef,
-		HAVE_SYSLOG => undef,
-		HAVE_SYS_EPOLL_H => undef,
-		HAVE_SYS_EVENT_H => undef,
-		HAVE_SYS_PERSONALITY_H => undef,
-		HAVE_SYS_PRCTL_H => undef,
-		HAVE_SYS_PROCCTL_H => undef,
-		HAVE_SYS_SIGNALFD_H => undef,
-		HAVE_SYS_STAT_H => 1,
-		HAVE_SYS_TYPES_H => 1,
-		HAVE_SYS_UCRED_H => undef,
-		HAVE_TERMIOS_H => undef,
-		HAVE_TYPEOF => undef,
-		HAVE_UCRED_H => undef,
-		HAVE_UINT64 => undef,
-		HAVE_UINT8 => undef,
-		HAVE_UNION_SEMUN => undef,
-		HAVE_UNISTD_H => 1,
-		HAVE_USELOCALE => undef,
-		HAVE_UUID_BSD => undef,
-		HAVE_UUID_E2FS => undef,
-		HAVE_UUID_OSSP => undef,
-		HAVE_UUID_H => undef,
-		HAVE_UUID_UUID_H => undef,
-		HAVE_WCSTOMBS_L => undef,
-		HAVE_VISIBILITY_ATTRIBUTE => undef,
-		HAVE_X509_GET_SIGNATURE_INFO => undef,
-		HAVE_X86_64_POPCNTQ => undef,
-		HAVE__BOOL => undef,
-		HAVE__BUILTIN_BSWAP16 => undef,
-		HAVE__BUILTIN_BSWAP32 => undef,
-		HAVE__BUILTIN_BSWAP64 => undef,
-		HAVE__BUILTIN_CLZ => undef,
-		HAVE__BUILTIN_CONSTANT_P => undef,
-		HAVE__BUILTIN_CTZ => undef,
-		HAVE__BUILTIN_FRAME_ADDRESS => undef,
-		HAVE__BUILTIN_OP_OVERFLOW => undef,
-		HAVE__BUILTIN_POPCOUNT => undef,
-		HAVE__BUILTIN_TYPES_COMPATIBLE_P => undef,
-		HAVE__BUILTIN_UNREACHABLE => undef,
-		HAVE__CONFIGTHREADLOCALE => 1,
-		HAVE__CPUID => 1,
-		HAVE__GET_CPUID => undef,
-		HAVE__STATIC_ASSERT => undef,
-		INT64_MODIFIER => qq{"ll"},
-		LOCALE_T_IN_XLOCALE => undef,
-		MAXIMUM_ALIGNOF => 8,
-		MEMSET_LOOP_LIMIT => 1024,
-		OPENSSL_API_COMPAT => $openssl_api_compat,
-		PACKAGE_BUGREPORT => qq{"$package_bugreport"},
-		PACKAGE_NAME => qq{"$package_name"},
-		PACKAGE_STRING => qq{"$package_name $package_version"},
-		PACKAGE_TARNAME => lc qq{"$package_name"},
-		PACKAGE_URL => qq{"$package_url"},
-		PACKAGE_VERSION => qq{"$package_version"},
-		PG_INT128_TYPE => undef,
-		PG_INT64_TYPE => 'long long int',
-		PG_KRB_SRVNAM => qq{"postgres"},
-		PG_MAJORVERSION => qq{"$majorver"},
-		PG_MAJORVERSION_NUM => $majorver,
-		PG_MINORVERSION_NUM => $minorver,
-		PG_PRINTF_ATTRIBUTE => undef,
-		PG_USE_STDBOOL => 1,
-		PG_VERSION => qq{"$package_version$extraver"},
-		PG_VERSION_NUM => sprintf("%d%04d", $majorver, $minorver),
-		PG_VERSION_STR =>
-		  qq{"PostgreSQL $package_version$extraver, compiled by Visual C++ build " CppAsString2(_MSC_VER) ", $bits-bit"},
-		PROFILE_PID_DIR => undef,
-		PTHREAD_CREATE_JOINABLE => undef,
-		RELSEG_SIZE => (1024 / $self->{options}->{blocksize}) *
-		  $self->{options}->{segsize} * 1024,
-		SIZEOF_BOOL => 1,
-		SIZEOF_LONG => 4,
-		SIZEOF_OFF_T => undef,
-		SIZEOF_SIZE_T => $bits / 8,
-		SIZEOF_VOID_P => $bits / 8,
-		STDC_HEADERS => 1,
-		STRERROR_R_INT => undef,
-		USE_ARMV8_CRC32C => undef,
-		USE_ARMV8_CRC32C_WITH_RUNTIME_CHECK => undef,
-		USE_ASSERT_CHECKING => $self->{options}->{asserts} ? 1 : undef,
-		USE_BONJOUR => undef,
-		USE_BSD_AUTH => undef,
-		USE_ICU => $self->{options}->{icu} ? 1 : undef,
-		USE_LIBXML => undef,
-		USE_LIBXSLT => undef,
-		USE_LZ4 => undef,
-		USE_LDAP => $self->{options}->{ldap} ? 1 : undef,
-		USE_LLVM => undef,
-		USE_LOONGARCH_CRC32C => undef,
-		USE_NAMED_POSIX_SEMAPHORES => undef,
-		USE_OPENSSL => undef,
-		USE_PAM => undef,
-		USE_SLICING_BY_8_CRC32C => undef,
-		USE_SSE42_CRC32C => undef,
-		USE_SSE42_CRC32C_WITH_RUNTIME_CHECK => 1,
-		USE_SYSTEMD => undef,
-		USE_SYSV_SEMAPHORES => undef,
-		USE_SYSV_SHARED_MEMORY => undef,
-		USE_UNNAMED_POSIX_SEMAPHORES => undef,
-		USE_WIN32_SEMAPHORES => 1,
-		USE_WIN32_SHARED_MEMORY => 1,
-		USE_ZSTD => undef,
-		WCSTOMBS_L_IN_XLOCALE => undef,
-		WORDS_BIGENDIAN => undef,
-		XLOG_BLCKSZ => 1024 * $self->{options}->{wal_blocksize},
-		_FILE_OFFSET_BITS => undef,
-		_LARGEFILE_SOURCE => undef,
-		_LARGE_FILES => undef,
-		inline => '__inline',
-		pg_restrict => '__restrict',
-		# not defined, because it'd conflict with __declspec(restrict)
-		restrict => undef,
-		typeof => undef,);
-
-	if ($self->{options}->{uuid})
-	{
-		$define{HAVE_UUID_OSSP} = 1;
-		$define{HAVE_UUID_H} = 1;
-	}
-	if ($self->{options}->{xml})
-	{
-		$define{HAVE_LIBXML2} = 1;
-		$define{USE_LIBXML} = 1;
-	}
-	if ($self->{options}->{xslt})
-	{
-		$define{HAVE_LIBXSLT} = 1;
-		$define{USE_LIBXSLT} = 1;
-	}
-	if ($self->{options}->{lz4})
-	{
-		$define{HAVE_LIBLZ4} = 1;
-		$define{USE_LZ4} = 1;
-	}
-	if ($self->{options}->{zstd})
-	{
-		$define{HAVE_LIBZSTD} = 1;
-		$define{USE_ZSTD} = 1;
-	}
-	if ($self->{options}->{openssl})
-	{
-		$define{USE_OPENSSL} = 1;
-		$define{HAVE_SSL_CTX_SET_CERT_CB} = 1;
-
-		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
-
-		# Symbols needed with OpenSSL 1.1.1 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '1'))
-		{
-			$define{HAVE_X509_GET_SIGNATURE_INFO} = 1;
-		}
-
-		# Symbols needed with OpenSSL 1.1.0 and above.
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
-		{
-			$define{HAVE_ASN1_STRING_GET0_DATA} = 1;
-			$define{HAVE_BIO_GET_DATA} = 1;
-			$define{HAVE_BIO_METH_NEW} = 1;
-			$define{HAVE_HMAC_CTX_FREE} = 1;
-			$define{HAVE_HMAC_CTX_NEW} = 1;
-			$define{HAVE_OPENSSL_INIT_SSL} = 1;
-		}
-	}
-
-	$self->GenerateConfigHeader('src/include/pg_config.h', \%define, 1);
-	$self->GenerateConfigHeader('src/include/pg_config_ext.h', \%define, 0);
-	$self->GenerateConfigHeader('src/interfaces/ecpg/include/ecpg_config.h',
-		\%define, 0);
-
-	$self->GenerateDefFile(
-		"src/interfaces/libpq/libpqdll.def",
-		"src/interfaces/libpq/exports.txt",
-		"LIBPQ");
-	$self->GenerateDefFile(
-		"src/interfaces/ecpg/ecpglib/ecpglib.def",
-		"src/interfaces/ecpg/ecpglib/exports.txt",
-		"LIBECPG");
-	$self->GenerateDefFile(
-		"src/interfaces/ecpg/compatlib/compatlib.def",
-		"src/interfaces/ecpg/compatlib/exports.txt",
-		"LIBECPG_COMPAT");
-	$self->GenerateDefFile(
-		"src/interfaces/ecpg/pgtypeslib/pgtypeslib.def",
-		"src/interfaces/ecpg/pgtypeslib/exports.txt",
-		"LIBPGTYPES");
-
-	chdir('src/backend/utils');
-	my $pg_proc_dat = '../../../src/include/catalog/pg_proc.dat';
-	if (   IsNewer('fmgr-stamp', 'Gen_fmgrtab.pl')
-		|| IsNewer('fmgr-stamp', '../catalog/Catalog.pm')
-		|| IsNewer('fmgr-stamp', $pg_proc_dat)
-		|| IsNewer('fmgr-stamp', '../../../src/include/access/transam.h'))
-	{
-		system(
-			"perl -I ../catalog Gen_fmgrtab.pl --include-path ../../../src/include/ $pg_proc_dat"
-		);
-		open(my $f, '>', 'fmgr-stamp')
-		  || confess "Could not touch fmgr-stamp";
-		close($f);
-	}
-	chdir('../../..');
-
-	if (IsNewer(
-			'src/include/utils/fmgroids.h',
-			'src/backend/utils/fmgroids.h'))
-	{
-		copyFile('src/backend/utils/fmgroids.h',
-			'src/include/utils/fmgroids.h');
-	}
-
-	if (IsNewer(
-			'src/include/utils/fmgrprotos.h',
-			'src/backend/utils/fmgrprotos.h'))
-	{
-		copyFile(
-			'src/backend/utils/fmgrprotos.h',
-			'src/include/utils/fmgrprotos.h');
-	}
-
-	if (IsNewer(
-			'src/include/storage/lwlocknames.h',
-			'src/backend/storage/lmgr/lwlocknames.txt'))
-	{
-		print "Generating lwlocknames.c and lwlocknames.h...\n";
-		my $lmgr = 'src/backend/storage/lmgr';
-		system(
-			"perl $lmgr/generate-lwlocknames.pl --outdir $lmgr $lmgr/lwlocknames.txt"
-		);
-	}
-	if (IsNewer(
-			'src/include/storage/lwlocknames.h',
-			'src/backend/storage/lmgr/lwlocknames.h'))
-	{
-		copyFile(
-			'src/backend/storage/lmgr/lwlocknames.h',
-			'src/include/storage/lwlocknames.h');
-	}
-
-	if (IsNewer(
-			'src/include/utils/wait_event_types.h',
-			'src/backend/utils/activity/wait_event_names.txt'))
-	{
-		print
-		  "Generating pgstat_wait_event.c, wait_event_types.h and wait_event_funcs_data.c...\n";
-		my $activ = 'src/backend/utils/activity';
-		system(
-			"perl $activ/generate-wait_event_types.pl --outdir $activ --code $activ/wait_event_names.txt"
-		);
-	}
-	if (IsNewer(
-			'src/include/utils/wait_event_types.h',
-			'src/backend/utils/activity/wait_event_types.h'))
-	{
-		copyFile(
-			'src/backend/utils/activity/wait_event_types.h',
-			'src/include/utils/wait_event_types.h');
-	}
-
-	if (IsNewer('src/include/utils/probes.h', 'src/backend/utils/probes.d'))
-	{
-		print "Generating probes.h...\n";
-		system(
-			'perl -n src/backend/utils/Gen_dummy_probes.pl src/backend/utils/probes.d > src/include/utils/probes.h'
-		);
-	}
-
-	if ($self->{options}->{python}
-		&& IsNewer(
-			'src/pl/plpython/spiexceptions.h',
-			'src/backend/utils/errcodes.txt'))
-	{
-		print "Generating spiexceptions.h...\n";
-		system(
-			'perl src/pl/plpython/generate-spiexceptions.pl src/backend/utils/errcodes.txt > src/pl/plpython/spiexceptions.h'
-		);
-	}
-
-	if (IsNewer(
-			'src/include/utils/errcodes.h',
-			'src/backend/utils/errcodes.txt'))
-	{
-		print "Generating errcodes.h...\n";
-		system(
-			'perl src/backend/utils/generate-errcodes.pl --outfile src/backend/utils/errcodes.h src/backend/utils/errcodes.txt'
-		);
-		copyFile('src/backend/utils/errcodes.h',
-			'src/include/utils/errcodes.h');
-	}
-
-	if (IsNewer(
-			'src/pl/plpgsql/src/plerrcodes.h',
-			'src/backend/utils/errcodes.txt'))
-	{
-		print "Generating plerrcodes.h...\n";
-		system(
-			'perl src/pl/plpgsql/src/generate-plerrcodes.pl src/backend/utils/errcodes.txt > src/pl/plpgsql/src/plerrcodes.h'
-		);
-	}
-
-	if ($self->{options}->{tcl}
-		&& IsNewer(
-			'src/pl/tcl/pltclerrcodes.h', 'src/backend/utils/errcodes.txt'))
-	{
-		print "Generating pltclerrcodes.h...\n";
-		system(
-			'perl src/pl/tcl/generate-pltclerrcodes.pl src/backend/utils/errcodes.txt > src/pl/tcl/pltclerrcodes.h'
-		);
-	}
-
-	if (IsNewer(
-			'contrib/fuzzystrmatch/daitch_mokotoff.h',
-			'contrib/fuzzystrmatch/daitch_mokotoff_header.pl'))
-	{
-		print "Generating daitch_mokotoff.h...\n";
-		system( 'perl contrib/fuzzystrmatch/daitch_mokotoff_header.pl '
-			  . 'contrib/fuzzystrmatch/daitch_mokotoff.h');
-	}
-
-	if (IsNewer('src/bin/psql/sql_help.h', 'src/bin/psql/create_help.pl'))
-	{
-		print "Generating sql_help.h...\n";
-		my $psql = 'src/bin/psql';
-		system(
-			"perl $psql/create_help.pl --docdir doc/src/sgml/ref --outdir $psql --basename sql_help"
-		);
-	}
-
-	if (IsNewer('src/common/kwlist_d.h', 'src/include/parser/kwlist.h'))
-	{
-		print "Generating kwlist_d.h...\n";
-		system(
-			'perl -I src/tools src/tools/gen_keywordlist.pl --extern -o src/common src/include/parser/kwlist.h'
-		);
-	}
-
-	if (IsNewer(
-			'src/pl/plpgsql/src/pl_reserved_kwlist_d.h',
-			'src/pl/plpgsql/src/pl_reserved_kwlist.h')
-		|| IsNewer(
-			'src/pl/plpgsql/src/pl_unreserved_kwlist_d.h',
-			'src/pl/plpgsql/src/pl_unreserved_kwlist.h'))
-	{
-		print
-		  "Generating pl_reserved_kwlist_d.h and pl_unreserved_kwlist_d.h...\n";
-		chdir('src/pl/plpgsql/src');
-		system(
-			'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname ReservedPLKeywords pl_reserved_kwlist.h'
-		);
-		system(
-			'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname UnreservedPLKeywords pl_unreserved_kwlist.h'
-		);
-		chdir('../../../..');
-	}
-
-	if (IsNewer(
-			'src/interfaces/ecpg/preproc/c_kwlist_d.h',
-			'src/interfaces/ecpg/preproc/c_kwlist.h')
-		|| IsNewer(
-			'src/interfaces/ecpg/preproc/ecpg_kwlist_d.h',
-			'src/interfaces/ecpg/preproc/ecpg_kwlist.h'))
-	{
-		print "Generating c_kwlist_d.h and ecpg_kwlist_d.h...\n";
-		chdir('src/interfaces/ecpg/preproc');
-		system(
-			'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname ScanCKeywords --no-case-fold c_kwlist.h'
-		);
-		system(
-			'perl -I ../../../tools ../../../tools/gen_keywordlist.pl --varname ScanECPGKeywords ecpg_kwlist.h'
-		);
-		chdir('../../../..');
-	}
-
-	if (IsNewer(
-			'src/interfaces/ecpg/preproc/preproc.y',
-			'src/backend/parser/gram.y'))
-	{
-		print "Generating preproc.y...\n";
-		my $ecpg = 'src/interfaces/ecpg';
-		system(
-			"perl $ecpg/preproc/parse.pl --srcdir $ecpg/preproc --parser src/backend/parser/gram.y --output $ecpg/preproc/preproc.y"
-		);
-	}
-
-	unless (-f "src/port/pg_config_paths.h")
-	{
-		print "Generating pg_config_paths.h...\n";
-		open(my $o, '>', 'src/port/pg_config_paths.h')
-		  || confess "Could not open pg_config_paths.h";
-		print $o <<EOF;
-#define PGBINDIR "/bin"
-#define PGSHAREDIR "/share"
-#define SYSCONFDIR "/etc"
-#define INCLUDEDIR "/include"
-#define PKGINCLUDEDIR "/include"
-#define INCLUDEDIRSERVER "/include/server"
-#define LIBDIR "/lib"
-#define PKGLIBDIR "/lib"
-#define LOCALEDIR "/share/locale"
-#define DOCDIR "/doc"
-#define HTMLDIR "/doc"
-#define MANDIR "/man"
-EOF
-		close($o);
-	}
-
-	my $mf = Project::read_file('src/backend/catalog/Makefile');
-	$mf =~ s{\\\r?\n}{}g;
-	$mf =~ /^CATALOG_HEADERS\s*:?=(.*)$/gm
-	  || croak "Could not find CATALOG_HEADERS in Makefile\n";
-	my @bki_srcs = split /\s+/, $1;
-	$mf =~ /^POSTGRES_BKI_DATA\s*:?=[^,]+,(.*)\)$/gm
-	  || croak "Could not find POSTGRES_BKI_DATA in Makefile\n";
-	my @bki_data = split /\s+/, $1;
-
-	my $need_genbki = 0;
-	foreach my $bki (@bki_srcs, @bki_data)
-	{
-		next if $bki eq "";
-		if (IsNewer(
-				'src/backend/catalog/bki-stamp',
-				"src/include/catalog/$bki"))
-		{
-			$need_genbki = 1;
-			last;
-		}
-	}
-	$need_genbki = 1
-	  if IsNewer('src/backend/catalog/bki-stamp',
-		'src/backend/catalog/genbki.pl');
-	$need_genbki = 1
-	  if IsNewer('src/backend/catalog/bki-stamp',
-		'src/backend/catalog/Catalog.pm');
-	if ($need_genbki)
-	{
-		chdir('src/backend/catalog');
-		my $bki_srcs = join(' ../../../src/include/catalog/', @bki_srcs);
-		system(
-			"perl genbki.pl --include-path ../../../src/include/ --set-version=$majorver $bki_srcs"
-		);
-		open(my $f, '>', 'bki-stamp')
-		  || confess "Could not touch bki-stamp";
-		close($f);
-		chdir('../../..');
-	}
-
-	if (IsNewer(
-			'src/include/catalog/header-stamp',
-			'src/backend/catalog/bki-stamp'))
-	{
-		# Copy generated headers to include directory.
-		opendir(my $dh, 'src/backend/catalog/')
-		  || die "Can't opendir src/backend/catalog/ $!";
-		my @def_headers = grep { /pg_\w+_d\.h$/ } readdir($dh);
-		closedir $dh;
-		foreach my $def_header (@def_headers)
-		{
-			copyFile(
-				"src/backend/catalog/$def_header",
-				"src/include/catalog/$def_header");
-		}
-		copyFile(
-			'src/backend/catalog/schemapg.h',
-			'src/include/catalog/schemapg.h');
-		copyFile(
-			'src/backend/catalog/system_fk_info.h',
-			'src/include/catalog/system_fk_info.h');
-		open(my $chs, '>', 'src/include/catalog/header-stamp')
-		  || confess "Could not touch header-stamp";
-		close($chs);
-	}
-
-	my $nmf = Project::read_file('src/backend/nodes/Makefile');
-	$nmf =~ s{\\\r?\n}{}g;
-	$nmf =~ /^node_headers\s*:?=(.*)$/gm
-	  || croak "Could not find node_headers in Makefile\n";
-	my @node_headers = split /\s+/, $1;
-	@node_headers = grep { $_ ne '' } @node_headers;
-	my @node_files = map { "src/include/$_" } @node_headers;
-
-	my $need_node_support = 0;
-	foreach my $nodefile (@node_files)
-	{
-		if (IsNewer('src/backend/nodes/node-support-stamp', $nodefile))
-		{
-			$need_node_support = 1;
-			last;
-		}
-	}
-	$need_node_support = 1
-	  if IsNewer(
-		'src/backend/nodes/node-support-stamp',
-		'src/backend/nodes/gen_node_support.pl');
-
-	if ($need_node_support)
-	{
-		system(
-			"perl src/backend/nodes/gen_node_support.pl --outdir src/backend/nodes @node_files"
-		);
-		open(my $f, '>', 'src/backend/nodes/node-support-stamp')
-		  || confess "Could not touch node-support-stamp";
-		close($f);
-	}
-
-	if (IsNewer(
-			'src/include/nodes/nodetags.h',
-			'src/backend/nodes/nodetags.h'))
-	{
-		copyFile('src/backend/nodes/nodetags.h',
-			'src/include/nodes/nodetags.h');
-	}
-
-	open(my $o, '>', "doc/src/sgml/version.sgml")
-	  || croak "Could not write to version.sgml\n";
-	print $o <<EOF;
-<!ENTITY version "$package_version">
-<!ENTITY majorversion "$majorver">
-EOF
-	close($o);
-	return;
-}
-
-# Read lines from input file and substitute symbols using the same
-# logic that config.status uses.  There should be one call of this for
-# each AC_CONFIG_HEADERS call in configure.ac.
-#
-# If the "required" argument is true, we also keep track which of our
-# defines have been found and error out if any are left unused at the
-# end.  That way we avoid accumulating defines in this file that are
-# no longer used by configure.
-sub GenerateConfigHeader
-{
-	my ($self, $config_header, $defines, $required) = @_;
-
-	my $config_header_in = $config_header . '.in';
-
-	if (   IsNewer($config_header, $config_header_in)
-		|| IsNewer($config_header, __FILE__))
-	{
-		my %defines_copy = %$defines;
-
-		open(my $i, '<', $config_header_in)
-		  || confess "Could not open $config_header_in\n";
-		open(my $o, '>', $config_header)
-		  || confess "Could not write to $config_header\n";
-
-		print $o
-		  "/* $config_header.  Generated from $config_header_in by src/tools/msvc/Solution.pm.  */\n";
-
-		while (<$i>)
-		{
-			if (m/^#(\s*)undef\s+(\w+)/)
-			{
-				my $ws = $1;
-				my $macro = $2;
-				if (exists $defines->{$macro})
-				{
-					if (defined $defines->{$macro})
-					{
-						print $o "#${ws}define $macro ", $defines->{$macro},
-						  "\n";
-					}
-					else
-					{
-						print $o "/* #${ws}undef $macro */\n";
-					}
-					delete $defines_copy{$macro};
-				}
-				else
-				{
-					croak
-					  "undefined symbol: $macro at $config_header line $.";
-				}
-			}
-			else
-			{
-				print $o $_;
-			}
-		}
-		close($o);
-		close($i);
-
-		if ($required && scalar(keys %defines_copy) > 0)
-		{
-			croak "unused defines: " . join(' ', keys %defines_copy);
-		}
-	}
-}
-
-sub GenerateDefFile
-{
-	my ($self, $deffile, $txtfile, $libname) = @_;
-
-	if (IsNewer($deffile, $txtfile))
-	{
-		print "Generating $deffile...\n";
-		open(my $if, '<', $txtfile) || confess("Could not open $txtfile\n");
-		open(my $of, '>', $deffile) || confess("Could not open $deffile\n");
-		print $of "LIBRARY $libname\nEXPORTS\n";
-		while (<$if>)
-		{
-			next if (/^#/);
-			next if (/^\s*$/);
-			my ($f, $o) = split;
-			print $of " $f @ $o\n";
-		}
-		close($of);
-		close($if);
-	}
-	return;
-}
-
-sub AddProject
-{
-	my ($self, $name, $type, $folder, $initialdir) = @_;
-
-	my $proj =
-	  VSObjectFactory::CreateProject($self->{vcver}, $name, $type, $self);
-	push @{ $self->{projects}->{$folder} }, $proj;
-	$proj->AddDir($initialdir) if ($initialdir);
-	if ($self->{options}->{zlib})
-	{
-		$proj->AddIncludeDir($self->{options}->{zlib} . '\include');
-		$proj->AddLibrary($self->{options}->{zlib} . '\lib\zdll.lib');
-	}
-	if ($self->{options}->{openssl})
-	{
-		$proj->AddIncludeDir($self->{options}->{openssl} . '\include');
-		my ($digit1, $digit2, $digit3) = $self->GetOpenSSLVersion();
-
-		# Starting at version 1.1.0 the OpenSSL installers have
-		# changed their library names from:
-		# - libeay to libcrypto
-		# - ssleay to libssl
-		if (   ($digit1 >= '3' && $digit2 >= '0' && $digit3 >= '0')
-			|| ($digit1 >= '1' && $digit2 >= '1' && $digit3 >= '0'))
-		{
-			my $dbgsuffix;
-			my $libsslpath;
-			my $libcryptopath;
-
-			# The format name of the libraries is slightly
-			# different between the Win32 and Win64 platform, so
-			# adapt.
-			if (-e "$self->{options}->{openssl}/lib/VC/sslcrypto32MD.lib")
-			{
-				# Win32 here, with a debugging library set.
-				$dbgsuffix = 1;
-				$libsslpath = '\lib\VC\libssl32.lib';
-				$libcryptopath = '\lib\VC\libcrypto32.lib';
-			}
-			elsif (-e "$self->{options}->{openssl}/lib/VC/sslcrypto64MD.lib")
-			{
-				# Win64 here, with a debugging library set.
-				$dbgsuffix = 1;
-				$libsslpath = '\lib\VC\libssl64.lib';
-				$libcryptopath = '\lib\VC\libcrypto64.lib';
-			}
-			else
-			{
-				# On both Win32 and Win64 the same library
-				# names are used without a debugging context.
-				$dbgsuffix = 0;
-				$libsslpath = '\lib\libssl.lib';
-				$libcryptopath = '\lib\libcrypto.lib';
-			}
-
-			$proj->AddLibrary($self->{options}->{openssl} . $libsslpath,
-				$dbgsuffix);
-			$proj->AddLibrary($self->{options}->{openssl} . $libcryptopath,
-				$dbgsuffix);
-		}
-		else
-		{
-			# Choose which set of libraries to use depending on if
-			# debugging libraries are in place in the installer.
-			if (-e "$self->{options}->{openssl}/lib/VC/ssleay32MD.lib")
-			{
-				$proj->AddLibrary(
-					$self->{options}->{openssl} . '\lib\VC\ssleay32.lib', 1);
-				$proj->AddLibrary(
-					$self->{options}->{openssl} . '\lib\VC\libeay32.lib', 1);
-			}
-			else
-			{
-				# We don't expect the config-specific library
-				# to be here, so don't ask for it in last
-				# parameter.
-				$proj->AddLibrary(
-					$self->{options}->{openssl} . '\lib\ssleay32.lib', 0);
-				$proj->AddLibrary(
-					$self->{options}->{openssl} . '\lib\libeay32.lib', 0);
-			}
-		}
-	}
-	if ($self->{options}->{nls})
-	{
-		$proj->AddIncludeDir($self->{options}->{nls} . '\include');
-		$proj->AddLibrary($self->{options}->{nls} . '\lib\libintl.lib');
-	}
-	if ($self->{options}->{gss})
-	{
-		$proj->AddIncludeDir($self->{options}->{gss} . '\include');
-		$proj->AddIncludeDir($self->{options}->{gss} . '\include\krb5');
-		if ($self->{platform} eq 'Win32')
-		{
-			$proj->AddLibrary(
-				$self->{options}->{gss} . '\lib\i386\krb5_32.lib');
-			$proj->AddLibrary(
-				$self->{options}->{gss} . '\lib\i386\comerr32.lib');
-			$proj->AddLibrary(
-				$self->{options}->{gss} . '\lib\i386\gssapi32.lib');
-		}
-		else
-		{
-			$proj->AddLibrary(
-				$self->{options}->{gss} . '\lib\amd64\krb5_64.lib');
-			$proj->AddLibrary(
-				$self->{options}->{gss} . '\lib\amd64\comerr64.lib');
-			$proj->AddLibrary(
-				$self->{options}->{gss} . '\lib\amd64\gssapi64.lib');
-		}
-	}
-	if ($self->{options}->{iconv})
-	{
-		$proj->AddIncludeDir($self->{options}->{iconv} . '\include');
-		$proj->AddLibrary($self->{options}->{iconv} . '\lib\iconv.lib');
-	}
-	if ($self->{options}->{icu})
-	{
-		$proj->AddIncludeDir($self->{options}->{icu} . '\include');
-		if ($self->{platform} eq 'Win32')
-		{
-			$proj->AddLibrary($self->{options}->{icu} . '\lib\icuin.lib');
-			$proj->AddLibrary($self->{options}->{icu} . '\lib\icuuc.lib');
-			$proj->AddLibrary($self->{options}->{icu} . '\lib\icudt.lib');
-		}
-		else
-		{
-			$proj->AddLibrary($self->{options}->{icu} . '\lib64\icuin.lib');
-			$proj->AddLibrary($self->{options}->{icu} . '\lib64\icuuc.lib');
-			$proj->AddLibrary($self->{options}->{icu} . '\lib64\icudt.lib');
-		}
-	}
-	if ($self->{options}->{xml})
-	{
-		$proj->AddIncludeDir($self->{options}->{xml} . '\include');
-		$proj->AddIncludeDir($self->{options}->{xml} . '\include\libxml2');
-		$proj->AddLibrary($self->{options}->{xml} . '\lib\libxml2.lib');
-	}
-	if ($self->{options}->{xslt})
-	{
-		$proj->AddIncludeDir($self->{options}->{xslt} . '\include');
-		$proj->AddLibrary($self->{options}->{xslt} . '\lib\libxslt.lib');
-	}
-	if ($self->{options}->{lz4})
-	{
-		$proj->AddIncludeDir($self->{options}->{lz4} . '\include');
-		$proj->AddLibrary($self->{options}->{lz4} . '\lib\liblz4.lib');
-	}
-	if ($self->{options}->{zstd})
-	{
-		$proj->AddIncludeDir($self->{options}->{zstd} . '\include');
-		$proj->AddLibrary($self->{options}->{zstd} . '\lib\libzstd.lib');
-	}
-	if ($self->{options}->{uuid})
-	{
-		$proj->AddIncludeDir($self->{options}->{uuid} . '\include');
-		$proj->AddLibrary($self->{options}->{uuid} . '\lib\uuid.lib');
-	}
-	return $proj;
-}
-
-sub Save
-{
-	my ($self) = @_;
-	my %flduid;
-
-	$self->GenerateFiles();
-	foreach my $fld (keys %{ $self->{projects} })
-	{
-		foreach my $proj (@{ $self->{projects}->{$fld} })
-		{
-			$proj->Save();
-		}
-	}
-
-	open(my $sln, '>', "pgsql.sln") || croak "Could not write to pgsql.sln\n";
-	print $sln <<EOF;
-Microsoft Visual Studio Solution File, Format Version $self->{solutionFileVersion}
-# $self->{visualStudioName}
-EOF
-
-	print $sln $self->GetAdditionalHeaders();
-
-	foreach my $fld (keys %{ $self->{projects} })
-	{
-		foreach my $proj (@{ $self->{projects}->{$fld} })
-		{
-			print $sln <<EOF;
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "$proj->{name}", "$proj->{name}$proj->{filenameExtension}", "$proj->{guid}"
-EndProject
-EOF
-		}
-		if ($fld ne "")
-		{
-			$flduid{$fld} = $^O eq "MSWin32" ? Win32::GuidGen() : 'FAKE';
-			print $sln <<EOF;
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "$fld", "$fld", "$flduid{$fld}"
-EndProject
-EOF
-		}
-	}
-
-	print $sln <<EOF;
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|$self->{platform}= Debug|$self->{platform}
-		Release|$self->{platform} = Release|$self->{platform}
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-EOF
-
-	foreach my $fld (keys %{ $self->{projects} })
-	{
-		foreach my $proj (@{ $self->{projects}->{$fld} })
-		{
-			print $sln <<EOF;
-		$proj->{guid}.Debug|$self->{platform}.ActiveCfg = Debug|$self->{platform}
-		$proj->{guid}.Debug|$self->{platform}.Build.0  = Debug|$self->{platform}
-		$proj->{guid}.Release|$self->{platform}.ActiveCfg = Release|$self->{platform}
-		$proj->{guid}.Release|$self->{platform}.Build.0 = Release|$self->{platform}
-EOF
-		}
-	}
-
-	print $sln <<EOF;
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-	GlobalSection(NestedProjects) = preSolution
-EOF
-
-	foreach my $fld (keys %{ $self->{projects} })
-	{
-		next if ($fld eq "");
-		foreach my $proj (@{ $self->{projects}->{$fld} })
-		{
-			print $sln "\t\t$proj->{guid} = $flduid{$fld}\n";
-		}
-	}
-
-	print $sln <<EOF;
-	EndGlobalSection
-EndGlobal
-EOF
-	close($sln);
-	return;
-}
-
-sub GetFakeConfigure
-{
-	my $self = shift;
-
-	my $cfg = '';
-	$cfg .= ' --enable-cassert' if ($self->{options}->{asserts});
-	$cfg .= ' --enable-nls' if ($self->{options}->{nls});
-	$cfg .= ' --enable-tap-tests' if ($self->{options}->{tap_tests});
-	$cfg .= ' --with-ldap' if ($self->{options}->{ldap});
-	$cfg .= ' --without-zlib' unless ($self->{options}->{zlib});
-	$cfg .= ' --with-extra-version' if ($self->{options}->{extraver});
-	$cfg .= ' --with-ssl=openssl' if ($self->{options}->{openssl});
-	$cfg .= ' --with-uuid' if ($self->{options}->{uuid});
-	$cfg .= ' --with-libxml' if ($self->{options}->{xml});
-	$cfg .= ' --with-libxslt' if ($self->{options}->{xslt});
-	$cfg .= ' --with-lz4' if ($self->{options}->{lz4});
-	$cfg .= ' --with-zstd' if ($self->{options}->{zstd});
-	$cfg .= ' --with-gssapi' if ($self->{options}->{gss});
-	$cfg .= ' --with-icu' if ($self->{options}->{icu});
-	$cfg .= ' --with-tcl' if ($self->{options}->{tcl});
-	$cfg .= ' --with-perl' if ($self->{options}->{perl});
-	$cfg .= ' --with-python' if ($self->{options}->{python});
-	my $port = $self->{options}->{'--with-pgport'};
-	$cfg .= " --with-pgport=$port" if defined($port);
-
-	return $cfg;
-}
-
-package VS2015Solution;
-
-#
-# Package that encapsulates a Visual Studio 2015 solution file
-#
-
-use Carp;
-use strict;
-use warnings;
-use base qw(Solution);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{solutionFileVersion} = '12.00';
-	$self->{vcver} = '14.00';
-	$self->{visualStudioName} = 'Visual Studio 2015';
-	$self->{VisualStudioVersion} = '14.0.24730.2';
-	$self->{MinimumVisualStudioVersion} = '10.0.40219.1';
-
-	return $self;
-}
-
-package VS2017Solution;
-
-#
-# Package that encapsulates a Visual Studio 2017 solution file
-#
-
-use Carp;
-use strict;
-use warnings;
-use base qw(Solution);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{solutionFileVersion} = '12.00';
-	$self->{vcver} = '15.00';
-	$self->{visualStudioName} = 'Visual Studio 2017';
-	$self->{VisualStudioVersion} = '15.0.26730.3';
-	$self->{MinimumVisualStudioVersion} = '10.0.40219.1';
-
-	return $self;
-}
-
-package VS2019Solution;
-
-#
-# Package that encapsulates a Visual Studio 2019 solution file
-#
-
-use Carp;
-use strict;
-use warnings;
-use base qw(Solution);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{solutionFileVersion} = '12.00';
-	$self->{vcver} = '16.00';
-	$self->{visualStudioName} = 'Visual Studio 2019';
-	$self->{VisualStudioVersion} = '16.0.28729.10';
-	$self->{MinimumVisualStudioVersion} = '10.0.40219.1';
-
-	return $self;
-}
-
-package VS2022Solution;
-
-#
-# Package that encapsulates a Visual Studio 2022 solution file
-#
-
-use Carp;
-use strict;
-use warnings;
-use base qw(Solution);
-
-no warnings qw(redefine);    ## no critic
-
-sub new
-{
-	my $classname = shift;
-	my $self = $classname->SUPER::_new(@_);
-	bless($self, $classname);
-
-	$self->{solutionFileVersion} = '12.00';
-	$self->{vcver} = '17.00';
-	$self->{visualStudioName} = 'Visual Studio 2022';
-	$self->{VisualStudioVersion} = '17.0.31903.59';
-	$self->{MinimumVisualStudioVersion} = '10.0.40219.1';
-
-	return $self;
-}
-
-sub GetAdditionalHeaders
-{
-	my ($self, $f) = @_;
-
-	return qq|VisualStudioVersion = $self->{VisualStudioVersion}
-MinimumVisualStudioVersion = $self->{MinimumVisualStudioVersion}
-|;
-}
-
-1;
diff --git a/src/tools/msvc/VSObjectFactory.pm b/src/tools/msvc/VSObjectFactory.pm
deleted file mode 100644
index 9df2ab4282..0000000000
--- a/src/tools/msvc/VSObjectFactory.pm
+++ /dev/null
@@ -1,174 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package VSObjectFactory;
-
-#
-# Package that creates Visual Studio wrapper objects for msvc build
-#
-# src/tools/msvc/VSObjectFactory.pm
-#
-
-use Carp;
-use strict;
-use warnings;
-
-use Exporter;
-use Project;
-use Solution;
-use MSBuildProject;
-
-our (@ISA, @EXPORT);
-@ISA = qw(Exporter);
-@EXPORT = qw(CreateSolution CreateProject DetermineVisualStudioVersion);
-
-no warnings qw(redefine);    ## no critic
-
-sub CreateSolution
-{
-	my $visualStudioVersion = shift;
-
-	if (!defined($visualStudioVersion))
-	{
-		$visualStudioVersion = DetermineVisualStudioVersion();
-	}
-
-	if ($visualStudioVersion eq '14.00')
-	{
-		return new VS2015Solution(@_);
-	}
-
-	# The version of nmake bundled in Visual Studio 2017 is greater
-	# than 14.10 and less than 14.20.  And the version number is
-	# actually 15.00.
-	elsif (
-		($visualStudioVersion ge '14.10' && $visualStudioVersion lt '14.20')
-		|| $visualStudioVersion eq '15.00')
-	{
-		return new VS2017Solution(@_);
-	}
-
-	# The version of nmake bundled in Visual Studio 2019 is greater
-	# than 14.20 and less than 14.30.  And the version number is
-	# actually 16.00.
-	elsif (
-		($visualStudioVersion ge '14.20' && $visualStudioVersion lt '14.30')
-		|| $visualStudioVersion eq '16.00')
-	{
-		return new VS2019Solution(@_);
-	}
-
-	# The version of nmake bundled in Visual Studio 2022 is greater
-	# than 14.30 and less than 14.40.  And the version number is
-	# actually 17.00.
-	elsif (
-		($visualStudioVersion ge '14.30' && $visualStudioVersion lt '14.40')
-		|| $visualStudioVersion eq '17.00')
-	{
-		return new VS2022Solution(@_);
-	}
-	else
-	{
-		croak
-		  "The requested Visual Studio version $visualStudioVersion is not supported.";
-	}
-}
-
-sub CreateProject
-{
-	my $visualStudioVersion = shift;
-
-	if (!defined($visualStudioVersion))
-	{
-		$visualStudioVersion = DetermineVisualStudioVersion();
-	}
-
-	if ($visualStudioVersion eq '14.00')
-	{
-		return new VC2015Project(@_);
-	}
-
-	# The version of nmake bundled in Visual Studio 2017 is greater
-	# than 14.10 and less than 14.20.  And the version number is
-	# actually 15.00.
-	elsif (
-		($visualStudioVersion ge '14.10' && $visualStudioVersion lt '14.20')
-		|| $visualStudioVersion eq '15.00')
-	{
-		return new VC2017Project(@_);
-	}
-
-	# The version of nmake bundled in Visual Studio 2019 is greater
-	# than 14.20 and less than 14.30.  And the version number is
-	# actually 16.00.
-	elsif (
-		($visualStudioVersion ge '14.20' && $visualStudioVersion lt '14.30')
-		|| $visualStudioVersion eq '16.00')
-	{
-		return new VC2019Project(@_);
-	}
-
-	# The version of nmake bundled in Visual Studio 2022 is greater
-	# than 14.30 and less than 14.40.  And the version number is
-	# actually 17.00.
-	elsif (
-		($visualStudioVersion ge '14.30' && $visualStudioVersion lt '14.40')
-		|| $visualStudioVersion eq '17.00')
-	{
-		return new VC2022Project(@_);
-	}
-	else
-	{
-		croak
-		  "The requested Visual Studio version $visualStudioVersion is not supported.";
-	}
-}
-
-sub DetermineVisualStudioVersion
-{
-	if ($^O eq "MSWin32")
-	{
-		# To determine version of Visual Studio we use nmake as it has
-		# existed for a long time and still exists in current Visual
-		# Studio versions.
-		my $output = `nmake /? 2>&1`;
-		$? >> 8 == 0
-		  or croak
-		  "Unable to determine Visual Studio version: The nmake command wasn't found.";
-		if ($output =~ /(\d+)\.(\d+)\.\d+(\.\d+)?/)
-		{
-			return _GetVisualStudioVersion($1, $2);
-		}
-
-		croak
-		  "Unable to determine Visual Studio version: The nmake version could not be determined.";
-	}
-	else
-	{
-		# fake version
-		return '17.00';
-	}
-}
-
-sub _GetVisualStudioVersion
-{
-	my ($major, $minor) = @_;
-
-	# The major visual studio that is supported has nmake
-	# version <= 14.40, so stick with it as the latest version
-	# if bumping on something even newer.
-	if ($major >= 14 && $minor >= 40)
-	{
-		carp
-		  "The determined version of Visual Studio is newer than the latest supported version. Returning the latest supported version instead.";
-		return '14.30';
-	}
-	elsif ($major < 12)
-	{
-		croak
-		  "Unable to determine Visual Studio version: Visual Studio versions before 12.0 aren't supported.";
-	}
-	return "$major.$minor";
-}
-
-1;
diff --git a/src/tools/msvc/build.bat b/src/tools/msvc/build.bat
deleted file mode 100755
index 171f7498e2..0000000000
--- a/src/tools/msvc/build.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-@echo off
-REM src/tools/msvc/build.bat
-REM all the logic for this now belongs in build.pl. This file really
-REM only exists so you don't have to type "perl build.pl"
-REM Resist any temptation to add any logic here.
-@perl %~dp0/build.pl %*
diff --git a/src/tools/msvc/build.pl b/src/tools/msvc/build.pl
deleted file mode 100644
index 9853e5c3d8..0000000000
--- a/src/tools/msvc/build.pl
+++ /dev/null
@@ -1,92 +0,0 @@
-# -*-perl-*- hey - emacs - this is a perl file
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-#
-# Script that provides 'make' functionality for msvc builds.
-#
-# src/tools/msvc/build.pl
-#
-use strict;
-use warnings;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use Cwd;
-
-use Mkvcbuild;
-
-sub usage
-{
-	die(    "Usage: build.pl [ [ <configuration> ] <component> ]\n"
-		  . "Options are case-insensitive.\n"
-		  . "  configuration: Release | Debug.  This sets the configuration\n"
-		  . "    to build.  Default is Release.\n"
-		  . "  component: name of component to build.  An empty value means\n"
-		  . "    to build all components.\n");
-}
-
-chdir('../../..') if (-d '../msvc' && -d '../../../src');
-die 'Must run from root or msvc directory'
-  unless (-d 'src/tools/msvc' && -d 'src');
-
-usage() unless scalar(@ARGV) <= 2;
-
-# buildenv.pl is for specifying the build environment settings
-# it should contain lines like:
-# $ENV{PATH} = "c:/path/to/bison/bin;$ENV{PATH}";
-
-if (-e "src/tools/msvc/buildenv.pl")
-{
-	do "./src/tools/msvc/buildenv.pl";
-}
-elsif (-e "./buildenv.pl")
-{
-	do "./buildenv.pl";
-}
-
-# set up the project
-our $config;
-do "./src/tools/msvc/config_default.pl";
-do "./src/tools/msvc/config.pl" if (-f "src/tools/msvc/config.pl");
-
-my $vcver = Mkvcbuild::mkvcbuild($config);
-
-# check what sort of build we are doing
-my $bconf = $ENV{CONFIG} || "Release";
-my $msbflags = $ENV{MSBFLAGS} || "";
-my $buildwhat = $ARGV[1] || "";
-
-if (defined($ARGV[0]))
-{
-	if (uc($ARGV[0]) eq 'DEBUG')
-	{
-		$bconf = "Debug";
-	}
-	elsif (uc($ARGV[0]) ne "RELEASE")
-	{
-		$buildwhat = $ARGV[0] || "";
-	}
-}
-
-# ... and do it
-
-if ($buildwhat)
-{
-	system(
-		"msbuild $buildwhat.vcxproj /verbosity:normal $msbflags /p:Configuration=$bconf"
-	);
-}
-else
-{
-	system(
-		"msbuild pgsql.sln /verbosity:normal $msbflags /p:Configuration=$bconf"
-	);
-}
-
-# report status
-
-my $status = $? >> 8;
-
-exit $status;
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
deleted file mode 100755
index ac8da581e4..0000000000
--- a/src/tools/msvc/clean.bat
+++ /dev/null
@@ -1,160 +0,0 @@
-@echo off
-REM src/tools/msvc/clean.bat
-
-set DIST=0
-if "%1"=="dist" set DIST=1
-
-setlocal
-
-cd "%~dp0\..\..\.."
-
-if exist debug rd /s /q debug
-if exist release rd /s /q release
-for %%f in (*.vcproj) do del %%f
-for %%f in (*.vcxproj) do del %%f
-for %%f in (*.vcxproj.user) do del %%f
-if exist pgsql.sln del /q pgsql.sln
-if exist pgsql.sln.cache del /q pgsql.sln.cache
-if exist pgsql.sdf del /q pgsql.sdf
-if exist pgsql.suo del /q /a:H pgsql.suo
-del /s /q src\bin\win32ver.rc 2> NUL
-del /s /q src\interfaces\win32ver.rc 2> NUL
-if exist src\backend\win32ver.rc del /q src\backend\win32ver.rc
-if exist src\backend\replication\libpqwalreceiver\win32ver.rc del /q src\backend\replication\libpqwalreceiver\win32ver.rc
-if exist src\backend\replication\pgoutput\win32ver.rc del /q src\backend\replication\pgoutput\win32ver.rc
-if exist src\backend\snowball\win32ver.rc del /q src\backend\snowball\win32ver.rc
-if exist src\interfaces\ecpg\test\win32ver.rc del /q src\interfaces\ecpg\test\win32ver.rc
-if exist src\pl\plperl\win32ver.rc del /q src\pl\plperl\win32ver.rc
-if exist src\pl\plpgsql\src\win32ver.rc del /q src\pl\plpgsql\src\win32ver.rc
-if exist src\pl\plpython\win32ver.rc del /q src\pl\plpython\win32ver.rc
-if exist src\pl\tcl\win32ver.rc del /q src\pl\tcl\win32ver.rc
-if exist src\test\isolation\win32ver.rc del /q src\test\isolation\win32ver.rc
-if exist src\test\regress\win32ver.rc del /q src\test\regress\win32ver.rc
-if exist src\timezone\win32ver.rc del /q src\timezone\win32ver.rc
-
-for /d %%f in (src\interfaces\ecpg\*) do if exist %%f\win32ver.rc del /q %%f\win32ver.rc
-for /d %%f in (contrib\*) do if exist %%f\win32ver.rc del /q %%f\win32ver.rc
-for /d %%f in (src\backend\utils\mb\conversion_procs\*) do if exist %%f\win32ver.rc del /q %%f\win32ver.rc
-for /d %%f in (src\test\modules\*) do if exist %%f\win32ver.rc del /q %%f\win32ver.rc
-
-REM Delete files created with GenerateFiles() in Solution.pm
-if exist src\include\pg_config.h del /q src\include\pg_config.h
-if exist src\include\pg_config_ext.h del /q src\include\pg_config_ext.h
-if exist src\include\pg_config_os.h del /q src\include\pg_config_os.h
-if exist src\include\nodes\nodetags.h del /q src\include\nodes\nodetags.h
-if exist src\include\utils\errcodes.h del /q src\include\utils\errcodes.h
-if exist src\include\utils\fmgroids.h del /q src\include\utils\fmgroids.h
-if exist src\include\utils\fmgrprotos.h del /q src\include\utils\fmgrprotos.h
-if exist src\include\storage\lwlocknames.h del /q src\include\storage\lwlocknames.h
-if exist src\include\utils\wait_event_types.h del /q src\include\utils\wait_event_types.h
-if exist src\include\utils\probes.h del /q src\include\utils\probes.h
-if exist src\include\catalog\schemapg.h del /q src\include\catalog\schemapg.h
-if exist src\include\catalog\system_fk_info.h del /q src\include\catalog\system_fk_info.h
-if exist src\include\catalog\pg_*_d.h del /q src\include\catalog\pg_*_d.h
-if exist src\include\catalog\header-stamp del /q src\include\catalog\header-stamp
-if exist doc\src\sgml\version.sgml del /q doc\src\sgml\version.sgml
-
-if %DIST%==1 if exist src\backend\utils\activity\pgstat_wait_event.c del /q src\backend\utils\activity\pgstat_wait_event.c
-if %DIST%==1 if exist src\backend\utils\activity\wait_event_funcs_data.c del /q src\backend\utils\activity\wait_event_funcs_data.c
-if %DIST%==1 if exist src\backend\utils\activity\wait_event_types.h del /q src\backend\utils\activity\wait_event_types.h
-if %DIST%==1 if exist src\backend\utils\fmgroids.h del /q src\backend\utils\fmgroids.h
-if %DIST%==1 if exist src\backend\utils\fmgrprotos.h del /q src\backend\utils\fmgrprotos.h
-if %DIST%==1 if exist src\backend\utils\fmgrtab.c del /q src\backend\utils\fmgrtab.c
-if %DIST%==1 if exist src\backend\utils\fmgr-stamp del /q src\backend\utils\fmgr-stamp
-if %DIST%==1 if exist src\backend\utils\errcodes.h del /q src\backend\utils\errcodes.h
-if %DIST%==1 if exist src\backend\nodes\node-support-stamp del /q src\backend\nodes\node-support-stamp
-if %DIST%==1 for %%F IN (copy equal out queryjumble read) do if exist src\backend\nodes\%%Ffuncs.funcs.c del /q src\backend\nodes\%%Ffuncs.funcs.c
-if %DIST%==1 for %%F IN (copy equal out queryjumble read) do if exist src\backend\nodes\%%Ffuncs.switch.c del /q src\backend\nodes\%%Ffuncs.switch.c
-if %DIST%==1 if exist src\backend\nodes\nodetags.h del /q src\backend\nodes\nodetags.h
-if %DIST%==1 if exist src\backend\storage\lmgr\lwlocknames.c del /q src\backend\storage\lmgr\lwlocknames.c
-if %DIST%==1 if exist src\backend\storage\lmgr\lwlocknames.h del /q src\backend\storage\lmgr\lwlocknames.h
-if %DIST%==1 if exist src\pl\plpython\spiexceptions.h del /q src\pl\plpython\spiexceptions.h
-if %DIST%==1 if exist src\pl\plpgsql\src\plerrcodes.h del /q src\pl\plpgsql\src\plerrcodes.h
-if %DIST%==1 if exist src\pl\tcl\pltclerrcodes.h del /q src\pl\tcl\pltclerrcodes.h
-if %DIST%==1 if exist src\bin\psql\sql_help.c del /q src\bin\psql\sql_help.c
-if %DIST%==1 if exist src\bin\psql\sql_help.h del /q src\bin\psql\sql_help.h
-if %DIST%==1 if exist src\common\kwlist_d.h del /q src\common\kwlist_d.h
-if %DIST%==1 if exist src\pl\plpgsql\src\pl_reserved_kwlist_d.h del /q src\pl\plpgsql\src\pl_reserved_kwlist_d.h
-if %DIST%==1 if exist src\pl\plpgsql\src\pl_unreserved_kwlist_d.h del /q src\pl\plpgsql\src\pl_unreserved_kwlist_d.h
-if %DIST%==1 if exist src\interfaces\ecpg\preproc\c_kwlist_d.h del /q src\interfaces\ecpg\preproc\c_kwlist_d.h
-if %DIST%==1 if exist src\interfaces\ecpg\preproc\ecpg_kwlist_d.h del /q src\interfaces\ecpg\preproc\ecpg_kwlist_d.h
-if %DIST%==1 if exist src\interfaces\ecpg\preproc\preproc.y del /q src\interfaces\ecpg\preproc\preproc.y
-if %DIST%==1 if exist src\backend\catalog\postgres.bki del /q src\backend\catalog\postgres.bki
-if %DIST%==1 if exist src\backend\catalog\system_constraints.sql del /q src\backend\catalog\system_constraints.sql
-if %DIST%==1 if exist src\backend\catalog\schemapg.h del /q src\backend\catalog\schemapg.h
-if %DIST%==1 if exist src\backend\catalog\system_fk_info.h del /q src\backend\catalog\system_fk_info.h
-if %DIST%==1 if exist src\backend\catalog\pg_*_d.h del /q src\backend\catalog\pg_*_d.h
-if %DIST%==1 if exist src\backend\catalog\bki-stamp del /q src\backend\catalog\bki-stamp
-if %DIST%==1 if exist src\backend\parser\scan.c del /q src\backend\parser\scan.c
-if %DIST%==1 if exist src\backend\parser\gram.c del /q src\backend\parser\gram.c
-if %DIST%==1 if exist src\backend\parser\gram.h del /q src\backend\parser\gram.h
-if %DIST%==1 if exist src\backend\bootstrap\bootscanner.c del /q src\backend\bootstrap\bootscanner.c
-if %DIST%==1 if exist src\backend\bootstrap\bootparse.c del /q src\backend\bootstrap\bootparse.c
-if %DIST%==1 if exist src\backend\bootstrap\bootparse.h del /q src\backend\bootstrap\bootparse.h
-if %DIST%==1 if exist src\backend\utils\adt\jsonpath_gram.c del /q src\backend\utils\adt\jsonpath_gram.c
-if %DIST%==1 if exist src\backend\utils\adt\jsonpath_gram.h del /q src\backend\utils\adt\jsonpath_gram.h
-if %DIST%==1 if exist src\backend\utils\adt\jsonpath_scan.c del /q src\backend\utils\adt\jsonpath_scan.c
-if %DIST%==1 if exist src\backend\utils\misc\guc-file.c del /q src\backend\utils\misc\guc-file.c
-if %DIST%==1 if exist src\backend\replication\repl_scanner.c del /q src\backend\replication\repl_scanner.c
-if %DIST%==1 if exist src\backend\replication\repl_gram.c del /q src\backend\replication\repl_gram.c
-if %DIST%==1 if exist src\backend\replication\repl_gram.h del /q src\backend\replication\repl_gram.h
-if %DIST%==1 if exist src\backend\replication\syncrep_scanner.c del /q src\backend\replication\syncrep_scanner.c
-if %DIST%==1 if exist src\backend\replication\syncrep_gram.c del /q src\backend\replication\syncrep_gram.c
-if %DIST%==1 if exist src\backend\replication\syncrep_gram.h del /q src\backend\replication\syncrep_gram.h
-
-
-if exist src\interfaces\libpq\libpqdll.def del /q src\interfaces\libpq\libpqdll.def
-if exist src\interfaces\ecpg\compatlib\compatlib.def del /q src\interfaces\ecpg\compatlib\compatlib.def
-if exist src\interfaces\ecpg\ecpglib\ecpglib.def del /q src\interfaces\ecpg\ecpglib\ecpglib.def
-if exist src\interfaces\ecpg\include\ecpg_config.h del /q src\interfaces\ecpg\include\ecpg_config.h
-if exist src\interfaces\ecpg\pgtypeslib\pgtypeslib.def del /q src\interfaces\ecpg\pgtypeslib\pgtypeslib.def
-if %DIST%==1 if exist src\interfaces\ecpg\preproc\pgc.c del /q src\interfaces\ecpg\preproc\pgc.c
-if %DIST%==1 if exist src\interfaces\ecpg\preproc\preproc.c del /q src\interfaces\ecpg\preproc\preproc.c
-if %DIST%==1 if exist src\interfaces\ecpg\preproc\preproc.h del /q src\interfaces\ecpg\preproc\preproc.h
-
-if exist src\port\pg_config_paths.h del /q src\port\pg_config_paths.h
-
-if exist src\pl\plperl\SPI.c del /q src\pl\plperl\SPI.c
-if exist src\pl\plperl\Util.c del /q src\pl\plperl\Util.c
-if exist src\pl\plperl\perlchunks.h del /q src\pl\plperl\perlchunks.h
-if exist src\pl\plperl\plperl_opmask.h del /q src\pl\plperl\plperl_opmask.h
-if %DIST%==1 if exist src\pl\plpgsql\src\pl_gram.c del /q src\pl\plpgsql\src\pl_gram.c
-if %DIST%==1 if exist src\pl\plpgsql\src\pl_gram.h del /q src\pl\plpgsql\src\pl_gram.h
-
-if %DIST%==1 if exist src\fe_utils\psqlscan.c del /q src\fe_utils\psqlscan.c
-if %DIST%==1 if exist src\bin\psql\psqlscanslash.c del /q src\bin\psql\psqlscanslash.c
-if %DIST%==1 if exist src\bin\pgbench\exprscan.c del /q src\bin\pgbench\exprscan.c
-if %DIST%==1 if exist src\bin\pgbench\exprparse.c del /q src\bin\pgbench\exprparse.c
-if %DIST%==1 if exist src\bin\pgbench\exprparse.h del /q src\bin\pgbench\exprparse.h
-
-if %DIST%==1 if exist contrib\cube\cubescan.c del /q contrib\cube\cubescan.c
-if %DIST%==1 if exist contrib\cube\cubeparse.c del /q contrib\cube\cubeparse.c
-if %DIST%==1 if exist contrib\cube\cubeparse.h del /q contrib\cube\cubeparse.h
-if %DIST%==1 if exist contrib\fuzzystrmatch\daitch_mokotoff.h del /q contrib\fuzzystrmatch\daitch_mokotoff.h
-if %DIST%==1 if exist contrib\seg\segscan.c del /q contrib\seg\segscan.c
-if %DIST%==1 if exist contrib\seg\segparse.c del /q contrib\seg\segparse.c
-if %DIST%==1 if exist contrib\seg\segparse.h del /q contrib\seg\segparse.h
-
-if exist src\test\regress\tmp_check rd /s /q src\test\regress\tmp_check
-if exist contrib\spi\refint.dll del /q contrib\spi\refint.dll
-if exist contrib\spi\autoinc.dll del /q contrib\spi\autoinc.dll
-if exist src\test\regress\regress.dll del /q src\test\regress\regress.dll
-if exist src\test\regress\refint.dll del /q src\test\regress\refint.dll
-if exist src\test\regress\autoinc.dll del /q src\test\regress\autoinc.dll
-if %DIST%==1 if exist src\test\isolation\specscanner.c del /q src\test\isolation\specscanner.c
-if %DIST%==1 if exist src\test\isolation\specparse.c del /q src\test\isolation\specparse.c
-if %DIST%==1 if exist src\test\isolation\specparse.h del /q src\test\isolation\specparse.h
-
-for /d %%f in (contrib\* src\bin\* src\test\* src\test\modules\*
-  ) do if exist %%f\tmp_check rd /s /q %%f\tmp_check
-
-REM Clean up datafiles built with contrib
-REM cd contrib
-REM for /r %%f in (*.sql) do if exist %%f.in del %%f
-
-cd "%~dp0"
-
-REM Clean up ecpg regression test files
-msbuild ecpg_regression.proj /NoLogo /v:q %MSBFLAGS% /t:clean
-
-goto :eof
diff --git a/src/tools/msvc/config_default.pl b/src/tools/msvc/config_default.pl
deleted file mode 100644
index 8945e772c2..0000000000
--- a/src/tools/msvc/config_default.pl
+++ /dev/null
@@ -1,32 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-# Configuration arguments for vcbuild.
-use strict;
-use warnings;
-
-our $config = {
-	asserts => 0,    # --enable-cassert
-
-	# blocksize => 8,         # --with-blocksize, 8kB by default
-	# wal_blocksize => 8,     # --with-wal-blocksize, 8kB by default
-	ldap => 1,             # --with-ldap
-	extraver => undef,     # --with-extra-version=<string>
-	gss => undef,          # --with-gssapi=<path>
-	icu => undef,          # --with-icu=<path>
-	lz4 => undef,          # --with-lz4=<path>
-	zstd => undef,         # --with-zstd=<path>
-	nls => undef,          # --enable-nls=<path>
-	tap_tests => undef,    # --enable-tap-tests
-	tcl => undef,          # --with-tcl=<path>
-	perl => undef,         # --with-perl=<path>
-	python => undef,       # --with-python=<path>
-	openssl => undef,      # --with-ssl=openssl with <path>
-	uuid => undef,         # --with-uuid=<path>
-	xml => undef,          # --with-libxml=<path>
-	xslt => undef,         # --with-libxslt=<path>
-	iconv => undef,        # (not in configure, path to iconv)
-	zlib => undef          # --with-zlib=<path>
-};
-
-1;
diff --git a/src/tools/msvc/dummylib/README b/src/tools/msvc/dummylib/README
deleted file mode 100644
index 7b63d0ed43..0000000000
--- a/src/tools/msvc/dummylib/README
+++ /dev/null
@@ -1,13 +0,0 @@
-
-src/tools/msvc/dummylib
-
-This directory contains just enough of a dummy library to allow checking of
-the programs in src/tools/msvc and src/tools/win32tzlist.pl with
-perl -cw, even on machines that lack the Win32 perl infrastructure.
-
-invoke via:
-
-PERL5LIB=src/tools/msvc/dummylib perl -cw $file
-
-This is the only use that should be made of this directory. Attempting actually
-running of any programs using this library will result in a lot of grief.
diff --git a/src/tools/msvc/dummylib/Win32.pm b/src/tools/msvc/dummylib/Win32.pm
deleted file mode 100644
index df2d7a2929..0000000000
--- a/src/tools/msvc/dummylib/Win32.pm
+++ /dev/null
@@ -1,7 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Win32;
-use strict;
-use warnings;
-1;
diff --git a/src/tools/msvc/dummylib/Win32/Registry.pm b/src/tools/msvc/dummylib/Win32/Registry.pm
deleted file mode 100644
index e14636eb31..0000000000
--- a/src/tools/msvc/dummylib/Win32/Registry.pm
+++ /dev/null
@@ -1,16 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Win32::Registry;
-
-use strict;
-use warnings;
-
-use vars qw($HKEY_LOCAL_MACHINE);
-
-use Exporter ();
-our (@EXPORT, @ISA);
-@ISA = qw(Exporter);
-@EXPORT = qw($HKEY_LOCAL_MACHINE);
-
-1;
diff --git a/src/tools/msvc/dummylib/Win32API/File.pm b/src/tools/msvc/dummylib/Win32API/File.pm
deleted file mode 100644
index 7baf34c4e5..0000000000
--- a/src/tools/msvc/dummylib/Win32API/File.pm
+++ /dev/null
@@ -1,17 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-package Win32API::File;
-
-use strict;
-use warnings;
-
-use constant { SEM_FAILCRITICALERRORS => 1, SEM_NOGPFAULTERRORBOX => 2 };
-sub SetErrormode { }
-use Exporter;
-our (@ISA, @EXPORT_OK, %EXPORT_TAGS);
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(SetErrorMode SEM_FAILCRITICALERRORS SEM_NOGPFAULTERRORBOX);
-%EXPORT_TAGS = (SEM_ => [qw(SEM_FAILCRITICALERRORS SEM_NOGPFAULTERRORBOX)]);
-
-1;
diff --git a/src/tools/msvc/ecpg_regression.proj b/src/tools/msvc/ecpg_regression.proj
deleted file mode 100644
index 0ec60a275e..0000000000
--- a/src/tools/msvc/ecpg_regression.proj
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0"?>
-<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="all">
-<!--
-  MSBuild project file to build ecpg regression tests
--->
-
- <PropertyGroup>
-  <TESTDIR>..\..\interfaces\ecpg\test</TESTDIR>
-  <CONFIG>Debug</CONFIG>
-  <OUTDIR>..\..\..\..\..\$(CONFIG)\</OUTDIR>
- </PropertyGroup>
- <PropertyGroup Condition="'$(CONFIG)'=='DEBUG'">
-  <!-- set debug runtime library if necessary to be compatible with the LIB files generated -->
-  <DEBUGLIB>d</DEBUGLIB>
- </PropertyGroup>
-
- <ItemGroup>
-  <Pgc Include="$(TESTDIR)\**\*.pgc" Exclude="$(TESTDIR)\performance\perftest.pgc"/>
- </ItemGroup>
-
- <ItemGroup>
-  <OutputToDelete Include="$(TESTDIR)\**\*.exe" />
-  <OutputToDelete Include="$(TESTDIR)\**\*.exe.manifest" />
-  <OutputToDelete Include="$(TESTDIR)\**\*.obj" />
-  <OutputToDelete Include="$(TESTDIR)\**\*.c" Exclude="$(TESTDIR)\pg_regress_ecpg.c;$(TESTDIR)\expected\*.c" />
- </ItemGroup>
-
- <Target Name="all" Inputs="@(Pgc)" Outputs="%(RelativeDir)%(Filename).exe">
-  <!-- Set special parameters for some tests -->
-  <CreateProperty Value="-C INFORMIX" Condition="'%(Pgc.RelativeDir)'=='$(TESTDIR)\compat_informix\'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-C INFORMIX -r no_indicator" Condition="'%(Pgc.FileName)'=='rnull'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-C ORACLE" Condition="'%(Pgc.RelativeDir)'=='$(TESTDIR)\compat_oracle\'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-c" Condition="'%(Pgc.FileName)'=='array_of_struct'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-c" Condition="'%(Pgc.FileName)'=='pointer_to_struct'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-r questionmarks" Condition="'%(Pgc.FileName)'=='oldexec'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-r prepare" Condition="'%(Pgc.FileName)'=='autoprep'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-  <CreateProperty Value="-i" Condition="'%(Pgc.FileName)'=='strings'">
-   <Output TaskParameter="Value" PropertyName="ECPGPARAM" />
-  </CreateProperty>
-
-  <!-- Run ECPG and the Visual C++ compiler on the files. Don't bother with dependency check between the steps -->
-  <Exec WorkingDirectory="%(Pgc.RelativeDir)" Command="$(OUTDIR)ecpg\ecpg -I ../../include --regression $(ECPGPARAM) -o %(Pgc.Filename).c %(Pgc.Filename).pgc" />
-  <Exec WorkingDirectory="%(Pgc.RelativeDir)" Command="cl /nologo %(Pgc.FileName).c /TC /MD$(DEBUGLIB) /DWIN32 /I. /I..\..\include /I..\..\..\libpq /I..\..\..\..\include /link /defaultlib:$(OUTDIR)libecpg\libecpg.lib /defaultlib:$(OUTDIR)libecpg_compat\libecpg_compat.lib /defaultlib:$(OUTDIR)libpgtypes\libpgtypes.lib" />
- </Target>
-
- <!-- Clean up all output files -->
- <Target Name="clean">
-  <Delete Files="@(OutputToDelete)" />
- </Target>
-</Project>
diff --git a/src/tools/msvc/install.bat b/src/tools/msvc/install.bat
deleted file mode 100644
index d02b80826b..0000000000
--- a/src/tools/msvc/install.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-@echo off
-REM src/tools/msvc/install.bat
-REM all the logic for this now belongs in install.pl. This file really
-REM only exists so you don't have to type "perl install.pl"
-REM Resist any temptation to add any logic here.
-@perl %~dp0/install.pl %*
diff --git a/src/tools/msvc/install.pl b/src/tools/msvc/install.pl
deleted file mode 100755
index 8de7cee90f..0000000000
--- a/src/tools/msvc/install.pl
+++ /dev/null
@@ -1,39 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-#
-# Script that provides 'make install' functionality for msvc builds
-#
-# src/tools/msvc/install.pl
-#
-use strict;
-use warnings;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use Install qw(Install);
-
-# buildenv.pl is for specifying the build environment settings
-# it should contain lines like:
-# $ENV{PATH} = "c:/path/to/bison/bin;$ENV{PATH}";
-
-if (-e "src/tools/msvc/buildenv.pl")
-{
-	do "./src/tools/msvc/buildenv.pl";
-}
-elsif (-e "./buildenv.pl")
-{
-	do "./buildenv.pl";
-}
-
-my $target = shift || Usage();
-my $insttype = shift;
-Install($target, $insttype);
-
-sub Usage
-{
-	print "Usage: install.pl <targetdir> [installtype]\n";
-	print "installtype: client\n";
-	exit(1);
-}
diff --git a/src/tools/msvc/mkvcbuild.pl b/src/tools/msvc/mkvcbuild.pl
deleted file mode 100644
index 7f94b1a6c9..0000000000
--- a/src/tools/msvc/mkvcbuild.pl
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-#
-# Script that parses Unix style build environment and generates build files
-# for building with Visual Studio.
-#
-# src/tools/msvc/mkvcbuild.pl
-#
-use strict;
-use warnings;
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use Mkvcbuild;
-
-chdir('../../..') if (-d '../msvc' && -d '../../../src');
-die 'Must run from root or msvc directory'
-  unless (-d 'src/tools/msvc' && -d 'src');
-
-die 'Could not find config_default.pl'
-  unless (-f 'src/tools/msvc/config_default.pl');
-print "Warning: no config.pl found, using default.\n"
-  unless (-f 'src/tools/msvc/config.pl');
-
-our $config;
-do './src/tools/msvc/config_default.pl';
-do './src/tools/msvc/config.pl' if (-f 'src/tools/msvc/config.pl');
-
-Mkvcbuild::mkvcbuild($config);
diff --git a/src/tools/msvc/pgbison.bat b/src/tools/msvc/pgbison.bat
deleted file mode 100755
index dc8ac4a2cf..0000000000
--- a/src/tools/msvc/pgbison.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-
-REM src/tools/msvc/pgbison.bat
-REM all the logic for this now belongs in pgbison.pl. This file really
-REM only exists so you don't have to type "perl src/tools/msvc/pgbison.pl"
-REM Resist any temptation to add any logic here.
-@perl %~dp0/pgbison.pl %*
diff --git a/src/tools/msvc/pgbison.pl b/src/tools/msvc/pgbison.pl
deleted file mode 100644
index 25df6699b5..0000000000
--- a/src/tools/msvc/pgbison.pl
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*-perl-*- hey - emacs - this is a perl file
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-# src/tools/msvc/pgbison.pl
-
-use strict;
-use warnings;
-
-use File::Basename;
-
-# assume we are in the postgres source root
-
-do './src/tools/msvc/buildenv.pl' if -e 'src/tools/msvc/buildenv.pl';
-
-my ($bisonver) = `bison -V`;                 # grab first line
-$bisonver = (split(/\s+/, $bisonver))[3];    # grab version number
-
-unless ($bisonver ge '2.3')
-{
-	print "WARNING! Bison install not found, or unsupported Bison version.\n";
-	print "echo Attempting to build without.\n";
-	exit 0;
-}
-
-my $input = shift;
-if ($input !~ /\.y$/)
-{
-	print "Input must be a .y file\n";
-	exit 1;
-}
-elsif (!-e $input)
-{
-	print "Input file $input not found\n";
-	exit 1;
-}
-
-(my $output = $input) =~ s/\.y$/.c/;
-
-# plpgsql just has to be different
-$output =~ s/gram\.c$/pl_gram.c/ if $input =~ /src.pl.plpgsql.src.gram\.y$/;
-
-my $makefile = dirname($input) . "/Makefile";
-my ($mf, $make);
-open($mf, '<', $makefile);
-local $/ = undef;
-$make = <$mf>;
-close($mf);
-my $basetarg = basename($output);
-my $headerflag = ($make =~ /^$basetarg:\s+BISONFLAGS\b.*-d/m ? '-d' : '');
-
-my $nodep = $bisonver ge '3.0' ? "-Wno-deprecated" : "";
-
-system("bison $nodep $headerflag $input -o $output");
-exit $? >> 8;
diff --git a/src/tools/msvc/pgflex.bat b/src/tools/msvc/pgflex.bat
deleted file mode 100755
index f20834ba9b..0000000000
--- a/src/tools/msvc/pgflex.bat
+++ /dev/null
@@ -1,7 +0,0 @@
-@echo off
-
-REM src/tools/msvc/pgflex.bat
-REM all the logic for this now belongs in pgflex.pl. This file really
-REM only exists so you don't have to type "perl src/tools/msvc/pgflex.pl"
-REM Resist any temptation to add any logic here.
-@perl %~dp0/pgflex.pl %*
diff --git a/src/tools/msvc/pgflex.pl b/src/tools/msvc/pgflex.pl
deleted file mode 100644
index c308a08b55..0000000000
--- a/src/tools/msvc/pgflex.pl
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*-perl-*- hey - emacs - this is a perl file
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-# src/tools/msvc/pgflex.pl
-
-use strict;
-use warnings;
-
-use File::Basename;
-
-# silence flex bleatings about file path style
-$ENV{CYGWIN} = 'nodosfilewarning';
-
-# assume we are in the postgres source root
-
-do './src/tools/msvc/buildenv.pl' if -e 'src/tools/msvc/buildenv.pl';
-
-my ($flexver) = `flex -V`;    # grab first line
-$flexver = (split(/\s+/, $flexver))[1];
-$flexver =~ s/[^0-9.]//g;
-my @verparts = split(/\./, $flexver);
-unless ($verparts[0] == 2
-	&& ($verparts[1] > 5 || ($verparts[1] == 5 && $verparts[2] >= 35)))
-{
-	print "WARNING! Flex install not found, or unsupported Flex version.\n";
-	print "echo Attempting to build without.\n";
-	exit 0;
-}
-
-my $input = shift;
-if ($input !~ /\.l$/)
-{
-	print "Input must be a .l file\n";
-	exit 1;
-}
-elsif (!-e $input)
-{
-	print "Input file $input not found\n";
-	exit 1;
-}
-
-(my $output = $input) =~ s/\.l$/.c/;
-
-# get flex flags from make file
-my $makefile = dirname($input) . "/Makefile";
-my ($mf, $make);
-open($mf, '<', $makefile);
-local $/ = undef;
-$make = <$mf>;
-close($mf);
-my $basetarg = basename($output);
-my $flexflags = ($make =~ /^$basetarg:\s*FLEXFLAGS\s*=\s*(\S.*)/m ? $1 : '');
-
-system("flex $flexflags -o$output $input");
-if ($? == 0)
-{
-
-	# Check for "%option reentrant" in .l file.
-	my $lfile;
-	open($lfile, '<', $input) || die "opening $input for reading: $!";
-	my $lcode = <$lfile>;
-	close($lfile);
-	if ($lcode =~ /\%option\sreentrant/)
-	{
-
-		# Reentrant scanners usually need a fix to prevent
-		# "unused variable" warnings with older flex versions.
-		system("perl src\\tools\\fix-old-flex-code.pl $output");
-	}
-	else
-	{
-
-		# For non-reentrant scanners we need to fix up the yywrap
-		# macro definition to keep the MS compiler happy.
-		# For reentrant scanners (like the core scanner) we do not
-		# need to (and must not) change the yywrap definition.
-		my $cfile;
-		open($cfile, '<', $output) || die "opening $output for reading: $!";
-		my $ccode = <$cfile>;
-		close($cfile);
-		$ccode =~ s/yywrap\(n\)/yywrap()/;
-		open($cfile, '>', $output) || die "opening $output for writing: $!";
-		print $cfile $ccode;
-		close($cfile);
-	}
-	if ($flexflags =~ /\s-b\s/)
-	{
-		my $lexback = "lex.backup";
-		open($lfile, '<', $lexback) || die "opening $lexback for reading: $!";
-		my $lexbacklines = <$lfile>;
-		close($lfile);
-		my $linecount = $lexbacklines =~ tr /\n/\n/;
-		if ($linecount != 1)
-		{
-			print "Scanner requires backup, see lex.backup.\n";
-			exit 1;
-		}
-		unlink $lexback;
-	}
-
-	exit 0;
-
-}
-else
-{
-	exit $? >> 8;
-}
diff --git a/src/tools/msvc/vcregress.bat b/src/tools/msvc/vcregress.bat
deleted file mode 100644
index 7fba45c1e7..0000000000
--- a/src/tools/msvc/vcregress.bat
+++ /dev/null
@@ -1,6 +0,0 @@
-@echo off
-REM src/tools/msvc/vcregress.bat
-REM all the logic for this now belongs in vcregress.pl. This file really
-REM only exists so you don't have to type "perl vcregress.pl"
-REM Resist any temptation to add any logic here.
-@perl %~dp0/vcregress.pl %*
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
deleted file mode 100644
index 78170d105d..0000000000
--- a/src/tools/msvc/vcregress.pl
+++ /dev/null
@@ -1,664 +0,0 @@
-# -*-perl-*- hey - emacs - this is a perl file
-
-# Copyright (c) 2021-2023, PostgreSQL Global Development Group
-
-# src/tools/msvc/vcregress.pl
-
-use strict;
-use warnings;
-
-our $config;
-
-use Cwd;
-use File::Basename;
-use File::Copy;
-use File::Find ();
-use File::Path qw(rmtree);
-use File::Spec qw(devnull);
-
-use FindBin;
-use lib $FindBin::RealBin;
-
-use Install qw(Install);
-
-my $startdir = getcwd();
-
-chdir "../../.." if (-d "../../../src/tools/msvc");
-
-my $topdir = getcwd();
-my $tmp_installdir = "$topdir/tmp_install";
-
-do './src/tools/msvc/config_default.pl';
-do './src/tools/msvc/config.pl' if (-f 'src/tools/msvc/config.pl');
-
-my $devnull = File::Spec->devnull;
-
-# These values are defaults that can be overridden by the calling environment
-# (see buildenv.pl processing below).  We assume that the ones listed here
-# always exist by default.  Other values may optionally be set for bincheck
-# or taptest, see set_command_env() below.
-# c.f. src/Makefile.global.in and configure.ac
-$ENV{TAR} ||= 'tar';
-
-# buildenv.pl is for specifying the build environment settings
-# it should contain lines like:
-# $ENV{PATH} = "c:/path/to/bison/bin;$ENV{PATH}";
-
-if (-e "src/tools/msvc/buildenv.pl")
-{
-	do "./src/tools/msvc/buildenv.pl";
-}
-
-my $what = shift || "";
-if ($what =~
-	/^(check|installcheck|plcheck|contribcheck|modulescheck|ecpgcheck|isolationcheck|upgradecheck|bincheck|recoverycheck|taptest)$/i
-  )
-{
-	$what = uc $what;
-}
-else
-{
-	usage();
-}
-
-# use a capital C here because config.pl has $config
-my $Config = -e "release/postgres/postgres.exe" ? "Release" : "Debug";
-
-copy("$Config/refint/refint.dll", "src/test/regress");
-copy("$Config/autoinc/autoinc.dll", "src/test/regress");
-copy("$Config/regress/regress.dll", "src/test/regress");
-copy("$Config/dummy_seclabel/dummy_seclabel.dll", "src/test/regress");
-
-# Configuration settings used by TAP tests
-$ENV{with_ssl} = $config->{openssl} ? 'openssl' : 'no';
-$ENV{with_ldap} = $config->{ldap} ? 'yes' : 'no';
-$ENV{with_icu} = $config->{icu} ? 'yes' : 'no';
-$ENV{with_gssapi} = $config->{gss} ? 'yes' : 'no';
-$ENV{with_krb_srvnam} = $config->{krb_srvnam} || 'postgres';
-$ENV{with_readline} = 'no';
-
-$ENV{PATH} = "$topdir/$Config/libpq;$ENV{PATH}";
-
-if ($ENV{PERL5LIB})
-{
-	$ENV{PERL5LIB} = "$topdir/src/tools/msvc;$ENV{PERL5LIB}";
-}
-else
-{
-	$ENV{PERL5LIB} = "$topdir/src/tools/msvc";
-}
-
-my $maxconn = "";
-$maxconn = "--max-connections=$ENV{MAX_CONNECTIONS}"
-  if $ENV{MAX_CONNECTIONS};
-
-my $temp_config = "";
-$temp_config = "--temp-config=\"$ENV{TEMP_CONFIG}\""
-  if $ENV{TEMP_CONFIG};
-
-chdir "src/test/regress";
-
-my %command = (
-	CHECK => \&check,
-	PLCHECK => \&plcheck,
-	INSTALLCHECK => \&installcheck,
-	ECPGCHECK => \&ecpgcheck,
-	CONTRIBCHECK => \&contribcheck,
-	MODULESCHECK => \&modulescheck,
-	ISOLATIONCHECK => \&isolationcheck,
-	BINCHECK => \&bincheck,
-	RECOVERYCHECK => \&recoverycheck,
-	UPGRADECHECK => \&upgradecheck,    # no-op
-	TAPTEST => \&taptest,);
-
-my $proc = $command{$what};
-
-exit 3 unless $proc;
-
-&$proc(@ARGV);
-
-exit 0;
-
-########################################################################
-
-# Helper function for set_command_env, to set one environment command.
-sub set_single_env
-{
-	my $envname = shift;
-	my $envdefault = shift;
-
-	# If a command is defined by the environment, just use it.
-	return if (defined($ENV{$envname}));
-
-	# Nothing is defined, so attempt to assign a default.  The command
-	# may not be in the current environment, hence check if it can be
-	# executed.
-	my $rc = system("$envdefault --version >$devnull 2>&1");
-
-	# Set the environment to the default if it exists, else leave it.
-	$ENV{$envname} = $envdefault if $rc == 0;
-	return;
-}
-
-# Set environment values for various command types.  These can be used
-# in the TAP tests.
-sub set_command_env
-{
-	set_single_env('GZIP_PROGRAM', 'gzip');
-	set_single_env('LZ4', 'lz4');
-	set_single_env('OPENSSL', 'openssl');
-	set_single_env('ZSTD', 'zstd');
-}
-
-sub installcheck_internal
-{
-	my ($schedule, @EXTRA_REGRESS_OPTS) = @_;
-	# for backwards compatibility, "serial" runs the tests in
-	# parallel_schedule one by one.
-	my $maxconn = $maxconn;
-	$maxconn = "--max-connections=1" if $schedule eq 'serial';
-	$schedule = 'parallel' if $schedule eq 'serial';
-
-	my @args = (
-		"../../../$Config/pg_regress/pg_regress",
-		"--dlpath=.",
-		"--bindir=../../../$Config/psql",
-		"--schedule=${schedule}_schedule",
-		"--max-concurrent-tests=20");
-	push(@args, $maxconn) if $maxconn;
-	push(@args, @EXTRA_REGRESS_OPTS);
-	system(@args);
-	my $status = $? >> 8;
-	exit $status if $status;
-	return;
-}
-
-sub installcheck
-{
-	my $schedule = shift || 'serial';
-	installcheck_internal($schedule);
-	return;
-}
-
-sub check
-{
-	my $schedule = shift || 'parallel';
-	my $encoding = $ENV{ENCODING} || "SQL_ASCII";
-	# for backwards compatibility, "serial" runs the tests in
-	# parallel_schedule one by one.
-	my $maxconn = $maxconn;
-	$maxconn = "--max-connections=1" if $schedule eq 'serial';
-	$schedule = 'parallel' if $schedule eq 'serial';
-
-	InstallTemp();
-	chdir "${topdir}/src/test/regress";
-	my @args = (
-		"../../../$Config/pg_regress/pg_regress",
-		"--dlpath=.",
-		"--bindir=",
-		"--schedule=${schedule}_schedule",
-		"--max-concurrent-tests=20",
-		"--encoding=${encoding}",
-		"--no-locale",
-		"--temp-instance=./tmp_check");
-	push(@args, $maxconn) if $maxconn;
-	push(@args, $temp_config) if $temp_config;
-	system(@args);
-	my $status = $? >> 8;
-	exit $status if $status;
-	return;
-}
-
-sub ecpgcheck
-{
-	my $msbflags = $ENV{MSBFLAGS} || "";
-	chdir $startdir;
-	system("msbuild ecpg_regression.proj $msbflags /p:config=$Config");
-	my $status = $? >> 8;
-	exit $status if $status;
-	InstallTemp();
-	chdir "$topdir/src/interfaces/ecpg/test";
-	my $schedule = "ecpg";
-	my @args = (
-		"../../../../$Config/pg_regress_ecpg/pg_regress_ecpg",
-		"--bindir=",
-		"--dbname=ecpg1_regression,ecpg2_regression",
-		"--create-role=regress_ecpg_user1,regress_ecpg_user2",
-		"--schedule=${schedule}_schedule",
-		"--encoding=SQL_ASCII",
-		"--no-locale",
-		"--temp-instance=./tmp_chk");
-	push(@args, $maxconn) if $maxconn;
-	system(@args);
-	$status = $? >> 8;
-	exit $status if $status;
-	return;
-}
-
-sub isolationcheck
-{
-	chdir "../isolation";
-	copy("../../../$Config/isolationtester/isolationtester.exe",
-		"../../../$Config/pg_isolation_regress");
-	my @args = (
-		"../../../$Config/pg_isolation_regress/pg_isolation_regress",
-		"--bindir=../../../$Config/psql",
-		"--inputdir=.",
-		"--schedule=./isolation_schedule");
-	push(@args, $maxconn) if $maxconn;
-	system(@args);
-	my $status = $? >> 8;
-	exit $status if $status;
-	return;
-}
-
-sub tap_check
-{
-	die "Tap tests not enabled in configuration"
-	  unless $config->{tap_tests};
-
-	my @flags;
-	foreach my $arg (0 .. scalar(@_) - 1)
-	{
-		next unless $_[$arg] =~ /^PROVE_FLAGS=(.*)/;
-		@flags = split(/\s+/, $1);
-		splice(@_, $arg, 1);
-		last;
-	}
-
-	my $dir = shift;
-	chdir $dir;
-
-	# Fetch and adjust PROVE_TESTS, applying glob() to each element
-	# defined to build a list of all the tests matching patterns.
-	my $prove_tests_val = $ENV{PROVE_TESTS} || "t/*.pl";
-	my @prove_tests_array = split(/\s+/, $prove_tests_val);
-	my @prove_tests = ();
-	foreach (@prove_tests_array)
-	{
-		push(@prove_tests, glob($_));
-	}
-
-	# Fetch and adjust PROVE_FLAGS, handling multiple arguments.
-	my $prove_flags_val = $ENV{PROVE_FLAGS} || "";
-	my @prove_flags = split(/\s+/, $prove_flags_val);
-
-	my @args = ("prove", @flags, @prove_tests, @prove_flags);
-
-	# adjust the environment for just this test
-	local %ENV = %ENV;
-	$ENV{PERL5LIB} = "$topdir/src/test/perl;$ENV{PERL5LIB}";
-	$ENV{PG_REGRESS} = "$topdir/$Config/pg_regress/pg_regress";
-	$ENV{REGRESS_SHLIB} = "$topdir/src/test/regress/regress.dll";
-
-	$ENV{TESTDATADIR} = "$dir/tmp_check";
-	$ENV{TESTLOGDIR} = "$dir/tmp_check/log";
-
-	my $module = basename $dir;
-	# add the module build dir as the second element in the PATH
-	$ENV{PATH} =~ s!;!;$topdir/$Config/$module;!;
-
-	rmtree('tmp_check');
-	system(@args);
-	my $status = $? >> 8;
-	return $status;
-}
-
-sub bincheck
-{
-	InstallTemp();
-
-	set_command_env();
-
-	my $mstat = 0;
-
-	# Find out all the existing TAP tests by looking for t/ directories
-	# in the tree.
-	my @bin_dirs = glob("$topdir/src/bin/*");
-
-	# Process each test
-	foreach my $dir (@bin_dirs)
-	{
-		next unless -d "$dir/t";
-
-		my $status = tap_check($dir);
-		$mstat ||= $status;
-	}
-	exit $mstat if $mstat;
-	return;
-}
-
-sub taptest
-{
-	my $dir = shift;
-	my @args;
-
-	if ($dir =~ /^PROVE_FLAGS=/)
-	{
-		push(@args, $dir);
-		$dir = shift;
-	}
-
-	die "no tests found!" unless -d "$topdir/$dir/t";
-
-	push(@args, "$topdir/$dir");
-
-	InstallTemp();
-
-	set_command_env();
-
-	my $status = tap_check(@args);
-	exit $status if $status;
-	return;
-}
-
-sub plcheck
-{
-	chdir "$topdir/src/pl";
-
-	foreach my $dir (glob("*/src *"))
-	{
-		next unless -d "$dir/sql" && -d "$dir/expected";
-		my $lang;
-		if ($dir eq 'plpgsql/src')
-		{
-			$lang = 'plpgsql';
-		}
-		elsif ($dir eq 'tcl')
-		{
-			$lang = 'pltcl';
-		}
-		else
-		{
-			$lang = $dir;
-		}
-		if ($lang eq 'plpython')
-		{
-			next
-			  unless -d "$topdir/$Config/plpython3";
-			$lang = 'plpythonu';
-		}
-		else
-		{
-			next unless -d "$topdir/$Config/$lang";
-		}
-		my @lang_args = ("--load-extension=$lang");
-		chdir $dir;
-		my @tests = fetchTests();
-		if ($lang eq 'plperl')
-		{
-
-			# plperl tests will install the extensions themselves
-			@lang_args = ();
-
-			# assume we're using this perl to built postgres
-			# test if we can run two interpreters in one backend, and if so
-			# run the trusted/untrusted interaction tests
-			use Config;
-			if ($Config{usemultiplicity} eq 'define')
-			{
-				push(@tests, 'plperl_plperlu');
-			}
-		}
-		elsif ($lang eq 'plpythonu' && -d "$topdir/$Config/plpython3")
-		{
-			@lang_args = ();
-		}
-
-		# Move on if no tests are listed.
-		next if (scalar @tests == 0);
-
-		print
-		  "============================================================\n";
-		print "Checking $lang\n";
-		my @args = (
-			"$topdir/$Config/pg_regress/pg_regress",
-			"--bindir=$topdir/$Config/psql",
-			"--dbname=pl_regression", @lang_args, @tests);
-		system(@args);
-		my $status = $? >> 8;
-		exit $status if $status;
-		chdir "$topdir/src/pl";
-	}
-
-	chdir "$topdir";
-	return;
-}
-
-sub subdircheck
-{
-	my $module = shift;
-
-	if (   !-d "$module/sql"
-		|| !-d "$module/expected"
-		|| (!-f "$module/GNUmakefile" && !-f "$module/Makefile"))
-	{
-		return;
-	}
-
-	chdir $module;
-	my @tests = fetchTests();
-
-	# Leave if no tests are listed in the module.
-	if (scalar @tests == 0)
-	{
-		chdir "..";
-		return;
-	}
-
-	my @opts = fetchRegressOpts();
-
-	print "============================================================\n";
-	print "Checking $module\n";
-	my @args = (
-		"$topdir/$Config/pg_regress/pg_regress",
-		"--bindir=${topdir}/${Config}/psql",
-		"--dbname=contrib_regression", @opts, @tests);
-	print join(' ', @args), "\n";
-	system(@args);
-	chdir "..";
-	return;
-}
-
-sub contribcheck
-{
-	chdir "../../../contrib";
-	my $mstat = 0;
-	foreach my $module (glob("*"))
-	{
-		# these configuration-based exclusions must match Install.pm
-		next if ($module eq "uuid-ossp" && !defined($config->{uuid}));
-		next if ($module eq "sslinfo" && !defined($config->{openssl}));
-		next if ($module eq "pgcrypto" && !defined($config->{openssl}));
-		next if ($module eq "xml2" && !defined($config->{xml}));
-		next if ($module =~ /_plperl$/ && !defined($config->{perl}));
-		next if ($module =~ /_plpython$/ && !defined($config->{python}));
-		next if ($module eq "sepgsql");
-
-		subdircheck($module);
-		my $status = $? >> 8;
-		$mstat ||= $status;
-	}
-	exit $mstat if $mstat;
-	return;
-}
-
-sub modulescheck
-{
-	chdir "../../../src/test/modules";
-	my $mstat = 0;
-	foreach my $module (glob("*"))
-	{
-		subdircheck($module);
-		my $status = $? >> 8;
-		$mstat ||= $status;
-	}
-	exit $mstat if $mstat;
-	return;
-}
-
-sub recoverycheck
-{
-	InstallTemp();
-
-	my $dir = "$topdir/src/test/recovery";
-	my $status = tap_check($dir);
-	exit $status if $status;
-	return;
-}
-
-# Run "initdb", then reconfigure authentication.
-sub standard_initdb
-{
-	return (
-		system('initdb', '-N') == 0 and system(
-			"$topdir/$Config/pg_regress/pg_regress", '--config-auth',
-			$ENV{PGDATA}) == 0);
-}
-
-# This is similar to appendShellString().  Perl system(@args) bypasses
-# cmd.exe, so omit the caret escape layer.
-sub quote_system_arg
-{
-	my $arg = shift;
-
-	# Change N >= 0 backslashes before a double quote to 2N+1 backslashes.
-	$arg =~ s/(\\*)"/${\($1 . $1)}\\"/gs;
-
-	# Change N >= 1 backslashes at end of argument to 2N backslashes.
-	$arg =~ s/(\\+)$/${\($1 . $1)}/gs;
-
-	# Wrap the whole thing in unescaped double quotes.
-	return "\"$arg\"";
-}
-
-sub upgradecheck
-{
-	# pg_upgrade is now handled by bincheck, but keep this target for
-	# backward compatibility.
-	print "upgradecheck is a no-op, use bincheck instead.\n";
-	return;
-}
-
-sub fetchRegressOpts
-{
-	my $handle;
-	open($handle, '<', "GNUmakefile")
-	  || open($handle, '<', "Makefile")
-	  || die "Could not open Makefile";
-	local ($/) = undef;
-	my $m = <$handle>;
-	close($handle);
-	my @opts;
-
-	$m =~ s{\\\r?\n}{}g;
-	if ($m =~ /^\s*REGRESS_OPTS\s*\+?=(.*)/m)
-	{
-
-		# Substitute known Makefile variables, then ignore options that retain
-		# an unhandled variable reference.  Ignore anything that isn't an
-		# option starting with "--".
-		@opts = grep { !/\$\(/ && /^--/ }
-		  map { (my $x = $_) =~ s/\Q$(top_builddir)\E/\"$topdir\"/; $x; }
-		  split(/\s+/, $1);
-	}
-	if ($m =~ /^\s*ENCODING\s*=\s*(\S+)/m)
-	{
-		push @opts, "--encoding=$1";
-	}
-	if ($m =~ /^\s*NO_LOCALE\s*=\s*\S+/m)
-	{
-		push @opts, "--no-locale";
-	}
-	return @opts;
-}
-
-# Fetch the list of tests by parsing a module's Makefile.  An empty
-# list is returned if the module does not need to run anything.
-sub fetchTests
-{
-	my $handle;
-	open($handle, '<', "GNUmakefile")
-	  || open($handle, '<', "Makefile")
-	  || die "Could not open Makefile";
-	local ($/) = undef;
-	my $m = <$handle>;
-	close($handle);
-	my $t = "";
-
-	$m =~ s{\\\r?\n}{}g;
-
-	# A module specifying NO_INSTALLCHECK does not support installcheck,
-	# so bypass its run by returning an empty set of tests.
-	if ($m =~ /^\s*NO_INSTALLCHECK\s*=\s*\S+/m)
-	{
-		return ();
-	}
-
-	if ($m =~ /^REGRESS\s*=\s*(.*)$/gm)
-	{
-		$t = $1;
-		$t =~ s/\s+/ /g;
-
-		if ($m =~ /contrib\/pgcrypto/)
-		{
-
-			# pgcrypto is special since some tests depend on the
-			# configuration of the build
-
-			my $pgptests =
-			  $config->{zlib}
-			  ? GetTests("ZLIB_TST", $m)
-			  : GetTests("ZLIB_OFF_TST", $m);
-			$t =~ s/\$\(CF_PGP_TESTS\)/$pgptests/;
-		}
-	}
-
-	return split(/\s+/, $t);
-}
-
-sub GetTests
-{
-	my $testname = shift;
-	my $m = shift;
-	if ($m =~ /^$testname\s*=\s*(.*)$/gm)
-	{
-		return $1;
-	}
-	return "";
-}
-
-sub InstallTemp
-{
-	unless ($ENV{NO_TEMP_INSTALL})
-	{
-		print "Setting up temp install\n\n";
-		Install("$tmp_installdir", "all", $config);
-	}
-	$ENV{PATH} = "$tmp_installdir/bin;$ENV{PATH}";
-	return;
-}
-
-sub usage
-{
-	print STDERR
-	  "Usage: vcregress.pl <mode> [<arg>]\n\n",
-	  "Options for <mode>:\n",
-	  "  bincheck       run tests of utilities in src/bin/\n",
-	  "  check          deploy instance and run regression tests on it\n",
-	  "  contribcheck   run tests of modules in contrib/\n",
-	  "  ecpgcheck      run regression tests of ECPG\n",
-	  "  installcheck   run regression tests on existing instance\n",
-	  "  isolationcheck run isolation tests\n",
-	  "  modulescheck   run tests of modules in src/test/modules/\n",
-	  "  plcheck        run tests of PL languages\n",
-	  "  recoverycheck  run recovery test suite\n",
-	  "  taptest        run an arbitrary TAP test set\n",
-	  "  upgradecheck   run tests of pg_upgrade (no-op)\n",
-	  "\nOptions for <arg>: (used by check and installcheck)\n",
-	  "  serial         serial mode\n",
-	  "  parallel       parallel mode\n",
-	  "\nOption for <arg>: for taptest\n",
-	  "  TEST_DIR       (required) directory where tests reside\n";
-	exit(1);
-}
diff --git a/src/tools/msvc/gendef.pl b/src/tools/msvc_gendef.pl
similarity index 97%
rename from src/tools/msvc/gendef.pl
rename to src/tools/msvc_gendef.pl
index cf83d7d056..8749fd0dd7 100644
--- a/src/tools/msvc/gendef.pl
+++ b/src/tools/msvc_gendef.pl
@@ -11,7 +11,7 @@ my @def;
 #
 # Script that generates a .DEF file for all objects in a directory
 #
-# src/tools/msvc/gendef.pl
+# src/tools/msvc_gendef.pl
 #
 
 # Given a symbol file path, loops over its contents
@@ -142,7 +142,7 @@ sub writedef
 
 sub usage
 {
-	die("Usage: gendef.pl --arch <arch> --deffile <deffile> --tempdir <tempdir> files-or-directories\n"
+	die("Usage: msvc_gendef.pl --arch <arch> --deffile <deffile> --tempdir <tempdir> files-or-directories\n"
 		  . "    arch: x86 | x86_64\n"
 		  . "    deffile: path of the generated file\n"
 		  . "    tempdir: directory for temporary files\n"
diff --git a/src/tools/perlcheck/pgperlsyncheck b/src/tools/perlcheck/pgperlsyncheck
index da59c9727c..657d2afcc0 100755
--- a/src/tools/perlcheck/pgperlsyncheck
+++ b/src/tools/perlcheck/pgperlsyncheck
@@ -2,7 +2,7 @@
 
 # script to detect compile time errors and warnings in all perl files
 
-INCLUDES="-I src/tools/msvc -I src/tools/msvc/dummylib -I src/backend/catalog"
+INCLUDES="-I src/backend/catalog"
 INCLUDES="-I src/test/perl -I src/backend/utils/mb/Unicode $INCLUDES"
 INCLUDES="-I src/bin/pg_rewind -I src/test/ssl/t $INCLUDES"
 
-- 
2.42.0

