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