1 package Generators::Vcxproj;
6 use Digest::SHA qw(sha256_hex);
9 our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
13 push @EXPORT_OK, qw(generate);
16 sub generate_guid ($) {
17 my $hex = sha256_hex($_[0]);
18 $hex =~ s/^(.{8})(.{4})(.{4})(.{4})(.{12}).*/{$1-$2-$3-$4-$5}/;
24 my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
25 my @libs = @{$build_structure{"LIBS"}};
27 createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 1);
30 my @apps = @{$build_structure{"APPS"}};
32 createProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure, 0);
35 createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure);
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";
46 $cdup =~ s/[^\/]+/../g;
48 $rel_dir = $rel_dir eq "." ? $cdup : "$cdup\\$rel_dir";
49 $rel_dir =~ s/\//\\/g;
52 if ($static_library) {
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;
65 my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"$prefix${name}_SOURCES"}}));
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/</</g;
75 $cflags =~ s/>/>/g;
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/g;
83 $libs_debug =~ s/libcurl\.lib/libcurl-d\.lib/g;
87 $defines =~ s/</</g;
88 $defines =~ s/>/>/g;
91 die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
93 open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
94 binmode F, ":crlf :utf8";
97 <?xml version="1.0" encoding="utf-8"?>
98 <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
99 <ItemGroup Label="ProjectConfigurations">
100 <ProjectConfiguration Include="Debug|Win32">
101 <Configuration>Debug</Configuration>
102 <Platform>Win32</Platform>
103 </ProjectConfiguration>
104 <ProjectConfiguration Include="Release|Win32">
105 <Configuration>Release</Configuration>
106 <Platform>Win32</Platform>
107 </ProjectConfiguration>
108 <ProjectConfiguration Include="Debug|x64">
109 <Configuration>Debug</Configuration>
110 <Platform>x64</Platform>
111 </ProjectConfiguration>
112 <ProjectConfiguration Include="Release|x64">
113 <Configuration>Release</Configuration>
114 <Platform>x64</Platform>
115 </ProjectConfiguration>
117 <PropertyGroup Label="Globals">
118 <ProjectGuid>$uuid</ProjectGuid>
119 <Keyword>Win32Proj</Keyword>
120 <VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch>
121 <VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch>
122 <VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory>
123 <VCPKGBinDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory>
124 <VCPKGLibDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory>
125 <VCPKGBinDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\bin</VCPKGBinDirectory>
126 <VCPKGLibDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\lib</VCPKGLibDirectory>
127 <VCPKGIncludeDirectory>\$(VCPKGArchDirectory)\\include</VCPKGIncludeDirectory>
128 <VCPKGLibs Condition="'\$(Configuration)'=='Debug'">$libs_debug</VCPKGLibs>
129 <VCPKGLibs Condition="'\$(Configuration)'!='Debug'">$libs_release</VCPKGLibs>
131 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
132 <PropertyGroup Condition="'\$(Configuration)'=='Debug'" Label="Configuration">
133 <UseDebugLibraries>true</UseDebugLibraries>
134 <LinkIncremental>true</LinkIncremental>
136 <PropertyGroup Condition="'\$(Configuration)'=='Release'" Label="Configuration">
137 <UseDebugLibraries>false</UseDebugLibraries>
138 <WholeProgramOptimization>true</WholeProgramOptimization>
141 <ConfigurationType>$config_type</ConfigurationType>
142 <PlatformToolset>v140</PlatformToolset>
143 <!-- <CharacterSet>UTF-8</CharacterSet> -->
144 <OutDir>..\\</OutDir>
145 <!-- <IntDir>\$(ProjectDir)\$(Configuration)\\</IntDir> -->
147 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" />
148 <ImportGroup Label="ExtensionSettings">
150 <ImportGroup Label="Shared">
152 <ImportGroup Label="PropertySheets">
153 <Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" />
155 <PropertyGroup Label="UserMacros" />
157 <GenerateManifest>false</GenerateManifest>
158 <EnableManagedIncrementalBuild>true</EnableManagedIncrementalBuild>
160 <ItemDefinitionGroup>
162 <AdditionalOptions>$cflags %(AdditionalOptions)</AdditionalOptions>
163 <AdditionalIncludeDirectories>$cdup;$cdup\\compat;$cdup\\compat\\regex;$cdup\\compat\\win32;$cdup\\compat\\poll;$cdup\\compat\\vcbuild\\include;\$(VCPKGIncludeDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
164 <EnableParallelCodeGeneration />
165 <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
166 <PrecompiledHeader />
167 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
170 <SuppressStartupBanner>true</SuppressStartupBanner>
173 <AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
174 <AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies>
175 <AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions>
176 <EntryPointSymbol>wmainCRTStartup</EntryPointSymbol>
177 <ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile>
178 <SubSystem>Console</SubSystem>
181 if ($target eq 'libgit') {
183 <PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)\\include\\openssl\\ssl.h')">
184 <Message>Initialize VCPKG</Message>
185 <Command>del "$cdup\\compat\\vcbuild\\vcpkg"</Command>
186 <Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat"</Command>
191 </ItemDefinitionGroup>
192 <ItemDefinitionGroup Condition="'\$(Platform)'=='Win32'">
194 <TargetMachine>MachineX86</TargetMachine>
196 </ItemDefinitionGroup>
197 <ItemDefinitionGroup Condition="'\$(Configuration)'=='Debug'">
199 <Optimization>Disabled</Optimization>
200 <PreprocessorDefinitions>WIN32;_DEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
201 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
204 <GenerateDebugInformation>true</GenerateDebugInformation>
206 </ItemDefinitionGroup>
207 <ItemDefinitionGroup Condition="'\$(Configuration)'=='Release'">
209 <Optimization>MaxSpeed</Optimization>
210 <IntrinsicFunctions>true</IntrinsicFunctions>
211 <PreprocessorDefinitions>WIN32;NDEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
212 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
213 <FunctionLevelLinking>true</FunctionLevelLinking>
214 <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
217 <GenerateDebugInformation>true</GenerateDebugInformation>
218 <EnableCOMDATFolding>true</EnableCOMDATFolding>
219 <OptimizeReferences>true</OptimizeReferences>
221 </ItemDefinitionGroup>
226 <ClCompile Include="$_" />
232 if (!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') {
233 my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"};
234 my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"};
238 <ProjectReference Include="$cdup\\libgit\\libgit.vcxproj">
239 <Project>$uuid_libgit</Project>
240 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
243 if (!($name =~ 'xdiff')) {
245 <ProjectReference Include="$cdup\\xdiff\\lib\\xdiff_lib.vcxproj">
246 <Project>$uuid_xdiff_lib</Project>
247 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
251 if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) {
252 my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"};
254 <ProjectReference Include="$cdup\\vcs-svn\\lib\\vcs-svn_lib.vcxproj">
255 <Project>$uuid_vcs_svn_lib</Project>
256 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
265 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" />
267 if (!$static_library) {
269 <Target Name="${target}_AfterBuild" AfterTargets="AfterBuild">
271 <DLLsAndPDBs Include="\$(VCPKGBinDirectory)\\*.dll;\$(VCPKGBinDirectory)\\*.pdb" />
273 <Copy SourceFiles="@(DLLsAndPDBs)" DestinationFolder="\$(OutDir)" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />
274 <MakeDir Directories="..\\templates\\blt\\branches" />
278 if ($target eq 'git') {
279 print F " <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
281 if ($target eq 'git-remote-http') {
282 print F " <Import Project=\"LinkOrCopyRemoteHttp.targets\" />\n";
290 sub createGlueProject {
291 my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
292 print "Generate solutions file\n";
293 $rel_dir = "..\\$rel_dir";
294 $rel_dir =~ s/\//\\/g;
295 my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n";
296 my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = ";
297 my $SLN_POST = "\nEndProject\n";
299 my @libs = @{$build_structure{"LIBS"}};
307 my @apps = @{$build_structure{"APPS"}};
319 open F, ">git.sln" || die "Could not open git.sln for writing!\n";
320 binmode F, ":crlf :utf8";
326 my $uuid = $build_structure{"APPS_${appname}_GUID"};
328 my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"};
329 $vcxproj =~ s/\//\\/g;
330 $appname =~ s/.*\///;
331 print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\"";
336 my $uuid = $build_structure{"LIBS_${libname}_GUID"};
338 my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"};
339 $vcxproj =~ s/\//\\/g;
340 $libname =~ s/\//_/g;
341 print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\"";
347 GlobalSection(SolutionConfigurationPlatforms) = preSolution
348 Debug|x64 = Debug|x64
349 Debug|x86 = Debug|x86
350 Release|x64 = Release|x64
351 Release|x86 = Release|x86
355 GlobalSection(ProjectConfigurationPlatforms) = postSolution
359 my $uuid = $build_structure{"APPS_${appname}_GUID"};
360 print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
361 print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
362 print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
363 print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
364 print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
365 print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
366 print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
367 print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
371 my $uuid = $build_structure{"LIBS_${libname}_GUID"};
372 print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
373 print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
374 print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
375 print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
376 print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
377 print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
378 print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
379 print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
384 GlobalSection(SolutionProperties) = preSolution
385 HideSolutionNode = FALSE