-
-
-
-EOF
- $self->WriteConfiguration($f, 'Debug',
- { defs=>'_DEBUG;DEBUG=1;', wholeopt=>0, opt=>0, strpool=>'false', runtime=>3 });
- $self->WriteConfiguration($f, 'Release',
- { defs=>'', wholeopt=>0, opt=>3, strpool=>'true', runtime=>2 });
- print $f <
-EOF
-}
-
-sub WriteConfiguration
-{
- my ($self, $f, $cfgname, $p) = @_;
- my $cfgtype = ($self->{type} eq "exe")?1:($self->{type} eq "dll"?2:4);
+ my ($self, $cfgname, $seperator) = @_;
my $libcfg = (uc $cfgname eq "RELEASE")?"MD":"MDd";
my $libs = '';
foreach my $lib (@{$self->{libraries}})
@@ -497,76 +378,11 @@ sub WriteConfiguration
last;
}
}
- $libs .= $xlib . " ";
+ $libs .= $xlib . $seperator;
}
- $libs =~ s/ $//;
+ $libs =~ s/.$//;
$libs =~ s/__CFGNAME__/$cfgname/g;
-
- my $targetmachine = $self->{platform} eq 'Win32' ? 1 : 17;
-
- print $f <
-
- {disablelinkerwarnings})
- {
- print $f "\t\tAdditionalOptions=\"/ignore:$self->{disablelinkerwarnings}\"\n";
- }
- if ($self->{implib})
- {
- my $l = $self->{implib};
- $l =~ s/__CFGNAME__/$cfgname/g;
- print $f "\t\tImportLibrary=\"$l\"\n";
- }
- if ($self->{def})
- {
- my $d = $self->{def};
- $d =~ s/__CFGNAME__/$cfgname/g;
- print $f "\t\tModuleDefinitionFile=\"$d\"\n";
- }
-
- print $f "\t/>\n";
- print $f
-"\t{name}\\$self->{name}.lib\" IgnoreDefaultLibraryNames=\"libc\" />\n";
- print $f
- "\t\n";
- if ($self->{builddef})
- {
- print $f
-"\t{name} $self->{platform}\" />\n";
- }
- print $f <
-EOF
-}
-
-sub Footer
-{
- my ($self, $f) = @_;
-
- print $f <
-
-
-EOF
+ return $libs;
}
# Utility function that loads a complete file
diff --git a/src/tools/msvc/README b/src/tools/msvc/README
index b8dd488b6f6..ad0eca3672b 100644
--- a/src/tools/msvc/README
+++ b/src/tools/msvc/README
@@ -4,19 +4,19 @@ MSVC build
==========
This directory contains the tools required to build PostgreSQL using
-Microsoft Visual Studio 2005. This builds the whole backend, not just
+Microsoft Visual Studio 2005 - 2011. This builds the whole backend, not just
the libpq frontend library. For more information, see the documentation
-chapter "Installation on Windows".
+chapter "Installation on Windows" and the description below.
Notes about Visual Studio Express
---------------------------------
-To build PostgreSQL using Visual Studio Express, the Platform SDK
+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 the latest Platform SDK from
-www.microsoft.com.
+First, download and install a supported version of the Microsoft Windows SDK
+from www.microsoft.com (v6.0 or greater).
Locate the files vcprojectengine.dll.express.config and
vcprojectengine.dll.config in the vc\vcpackages directory of
@@ -26,3 +26,77 @@ 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
+builddoc.pl tool to build the docs
+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 2010 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.
+VCBuildProject.pm module containing the code to generate VCBuild based
+ project files (Visual Studio 2005/2008)
+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
+it's 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 addtion 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 a VS2005Solution,
+a VS2008Solution or a VS2010Solution, all in Solution.pm, depending on the
+user's build environment) and adding objects implementing the corresponding
+Project interface (VC2005Project or VC2008Project from VCBuildProject.pm or
+VC2010Project 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 or vcbuild)
+is performed in build.pl again.
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 36fd4b71601..1725fbb5330 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -8,10 +8,11 @@ package Solution;
use Carp;
use strict;
use warnings;
+use VSObjectFactory;
-sub new
+sub _new
{
- my $junk = shift;
+ my $classname = shift;
my $options = shift;
my $self = {
projects => {},
@@ -21,7 +22,7 @@ sub new
vcver => undef,
platform => undef,
};
- bless $self;
+ bless($self, $classname);
# integer_datetimes is now the default
$options->{integer_datetimes} = 1
@@ -53,28 +54,15 @@ sub new
die "Bad wal_segsize $options->{wal_segsize}"
unless grep {$_ == $options->{wal_segsize}} (1,2,4,8,16,32,64);
- $self->DetermineToolVersions();
+ $self->DeterminePlatform();
return $self;
}
-sub DetermineToolVersions
+sub DeterminePlatform
{
my $self = shift;
- # Determine version of vcbuild command, to set proper verison of visual studio
- open(P,"vcbuild /? |") || die "vcbuild command not found";
- my $line = ;
- close(P);
- if ($line !~ /^Microsoft\s*\(R\) Visual C\+\+ [^-]+ - \D+(\d+)\.00\.\d+/)
- {
- die "Unable to determine vcbuild version from first line of output!";
- }
- if ($1 == 8) { $self->{vcver} = '8.00' }
- elsif ($1 == 9) { $self->{vcver} = '9.00' }
- else { die "Unsupported version of Visual Studio: $1" }
- print "Detected Visual Studio version $self->{vcver}\n";
-
# Determine if we are in 32 or 64-bit mode. Do this by seeing if CL has
# 64-bit only parameters.
$self->{platform} = 'Win32';
@@ -428,7 +416,7 @@ sub AddProject
{
my ($self, $name, $type, $folder, $initialdir) = @_;
- my $proj = new Project($name, $type, $self);
+ my $proj = VSObjectFactory::CreateProject($self->{vcver}, $name, $type, $self);
push @{$self->{projects}->{$folder}}, $proj;
$proj->AddDir($initialdir) if ($initialdir);
if ($self->{options}->{zlib})
@@ -488,8 +476,8 @@ sub Save
open(SLN,">pgsql.sln") || croak "Could not write to pgsql.sln\n";
print SLN <{solutionFileVersion}
+# $self->{visualStudioName}
EOF
foreach my $fld (keys %{$self->{projects}})
@@ -497,7 +485,7 @@ EOF
foreach my $proj (@{$self->{projects}->{$fld}})
{
print SLN <{name}", "$proj->{name}.vcproj", "$proj->{guid}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "$proj->{name}", "$proj->{name}$proj->{filenameExtension}", "$proj->{guid}"
EndProject
EOF
}
@@ -579,4 +567,74 @@ sub GetFakeConfigure
return $cfg;
}
+package VS2005Solution;
+
+#
+# Package that encapsulates a Visual Studio 2005 solution file
+#
+
+use strict;
+use warnings;
+use base qw(Solution);
+
+sub new
+{
+ my $classname = shift;
+ my $self = $classname->SUPER::_new(@_);
+ bless($self, $classname);
+
+ $self->{solutionFileVersion} = '9.00';
+ $self->{vcver} = '8.00';
+ $self->{visualStudioName} = 'Visual Studio 2005';
+
+ return $self;
+}
+
+package VS2008Solution;
+
+#
+# Package that encapsulates a Visual Studio 2008 solution file
+#
+
+use strict;
+use warnings;
+use base qw(Solution);
+
+sub new
+{
+ my $classname = shift;
+ my $self = $classname->SUPER::_new(@_);
+ bless($self, $classname);
+
+ $self->{solutionFileVersion} = '10.00';
+ $self->{vcver} = '9.00';
+ $self->{visualStudioName} = 'Visual Studio 2008';
+
+ return $self;
+}
+
+package VS2010Solution;
+
+#
+# Package that encapsulates a Visual Studio 2010 solution file
+#
+
+use Carp;
+use strict;
+use warnings;
+use base qw(Solution);
+
+sub new
+{
+ my $classname = shift;
+ my $self = $classname->SUPER::_new(@_);
+ bless($self, $classname);
+
+ $self->{solutionFileVersion} = '11.00';
+ $self->{vcver} = '10.00';
+ $self->{visualStudioName} = 'Visual Studio 2010';
+
+ return $self;
+}
+
1;
diff --git a/src/tools/msvc/VCBuildProject.pm b/src/tools/msvc/VCBuildProject.pm
new file mode 100644
index 00000000000..97439d9d5c4
--- /dev/null
+++ b/src/tools/msvc/VCBuildProject.pm
@@ -0,0 +1,267 @@
+package VCBuildProject;
+
+#
+# Package that encapsulates a VCBuild (Visual C++ 2005/2008) project file
+#
+# src/tools/msvc/VCBuildProject.pm
+#
+
+use Carp;
+use strict;
+use warnings;
+use base qw(Project);
+
+sub _new
+{
+ my $classname = shift;
+ my $self = $classname->SUPER::_new(@_);
+ bless($self, $classname);
+
+ $self->{filenameExtension} = '.vcproj';
+
+ return $self;
+}
+
+sub WriteHeader
+{
+ my ($self, $f) = @_;
+
+ print $f <
+
+
+
+EOF
+ $self->WriteConfiguration($f, 'Debug',
+ { defs=>'_DEBUG;DEBUG=1;', wholeopt=>0, opt=>0, strpool=>'false', runtime=>3 });
+ $self->WriteConfiguration($f, 'Release',
+ { defs=>'', wholeopt=>0, opt=>3, strpool=>'true', runtime=>2 });
+ print $f <
+EOF
+ $self->WriteReferences($f);
+}
+
+sub WriteFiles
+{
+ my ($self, $f) = @_;
+ print $f <
+EOF
+ my @dirstack = ();
+ my %uniquefiles;
+ foreach my $fileNameWithPath (sort keys %{ $self->{files} })
+ {
+ confess "Bad format filename '$fileNameWithPath'\n"
+ unless ($fileNameWithPath =~ /^(.*)\\([^\\]+)\.[r]?[cyl]$/);
+ my $dir = $1;
+ my $file = $2;
+
+ # Walk backwards down the directory stack and close any dirs we're done with
+ while ($#dirstack >= 0)
+ {
+ if (join('\\',@dirstack) eq substr($dir, 0, length(join('\\',@dirstack))))
+ {
+ last if (length($dir) == length(join('\\',@dirstack)));
+ last if (substr($dir, length(join('\\',@dirstack)),1) eq '\\');
+ }
+ print $f ' ' x $#dirstack . " \n";
+ pop @dirstack;
+ }
+
+ # Now walk forwards and create whatever directories are needed
+ while (join('\\',@dirstack) ne $dir)
+ {
+ my $left = substr($dir, length(join('\\',@dirstack)));
+ $left =~ s/^\\//;
+ my @pieces = split /\\/, $left;
+ push @dirstack, $pieces[0];
+ print $f ' ' x $#dirstack . " \n";
+ }
+
+ print $f ' ' x $#dirstack . " '
+ . $self->GenerateCustomTool('Running bison on ' . $fileNameWithPath,
+ "perl src\\tools\\msvc\\pgbison.pl $fileNameWithPath", $of)
+ . '' . "\n";
+ }
+ elsif ($fileNameWithPath =~ /\.l$/)
+ {
+ my $of = $fileNameWithPath;
+ $of =~ s/\.l$/.c/;
+ print $f '>'
+ . $self->GenerateCustomTool('Running flex on ' . $fileNameWithPath,
+ "perl src\\tools\\msvc\\pgflex.pl $fileNameWithPath", $of)
+ . '' . "\n";
+ }
+ elsif (defined($uniquefiles{$file}))
+ {
+
+ # File already exists, so fake a new name
+ my $obj = $dir;
+ $obj =~ s/\\/_/g;
+ print $f
+">{platform}\">{name}\\$obj"
+ . "_$file.obj\" />{platform}\">{name}\\$obj"
+ . "_$file.obj\" />\n";
+ }
+ else
+ {
+ $uniquefiles{$file} = 1;
+ print $f " />\n";
+ }
+ }
+ while ($#dirstack >= 0)
+ {
+ print $f ' ' x $#dirstack . " \n";
+ pop @dirstack;
+ }
+ print $f <
+EOF
+}
+
+sub Footer
+{
+ my ($self, $f) = @_;
+
+ print $f <
+
+EOF
+}
+
+sub WriteConfiguration
+{
+ my ($self, $f, $cfgname, $p) = @_;
+ my $cfgtype = ($self->{type} eq "exe")?1:($self->{type} eq "dll"?2:4);
+ my $libs = $self->GetAdditionalLinkerDependencies($cfgname, ' ');
+
+ my $targetmachine = $self->{platform} eq 'Win32' ? 1 : 17;
+
+ print $f <
+
+ {disablelinkerwarnings})
+ {
+ print $f "\t\tAdditionalOptions=\"/ignore:$self->{disablelinkerwarnings}\"\n";
+ }
+ if ($self->{implib})
+ {
+ my $l = $self->{implib};
+ $l =~ s/__CFGNAME__/$cfgname/g;
+ print $f "\t\tImportLibrary=\"$l\"\n";
+ }
+ if ($self->{def})
+ {
+ my $d = $self->{def};
+ $d =~ s/__CFGNAME__/$cfgname/g;
+ print $f "\t\tModuleDefinitionFile=\"$d\"\n";
+ }
+
+ print $f "\t/>\n";
+ print $f
+"\t{name}\\$self->{name}.lib\" IgnoreDefaultLibraryNames=\"libc\" />\n";
+ print $f
+ "\t\n";
+ if ($self->{builddef})
+ {
+ print $f
+"\t{name} $self->{platform}\" />\n";
+ }
+ print $f <
+EOF
+}
+
+sub WriteReferences
+{
+ my ($self, $f) = @_;
+ print $f " \n";
+ foreach my $ref (@{$self->{references}})
+ {
+ print $f
+" {guid}\" Name=\"$ref->{name}\" />\n";
+ }
+ print $f " \n";
+}
+
+sub GenerateCustomTool
+{
+ my ($self, $desc, $tool, $output, $cfg) = @_;
+ if (!defined($cfg))
+ {
+ return $self->GenerateCustomTool($desc, $tool, $output, 'Debug')
+ .$self->GenerateCustomTool($desc, $tool, $output, 'Release');
+ }
+ return
+"{platform}\">";
+}
+
+package VC2005Project;
+
+#
+# Package that encapsulates a Visual C++ 2005 project file
+#
+
+use strict;
+use warnings;
+use base qw(VCBuildProject);
+
+sub new
+{
+ my $classname = shift;
+ my $self = $classname->SUPER::_new(@_);
+ bless($self, $classname);
+
+ $self->{vcver} = '8.00';
+
+ return $self;
+}
+
+package VC2008Project;
+
+#
+# Package that encapsulates a Visual C++ 2008 project file
+#
+
+use strict;
+use warnings;
+use base qw(VCBuildProject);
+
+sub new
+{
+ my $classname = shift;
+ my $self = $classname->SUPER::_new(@_);
+ bless($self, $classname);
+
+ $self->{vcver} = '9.00';
+
+ return $self;
+}
+
+1;
diff --git a/src/tools/msvc/VSObjectFactory.pm b/src/tools/msvc/VSObjectFactory.pm
new file mode 100644
index 00000000000..44db1f6814c
--- /dev/null
+++ b/src/tools/msvc/VSObjectFactory.pm
@@ -0,0 +1,122 @@
+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 VCBuildProject;
+use MSBuildProject;
+
+our (@ISA, @EXPORT);
+@ISA = qw(Exporter);
+@EXPORT = qw(CreateSolution CreateProject DetermineVisualStudioVersion);
+
+sub CreateSolution
+{
+ my $visualStudioVersion = shift;
+
+ if (!defined($visualStudioVersion))
+ {
+ $visualStudioVersion = DetermineVisualStudioVersion();
+ }
+
+ if ($visualStudioVersion eq '8.00')
+ {
+ return new VS2005Solution(@_);
+ }
+ elsif ($visualStudioVersion eq '9.00')
+ {
+ return new VS2008Solution(@_);
+ }
+ elsif ($visualStudioVersion eq '10.00')
+ {
+ return new VS2010Solution(@_);
+ }
+ else
+ {
+ croak "The requested Visual Studio version is not supported.";
+ }
+}
+
+sub CreateProject
+{
+ my $visualStudioVersion = shift;
+
+ if (!defined($visualStudioVersion))
+ {
+ $visualStudioVersion = DetermineVisualStudioVersion();
+ }
+
+ if ($visualStudioVersion eq '8.00')
+ {
+ return new VC2005Project(@_);
+ }
+ elsif ($visualStudioVersion eq '9.00')
+ {
+ return new VC2008Project(@_);
+ }
+ elsif ($visualStudioVersion eq '10.00')
+ {
+ return new VC2010Project(@_);
+ }
+ else
+ {
+ croak "The requested Visual Studio version is not supported.";
+ }
+}
+
+sub DetermineVisualStudioVersion
+{
+ my $nmakeVersion = shift;
+
+ if (!defined($nmakeVersion))
+ {
+
+ # Determine version of nmake command, to set proper verison of visual studio
+ # we use nmake as it has existed for a long time and still exists in visual studio 2010
+ open(P,"nmake /? 2>&1 |")
+ || croak "Unable to determine Visual Studio version: The nmake command wasn't found.";
+ while()
+ {
+ chomp;
+ if (/(\d+)\.(\d+)\.\d+(\.\d+)?$/)
+ {
+ return _GetVisualStudioVersion($1, $2);
+ }
+ }
+ close(P);
+ }
+ elsif($nmakeVersion =~ /(\d+)\.(\d+)\.\d+(\.\d+)?$/)
+ {
+ return _GetVisualStudioVersion($1, $2);
+ }
+ croak "Unable to determine Visual Studio version: The nmake version could not be determined.";
+}
+
+sub _GetVisualStudioVersion
+{
+ my($major, $minor) = @_;
+ if ($major > 10)
+ {
+ carp
+"The determined version of Visual Studio is newer than the latest supported version. Returning the latest supported version instead.";
+ return '10.00';
+ }
+ elsif ($major < 6)
+ {
+ croak
+"Unable to determine Visual Studio version: Visual Studio versions before 6.0 aren't supported.";
+ }
+ return "$major.$minor";
+}
+
+1;
diff --git a/src/tools/msvc/build.pl b/src/tools/msvc/build.pl
index 66b5c4c59ba..151849bba51 100644
--- a/src/tools/msvc/build.pl
+++ b/src/tools/msvc/build.pl
@@ -33,7 +33,7 @@ our $config;
require "config_default.pl";
require "config.pl" if (-f "src/tools/msvc/config.pl");
-Mkvcbuild::mkvcbuild($config);
+my $vcver = Mkvcbuild::mkvcbuild($config);
# check what sort of build we are doing
@@ -50,7 +50,11 @@ elsif ($ARGV[0] ne "RELEASE")
# ... and do it
-if ($buildwhat)
+if ($buildwhat and $vcver eq '10.00')
+{
+ system("msbuild $buildwhat.vcxproj /verbosity:detailed /p:Configuration=$bconf");
+}
+elsif ($buildwhat)
{
system("vcbuild $buildwhat.vcproj $bconf");
}
diff --git a/src/tools/msvc/builddoc.pl b/src/tools/msvc/builddoc.pl
index 6531e98f1a6..8d8d8a35ccf 100644
--- a/src/tools/msvc/builddoc.pl
+++ b/src/tools/msvc/builddoc.pl
@@ -69,8 +69,8 @@ $cmd =
."| findstr /V \"DTDDECL catalog entries are not supported\" ";
system($cmd); # die "openjade" if $?;
print "Running collateindex...\n";
-$cmd ="perl \"$docroot/$dsssl/bin/collateindex.pl\" -f -g -i bookindex "
- ."-o bookindex.sgml HTML.index";
+$cmd =
+ "perl \"$docroot/$dsssl/bin/collateindex.pl\" -f -g -i bookindex "."-o bookindex.sgml HTML.index";
system($cmd);
die "collateindex" if $?;
mkdir "html";
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
index a59bbe55da9..ac310382e32 100755
--- a/src/tools/msvc/clean.bat
+++ b/src/tools/msvc/clean.bat
@@ -10,8 +10,12 @@ if exist ..\msvc if exist ..\..\..\src cd ..\..\..
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