1package Generators::Vcproj;
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 createLibProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure);
28 }
29
30 my @apps = @{$build_structure{"APPS"}};
31 foreach (@apps) {
32 createAppProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure);
33 }
34
35 createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure);
36 return 0;
37}
38
39sub createLibProject {
40 my ($libname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_;
41 print "Generate $libname vcproj lib project\n";
42 $rel_dir = "..\\$rel_dir";
43 $rel_dir =~ s/\//\\/g;
44
45 my $target = $libname;
46 $target =~ s/\//_/g;
47 $target =~ s/\.a//;
48
49 my $uuid = generate_guid($libname);
50 $$build_structure{"LIBS_${target}_GUID"} = $uuid;
51
52 my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"LIBS_${libname}_SOURCES"}}));
53 my @sources;
54 foreach (@srcs) {
55 $_ =~ s/\//\\/g;
56 push(@sources, $_);
57 }
58 my $defines = join(",", sort(@{$$build_structure{"LIBS_${libname}_DEFINES"}}));
59 my $includes= join(";", sort(map(""$rel_dir\\$_"", @{$$build_structure{"LIBS_${libname}_INCLUDES"}})));
60 my $cflags = join(" ", sort(@{$$build_structure{"LIBS_${libname}_CFLAGS"}}));
61 $cflags =~ s/\"/"/g;
62
63 my $cflags_debug = $cflags;
64 $cflags_debug =~ s/-MT/-MTd/;
65 $cflags_debug =~ s/-O.//;
66
67 my $cflags_release = $cflags;
68 $cflags_release =~ s/-MTd/-MT/;
69
70 my @tmp = @{$$build_structure{"LIBS_${libname}_LFLAGS"}};
71 my @tmp2 = ();
72 foreach (@tmp) {
73 if (/^-LTCG/) {
74 } elsif (/^-L/) {
75 $_ =~ s/^-L/-LIBPATH:$rel_dir\//;
76 }
77 push(@tmp2, $_);
78 }
79 my $lflags = join(" ", sort(@tmp));
80
81 $defines =~ s/-D//g;
82 $defines =~ s/\"/\\"/g;
83 $defines =~ s/\'//g;
84 $includes =~ s/-I//g;
85 mkdir "$target" || die "Could not create the directory $target for lib project!\n";
86 open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n";
87 binmode F, ":crlf";
88 print F << "EOM";
89<?xml version="1.0" encoding = "Windows-1252"?>
90<VisualStudioProject
91 ProjectType="Visual C++"
92 Version="9,00"
93 Name="$target"
94 ProjectGUID="$uuid">
95 <Platforms>
96 <Platform
97 Name="Win32"/>
98 </Platforms>
99 <ToolFiles>
100 </ToolFiles>
101 <Configurations>
102 <Configuration
103 Name="Debug|Win32"
104 OutputDirectory="$rel_dir"
105 ConfigurationType="4"
106 CharacterSet="0"
107 IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
108 >
109 <Tool
110 Name="VCPreBuildEventTool"
111 />
112 <Tool
113 Name="VCCustomBuildTool"
114 />
115 <Tool
116 Name="VCXMLDataGeneratorTool"
117 />
118 <Tool
119 Name="VCWebServiceProxyGeneratorTool"
120 />
121 <Tool
122 Name="VCMIDLTool"
123 />
124 <Tool
125 Name="VCCLCompilerTool"
126 AdditionalOptions="$cflags_debug"
127 Optimization="0"
128 InlineFunctionExpansion="1"
129 AdditionalIncludeDirectories="$includes"
130 PreprocessorDefinitions="WIN32,_DEBUG,$defines"
131 MinimalRebuild="true"
132 RuntimeLibrary="1"
133 UsePrecompiledHeader="0"
134 ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
135 WarningLevel="3"
136 DebugInformationFormat="3"
137 />
138 <Tool
139 Name="VCManagedResourceCompilerTool"
140 />
141 <Tool
142 Name="VCResourceCompilerTool"
143 />
144 <Tool
145 Name="VCPreLinkEventTool"
146 />
147 <Tool
148 Name="VCLibrarianTool"
149 SuppressStartupBanner="true"
150 />
151 <Tool
152 Name="VCALinkTool"
153 />
154 <Tool
155 Name="VCXDCMakeTool"
156 />
157 <Tool
158 Name="VCBscMakeTool"
159 />
160 <Tool
161 Name="VCFxCopTool"
162 />
163 <Tool
164 Name="VCPostBuildEventTool"
165 />
166 </Configuration>
167 <Configuration
168 Name="Release|Win32"
169 OutputDirectory="$rel_dir"
170 ConfigurationType="4"
171 CharacterSet="0"
172 WholeProgramOptimization="1"
173 IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
174 >
175 <Tool
176 Name="VCPreBuildEventTool"
177 />
178 <Tool
179 Name="VCCustomBuildTool"
180 />
181 <Tool
182 Name="VCXMLDataGeneratorTool"
183 />
184 <Tool
185 Name="VCWebServiceProxyGeneratorTool"
186 />
187 <Tool
188 Name="VCMIDLTool"
189 />
190 <Tool
191 Name="VCCLCompilerTool"
192 AdditionalOptions="$cflags_release"
193 Optimization="2"
194 InlineFunctionExpansion="1"
195 EnableIntrinsicFunctions="true"
196 AdditionalIncludeDirectories="$includes"
197 PreprocessorDefinitions="WIN32,NDEBUG,$defines"
198 RuntimeLibrary="0"
199 EnableFunctionLevelLinking="true"
200 UsePrecompiledHeader="0"
201 ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
202 WarningLevel="3"
203 DebugInformationFormat="3"
204 />
205 <Tool
206 Name="VCManagedResourceCompilerTool"
207 />
208 <Tool
209 Name="VCResourceCompilerTool"
210 />
211 <Tool
212 Name="VCPreLinkEventTool"
213 />
214 <Tool
215 Name="VCLibrarianTool"
216 SuppressStartupBanner="true"
217 />
218 <Tool
219 Name="VCALinkTool"
220 />
221 <Tool
222 Name="VCXDCMakeTool"
223 />
224 <Tool
225 Name="VCBscMakeTool"
226 />
227 <Tool
228 Name="VCFxCopTool"
229 />
230 <Tool
231 Name="VCPostBuildEventTool"
232 />
233 </Configuration>
234 </Configurations>
235 <Files>
236 <Filter
237 Name="Source Files"
238 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
239 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
240EOM
241 foreach(@sources) {
242 print F << "EOM";
243 <File
244 RelativePath="$_"/>
245EOM
246 }
247 print F << "EOM";
248 </Filter>
249 </Files>
250 <Globals>
251 </Globals>
252</VisualStudioProject>
253EOM
254 close F;
255}
256
257sub createAppProject {
258 my ($appname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_;
259 print "Generate $appname vcproj app project\n";
260 $rel_dir = "..\\$rel_dir";
261 $rel_dir =~ s/\//\\/g;
262
263 my $target = $appname;
264 $target =~ s/\//_/g;
265 $target =~ s/\.exe//;
266
267 my $uuid = generate_guid($appname);
268 $$build_structure{"APPS_${target}_GUID"} = $uuid;
269
270 my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"APPS_${appname}_SOURCES"}}));
271 my @sources;
272 foreach (@srcs) {
273 $_ =~ s/\//\\/g;
274 push(@sources, $_);
275 }
276 my $defines = join(",", sort(@{$$build_structure{"APPS_${appname}_DEFINES"}}));
277 my $includes= join(";", sort(map(""$rel_dir\\$_"", @{$$build_structure{"APPS_${appname}_INCLUDES"}})));
278 my $cflags = join(" ", sort(@{$$build_structure{"APPS_${appname}_CFLAGS"}}));
279 $cflags =~ s/\"/"/g;
280
281 my $cflags_debug = $cflags;
282 $cflags_debug =~ s/-MT/-MTd/;
283 $cflags_debug =~ s/-O.//;
284
285 my $cflags_release = $cflags;
286 $cflags_release =~ s/-MTd/-MT/;
287
288 my $libs;
289 foreach (sort(@{$$build_structure{"APPS_${appname}_LIBS"}})) {
290 $_ =~ s/\//_/g;
291 $libs .= " $_";
292 }
293 my @tmp = @{$$build_structure{"APPS_${appname}_LFLAGS"}};
294 my @tmp2 = ();
295 foreach (@tmp) {
296 if (/^-LTCG/) {
297 } elsif (/^-L/) {
298 $_ =~ s/^-L/-LIBPATH:$rel_dir\//;
299 }
300 push(@tmp2, $_);
301 }
302 my $lflags = join(" ", sort(@tmp)) . " -LIBPATH:$rel_dir";
303
304 $defines =~ s/-D//g;
305 $defines =~ s/\"/\\"/g;
306 $defines =~ s/\'//g;
307 $defines =~ s/\\\\/\\/g;
308 $includes =~ s/-I//g;
309 mkdir "$target" || die "Could not create the directory $target for lib project!\n";
310 open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n";
311 binmode F, ":crlf";
312 print F << "EOM";
313<?xml version="1.0" encoding = "Windows-1252"?>
314<VisualStudioProject
315 ProjectType="Visual C++"
316 Version="9,00"
317 Name="$target"
318 ProjectGUID="$uuid">
319 <Platforms>
320 <Platform
321 Name="Win32"/>
322 </Platforms>
323 <ToolFiles>
324 </ToolFiles>
325 <Configurations>
326 <Configuration
327 Name="Debug|Win32"
328 OutputDirectory="$rel_dir"
329 ConfigurationType="1"
330 CharacterSet="0"
331 IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
332 >
333 <Tool
334 Name="VCPreBuildEventTool"
335 />
336 <Tool
337 Name="VCCustomBuildTool"
338 />
339 <Tool
340 Name="VCXMLDataGeneratorTool"
341 />
342 <Tool
343 Name="VCWebServiceProxyGeneratorTool"
344 />
345 <Tool
346 Name="VCMIDLTool"
347 />
348 <Tool
349 Name="VCCLCompilerTool"
350 AdditionalOptions="$cflags_debug"
351 Optimization="0"
352 InlineFunctionExpansion="1"
353 AdditionalIncludeDirectories="$includes"
354 PreprocessorDefinitions="WIN32,_DEBUG,$defines"
355 MinimalRebuild="true"
356 RuntimeLibrary="1"
357 UsePrecompiledHeader="0"
358 ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
359 WarningLevel="3"
360 DebugInformationFormat="3"
361 />
362 <Tool
363 Name="VCManagedResourceCompilerTool"
364 />
365 <Tool
366 Name="VCResourceCompilerTool"
367 />
368 <Tool
369 Name="VCPreLinkEventTool"
370 />
371 <Tool
372 Name="VCLinkerTool"
373 AdditionalDependencies="$libs"
374 AdditionalOptions="$lflags"
375 LinkIncremental="2"
376 GenerateDebugInformation="true"
377 SubSystem="1"
378 TargetMachine="1"
379 />
380 <Tool
381 Name="VCALinkTool"
382 />
383 <Tool
384 Name="VCXDCMakeTool"
385 />
386 <Tool
387 Name="VCBscMakeTool"
388 />
389 <Tool
390 Name="VCFxCopTool"
391 />
392 <Tool
393 Name="VCPostBuildEventTool"
394 />
395 </Configuration>
396 <Configuration
397 Name="Release|Win32"
398 OutputDirectory="$rel_dir"
399 ConfigurationType="1"
400 CharacterSet="0"
401 WholeProgramOptimization="1"
402 IntermediateDirectory="\$(ProjectDir)\$(ConfigurationName)"
403 >
404 <Tool
405 Name="VCPreBuildEventTool"
406 />
407 <Tool
408 Name="VCCustomBuildTool"
409 />
410 <Tool
411 Name="VCXMLDataGeneratorTool"
412 />
413 <Tool
414 Name="VCWebServiceProxyGeneratorTool"
415 />
416 <Tool
417 Name="VCMIDLTool"
418 />
419 <Tool
420 Name="VCCLCompilerTool"
421 AdditionalOptions="$cflags_release"
422 Optimization="2"
423 InlineFunctionExpansion="1"
424 EnableIntrinsicFunctions="true"
425 AdditionalIncludeDirectories="$includes"
426 PreprocessorDefinitions="WIN32,NDEBUG,$defines"
427 RuntimeLibrary="0"
428 EnableFunctionLevelLinking="true"
429 UsePrecompiledHeader="0"
430 ProgramDataBaseFileName="\$(IntDir)\\\$(TargetName).pdb"
431 WarningLevel="3"
432 DebugInformationFormat="3"
433 />
434 <Tool
435 Name="VCManagedResourceCompilerTool"
436 />
437 <Tool
438 Name="VCResourceCompilerTool"
439 />
440 <Tool
441 Name="VCPreLinkEventTool"
442 />
443 <Tool
444 Name="VCLinkerTool"
445 AdditionalDependencies="$libs"
446 AdditionalOptions="$lflags"
447 LinkIncremental="1"
448 GenerateDebugInformation="true"
449 SubSystem="1"
450 TargetMachine="1"
451 OptimizeReferences="2"
452 EnableCOMDATFolding="2"
453 />
454 <Tool
455 Name="VCALinkTool"
456 />
457 <Tool
458 Name="VCXDCMakeTool"
459 />
460 <Tool
461 Name="VCBscMakeTool"
462 />
463 <Tool
464 Name="VCFxCopTool"
465 />
466 <Tool
467 Name="VCPostBuildEventTool"
468 />
469 </Configuration>
470 </Configurations>
471 <Files>
472 <Filter
473 Name="Source Files"
474 Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
475 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
476EOM
477 foreach(@sources) {
478 print F << "EOM";
479 <File
480 RelativePath="$_"/>
481EOM
482 }
483 print F << "EOM";
484 </Filter>
485 </Files>
486 <Globals>
487 </Globals>
488</VisualStudioProject>
489EOM
490 close F;
491}
492
493sub createGlueProject {
494 my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_;
495 print "Generate solutions file\n";
496 $rel_dir = "..\\$rel_dir";
497 $rel_dir =~ s/\//\\/g;
498 my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 10.00\n# Visual Studio 2008\n";
499 my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = ";
500 my $SLN_POST = "\nEndProject\n";
501
502 my @libs = @{$build_structure{"LIBS"}};
503 my @tmp;
504 foreach (@libs) {
505 $_ =~ s/\//_/g;
506 $_ =~ s/\.a//;
507 push(@tmp, $_);
508 }
509 @libs = @tmp;
510
511 my @apps = @{$build_structure{"APPS"}};
512 @tmp = ();
513 foreach (@apps) {
514 $_ =~ s/\//_/g;
515 $_ =~ s/\.exe//;
516 if ($_ eq "git" ) {
517 unshift(@tmp, $_);
518 } else {
519 push(@tmp, $_);
520 }
521 }
522 @apps = @tmp;
523
524 open F, ">git.sln" || die "Could not open git.sln for writing!\n";
525 binmode F, ":crlf";
526 print F "$SLN_HEAD";
527
528 my $uuid_libgit = $build_structure{"LIBS_libgit_GUID"};
529 my $uuid_xdiff_lib = $build_structure{"LIBS_xdiff_lib_GUID"};
530 foreach (@apps) {
531 my $appname = $_;
532 my $uuid = $build_structure{"APPS_${appname}_GUID"};
533 print F "$SLN_PRE";
534 print F "\"${appname}\", \"${appname}\\${appname}.vcproj\", \"${uuid}\"\n";
535 print F " ProjectSection(ProjectDependencies) = postProject\n";
536 print F " ${uuid_libgit} = ${uuid_libgit}\n";
537 print F " ${uuid_xdiff_lib} = ${uuid_xdiff_lib}\n";
538 print F " EndProjectSection";
539 print F "$SLN_POST";
540 }
541 foreach (@libs) {
542 my $libname = $_;
543 my $uuid = $build_structure{"LIBS_${libname}_GUID"};
544 print F "$SLN_PRE";
545 print F "\"${libname}\", \"${libname}\\${libname}.vcproj\", \"${uuid}\"";
546 print F "$SLN_POST";
547 }
548
549 print F << "EOM";
550Global
551 GlobalSection(SolutionConfigurationPlatforms) = preSolution
552 Debug|Win32 = Debug|Win32
553 Release|Win32 = Release|Win32
554 EndGlobalSection
555EOM
556 print F << "EOM";
557 GlobalSection(ProjectConfigurationPlatforms) = postSolution
558EOM
559 foreach (@apps) {
560 my $appname = $_;
561 my $uuid = $build_structure{"APPS_${appname}_GUID"};
562 print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n";
563 print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n";
564 print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n";
565 print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n";
566 }
567 foreach (@libs) {
568 my $libname = $_;
569 my $uuid = $build_structure{"LIBS_${libname}_GUID"};
570 print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n";
571 print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n";
572 print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n";
573 print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n";
574 }
575
576 print F << "EOM";
577 EndGlobalSection
578EndGlobal
579EOM
580 close F;
581}
582
5831;