Vcproj.pm: auto-generate GUIDs
[git] / contrib / buildsystems / Generators / Vcproj.pm
1 package Generators::Vcproj;
2 require Exporter;
3
4 use strict;
5 use vars qw($VERSION);
6 use Digest::SHA qw(sha256_hex);
7
8 our $VERSION = '1.00';
9 our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE);
10 @ISA = qw(Exporter);
11
12 BEGIN {
13     push @EXPORT_OK, qw(generate);
14 }
15
16 sub 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
23 sub 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
39 sub 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}">
240 EOM
241     foreach(@sources) {
242         print F << "EOM";
243                         <File
244                                 RelativePath="$_"/>
245 EOM
246     }
247     print F << "EOM";
248                 </Filter>
249         </Files>
250         <Globals>
251         </Globals>
252 </VisualStudioProject>
253 EOM
254     close F;
255 }
256
257 sub 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("&quot;$rel_dir\\$_&quot;", @{$$build_structure{"APPS_${appname}_INCLUDES"}})));
278     my $cflags  = join(" ", sort(@{$$build_structure{"APPS_${appname}_CFLAGS"}}));
279     $cflags =~ s/\"/&quot;/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/\"/\\&quot;/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}">
476 EOM
477     foreach(@sources) {
478         print F << "EOM";
479                         <File
480                                 RelativePath="$_"/>
481 EOM
482     }
483     print F << "EOM";
484                 </Filter>
485         </Files>
486         <Globals>
487         </Globals>
488 </VisualStudioProject>
489 EOM
490     close F;
491 }
492
493 sub 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         push(@tmp, $_);
517     }
518     @apps = @tmp;
519
520     open F, ">git.sln" || die "Could not open git.sln for writing!\n";
521     binmode F, ":crlf";
522     print F "$SLN_HEAD";
523     foreach (@libs) {
524         my $libname = $_;
525         my $uuid = $build_structure{"LIBS_${libname}_GUID"};
526         print F "$SLN_PRE";
527         print F "\"${libname}\", \"${libname}\\${libname}.vcproj\", \"${uuid}\"";
528         print F "$SLN_POST";
529     }
530     my $uuid_libgit = $build_structure{"LIBS_libgit_GUID"};
531     my $uuid_xdiff_lib = $build_structure{"LIBS_xdiff_lib_GUID"};
532     foreach (@apps) {
533         my $appname = $_;
534         my $uuid = $build_structure{"APPS_${appname}_GUID"};
535         print F "$SLN_PRE";
536         print F "\"${appname}\", \"${appname}\\${appname}.vcproj\", \"${uuid}\"\n";
537         print F "       ProjectSection(ProjectDependencies) = postProject\n";
538         print F "               ${uuid_libgit} = ${uuid_libgit}\n";
539         print F "               ${uuid_xdiff_lib} = ${uuid_xdiff_lib}\n";
540         print F "       EndProjectSection";
541         print F "$SLN_POST";
542     }
543
544     print F << "EOM";
545 Global
546         GlobalSection(SolutionConfigurationPlatforms) = preSolution
547                 Debug|Win32 = Debug|Win32
548                 Release|Win32 = Release|Win32
549         EndGlobalSection
550 EOM
551     print F << "EOM";
552         GlobalSection(ProjectConfigurationPlatforms) = postSolution
553 EOM
554     foreach (@libs) {
555         my $libname = $_;
556         my $uuid = $build_structure{"LIBS_${libname}_GUID"};
557         print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n";
558         print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n";
559         print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n";
560         print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n";
561     }
562     foreach (@apps) {
563         my $appname = $_;
564         my $uuid = $build_structure{"APPS_${appname}_GUID"};
565         print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n";
566         print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n";
567         print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n";
568         print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n";
569     }
570
571     print F << "EOM";
572         EndGlobalSection
573 EndGlobal
574 EOM
575     close F;
576 }
577
578 1;