mirror of
https://github.com/postgres/postgres.git
synced 2026-04-14 13:37:39 -04:00
Run pgindent, pgperltidy, and reformat-dat-files. This set of diffs is a bit larger than typical. We've updated to pg_bsd_indent 2.1.2, which properly indents variable declarations that have multi-line initialization expressions (the continuation lines are now indented one tab stop). We've also updated to perltidy version 20230309 and changed some of its settings, which reduces its desire to add whitespace to lines to make assignments etc. line up. Going forward, that should make for fewer random-seeming changes to existing code. Discussion: https://postgr.es/m/20230428092545.qfb3y5wcu4cm75ur@alvherre.pgsql
746 lines
17 KiB
Perl
746 lines
17 KiB
Perl
|
|
# Copyright (c) 2021-2023, PostgreSQL Global Development Group
|
|
|
|
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);
|
|
|
|
my $insttype;
|
|
my @client_contribs = ('oid2name', 'pgbench', 'vacuumlo');
|
|
my @client_program_files = (
|
|
'clusterdb', 'createdb', 'createuser', 'dropdb',
|
|
'dropuser', 'ecpg', 'libecpg', 'libecpg_compat',
|
|
'libpgtypes', 'libpq', 'pg_amcheck', 'pg_basebackup',
|
|
'pg_config', 'pg_dump', 'pg_dumpall', 'pg_isready',
|
|
'pg_receivewal', 'pg_recvlogical', 'pg_restore', 'psql',
|
|
'reindexdb', 'vacuumdb', @client_contribs);
|
|
|
|
sub lcopy
|
|
{
|
|
my $src = shift;
|
|
my $target = shift;
|
|
|
|
if (-f $target)
|
|
{
|
|
unlink $target || confess "Could not delete $target\n";
|
|
}
|
|
|
|
(my $retval = copy($src, $target))
|
|
|| confess "Could not copy $src to $target\n";
|
|
|
|
return $retval;
|
|
}
|
|
|
|
sub Install
|
|
{
|
|
$| = 1;
|
|
|
|
my $target = shift;
|
|
$insttype = shift;
|
|
$insttype = "all" unless ($insttype);
|
|
|
|
# if called from vcregress, the config will be passed to us
|
|
# so no need to re-include these
|
|
our $config = shift;
|
|
unless ($config)
|
|
{
|
|
|
|
# suppress warning about harmless redeclaration of $config
|
|
no warnings 'misc';
|
|
do "./config_default.pl";
|
|
do "./config.pl" if (-f "config.pl");
|
|
}
|
|
|
|
# Move to the root path depending on the current location.
|
|
if (-f "../../../configure")
|
|
{
|
|
chdir("../../..");
|
|
}
|
|
elsif (-f "../../../../configure")
|
|
{
|
|
chdir("../../../..");
|
|
}
|
|
|
|
my $conf = "";
|
|
if (-d "debug")
|
|
{
|
|
$conf = "debug";
|
|
}
|
|
if (-d "release")
|
|
{
|
|
$conf = "release";
|
|
}
|
|
die "Could not find debug or release binaries" if ($conf eq "");
|
|
my $majorver = DetermineMajorVersion();
|
|
print "Installing version $majorver for $conf in $target\n";
|
|
|
|
my @client_dirs = ('bin', 'lib', 'share', 'symbols');
|
|
my @all_dirs = (
|
|
@client_dirs, 'doc', 'doc/contrib', 'doc/extension', 'share/contrib',
|
|
'share/extension', 'share/timezonesets', 'share/tsearch_data');
|
|
if ($insttype eq "client")
|
|
{
|
|
EnsureDirectories($target, @client_dirs);
|
|
}
|
|
else
|
|
{
|
|
EnsureDirectories($target, @all_dirs);
|
|
}
|
|
|
|
CopySolutionOutput($conf, $target);
|
|
my $sample_files = [];
|
|
my @top_dir = ("src");
|
|
@top_dir = ("src\\bin", "src\\interfaces") if ($insttype eq "client");
|
|
File::Find::find(
|
|
{
|
|
wanted => sub {
|
|
/^.*\.sample\z/s
|
|
&& push(@$sample_files, $File::Find::name);
|
|
|
|
# Don't find files of in-tree temporary installations.
|
|
$_ eq 'share' and $File::Find::prune = 1;
|
|
}
|
|
},
|
|
@top_dir);
|
|
CopySetOfFiles('config files', $sample_files, $target . '/share/');
|
|
CopyFiles(
|
|
'Import libraries',
|
|
$target . '/lib/',
|
|
"$conf\\", "postgres\\postgres.lib", "libpgcommon\\libpgcommon.lib",
|
|
"libpgport\\libpgport.lib");
|
|
CopyContribFiles($config, $target);
|
|
CopyIncludeFiles($target);
|
|
|
|
if ($insttype ne "client")
|
|
{
|
|
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',
|
|
[ glob("src\\backend\\catalog\\postgres.*") ],
|
|
$target . '/share/');
|
|
CopySetOfFiles(
|
|
'SQL files',
|
|
[ glob("src\\backend\\catalog\\*.sql") ],
|
|
$target . '/share/');
|
|
CopyFiles(
|
|
'Information schema data', $target . '/share/',
|
|
'src/backend/catalog/', 'sql_features.txt');
|
|
CopyFiles(
|
|
'Error code data', $target . '/share/',
|
|
'src/backend/utils/', 'errcodes.txt');
|
|
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\\dicts\\*_sample*") ],
|
|
$target . '/share/tsearch_data/');
|
|
|
|
my $pl_extension_files = [];
|
|
my @pldirs = ('src/pl/plpgsql/src');
|
|
push @pldirs, "src/pl/plperl" if $config->{perl};
|
|
push @pldirs, "src/pl/plpython" if $config->{python};
|
|
push @pldirs, "src/pl/tcl" if $config->{tcl};
|
|
File::Find::find(
|
|
{
|
|
wanted => sub {
|
|
/^(.*--.*\.sql|.*\.control)\z/s
|
|
&& push(@$pl_extension_files, $File::Find::name);
|
|
|
|
# Don't find files of in-tree temporary installations.
|
|
$_ eq 'share' and $File::Find::prune = 1;
|
|
}
|
|
},
|
|
@pldirs);
|
|
CopySetOfFiles('PL Extension files',
|
|
$pl_extension_files, $target . '/share/extension/');
|
|
}
|
|
|
|
GenerateNLSFiles($target, $config->{nls}, $majorver) if ($config->{nls});
|
|
|
|
print "Installation complete.\n";
|
|
return;
|
|
}
|
|
|
|
sub EnsureDirectories
|
|
{
|
|
my $target = shift;
|
|
mkdir $target unless -d ($target);
|
|
while (my $d = shift)
|
|
{
|
|
mkdir $target . '/' . $d unless -d ($target . '/' . $d);
|
|
}
|
|
return;
|
|
}
|
|
|
|
sub CopyFiles
|
|
{
|
|
my $what = shift;
|
|
my $target = shift;
|
|
my $basedir = shift;
|
|
|
|
print "Copying $what";
|
|
while (my $f = shift)
|
|
{
|
|
print ".";
|
|
$f = $basedir . $f;
|
|
die "No file $f\n" if (!-f $f);
|
|
lcopy($f, $target . basename($f)) || croak "Could not copy $f: $!\n";
|
|
}
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
sub CopySetOfFiles
|
|
{
|
|
my $what = shift;
|
|
my $flist = shift;
|
|
my $target = shift;
|
|
print "Copying $what" if $what;
|
|
foreach (@$flist)
|
|
{
|
|
my $tgt = $target . basename($_);
|
|
print ".";
|
|
lcopy($_, $tgt) || croak "Could not copy $_: $!\n";
|
|
}
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
sub CopySolutionOutput
|
|
{
|
|
my $conf = shift;
|
|
my $target = shift;
|
|
my $rem =
|
|
qr{Project\("\{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942\}"\) = "([^"]+)"};
|
|
|
|
my $sln = read_file("pgsql.sln") || croak "Could not open pgsql.sln\n";
|
|
|
|
my $vcproj = 'vcproj';
|
|
if ($sln =~
|
|
/Microsoft Visual Studio Solution File, Format Version (\d+)\.\d+/
|
|
&& $1 >= 11)
|
|
{
|
|
$vcproj = 'vcxproj';
|
|
}
|
|
|
|
print "Copying build output files...";
|
|
while ($sln =~ $rem)
|
|
{
|
|
my $pf = $1;
|
|
|
|
# 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//;
|
|
|
|
next
|
|
if ($insttype eq "client" && !grep { $_ eq $pf }
|
|
@client_program_files);
|
|
|
|
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)
|
|
{
|
|
push(@{ $install_list{'bin'} }, "exe");
|
|
}
|
|
elsif ($1 == 2)
|
|
{
|
|
push(@{ $install_list{'lib'} }, "dll");
|
|
if ($is_sharedlib)
|
|
{
|
|
push(@{ $install_list{'bin'} }, "dll");
|
|
push(@{ $install_list{'lib'} }, "lib");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
# Static libraries, such as libpgport, only used internally
|
|
# during build, don't install.
|
|
next;
|
|
}
|
|
}
|
|
elsif ($vcproj eq 'vcxproj'
|
|
&& $proj =~ qr{<ConfigurationType>(\w+)</ConfigurationType>})
|
|
{
|
|
if ($1 eq 'Application')
|
|
{
|
|
push(@{ $install_list{'bin'} }, "exe");
|
|
}
|
|
elsif ($1 eq 'DynamicLibrary')
|
|
{
|
|
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.
|
|
next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
croak "Could not parse $pf.$vcproj\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 ".";
|
|
}
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
sub GenerateTimezoneFiles
|
|
{
|
|
my $target = shift;
|
|
my $conf = shift;
|
|
my $mf = read_file("src/timezone/Makefile");
|
|
$mf =~ s{\\\r?\n}{}g;
|
|
|
|
$mf =~ /^TZDATAFILES\s*:?=\s*(.*)$/m
|
|
|| die "Could not find TZDATAFILES line in timezone makefile\n";
|
|
my @tzfiles = split /\s+/, $1;
|
|
|
|
print "Generating timezone files...";
|
|
|
|
my @args = ("$conf/zic/zic", '-d', "$target/share/timezone");
|
|
foreach (@tzfiles)
|
|
{
|
|
my $tzfile = $_;
|
|
$tzfile =~ s|\$\(srcdir\)|src/timezone|;
|
|
push(@args, $tzfile);
|
|
}
|
|
|
|
system(@args);
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
sub GenerateTsearchFiles
|
|
{
|
|
my $target = shift;
|
|
|
|
print "Generating tsearch script...";
|
|
system(
|
|
'perl', 'src/backend/snowball/snowball_create.pl',
|
|
'--input', 'src/backend/snowball/',
|
|
'--outdir', "$target/share/");
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
sub CopyContribFiles
|
|
{
|
|
my $config = shift;
|
|
my $target = shift;
|
|
|
|
print "Copying contrib data files...";
|
|
foreach my $subdir ('contrib', 'src/test/modules')
|
|
{
|
|
my $D;
|
|
opendir($D, $subdir) || croak "Could not opendir on $subdir!\n";
|
|
while (my $d = readdir($D))
|
|
{
|
|
# These configuration-based exclusions must match vcregress.pl
|
|
next if ($d eq "uuid-ossp" && !defined($config->{uuid}));
|
|
next if ($d eq "sslinfo" && !defined($config->{openssl}));
|
|
next if ($d eq "pgcrypto" && !defined($config->{openssl}));
|
|
next if ($d eq "xml2" && !defined($config->{xml}));
|
|
next if ($d =~ /_plperl$/ && !defined($config->{perl}));
|
|
next if ($d =~ /_plpython$/ && !defined($config->{python}));
|
|
next if ($d eq "sepgsql");
|
|
|
|
CopySubdirFiles($subdir, $d, $config, $target);
|
|
}
|
|
}
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
sub CopySubdirFiles
|
|
{
|
|
my $subdir = shift;
|
|
my $module = shift;
|
|
my $config = shift;
|
|
my $target = shift;
|
|
|
|
return if ($module =~ /^\./);
|
|
return unless (-f "$subdir/$module/Makefile");
|
|
return
|
|
if ($insttype eq "client" && !grep { $_ eq $module } @client_contribs);
|
|
|
|
my $mf = read_file("$subdir/$module/Makefile");
|
|
$mf =~ s{\\\r?\n}{}g;
|
|
|
|
# Note: we currently don't support setting MODULEDIR in the makefile
|
|
my $moduledir = 'contrib';
|
|
|
|
my $flist = '';
|
|
if ($mf =~ /^EXTENSION\s*=\s*(.*)$/m) { $flist .= $1 }
|
|
if ($flist ne '')
|
|
{
|
|
$moduledir = 'extension';
|
|
$flist = ParseAndCleanRule($flist, $mf);
|
|
|
|
foreach my $f (split /\s+/, $flist)
|
|
{
|
|
lcopy("$subdir/$module/$f.control",
|
|
"$target/share/extension/$f.control")
|
|
|| croak("Could not copy file $f.control in contrib $module");
|
|
print '.';
|
|
}
|
|
}
|
|
|
|
$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);
|
|
|
|
foreach my $f (split /\s+/, $flist)
|
|
{
|
|
lcopy("$subdir/$module/$f",
|
|
"$target/share/$moduledir/" . basename($f))
|
|
|| croak("Could not copy file $f in contrib $module");
|
|
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("$subdir/$module/$f",
|
|
"$target/share/tsearch_data/" . basename($f))
|
|
|| croak("Could not copy file $f in $subdir $module");
|
|
print '.';
|
|
}
|
|
}
|
|
|
|
{
|
|
$flist = '';
|
|
if ($mf =~ /^HEADERS\s*=\s*(.*)$/m) { $flist .= $1 }
|
|
my @modlist = ();
|
|
my %fmodlist = ();
|
|
while ($mf =~ /^HEADERS_([^\s=]+)\s*=\s*(.*)$/mg)
|
|
{
|
|
$fmodlist{$1} .= $2;
|
|
}
|
|
|
|
if ($mf =~ /^MODULE_big\s*=\s*(.*)$/m)
|
|
{
|
|
push @modlist, $1;
|
|
if ($flist ne '')
|
|
{
|
|
$fmodlist{$1} = $flist;
|
|
$flist = '';
|
|
}
|
|
}
|
|
elsif ($mf =~ /^MODULES\s*=\s*(.*)$/m)
|
|
{
|
|
push @modlist, split /\s+/, $1;
|
|
}
|
|
|
|
croak "HEADERS requires MODULE_big in $subdir $module"
|
|
if $flist ne '';
|
|
|
|
foreach my $mod (keys %fmodlist)
|
|
{
|
|
croak "HEADERS_$mod for unknown module in $subdir $module"
|
|
unless grep { $_ eq $mod } @modlist;
|
|
$flist = ParseAndCleanRule($fmodlist{$mod}, $mf);
|
|
EnsureDirectories($target, "include", "include/server",
|
|
"include/server/$moduledir",
|
|
"include/server/$moduledir/$mod");
|
|
foreach my $f (split /\s+/, $flist)
|
|
{
|
|
lcopy("$subdir/$module/$f",
|
|
"$target/include/server/$moduledir/$mod/" . basename($f))
|
|
|| croak("Could not copy file $f in $subdir $module");
|
|
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"
|
|
if ($module eq 'spi');
|
|
foreach my $f (split /\s+/, $flist)
|
|
{
|
|
lcopy("$subdir/$module/$f", "$target/doc/$moduledir/$f")
|
|
|| croak("Could not copy file $f in contrib $module");
|
|
print '.';
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
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', 'include/server/parser');
|
|
|
|
CopyFiles(
|
|
'Public headers', $target . '/include/',
|
|
'src/include/', 'postgres_ext.h',
|
|
'pg_config.h', 'pg_config_ext.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', 'fe-auth-sasl.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_ext.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";
|
|
|
|
CopyFiles(
|
|
'PL/pgSQL header',
|
|
$target . '/include/server/',
|
|
'src/pl/plpgsql/src/', 'plpgsql.h');
|
|
|
|
# some xcopy progs don't like mixed slash style paths
|
|
(my $ctarget = $target) =~ s!/!\\!g;
|
|
while (my $d = readdir($D))
|
|
{
|
|
next if ($d =~ /^\./);
|
|
next if ($d eq '.git');
|
|
next if ($d eq 'CVS');
|
|
next unless (-d "src/include/$d");
|
|
|
|
EnsureDirectories("$target/include/server/$d");
|
|
my @args = (
|
|
'xcopy', '/s', '/i', '/q', '/r', '/y', "src\\include\\$d\\*.h",
|
|
"$ctarget\\include\\server\\$d\\");
|
|
system(@args) && croak("Failed to copy include directory $d\n");
|
|
}
|
|
closedir($D);
|
|
|
|
my $mf = read_file('src/interfaces/ecpg/include/Makefile');
|
|
$mf =~ s{\\\r?\n}{}g;
|
|
$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);
|
|
return;
|
|
}
|
|
|
|
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");
|
|
my @args = (
|
|
"$nlspath\\bin\\msgfmt",
|
|
'-o',
|
|
"$target\\share\\locale\\$lang\\LC_MESSAGES\\$prgm-$majorver.mo",
|
|
$_);
|
|
system(@args) && croak("Could not run msgfmt on $dir\\$_");
|
|
print ".";
|
|
}
|
|
}
|
|
print "\n";
|
|
return;
|
|
}
|
|
|
|
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;
|
|
my $F;
|
|
local $/ = undef;
|
|
open($F, '<', $filename) || die "Could not open file $filename\n";
|
|
my $txt = <$F>;
|
|
close($F);
|
|
|
|
return $txt;
|
|
}
|
|
|
|
1;
|