contrib / buildsystems / Generators / Vcxproj.pmon commit Merge branch 'bc/reread-attributes-during-rebase' (c8ada15)
   1package Generators::Vcxproj;
   2require Exporter;
   3
   4use strict;
   5use vars qw($VERSION);
   6use Digest::SHA qw(sha256_hex);
   7
   8our $VERSION = '1.00';
   9our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
  10@ISA = qw(Exporter);
  11
  12BEGIN {
  13    push @EXPORT_OK, qw(generate);
  14}
  15
  16sub generate_guid ($) {
  17        my $hex = sha256_hex($_[0]);
  18        $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12}).*/{$1-$2-$3-$4-$5}/;
  19        $hex =~ tr/a-z/A-Z/;
  20        return $hex;
  21}
  22
  23sub generate {
  24    my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
  25    my @libs = @{$build_structure{"LIBS"}};
  26    foreach (@libs) {
  27        createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 1);
  28    }
  29
  30    my @apps = @{$build_structure{"APPS"}};
  31    foreach (@apps) {
  32        createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 0);
  33    }
  34
  35    createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure);
  36    return 0;
  37}
  38
  39sub createProject {
  40    my ($name, $git_dir, $out_dir, $rel_dir, $build_structure, $static_library) = @_;
  41    my $label = $static_library ? "lib" : "app";
  42    my $prefix = $static_library ? "LIBS_" : "APPS_";
  43    my $config_type = $static_library ? "StaticLibrary" : "Application";
  44    print "Generate $name vcxproj $label project\n";
  45    my $cdup = $name;
  46    $cdup =~ s/[^\/]+/../g;
  47    $cdup =~ s/\//\\/g;
  48    $rel_dir = $rel_dir eq "." ? $cdup : "$cdup\\$rel_dir";
  49    $rel_dir =~ s/\//\\/g;
  50
  51    my $target = $name;
  52    if ($static_library) {
  53      $target =~ s/\.a//;
  54    } else {
  55      $target =~ s/\.exe//;
  56    }
  57
  58    my $uuid = generate_guid($name);
  59    $$build_structure{"$prefix${target}_GUID"} = $uuid;
  60    my $vcxproj = $target;
  61    $vcxproj =~ s/(.*\/)?(.*)/$&\/$2.vcxproj/;
  62    $vcxproj =~ s/([^\/]*)(\/lib)\/(lib.vcxproj)/$1$2\/$1_$3/;
  63    $$build_structure{"$prefix${target}_VCXPROJ"} = $vcxproj;
  64
  65    my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"$prefix${name}_SOURCES"}}));
  66    my @sources;
  67    foreach (@srcs) {
  68        $_ =~ s/\//\\/g;
  69        push(@sources, $_);
  70    }
  71    my $defines = join(";", sort(@{$$build_structure{"$prefix${name}_DEFINES"}}));
  72    my $includes= join(";", sort(map { s/^-I//; s/\//\\/g; File::Spec->file_name_is_absolute($_) ? $_ : "$rel_dir\\$_" } @{$$build_structure{"$prefix${name}_INCLUDES"}}));
  73    my $cflags = join(" ", sort(map { s/^-[GLMOWZ].*//; s/.* .*/"$&"/; $_; } @{$$build_structure{"$prefix${name}_CFLAGS"}}));
  74    $cflags =~ s/</&lt;/g;
  75    $cflags =~ s/>/&gt;/g;
  76
  77    my $libs_release = "\n    ";
  78    my $libs_debug = "\n    ";
  79    if (!$static_library) {
  80      $libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
  81      $libs_debug = $libs_release;
  82      $libs_debug =~ s/zlib\.lib/zlibd\.lib/;
  83    }
  84
  85    $defines =~ s/-D//g;
  86    $defines =~ s/</&lt;/g;
  87    $defines =~ s/>/&gt;/g;
  88    $defines =~ s/\'//g;
  89
  90    die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
  91
  92    open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
  93    binmode F, ":crlf :utf8";
  94    print F chr(0xFEFF);
  95    print F << "EOM";
  96<?xml version="1.0" encoding="utf-8"?>
  97<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  98  <ItemGroup Label="ProjectConfigurations">
  99    <ProjectConfiguration Include="Debug|Win32">
 100      <Configuration>Debug</Configuration>
 101      <Platform>Win32</Platform>
 102    </ProjectConfiguration>
 103    <ProjectConfiguration Include="Release|Win32">
 104      <Configuration>Release</Configuration>
 105      <Platform>Win32</Platform>
 106    </ProjectConfiguration>
 107    <ProjectConfiguration Include="Debug|x64">
 108      <Configuration>Debug</Configuration>
 109      <Platform>x64</Platform>
 110    </ProjectConfiguration>
 111    <ProjectConfiguration Include="Release|x64">
 112      <Configuration>Release</Configuration>
 113      <Platform>x64</Platform>
 114    </ProjectConfiguration>
 115  </ItemGroup>
 116  <PropertyGroup Label="Globals">
 117    <ProjectGuid>$uuid</ProjectGuid>
 118    <Keyword>Win32Proj</Keyword>
 119    <VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch>
 120    <VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch>
 121    <VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory>
 122    <VCPKGBinDirectory Condition="'\(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory>
 123    <VCPKGLibDirectory Condition="'\(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory>
 124    <VCPKGBinDirectory Condition="'\(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\bin</VCPKGBinDirectory>
 125    <VCPKGLibDirectory Condition="'\(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\lib</VCPKGLibDirectory>
 126    <VCPKGIncludeDirectory>\$(VCPKGArchDirectory)\\include</VCPKGIncludeDirectory>
 127    <VCPKGLibs Condition="'\(Configuration)'=='Debug'">$libs_debug</VCPKGLibs>
 128    <VCPKGLibs Condition="'\(Configuration)'!='Debug'">$libs_release</VCPKGLibs>
 129  </PropertyGroup>
 130  <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
 131  <PropertyGroup Condition="'\$(Configuration)'=='Debug'" Label="Configuration">
 132    <UseDebugLibraries>true</UseDebugLibraries>
 133    <LinkIncremental>true</LinkIncremental>
 134  </PropertyGroup>
 135  <PropertyGroup Condition="'\$(Configuration)'=='Release'" Label="Configuration">
 136    <UseDebugLibraries>false</UseDebugLibraries>
 137    <WholeProgramOptimization>true</WholeProgramOptimization>
 138  </PropertyGroup>
 139  <PropertyGroup>
 140    <ConfigurationType>$config_type</ConfigurationType>
 141    <PlatformToolset>v140</PlatformToolset>
 142    <!-- <CharacterSet>UTF-8</CharacterSet> -->
 143    <OutDir>..\\</OutDir>
 144    <!-- <IntDir>\$(ProjectDir)\$(Configuration)\\</IntDir> -->
 145  </PropertyGroup>
 146  <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" />
 147  <ImportGroup Label="ExtensionSettings">
 148  </ImportGroup>
 149  <ImportGroup Label="Shared">
 150  </ImportGroup>
 151  <ImportGroup Label="PropertySheets">
 152    <Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" />
 153  </ImportGroup>
 154  <PropertyGroup Label="UserMacros" />
 155  <PropertyGroup>
 156    <GenerateManifest>false</GenerateManifest>
 157    <EnableManagedIncrementalBuild>true</EnableManagedIncrementalBuild>
 158  </PropertyGroup>
 159  <ItemDefinitionGroup>
 160    <ClCompile>
 161      <AdditionalOptions>$cflags %(AdditionalOptions)</AdditionalOptions>
 162      <AdditionalIncludeDirectories>$cdup;$cdup\\compat;$cdup\\compat\\regex;$cdup\\compat\\win32;$cdup\\compat\\poll;$cdup\\compat\\vcbuild\\include;\$(VCPKGIncludeDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
 163      <EnableParallelCodeGeneration />
 164      <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
 165      <PrecompiledHeader />
 166      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
 167    </ClCompile>
 168    <Lib>
 169      <SuppressStartupBanner>true</SuppressStartupBanner>
 170    </Lib>
 171    <Link>
 172      <AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
 173      <AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies>
 174      <AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions>
 175      <EntryPointSymbol>wmainCRTStartup</EntryPointSymbol>
 176      <ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile>
 177      <SubSystem>Console</SubSystem>
 178    </Link>
 179EOM
 180    if ($target eq 'libgit') {
 181        print F << "EOM";
 182    <PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)\\include\\openssl\\ssl.h')">
 183      <Message>Initialize VCPKG</Message>
 184      <Command>del "$cdup\\compat\\vcbuild\\vcpkg"</Command>
 185      <Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat"</Command>
 186    </PreBuildEvent>
 187EOM
 188    }
 189    print F << "EOM";
 190  </ItemDefinitionGroup>
 191  <ItemDefinitionGroup Condition="'\$(Platform)'=='Win32'">
 192    <Link>
 193      <TargetMachine>MachineX86</TargetMachine>
 194    </Link>
 195  </ItemDefinitionGroup>
 196  <ItemDefinitionGroup Condition="'\$(Configuration)'=='Debug'">
 197    <ClCompile>
 198      <Optimization>Disabled</Optimization>
 199      <PreprocessorDefinitions>WIN32;_DEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 200      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
 201    </ClCompile>
 202    <Link>
 203      <GenerateDebugInformation>true</GenerateDebugInformation>
 204    </Link>
 205  </ItemDefinitionGroup>
 206  <ItemDefinitionGroup Condition="'\$(Configuration)'=='Release'">
 207    <ClCompile>
 208      <Optimization>MaxSpeed</Optimization>
 209      <IntrinsicFunctions>true</IntrinsicFunctions>
 210      <PreprocessorDefinitions>WIN32;NDEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
 211      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
 212      <FunctionLevelLinking>true</FunctionLevelLinking>
 213      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
 214    </ClCompile>
 215    <Link>
 216      <GenerateDebugInformation>true</GenerateDebugInformation>
 217      <EnableCOMDATFolding>true</EnableCOMDATFolding>
 218      <OptimizeReferences>true</OptimizeReferences>
 219    </Link>
 220  </ItemDefinitionGroup>
 221  <ItemGroup>
 222EOM
 223    foreach(@sources) {
 224        print F << "EOM";
 225    <ClCompile Include="$_" />
 226EOM
 227    }
 228    print F << "EOM";
 229  </ItemGroup>
 230EOM
 231    if (!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') {
 232      my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"};
 233      my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"};
 234
 235      print F << "EOM";
 236  <ItemGroup>
 237    <ProjectReference Include="$cdup\\libgit\\libgit.vcxproj">
 238      <Project>$uuid_libgit</Project>
 239      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
 240    </ProjectReference>
 241EOM
 242      if (!($name =~ 'xdiff')) {
 243        print F << "EOM";
 244    <ProjectReference Include="$cdup\\xdiff\\lib\\xdiff_lib.vcxproj">
 245      <Project>$uuid_xdiff_lib</Project>
 246      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
 247    </ProjectReference>
 248EOM
 249      }
 250      if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) {
 251        my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"};
 252        print F << "EOM";
 253    <ProjectReference Include="$cdup\\vcs-svn\\lib\\vcs-svn_lib.vcxproj">
 254      <Project>$uuid_vcs_svn_lib</Project>
 255      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
 256    </ProjectReference>
 257EOM
 258      }
 259      print F << "EOM";
 260  </ItemGroup>
 261EOM
 262    }
 263    print F << "EOM";
 264  <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" />
 265EOM
 266    if (!$static_library) {
 267      print F << "EOM";
 268  <Target Name="${target}_AfterBuild" AfterTargets="AfterBuild">
 269    <ItemGroup>
 270      <DLLsAndPDBs Include="\$(VCPKGBinDirectory)\\*.dll;\$(VCPKGBinDirectory)\\*.pdb" />
 271    </ItemGroup>
 272    <Copy SourceFiles="@(DLLsAndPDBs)" DestinationFolder="\$(OutDir)" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />
 273    <MakeDir Directories="..\\templates\\blt\\branches" />
 274  </Target>
 275EOM
 276    }
 277    if ($target eq 'git') {
 278      print F "  <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
 279    }
 280    print F << "EOM";
 281</Project>
 282EOM
 283    close F;
 284}
 285
 286sub createGlueProject {
 287    my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
 288    print "Generate solutions file\n";
 289    $rel_dir = "..\\$rel_dir";
 290    $rel_dir =~ s/\//\\/g;
 291    my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n";
 292    my $SLN_PRE  = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = ";
 293    my $SLN_POST = "\nEndProject\n";
 294
 295    my @libs = @{$build_structure{"LIBS"}};
 296    my @tmp;
 297    foreach (@libs) {
 298        $_ =~ s/\.a//;
 299        push(@tmp, $_);
 300    }
 301    @libs = @tmp;
 302
 303    my @apps = @{$build_structure{"APPS"}};
 304    @tmp = ();
 305    foreach (@apps) {
 306        $_ =~ s/\.exe//;
 307        if ($_ eq "git" ) {
 308            unshift(@tmp, $_);
 309        } else {
 310            push(@tmp, $_);
 311        }
 312    }
 313    @apps = @tmp;
 314
 315    open F, ">git.sln" || die "Could not open git.sln for writing!\n";
 316    binmode F, ":crlf :utf8";
 317    print F chr(0xFEFF);
 318    print F "$SLN_HEAD";
 319
 320    foreach (@apps) {
 321        my $appname = $_;
 322        my $uuid = $build_structure{"APPS_${appname}_GUID"};
 323        print F "$SLN_PRE";
 324        my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"};
 325        $vcxproj =~ s/\//\\/g;
 326        $appname =~ s/.*\///;
 327        print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\"";
 328        print F "$SLN_POST";
 329    }
 330    foreach (@libs) {
 331        my $libname = $_;
 332        my $uuid = $build_structure{"LIBS_${libname}_GUID"};
 333        print F "$SLN_PRE";
 334        my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"};
 335        $vcxproj =~ s/\//\\/g;
 336        $libname =~ s/\//_/g;
 337        print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\"";
 338        print F "$SLN_POST";
 339    }
 340
 341    print F << "EOM";
 342Global
 343        GlobalSection(SolutionConfigurationPlatforms) = preSolution
 344                Debug|x64 = Debug|x64
 345                Debug|x86 = Debug|x86
 346                Release|x64 = Release|x64
 347                Release|x86 = Release|x86
 348        EndGlobalSection
 349EOM
 350    print F << "EOM";
 351        GlobalSection(ProjectConfigurationPlatforms) = postSolution
 352EOM
 353    foreach (@apps) {
 354        my $appname = $_;
 355        my $uuid = $build_structure{"APPS_${appname}_GUID"};
 356        print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
 357        print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
 358        print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
 359        print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
 360        print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
 361        print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
 362        print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
 363        print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
 364    }
 365    foreach (@libs) {
 366        my $libname = $_;
 367        my $uuid = $build_structure{"LIBS_${libname}_GUID"};
 368        print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
 369        print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
 370        print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
 371        print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
 372        print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
 373        print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
 374        print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
 375        print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
 376    }
 377
 378    print F << "EOM";
 379        EndGlobalSection
 380        GlobalSection(SolutionProperties) = preSolution
 381                HideSolutionNode = FALSE
 382        EndGlobalSection
 383EndGlobal
 384EOM
 385    close F;
 386}
 387
 3881;