Enable building with Microsoft Visual Studio 2012.
authorAndrew Dunstan
Wed, 6 Feb 2013 19:52:29 +0000 (14:52 -0500)
committerAndrew Dunstan
Wed, 6 Feb 2013 19:52:29 +0000 (14:52 -0500)
Backpatch to release 9.2

Brar Piening and Noah Misch, reviewed by Craig Ringer.

doc/src/sgml/install-windows.sgml
src/backend/utils/adt/pg_locale.c
src/bin/initdb/initdb.c
src/port/chklocale.c
src/port/win32env.c
src/tools/msvc/MSBuildProject.pm
src/tools/msvc/README
src/tools/msvc/Solution.pm
src/tools/msvc/VSObjectFactory.pm
src/tools/msvc/build.pl
src/tools/msvc/gendef.pl

index 452cf3195a52bf977878ebf102fbd906dc19deee..a33038195428bc599c61c31a49cf28ff9c362db5 100644 (file)
@@ -19,8 +19,8 @@
  
   There are several different ways of building PostgreSQL on
   Windows. The simplest way to build with
-  Microsoft tools is to install a supported version of the
-  Microsoft Windows SDK and use the included
+  Microsoft tools is to install Visual Studio Express 2012
+  for Windows Desktop and use the included
   compiler. It is also possible to build with the full
   Microsoft Visual C++ 2005, 2008 or 2010. In some cases
   that requires the installation of the Windows SDK
   Visual Studio Express or some versions of the
   Microsoft Windows SDK. If you do not already have a
   Visual Studio environment set up, the easiest
-  way is to use the compilers in the Windows SDK,
-  which is a free download from Microsoft.
+  ways are to use the compilers in the Windows SDK 7.1
+  or those from Visual Studio Express 2012 for Windows
+  Desktop, which are both free downloads from Microsoft.
  
 
  
   PostgreSQL is known to support compilation using the compilers shipped with
   Visual Studio 2005 to
-  Visual Studio 2010 (including Express editions),
+  Visual Studio 2012 (including Express editions),
   as well as standalone Windows SDK releases 6.0 to 7.1.
   64-bit PostgreSQL builds are only supported with
-  Microsoft Windows SDK version 6.0a and above or
+  Microsoft Windows SDK version 6.0a to 7.1 or
   Visual Studio 2008 and above.
  
 
@@ -149,17 +150,20 @@ $ENV{PATH}=$ENV{PATH} . ';c:\some\where\bison\bin';
     
      Microsoft Windows SDK
      
