1package MSBuildProject; 2 3# 4# Package that encapsulates a MSBuild project file (Visual C++ 2010 or greater) 5# 6# src/tools/msvc/MSBuildProject.pm 7# 8 9use Carp; 10use strict; 11use warnings; 12use base qw(Project); 13 14no warnings qw(redefine); ## no critic 15 16sub _new 17{ 18 my $classname = shift; 19 my $self = $classname->SUPER::_new(@_); 20 bless($self, $classname); 21 22 $self->{filenameExtension} = '.vcxproj'; 23 $self->{ToolsVersion} = '4.0'; 24 25 return $self; 26} 27 28sub WriteHeader 29{ 30 my ($self, $f) = @_; 31 32 print $f <<EOF; 33<?xml version="1.0" encoding="Windows-1252"?> 34<Project DefaultTargets="Build" ToolsVersion="$self->{ToolsVersion}" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 35 <ItemGroup Label="ProjectConfigurations"> 36EOF 37 $self->WriteConfigurationHeader($f, 'Debug'); 38 $self->WriteConfigurationHeader($f, 'Release'); 39 print $f <<EOF; 40 </ItemGroup> 41 <PropertyGroup Label="Globals"> 42 <ProjectGuid>$self->{guid}</ProjectGuid> 43EOF 44 # Check whether WindowsSDKVersion env variable is present. 45 # Add WindowsTargetPlatformVersion node if so. 46 my $sdkVersion = $ENV{'WindowsSDKVersion'}; 47 if (defined($sdkVersion)) 48 { 49 # remove trailing backslash if necessary. 50 $sdkVersion =~ s/\\$//; 51 print $f <<EOF 52 <WindowsTargetPlatformVersion>$sdkVersion</WindowsTargetPlatformVersion> 53EOF 54 } 55 print $f <<EOF; 56 </PropertyGroup> 57 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" /> 58EOF 59 $self->WriteConfigurationPropertyGroup($f, 'Release', 60 { wholeopt => 'false' }); 61 $self->WriteConfigurationPropertyGroup($f, 'Debug', 62 { wholeopt => 'false' }); 63 print $f <<EOF; 64 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" /> 65 <ImportGroup Label="ExtensionSettings"> 66 </ImportGroup> 67EOF 68 $self->WritePropertySheetsPropertyGroup($f, 'Release'); 69 $self->WritePropertySheetsPropertyGroup($f, 'Debug'); 70 print $f <<EOF; 71 <PropertyGroup Label="UserMacros" /> 72 <PropertyGroup> 73 <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> 74EOF 75 $self->WriteAdditionalProperties($f, 'Debug'); 76 $self->WriteAdditionalProperties($f, 'Release'); 77 print $f <<EOF; 78 </PropertyGroup> 79EOF 80 81 $self->WriteItemDefinitionGroup( 82 $f, 'Debug', 83 { 84 defs => "_DEBUG;DEBUG=1", 85 opt => 'Disabled', 86 strpool => 'false', 87 runtime => 'MultiThreadedDebugDLL' 88 }); 89 $self->WriteItemDefinitionGroup( 90 $f, 91 'Release', 92 { 93 defs => "", 94 opt => 'Full', 95 strpool => 'true', 96 runtime => 'MultiThreadedDLL' 97 }); 98 return; 99} 100 101sub AddDefine 102{ 103 my ($self, $def) = @_; 104 105 $self->{defines} .= $def . ';'; 106 return; 107} 108 109sub WriteReferences 110{ 111 my ($self, $f) = @_; 112 113 my @references = @{ $self->{references} }; 114 115 if (scalar(@references)) 116 { 117 print $f <<EOF; 118 <ItemGroup> 119EOF 120 foreach my $ref (@references) 121 { 122 print $f <<EOF; 123 <ProjectReference Include="$ref->{name}$ref->{filenameExtension}"> 124 <Project>$ref->{guid}</Project> 125 </ProjectReference> 126EOF 127 } 128 print $f <<EOF; 129 </ItemGroup> 130EOF 131 } 132 return; 133} 134 135sub WriteFiles 136{ 137 my ($self, $f) = @_; 138 print $f <<EOF; 139 <ItemGroup> 140EOF 141 my @grammarFiles = (); 142 my @resourceFiles = (); 143 my %uniquefiles; 144 foreach my $fileNameWithPath (sort keys %{ $self->{files} }) 145 { 146 confess "Bad format filename '$fileNameWithPath'\n" 147 unless ($fileNameWithPath =~ m!^(.*)/([^/]+)\.(c|cpp|y|l|rc)$!); 148 my $dir = $1; 149 my $fileName = $2; 150 if ($fileNameWithPath =~ /\.y$/ or $fileNameWithPath =~ /\.l$/) 151 { 152 push @grammarFiles, $fileNameWithPath; 153 } 154 elsif ($fileNameWithPath =~ /\.rc$/) 155 { 156 push @resourceFiles, $fileNameWithPath; 157 } 158 elsif (defined($uniquefiles{$fileName})) 159 { 160 161 # File already exists, so fake a new name 162 my $obj = $dir; 163 $obj =~ s!/!_!g; 164 165 print $f <<EOF; 166 <ClCompile Include="$fileNameWithPath"> 167 <ObjectFileName Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">.\\debug\\$self->{name}\\${obj}_$fileName.obj</ObjectFileName> 168 <ObjectFileName Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">.\\release\\$self->{name}\\${obj}_$fileName.obj</ObjectFileName> 169 </ClCompile> 170EOF 171 } 172 else 173 { 174 $uniquefiles{$fileName} = 1; 175 print $f <<EOF; 176 <ClCompile Include="$fileNameWithPath" /> 177EOF 178 } 179 180 } 181 print $f <<EOF; 182 </ItemGroup> 183EOF 184 if (scalar(@grammarFiles)) 185 { 186 print $f <<EOF; 187 <ItemGroup> 188EOF 189 foreach my $grammarFile (@grammarFiles) 190 { 191 (my $outputFile = $grammarFile) =~ s/\.(y|l)$/.c/; 192 if ($grammarFile =~ /\.y$/) 193 { 194 $outputFile =~ 195 s{^src\\pl\\plpgsql\\src\\gram.c$}{src\\pl\\plpgsql\\src\\pl_gram.c}; 196 print $f <<EOF; 197 <CustomBuild Include="$grammarFile"> 198 <Message Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">Running bison on $grammarFile</Message> 199 <Command Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">perl "src\\tools\\msvc\\pgbison.pl" "$grammarFile"</Command> 200 <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs> 201 <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">$outputFile;%(Outputs)</Outputs> 202 <Message Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">Running bison on $grammarFile</Message> 203 <Command Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">perl "src\\tools\\msvc\\pgbison.pl" "$grammarFile"</Command> 204 <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs> 205 <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">$outputFile;%(Outputs)</Outputs> 206 </CustomBuild> 207EOF 208 } 209 else #if ($grammarFile =~ /\.l$/) 210 { 211 print $f <<EOF; 212 <CustomBuild Include="$grammarFile"> 213 <Message Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">Running flex on $grammarFile</Message> 214 <Command Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">perl "src\\tools\\msvc\\pgflex.pl" "$grammarFile"</Command> 215 <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs> 216 <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Debug|$self->{platform}'">$outputFile;%(Outputs)</Outputs> 217 <Message Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">Running flex on $grammarFile</Message> 218 <Command Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">perl "src\\tools\\msvc\\pgflex.pl" "$grammarFile"</Command> 219 <AdditionalInputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">%(AdditionalInputs)</AdditionalInputs> 220 <Outputs Condition="'\$(Configuration)|\$(Platform)'=='Release|$self->{platform}'">$outputFile;%(Outputs)</Outputs> 221 </CustomBuild> 222EOF 223 } 224 } 225 print $f <<EOF; 226 </ItemGroup> 227EOF 228 } 229 if (scalar(@resourceFiles)) 230 { 231 print $f <<EOF; 232 <ItemGroup> 233EOF 234 foreach my $rcFile (@resourceFiles) 235 { 236 print $f <<EOF; 237 <ResourceCompile Include="$rcFile" /> 238EOF 239 } 240 print $f <<EOF; 241 </ItemGroup> 242EOF 243 } 244 return; 245} 246 247sub WriteConfigurationHeader 248{ 249 my ($self, $f, $cfgname) = @_; 250 print $f <<EOF; 251 <ProjectConfiguration Include="$cfgname|$self->{platform}"> 252 <Configuration>$cfgname</Configuration> 253 <Platform>$self->{platform}</Platform> 254 </ProjectConfiguration> 255EOF 256 return; 257} 258 259sub WriteConfigurationPropertyGroup 260{ 261 my ($self, $f, $cfgname, $p) = @_; 262 my $cfgtype = 263 ($self->{type} eq "exe") 264 ? 'Application' 265 : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary'); 266 267 print $f <<EOF; 268 <PropertyGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'" Label="Configuration"> 269 <ConfigurationType>$cfgtype</ConfigurationType> 270 <UseOfMfc>false</UseOfMfc> 271 <CharacterSet>MultiByte</CharacterSet> 272 <WholeProgramOptimization>$p->{wholeopt}</WholeProgramOptimization> 273 </PropertyGroup> 274EOF 275 return; 276} 277 278sub WritePropertySheetsPropertyGroup 279{ 280 my ($self, $f, $cfgname) = @_; 281 print $f <<EOF; 282 <ImportGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'" Label="PropertySheets"> 283 <Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" /> 284 </ImportGroup> 285EOF 286 return; 287} 288 289sub WriteAdditionalProperties 290{ 291 my ($self, $f, $cfgname) = @_; 292 print $f <<EOF; 293 <OutDir Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">.\\$cfgname\\$self->{name}\\</OutDir> 294 <IntDir Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">.\\$cfgname\\$self->{name}\\</IntDir> 295 <LinkIncremental Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'">false</LinkIncremental> 296EOF 297 return; 298} 299 300sub WriteItemDefinitionGroup 301{ 302 my ($self, $f, $cfgname, $p) = @_; 303 my $cfgtype = 304 ($self->{type} eq "exe") 305 ? 'Application' 306 : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary'); 307 my $libs = $self->GetAdditionalLinkerDependencies($cfgname, ';'); 308 309 my $targetmachine = 310 $self->{platform} eq 'Win32' ? 'MachineX86' : 'MachineX64'; 311 312 my $includes = $self->{includes}; 313 unless ($includes eq '' or $includes =~ /;$/) 314 { 315 $includes .= ';'; 316 } 317 print $f <<EOF; 318 <ItemDefinitionGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'"> 319 <ClCompile> 320 <Optimization>$p->{opt}</Optimization> 321 <AdditionalIncludeDirectories>$self->{prefixincludes}src/include;src/include/port/win32;src/include/port/win32_msvc;$includes\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> 322 <PreprocessorDefinitions>WIN32;_WINDOWS;__WINDOWS__;__WIN32__;EXEC_BACKEND;WIN32_STACK_RLIMIT=4194304;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE$self->{defines}$p->{defs}\%(PreprocessorDefinitions)</PreprocessorDefinitions> 323 <StringPooling>$p->{strpool}</StringPooling> 324 <RuntimeLibrary>$p->{runtime}</RuntimeLibrary> 325 <DisableSpecificWarnings>$self->{disablewarnings};\%(DisableSpecificWarnings)</DisableSpecificWarnings> 326 <AdditionalOptions>/MP \%(AdditionalOptions)</AdditionalOptions> 327 <AssemblerOutput> 328 </AssemblerOutput> 329 <AssemblerListingLocation>.\\$cfgname\\$self->{name}\\</AssemblerListingLocation> 330 <ObjectFileName>.\\$cfgname\\$self->{name}\\</ObjectFileName> 331 <ProgramDataBaseFileName>.\\$cfgname\\$self->{name}\\</ProgramDataBaseFileName> 332 <BrowseInformation>false</BrowseInformation> 333 <WarningLevel>Level3</WarningLevel> 334 <SuppressStartupBanner>true</SuppressStartupBanner> 335 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 336 <CompileAs>Default</CompileAs> 337 </ClCompile> 338 <Link> 339 <OutputFile>.\\$cfgname\\$self->{name}\\$self->{name}.$self->{type}</OutputFile> 340 <AdditionalDependencies>$libs;\%(AdditionalDependencies)</AdditionalDependencies> 341 <SuppressStartupBanner>true</SuppressStartupBanner> 342 <AdditionalLibraryDirectories>\%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> 343 <IgnoreSpecificDefaultLibraries>libc;\%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries> 344 <StackReserveSize>4194304</StackReserveSize> 345 <GenerateDebugInformation>true</GenerateDebugInformation> 346 <ProgramDatabaseFile>.\\$cfgname\\$self->{name}\\$self->{name}.pdb</ProgramDatabaseFile> 347 <GenerateMapFile>false</GenerateMapFile> 348 <MapFileName>.\\$cfgname\\$self->{name}\\$self->{name}.map</MapFileName> 349 <RandomizedBaseAddress>false</RandomizedBaseAddress> 350 <!-- Permit links to MinGW-built, 32-bit DLLs (default before VS2012). --> 351 <ImageHasSafeExceptionHandlers/> 352 <SubSystem>Console</SubSystem> 353 <TargetMachine>$targetmachine</TargetMachine> 354EOF 355 if ($self->{disablelinkerwarnings}) 356 { 357 print $f 358 " <AdditionalOptions>/ignore:$self->{disablelinkerwarnings} \%(AdditionalOptions)</AdditionalOptions>\n"; 359 } 360 if ($self->{implib}) 361 { 362 my $l = $self->{implib}; 363 $l =~ s/__CFGNAME__/$cfgname/g; 364 print $f " <ImportLibrary>$l</ImportLibrary>\n"; 365 } 366 if ($self->{def}) 367 { 368 my $d = $self->{def}; 369 $d =~ s/__CFGNAME__/$cfgname/g; 370 print $f " <ModuleDefinitionFile>$d</ModuleDefinitionFile>\n"; 371 } 372 print $f <<EOF; 373 </Link> 374 <ResourceCompile> 375 <AdditionalIncludeDirectories>src\\include;\%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> 376 </ResourceCompile> 377EOF 378 if ($self->{builddef}) 379 { 380 print $f <<EOF; 381 <PreLinkEvent> 382 <Message>Generate DEF file</Message> 383 <Command>perl src\\tools\\msvc\\gendef.pl $cfgname\\$self->{name} $self->{platform}</Command> 384 </PreLinkEvent> 385EOF 386 } 387 print $f <<EOF; 388 </ItemDefinitionGroup> 389EOF 390 return; 391} 392 393sub Footer 394{ 395 my ($self, $f) = @_; 396 $self->WriteReferences($f); 397 398 print $f <<EOF; 399 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" /> 400 <ImportGroup Label="ExtensionTargets"> 401 </ImportGroup> 402</Project> 403EOF 404 return; 405} 406 407package VC2010Project; 408 409# 410# Package that encapsulates a Visual C++ 2010 project file 411# 412 413use strict; 414use warnings; 415use base qw(MSBuildProject); 416 417no warnings qw(redefine); ## no critic 418 419sub new 420{ 421 my $classname = shift; 422 my $self = $classname->SUPER::_new(@_); 423 bless($self, $classname); 424 425 $self->{vcver} = '10.00'; 426 427 return $self; 428} 429 430package VC2012Project; 431 432# 433# Package that encapsulates a Visual C++ 2012 project file 434# 435 436use strict; 437use warnings; 438use base qw(MSBuildProject); 439 440no warnings qw(redefine); ## no critic 441 442sub new 443{ 444 my $classname = shift; 445 my $self = $classname->SUPER::_new(@_); 446 bless($self, $classname); 447 448 $self->{vcver} = '11.00'; 449 $self->{PlatformToolset} = 'v110'; 450 451 return $self; 452} 453 454# This override adds the <PlatformToolset> element 455# to the PropertyGroup labeled "Configuration" 456sub WriteConfigurationPropertyGroup 457{ 458 my ($self, $f, $cfgname, $p) = @_; 459 my $cfgtype = 460 ($self->{type} eq "exe") 461 ? 'Application' 462 : ($self->{type} eq "dll" ? 'DynamicLibrary' : 'StaticLibrary'); 463 464 print $f <<EOF; 465 <PropertyGroup Condition="'\$(Configuration)|\$(Platform)'=='$cfgname|$self->{platform}'" Label="Configuration"> 466 <ConfigurationType>$cfgtype</ConfigurationType> 467 <UseOfMfc>false</UseOfMfc> 468 <CharacterSet>MultiByte</CharacterSet> 469 <WholeProgramOptimization>$p->{wholeopt}</WholeProgramOptimization> 470 <PlatformToolset>$self->{PlatformToolset}</PlatformToolset> 471 </PropertyGroup> 472EOF 473 return; 474} 475 476package VC2013Project; 477 478# 479# Package that encapsulates a Visual C++ 2013 project file 480# 481 482use strict; 483use warnings; 484use base qw(VC2012Project); 485 486no warnings qw(redefine); ## no critic 487 488sub new 489{ 490 my $classname = shift; 491 my $self = $classname->SUPER::_new(@_); 492 bless($self, $classname); 493 494 $self->{vcver} = '12.00'; 495 $self->{PlatformToolset} = 'v120'; 496 $self->{ToolsVersion} = '12.0'; 497 498 return $self; 499} 500 501package VC2015Project; 502 503# 504# Package that encapsulates a Visual C++ 2015 project file 505# 506 507use strict; 508use warnings; 509use base qw(VC2012Project); 510 511no warnings qw(redefine); ## no critic 512 513sub new 514{ 515 my $classname = shift; 516 my $self = $classname->SUPER::_new(@_); 517 bless($self, $classname); 518 519 $self->{vcver} = '14.00'; 520 $self->{PlatformToolset} = 'v140'; 521 $self->{ToolsVersion} = '14.0'; 522 523 return $self; 524} 525 526package VC2017Project; 527 528# 529# Package that encapsulates a Visual C++ 2017 project file 530# 531 532use strict; 533use warnings; 534use base qw(VC2012Project); 535 536no warnings qw(redefine); ## no critic 537 538sub new 539{ 540 my $classname = shift; 541 my $self = $classname->SUPER::_new(@_); 542 bless($self, $classname); 543 544 $self->{vcver} = '15.00'; 545 $self->{PlatformToolset} = 'v141'; 546 $self->{ToolsVersion} = '15.0'; 547 548 return $self; 549} 550 551package VC2019Project; 552 553# 554# Package that encapsulates a Visual C++ 2019 project file 555# 556 557use strict; 558use warnings; 559use base qw(VC2012Project); 560 561no warnings qw(redefine); ## no critic 562 563sub new 564{ 565 my $classname = shift; 566 my $self = $classname->SUPER::_new(@_); 567 bless($self, $classname); 568 569 $self->{vcver} = '16.00'; 570 $self->{PlatformToolset} = 'v142'; 571 $self->{ToolsVersion} = '16.0'; 572 573 return $self; 574} 575 5761; 577