Hi all

If you're trying to build postgres with Visual Studio Build Tools 16 2019
using the optional v140 toolset that installs the Visual Studio 14 2019
C/C++ toolchain to get binaries that're fully compatible with the EDB
postgres builds, you may run into some confusing issues.

Use this incantation in cmd.exe (not a powershell.exe or pwsh.exe session)
to select the VS 16 msbuild with vs 14 compiler:

    "%PROGRAMFILES(x86)%\Microsoft Visual
Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64
-vcvars_ver=14.0

all on one line, then run src\tools\msvc\build.bat as normal.

If you instead attempt to use the vcvarsall.bat from the v140 toolchain
that VS Build Tools 2019 installed for you, it'll appear to work, but
compilation will then fail by spamming:

    some.vcxproj(17,3): error MSB4019: The imported project
"C:\Microsoft.Cpp.Default.props" was not found. Confirm that the path in
the <Import> declaration is correct, and that the file exists on disk.

This is because the v140 toolset does not include the v140 msbuild. You're
expected to use the v160 msbuild and configure it to use the v140 toolset
instead.

Similar issues occur when you try to use the CMake generator "Visual Studio
14 2015" with a VS Build Tools 2019-installed version of the 140 toolchain;
you have to instead use -G "Visual Studio 16 2019" -T "v140" to select the
VS 16 msbuild and tell it to use the v140 toolchain. Crazy stuff.

If you instead just run:

    "%PROGRAMFILES(x86)%\Microsoft Visual
Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64

Then compilation will run fine, but the resulting binary will use the
version 16 MSVC compilers, runtime library and redist, etc.


Note that all these builds will target the default Windows 10 SDK. That
should be fine; we're very conservative in postgres about new Windows
features and functions, and we do dynamic lookups for a few symbols when
we're not sure if they'll be available. But you can force it to compile for
Windows 7 and higher with by editing Mk.pm and adding the definitions

   WINVER=0x0601
   _WIN32_WINNT=0x0601

to your project. I didn't find a way to add custom preprocessor definitions
in config.pl so for testing purposes I hacked it into MSBuildProject.pm in
the <PreprocessorDefinitions> clause as

    ;WINVER=0x0601;_WIN32_WINNT=0x0601

I've attached a patch that teaches config.pl about a new 'definitions'
option to make this more graceful.

See
https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-160