-      It is recommended that you upgrade to the latest supported version
-      of the Microsoft Windows SDK (currently
+      If your build environment doesn't ship with a supported version of the
+      Microsoft Windows SDK it
+      is recommended that you upgrade to the latest version (currently
       version 7.1), available for download from
       .
      
      
       You must always include the
       Windows Headers and Libraries part of the SDK.
-      If you install the Windows SDK
+      If you install a Windows SDK
       including the Visual C++ Compilers,
       you don't need Visual Studio to build.
+      Note that as of Version 8.0a the Windows SDK no longer ships with a
+      complete command-line build environment.
      
     
 
index 8fe824b426e21586285e2ad44e4cc975366c082f..890aa198167d5e1c5b55bef68968a3b0bc27ba4c 100644 (file)
@@ -715,12 +715,41 @@ cache_locale_time(void)
 
 #if defined(WIN32) && defined(LC_MESSAGES)
 /*
- * Convert Windows locale name to the ISO formatted one
- * if possible.
+ * Convert a Windows setlocale() argument to a Unix-style one.
  *
- * This function returns NULL if conversion is impossible,
- * otherwise returns the pointer to a static area which
- * contains the iso formatted locale name.
+ * Regardless of platform, we install message catalogs under a Unix-style
+ * LL[_CC][.ENCODING][@VARIANT] naming convention.  Only LC_MESSAGES settings
+ * following that style will elicit localized interface strings.
+ *
+ * Before Visual Studio 2012 (msvcr110.dll), Windows setlocale() accepted "C"
+ * (but not "c") and strings of the form [_][.],
+ * case-insensitive.  setlocale() returns the fully-qualified form; for
+ * example, setlocale("thaI") returns "Thai_Thailand.874".  Internally,
+ * setlocale() and _create_locale() select a "locale identifier"[1] and store
+ * it in an undocumented _locale_t field.  From that LCID, we can retrieve the
+ * ISO 639 language and the ISO 3166 country.  Character encoding does not
+ * matter, because the server and client encodings govern that.
+ *
+ * Windows Vista introduced the "locale name" concept[2], closely following
+ * RFC 4646.  Locale identifiers are now deprecated.  Starting with Visual
+ * Studio 2012, setlocale() accepts locale names in addition to the strings it
+ * accepted historically.  It does not standardize them; setlocale("Th-tH")
+ * returns "Th-tH".  setlocale(category, "") still returns a traditional
+ * string.  Furthermore, msvcr110.dll changed the undocumented _locale_t
+ * content to carry locale names instead of locale identifiers.
+ *
+ * MinGW headers declare _create_locale(), but msvcrt.dll lacks that symbol.
+ * IsoLocaleName() always fails in a MinGW-built postgres.exe, so only
+ * Unix-style values of the lc_messages GUC can elicit localized messages.  In
+ * particular, every lc_messages setting that initdb can select automatically
+ * will yield only C-locale messages.  XXX This could be fixed by running the
+ * fully-qualified locale name through a lookup table.
+ *
+ * This function returns a pointer to a static buffer bearing the converted
+ * name or NULL if conversion fails.
+ *
+ * [1] http://msdn.microsoft.com/en-us/library/windows/desktop/dd373763.aspx
+ * [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd373814.aspx
  */
 static char *
 IsoLocaleName(const char *winlocname)
@@ -739,6 +768,34 @@ IsoLocaleName(const char *winlocname)
    loct = _create_locale(LC_CTYPE, winlocname);
    if (loct != NULL)
    {
+#if (_MSC_VER >= 1700)         /* Visual Studio 2012 or later */
+       size_t      rc;
+       char       *hyphen;
+
+       /* Locale names use only ASCII, any conversion locale suffices. */
+       rc = wchar2char(iso_lc_messages, loct->locinfo->locale_name[LC_CTYPE],
+                       sizeof(iso_lc_messages), NULL);
+       _free_locale(loct);
+       if (rc == -1 || rc == sizeof(iso_lc_messages))
+           return NULL;
+
+       /*
+        * Since the message catalogs sit on a case-insensitive filesystem, we
+        * need not standardize letter case here.  So long as we do not ship
+        * message catalogs for which it would matter, we also need not
+        * translate the script/variant portion, e.g. uz-Cyrl-UZ to
+        * uz_UZ@cyrillic.  Simply replace the hyphen with an underscore.
+        *
+        * Note that the locale name can be less-specific than the value we
+        * would derive under earlier Visual Studio releases.  For example,
+        * French_France.1252 yields just "fr".  This does not affect any of
+        * the country-specific message catalogs available as of this writing
+        * (pt_BR, zh_CN, zh_TW).
+        */
+       hyphen = strchr(iso_lc_messages, '-');
+       if (hyphen)
+           *hyphen = '_';
+#else
        char        isolang[32],
                    isocrty[32];
        LCID        lcid;
@@ -753,6 +810,7 @@ IsoLocaleName(const char *winlocname)
        if (!GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, isocrty, sizeof(isocrty)))
            return NULL;
        snprintf(iso_lc_messages, sizeof(iso_lc_messages) - 1, "%s_%s", isolang, isocrty);
+#endif
        return iso_lc_messages;
    }
    return NULL;
index 1bba4268a5a90c0ac7806e131050085fb78ef897..b75d9768561ed25a6620cd02060c989cb158f9b8 100644 (file)
@@ -935,14 +935,22 @@ find_matching_ts_config(const char *lc_type)
 
    /*
     * Convert lc_ctype to a language name by stripping everything after an
-    * underscore.  Just for paranoia, we also stop at '.' or '@'.
+    * underscore (usual case) or a hyphen (Windows "locale name"; see
+    * comments at IsoLocaleName()).
+    *
+    * XXX Should ' ' be a stop character?  This would select "norwegian" for
+    * the Windows locale "Norwegian (Nynorsk)_Norway.1252".  If we do so, we
+    * should also accept the "nn" and "nb" Unix locales.
+    *
+    * Just for paranoia, we also stop at '.' or '@'.
     */
    if (lc_type == NULL)
        langname = pg_strdup("");
    else
    {
        ptr = langname = pg_strdup(lc_type);
-       while (*ptr && *ptr != '_' && *ptr != '.' && *ptr != '@')
+       while (*ptr &&
+              *ptr != '_' && *ptr != '-' && *ptr != '.' && *ptr != '@')
            ptr++;
        *ptr = '\0';
    }
