]> granicus.if.org Git - postgresql/blobdiff - src/tools/msvc/Install.pm
Remove cvs keywords from all files.
[postgresql] / src / tools / msvc / Install.pm
index 0b7a9b1983fef4e530f132f70c1e77291dbdef6e..4d070b93030eb6b135955b4ef51cec9a7ab19ec8 100644 (file)
@@ -1,23 +1,48 @@
 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);
 
+sub lcopy
+{
+    my $src = shift;
+    my $target = shift;
+
+    if (-f $target)
+    {
+        unlink $target || confess "Could not delete $target\n";
+    }
+
+    copy($src,$target)
+      || confess "Could not copy $src to $target\n";
+
+}
+
 sub Install
 {
     $| = 1;
 
     my $target = shift;
+    our $config;
+    require "config_default.pl";
+    require "config.pl" if (-f "config.pl");
 
     chdir("../../..") if (-f "../../../configure");
+    chdir("../../../..") if (-f "../../../../configure");
     my $conf = "";
     if (-d "debug")
     {
@@ -28,21 +53,43 @@ sub Install
         $conf = "release";
     }
     die "Could not find debug or release binaries" if ($conf eq "");
-    print "Installing for $conf\n";
+    my $majorver = DetermineMajorVersion();
+    print "Installing version $majorver for $conf in $target\n";
 
-    EnsureDirectories($target, 'bin','lib','share','share/timezonesets');
+    EnsureDirectories($target, 'bin','lib','share','share/timezonesets','share/contrib','doc',
+        'doc/contrib', 'symbols', 'share/tsearch_data');
 
     CopySolutionOutput($conf, $target);
-    copy($target . '/lib/libpq.dll', $target . '/bin/libpq.dll');
-    CopySetOfFiles('config files', "*.sample", $target . '/share/');
-    CopySetOfFiles('timezone names', 'src\timezone\tznames\*.txt',$target . '/share/timezonesets/');
+    lcopy($target . '/lib/libpq.dll', $target . '/bin/libpq.dll');
+    my $sample_files = [];
+    File::Find::find(
+        {
+            wanted =>sub {
+                /^.*\.sample\z/s
+                  &&push(@$sample_files, $File::Find::name);
+              }
+        },
+        "src"
+    );
+    CopySetOfFiles('config files', $sample_files, $target . '/share/');
+    CopyFiles(
+        'Import libraries',
+        $target .'/lib/',
+        "$conf\\", "postgres\\postgres.lib","libpq\\libpq.lib", "libecpg\\libecpg.lib",
+        "libpgport\\libpgport.lib"
+    );
+    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', "src\\backend\\catalog\\postgres.*", $target .'/share/');
-    CopySetOfFiles('SQL files', "src\\backend\\catalog\\*.sql", $target . '/share/');
+    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/',
@@ -50,6 +97,23 @@ sub Install
     );
     GenerateConversionScript($target);
     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\\*_sample.*") ],
+        $target . '/share/tsearch_data/'
+    );
+    CopyContribFiles($config,$target);
+    CopyIncludeFiles($target);
+
+    GenerateNLSFiles($target,$config->{nls},$majorver) if ($config->{nls});
+
+    print "Installation complete.\n";
 }
 
 sub EnsureDirectories
@@ -74,8 +138,7 @@ sub CopyFiles
         print ".";
         $f = $basedir . $f;
         die "No file $f\n" if (!-f $f);
-        copy($f, $target . basename($f))
-          || croak "Could not copy $f to $target". basename($f). " to $target". basename($f) . "\n";
+        lcopy($f, $target . basename($f));
     }
     print "\n";
 }
@@ -83,21 +146,17 @@ sub CopyFiles
 sub CopySetOfFiles
 {
     my $what = shift;
-    my $spec = shift;
+    my $flist = shift;
     my $target = shift;
-    my $D;
-
-    print "Copying $what";
-    open($D, "dir /b /s $spec |") || croak "Could not list $spec\n";
-    while (<$D>)
+    print "Copying $what" if $what;
+    foreach (@$flist)
     {
-        chomp;
         next if /regress/; # Skip temporary install in regression subdir
+        next if /ecpg.test/; # Skip temporary install in regression subdir
         my $tgt = $target . basename($_);
         print ".";
-        copy($_, $tgt) || croak "Could not copy $_: $!\n";
+        lcopy($_, $tgt) || croak "Could not copy $_: $!\n";
     }
-    close($D);
     print "\n";
 }
 
@@ -138,7 +197,10 @@ sub CopySolutionOutput
             # Static lib, such as libpgport, only used internally during build, don't install
             next;
         }
-        copy("$conf\\$pf\\$pf.$ext","$target\\$dir\\$pf.$ext") || croak "Could not copy $pf.$ext\n";
+        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";
@@ -166,8 +228,11 @@ sub GenerateConversionScript
         $sql .= "-- $se --> $de\n";
         $sql .=
 "CREATE OR REPLACE FUNCTION $func (INTEGER, INTEGER, CSTRING, INTERNAL, INTEGER) RETURNS VOID AS '\$libdir/$obj', '$func' LANGUAGE C STRICT;\n";
+        $sql .=
+"COMMENT ON FUNCTION $func(INTEGER, INTEGER, CSTRING, INTERNAL, INTEGER) IS 'internal conversion function for $se to $de';\n";
         $sql .= "DROP CONVERSION pg_catalog.$name;\n";
         $sql .= "CREATE DEFAULT CONVERSION pg_catalog.$name FOR '$se' TO '$de' FROM $func;\n";
