403 lines
15 KiB
Perl
403 lines
15 KiB
Perl
package Generators::Vcxproj;
|
|
require Exporter;
|
|
|
|
use strict;
|
|
use vars qw($VERSION);
|
|
use Digest::SHA qw(sha256_hex);
|
|
|
|
our $VERSION = '1.00';
|
|
our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
|
|
@ISA = qw(Exporter);
|
|
|
|
BEGIN {
|
|
push @EXPORT_OK, qw(generate);
|
|
}
|
|
|
|
sub generate_guid ($) {
|
|
my $hex = sha256_hex($_[0]);
|
|
$hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12}).*/{$1-$2-$3-$4-$5}/;
|
|
$hex =~ tr/a-z/A-Z/;
|
|
return $hex;
|
|
}
|
|
|
|
sub generate {
|
|
my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
|
|
my @libs = @{$build_structure{"LIBS"}};
|
|
foreach (@libs) {
|
|
createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 1);
|
|
}
|
|
|
|
my @apps = @{$build_structure{"APPS"}};
|
|
foreach (@apps) {
|
|
createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 0);
|
|
}
|
|
|
|
createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure);
|
|
return 0;
|
|
}
|
|
|
|
sub createProject {
|
|
my ($name, $git_dir, $out_dir, $rel_dir, $build_structure, $static_library) = @_;
|
|
my $label = $static_library ? "lib" : "app";
|
|
my $prefix = $static_library ? "LIBS_" : "APPS_";
|
|
my $config_type = $static_library ? "StaticLibrary" : "Application";
|
|
print "Generate $name vcxproj $label project\n";
|
|
my $cdup = $name;
|
|
$cdup =~ s/[^\/]+/../g;
|
|
$cdup =~ s/\//\\/g;
|
|
$rel_dir = $rel_dir eq "." ? $cdup : "$cdup\\$rel_dir";
|
|
$rel_dir =~ s/\//\\/g;
|
|
|
|
my $target = $name;
|
|
if ($static_library) {
|
|
$target =~ s/\.a//;
|
|
} else {
|
|
$target =~ s/\.exe//;
|
|
}
|
|
|
|
my $uuid = generate_guid($name);
|
|
$$build_structure{"$prefix${target}_GUID"} = $uuid;
|
|
my $vcxproj = $target;
|
|
$vcxproj =~ s/(.*\/)?(.*)/$&\/$2.vcxproj/;
|
|
$vcxproj =~ s/([^\/]*)(\/lib)\/(lib.vcxproj)/$1$2\/$1_$3/;
|
|
$$build_structure{"$prefix${target}_VCXPROJ"} = $vcxproj;
|
|
|
|
my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"$prefix${name}_SOURCES"}}));
|
|
my @sources;
|
|
foreach (@srcs) {
|
|
$_ =~ s/\//\\/g;
|
|
push(@sources, $_);
|
|
}
|
|
my $defines = join(";", sort(@{$$build_structure{"$prefix${name}_DEFINES"}}));
|
|
my $includes= join(";", sort(map { s/^-I//; s/\//\\/g; File::Spec->file_name_is_absolute($_) ? $_ : "$rel_dir\\$_" } @{$$build_structure{"$prefix${name}_INCLUDES"}}));
|
|
my $cflags = join(" ", sort(map { s/^-[GLMOWZ].*//; s/.* .*/"$&"/; $_; } @{$$build_structure{"$prefix${name}_CFLAGS"}}));
|
|
$cflags =~ s/</</g;
|
|
$cflags =~ s/>/>/g;
|
|
|
|
my $libs_release = "\n ";
|
|
my $libs_debug = "\n ";
|
|
if (!$static_library && $name ne 'headless-git') {
|
|
$libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|reftable\/libreftable\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
|
|
$libs_debug = $libs_release;
|
|
$libs_debug =~ s/zlib\.lib/zlibd\.lib/g;
|
|
$libs_debug =~ s/libexpat\.lib/libexpatd\.lib/g;
|
|
$libs_debug =~ s/libcurl\.lib/libcurl-d\.lib/g;
|
|
}
|
|
|
|
$defines =~ s/-D//g;
|
|
$defines =~ s/</</g;
|
|
$defines =~ s/>/>/g;
|
|
$defines =~ s/\'//g;
|
|
|
|
die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
|
|
|
|
open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
|
|
binmode F, ":crlf :utf8";
|
|
print F chr(0xFEFF);
|
|
print F << "EOM";
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
<ItemGroup Label="ProjectConfigurations">
|
|
<ProjectConfiguration Include="Debug|Win32">
|
|
<Configuration>Debug</Configuration>
|
|
<Platform>Win32</Platform>
|
|
</ProjectConfiguration>
|
|
<ProjectConfiguration Include="Release|Win32">
|
|
<Configuration>Release</Configuration>
|
|
<Platform>Win32</Platform>
|
|
</ProjectConfiguration>
|
|
<ProjectConfiguration Include="Debug|x64">
|
|
<Configuration>Debug</Configuration>
|
|
<Platform>x64</Platform>
|
|
</ProjectConfiguration>
|
|
<ProjectConfiguration Include="Release|x64">
|
|
<Configuration>Release</Configuration>
|
|
<Platform>x64</Platform>
|
|
</ProjectConfiguration>
|
|
</ItemGroup>
|
|
<PropertyGroup Label="Globals">
|
|
<ProjectGuid>$uuid</ProjectGuid>
|
|
<Keyword>Win32Proj</Keyword>
|
|
<VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch>
|
|
<VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch>
|
|
<VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory>
|
|
<VCPKGBinDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory>
|
|
<VCPKGLibDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory>
|
|
<VCPKGBinDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\bin</VCPKGBinDirectory>
|
|
<VCPKGLibDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\lib</VCPKGLibDirectory>
|
|
<VCPKGIncludeDirectory>\$(VCPKGArchDirectory)\\include</VCPKGIncludeDirectory>
|
|
<VCPKGLibs Condition="'\$(Configuration)'=='Debug'">$libs_debug</VCPKGLibs>
|
|
<VCPKGLibs Condition="'\$(Configuration)'!='Debug'">$libs_release</VCPKGLibs>
|
|
</PropertyGroup>
|
|
<Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
|
|
<PropertyGroup Condition="'\$(Configuration)'=='Debug'" Label="Configuration">
|
|
<UseDebugLibraries>true</UseDebugLibraries>
|
|
<LinkIncremental>true</LinkIncremental>
|
|
</PropertyGroup>
|
|
<PropertyGroup Condition="'\$(Configuration)'=='Release'" Label="Configuration">
|
|
<UseDebugLibraries>false</UseDebugLibraries>
|
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
</PropertyGroup>
|
|
<PropertyGroup>
|
|
<ConfigurationType>$config_type</ConfigurationType>
|
|
<PlatformToolset>v140</PlatformToolset>
|
|
<!-- <CharacterSet>UTF-8</CharacterSet> -->
|
|
<OutDir>..\\</OutDir>
|
|
<!-- <IntDir>\$(ProjectDir)\$(Configuration)\\</IntDir> -->
|
|
</PropertyGroup>
|
|
<Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" />
|
|
<ImportGroup Label="ExtensionSettings">
|
|
</ImportGroup>
|
|
<ImportGroup Label="Shared">
|
|
</ImportGroup>
|
|
<ImportGroup Label="PropertySheets">
|
|
<Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
</ImportGroup>
|
|
<PropertyGroup Label="UserMacros" />
|
|
<PropertyGroup>
|
|
<GenerateManifest>false</GenerateManifest>
|
|
<EnableManagedIncrementalBuild>true</EnableManagedIncrementalBuild>
|
|
</PropertyGroup>
|
|
<ItemDefinitionGroup>
|
|
<ClCompile>
|
|
<AdditionalOptions>$cflags %(AdditionalOptions)</AdditionalOptions>
|
|
<AdditionalIncludeDirectories>$cdup;$cdup\\compat;$cdup\\compat\\regex;$cdup\\compat\\win32;$cdup\\compat\\poll;$cdup\\compat\\vcbuild\\include;\$(VCPKGIncludeDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
<EnableParallelCodeGeneration />
|
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
|
<PrecompiledHeader />
|
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
|
</ClCompile>
|
|
<Lib>
|
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
|
</Lib>
|
|
<Link>
|
|
<AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
<AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies>
|
|
<AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions>
|
|
<EntryPointSymbol>wmainCRTStartup</EntryPointSymbol>
|
|
<ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile>
|
|
<SubSystem>Console</SubSystem>
|
|
</Link>
|
|
EOM
|
|
if ($target eq 'libgit') {
|
|
print F << "EOM";
|
|
<PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)\\include\\openssl\\ssl.h')">
|
|
<Message>Initialize VCPKG</Message>
|
|
<Command>del "$cdup\\compat\\vcbuild\\vcpkg"</Command>
|
|
<Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat"</Command>
|
|
</PreBuildEvent>
|
|
EOM
|
|
}
|
|
print F << "EOM";
|
|
</ItemDefinitionGroup>
|
|
<ItemDefinitionGroup Condition="'\$(Platform)'=='Win32'">
|
|
<Link>
|
|
<TargetMachine>MachineX86</TargetMachine>
|
|
</Link>
|
|
</ItemDefinitionGroup>
|
|
<ItemDefinitionGroup Condition="'\$(Configuration)'=='Debug'">
|
|
<ClCompile>
|
|
<Optimization>Disabled</Optimization>
|
|
<PreprocessorDefinitions>WIN32;_DEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
|
</ClCompile>
|
|
<Link>
|
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
</Link>
|
|
</ItemDefinitionGroup>
|
|
<ItemDefinitionGroup Condition="'\$(Configuration)'=='Release'">
|
|
<ClCompile>
|
|
<Optimization>MaxSpeed</Optimization>
|
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
<PreprocessorDefinitions>WIN32;NDEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
|
</ClCompile>
|
|
<Link>
|
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
<OptimizeReferences>true</OptimizeReferences>
|
|
</Link>
|
|
</ItemDefinitionGroup>
|
|
<ItemGroup>
|
|
EOM
|
|
foreach(@sources) {
|
|
print F << "EOM";
|
|
<ClCompile Include="$_" />
|
|
EOM
|
|
}
|
|
print F << "EOM";
|
|
</ItemGroup>
|
|
EOM
|
|
if ((!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') && !($name =~ /headless-git/)) {
|
|
my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"};
|
|
my $uuid_libreftable = $$build_structure{"LIBS_reftable/libreftable_GUID"};
|
|
my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"};
|
|
|
|
print F << "EOM";
|
|
<ItemGroup>
|
|
<ProjectReference Include="$cdup\\libgit\\libgit.vcxproj">
|
|
<Project>$uuid_libgit</Project>
|
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
</ProjectReference>
|
|
EOM
|
|
if (!($name =~ /xdiff|libreftable/)) {
|
|
print F << "EOM";
|
|
<ProjectReference Include="$cdup\\reftable\\libreftable\\libreftable.vcxproj">
|
|
<Project>$uuid_libreftable</Project>
|
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
</ProjectReference>
|
|
EOM
|
|
}
|
|
if (!($name =~ 'xdiff')) {
|
|
print F << "EOM";
|
|
<ProjectReference Include="$cdup\\xdiff\\lib\\xdiff_lib.vcxproj">
|
|
<Project>$uuid_xdiff_lib</Project>
|
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
</ProjectReference>
|
|
EOM
|
|
}
|
|
if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) {
|
|
my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"};
|
|
print F << "EOM";
|
|
<ProjectReference Include="$cdup\\vcs-svn\\lib\\vcs-svn_lib.vcxproj">
|
|
<Project>$uuid_vcs_svn_lib</Project>
|
|
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
|
</ProjectReference>
|
|
EOM
|
|
}
|
|
print F << "EOM";
|
|
</ItemGroup>
|
|
EOM
|
|
}
|
|
print F << "EOM";
|
|
<Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" />
|
|
EOM
|
|
if (!$static_library) {
|
|
print F << "EOM";
|
|
<Target Name="${target}_AfterBuild" AfterTargets="AfterBuild">
|
|
<ItemGroup>
|
|
<DLLsAndPDBs Include="\$(VCPKGBinDirectory)\\*.dll;\$(VCPKGBinDirectory)\\*.pdb" />
|
|
</ItemGroup>
|
|
<Copy SourceFiles="@(DLLsAndPDBs)" DestinationFolder="\$(OutDir)" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />
|
|
<MakeDir Directories="..\\templates\\blt\\branches" />
|
|
</Target>
|
|
EOM
|
|
}
|
|
if ($target eq 'git') {
|
|
print F " <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
|
|
}
|
|
if ($target eq 'git-remote-http') {
|
|
print F " <Import Project=\"LinkOrCopyRemoteHttp.targets\" />\n";
|
|
}
|
|
print F << "EOM";
|
|
</Project>
|
|
EOM
|
|
close F;
|
|
}
|
|
|
|
sub createGlueProject {
|
|
my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
|
|
print "Generate solutions file\n";
|
|
$rel_dir = "..\\$rel_dir";
|
|
$rel_dir =~ s/\//\\/g;
|
|
my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n";
|
|
my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = ";
|
|
my $SLN_POST = "\nEndProject\n";
|
|
|
|
my @libs = @{$build_structure{"LIBS"}};
|
|
my @tmp;
|
|
foreach (@libs) {
|
|
$_ =~ s/\.a//;
|
|
push(@tmp, $_);
|
|
}
|
|
@libs = @tmp;
|
|
|
|
my @apps = @{$build_structure{"APPS"}};
|
|
@tmp = ();
|
|
foreach (@apps) {
|
|
$_ =~ s/\.exe//;
|
|
if ($_ eq "git" ) {
|
|
unshift(@tmp, $_);
|
|
} else {
|
|
push(@tmp, $_);
|
|
}
|
|
}
|
|
@apps = @tmp;
|
|
|
|
open F, ">git.sln" || die "Could not open git.sln for writing!\n";
|
|
binmode F, ":crlf :utf8";
|
|
print F chr(0xFEFF);
|
|
print F "$SLN_HEAD";
|
|
|
|
foreach (@apps) {
|
|
my $appname = $_;
|
|
my $uuid = $build_structure{"APPS_${appname}_GUID"};
|
|
print F "$SLN_PRE";
|
|
my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"};
|
|
$vcxproj =~ s/\//\\/g;
|
|
$appname =~ s/.*\///;
|
|
print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\"";
|
|
print F "$SLN_POST";
|
|
}
|
|
foreach (@libs) {
|
|
my $libname = $_;
|
|
my $uuid = $build_structure{"LIBS_${libname}_GUID"};
|
|
print F "$SLN_PRE";
|
|
my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"};
|
|
$vcxproj =~ s/\//\\/g;
|
|
$libname =~ s/\//_/g;
|
|
print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\"";
|
|
print F "$SLN_POST";
|
|
}
|
|
|
|
print F << "EOM";
|
|
Global
|
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
Debug|x64 = Debug|x64
|
|
Debug|x86 = Debug|x86
|
|
Release|x64 = Release|x64
|
|
Release|x86 = Release|x86
|
|
EndGlobalSection
|
|
EOM
|
|
print F << "EOM";
|
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
EOM
|
|
foreach (@apps) {
|
|
my $appname = $_;
|
|
my $uuid = $build_structure{"APPS_${appname}_GUID"};
|
|
print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
|
|
print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
|
|
print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
|
|
print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
|
|
print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
|
|
print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
|
|
print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
|
|
print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
|
|
}
|
|
foreach (@libs) {
|
|
my $libname = $_;
|
|
my $uuid = $build_structure{"LIBS_${libname}_GUID"};
|
|
print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
|
|
print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
|
|
print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
|
|
print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
|
|
print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
|
|
print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
|
|
print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
|
|
print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
|
|
}
|
|
|
|
print F << "EOM";
|
|
EndGlobalSection
|
|
GlobalSection(SolutionProperties) = preSolution
|
|
HideSolutionNode = FALSE
|
|
EndGlobalSection
|
|
EndGlobal
|
|
EOM
|
|
close F;
|
|
}
|
|
|
|
1;
|