| #!/usr/bin/perl -w |
| # -*- tab-width: 4; cperl-indent-level: 4; indent-tabs-mode: nil -*- |
| |
| use File::Copy; |
| use File::Glob; |
| |
| my $output_format = 'u'; |
| |
| sub reg_get_value($) |
| { |
| # it is believed that the registry moves keys around |
| # depending on OS version, this will de-mangle that |
| my $key = shift; |
| my $fhandle; |
| my $value; |
| |
| open ($fhandle, "/proc/registry/$key") || return; |
| # reg keys have 0x00 0x5c at the end |
| $value = (split /\0/, <$fhandle>)[0]; |
| close ($fhandle); |
| |
| if ( defined $value ) { |
| chomp ($value); |
| $value =~ s|\r\n||; |
| # print "Value '$value' at '$key'\n"; |
| } |
| |
| return $value; |
| } |
| |
| sub print_syntax() |
| { |
| print "oowintool [option] ...\n"; |
| print " encoding options\n"; |
| print " -w - windows form\n"; |
| print " -u - unix form (default)\n"; |
| print " commands:\n"; |
| print " --msvc-ver - print version of MSVC eg. 6.0\n"; |
| print " --msvc-copy-dlls <dest> - copy msvc[pr]??.dlls into <dest>/msvcp??/\n"; |
| print " --msvc-copy-dlls-64 <dest> - copy x64 msvc[pr]??.dlls into <dest>/msvcp??/\n"; |
| print " --msvc-copy-msms <dest> - copy mscrt merge modules to <dest>/msm90/\n"; |
| print " --msvc-copy-msms-64 <ds> - copy the x64 mscrt merge modules to <ds>/msm90/\n"; |
| print " --msvc-productdir - print productdir\n"; |
| print " --msvs-productdir - print productdir\n"; |
| print " --dotnetsdk-dir - print .NET SDK path\n"; |
| print " --csc-compilerdir - print .NET SDK compiler path\n"; |
| print " --al-home - print AL.exe install dir\n"; |
| print " --windows-sdk-home - print Windows SDK install dir\n"; |
| print " --jdk-home - print the jdk install dir\n"; |
| print " --help - print this message\n"; |
| } |
| |
| sub cygpath($$$) |
| { |
| my ($path, $input_format, $format) = @_; |
| |
| return $path if ( ! defined $path ); |
| # Strip trailing path separators |
| if ($input_format eq 'u') { |
| $path =~ s|/*\s*$||; |
| } else { |
| $path =~ s|\\*\s*$||; |
| } |
| |
| # 'Unterminated quoted string errors' from 'ash' when |
| # forking cygpath so - reimplement cygpath in perl [ gack ] |
| if ($format eq 'u' && $input_format eq 'w') { |
| $path =~ s|\\|/|g; |
| $path =~ s|([a-zA-Z]):/|/cygdrive/$1/|g; |
| } |
| elsif ($format eq 'w' && $input_format eq 'u') { |
| $path =~ s|/cygdrive/([a-zA-Z])/|/$1/|g; |
| $path =~ s|/|\\|g; |
| } |
| |
| return $path; |
| } |
| |
| sub print_path($$) |
| { |
| my ($path, $unix) = @_; |
| |
| $path = cygpath ($path, $unix, $output_format); |
| |
| print $path; |
| } |
| |
| sub print_windows_sdk_home() |
| { |
| my ($value, $key); |
| |
| # This is for the Windows SDK 8 distributed with MSVS 2012 |
| $value = reg_get_value ('HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows Kits/Installed Roots/KitsRoot'); |
| |
| if (!defined $value) { |
| $value = reg_get_value ('HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/CurrentInstallFolder'); |
| } |
| if (!defined $value) { |
| $value = reg_get_value ('HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MicrosoftSDK/Directories/Install Dir'); |
| } |
| |
| if (!defined $value) { |
| # Unclear whether we ever get here, don't the above match any |
| # recent Windows SDK? |
| foreach $key (File::Glob::bsd_glob('/proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/MicrosoftSDK/InstalledSDKs/*/Install Dir')) { |
| $value = reg_get_value ($key); |
| last if defined $value; |
| } |
| } |
| |
| defined $value || die "Windows SDK not found"; |
| |
| print cygpath ($value, 'w', $output_format); |
| } |
| |
| sub print_al_home() |
| { |
| # Called by configure only if al.exe is not in the Windows SDK's |
| # bin folder, where it AFAIK always is in any recent Windows SDK, |
| # so whether this will ever be called is unclear... |
| |
| my ($value, $key); |
| |
| foreach $key (File::Glob::bsd_glob('/proc/registry/HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Microsoft SDKs/Windows/*/WinSDK-NetFx40Tools/InstallationFolder')) { |
| $key =~ s!^/proc/registry/!!; |
| $value = reg_get_value ($key); |
| |
| # Sigh, the same test that configure does for al.exe |
| # being either directly in it, or in a "bin" subdir... But on |
| # the other hand we don't want to be mislead by a registry key |
| # that matches the above but points to a directory that does |
| # in fact not contain an al.exe. For me, |
| # HKLM/SOFTWARE/Microsoft/Microsoft SDKs/Windows/v7.0A/WinSDK-NetFx40Tools/InstallationFolder |
| # contains |
| # c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\ |
| # but that then does not contain any al.exe. |
| |
| if (-f "$value/bin/al.exe" || -f "$value/al.exe") { |
| print cygpath ($value, 'w', $output_format); |
| return; |
| } |
| } |
| die "Can't find al.exe"; |
| } |
| |
| my %msvs_2008 = ( |
| 'ver' => '9.0', |
| 'key' => 'Microsoft/VisualStudio/9.0/Setup/VS/ProductDir', |
| 'dll_path' => 'VC/redist/x86/Microsoft.VC90.CRT', |
| 'dll_suffix' => '90' |
| ); |
| my %msvc_2008 = ( |
| 'ver' => '9.0', |
| 'key' => 'Microsoft/VisualStudio/9.0/Setup/VC/ProductDir', |
| 'dll_path' => 'redist/x86/Microsoft.VC90.CRT', |
| 'dll_suffix' => '90' |
| ); |
| my %msvs_express_2008 = ( |
| 'ver' => '9.0', |
| 'key' => 'Microsoft/VCExpress/9.0/Setup/VS/ProductDir', |
| 'dll_path' => 'VC/redist/x86/Microsoft.VC90.CRT', |
| 'dll_suffix' => '90' |
| ); |
| my %msvc_express_2008 = ( |
| 'ver' => '9.0', |
| 'key' => 'Microsoft/VCExpress/9.0/Setup/VC/ProductDir', |
| 'dll_path' => 'redist/x86/Microsoft.VC90.CRT', |
| 'dll_suffix' => '90' |
| ); |
| my %msvs_2010 = ( |
| 'ver' => '10.0', |
| 'key' => 'Microsoft/VisualStudio/10.0/Setup/VS/ProductDir', |
| 'dll_path' => 'VC/redist/x86/Microsoft.VC100.CRT', |
| 'dll_suffix' => '100' |
| ); |
| my %msvc_2010 = ( |
| 'ver' => '10.0', |
| 'key' => 'Microsoft/VisualStudio/10.0/Setup/VC/ProductDir', |
| 'dll_path' => 'redist/x86/Microsoft.VC100.CRT', |
| 'dll_suffix' => '100' |
| ); |
| my %msvs_2012 = ( |
| 'ver' => '11.0', |
| 'key' => 'Microsoft/VisualStudio/11.0/Setup/VS/ProductDir', |
| 'dll_path' => 'VC/redist/x86/Microsoft.VC110.CRT', |
| 'dll_suffix' => '110' |
| ); |
| my %msvc_2012 = ( |
| 'ver' => '11.0', |
| 'key' => 'Microsoft/VisualStudio/11.0/Setup/VC/ProductDir', |
| 'dll_path' => 'redist/x86/Microsoft.VC110.CRT', |
| 'dll_suffix' => '110' |
| ); |
| |
| sub find_msvs() |
| { |
| my @ms_versions = ( \%msvs_2010, \%msvs_2012, \%msvs_2008, \%msvs_express_2008 ); |
| |
| for $ver (@ms_versions) { |
| my $install = reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/" . $ver->{'key'}); |
| if (defined $install && $install ne '') { |
| $ver->{'product_dir'} = $install; |
| return $ver; |
| } |
| } |
| die "Can't find MS Visual Studio / VC++"; |
| } |
| |
| sub find_msvc() |
| { |
| my @ms_versions = ( \%msvc_2010, \%msvc_2012, \%msvc_2008, \%msvc_express_2008 ); |
| |
| for $ver (@ms_versions) { |
| my $install = reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/" . $ver->{'key'}); |
| if (defined $install && $install ne '') { |
| $ver->{'product_dir'} = $install; |
| return $ver; |
| } |
| } |
| die "Can't find MS Visual Studio / VC++"; |
| } |
| |
| sub print_msvc_ver() |
| { |
| my $ver = find_msvc(); |
| print $ver->{'ver'}; |
| } |
| |
| sub print_msvc_product_dir() |
| { |
| my $ver = find_msvc(); |
| print cygpath ($ver->{'product_dir'}, 'w', $output_format); |
| } |
| |
| sub print_msvs_productdir() |
| { |
| my $ver = find_msvs(); |
| print cygpath ($ver->{'product_dir'}, 'w', $output_format); |
| } |
| |
| sub print_csc_compiler_dir() |
| { |
| my $csc_exe; |
| my $ver = find_msvc(); |
| if ($ver->{'ver'} == "9.0") { |
| # We need to compile C# with the 3.5 or 2.0 compiler in order |
| # for the assemblies to be loadable by managed C++ code |
| # compiled with MSVC 2008. |
| $csc_exe = |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/NET Framework Setup/NDP/v3.5/InstallPath") || |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework/InstallRoot") . "v2.0.50727"; |
| } else { |
| # Is it enough to look for the 4.0 compiler? |
| $csc_exe = |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/NET Framework Setup/NDP/v4/Client/InstallPath"); |
| } |
| print cygpath ($csc_exe, 'w', $output_format); |
| } |
| |
| sub print_dotnetsdk_dir() |
| { |
| my $dir = |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework/sdkInstallRootv1.1") || |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/.NETFramework/sdkInstallRootv2.0"); |
| if ($dir) { |
| print cygpath ($dir, 'w', $output_format); |
| } |
| } |
| |
| sub print_jdk_dir() |
| { |
| my $dir = |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java\ Development\ Kit/1.7/JavaHome") || |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java\ Development\ Kit/1.6/JavaHome") || |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java\ Development\ Kit/1.5/JavaHome") || |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java\ Development\ Kit/1.4/JavaHome") || |
| reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/JavaSoft/Java\ Development\ Kit/1.3/JavaHome"); |
| print cygpath($dir, 'w', $output_format); |
| } |
| |
| sub copy_dll($$$) |
| { |
| my ($src, $fname, $dest) = @_; |
| |
| -f "$src/$fname" || die "can't find $src"; |
| -d $dest || die "no directory $dest"; |
| |
| print STDERR "Copying $src/$fname to $dest\n"; |
| copy ("$src/$fname", $dest) || die "copy failed: $!"; |
| chmod (0755, "$dest/$fname") || die "failed to set dll executable: $!"; |
| } |
| |
| sub msvc_find_version($) |
| { |
| my $checkpath = shift; |
| my $ver = find_msvc(); |
| my $srcdir = (cygpath ($ver->{'product_dir'}, 'w', 'u') . '/' . |
| $ver->{$checkpath}); |
| -d $srcdir && return $ver; |
| $ver = find_msvs(); |
| $srcdir = (cygpath ($ver->{'product_dir'}, 'w', 'u') . '/' . |
| $ver->{$checkpath}); |
| -d $srcdir && return $ver; |
| return undef; |
| } |
| |
| sub msvc_copy_dlls($$) |
| { |
| my $dest = shift; |
| my $arch = shift; |
| my $ver = msvc_find_version('dll_path'); |
| defined $ver || return; |
| my $srcdir = (cygpath ($ver->{'product_dir'}, 'w', 'u') . '/' . |
| $ver->{'dll_path'}); |
| |
| $srcdir =~ s/x86/amd64/ if ($arch eq 'amd64'); |
| |
| copy_dll ($srcdir, "msvcp" . $ver->{'dll_suffix'} . ".dll", |
| $dest . $ver->{'dll_suffix'}); |
| copy_dll ($srcdir, "msvcr" . $ver->{'dll_suffix'} . ".dll", |
| $dest . $ver->{'dll_suffix'}); |
| if ($ver->{'dll_suffix'} == 90) { |
| copy_dll ($srcdir, "msvcm" . $ver->{'dll_suffix'} . ".dll", |
| $dest . $ver->{'dll_suffix'}); |
| copy_dll ($srcdir, "Microsoft.VC90.CRT.manifest", $dest . $ver->{'dll_suffix'}); |
| } |
| } |
| |
| sub msvc_find_msms() |
| { |
| my $ver = find_msvc(); |
| my $msm_path = (cygpath reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/VisualStudio/9.0/Setup/VS/MSMDir"), 'w', $output_format) || |
| (cygpath reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/VisualStudio/10.0/Setup/VS/MSMDir"), 'w', $output_format) || |
| (cygpath reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/VisualStudio/11.0/Setup/VS/MSMDir"), 'w', $output_format); |
| defined $msm_path || die "MSMDir not found"; |
| return -e "$msm_path/Microsoft_VC".$ver->{'dll_suffix'}."_CRT_x86.msm" ? 0 : 1; |
| } |
| |
| sub msvc_copy_msms($$) |
| { |
| # $postfix is empty for x86, and '_x64' for x64 |
| my ($dest, $postfix) = @_; |
| |
| my $ver = find_msvc(); |
| defined $ver || return; |
| |
| my $msm_path = (cygpath reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/VisualStudio/9.0/Setup/VS/MSMDir"), 'w', $output_format) || |
| (cygpath reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/VisualStudio/10.0/Setup/VS/MSMDir"), 'w', $output_format) || |
| (cygpath reg_get_value ("HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/VisualStudio/11.0/Setup/VS/MSMDir"), 'w', $output_format); |
| defined $msm_path || die "MSMDir not found"; |
| if ($ver->{'dll_suffix'} == 90) { |
| if ( $postfix eq "_x86" ) { |
| $postfix = "" |
| } |
| foreach $fname ("Microsoft_VC90_CRT_x86$postfix.msm", "policy_9_0_Microsoft_VC90_CRT_x86$postfix.msm") { |
| print STDERR "Copying $msm_path/$fname to $dest\n"; |
| copy ("$msm_path/$fname", $dest) || die "copy failed: $!"; |
| } |
| } |
| elsif ($ver->{'dll_suffix'} == 100) { |
| foreach $fname ("Microsoft_VC100_CRT$postfix.msm") { |
| print STDERR "Copying $msm_path/$fname to $dest\n"; |
| copy ("$msm_path/$fname", $dest) || print "copy failed: $!\n"; |
| } |
| } |
| else { |
| foreach $fname ("Microsoft_VC110_CRT$postfix.msm") { |
| print STDERR "Copying $msm_path/$fname to $dest\n"; |
| copy ("$msm_path/$fname", $dest) || print "copy failed: $!\n"; |
| } |
| } |
| } |
| |
| if (!@ARGV) { |
| print_syntax(); |
| exit 1; |
| } |
| |
| my @commands = (); |
| my $opt; |
| while (@ARGV) { |
| $opt = shift @ARGV; |
| |
| if ($opt eq '-w' || $opt eq '-u') { |
| $output_format = substr($opt, 1, 1); |
| } else { |
| push @commands, $opt; |
| } |
| } |
| |
| while (@commands) { |
| $opt = shift @commands; |
| |
| if (0) { |
| } elsif ($opt eq '--msvc-ver') { |
| print_msvc_ver(); |
| } elsif ($opt eq '--msvc-copy-dlls') { |
| my $dest = shift @commands; |
| defined $dest || die "copy-dlls requires a destination directory"; |
| msvc_copy_dlls( $dest, 'x86' ); |
| } elsif ($opt eq '--msvc-copy-dlls-64') { |
| my $dest = shift @commands; |
| defined $dest || die "copy-dlls requires a destination directory"; |
| msvc_copy_dlls( $dest, 'amd64' ); |
| } elsif ($opt eq '--msvc-find-msms') { |
| exit msvc_find_msms(); |
| } elsif ($opt eq '--msvc-copy-msms') { |
| my $dest = shift @commands; |
| defined $dest || die "copy-msms requires a destination directory"; |
| msvc_copy_msms( $dest, '_x86' ); |
| } elsif ($opt eq '--msvc-copy-msms-64') { |
| my $dest = shift @commands; |
| defined $dest || die "copy-msms-64 requires a destination directory"; |
| msvc_copy_msms( $dest, '_x64' ); |
| } elsif ($opt eq '--msvs-productdir') { |
| print_msvs_productdir(); |
| } elsif ($opt eq '--msvc-productdir') { |
| print_msvc_product_dir(); |
| } elsif ($opt eq '--dotnetsdk-dir') { |
| print_dotnetsdk_dir(); |
| } elsif ($opt eq '--csc-compilerdir') { |
| print_csc_compiler_dir(); |
| } elsif ($opt eq '--windows-sdk-home') { |
| print_windows_sdk_home(); |
| } elsif ($opt eq '--al-home') { |
| print_al_home(); |
| } elsif ($opt eq '--jdk-home') { |
| print_jdk_dir(); |
| } elsif ($opt eq '--help' || $opt eq '/?') { |
| print_syntax(); |
| } else { |
| print "Unknown option '$opt'\n"; |
| print_syntax(); |
| exit 1; |
| } |
| } |
| |
| # vim:set shiftwidth=4 softtabstop=4 expandtab: |