4 # Package that provides 'make install' functionality for msvc builds
16 our (@ISA,@EXPORT_OK);
18 @EXPORT_OK = qw(Install);
27 unlink $target || confess
"Could not delete $target\n";
31 || confess
"Could not copy $src to $target\n";
43 chdir("../../..") if (-f
"../../../configure");
44 chdir("../../../..") if (-f
"../../../../configure");
54 die "Could not find debug or release binaries" if ($conf eq "");
55 my $majorver = DetermineMajorVersion
();
56 print "Installing version $majorver for $conf in $target\n";
58 EnsureDirectories
($target, 'bin','lib','share','share/timezonesets','share/contrib','doc',
59 'doc/contrib', 'symbols', 'share/tsearch_data');
61 CopySolutionOutput
($conf, $target);
62 lcopy
($target . '/lib/libpq.dll', $target . '/bin/libpq.dll');
63 my $sample_files = [];
64 File
::Find
::find
({wanted
=>
65 sub { /^.*\.sample\z/s &&
66 push(@
$sample_files, $File::Find
::name
);
70 CopySetOfFiles
('config files', $sample_files , $target . '/share/');
74 "$conf\\", "postgres\\postgres.lib","libpq\\libpq.lib", "libecpg\\libecpg.lib", "libpgport\\libpgport.lib"
76 CopySetOfFiles
('timezone names',
77 [ glob('src\timezone\tznames\*.txt') ] ,
78 $target . '/share/timezonesets/');
81 $target . '/share/timezonesets/',
82 'src/timezone/tznames/', 'Default','Australia','India'
84 CopySetOfFiles
('BKI files', [ glob("src\\backend\\catalog\\postgres.*") ],
86 CopySetOfFiles
('SQL files', [ glob("src\\backend\\catalog\\*.sql") ],
89 'Information schema data',
91 'src/backend/catalog/', 'sql_features.txt'
93 GenerateConversionScript
($target);
94 GenerateTimezoneFiles
($target,$conf);
95 GenerateTsearchFiles
($target);
96 CopySetOfFiles
('Stopword files',
97 [ glob ("src\\backend\\snowball\\stopwords\\*.stop") ],
98 $target . '/share/tsearch_data/');
99 CopySetOfFiles
('Dictionaries sample files',
100 [ glob ("src\\backend\\tsearch\\*_sample.*" ) ],
101 $target . '/share/tsearch_data/');
102 CopyContribFiles
($config,$target);
103 CopyIncludeFiles
($target);
105 GenerateNLSFiles
($target,$config->{nls
},$majorver) if ($config->{nls
});
107 print "Installation complete.\n";
110 sub EnsureDirectories
113 mkdir $target unless -d
($target);
114 while (my $d = shift)
116 mkdir $target . '/' . $d unless -d
($target . '/' . $d);
126 print "Copying $what";
127 while (my $f = shift)
131 die "No file $f\n" if (!-f
$f);
132 lcopy
($f, $target . basename
($f));
142 print "Copying $what" if $what;
145 next if /regress/; # Skip temporary install in regression subdir
146 next if /ecpg.test/; # Skip temporary install in regression subdir
147 my $tgt = $target . basename
($_);
149 lcopy
($_, $tgt) || croak
"Could not copy $_: $!\n";
154 sub CopySolutionOutput
158 my $rem = qr{Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}"\) = "([^"]+)"};
160 my $sln = read_file
("pgsql.sln") || croak
"Could not open pgsql.sln\n";
161 print "Copying build output files...";
170 my $proj = read_file
("$pf.vcproj") || croak
"Could not open $pf.vcproj\n";
171 if ($proj !~ qr{ConfigurationType="([^"]+)"})
173 croak
"Could not parse $pf.vcproj\n";
188 # Static lib, such as libpgport, only used internally during build, don't install
191 lcopy
("$conf\\$pf\\$pf.$ext","$target\\$dir\\$pf.$ext") || croak
"Could not copy $pf.$ext\n";
192 lcopy
("$conf\\$pf\\$pf.pdb","$target\\symbols\\$pf.pdb") || croak
"Could not copy $pf.pdb\n";
198 sub GenerateConversionScript
204 print "Generating conversion proc script...";
205 my $mf = read_file
('src/backend/utils/mb/conversion_procs/Makefile');
206 $mf =~ s{\\\s*[\r\n]+}{}mg;
207 $mf =~ /^CONVERSIONS\s*=\s*(.*)$/m
208 || die "Could not find CONVERSIONS line in conversions Makefile\n";
209 my @pieces = split /\s+/,$1;
212 my $name = shift @pieces;
213 my $se = shift @pieces;
214 my $de = shift @pieces;
215 my $func = shift @pieces;
216 my $obj = shift @pieces;
217 $sql .= "-- $se --> $de\n";
219 "CREATE OR REPLACE FUNCTION $func (INTEGER, INTEGER, CSTRING, INTERNAL, INTEGER) RETURNS VOID AS '\$libdir/$obj', '$func' LANGUAGE C STRICT;\n";
221 "COMMENT ON FUNCTION $func(INTEGER, INTEGER, CSTRING, INTERNAL, INTEGER) IS 'internal conversion function for $se to $de';\n";
222 $sql .= "DROP CONVERSION pg_catalog.$name;\n";
223 $sql .= "CREATE DEFAULT CONVERSION pg_catalog.$name FOR '$se' TO '$de' FROM $func;\n";
224 $sql .= "COMMENT ON CONVERSION pg_catalog.$name IS 'conversion for $se to $de';\n";
226 open($F,">$target/share/conversion_create.sql")
227 || die "Could not write to conversion_create.sql\n";
233 sub GenerateTimezoneFiles
237 my $mf = read_file
("src/timezone/Makefile");
238 $mf =~ s{\\\s*[\r\n]+}{}mg;
239 $mf =~ /^TZDATA\s*:?=\s*(.*)$/m || die "Could not find TZDATA row in timezone makefile\n";
240 my @tzfiles = split /\s+/,$1;
242 print "Generating timezone files...";
243 system("$conf\\zic\\zic -d \"$target/share/timezone\" " . join(" src/timezone/data/", @tzfiles));
247 sub GenerateTsearchFiles
251 print "Generating tsearch script...";
253 my $tmpl = read_file
('src/backend/snowball/snowball.sql.in');
254 my $mf = read_file
('src/backend/snowball/Makefile');
255 $mf =~ s{\\\s*[\r\n]+}{}mg;
256 $mf =~ /^LANGUAGES\s*=\s*(.*)$/m
257 || die "Could not find LANGUAGES line in snowball Makefile\n";
258 my @pieces = split /\s+/,$1;
259 open($F,">$target/share/snowball_create.sql")
260 || die "Could not write snowball_create.sql";
261 print $F read_file
('src/backend/snowball/snowball_func.sql.in');
264 my $lang = shift @pieces || last;
265 my $asclang = shift @pieces || last;
269 if (-s
"src/backend/snowball/stopwords/$lang.stop") {
270 $stop = ", StopWords=$lang";
273 $txt =~ s
#_LANGNAME_#${lang}#gs;
274 $txt =~ s
#_DICTNAME_#${lang}_stem#gs;
275 $txt =~ s
#_CFGNAME_#${lang}#gs;
276 $txt =~ s
#_ASCDICTNAME_#${asclang}_stem#gs;
277 $txt =~ s
#_NONASCDICTNAME_#${lang}_stem#gs;
278 $txt =~ s
#_STOPWORDS_#$stop#gs;
291 print "Copying contrib data files...";
293 opendir($D, 'contrib') || croak
"Could not opendir on contrib!\n";
294 while (my $d = readdir($D))
296 next if ($d =~ /^\./);
297 next unless (-f
"contrib/$d/Makefile");
298 next if ($d eq "uuid-ossp"&& !defined($config->{uuid
}));
299 next if ($d eq "sslinfo" && !defined($config->{openssl
}));
300 next if ($d eq "xml2" && !defined($config->{xml
}));
302 my $mf = read_file
("contrib/$d/Makefile");
303 $mf =~ s{\\s*[\r\n]+}{}mg;
305 if ($mf =~ /^DATA_built\s*=\s*(.*)$/m) {$flist .= $1}
306 if ($mf =~ /^DATA\s*=\s*(.*)$/m) {$flist .= " $1"}
307 $flist =~ s/^\s*//; # Remove leading spaces if we had only DATA_built
311 $flist = ParseAndCleanRule
($flist, $mf);
313 # Special case for contrib/spi
314 $flist = "autoinc.sql insert_username.sql moddatetime.sql refint.sql timetravel.sql"
316 foreach my $f (split /\s+/,$flist)
318 lcopy
('contrib/' . $d . '/' . $f,$target . '/share/contrib/' . basename
($f))
319 || croak
("Could not copy file $f in contrib $d");
325 if ($mf =~ /^DATA_TSEARCH\s*=\s*(.*)$/m) {$flist .= $1}
328 $flist = ParseAndCleanRule
($flist, $mf);
330 foreach my $f (split /\s+/,$flist)
332 lcopy
('contrib/' . $d . '/' . $f,$target . '/share/tsearch_data/' . basename
($f))
333 || croak
("Could not copy file $f in contrib $d");
339 if ($mf =~ /^DOCS\s*=\s*(.*)$/mg) {$flist .= $1}
342 $flist = ParseAndCleanRule
($flist, $mf);
344 # Special case for contrib/spi
346 "autoinc.example insert_username.example moddatetime.example refint.example timetravel.example"
348 foreach my $f (split /\s+/,$flist)
350 lcopy
('contrib/' . $d . '/' . $f, $target . '/doc/contrib/' . $f)
351 || croak
("Could not copy file $f in contrib $d");
360 sub ParseAndCleanRule
365 # Strip out $(addsuffix) rules
366 if (index($flist, '$(addsuffix ') >= 0)
370 for ($i = index($flist, '$(addsuffix ') + 12; $i < length($flist); $i++)
372 $pcount++ if (substr($flist, $i, 1) eq '(');
373 $pcount-- if (substr($flist, $i, 1) eq ')');
374 last if ($pcount < 0);
376 $flist = substr($flist, 0, index($flist, '$(addsuffix ')) . substr($flist, $i+1);
385 EnsureDirectories
($target, 'include', 'include/libpq',
386 'include/internal', 'include/internal/libpq',
391 $target . '/include/',
392 'src/include/', 'postgres_ext.h', 'pg_config.h', 'pg_config_os.h', 'pg_config_manual.h'
394 lcopy
('src/include/libpq/libpq-fs.h', $target . '/include/libpq/')
395 || croak
'Could not copy libpq-fs.h';
397 CopyFiles
('Libpq headers',
398 $target . '/include/', 'src/interfaces/libpq/',
399 'libpq-fe.h', 'libpq-events.h');
401 'Libpq internal headers',
402 $target .'/include/internal/',
403 'src/interfaces/libpq/', 'libpq-int.h', 'pqexpbuffer.h'
408 $target . '/include/internal/',
409 'src/include/', 'c.h', 'port.h', 'postgres_fe.h'
411 lcopy
('src/include/libpq/pqcomm.h', $target . '/include/internal/libpq/')
412 || croak
'Could not copy pqcomm.h';
416 $target . '/include/server/',
417 'src/include/', 'pg_config.h', 'pg_config_os.h'
420 [ glob( "src\\include\\*.h" ) ],
421 $target . '/include/server/');
423 opendir($D, 'src/include') || croak
"Could not opendir on src/include!\n";
425 while (my $d = readdir($D))
427 next if ($d =~ /^\./);
428 next if ($d eq 'CVS');
429 next unless (-d
'src/include/' . $d);
431 EnsureDirectories
($target . '/include/server', $d);
433 "xcopy /s /i /q /r /y src\\include\\$d\\*.h \"$target\\include\\server\\$d\\\"")
434 && croak
("Failed to copy include directory $d\n");
438 my $mf = read_file
('src/interfaces/ecpg/include/Makefile');
439 $mf =~ s{\\s*[\r\n]+}{}mg;
440 $mf =~ /^ecpg_headers\s*=\s*(.*)$/m || croak
"Could not find ecpg_headers line\n";
443 $target . '/include/',
444 'src/interfaces/ecpg/include/',
445 'ecpg_config.h', split /\s+/,$1
447 $mf =~ /^informix_headers\s*=\s*(.*)$/m || croak
"Could not find informix_headers line\n";
448 EnsureDirectories
($target . '/include', 'informix', 'informix/esql');
450 'ECPG informix headers',
451 $target .'/include/informix/esql/',
452 'src/interfaces/ecpg/include/',
461 my $majorver = shift;
463 print "Installing NLS files...";
464 EnsureDirectories
($target, "share/locale");
466 File
::Find
::find
({wanted
=>
467 sub { /^nls\.mk\z/s &&
468 !push(@flist, $File::Find
::name
);
473 my $prgm = DetermineCatalogName
($_);
476 next unless ($dir =~ /([^\/]+)\
/po$/);
477 foreach (glob("$dir/*.po"))
480 next unless /([^\/]+)\
.po
/;
483 EnsureDirectories
($target, "share/locale/$lang", "share/locale/$lang/LC_MESSAGES");
485 "\"$nlspath\\bin\\msgfmt\" -o \"$target\\share\\locale\\$lang\\LC_MESSAGES\\$prgm-$majorver.mo\" $_"
487 && croak
("Could not run msgfmt on $dir\\$_");
494 sub DetermineMajorVersion
496 my $f = read_file
('src/include/pg_config.h') || croak
'Could not open pg_config.h';
497 $f =~ /^#define\s+PG_MAJORVERSION\s+"([^"]+)"/m || croak
'Could not determine major version';
501 sub DetermineCatalogName
503 my $filename = shift;
505 my $f = read_file
($filename) || croak
"Could not open $filename";
506 $f =~ /CATALOG_NAME\s*\:?=\s*(\S+)/m || croak
"Could not determine catalog name in $filename";
512 my $filename = shift;
517 open($F, $filename) || die "Could not open file $filename\n";