# The OlympusBuild build module # Thomas K Harris 4/2008 # See http://wiki.speech.cs.cmu.edu/olympus/index.php/title=Build_Module use strict; use File::Spec; use Win32::TieRegistry; use Win32::API; use File::Copy qw/cp/; my $HWND_BROADCAST = -1; my $WM_SETTINGCHANGE = 0x1a; #use constant HWND_BROADCAST => -1; #use constant WM_SETTINGCHANGE => 0x1a; package OlympusBuild; $Win32::TieRegistry::Registry->Delimiter("/"); sub new { my $class = shift; my %params = @_; #process cmd line style arguments into params #just include an 'ARGV' hash refernce to @ARGV if(defined $params{'ARGV'}) { for my $arg (@{$params{'ARGV'}}) { if($arg =~ m/--(.+)/ && !defined $params{$1}) { $params{$1} = 1; } } } my $objref = { 'PROJECT' => $params{'PROJECT'}, 'PROJECT_ROOT' => (defined $params{'PROJECT'}? File::Spec->rel2abs($params{'PROJECT_ROOT'} || File::Spec->curdir): undef), 'OLYMPUS_ROOT' => (defined $params{'PROJECT'}? $params{'OLYMPUS_ROOT'} || $ENV{'OLYMPUS_ROOT'}: File::Spec->curdir), 'BUILD_TYPE' => $params{'BUILD_TYPE'} || 'Build', 'BUILD_CONF' => $params{'BUILD_CONF'} || 'Release', 'NO_SET_OLYMPUS_ROOT' => $params{'no_set_olympus_root'} }; for my $param (keys %$objref) { print STDERR "$param: ${$objref}{$param}$/" if defined ${$objref}{$param}; } print STDERR $/; bless $objref, $class; } sub buildOlympus { my $self = shift; $self->buildSAPI; print STDERR $/; $self->buildAgents; $self->setEnv('OLYMPUS_ROOT', File::Spec->rel2abs($self->{'OLYMPUS_ROOT'})) unless $self->{'NO_SET_OLYMPUS_ROOT'}; } sub buildSystem { my $self = shift; $self->buildAgents; } sub buildSAPI { my $self = shift; my $sapisdkhome; if(defined $ENV{'SAPI_SDK_DIR'}) { $sapisdkhome = $ENV{'SAPI_SDK_DIR'}; } else { my $speechKey = $Win32::TieRegistry::Registry->{'LMachine/SOFTWARE/Microsoft/Speech/'}; $sapisdkhome = $speechKey->{'/SDKPath'}; } die "Can't find SAPI" if !-e File::Spec->catfile($sapisdkhome, 'include', 'sapi.h'); $self->setEnv('SAPI_SDK_DIR', $sapisdkhome); if(! #### Below I had to change the paths to match the Windows 7 SDK paths. I also needed to #### add an environment variable to my system for 'SAPI_SDK_DIR' pointing to the Windows 7 SDK (File::Copy::cp('Libraries\MS-SAPI\spcollec.h', "$sapisdkhome\\include") && File::Copy::cp('Libraries\MS-SAPI\sphelper.h', "$sapisdkhome\\include") && File::Copy::cp('Libraries\MS-SAPI\simpleaudio.sln', "$sapisdkhome\\Samples\\winui\\speech\\simpleAudio") && File::Copy::cp('Libraries\MS-SAPI\simpleaudio.vcproj', "$sapisdkhome\\Samples\\winui\\speech\\simpleAudio"))) { warn "Can't copy sdk fixup$/"; } else { $self->buildVSSolution("$sapisdkhome\\Samples\\winui\\speech\\simpleaudio\\simpleaudio.sln", {'BUILD_CONF' => 'Release MinSize'}); } } sub buildAgents { my $self = shift; $self->buildVSSolution($self->getSolution); print STDERR $/; if (!defined $self->{'PROJECT'}) { if ($self->buildAnt(File::Spec->catfile('Agents', 'JavaTTY', 'build.xml')) != 0) { warn "problem building optional JavaTTY component$/"; } } } sub buildAnt { my $self = shift; my $buildfile = shift; my $ant = $self->getAnt; my $antTarget = ($self->{'BUILD_TYPE'} eq 'Rebuild'? 'clean default': 'default'); if (defined $ant) { &runWin32Prog("\"$ant\" -buildfile $buildfile $antTarget"); return 0; } else { return -1; } } sub buildVSSolution { my $self = shift; my $solution = shift; my $params = shift; my $build_type = ${$params}{'BUILD_TYPE'} || $self->{'BUILD_TYPE'}; my $build_conf = ${$params}{'BUILD_CONF'} || $self->{'BUILD_CONF'}; my $msdev = $self->getMSDev; &runWin32Prog("\"$msdev\" \"$solution\" /$build_type \"$build_conf\""); } sub runWin32Prog { my $strCommand = shift; print STDERR "Running command: $strCommand$/$/"; system($strCommand); } sub buildResources { my $self = shift; my $currentDir = File::Spec->rel2abs(File::Spec->curdir); chdir File::Spec->catdir($self->{'OLYMPUS_ROOT'}, 'Tools', 'MakeLM'); &runWin32Prog("perl makelm.pl --resourcesdir \"".File::Spec->catfile($self->{'PROJECT_ROOT'}, 'Resources')."\" --projectname $self->{'PROJECT'}"); chdir $currentDir; } sub compileGrammar { my $self = shift; my $currentDir = File::Spec->rel2abs(File::Spec->curdir); chdir File::Spec->catdir($self->{'PROJECT_ROOT'}, 'Resources', 'Grammar'); &runWin32Prog("cmp.bat"); chdir $currentDir; } sub getSolution { my $self = shift; my $solution = (defined $self->{'PROJECT'}? File::Spec->catfile($self->{'PROJECT_ROOT'}, 'System.sln'): File::Spec->catfile($self->{'OLYMPUS_ROOT'}, 'Olympus.sln')); die "Can't find build target \"$solution\"" if !-e $solution; return $solution; } sub getMSDev { my $self = shift; return $self->{'MSDev'} if defined $self->{'MSDev'}; my $vsKey = $Win32::TieRegistry::Registry->{"LMachine/Software/Microsoft/VisualStudio/8.0/"}; my $vshome = $vsKey->{'/InstallDir'}; #### Here I had to manually path out this directory. The above registry key doesn't exist #### on my machine. I am using Microsoft Visual Studio 2008 Professional Edition v9.0.21022.8 RTM $vshome = 'C:\\MSVS2008\\Common7\\IDE'; $self->{'MSDev'} = File::Spec->catfile($vshome, 'devenv.com'); die "Can't seem to find visual studio 8.0" if !-e $self->{'MSDev'}; return $self->{'MSDev'}; } sub getAnt { my $self = shift; return $self->{'Ant'} if defined $self->{'Ant'}; if (defined $ENV{'ANT_HOME'}) { $self->{'Ant'} = File::Spec->catfile($ENV{'ANT_HOME'}, 'bin', 'ant.bat'); } else { #try to get ant from netbeans my $uninstallKey = $Win32::TieRegistry::Registry->{"LMachine/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/"} || die "Can't read LMachine/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/ key: $^E\n"; my $bestNetbeansVer; for my $netbeans (grep(/nbi-nb-base-/, $uninstallKey->SubKeyNames)) { $netbeans =~ s/nbi-nb-base-//; $bestNetbeansVer = $netbeans if !defined $bestNetbeansVer || $netbeans > $bestNetbeansVer; } my $majorNbVer; my $minorNbVer; if($bestNetbeansVer =~ /(\d+)\.(\d+)/) { $majorNbVer = $1; $minorNbVer = $2; } else { warn "Can't determine netbeans version for $bestNetbeansVer$/"; return; } if($bestNetbeansVer < 6) { warn "You should get Netbeans version 6 or greater$/"; return; } my $bestNetbeansKey = $uninstallKey->{"nbi-nb-base-$bestNetbeansVer/"}; if (!defined $bestNetbeansKey) { warn "Can't seem to find ant. See http://wiki.speech.cs.cmu.edu/olympus/index.php/Apache_ANT$/"; return; } my $nbhome = $bestNetbeansKey->{"/InstallLocation"}; if($majorNbVer == 6 && $minorNbVer < 1) { $self->{'Ant'} = File::Spec->catfile($nbhome, 'java1', 'ant', 'bin', 'ant.bat'); } else { $self->{'Ant'} = File::Spec->catfile($nbhome, 'java2', 'ant', 'bin', 'ant.bat'); } } if (!-e $self->{'Ant'}) { warn "Can't seem to find ant. See http://wiki.speech.cs.cmu.edu/olympus/index.php/Apache_ANT$/"; return; } return $self->{'Ant'}; } sub setEnv { my $self = shift; my ($envVar, $envVal) = @_; my $envKey = $Win32::TieRegistry::Registry->{'LMachine/SYSTEM/CurrentControlSet/Control/Session Manager/Environment'}; return if $envKey->{'/'.$envVar} eq $envVal; $envKey->{'/'.$envVar} = $envVal; my $SendMessage = new Win32::API("user32", "SendMessage", 'NNNP', 'N') or die "Couldn't create SendMessage: $!\n"; my $RetVal = $SendMessage->Call($HWND_BROADCAST, $WM_SETTINGCHANGE, 0, 'Environment'); $self->{'RESTART_CONSOLE'} = 1; } sub DESTROY { my $self = shift; print STDERR "******* You MUST restart your console for the changes to take effect *******$/" if defined $self->{'RESTART_CONSOLE'}; } 1;