# Copyright (c) 2021-2022, PostgreSQL Global Development Group package MSBuildProject; # # Package that encapsulates a MSBuild project file (Visual C++ 2013 or greater) # # src/tools/msvc/MSBuildProject.pm # use Carp; use strict; use warnings; use base qw(Project); no warnings qw(redefine); ## no critic sub _new { my $classname = shift; my $self = $classname->SUPER::_new(@_); bless($self, $classname); $self->{filenameExtension} = '.vcxproj'; $self->{ToolsVersion} = '4.0'; return $self; } sub WriteHeader { my ($self, $f) = @_; print $f < EOF $self->WriteConfigurationHeader($f, 'Debug'); $self->WriteConfigurationHeader($f, 'Release'); print $f < $self->{guid} EOF # Check whether WindowsSDKVersion env variable is present. # Add WindowsTargetPlatformVersion node if so. my $sdkVersion = $ENV{'WindowsSDKVersion'}; if (defined($sdkVersion)) { # remove trailing backslash if necessary. $sdkVersion =~ s/\\$//; print $f <$sdkVersion EOF } print $f < EOF $self->WriteConfigurationPropertyGroup($f, 'Release', { wholeopt => 'false' }); $self->WriteConfigurationPropertyGroup($f, 'Debug', { wholeopt => 'false' }); print $f < EOF $self->WritePropertySheetsPropertyGroup($f, 'Release'); $self->WritePropertySheetsPropertyGroup($f, 'Debug'); print $f < <_ProjectFileVersion>10.0.30319.1 EOF $self->WriteAdditionalProperties($f, 'Debug'); $self->WriteAdditionalProperties($f, 'Release'); print $f < EOF $self->WriteItemDefinitionGroup( $f, 'Debug', { defs => "_DEBUG;DEBUG=1", opt => 'Disabled', strpool => 'false', runtime => 'MultiThreadedDebugDLL' }); $self->WriteItemDefinitionGroup( $f, 'Release', { defs => "", opt => 'Full', strpool => 'true', runtime => 'MultiThreadedDLL' }); return; } sub AddDefine { my ($self, $def) = @_; $self->{defines} .= $def . ';'; return; } sub WriteReferences { my ($self, $f) = @_; my @references = @{ $self->{references} }; if (scalar(@references)) { print $f < EOF foreach my $ref (@references) { print $f < $ref->{guid} EOF } print $f < EOF } return; } sub WriteFiles { my ($self, $f) = @_; print $f < EOF my @grammarFiles = (); my @resourceFiles = (); my %uniquefiles; foreach my $fileNameWithPath (sort keys %{ $self->{files} }) { confess "Bad format filename '$fileNameWithPath'\n" unless ($fileNameWithPath =~ m!^(.*)/([^/]+)\.(c|cpp|y|l|rc)$!); my $dir = $1; my $fileName = $2; if ($fileNameWithPath =~ /\.y$/ or $fileNameWithPath =~ /\.l$/) { push @grammarFiles, $fileNameWithPath; } elsif ($fileNameWithPath =~ /\.rc$/) { push @resourceFiles, $fileNameWithPath; } elsif (defined($uniquefiles{$fileName})) { # File already exists, so fake a new name my $obj = $dir; $obj =~ s!/!_!g; print $f < .\\debug\\$self->{name}\\${obj}_$fileName.obj .\\release\\$self->{name}\\${obj}_$fileName.obj EOF } else { $uniquefiles{$fileName} = 1; print $f < EOF } } print $f < EOF if (scalar(@grammarFiles)) { print $f < EOF foreach my $grammarFile (@grammarFiles) { (my $outputFile = $grammarFile) =~ s/\.(y|l)$/.c/; if ($grammarFile =~ /\.y$/) { $outputFile =~ s{^src\\pl\\plpgsql\\src\\gram.c$}{src\\pl\\plpgsql\\src\\pl_gram.c}; print $f < Running bison on $grammarFile perl "src\\tools\\msvc\\pgbison.pl" "$grammarFile" %(AdditionalInputs) $outputFile;%(Outputs) Running bison on $grammarFile perl "src\\tools\\msvc\\pgbison.pl" "$grammarFile" %(AdditionalInputs) $outputFile;%(Outputs) EOF } else #if ($grammarFile =~ /\.l$/) { print $f < Running flex on $grammarFile perl "src\\tools\\msvc\\pgflex.pl" "$grammarFile" %(AdditionalInputs) $outputFile;%(Outputs) Running flex on $grammarFile perl "src\\tools\\msvc\\pgflex.pl" "$grammarFile" %(AdditionalInputs) $outputFile;%(Outputs) EOF } } print $f < EOF } if (scalar(@resourceFiles)) { print $f < EOF foreach my $rcFile (@resourceFiles) { print $f < EOF } print $f < EOF } return; } sub WriteConfigurationHeader { my ($self, $f, $cfgname) = @_; print $f < $cfgname $self->{platform} EOF return; } sub WriteConfigurationPropertyGroup { my ($self, $f, $cfgname, $p) = @_; my $cfgtype = ($self->{type} eq "exe") ? 'Application' : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary'); print $f < $cfgtype false MultiByte $p->{wholeopt} $self->{PlatformToolset} EOF return; } sub WritePropertySheetsPropertyGroup { my ($self, $f, $cfgname) = @_; print $f < EOF return; } sub WriteAdditionalProperties { my ($self, $f, $cfgname) = @_; print $f <.\\$cfgname\\$self->{name}\\ .\\$cfgname\\$self->{name}\\ false EOF return; } sub WriteItemDefinitionGroup { my ($self, $f, $cfgname, $p) = @_; my $cfgtype = ($self->{type} eq "exe") ? 'Application' : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary'); my $libs = $self->GetAdditionalLinkerDependencies($cfgname, ';'); my $targetmachine = $self->{platform} eq 'Win32' ? 'MachineX86' : 'MachineX64'; my $includes = join ';', @{ $self->{includes} }, ""; print $f < $p->{opt} $self->{prefixincludes}src/include;src/include/port/win32;src/include/port/win32_msvc;$includes\%(AdditionalIncludeDirectories) WIN32;_WINDOWS;__WINDOWS__;__WIN32__;WIN32_STACK_RLIMIT=4194304;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE$self->{defines}$p->{defs}\%(PreprocessorDefinitions) $p->{strpool} $p->{runtime} $self->{disablewarnings};\%(DisableSpecificWarnings) /MP \%(AdditionalOptions) .\\$cfgname\\$self->{name}\\ .\\$cfgname\\$self->{name}\\ .\\$cfgname\\$self->{name}\\ false Level3 true ProgramDatabase Default .\\$cfgname\\$self->{name}\\$self->{name}.$self->{type} $libs;\%(AdditionalDependencies) true \%(AdditionalLibraryDirectories) libc;\%(IgnoreSpecificDefaultLibraries) 4194304 true .\\$cfgname\\$self->{name}\\$self->{name}.pdb false .\\$cfgname\\$self->{name}\\$self->{name}.map false Console $targetmachine EOF if ($self->{disablelinkerwarnings}) { print $f " /ignore:$self->{disablelinkerwarnings} \%(AdditionalOptions)\n"; } if ($self->{implib}) { my $l = $self->{implib}; $l =~ s/__CFGNAME__/$cfgname/g; print $f " $l\n"; } if ($self->{def}) { my $d = $self->{def}; $d =~ s/__CFGNAME__/$cfgname/g; print $f " $d\n"; } print $f < src\\include;\%(AdditionalIncludeDirectories) EOF if ($self->{builddef}) { print $f < Generate DEF file perl src\\tools\\msvc\\gendef.pl $cfgname\\$self->{name} $self->{platform} EOF } print $f < EOF return; } sub Footer { my ($self, $f) = @_; $self->WriteReferences($f); print $f < EOF return; } package VC2013Project; # # Package that encapsulates a Visual C++ 2013 project file # use strict; use warnings; use base qw(MSBuildProject); no warnings qw(redefine); ## no critic sub new { my $classname = shift; my $self = $classname->SUPER::_new(@_); bless($self, $classname); $self->{vcver} = '12.00'; $self->{PlatformToolset} = 'v120'; $self->{ToolsVersion} = '12.0'; return $self; } package VC2015Project; # # Package that encapsulates a Visual C++ 2015 project file # use strict; use warnings; use base qw(MSBuildProject); no warnings qw(redefine); ## no critic sub new { my $classname = shift; my $self = $classname->SUPER::_new(@_); bless($self, $classname); $self->{vcver} = '14.00'; $self->{PlatformToolset} = 'v140'; $self->{ToolsVersion} = '14.0'; return $self; } package VC2017Project; # # Package that encapsulates a Visual C++ 2017 project file # use strict; use warnings; use base qw(MSBuildProject); no warnings qw(redefine); ## no critic sub new { my $classname = shift; my $self = $classname->SUPER::_new(@_); bless($self, $classname); $self->{vcver} = '15.00'; $self->{PlatformToolset} = 'v141'; $self->{ToolsVersion} = '15.0'; return $self; } package VC2019Project; # # Package that encapsulates a Visual C++ 2019 project file # use strict; use warnings; use base qw(MSBuildProject); no warnings qw(redefine); ## no critic sub new { my $classname = shift; my $self = $classname->SUPER::_new(@_); bless($self, $classname); $self->{vcver} = '16.00'; $self->{PlatformToolset} = 'v142'; $self->{ToolsVersion} = '16.0'; return $self; } package VC2022Project; # # Package that encapsulates a Visual C++ 2022 project file # use strict; use warnings; use base qw(MSBuildProject); no warnings qw(redefine); ## no critic sub new { my $classname = shift; my $self = $classname->SUPER::_new(@_); bless($self, $classname); $self->{vcver} = '17.00'; $self->{PlatformToolset} = 'v143'; $self->{ToolsVersion} = '17.0'; return $self; } 1;