index 7e2062c6bb37624561205a12084ddb834b3c67e9..9e889383f26ade91f1c92e0491adff51c592a676 100644 (file)
@@ -189,26 +189,49 @@ static const struct encoding_match encoding_match_list[] = {
 
 #ifdef WIN32
 /*
- * On Windows, use CP instead of the nl_langinfo() result
+ * On Windows, use CP instead of the nl_langinfo() result
+ *
+ * Visual Studio 2012 expanded the set of valid LC_CTYPE values, so have its
+ * locale machinery determine the code page.  See comments at IsoLocaleName().
+ * For other compilers, follow the locale's predictable format.
+ *
+ * Returns a malloc()'d string for the caller to free.
  */
 static char *
 win32_langinfo(const char *ctype)
 {
-   char       *r;
+   char       *r = NULL;
+
+#if (_MSC_VER >= 1700)
+   _locale_t   loct = NULL;
+
+   loct = _create_locale(LC_CTYPE, ctype);
+   if (loct != NULL)
+   {
+       r = malloc(16);         /* excess */
+       if (r != NULL)
+           sprintf(r, "CP%u", loct->locinfo->lc_codepage);
+       _free_locale(loct);
+   }
+#else
    char       *codepage;
-   int         ln;
 
    /*
     * Locale format on Win32 is _. . For
-    * example, English_USA.1252.
+    * example, English_United States.1252.
     */
    codepage = strrchr(ctype, '.');
-   if (!codepage)
-       return NULL;
-   codepage++;
-   ln = strlen(codepage);
-   r = malloc(ln + 3);
-   sprintf(r, "CP%s", codepage);
+   if (codepage != NULL)
+   {
+       int         ln;
+
+       codepage++;
+       ln = strlen(codepage);
+       r = malloc(ln + 3);
+       if (r != NULL)
+           sprintf(r, "CP%s", codepage);
+   }
+#endif
 
    return r;
 }
index 5f0f6f98599c67ce47498822a4f2dbc27fcacca4..b5f4e8e6d66bd32ff583a8194b5e462dd55c3de0 100644 (file)
@@ -60,6 +60,12 @@ pgwin32_putenv(const char *envval)
        {
            "msvcr90", 0, NULL
        },                      /* Visual Studio 2008 */
+       {
+           "msvcr100", 0, NULL
+       },                      /* Visual Studio 2010 */
+       {
+           "msvcr110", 0, NULL
+       },                      /* Visual Studio 2012 */
        {
            NULL, 0, NULL
        }
index 2e3eab6599d2dbf37cb501e30c2d2fea4bfb0121..0cafd717a2baae8f4235e4a22dccb1697ddb2030 100644 (file)
@@ -1,7 +1,7 @@
 package MSBuildProject;
 
 #
-# Package that encapsulates a MSBuild (Visual C++ 2010) project file
+# Package that encapsulates a MSBuild project file (Visual C++ 2010 or greater)
 #
 # src/tools/msvc/MSBuildProject.pm
 #
@@ -397,4 +397,46 @@ sub new
    return $self;
 }
 
+package VC2012Project;
+
+#
+# Package that encapsulates a Visual C++ 2012 project file
+#
+
+use strict;
+use warnings;
+use base qw(MSBuildProject);
+
+sub new
+{
+    my $classname = shift;
+    my $self = $classname->SUPER::_new(@_);
+    bless($self, $classname);
+
+    $self->{vcver} = '11.00';
+
+    return $self;
+}
+
+# This override adds the  element
+# to the PropertyGroup labeled "Configuration"
+sub WriteConfigurationPropertyGroup
+{
+    my ($self, $f, $cfgname, $p) = @_;
+    my $cfgtype =
+      ($self->{type} eq "exe")
+      ?'Application'
+      :($self->{type} eq "dll"?'DynamicLibrary':'StaticLibrary');
+
+    print $f <
+  {platform}'" Label="Configuration">
+    $cfgtype
+    false
+    MultiByte
+    $p->{wholeopt}
+    v110
+  
+EOF
+}
+
 1;
