]> git.ipfire.org Git - thirdparty/git.git/blame - contrib/buildsystems/Generators/Vcxproj.pm
Merge branch 'mp/rebase-label-length-limit' into maint-2.42
[thirdparty/git.git] / contrib / buildsystems / Generators / Vcxproj.pm
CommitLineData
384a61bc
JS
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 ";
4b8a2717 79 if (!$static_library && $name ne 'headless-git') {
ef8a6c62 80 $libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|reftable\/libreftable\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
384a61bc 81 $libs_debug = $libs_release;
fe0ed5d5 82 $libs_debug =~ s/zlib\.lib/zlibd\.lib/g;
e58e4055 83 $libs_debug =~ s/libexpat\.lib/libexpatd\.lib/g;
fe0ed5d5 84 $libs_debug =~ s/libcurl\.lib/libcurl-d\.lib/g;
384a61bc
JS
85 }
86
87 $defines =~ s/-D//g;
88 $defines =~ s/</&lt;/g;
89 $defines =~ s/>/&gt;/g;
90 $defines =~ s/\'//g;
91
92 die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
93
94 open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
95 binmode F, ":crlf :utf8";
96 print F chr(0xFEFF);
97 print F << "EOM";
98<?xml version="1.0" encoding="utf-8"?>
99<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
100 <ItemGroup Label="ProjectConfigurations">
101 <ProjectConfiguration Include="Debug|Win32">
102 <Configuration>Debug</Configuration>
103 <Platform>Win32</Platform>
104 </ProjectConfiguration>
105 <ProjectConfiguration Include="Release|Win32">
106 <Configuration>Release</Configuration>
107 <Platform>Win32</Platform>
108 </ProjectConfiguration>
109 <ProjectConfiguration Include="Debug|x64">
110 <Configuration>Debug</Configuration>
111 <Platform>x64</Platform>
112 </ProjectConfiguration>
113 <ProjectConfiguration Include="Release|x64">
114 <Configuration>Release</Configuration>
115 <Platform>x64</Platform>
116 </ProjectConfiguration>
117 </ItemGroup>
118 <PropertyGroup Label="Globals">
119 <ProjectGuid>$uuid</ProjectGuid>
120 <Keyword>Win32Proj</Keyword>
121 <VCPKGArch Condition="'\$(Platform)'=='Win32'">x86-windows</VCPKGArch>
122 <VCPKGArch Condition="'\$(Platform)'!='Win32'">x64-windows</VCPKGArch>
123 <VCPKGArchDirectory>$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)</VCPKGArchDirectory>
fe0ed5d5
AM
124 <VCPKGBinDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\bin</VCPKGBinDirectory>
125 <VCPKGLibDirectory Condition="'\$(Configuration)'=='Debug'">\$(VCPKGArchDirectory)\\debug\\lib</VCPKGLibDirectory>
126 <VCPKGBinDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\bin</VCPKGBinDirectory>
127 <VCPKGLibDirectory Condition="'\$(Configuration)'!='Debug'">\$(VCPKGArchDirectory)\\lib</VCPKGLibDirectory>
384a61bc 128 <VCPKGIncludeDirectory>\$(VCPKGArchDirectory)\\include</VCPKGIncludeDirectory>
fe0ed5d5
AM
129 <VCPKGLibs Condition="'\$(Configuration)'=='Debug'">$libs_debug</VCPKGLibs>
130 <VCPKGLibs Condition="'\$(Configuration)'!='Debug'">$libs_release</VCPKGLibs>
384a61bc
JS
131 </PropertyGroup>
132 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />
133 <PropertyGroup Condition="'\$(Configuration)'=='Debug'" Label="Configuration">
134 <UseDebugLibraries>true</UseDebugLibraries>
135 <LinkIncremental>true</LinkIncremental>
136 </PropertyGroup>
137 <PropertyGroup Condition="'\$(Configuration)'=='Release'" Label="Configuration">
138 <UseDebugLibraries>false</UseDebugLibraries>
139 <WholeProgramOptimization>true</WholeProgramOptimization>
140 </PropertyGroup>
141 <PropertyGroup>
142 <ConfigurationType>$config_type</ConfigurationType>
143 <PlatformToolset>v140</PlatformToolset>
144 <!-- <CharacterSet>UTF-8</CharacterSet> -->
145 <OutDir>..\\</OutDir>
146 <!-- <IntDir>\$(ProjectDir)\$(Configuration)\\</IntDir> -->
147 </PropertyGroup>
148 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.props" />
149 <ImportGroup Label="ExtensionSettings">
150 </ImportGroup>
151 <ImportGroup Label="Shared">
152 </ImportGroup>
153 <ImportGroup Label="PropertySheets">
154 <Import Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" Label="LocalAppDataPlatform" />
155 </ImportGroup>
156 <PropertyGroup Label="UserMacros" />
157 <PropertyGroup>
158 <GenerateManifest>false</GenerateManifest>
159 <EnableManagedIncrementalBuild>true</EnableManagedIncrementalBuild>
160 </PropertyGroup>
161 <ItemDefinitionGroup>
162 <ClCompile>
163 <AdditionalOptions>$cflags %(AdditionalOptions)</AdditionalOptions>
164 <AdditionalIncludeDirectories>$cdup;$cdup\\compat;$cdup\\compat\\regex;$cdup\\compat\\win32;$cdup\\compat\\poll;$cdup\\compat\\vcbuild\\include;\$(VCPKGIncludeDirectory);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
165 <EnableParallelCodeGeneration />
166 <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
167 <PrecompiledHeader />
168 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
169 </ClCompile>
170 <Lib>
171 <SuppressStartupBanner>true</SuppressStartupBanner>
172 </Lib>
173 <Link>
174 <AdditionalLibraryDirectories>\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
175 <AdditionalDependencies>\$(VCPKGLibs);\$(AdditionalDependencies)</AdditionalDependencies>
176 <AdditionalOptions>invalidcontinue.obj %(AdditionalOptions)</AdditionalOptions>
177 <EntryPointSymbol>wmainCRTStartup</EntryPointSymbol>
178 <ManifestFile>$cdup\\compat\\win32\\git.manifest</ManifestFile>
179 <SubSystem>Console</SubSystem>
180 </Link>
181EOM
182 if ($target eq 'libgit') {
183 print F << "EOM";
184 <PreBuildEvent Condition="!Exists('$cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch)\\include\\openssl\\ssl.h')">
185 <Message>Initialize VCPKG</Message>
186 <Command>del "$cdup\\compat\\vcbuild\\vcpkg"</Command>
187 <Command>call "$cdup\\compat\\vcbuild\\vcpkg_install.bat"</Command>
188 </PreBuildEvent>
189EOM
190 }
191 print F << "EOM";
192 </ItemDefinitionGroup>
193 <ItemDefinitionGroup Condition="'\$(Platform)'=='Win32'">
194 <Link>
195 <TargetMachine>MachineX86</TargetMachine>
196 </Link>
197 </ItemDefinitionGroup>
198 <ItemDefinitionGroup Condition="'\$(Configuration)'=='Debug'">
199 <ClCompile>
200 <Optimization>Disabled</Optimization>
201 <PreprocessorDefinitions>WIN32;_DEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
202 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
203 </ClCompile>
204 <Link>
205 <GenerateDebugInformation>true</GenerateDebugInformation>
206 </Link>
207 </ItemDefinitionGroup>
208 <ItemDefinitionGroup Condition="'\$(Configuration)'=='Release'">
209 <ClCompile>
210 <Optimization>MaxSpeed</Optimization>
211 <IntrinsicFunctions>true</IntrinsicFunctions>
212 <PreprocessorDefinitions>WIN32;NDEBUG;$defines;%(PreprocessorDefinitions)</PreprocessorDefinitions>
213 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
214 <FunctionLevelLinking>true</FunctionLevelLinking>
215 <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
216 </ClCompile>
217 <Link>
218 <GenerateDebugInformation>true</GenerateDebugInformation>
219 <EnableCOMDATFolding>true</EnableCOMDATFolding>
220 <OptimizeReferences>true</OptimizeReferences>
221 </Link>
222 </ItemDefinitionGroup>
223 <ItemGroup>
224EOM
225 foreach(@sources) {
226 print F << "EOM";
227 <ClCompile Include="$_" />
228EOM
229 }
230 print F << "EOM";
231 </ItemGroup>
232EOM
4b8a2717 233 if ((!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') && !($name =~ /headless-git/)) {
384a61bc 234 my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"};
ef8a6c62 235 my $uuid_libreftable = $$build_structure{"LIBS_reftable/libreftable_GUID"};
384a61bc
JS
236 my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"};
237
238 print F << "EOM";
239 <ItemGroup>
240 <ProjectReference Include="$cdup\\libgit\\libgit.vcxproj">
241 <Project>$uuid_libgit</Project>
242 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
243 </ProjectReference>
244EOM
ef8a6c62
HWN
245 if (!($name =~ /xdiff|libreftable/)) {
246 print F << "EOM";
247 <ProjectReference Include="$cdup\\reftable\\libreftable\\libreftable.vcxproj">
248 <Project>$uuid_libreftable</Project>
249 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
250 </ProjectReference>
251EOM
252 }
384a61bc
JS
253 if (!($name =~ 'xdiff')) {
254 print F << "EOM";
255 <ProjectReference Include="$cdup\\xdiff\\lib\\xdiff_lib.vcxproj">
256 <Project>$uuid_xdiff_lib</Project>
257 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
258 </ProjectReference>
259EOM
260 }
261 if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) {
262 my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"};
263 print F << "EOM";
264 <ProjectReference Include="$cdup\\vcs-svn\\lib\\vcs-svn_lib.vcxproj">
265 <Project>$uuid_vcs_svn_lib</Project>
266 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
267 </ProjectReference>
268EOM
269 }
270 print F << "EOM";
271 </ItemGroup>
272EOM
273 }
274 print F << "EOM";
275 <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" />
276EOM
277 if (!$static_library) {
278 print F << "EOM";
279 <Target Name="${target}_AfterBuild" AfterTargets="AfterBuild">
280 <ItemGroup>
281 <DLLsAndPDBs Include="\$(VCPKGBinDirectory)\\*.dll;\$(VCPKGBinDirectory)\\*.pdb" />
282 </ItemGroup>
283 <Copy SourceFiles="@(DLLsAndPDBs)" DestinationFolder="\$(OutDir)" SkipUnchangedFiles="true" UseHardlinksIfPossible="true" />
284 <MakeDir Directories="..\\templates\\blt\\branches" />
285 </Target>
286EOM
287 }
b18ae14a
JS
288 if ($target eq 'git') {
289 print F " <Import Project=\"LinkOrCopyBuiltins.targets\" />\n";
290 }
030a628b
JS
291 if ($target eq 'git-remote-http') {
292 print F " <Import Project=\"LinkOrCopyRemoteHttp.targets\" />\n";
293 }
384a61bc
JS
294 print F << "EOM";
295</Project>
296EOM
297 close F;
298}
299
300sub createGlueProject {
301 my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
302 print "Generate solutions file\n";
303 $rel_dir = "..\\$rel_dir";
304 $rel_dir =~ s/\//\\/g;
305 my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n";
306 my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = ";
307 my $SLN_POST = "\nEndProject\n";
308
309 my @libs = @{$build_structure{"LIBS"}};
310 my @tmp;
311 foreach (@libs) {
312 $_ =~ s/\.a//;
313 push(@tmp, $_);
314 }
315 @libs = @tmp;
316
317 my @apps = @{$build_structure{"APPS"}};
318 @tmp = ();
319 foreach (@apps) {
320 $_ =~ s/\.exe//;
321 if ($_ eq "git" ) {
322 unshift(@tmp, $_);
323 } else {
324 push(@tmp, $_);
325 }
326 }
327 @apps = @tmp;
328
329 open F, ">git.sln" || die "Could not open git.sln for writing!\n";
330 binmode F, ":crlf :utf8";
331 print F chr(0xFEFF);
332 print F "$SLN_HEAD";
333
334 foreach (@apps) {
335 my $appname = $_;
336 my $uuid = $build_structure{"APPS_${appname}_GUID"};
337 print F "$SLN_PRE";
338 my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"};
339 $vcxproj =~ s/\//\\/g;
340 $appname =~ s/.*\///;
341 print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\"";
342 print F "$SLN_POST";
343 }
344 foreach (@libs) {
345 my $libname = $_;
346 my $uuid = $build_structure{"LIBS_${libname}_GUID"};
347 print F "$SLN_PRE";
348 my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"};
349 $vcxproj =~ s/\//\\/g;
350 $libname =~ s/\//_/g;
351 print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\"";
352 print F "$SLN_POST";
353 }
354
355 print F << "EOM";
356Global
357 GlobalSection(SolutionConfigurationPlatforms) = preSolution
358 Debug|x64 = Debug|x64
359 Debug|x86 = Debug|x86
360 Release|x64 = Release|x64
361 Release|x86 = Release|x86
362 EndGlobalSection
363EOM
364 print F << "EOM";
365 GlobalSection(ProjectConfigurationPlatforms) = postSolution
366EOM
367 foreach (@apps) {
368 my $appname = $_;
369 my $uuid = $build_structure{"APPS_${appname}_GUID"};
370 print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
371 print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
372 print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
373 print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
374 print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
375 print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
376 print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
377 print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
378 }
379 foreach (@libs) {
380 my $libname = $_;
381 my $uuid = $build_structure{"LIBS_${libname}_GUID"};
382 print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n";
383 print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n";
384 print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n";
385 print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n";
386 print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n";
387 print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n";
388 print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n";
389 print F "\t\t${uuid}.Release|x86.Build.0 = Release|Win32\n";
390 }
391
392 print F << "EOM";
393 EndGlobalSection
394 GlobalSection(SolutionProperties) = preSolution
395 HideSolutionNode = FALSE
396 EndGlobalSection
397EndGlobal
398EOM
399 close F;
400}
401
4021;