Install shared libraries to bin/ in Windows under MSVC
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 18 Mar 2015 18:16:29 +0000 (15:16 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Wed, 18 Mar 2015 18:16:29 +0000 (15:16 -0300)
Since commit cb4a3b04 we were already doing this for the Cygwin/mingw
toolchains, but MSVC had not been updated to do it.  At Install.pm time,
the Makefile (or GNUmakefile) is inspected, and if a line matching
SO_MAJOR_VERSION is found (indicating a shared library is being built),
then files with the .dll extension are set to be installed in bin/
rather than lib/, while files with .lib extension are installed in lib/.
This makes the MSVC toolchain up to date with cygwin/mingw.

This removes ad-hoc hacks that were copying files into bin/ or lib/
manually (libpq.dll in particular was already being copied into bin).
So while this is a rather ugly kludge, it's still cleaner than what was
there before.

Author: Michael Paquier
Reviewed by: Asif Naeem

src/tools/msvc/Install.pm

index eba9aa08f1b8a32a1e0490c3dd1f20fe78dfcaf1..93a672498ab5f3c34b88be25a8de19b6c83fa84e 100644 (file)
@@ -91,7 +91,6 @@ sub Install
        }
 
        CopySolutionOutput($conf, $target);
-       lcopy($target . '/lib/libpq.dll', $target . '/bin/libpq.dll');
        my $sample_files = [];
        my @top_dir      = ("src");
        @top_dir = ("src\\bin", "src\\interfaces") if ($insttype eq "client");
@@ -106,14 +105,8 @@ sub Install
        CopyFiles(
                'Import libraries',
                $target . '/lib/',
-               "$conf\\",
-               "postgres\\postgres.lib",
-               "libpq\\libpq.lib",
-               "libecpg\\libecpg.lib",
-               "libpgcommon\\libpgcommon.lib",
-               "libpgport\\libpgport.lib",
-               "libpgtypes\\libpgtypes.lib",
-               "libecpg_compat\\libecpg_compat.lib");
+               "$conf\\", "postgres\\postgres.lib", "libpgcommon\\libpgcommon.lib",
+               "libpgport\\libpgport.lib");
        CopyContribFiles($config, $target);
        CopyIncludeFiles($target);
 
@@ -236,8 +229,14 @@ sub CopySolutionOutput
        while ($sln =~ $rem)
        {
                my $pf = $1;
-               my $dir;
-               my $ext;
+
+               # 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//;
 
@@ -247,22 +246,45 @@ sub CopySolutionOutput
 
                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)
                        {
-                               $dir = "bin";
-                               $ext = "exe";
+                               push(@{ $install_list{'bin'} }, "exe");
                        }
                        elsif ($1 == 2)
                        {
-                               $dir = "lib";
-                               $ext = "dll";
+                               push(@{ $install_list{'lib'} }, "dll");
+                               if ($is_sharedlib)
+                               {
+                                       push(@{ $install_list{'bin'} }, "dll");
+                                       push(@{ $install_list{'lib'} }, "lib");
+                               }
                        }
                        else
                        {
 
-# Static lib, such as libpgport, only used internally during build, don't install
+                               # Static libraries, such as libpgport, only used internally
+                               # during build, don't install.
                                next;
                        }
                }
@@ -271,18 +293,21 @@ sub CopySolutionOutput
                {
                        if ($1 eq 'Application')
                        {
-                               $dir = "bin";
-                               $ext = "exe";
+                               push(@{ $install_list{'bin'} }, "exe");
                        }
                        elsif ($1 eq 'DynamicLibrary')
                        {
-                               $dir = "lib";
-                               $ext = "dll";
+                               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
+                               # Static lib, such as libpgport, only used internally
+                               # during build, don't install.
                                next;
                        }
                }
@@ -290,8 +315,16 @@ sub CopySolutionOutput
                {
                        croak "Could not parse $pf.$vcproj\n";
                }
-               lcopy("$conf\\$pf\\$pf.$ext", "$target\\$dir\\$pf.$ext")
-                 || croak "Could not copy $pf.$ext\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 ".";