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