If you don't have the toolchain installed, you can install Chocolatey
(there's a one-liner on their website) then:

    choco install -y visualstudio2019buildtools

    choco install -y visualstudio2019-vc++ --packageparameters "--add
Microsoft.VisualStudio.Component.VC.140"

You may also want

    choco install -y winflexbison

(I've attached a patch that teaches pgflex.pl and pgbision.pl to use
win_flex.exe and win_bison.exe if they're found, and to accept full paths
for these tools in buildenv.pl).
From ad9625026bcb7768c636fdf3a37a3403db195ae2 Mon Sep 17 00:00:00 2001
From: Craig Ringer <craig.rin...@enterprisedb.com>
Date: Tue, 13 Jul 2021 14:18:44 +1000
Subject: [PATCH v1 1/2] Teach pgflex.pl and pgbision.pl to read buildenv.pl
 for tool names

Some distributions of flex and bison on Windows use alternate executable
names such as win_flex.exe and win_bison.exe. Teach our pgflex.pl and
pgbison.pl wrappers how to handle them by reading the executables to use
from the new $flex and $bison variables in src/tools/msvc/buildenv.pl .

These may be bare names of commands on the PATH or they may be a fully
qualified path to the target executable.

While we're at it, notice when the test execution of flex or bision to
check the version fails and complain with a more informative error.
---
 src/tools/msvc/build.pl            |  4 ++++
 src/tools/msvc/buildenv_default.pl | 14 ++++++++++++++
 src/tools/msvc/pgbison.pl          | 27 +++++++++++++++++++++++----
 src/tools/msvc/pgflex.pl           | 25 +++++++++++++++++++++----
 4 files changed, 62 insertions(+), 8 deletions(-)
 create mode 100644 src/tools/msvc/buildenv_default.pl

diff --git a/src/tools/msvc/build.pl b/src/tools/msvc/build.pl
index de50554e7e..dedd515307 100644
--- a/src/tools/msvc/build.pl
+++ b/src/tools/msvc/build.pl
@@ -28,6 +28,10 @@ elsif (-e "./buildenv.pl")
 {
 	do "./buildenv.pl";
 }
+elsif (-e "src/tools/msvc/buildenv_default.pl")
+{
+	do "src/tools/msvc/buildenv_default.pl";
+}
 
 # set up the project
 our $config;
diff --git a/src/tools/msvc/buildenv_default.pl b/src/tools/msvc/buildenv_default.pl
new file mode 100644
index 0000000000..b3868f2145
--- /dev/null
+++ b/src/tools/msvc/buildenv_default.pl
@@ -0,0 +1,14 @@
+# Copy this file to src\test\msvc\buildenv.pl and modify it as required
+# for your build toolchain, path, etc.
+#
+# Note that there's no way to run vcvarsall.bat from here to set up the
+# visual studio environment. You still have to do that before starting
+# the build.
+#
+# Examples:
+
+#$ENV{PATH}="$ENV{PATH};C:\\ProgramData\\chocolatey\\bin";
+#our $flex = "$ENV{ProgramData}\\chocolatey\\bin\\win_flex.exe";
+#our $bison = "$ENV{ProgramData}\\chocolatey\\bin\\win_bison.exe";
+
+1;
diff --git a/src/tools/msvc/pgbison.pl b/src/tools/msvc/pgbison.pl
index 774d5be059..6289c1aa18 100644
--- a/src/tools/msvc/pgbison.pl
+++ b/src/tools/msvc/pgbison.pl
@@ -7,11 +7,26 @@ use warnings;
 
 use File::Basename;
 
-# assume we are in the postgres source root
+my $bison = $ENV{BISON_EXE} // 'bison';
 
-do './src/tools/msvc/buildenv.pl' if -e 'src/tools/msvc/buildenv.pl';
+# assume we're in the build root.
+if (-e 'src/tools/msvc/buildenv.pl') {
+	do './src/tools/msvc/buildenv.pl';
+} elsif (-e './src/tools/msvc/buildenv_default.pl') {
+	do './src/tools/msvc/buildenv_default.pl';
+} else {
+	die 'Could not find src/tools/msvc/buildenv.pl or ./src/tools/msvc/buildenv_default.pl. Run pgbison from the build root, not src/test/msvc';
+}
 
-my ($bisonver) = `bison -V`;    # grab first line
+our $bison;
+if (! $bison) {
+	$bison = 'bison';
+}
+
+my ($bisonver) = `"$bison" -V`;    # grab first line
+if ($? ne 0) {
+	die "bison (\"$bison\") died with $?, see stderr output above. Check PATH and buildenv.pl"
+}
 $bisonver = (split(/\s+/, $bisonver))[3];    # grab version number
 
 unless ($bisonver eq '1.875' || $bisonver ge '2.2')
@@ -22,6 +37,10 @@ unless ($bisonver eq '1.875' || $bisonver ge '2.2')
 }
 
 my $input = shift;
