4 # Package that encapsulates a Visual C++ solution file generation
6 # $PostgreSQL: pgsql/src/tools/msvc/Solution.pm,v 1.39 2008/04/21 10:01:32 mha Exp $
25 # integer_datetimes is now the default
26 $options->{integer_datetimes} = 1
27 unless exists $options->{integer_datetimes};
28 $options->{float4byval} = 1
29 unless exists $options->{float4byval};
32 if (!($options->{xslt} && $options->{iconv}))
34 die "XML requires both XSLT and ICONV\n";
40 # Return 1 if $oldfile is newer than $newfile, or if $newfile doesn't exist.
41 # Special case - if config.pl has changed, always return 1
44 my ($newfile, $oldfile) = @_;
45 if ($oldfile ne 'src\tools\msvc\config.pl')
47 return 1 if IsNewer($newfile, 'src\tools\msvc\config.pl');
49 return 1 if (!(-e $newfile));
50 my @nstat = stat($newfile);
51 my @ostat = stat($oldfile);
52 return 1 if ($nstat[9] < $ostat[9]);
56 # Copy a file, *not* preserving date. Only works for text files.
59 my ($src, $dest) = @_;
60 open(I,$src) || croak "Could not open $src";
61 open(O,">$dest") || croak "Could not open $dest";
74 # Parse configure.in to get version numbers
75 open(C,"configure.in") || confess("Could not open configure.in for reading\n");
78 if (/^AC_INIT\(\[PostgreSQL\], \[([^\]]+)\]/)
81 if ($self->{strver} !~ /^(\d+)\.(\d+)(?:\.(\d+))?/)
83 confess "Bad format of version: $self->{strver}\n";
85 $self->{numver} = sprintf("%d%02d%02d", $1, $2, $3?$3:0);
86 $self->{majorver} = sprintf("%d.%d", $1, $2);
90 confess "Unable to parse configure.in for all variables!"
91 if ($self->{strver} eq '' || $self->{numver} eq '');
93 if (IsNewer("src\\include\\pg_config_os.h","src\\include\\port\\win32.h"))
95 print "Copying pg_config_os.h...\n";
96 copyFile("src\\include\\port\\win32.h","src\\include\\pg_config_os.h");
99 if (IsNewer("src\\include\\pg_config.h","src\\include\\pg_config.h.win32"))
101 print "Generating pg_config.h...\n";
102 open(I,"src\\include\\pg_config.h.win32") || confess "Could not open pg_config.h.win32\n";
103 open(O,">src\\include\\pg_config.h") || confess "Could not write to pg_config.h\n";
106 s{PG_VERSION "[^"]+"}{PG_VERSION "$self->{strver}"};
107 s{PG_VERSION_NUM \d+}{PG_VERSION_NUM $self->{numver}};
108 s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY(z)\n#define PG_VERSION_STR "PostgreSQL $self->{strver}, compiled by Visual C++ build " __STRINGIFY2(_MSC_VER)};
111 print O "#define LOCALEDIR \"/share/locale\"\n" if ($self->{options}->{nls});
112 print O "/* defines added by config steps */\n";
113 print O "#ifndef IGNORE_CONFIGURED_SETTINGS\n";
114 print O "#define USE_ASSERT_CHECKING 1\n" if ($self->{options}->{asserts});
115 print O "#define USE_INTEGER_DATETIMES 1\n" if ($self->{options}->{integer_datetimes});
116 print O "#define USE_LDAP 1\n" if ($self->{options}->{ldap});
117 print O "#define HAVE_LIBZ 1\n" if ($self->{options}->{zlib});
118 print O "#define USE_SSL 1\n" if ($self->{options}->{openssl});
119 print O "#define ENABLE_NLS 1\n" if ($self->{options}->{nls});
121 unless ($self->{options}->{float4byval})
123 # float4byval is the default, so undefine
124 print O "#undef USE_FLOAT4_BYVAL\n";
125 print O "#undef FLOAT4PASSBYVAL\n";
126 print O "#define FLOAT4PASSBYVAL false\n";
128 if ($self->{options}->{float8byval})
130 print O "#define USE_FLOAT8_BYVAL\n";
131 print O "#undef FLOAT8PASSBYVAL\n";
132 print O "#define FLOAT8PASSBYVAL true\n";
135 if ($self->{options}->{uuid})
137 print O "#define HAVE_UUID_H\n";
139 if ($self->{options}->{xml})
141 print O "#define HAVE_LIBXML2\n";
142 print O "#define USE_LIBXML\n";
144 if ($self->{options}->{krb5})
146 print O "#define KRB5 1\n";
147 print O "#define HAVE_KRB5_ERROR_TEXT_DATA 1\n";
148 print O "#define HAVE_KRB5_TICKET_ENC_PART2 1\n";
149 print O "#define HAVE_KRB5_FREE_UNPARSED_NAME 1\n";
150 print O "#define ENABLE_GSS 1\n";
152 if (my $port = $self->{options}->{"--with-pgport"})
154 print O "#undef DEF_PGPORT\n";
155 print O "#undef DEF_PGPORT_STR\n";
156 print O "#define DEF_PGPORT $port\n";
157 print O "#define DEF_PGPORT_STR \"$port\"\n";
159 print O "#define VAL_CONFIGURE \"" . $self->GetFakeConfigure() . "\"\n";
160 print O "#endif /* IGNORE_CONFIGURED_SETTINGS */\n";
165 $self->GenerateDefFile("src\\interfaces\\libpq\\libpqdll.def","src\\interfaces\\libpq\\exports.txt","LIBPQ");
166 $self->GenerateDefFile("src\\interfaces\\ecpg\\ecpglib\\ecpglib.def","src\\interfaces\\ecpg\\ecpglib\\exports.txt","LIBECPG");
167 $self->GenerateDefFile("src\\interfaces\\ecpg\\compatlib\\compatlib.def","src\\interfaces\\ecpg\\compatlib\\exports.txt","LIBECPG_COMPAT");
168 $self->GenerateDefFile("src\\interfaces\\ecpg\\pgtypeslib\\pgtypeslib.def","src\\interfaces\\ecpg\\pgtypeslib\\exports.txt","LIBPGTYPES");
170 if (IsNewer("src\\backend\\utils\\fmgrtab.c","src\\include\\catalog\\pg_proc.h"))
172 print "Generating fmgrtab.c and fmgroids.h...\n";
173 open(I,"src\\include\\catalog\\pg_proc.h") || confess "Could not open pg_proc.h";
178 next unless (/^DATA/);
179 s/^.*OID[^=]*=[^0-9]*//;
183 next if ($p[4] ne "12");
196 open(H,'>', 'src\include\utils\fmgroids.h')
197 ||confess "Could not open fmgroids.h";
199 "/* fmgroids.h generated for Visual C++ */\n#ifndef FMGROIDS_H\n#define FMGROIDS_H\n\n";
200 open(T,">src\\backend\\utils\\fmgrtab.c") || confess "Could not open fmgrtab.c";
202 "/* fmgrtab.c generated for Visual C++ */\n#include \"postgres.h\"\n#include \"utils/fmgrtab.h\"\n\n";
203 foreach my $s (sort {$a->{oid} <=> $b->{oid}} @fmgr)
205 next if $seenit{$s->{prosrc}};
206 $seenit{$s->{prosrc}} = 1;
207 print H "#define F_" . uc $s->{prosrc} . " $s->{oid}\n";
208 print T "extern Datum $s->{prosrc} (PG_FUNCTION_ARGS);\n";
210 print H "\n#endif\n /* FMGROIDS_H */\n";
212 print T "const FmgrBuiltin fmgr_builtins[] = {\n";
215 $bmap{'f'} = 'false';
216 foreach my $s (sort {$a->{oid} <=> $b->{oid}} @fmgr)
219 " { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n";
223 " { 0, NULL, 0, false, false, NULL }\n};\n\nconst int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;\n";
227 if (IsNewer('src\include\utils\probes.h','src\backend\utils\pg_trace.d'))
229 print "Generating probes.h...\n";
230 system('psed -f src\backend\utils\Gen_dummy_probes.sed src\backend\utils\probes.d > src\include\utils\probes.h');
233 if (IsNewer('src\interfaces\libpq\libpq.rc','src\interfaces\libpq\libpq.rc.in'))
235 print "Generating libpq.rc...\n";
236 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
237 my $d = ($year - 100) . "$yday";
238 open(I,'<', 'src\interfaces\libpq\libpq.rc.in') || confess "Could not open libpq.rc.in";
239 open(O,'>', 'src\interfaces\libpq\libpq.rc') || confess "Could not open libpq.rc";
242 s/(VERSION.*),0/$1,$d/;
249 if (IsNewer('src\bin\psql\sql_help.h','src\bin\psql\create_help.pl'))
251 print "Generating sql_help.h...\n";
252 chdir('src\bin\psql');
253 system("perl create_help.pl ../../../doc/src/sgml/ref sql_help.h");
259 'src\interfaces\ecpg\include\ecpg_config.h',
260 'src\interfaces\ecpg\include\ecpg_config.h.in'
264 print "Generating ecpg_config.h...\n";
265 open(O,'>','src\interfaces\ecpg\include\ecpg_config.h')
266 || confess "Could not open ecpg_config.h";
268 #if (_MSC_VER > 1200)
269 #define HAVE_LONG_LONG_INT_64
270 #define ENABLE_THREAD_SAFETY 1
272 print O "#define USE_INTEGER_DATETIMES 1\n" if ($self->{options}->{integer_datetimes});
277 unless (-f "src\\port\\pg_config_paths.h")
279 print "Generating pg_config_paths.h...\n";
280 open(O,'>', 'src\port\pg_config_paths.h') || confess "Could not open pg_config_paths.h";
282 #define PGBINDIR "/bin"
283 #define PGSHAREDIR "/share"
284 #define SYSCONFDIR "/etc"
285 #define INCLUDEDIR "/include"
286 #define PKGINCLUDEDIR "/include"
287 #define INCLUDEDIRSERVER "/include/server"
288 #define LIBDIR "/lib"
289 #define PKGLIBDIR "/lib"
290 #define LOCALEDIR "/share/locale"
291 #define DOCDIR "/doc"
292 #define HTMLDIR "/doc"
293 #define MANDIR "/man"
298 my $mf = Project::read_file('src\backend\catalog\Makefile');
299 $mf =~ s{\\s*[\r\n]+}{}mg;
300 $mf =~ /^POSTGRES_BKI_SRCS\s*:?=[^,]+,(.*)\)$/gm
301 || croak "Could not find POSTGRES_BKI_SRCS in Makefile\n";
302 my @allbki = split /\s+/, $1;
303 foreach my $bki (@allbki)
306 if (IsNewer('src/backend/catalog/postgres.bki', "src/include/catalog/$bki"))
308 print "Generating postgres.bki...\n";
311 "src/backend/catalog/postgres",
312 split(/ /,join(' src/include/catalog/',@allbki))
318 open(O, ">doc/src/sgml/version.sgml") || croak "Could not write to version.sgml\n";
320 <!entity version "$self->{strver}">
321 <!entity majorversion "$self->{majorver}">
328 my ($self, $deffile, $txtfile, $libname) = @_;
330 if (IsNewer($deffile,$txtfile))
332 print "Generating $deffile...\n";
333 open(I,$txtfile) || confess("Could not open $txtfile\n");
334 open(O,">$deffile") || confess("Could not open $deffile\n");
335 print O "LIBRARY $libname\nEXPORTS\n";
341 print O " $f @ $o\n";
350 my ($self, $name, $type, $folder, $initialdir) = @_;
352 my $proj = new Project($name, $type, $self);
353 push @{$self->{projects}->{$folder}}, $proj;
354 $proj->AddDir($initialdir) if ($initialdir);
355 if ($self->{options}->{zlib})
357 $proj->AddIncludeDir($self->{options}->{zlib} . '\include');
358 $proj->AddLibrary($self->{options}->{zlib} . '\lib\zdll.lib');
360 if ($self->{options}->{openssl})
362 $proj->AddIncludeDir($self->{options}->{openssl} . '\include');
363 $proj->AddLibrary($self->{options}->{openssl} . '\lib\VC\ssleay32.lib', 1);
364 $proj->AddLibrary($self->{options}->{openssl} . '\lib\VC\libeay32.lib', 1);
366 if ($self->{options}->{nls})
368 $proj->AddIncludeDir($self->{options}->{nls} . '\include');
369 $proj->AddLibrary($self->{options}->{nls} . '\lib\libintl.lib');
371 if ($self->{options}->{krb5})
373 $proj->AddIncludeDir($self->{options}->{krb5} . '\inc\krb5');
374 $proj->AddLibrary($self->{options}->{krb5} . '\lib\i386\krb5_32.lib');
375 $proj->AddLibrary($self->{options}->{krb5} . '\lib\i386\comerr32.lib');
376 $proj->AddLibrary($self->{options}->{krb5} . '\lib\i386\gssapi32.lib');
378 if ($self->{options}->{xml})
380 $proj->AddIncludeDir($self->{options}->{xml} . '\include');
381 $proj->AddIncludeDir($self->{options}->{iconv} . '\include');
382 $proj->AddLibrary($self->{options}->{xml} . '\lib\libxml2.lib');
392 $self->GenerateFiles();
393 foreach my $fld (keys %{$self->{projects}})
395 foreach my $proj (@{$self->{projects}->{$fld}})
401 open(SLN,">pgsql.sln") || croak "Could not write to pgsql.sln\n";
403 Microsoft Visual Studio Solution File, Format Version 9.00
407 foreach my $fld (keys %{$self->{projects}})
409 foreach my $proj (@{$self->{projects}->{$fld}})
412 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "$proj->{name}", "$proj->{name}.vcproj", "$proj->{guid}"
418 $flduid{$fld} = Win32::GuidGen();
420 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "$fld", "$fld", "$flduid{$fld}"
428 GlobalSection(SolutionConfigurationPlatforms) = preSolution
429 Debug|Win32 = Debug|Win32
430 Release|Win32 = Release|Win32
432 GlobalSection(ProjectConfigurationPlatforms) = postSolution
435 foreach my $fld (keys %{$self->{projects}})
437 foreach my $proj (@{$self->{projects}->{$fld}})
440 $proj->{guid}.Debug|Win32.ActiveCfg = Debug|Win32
441 $proj->{guid}.Debug|Win32.Build.0 = Debug|Win32
442 $proj->{guid}.Release|Win32.ActiveCfg = Release|Win32
443 $proj->{guid}.Release|Win32.Build.0 = Release|Win32
450 GlobalSection(SolutionProperties) = preSolution
451 HideSolutionNode = FALSE
453 GlobalSection(NestedProjects) = preSolution
456 foreach my $fld (keys %{$self->{projects}})
458 next if ($fld eq "");
459 foreach my $proj (@{$self->{projects}->{$fld}})
461 print SLN "\t\t$proj->{guid} = $flduid{$fld}\n";
476 my $cfg = '--enable-thread-safety';
477 $cfg .= ' --enable-cassert' if ($self->{options}->{asserts});
478 $cfg .= ' --enable-integer-datetimes' if ($self->{options}->{integer_datetimes});
479 $cfg .= ' --enable-nls' if ($self->{options}->{nls});
480 $cfg .= ' --with-ldap' if ($self->{options}->{ldap});
481 $cfg .= ' --without-zlib' unless ($self->{options}->{zlib});
482 $cfg .= ' --with-openssl' if ($self->{options}->{ssl});
483 $cfg .= ' --with-ossp-uuid' if ($self->{options}->{uuid});
484 $cfg .= ' --with-libxml' if ($self->{options}->{xml});
485 $cfg .= ' --with-libxslt' if ($self->{options}->{xslt});
486 $cfg .= ' --with-krb5' if ($self->{options}->{krb5});
487 $cfg .= ' --with-tcl' if ($self->{options}->{tcl});
488 $cfg .= ' --with-perl' if ($self->{options}->{perl});
489 $cfg .= ' --with-python' if ($self->{options}->{python});