]>
Commit | Line | Data |
---|---|---|
384a61bc JS |
1 | package Generators::Vcxproj; |
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 | 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 | ||
39 | sub 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/</</g; | |
75 | $cflags =~ s/>/>/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/</</g; | |
89 | $defines =~ s/>/>/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> | |
181 | EOM | |
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> | |
189 | EOM | |
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> | |
224 | EOM | |
225 | foreach(@sources) { | |
226 | print F << "EOM"; | |
227 | <ClCompile Include="$_" /> | |
228 | EOM | |
229 | } | |
230 | print F << "EOM"; | |
231 | </ItemGroup> | |
232 | EOM | |
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> | |
244 | EOM | |
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> | |
251 | EOM | |
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> | |
259 | EOM | |
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> | |
268 | EOM | |
269 | } | |
270 | print F << "EOM"; | |
271 | </ItemGroup> | |
272 | EOM | |
273 | } | |
274 | print F << "EOM"; | |
275 | <Import Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets" /> | |
276 | EOM | |
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> | |
286 | EOM | |
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> | |
296 | EOM | |
297 | close F; | |
298 | } | |
299 | ||
300 | sub 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"; | |
356 | Global | |
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 | |
363 | EOM | |
364 | print F << "EOM"; | |
365 | GlobalSection(ProjectConfigurationPlatforms) = postSolution | |
366 | EOM | |
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 | |
397 | EndGlobal | |
398 | EOM | |
399 | close F; | |
400 | } | |
401 | ||
402 | 1; |