+if (!defined($input)) {
+	print STDERR "Using bison from ${bison}\n";
+	die "usage: src/test/msvc/pgbison.pl inputfile.l [...]";
+}
 if ($input !~ /\.y$/)
 {
 	print "Input must be a .y file\n";
@@ -49,5 +68,5 @@ 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");
+system("\"$bison\" $nodep $headerflag $input -o $output");
 exit $? >> 8;
diff --git a/src/tools/msvc/pgflex.pl b/src/tools/msvc/pgflex.pl
index 26c73dbfad..69f8ac261c 100644
--- a/src/tools/msvc/pgflex.pl
+++ b/src/tools/msvc/pgflex.pl
@@ -6,15 +6,28 @@ use strict;
 use warnings;
 
 use File::Basename;
+use Cwd;
 
 # silence flex bleatings about file path style
 $ENV{CYGWIN} = 'nodosfilewarning';
 
-# assume we are in the postgres source root
+if (-e 'src/tools/msvc/buildenv.pl') {
+	do './src/tools/msvc/buildenv.pl';
+} elsif (-e './src/tools/msvc/buildenv_default.pl') {
+	do './src/tools/msvc/buildenv_default.pl';
+} else {
+	die 'Could not find src/tools/msvc/buildenv.pl or ./src/tools/msvc/buildenv_default.pl. Run pgflex from the build root, not src/test/msvc';
+}
 
-do './src/tools/msvc/buildenv.pl' if -e 'src/tools/msvc/buildenv.pl';
+our $flex;
+if (! $flex) {
+	$flex = 'flex';
+}
 
-my ($flexver) = `flex -V`;    # grab first line
+my ($flexver) = `"$flex" -V`;    # grab first line
+if ($? ne 0) {
+	die "flex (\"$flex\") died with $?, see stderr output above. Check PATH and buildenv.pl";
+}
 $flexver = (split(/\s+/, $flexver))[1];
 $flexver =~ s/[^0-9.]//g;
 my @verparts = split(/\./, $flexver);
@@ -27,6 +40,10 @@ unless ($verparts[0] == 2
 }
 
 my $input = shift;
+if (!defined($input)) {
+	print STDERR "Using flex from ${flex}\n";
+	die "usage: src/test/msvc/pgflex.pl inputfile.l [...]";
+}
 if ($input !~ /\.l$/)
 {
 	print "Input must be a .l file\n";
@@ -50,7 +67,7 @@ close($mf);
 my $basetarg = basename($output);
 my $flexflags = ($make =~ /^$basetarg:\s*FLEXFLAGS\s*=\s*(\S.*)/m ? $1 : '');
 
-system("flex $flexflags -o$output $input");
+system("\"$flex\" $flexflags -o$output $input");
 if ($? == 0)
 {
 
-- 
2.31.1

From 5df704664843fb6d30bca632bdc009950799acc6 Mon Sep 17 00:00:00 2001
From: Craig Ringer <craig.rin...@enterprisedb.com>
Date: Tue, 13 Jul 2021 14:48:42 +1000
Subject: [PATCH v1 2/2] Support extra preprocessor definitions in config.pl

Add a new 'defines' option in config.pl. This accepts an array of NAME
or NAME=VALUE preprocessor definitions to apply to all projects being
compiled, like somewhat like CPPFLAGS on *nix.

Unlike CPPFLAGS, you cannot pass arbitrary preprocessor, compiler or
linker flags using this method, only actual preprocessor definitions.
---
 src/tools/msvc/Solution.pm       | 9 +++++++++
 src/tools/msvc/config_default.pl | 9 ++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index a13ca6e02e..15701ab03b 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -1045,6 +1045,15 @@ sub AddProject
 		$proj->AddIncludeDir($self->{options}->{uuid} . '\include');
 		$proj->AddLibrary($self->{options}->{uuid} . '\lib\uuid.lib');
 	}
+	if ($self->{options}->{defines}) {
+		if (ref $self->{options}->{defines} eq "ARRAY") {
+			foreach my $definition (@{$self->{options}->{defines}}) {
+				$proj->AddDefine($definition);
+			}
+		} else {
+			die "Key 'defines' in config.pl must have an array value like [\"def1\", \"def2=val\"]."
+		}
+	}
 	return $proj;
 }
 
diff --git a/src/tools/msvc/config_default.pl b/src/tools/msvc/config_default.pl
index 2ef2cfc4e9..1479ea5a9b 100644
--- a/src/tools/msvc/config_default.pl
+++ b/src/tools/msvc/config_default.pl
@@ -1,4 +1,7 @@
 # Configuration arguments for vcbuild.
+#
+# Overridden by any values set in config.pl if it exists.
+#
 use strict;
 use warnings;
 
@@ -21,7 +24,11 @@ our $config = {
 	xml       => undef,    # --with-libxml=<path>
 	xslt      => undef,    # --with-libxslt=<path>
 	iconv     => undef,    # (not in configure, path to iconv)
-	zlib      => undef     # --with-zlib=<path>
+	zlib      => undef,     # --with-zlib=<path>
+	# extra preprocessor definitions in "DEFNAME" or "DEFNAME=VALUE" form.
+	# Does not accept arbitrary compiler flags. e.g.
+	#     ["WINVER=0x0601", "_WIN32_WINNT=0x0601"]
+	defines	  => []
 };
 
 1;
-- 
2.31.1

Reply via email to