]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/kaldi.git/blob - windows/generate_solution.pl
[build] Change to compilation flags for Sequitur on Mac (#1716)
[processor-sdk/kaldi.git] / windows / generate_solution.pl
1 #!/usr/bin/perl
3 #
4 # Copyright:2012-2015 Jan Silovsky
5 #           2015 Johns Hopkins University (Author: Jan "Yenda" Trmal <jtrmal@gmail.com>)
7 # Licence: Apache 2.0
8 # Copyright Jan Silovsky.
9 # Modifications and small bugfixes by Jan "Yenda" Trmal
11 # This program generates the Visual Studio solution file.
12 # Note, this program has been tested with both cygwin and
13 # Windows (ActiveState perl) versions of Perl
15 use strict;
16 use File::Find;
17 use File::Path;
18 use File::Copy;
19 use FindBin qw($Bin);
20 use lib "$Bin";
21 use Data::Dumper;
22 use Getopt::Long;
24 my $vsver="vs2013";
26 my %ENABLED = (CUDA => 0,
27                OPENBLAS => 0,
28                MKL => 1 );
30 GetOptions ("vsver=s" => \$vsver,
31             "enable-cuda" => \$ENABLED{CUDA},
32                         "enable-openblas" => sub {$ENABLED{OPENBLAS}=1; $ENABLED{MKL}=0;},
33                         "enable-mkl" => sub {$ENABLED{OPENBLAS}=0; $ENABLED{MKL}=1;},
34                         );
36 my %TOOLS=( default=>  "4.0",
37             vs2013 => "12.0",
38             vs2015 => "14.0");
40 my %FORMAT=( default=> "11.00",
41              vs2013 =>  "12.00",
42              vs2015 =>  "14.00");
44 my %TOOLSET=( default=> "v100",
45               vs2013 => "v120",
46               vs2015 => "v140");
49 unless ((defined $TOOLS{$vsver}) && (defined $FORMAT{$vsver}) && (defined $TOOLSET{$vsver})) {
50         die "Unknown vsver value: $vsver";
51 }
53 my $features_suffix;
54 my @features_enabled;
56 if ($ENABLED{OPENBLAS}) {
57   push @features_enabled, "OPENBLAS";
58 }
59 if ($ENABLED{MKL}) {
60   push @features_enabled, "MKL";
61 }
62 if ($ENABLED{CUDA}) {
63   push @features_enabled, "CUDA";
64 }
66 $features_suffix = join("_", @features_enabled);
68 my $root = "$Bin/..";
69 my $solutionDir = "$root/kaldiwin_${vsver}_${features_suffix}";
70 my $projDir = "$solutionDir/kaldiwin";
71 my $solutionFileName = "kaldiwin_${vsver}.sln";
72 my $srcDir = "$root/src";
75 # The following files are in the same dir (windows/) as the
76 # Perl script.
77 my @propsFiles = (
78   "$Bin/variables.props",
79   "$Bin/kaldiwin.props",
80   "$Bin/kaldiwin_win32.props",
81   "$Bin/openfstwin_debug.props",
82   "$Bin/openfstwin_release.props",
83   "$Bin/openfstwin_debug_win32.props",
84   "$Bin/openfstwin_release_win32.props",
85 );
87 my %optionalProps = (
88         CUDA => "$Bin/cuda_7.0.props"
89         );
91 # see http://www.mztools.com/Articles/2008/MZ2008017.aspx for list of GUIDs for VS solutions
92 my $globalGUID = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";  # Windows (Visual C++)
94 my $projguidListFileName = "$Bin/kaldiwin_projguids.txt";
95 my $guidgen = "$Bin/NewGuidCmd.exe";  # it is C# application
97 my $osPathConversion = \&winPath;
98 if ($^O !~ /MSWin32/i) {
99   $osPathConversion = \&unixPath;
102 # function
103 sub winPath {
104   my $path = shift;
105   $path =~ s/\//\\/g;
106   return $path;
109 # function
110 sub unixPath {
111   my $path = shift;
112   $path =~ s/\\/\//g;
113   return $path;
116 # function
117 sub removeStartSlash {
118   my $path = shift;
119   $path =~ s/^[\\\/]//;
120   return $path;
123 sub makeRelPath {
124   my $path = winPath(shift);
125   my $actual_path = winPath(shift);
126   my $relpath = '';
128   $path =~ s/\\cygdrive\\(.)\\/$1:\\/;
129   $actual_path =~ s/\\cygdrive\\(.)\\/$1:\\/;
131   #$path =~ s/[\\\/]+[^\\\/]*$//;
132   $actual_path =~ s/[\\\/]+[^\\\/]*$//;
134   my @path = split /\\+/, $path;
135   my @actual_path = split /\\+/, $actual_path;
137   my $i = 0;
138   for ($i; $i < @actual_path; $i++) {
139     # the zero-length condition may seem ackward, but it solves encountered troubles when two empty string were evaluated as different
140     # the case-insensitive comparison is used because of Windows filesystem case-insensitivity
141     if (($path[$i] !~ /$actual_path[$i]/i) && (length($path[$i]) > 0) && (length($actual_path[$i]) > 0)) {
142       last;
143     }
144   }
145   my $j = $i;
146   for ($i; $i < @actual_path; $i++) {
147     $relpath .= "..\\";
148   }
149   for ($j; $j < (@path - 1); $j++) {
150     $relpath .= $path[$j] . "\\";
151   }
152   $relpath .= $path[$j];
154   return $relpath;
157 # function
158 sub checkCRLF {
159   my $filename = shift;
161   if ($^O =~ /MSWin32/i) {
162     print "INFO: function checkCRLF supported only for non-Win environment\n";
163     return;
164   }
166   open(FILE, '<', $filename);
167   my @data = <FILE>;
168   close(FILE);
170   open(FILE, '>', $filename);
171   foreach my $line (@data) {
172     $line =~ s/(\n|\r\n)$//;
173     print FILE $line . "\r\n";
174   }
175   close(FILE);
178 # function
179 sub loadHashTxtFile {
180   my $filename = shift;
181   my $hash = shift;
183   open(FILE, '<', &{$osPathConversion}($filename));
184   while (my $line = <FILE>) {
185     $line =~ s/(\n|\r\n)$//;
186     if (my ($key, $value) = $line =~ /^(\S+)\s+(\S+)$/) {
187       $hash->{$key} = $value;
188     } else {
189       print STDERR "ERROR: unable to parse line $line in file $filename\n";
190     }
191   }
192   close(FILE);
195 # function
196 sub saveHashTxtFile {
197   my $filename = shift;
198   my $hash = shift;
200   open(FILE, '>', &{$osPathConversion}($filename));
201   foreach my $key (sort { $a cmp $b } keys %$hash) {
202     print FILE $key . "\t" . $hash->{$key} . "\n";
203   }
204   close(FILE);
207 # function
208 sub parseMakefile {
209   my $makefile = shift;
210   my $list = shift;
211   my $deps = shift;
212   my $libs = shift;
214   my $file = $makefile;
215   my $path = $file;
216   $path =~ s/Makefile$//i;
218   open(FILE, '<', &{$osPathConversion}($file));
219   my @lines = <FILE>;
220   close(FILE);
222   my $lines = join '', @lines;
223   $lines =~ s/#[^\n]+//g;
224   $lines =~ s/\\\s*\n//g;
225   if ($ENABLED{CUDA}) {
226     $lines =~ s/\n\s*ifeq\s+\(\$\(CUDA\),\strue\)\s*\n\s*OBJFILES\s*\+=\s*([^\n]+)\n\s*endif/\nOBJFILES = \1/gmi
227   }
228   @lines = split /\n/, $lines;
229   #$lines =~ s/\\//g;
230   #$lines =~ s/\n/\\/g;
231   #print $lines . "\n";
232   #@lines = split /\\/, $lines;
234   my $aobjects = {};
235   my $alibs = {};
236   foreach my $line (@lines) {
237     $line =~ s/(\n|\r\n)$//;
239     if (my ($type, $items) = $line =~ /^\s*(TESTFILES|LIBNAME|BINFILES)\s+=(.+?)$/) {
240       #my @items = split /\s+/, $items;
241       my @items = $items =~ /(\S+)/g;
242       foreach my $item (@items) {
243         # $item =~ s/\.a$//i;
245         $list->{$type}->{$item} = 1;
246         $list->{ALL}->{$item}->{'type'} = $type;
247         $list->{ALL}->{$item}->{'path'} = $path;
249         if ($type =~ /LIBNAME/) {
250           $alibs->{$item} = 1;
251         }
252       }
253     }
255     if (my ($items) = $line =~ /^ADDLIBS[^=]*?=(.+?)$/) {
256           my @items = $items =~ /(\S+)/g;
258           foreach my $alib (keys %$alibs) {
259                 $deps->{$path}->{$alib} = 1;
260           }
261       foreach my $item (@items) {
262         $item =~ s/^.*[\\\/]//;
263         $item =~ s/\.[^\.]*$//;
265         $deps->{$path}->{$item} = 1;
267       }
268     }
270     if (my ($type, $items) = $line =~ /^\s*(OBJFILES)\s+=(.+?)$/) {
271       my @items = $items =~ /(\S+)/g;
272       foreach my $item (@items) {
273         $aobjects->{$item} = 1;
274       }
275     }
276   }
278   if (scalar keys %{$aobjects} > 0) {
279     if (scalar keys %{$alibs} != 1) {
280       print STDERR "ERROR: less or more than one libfile, cannot assign aobjects\n";
281     } else {
282       my $alib = join('', keys %{$alibs}); # $alibs obsahuje nazev pouze jedne knihovny
283       foreach my $obj (keys %{$aobjects}) {
284         $obj =~ s/\.o$//i;
285         $list->{ALL}->{$alib}->{'objs'}->{$obj} = 1;
286       }
287     }
288   }
291 # function
292 sub makefileFilter {
293   if ($_ =~ /Makefile/) { return 1; }
296 # function
297 sub getProjFileDir {
298   my $projname = shift;
299   my $projFileName = $projDir . "/$projname";
300   return $projFileName;
303 # function
304 sub writeSolutionFile {
305   my $filename = shift;
306   my $projlist = shift;
307   my $projguids = shift;
309   open(SLN, '>', &{$osPathConversion}($filename));
310   print SLN
311 "Microsoft Visual Studio Solution File, Format Version $FORMAT{$vsver}
312 # Visual Studio 2013
313 ";
314   foreach my $projname (sort { $a cmp $b } keys %{$projlist->{ALL}}) {
315     if (!exists $projguids->{$projname}) {
316       my $cmd = "$guidgen";
317       my $guid = `$cmd`;
318       $guid =~ s/(\n|\r\n)$//;
319       $projguids->{$projname} = uc('{' . $guid . '}');
320     }
321     my $guid = $projguids->{$projname};
322     $projlist->{ALL}->{$projname}->{'guid'} = $guid;
323     my $projFileName = winPath(makeRelPath(getProjFileDir($projname), $filename) . "/$projname.vcxproj");
324     print SLN
325 "Project(\"$globalGUID\") = \"$projname\", \"$projFileName\", \"$guid\"
326 EndProject
327 ";
328   }
329   print SLN
330 "Global
331         GlobalSection(SolutionConfigurationPlatforms) = preSolution
332                 Debug|x64 = Debug|x64
333                 Debug|Win32 = Debug|Win32
334                 Release|x64 = Release|x64
335                 Release|Win32 = Release|Win32
336         EndGlobalSection
337         GlobalSection(ProjectConfigurationPlatforms) = postSolution
338 ";
339   foreach my $projname (sort { $a cmp $b } keys %{$projlist->{ALL}}) {
340     my $guid = $projlist->{ALL}->{$projname}->{'guid'};
341     print SLN
342 "               $guid.Debug|Win32.ActiveCfg = Debug|Win32
343                 $guid.Debug|Win32.Build.0 = Debug|Win32
344                 $guid.Debug|x64.ActiveCfg = Debug|x64
345                 $guid.Debug|x64.Build.0 = Debug|x64
346                 $guid.Release|Win32.ActiveCfg = Release|Win32
347                 $guid.Release|Win32.Build.0 = Release|Win32
348                 $guid.Release|x64.ActiveCfg = Release|x64
349                 $guid.Release|x64.Build.0 = Release|x64
350 ";
351   }
352   print SLN
353 "       EndGlobalSection
354         GlobalSection(SolutionProperties) = preSolution
355                 HideSolutionNode = FALSE
356         EndGlobalSection
357 EndGlobal
358 ";
359   close(SLN);
362 # function
363 sub writeProjectFiles {
364   my $projname = shift;
365   my $projlist = shift;
366   my $projdeps = shift;
367   my $projlibs = shift;
368   my $projguids = shift;
370   my $projFileName = winPath(getProjFileDir($projname) . "/$projname.vcxproj");
372   my $guid = $projguids->{$projname};
373   my $rootnamespace = $projname;
374   $rootnamespace =~ s/\W+//g;
375   my $srcfiles = {};
376   my $conftype = "";
378   # set projtype-specific params and add .cc files
379   if ($projlist->{ALL}->{$projname}->{'type'} =~ /LIBNAME/) {
380     $conftype = "StaticLibrary";
382     foreach my $obj (keys %{$projlist->{ALL}->{$projname}->{'objs'}}) {
383       my $cfile = winPath($projlist->{ALL}->{$projname}->{'path'} . $obj . '.cc');
384           if (!-e &{$osPathConversion}($cfile)) {
385             if ($ENABLED{CUDA}) {
386           my $cufile = winPath($projlist->{ALL}->{$projname}->{'path'} . $obj . '.cu');
387           $srcfiles->{'cu'}->{$cufile} = 1;
388           if (!-e &{$osPathConversion}($cufile)) {
389                     print "ERROR: file $cfile nor $cufile not found - project $projname\n";
390                   }
391         } else {
392           if (!-e &{$osPathConversion}($cfile)) {
393                     print "ERROR?: file $cfile not found - project $projname\n";
394                   }
395         }
396       } else {
397         $srcfiles->{'cc'}->{$cfile} = 1;
398           }
399     }
400   } else {
401     $conftype = "Application";
403     my $cfile = winPath($projlist->{ALL}->{$projname}->{'path'} . $projname . '.cc');
404     $srcfiles->{'cc'}->{$cfile} = 1;
405   }
407   # add .h files + check that .cc files exist
408   foreach my $cfile (keys %{$srcfiles->{'cc'}}) {
409     if (!-e &{$osPathConversion}($cfile)) {
410       print "ERROR: file $cfile not found - project $projname\n";
411     }
412     my $hfile = $cfile;
413     $hfile =~ s/\.[^\.]+$/.h/;
414     if (-e &{$osPathConversion}($hfile)) {
415       $srcfiles->{'h'}->{$hfile} = 1;
416     }
417     my $hinlfile = $cfile;
418     $hinlfile =~ s/\.[^\.]+$/-inl.h/;
419     if (-e &{$osPathConversion}($hinlfile)) {
420       $srcfiles->{'h'}->{$hinlfile} = 1;
421     }
422   }
424   open(PROJ, '>', &{$osPathConversion}($projFileName));
425   print PROJ
426 "<?xml version=\"1.0\" encoding=\"utf-8\"?>
427 <Project DefaultTargets=\"Build\" ToolsVersion=\"$TOOLS{$vsver}\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
428   <ItemGroup Label=\"ProjectConfigurations\">
429     <ProjectConfiguration Include=\"Debug|Win32\">
430       <Configuration>Debug</Configuration>
431       <Platform>Win32</Platform>
432     </ProjectConfiguration>
433     <ProjectConfiguration Include=\"Debug|x64\">
434       <Configuration>Debug</Configuration>
435       <Platform>x64</Platform>
436     </ProjectConfiguration>
437     <ProjectConfiguration Include=\"Release|Win32\">
438       <Configuration>Release</Configuration>
439       <Platform>Win32</Platform>
440     </ProjectConfiguration>
441     <ProjectConfiguration Include=\"Release|x64\">
442       <Configuration>Release</Configuration>
443       <Platform>x64</Platform>
444     </ProjectConfiguration>
445   </ItemGroup>
446   <PropertyGroup Label=\"Globals\">
447     <ProjectGuid>" . $guid . "</ProjectGuid>
448     <Keyword>Win32Proj</Keyword>
449     <RootNamespace>" . $rootnamespace . "</RootNamespace>
450   </PropertyGroup>
451 ";
453   if ($projlist->{ALL}->{$projname}->{'type'} =~ /LIBNAME/) { # Microsoft.Cpp.Default.props - Library
454     print PROJ
455 "  <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />
456   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">
457     <ConfigurationType>" . $conftype . "</ConfigurationType>
458     <CharacterSet>Unicode</CharacterSet>
459     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
460   </PropertyGroup>
461   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\" Label=\"Configuration\">
462     <ConfigurationType>" . $conftype . "</ConfigurationType>
463     <CharacterSet>Unicode</CharacterSet>
464     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
465   </PropertyGroup>
466   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\" Label=\"Configuration\">
467     <ConfigurationType>" . $conftype . "</ConfigurationType>
468     <CharacterSet>Unicode</CharacterSet>
469     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
470     <WholeProgramOptimization>true</WholeProgramOptimization>
471   </PropertyGroup>
472   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\" Label=\"Configuration\">
473      <ConfigurationType>" . $conftype . "</ConfigurationType>
474      <CharacterSet>Unicode</CharacterSet>
475      <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
476      <WholeProgramOptimization>true</WholeProgramOptimization>
477   </PropertyGroup>
478 ";
479   } else {  # Microsoft.Cpp.Default.props - Binfile
480     print PROJ
481 "  <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />
482   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">
483     <ConfigurationType>" . $conftype . "</ConfigurationType>
484     <UseDebugLibraries>true</UseDebugLibraries>
485     <CharacterSet>Unicode</CharacterSet>
486     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
487   </PropertyGroup>
488   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\" Label=\"Configuration\">
489     <ConfigurationType>" . $conftype . "</ConfigurationType>
490     <UseDebugLibraries>false</UseDebugLibraries>
491     <WholeProgramOptimization>true</WholeProgramOptimization>
492     <CharacterSet>Unicode</CharacterSet>
493     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
494   </PropertyGroup>
495   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\" Label=\"Configuration\">
496     <ConfigurationType>" . $conftype . "</ConfigurationType>
497     <UseDebugLibraries>true</UseDebugLibraries>
498     <CharacterSet>Unicode</CharacterSet>
499     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
500   </PropertyGroup>
501   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\" Label=\"Configuration\">
502     <ConfigurationType>" . $conftype . "</ConfigurationType>
503     <UseDebugLibraries>false</UseDebugLibraries>
504     <WholeProgramOptimization>true</WholeProgramOptimization>
505     <CharacterSet>Unicode</CharacterSet>
506     <PlatformToolset>$TOOLSET{$vsver}</PlatformToolset>
507   </PropertyGroup>
508 ";
509   }
511   print PROJ
512 "  <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.props\" />
513   <ImportGroup Label=\"ExtensionSettings\">
514 ";
515   if ($ENABLED{CUDA}) {
516   print PROJ
517 '    <Import Project="$(VCTargetsPath)\BuildCustomizations\CUDA 7.0.props" />
519   }
520   print PROJ
521 "  </ImportGroup>
522   <ImportGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\"  Label=\"PropertySheets\">
523     <Import Project=\"..\\variables.props\" />
524     <Import Project=\"\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props\" Condition=\"exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />
525 ";
526   if ($ENABLED{CUDA}) {
527   print PROJ
528 "    <Import Project=\"..\\cuda_7.0.props\" />
530   }
531   print PROJ
532 "    <Import Project=\"..\\kaldiwin_win32.props\" />
533     <Import Project=\"..\\openfstwin_debug_win32.props\" />
534   </ImportGroup>
535   <ImportGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">
536     <Import Project=\"..\\variables.props\" />
537     <Import Project=\"\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props\" Condition=\"exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />
538 ";
539   if ($ENABLED{CUDA}) {
540   print PROJ
541 "    <Import Project=\"..\\cuda_7.0.props\" />
542 ";
543   }
544   print PROJ
545 "    <Import Project=\"..\\kaldiwin.props\" />
546     <Import Project=\"..\\openfstwin_debug.props\" />
547   </ImportGroup>
548   <ImportGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\" Label=\"PropertySheets\">
549     <Import Project=\"..\\variables.props\" />
550     <Import Project=\"\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props\" Condition=\"exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />
551 ";
552   if ($ENABLED{CUDA}) {
553   print PROJ
554 "    <Import Project=\"..\\cuda_7.0.props\" />
555 ";
556   }
557   print PROJ
558 "    <Import Project=\"..\\kaldiwin_win32.props\" />
559     <Import Project=\"..\\openfstwin_release_win32.props\" />
560   </ImportGroup>
561   <ImportGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">
562     <Import Project=\"..\\variables.props\" />
563     <Import Project=\"\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props\" Condition=\"exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />
564 ";
565   if ($ENABLED{CUDA}) {
566   print PROJ
567 "    <Import Project=\"..\\cuda_7.0.props\" />
568 ";
569   }
570   print PROJ
571 "    <Import Project=\"..\\kaldiwin.props\" />
572     <Import Project=\"..\\openfstwin_release.props\" />
573   </ImportGroup>
574 ";
576   if ($projlist->{ALL}->{$projname}->{'type'} =~ /LIBNAME/) { # UserMacros - Library
577     print PROJ
578 "  <PropertyGroup Label=\"UserMacros\" />
579   <PropertyGroup>
580     <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
581     <OutDir Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">\$(SolutionDir)\$(Configuration)\\</OutDir>
582     <IntDir Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">\$(Configuration)\\</IntDir>
583     <OutDir Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">\$(SolutionDir)\$(Configuration)\\</OutDir>
584     <IntDir Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">\$(Configuration)\\</IntDir>
585   </PropertyGroup>
586 ";
587   } else {  # UserMacros - Binfile
588     print PROJ
589 "  <PropertyGroup Label=\"UserMacros\" />
590   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">
591     <LinkIncremental>true</LinkIncremental>
592   </PropertyGroup>
593   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\">
594     <LinkIncremental>true</LinkIncremental>
595   </PropertyGroup>
596   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">
597     <LinkIncremental>false</LinkIncremental>
598   </PropertyGroup>
599   <PropertyGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\">
600     <LinkIncremental>false</LinkIncremental>
601   </PropertyGroup>
602 ";
603   }
605   if ($projlist->{ALL}->{$projname}->{'type'} =~ /LIBNAME/) { # ItemDefinitionGroup Conditions - Library
606     print PROJ
607 "  <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">
608     <ClCompile>
609       <Optimization>Disabled</Optimization>
610       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
611       <MinimalRebuild>true</MinimalRebuild>
612       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
613       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
614       <PrecompiledHeader>
615       </PrecompiledHeader>
616       <WarningLevel>Level3</WarningLevel>
617       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
618     </ClCompile>
619   </ItemDefinitionGroup>
620   <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\">
621     <ClCompile>
622       <Optimization>Disabled</Optimization>
623       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
624       <MinimalRebuild>true</MinimalRebuild>
625       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
626       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
627       <PrecompiledHeader>
628       </PrecompiledHeader>
629       <WarningLevel>Level3</WarningLevel>
630       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
631     </ClCompile>
632   </ItemDefinitionGroup>
633   <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">
634     <ClCompile>
635       <Optimization>MaxSpeed</Optimization>
636       <IntrinsicFunctions>true</IntrinsicFunctions>
637       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
638       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
639       <FunctionLevelLinking>true</FunctionLevelLinking>
640       <PrecompiledHeader>
641       </PrecompiledHeader>
642       <WarningLevel>Level3</WarningLevel>
643       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
644     </ClCompile>
645   </ItemDefinitionGroup>
646   <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\">
647     <ClCompile>
648       <Optimization>MaxSpeed</Optimization>
649       <IntrinsicFunctions>true</IntrinsicFunctions>
650       <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
651       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
652       <FunctionLevelLinking>true</FunctionLevelLinking>
653       <PrecompiledHeader>
654       </PrecompiledHeader>
655       <WarningLevel>Level3</WarningLevel>
656       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
657     </ClCompile>
658   </ItemDefinitionGroup>
659 ";
660   } else {  # ItemDefinitionGroup Conditions - Binfile
661     print PROJ
662 "  <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|Win32'\">
663     <ClCompile>
664       <PrecompiledHeader>
665       </PrecompiledHeader>
666       <WarningLevel>Level3</WarningLevel>
667       <Optimization>Disabled</Optimization>
668       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
669     </ClCompile>
670     <Link>
671       <SubSystem>Console</SubSystem>
672       <GenerateDebugInformation>true</GenerateDebugInformation>
673     </Link>
674   </ItemDefinitionGroup>
675    <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Debug|x64'\">
676      <ClCompile>
677        <PrecompiledHeader>
678        </PrecompiledHeader>
679        <WarningLevel>Level3</WarningLevel>
680        <Optimization>Disabled</Optimization>
681        <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
682      </ClCompile>
683      <Link>
684        <SubSystem>Console</SubSystem>
685        <GenerateDebugInformation>true</GenerateDebugInformation>
686      </Link>
687    </ItemDefinitionGroup>
688   <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|Win32'\">
689     <ClCompile>
690       <WarningLevel>Level3</WarningLevel>
691       <PrecompiledHeader>
692       </PrecompiledHeader>
693       <Optimization>MaxSpeed</Optimization>
694       <FunctionLevelLinking>true</FunctionLevelLinking>
695       <IntrinsicFunctions>true</IntrinsicFunctions>
696       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
697     </ClCompile>
698     <Link>
699       <SubSystem>Console</SubSystem>
700       <GenerateDebugInformation>true</GenerateDebugInformation>
701       <EnableCOMDATFolding>true</EnableCOMDATFolding>
702       <OptimizeReferences>true</OptimizeReferences>
703     </Link>
704   </ItemDefinitionGroup>
705   <ItemDefinitionGroup Condition=\"'\$(Configuration)|\$(Platform)'=='Release|x64'\">
706     <ClCompile>
707       <WarningLevel>Level3</WarningLevel>
708       <PrecompiledHeader>
709       </PrecompiledHeader>
710       <Optimization>MaxSpeed</Optimization>
711       <FunctionLevelLinking>true</FunctionLevelLinking>
712       <IntrinsicFunctions>true</IntrinsicFunctions>
713       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
714     </ClCompile>
715     <Link>
716       <SubSystem>Console</SubSystem>
717       <GenerateDebugInformation>true</GenerateDebugInformation>
718       <EnableCOMDATFolding>true</EnableCOMDATFolding>
719       <OptimizeReferences>true</OptimizeReferences>
720     </Link>
721   </ItemDefinitionGroup>
722 ";
723   }
725   # .c files
726   if (scalar keys %{$srcfiles->{'cc'}} > 0) {
727     print PROJ
728 "  <ItemGroup>
729 ";
730     foreach my $cfile (sort { $a cmp $b } keys %{$srcfiles->{'cc'}}) {
731       print PROJ
732 "    <ClCompile Include=\"" . makeRelPath($cfile, $projFileName) . "\" />
733 ";
734     }
735     print PROJ
736 "  </ItemGroup>
737 ";
738   }
739   # .cu files
740   if (scalar keys %{$srcfiles->{'cu'}} > 0) {
741     print PROJ
742 "  <ItemGroup>
743 ";
744     foreach my $cfile (sort { $a cmp $b } keys %{$srcfiles->{'cu'}}) {
745       print PROJ
746 "    <CudaCompile Include=\"" . makeRelPath($cfile, $projFileName) . "\" />
747 ";
748     }
749     print PROJ
750 "  </ItemGroup>
751 ";
752   }
754   # .h files
755   if (scalar keys %{$srcfiles->{'h'}} > 0) {
756     print PROJ
757 "  <ItemGroup>
758 ";
759     foreach my $hfile (sort { $a cmp $b } keys %{$srcfiles->{'h'}}) {
760       print PROJ
761 "    <ClInclude Include=\"" . makeRelPath($hfile, $projFileName) . "\" />
762 ";
763     }
764     print PROJ
765 "  </ItemGroup>
766 ";
767   }
769   # refs
770   if (($projlist->{ALL}->{$projname}->{'type'} !~ /LIBNAME/) &&
771       (scalar keys %{$projdeps->{$projlist->{ALL}->{$projname}->{'path'}}} > 0)) {
772     print PROJ
773 "  <ItemGroup>
774 ";
775     foreach my $lib (sort { $a cmp $b } keys%{$projdeps->{$projlist->{ALL}->{$projname}->{'path'}}}) {
776       my $refProjFileName = makeRelPath(winPath(getProjFileDir($lib) . "/$lib.vcxproj"), $projFileName);
777       print PROJ
778 "    <ProjectReference Include=\"" . $refProjFileName . "\">
779       <Project>" .   lc($projguids->{$lib}) . "</Project>
780     </ProjectReference>
781 ";
782     }
783     print PROJ
784 "  </ItemGroup>
785 ";
786   }
788   # terminate
789   print PROJ
790 "  <Import Project=\"\$(VCTargetsPath)\\Microsoft.Cpp.targets\" />
791   <ImportGroup Label=\"ExtensionTargets\">
792 ";
793   if ($ENABLED{CUDA}) {
794     print PROJ
795 '    <Import Project="$(VCTargetsPath)\BuildCustomizations\CUDA 7.0.targets" />
796 ';
797   }
798   print PROJ
799 "  </ImportGroup>
800 </Project>
801 ";
802   close(PROJ);
804   # create .user file
805   #   my $filename_userfile = $projFileName . '.user';
806     # open(USER, '>', &{$osPathConversion}($filename_userfile));
807     # print USER
808   # "<?xml version=\"1.0\" encoding=\"utf-8\"?>
809   # <Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
810   # </Project>
811   # ";
812     # close(USER);
814   # create .filters file
815   my $filename_filtersfile = $projFileName . '.filters';
816   open(FLTS, '>', &{$osPathConversion}($filename_filtersfile));
817   print FLTS
818 "<?xml version=\"1.0\" encoding=\"utf-8\"?>
819 <Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">
820   <ItemGroup>
821     <Filter Include=\"Source Files\">
822       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
823       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
824     </Filter>
825     <Filter Include=\"Header Files\">
826       <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
827       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
828     </Filter>
829     <Filter Include=\"Resource Files\">
830       <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
831       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
832     </Filter>
833     <Filter Include=\"Cuda Kernels\">
834       <UniqueIdentifier>{6841a02e-469b-487d-a1ea-7d138415dd41}</UniqueIdentifier>
835       <Extensions>cu</Extensions>
836     </Filter>
837   </ItemGroup>
838 ";
839   # .c files
840   if (scalar keys %{$srcfiles->{'cc'}} > 0) {
841     print FLTS
842 "  <ItemGroup>
843 ";
844     foreach my $cfile (sort { $a cmp $b } keys %{$srcfiles->{'cc'}}) {
845       print FLTS
846 "    <ClCompile Include=\"" . makeRelPath($cfile, $projFileName) . "\">
847       <Filter>Source Files</Filter>
848     </ClCompile>
849 ";
850     }
851     print FLTS
852 "  </ItemGroup>
853 ";
854   }
855   # .h files
856   if (scalar keys %{$srcfiles->{'h'}} > 0) {
857     print FLTS
858 "  <ItemGroup>
859 ";
860     foreach my $hfile (sort { $a cmp $b } keys %{$srcfiles->{'h'}}) {
861       print FLTS
862 "    <ClInclude Include=\"" . makeRelPath($hfile, $projFileName) . "\">
863       <Filter>Header Files</Filter>
864     </ClInclude>
865 ";
866     }
867     print FLTS
868 "  </ItemGroup>
869 ";
870   }
871   # .cu files
872   if (scalar keys %{$srcfiles->{'cu'}} > 0) {
873     print FLTS
874 "  <ItemGroup>
875 ";
876     foreach my $cufile (sort { $a cmp $b } keys %{$srcfiles->{'cu'}}) {
877       print FLTS
878 "    <CudaCompile Include=\"" . makeRelPath($cufile, $projFileName) . "\">
879       <Filter>Cuda Kernels</Filter>
880     </CudaCompile>
881 ";
882     }
883     print FLTS
884 "  </ItemGroup>
885 ";
886   }
887   print FLTS
888 "</Project>
889 ";
890   close(FLTS);
894 sub ltrim {
895    my $s = shift;
896     $s =~ s/^\s+//;
897      return $s;
900 sub isEmptyLine{
901    my $line = shift;
903    my $lineTrimmed  = ltrim($line);
905    if($lineTrimmed eq "")
906    {
907        return 1;
908    }
909    else
910    {
911        return 0;
912    }
915 sub isValidProjectLine{
916    my $line = shift;
918    if(!( isEmptyLine($line) || $line =~ m:(EXT_SUBDIRS_LIB.*\n{0,1}): ) )
919    {
920        return 1;
921    }
922    else
923    {
924        return 0;
925    }
931 # ****************************************************
932 # ****************************************************
933 # ****************************************************
935 if (-e &{$osPathConversion}($solutionDir)) {
936   print "Solution directory already exists, do you want to (r)emove, (o)verwrite, or (c)ancel? : ";
937   my $ans = <STDIN>;
938   if ($ans =~ /^c$/i) { exit 0; }
939   elsif($ans =~ /^r/i) { &{$osPathConversion}($solutionDir); }
940   elsif($ans !~ /^o/) { die "Invalid option given."; }
942 mkpath &{$osPathConversion}($solutionDir);
943 mkpath &{$osPathConversion}($projDir);
945 my $projguids = {};
946 loadHashTxtFile($projguidListFileName, $projguids);
948 my $projlist = {};
949 my $projdeps = {};
950 my $projlibs = {};
952 #my $makefiles = [];
953 #find(sub { if ($_ =~ /Makefile$/) { push @$makefiles, $File::Find::name; } },
954 #     &{$osPathConversion}($srcDir));
956 my @makefiles = (); # will be all the Makefiles in the subdirectories.
957 my $topLevelMakefile = "$srcDir/Makefile";
958 open(M, '<', &{$osPathConversion}($topLevelMakefile)) || die "opening $topLevelMakefile";
959 while(<M>) {
960   # parsing the part of the top-level Makefile that's like:
961   # SUBDIRS = base util matrix feat tree model fstext hmm optimization \
962   #         transform lm decoder bin fstbin gmmbin featbin
963   if (s/^(SUBDIRS|EXT_SUBDIRS)\s+=\s+//) {
964     # print STDERR "here\n";
965     while ( isValidProjectLine($_) ) { # till we get an empty line or a line starting with EXT_SUBDIRS_LIB..
966       s:\\::;
967       foreach my $f (split(" ", $_)) {
968        if($f eq "#"){
969            last;
970        }
971         push @makefiles, "$srcDir/$f/Makefile";
972       }
973       $_ = <M>;
974     }
975   }
977 ##foreach my $f (@makefiles) { print STDERR "Adding $f\n"; }
979 # was @$makefiles in the line below.
980 my $i = 0;
981 foreach my $makefile (@makefiles) {
982   print "INFO: parsing " . $makefile . "\n";
983   parseMakefile($makefile, $projlist, $projdeps, $projlibs);
984         #print Dumper("Projlist", $projlist);
985         #print Dumper("Projdeps", $projdeps);
986         #print Dumper("Projlibs", $projlibs);
987         #die "To staci" if $i >=3;
988         $i++;
989   }
991 # writeSolutionFile also creates guids for new projects
992 writeSolutionFile($solutionDir . '/' . $solutionFileName, $projlist, $projguids);
994 foreach my $propFile (@propsFiles) {
995   copy(&{$osPathConversion}($propFile),
996        &{$osPathConversion}($projDir . "/")) or die "ERROR: failed to copy prop file $propFile\n";
998 foreach my $option (keys %optionalProps) {
999         if ($ENABLED{$option} ) {
1000                 my $propFile = $optionalProps{$option};
1001                 copy(&{$osPathConversion}($propFile), &{$osPathConversion}($projDir . "/")) or
1002                         die "ERROR: failed to copy prop file $propFile\n";
1003         }
1006 foreach my $projname (sort { $a cmp $b } keys %{$projlist->{ALL}}) {
1007   my $projFileDir = winPath(getProjFileDir($projname));
1008   mkpath &{$osPathConversion}($projFileDir);
1009   writeProjectFiles($projname, $projlist, $projdeps, $projlibs, $projguids);
1012 saveHashTxtFile($projguidListFileName, $projguids);
1014 # make Windows line-endings in non-Win environment
1015 if ($^O !~ /MSWin32/i) {
1016   my $allfiles = [];
1017   find(sub { if ($_ =~ /sln$|vcxproj$|props$/) { push @$allfiles, $File::Find::name; } },
1018        &{$osPathConversion}($solutionDir));
1019   foreach my $file (@$allfiles) {
1020     checkCRLF($file);
1021   }