+        $sql .= "COMMENT ON CONVERSION pg_catalog.$name IS 'conversion for $se to $de';\n";
     }
     open($F,">$target/share/conversion_create.sql")
       || die "Could not write to conversion_create.sql\n";
@@ -186,10 +251,277 @@ sub GenerateTimezoneFiles
     my @tzfiles = split /\s+/,$1;
     unshift @tzfiles,'';
     print "Generating timezone files...";
-    system("$conf\\zic\\zic -d $target/share/timezone " . join(" src/timezone/data/", @tzfiles));
+    system(
+        "$conf\\zic\\zic -d \"$target/share/timezone\" " . join(" src/timezone/data/", @tzfiles));
     print "\n";
 }
 
+sub GenerateTsearchFiles
+{
+    my $target = shift;
+
+    print "Generating tsearch script...";
+    my $F;
+    my $tmpl = read_file('src/backend/snowball/snowball.sql.in');
+    my $mf = read_file('src/backend/snowball/Makefile');
+    $mf =~ s{\\\s*[\r\n]+}{}mg;
+    $mf =~ /^LANGUAGES\s*=\s*(.*)$/m
+      || die "Could not find LANGUAGES line in snowball Makefile\n";
+    my @pieces = split /\s+/,$1;
+    open($F,">$target/share/snowball_create.sql")
+      || die "Could not write snowball_create.sql";
+    print $F read_file('src/backend/snowball/snowball_func.sql.in');
+
+    while ($#pieces > 0)
+    {
+        my $lang = shift @pieces || last;
+        my $asclang = shift @pieces || last;
+        my $txt = $tmpl;
+        my $stop = '';
+
+        if (-s "src/backend/snowball/stopwords/$lang.stop")
+        {
+            $stop = ", StopWords=$lang";
+        }
+
+        $txt =~ s#_LANGNAME_#${lang}#gs;
+        $txt =~ s#_DICTNAME_#${lang}_stem#gs;
+        $txt =~ s#_CFGNAME_#${lang}#gs;
+        $txt =~ s#_ASCDICTNAME_#${asclang}_stem#gs;
+        $txt =~ s#_NONASCDICTNAME_#${lang}_stem#gs;
+        $txt =~ s#_STOPWORDS_#$stop#gs;
+        print $F $txt;
+        print ".";
+    }
+    close($F);
+    print "\n";
+}
+
+sub CopyContribFiles
+{
+    my $config = shift;
+    my $target = shift;
+
+    print "Copying contrib data files...";
+    my $D;
+    opendir($D, 'contrib') || croak "Could not opendir on contrib!\n";
+    while (my $d = readdir($D))
+    {
+        next if ($d =~ /^\./);
+        next unless (-f "contrib/$d/Makefile");
+        next if ($d eq "uuid-ossp"&& !defined($config->{uuid}));
+        next if ($d eq "sslinfo" && !defined($config->{openssl}));
+        next if ($d eq "xml2" && !defined($config->{xml}));
+
+        my $mf = read_file("contrib/$d/Makefile");
+        $mf =~ s{\\s*[\r\n]+}{}mg;
+        my $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);
+
+            # Special case for contrib/spi
+            $flist = "autoinc.sql insert_username.sql moddatetime.sql refint.sql timetravel.sql"
+              if ($d eq 'spi');
+            foreach my $f (split /\s+/,$flist)
+            {
+                lcopy('contrib/' . $d . '/' . $f,$target . '/share/contrib/' . basename($f))
+                  || croak("Could not copy file $f in contrib $d");
+                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('contrib/' . $d . '/' . $f,$target . '/share/tsearch_data/' . basename($f))
+                  || croak("Could not copy file $f in contrib $d");
+                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 timetravel.example"
+              if ($d eq 'spi');
+            foreach my $f (split /\s+/,$flist)
+            {
+                lcopy('contrib/' . $d . '/' . $f, $target . '/doc/contrib/' . $f)
+                  || croak("Could not copy file $f in contrib $d");
+                print '.';
+            }
+        }
+    }
+    closedir($D);
+    print "\n";
+}
+
+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');
+
+    CopyFiles(
+        'Public headers',
+        $target . '/include/',
+        'src/include/', 'postgres_ext.h', 'pg_config.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', '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';
+
+    CopyFiles(
+        'Server headers',
+        $target . '/include/server/',
+        'src/include/', 'pg_config.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";
+
+    while (my $d = readdir($D))
+    {
+        next if ($d =~ /^\./);
+        next if ($d eq 'CVS');
+        next unless (-d 'src/include/' . $d);
+
+        EnsureDirectories($target . '/include/server', $d);
+        system("xcopy /s /i /q /r /y src\\include\\$d\\*.h \"$target\\include\\server\\$d\\\"")
+          && croak("Failed to copy include directory $d\n");
+    }
+    closedir($D);
+
+    my $mf = read_file('src/interfaces/ecpg/include/Makefile');
+    $mf =~ s{\\s*[\r\n]+}{}mg;
+    $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
+    );
+}
+
+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");
+            system(
+"\"$nlspath\\bin\\msgfmt\" -o \"$target\\share\\locale\\$lang\\LC_MESSAGES\\$prgm-$majorver.mo\" $_"
+            )&& croak("Could not run msgfmt on $dir\\$_");
+            print ".";
+        }
+    }
+    print "\n";
+}
+
+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;