index 3b2939ad68692c2e097430aedc3a60858cdf2412..b61ddb8791328dd594af6cf201fe3c70e79f8f73 100644 (file)
@@ -92,10 +92,11 @@ 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.
+a VS2008Solution, a VS2010Solution or a VS2012Solution, 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 or VC2012Project 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)
index 850a1dfabcf58907bf5a41314309e6eb75c8b77d..e271ac8d9be75a0a26851a46836c8882c78b61a6 100644 (file)
@@ -63,13 +63,12 @@ sub DeterminePlatform
 {
    my $self = shift;
 
-   # Determine if we are in 32 or 64-bit mode. Do this by seeing if CL has
-   # 64-bit only parameters.
+   # Examine CL help output to determine if we are in 32 or 64-bit mode.
    $self->{platform} = 'Win32';
-   open(P, "cl /? 2>NUL|") || die "cl command not found";
+   open(P, "cl /? 2>&1 |") || die "cl command not found";
    while (

)

    {
-       if (/^\/favor:
+       if (/^\/favor:<.+AMD64/)
        {
            $self->{platform} = 'x64';
            last;
@@ -700,4 +699,28 @@ sub new
    return $self;
 }
 
+package VS2012Solution;
+
+#
+# Package that encapsulates a Visual Studio 2012 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} = '12.00';
+    $self->{vcver} = '11.00';
+    $self->{visualStudioName} = 'Visual Studio 2012';
+
+    return $self;
+}
+
 1;
index c3aa33ec24ff4bc3acdec16a4c59f79175ff39fb..0fbf3faa0eddc7dce5d70d58f42fc5e7bc7b479d 100644 (file)
@@ -41,6 +41,10 @@ sub CreateSolution
    {
        return new VS2010Solution(@_);
    }
+   elsif ($visualStudioVersion eq '11.00')
+   {
+       return new VS2012Solution(@_);
+   }
    else
    {
        croak "The requested Visual Studio version is not supported.";
@@ -68,6 +72,10 @@ sub CreateProject
    {
        return new VC2010Project(@_);
    }
+   elsif ($visualStudioVersion eq '11.00')
+   {
+       return new VC2012Project(@_);
+   }
    else
    {
        croak "The requested Visual Studio version is not supported.";
@@ -82,7 +90,7 @@ sub DetermineVisualStudioVersion
    {
 
 # Determine version of nmake command, to set proper version of visual studio
-# we use nmake as it has existed for a long time and still exists in visual studio 2010
+# we use nmake as it has existed for a long time and still exists in current visual studio versions
        open(P, "nmake /? 2>&1 |")
          || croak
 "Unable to determine Visual Studio version: The nmake command wasn't found.";
@@ -107,11 +115,11 @@ sub DetermineVisualStudioVersion
 sub _GetVisualStudioVersion
 {
    my ($major, $minor) = @_;
-   if ($major > 10)
+   if ($major > 11)
    {
        carp
 "The determined version of Visual Studio is newer than the latest supported version. Returning the latest supported version instead.";
-       return '10.00';
+       return '11.00';
    }
    elsif ($major < 6)
    {
index 8979402d4c1b3e77def97bd5fbd850db2ac3ddec..c947bbe318e36a1f7ecf6c3dbd15c17f3e008997 100644 (file)
@@ -50,7 +50,7 @@ elsif ($ARGV[0] ne "RELEASE")
 
 # ... and do it
 
-if ($buildwhat and $vcver eq '10.00')
+if ($buildwhat and $vcver >= 10.00)
 {
    system(
 "msbuild $buildwhat.vcxproj /verbosity:detailed /p:Configuration=$bconf");
index ab65c46cfae9b07e94fa8e1208b0c26e7e61aa9b..8ef0422df9d6514ca901ccd8b2ed65839def2580 100644 (file)
@@ -40,6 +40,7 @@ while (<$ARGV[0]/*.obj>)
        next if $pieces[6] =~ /^\(/;
        next if $pieces[6] =~ /^__real/;
        next if $pieces[6] =~ /^__imp/;
+       next if $pieces[6] =~ /^__xmm/;
        next if $pieces[6] =~ /NULL_THUNK_DATA$/;
        next if $pieces[6] =~ /^__IMPORT_DESCRIPTOR/;
        next if $pieces[6] =~ /^__NULL_IMPORT/;