diff options
author | lloyd <[email protected]> | 2006-09-09 14:14:45 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-09-09 14:14:45 +0000 |
commit | d59000d08c3814bde65e0234088c8a822364154b (patch) | |
tree | 1b5babc143c6a37302f919f772a2b0cd51cdd1ad | |
parent | 537f690ff35042ae71aafc743d15892f41662951 (diff) |
Split main() into several subroutines.
Improve help and diagnostic output.
Exit if an error is encountered when parsing options.
-rwxr-xr-x | configure.pl | 1230 |
1 files changed, 650 insertions, 580 deletions
diff --git a/configure.pl b/configure.pl index d659fcf2c..d44368291 100755 --- a/configure.pl +++ b/configure.pl @@ -11,6 +11,8 @@ my $MAJOR_VERSION = 1; my $MINOR_VERSION = 5; my $PATCH_VERSION = 11; +my $VERSION_STRING = "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION"; + ################################################## # Data # ################################################## @@ -22,6 +24,14 @@ my @DOCS = ( 'credits.txt', 'info.txt', 'license.txt', 'log.txt', 'thanks.txt', 'todo.txt', 'botan.rc', 'pgpkeys.asc'); +my %MODULE_SETS = + ( + 'unix' => [ 'alloc_mmap', 'es_egd', 'es_ftw', 'es_unix', 'fd_unix', + 'tm_unix' ], + 'beos' => [ 'es_beos', 'es_unix', 'fd_unix', 'tm_unix' ], + 'win32' => ['es_capi', 'es_win32', 'mux_win32', 'tm_win32' ], + ); + ################################################## # Run main() and Quit # ################################################## @@ -32,13 +42,9 @@ exit; # Main Driver # ################################################## sub main { - my $ARCH_DIR = File::Spec->catdir('misc', 'config', 'arch'); - my $OS_DIR = File::Spec->catdir('misc', 'config', 'os'); - my $CC_DIR = File::Spec->catdir('misc', 'config', 'cc'); - - %CPU = read_info_files($ARCH_DIR, \&get_arch_info); - %OPERATING_SYSTEM = read_info_files($OS_DIR, \&get_os_info); - %COMPILER = read_info_files($CC_DIR, \&get_cc_info); + %CPU = read_info_files('arch', \&get_arch_info); + %OPERATING_SYSTEM = read_info_files('os', \&get_os_info); + %COMPILER = read_info_files('cc', \&get_cc_info); %MODULES = read_module_files('modules'); my $config = {}; @@ -47,185 +53,59 @@ sub main { 'version_major' => $MAJOR_VERSION, 'version_minor' => $MINOR_VERSION, 'version_patch' => $PATCH_VERSION, - 'version' => "$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION" - }); - - my ($prefix, $doc_dir, $lib_dir) = ('', '', ''); - my $shared = 'yes'; - my ($debug, $dumb_gcc) = (0, 0); - my $build_dir = 'build'; - my ($make_style, $module_set, $local_config) = ('', '', ''); - - my $autoconfig = 1; - my @using_mods; - - GetOptions('debug' => sub { $debug = 1; }, - 'disable-shared' => sub { $shared = 'no'; }, - 'noauto' => sub { $autoconfig = 0 }, - 'dumb-gcc|gcc295x' => sub { $dumb_gcc = 1; }, - 'make-style=s' => \$make_style, - 'modules=s' => \@using_mods, - 'module-set=s' => \$module_set, - 'prefix=s' => \$prefix, - 'docdir=s' => \$doc_dir, - 'libdir=s' => \$lib_dir, - 'build-dir=s' => \$build_dir, - 'local-config=s' => \$local_config, - 'help' => sub { help(); } - ); - - add_to($config, { - 'debug' => $debug, - 'shared' => $shared, - 'build' => $build_dir, - 'local_config' => slurp_file($local_config), + 'version' => $VERSION_STRING, }); - my $cc_os_cpu_set = ''; - if($#ARGV == 0) { $cc_os_cpu_set = $ARGV[0]; } - elsif($autoconfig) { - $cc_os_cpu_set = guess_triple(); - print "(autoconfig): Guessing your system config is $cc_os_cpu_set\n"; - } - else { help(); } - - my ($cc,$os,$submodel) = split(/-/,$cc_os_cpu_set,3); - - help() unless(defined($cc) and defined($os) and defined($submodel)); - - croak("Compiler $cc isn't known (try --help)") - unless defined($COMPILER{$cc}); - - $os = os_alias($os); - croak("OS $os isn't known (try --help)") unless - ($os eq 'generic' or defined($OPERATING_SYSTEM{$os})); - - my $arch = undef; - ($arch, $submodel) = figure_out_arch($submodel); - - croak(realname($os), " doesn't run on $arch ($submodel)") - unless($arch eq 'generic' or $os eq 'generic' or - in_array($arch, $OPERATING_SYSTEM{$os}{'arch'})); - - croak(realname($cc), " doesn't run on $arch ($submodel)") - unless($arch eq 'generic' or - (in_array($arch, $COMPILER{$cc}{'arch'}))); - - croak(realname($cc), " doesn't run on ", realname($os)) - unless($os eq 'generic' or (in_array($os, $COMPILER{$cc}{'os'}))); - - # hacks - - if($cc eq 'gcc' and $os eq 'darwin') { - $COMPILER{'gcc'}{'binary_name'} = 'c++'; - } - - if($cc eq 'gcc' && $dumb_gcc != 1) - { - my $binary = $COMPILER{$cc}{'binary_name'}; - - my $gcc_version = `$binary -v 2>&1`; - - $gcc_version = '' if not defined $gcc_version; - - # Some versions of GCC are a little buggy dealing with long - # long in C++. The last check is because on Cygwin (at least - # for me) $gcc_version doesn't get the output, maybe something - # to do with the stderr redirection? If it's Cygwin and we - # didn't get output, assume it's a buggy GCC. There is no - # reduction in code quality so even if we're wrong it's OK. - - if(($gcc_version =~ /4\.[01]/) || ($gcc_version =~ /3\.[34]/) || - ($gcc_version =~ /2\.95\.[0-4]/) || - ($gcc_version eq '' && $^O eq 'cygwin')) - { - warning("Enabling -fpermissive to work around possible GCC bug"); - $dumb_gcc = 1; - } - if($gcc_version =~ /2\.95\.[0-4]/) - { - warning("GCC 2.95.x issues many spurious warnings during build"); - } - } + my ($target, $module_list) = get_options($config); - my %MODULE_SETS = - ( - 'unix' => [ 'alloc_mmap', 'es_egd', 'es_ftw', 'es_unix', 'fd_unix', - 'tm_unix' ], - 'beos' => [ 'es_beos', 'es_unix', 'fd_unix', 'tm_unix' ], - 'win32' => ['es_capi', 'es_win32', 'mux_win32', 'tm_win32' ], - ); - - croak("Module set $module_set isn't known") - if($module_set && !defined($MODULE_SETS{$module_set})); + my $default_value_is = sub { + my ($var, $val) = @_; + $$config{$var} = $val if not defined($$config{$var}); + }; - if($module_set) { - foreach (@{ $MODULE_SETS{$module_set} }) { push @using_mods,$_; } - } + &$default_value_is('gcc_bug', 0); + &$default_value_is('autoconfig', 1); + &$default_value_is('debug', 0); + &$default_value_is('shared', 'yes'); + &$default_value_is('build-dir', 'build'); + &$default_value_is('local_config', ''); - @using_mods = grep {/./} split(/,/,join(',',@using_mods)); + choose_target($config, $target); - if($autoconfig) - { - foreach my $mod (guess_mods($cc,$os,$arch,$submodel)) - { - print " (autoconfig): Enabling module $mod\n" - unless(in_array($mod, \@using_mods)); + my $os = $$config{'os'}; + my $cc = $$config{'compiler'}; - push @using_mods, $mod; - } - } + &$default_value_is('prefix', os_info_for($os, 'install_root')); + &$default_value_is('libdir', os_info_for($os, 'lib_dir')); + &$default_value_is('docdir', os_info_for($os, 'doc_dir')); + &$default_value_is('make_style', $COMPILER{$cc}{'makefile_style'}); - # Uniqify @using_mods - my %uniqed_mods = map { $_ => undef } @using_mods; - @using_mods = sort keys %uniqed_mods; + my @modules = choose_modules($config, $module_list); - foreach (@using_mods) { - croak("Module $_ isn't known (try --help)") - unless(exists($MODULES{$_})); - } - - my $list_checks = sub { + my $list_checks_dir = sub { my @list = dir_list('checks'); @list = grep { !/\.dat$/ } grep { !/^keys$/ } grep { !/\.h$/ } @list; return map { $_ => 'checks' } @list; }; - $make_style = $COMPILER{$cc}{'makefile_style'} unless($make_style); - add_to($config, { - 'compiler' => $cc, - 'os' => $os, - 'arch' => $arch, - 'submodel' => $submodel, + 'includedir' => os_info_for($os, 'header_dir'), - 'make_style' => $make_style, - 'gcc_bug' => $dumb_gcc, + 'build_lib' => File::Spec->catdir($$config{'build-dir'}, 'lib'), + 'build_check' => File::Spec->catdir($$config{'build-dir'}, 'checks'), + 'build_include' => + File::Spec->catdir($$config{'build-dir'}, 'include'), - 'prefix' => os_install_info($os, 'install_root'), - 'libdir' => os_install_info($os, 'lib_dir'), - 'docdir' => os_install_info($os, 'doc_dir'), - - 'includedir' => os_install_info($os, 'header_dir'), - - 'build_lib' => File::Spec->catdir($$config{'build'}, 'lib'), - 'build_check' => File::Spec->catdir($$config{'build'}, 'checks'), - 'build_include' => File::Spec->catdir($$config{'build'}, 'include'), - - 'modules' => [ @using_mods ], - 'mp_bits' => find_mp_bits(@using_mods), - 'mod_libs' => [ using_libs($os, @using_mods) ], + 'modules' => [ @modules ], + 'mp_bits' => find_mp_bits(@modules), + 'mod_libs' => [ using_libs($os, @modules) ], 'sources' => { map { $_ => 'src' } dir_list('src') }, 'includes' => { map { $_ => 'include' } dir_list('include') }, - 'check_src' => { &$list_checks() } + 'check_src' => { &$list_checks_dir() } }); - $$config{'prefix'} = $prefix if($prefix ne ''); - $$config{'libdir'} = $lib_dir if($lib_dir ne ''); - $$config{'docdir'} = $doc_dir if($doc_dir ne ''); - - foreach my $mod (@using_mods) { + foreach my $mod (@modules) { load_module($MODULES{$mod}, $config); } @@ -236,19 +116,18 @@ sub main { File::Spec->catdir($$config{'build_include'}, 'botan') }); - mkdirs($$config{'build'}, + mkdirs($$config{'build-dir'}, $$config{'build_include'}, $$config{'build_include_botan'}, $$config{'build_lib'}, $$config{'build_check'}); - print_pkg_config($config); + write_pkg_config($config); process_template(File::Spec->catfile('misc', 'config', 'buildh.in'), - File::Spec->catfile($$config{'build'}, 'build.h'), + File::Spec->catfile($$config{'build-dir'}, 'build.h'), $config); - $$config{'includes'}{'build.h'} = $$config{'build'}; + $$config{'includes'}{'build.h'} = $$config{'build-dir'}; - clean_out_dir($$config{'build_include_botan'}); - copy_files($$config{'build_include_botan'}, $$config{'includes'}); + copy_include_files($config); generate_makefile($config); } @@ -256,18 +135,27 @@ sub main { ################################################## # Diagnostics # ################################################## +sub with_diagnostic { + my ($type, @args) = @_; + + my $args = join('', @args); + my $str = "($type): "; + while(length($str) < 14) { $str = ' ' . $str; } + + $str .= $args . "\n"; + return $str; +} + sub croak { - my $str = '(error): '; - foreach(@_) { $str .= $_; } - $str .= "\n"; - die $str; + die with_diagnostic('error', @_); } sub warning { - my $str = '(note): '; - foreach(@_) { $str .= $_; } - $str .= "\n"; - warn $str; + warn with_diagnostic('note', @_); +} + +sub autoconfig { + print with_diagnostic('autoconfig', @_); } sub trace { @@ -280,18 +168,16 @@ sub trace { $func1 =~ s/main:://; $func2 =~ s/main:://; - #my $str = "(trace): $func2:$line2 -> $func1:$line1: "; - my $str = "(trace) [$func1:$line1] "; - foreach(@_) { $str .= $_; } - $str .= "\n"; - warn $str; + warn with_diagnostic('trace', "at $func1:$line1 -\n", @_); } ################################################## -# Display Help # +# Display Help and Quit # ################################################## sub help { - print <<ENDOFHELP; + my $sets = join('|', sort keys %MODULE_SETS); + + my $helptxt = <<ENDOFHELP; Usage: $0 [options] CC-OS-CPU See doc/building.pdf for more information about this program. @@ -304,7 +190,8 @@ Options: --local-config=FILE: include the contents of FILE into build.h --modules=MODS: add module(s) MODS to the library. - --module-set=SET: add a pre-specified set of modules (unix|win32|beos) + --module-set=SET: add a pre-specified set of modules ($sets) + --module-info: display some information about known modules --debug: set compiler flags for debugging --disable-shared: disable building shared libararies @@ -319,31 +206,210 @@ code that will not run on earlier versions of that architecture. ENDOFHELP - my $print_listing = sub { - my ($header, $hash) = @_; - print "$header: "; - my $len = length "$header: "; + my $listing = sub { + my ($header, @list) = @_; + my ($output, $len) = ('', 0); - foreach my $name (sort keys %$hash) { + my $append = sub { + my ($to_append) = @_; + $output .= $to_append; + $len += length $to_append; + }; + + &$append($header . ': '); + + foreach my $name (sort @list) { + next if $name eq 'defaults'; if($len > 71) { - print "\n "; + $output .= "\n "; $len = 3; } - print "$name "; - $len += length "$name "; + &$append($name . ' '); } - - print "\n"; + return $output . "\n"; }; - &$print_listing('CC', \%COMPILER); - &$print_listing('OS', \%OPERATING_SYSTEM); - &$print_listing('CPU', \%CPU); - &$print_listing('Modules', \%MODULES) if(%MODULES); + $helptxt .= &$listing('CC', keys %COMPILER); + $helptxt .= &$listing('OS', keys %OPERATING_SYSTEM); + $helptxt .= &$listing('CPU', keys %CPU); + $helptxt .= &$listing('Modules', keys %MODULES) if(%MODULES); + + print $helptxt; exit; } ################################################## +# Display Further Information about Modules # +################################################## +sub display_module_info { + foreach my $mod (sort keys %MODULES) { + my $modinfo = $MODULES{$mod}; + my $fullname = $$modinfo{'realname'}; + + while(length($mod) < 10) { $mod .= ' '; } + print "$mod - $fullname\n"; + } + exit; +} + +################################################## +# +################################################## +sub choose_target { + my ($config, $target) = @_; + + if($target eq '' and $$config{'autoconfig'}) { + $target = guess_triple(); + autoconfig("Guessing your system config is $target"); + } + + my ($cc,$os,$submodel) = split(/-/,$target,3); + + help() unless(defined($cc) and defined($os) and defined($submodel)); + + croak("Compiler $cc isn't known (try --help)") + unless defined($COMPILER{$cc}); + + my %ccinfo = %{$COMPILER{$cc}}; + + $os = os_alias($os); + croak("OS $os isn't known (try --help)") unless + ($os eq 'generic' or defined($OPERATING_SYSTEM{$os})); + + my $arch = undef; + ($arch, $submodel) = figure_out_arch($submodel); + + croak(realname($os), " doesn't run on $arch ($submodel)") + unless($arch eq 'generic' or $os eq 'generic' or + in_array($arch, $OPERATING_SYSTEM{$os}{'arch'})); + + croak(realname($cc), " doesn't run on $arch ($submodel)") + unless($arch eq 'generic' or + (in_array($arch, $ccinfo{'arch'}))); + + croak(realname($cc), " doesn't run on ", realname($os)) + unless($os eq 'generic' or (in_array($os, $ccinfo{'os'}))); + + # hacks + if($cc eq 'gcc') { + $ccinfo{'binary_name'} = 'c++' if($os eq 'darwin'); + + if($$config{'gcc_bug'} != 1) { + my $binary = $ccinfo{'binary_name'}; + + my $gcc_version = `$binary -v 2>&1`; + + $gcc_version = '' if not defined $gcc_version; + + # Some versions of GCC are a little buggy dealing with + # long long in C++. The last check is because on Cygwin + # (at least for me) gcc_version doesn't get the output, + # maybe something to do with the stderr redirection? If + # it's Cygwin and we didn't get output, assume it's a + # buggy GCC. There is no reduction in code quality so even + # if we're wrong it's OK. + + if(($gcc_version =~ /4\.[01]/) || ($gcc_version =~ /3\.[34]/) || + ($gcc_version =~ /2\.95\.[0-4]/) || + ($gcc_version eq '' && $^O eq 'cygwin')) + { + warning('Enabling -fpermissive to work around ', + 'possible GCC bug'); + + $$config{'gcc_bug'} = 1; + } + if($gcc_version =~ /2\.95\.[0-4]/) + { + warning('GCC 2.95.x issues many spurious warnings'); + } + } + } + + add_to($config, { + 'compiler' => $cc, + 'os' => $os, + 'arch' => $arch, + 'submodel' => $submodel, + }); +} + +sub choose_modules { + my ($config, $mod_str) = @_; + + my @modules = grep {/./} split(/,/, $mod_str); + + if($$config{'autoconfig'}) + { + foreach my $mod (guess_mods($config)) { + + autoconfig("Enabling module $mod") + unless in_array($mod, \@modules); + + push @modules, $mod; + } + } + + # Uniqify @modules + my %uniqed_mods = map { $_ => undef } @modules; + @modules = sort keys %uniqed_mods; + + foreach (@modules) { + croak("Module '$_' isn't known (try --help)") + unless defined $MODULES{$_}; + } + return @modules; +} + +sub get_options { + my ($config) = @_; + + my $save_option = sub { + my ($opt, $val) = @_; + $opt =~ s/-/_/g; + print "$opt -> $val\n"; + $$config{$opt} = $val; + }; + + my $module_set = ''; + my @modules; + exit 1 unless GetOptions( + 'help' => sub { help(); }, + 'module-info' => sub { display_module_info(); }, + 'version' => sub { print "Botan $VERSION_STRING\n"; exit; }, + + 'prefix=s' => sub { &$save_option(@_); }, + 'docdir=s' => sub { &$save_option(@_); }, + 'libdir=s' => sub { &$save_option(@_); }, + 'build-dir=s' => sub { &$save_option('build', $_[0]); }, + 'local-config=s' => + sub { &$save_option('local_config', slurp_file($_[1])); }, + + 'make-style=s' => sub { &$save_option(@_); }, + + 'modules=s' => \@modules, + 'module-set=s' => \$module_set, + + 'debug' => sub { &$save_option($_[0], 1); }, + 'disable-shared' => sub { $$config{'shared'} = 'no'; }, + 'noauto' => sub { $$config{'autoconfig'} = 0; }, + 'dumb-gcc|gcc295x' => sub { $$config{'gcc_bug'} = 1; } + ); + + croak("Module set $module_set isn't known (try --help)") + if($module_set && !defined($MODULE_SETS{$module_set})); + + if($module_set) { + foreach (@{ $MODULE_SETS{$module_set} }) { push @modules,$_; } + } + + my $mod_str = join(',', @modules); + + return ('', $mod_str) if($#ARGV == -1); + return ($ARGV[0], $mod_str) if($#ARGV == 0); + help(); +} + +################################################## # Functions to search the info tables # ################################################## sub figure_out_arch { @@ -357,7 +423,7 @@ sub figure_out_arch { my %info = %{$info}; foreach my $submodel (@{$info{'submodels'}}) { - return $submodel if ($name eq $submodel); + return $submodel if($name eq $submodel); } return '' unless defined $info{'submodel_aliases'}; @@ -376,18 +442,18 @@ sub figure_out_arch { foreach my $arch (keys %CPU) { my %info = %{$CPU{$arch}}; - return $arch if ($name eq $arch); + return $arch if($name eq $arch); foreach my $alias (@{$info{'aliases'}}) { - return $arch if ($name eq $alias); + return $arch if($name eq $alias); } foreach my $submodel (@{$info{'submodels'}}) { - return $arch if ($name eq $submodel); + return $arch if($name eq $submodel); } foreach my $submodel (keys %{$info{'submodel_aliases'}}) { - return $arch if ($name eq $submodel); + return $arch if($name eq $submodel); } } return undef; @@ -434,7 +500,7 @@ sub os_alias { sub os_info_for { my ($os,$what) = @_; - croak("os_info_for called with an os of defaults (internal problem)") + croak('os_info_for called with an os of defaults (internal problem)') if($os eq 'defaults'); my $result = ''; @@ -453,22 +519,23 @@ sub os_info_for { return $result; } -sub os_install_info { - my ($os,$what) = @_; +sub my_compiler { + my ($config) = @_; + my $cc = $$config{'compiler'}; - my $result = $OPERATING_SYSTEM{$os}{$what}; + croak('my_compiler called, but no compiler set') + unless defined $cc and $cc ne ''; - if(defined($result) and $result ne '') { - return $result; - } + croak('unknown compiler $cc') + unless defined $COMPILER{$cc}; - return $OPERATING_SYSTEM{'defaults'}{$what}; + return %{$COMPILER{$cc}}; } sub mach_opt { my ($config) = @_; - my %ccinfo = %{$COMPILER{$$config{'compiler'}}}; + my %ccinfo = my_compiler($config); # Nothing we can do in that case return '' unless defined($ccinfo{'mach_opt_flags'}); @@ -532,8 +599,48 @@ sub libs { ################################################## # Path and file manipulation utilities # ################################################## -sub copy_files { - my ($include_dir, $files) = @_; +sub portable_symlink { + my ($from, $to_dir, $to_fname) = @_; + + my $can_symlink = 0; + my $can_link = 0; + + unless($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'cygwin') { + $can_symlink = eval { symlink("",""); 1 }; + $can_link = eval { link("",""); 1 }; + } + + chdir $to_dir or croak("Can't chdir to $to_dir ($!)"); + + if($can_symlink) { + symlink $from, $to_fname or + croak("Can't symlink $from to $to_fname ($!)"); + } + elsif($can_link) { + link $from, $to_fname or + croak("Can't link $from to $to_fname ($!)"); + } + else { + copy ($from, $to_fname) or + croak("Can't copy $from to $to_fname ($!)"); + } + + my $go_up = File::Spec->splitdir($to_dir); + for(my $j = 0; $j != $go_up; $j++) # return to where we were + { + chdir File::Spec->updir(); + } +} + +sub copy_include_files { + my ($config) = @_; + + my $include_dir = $$config{'build_include_botan'}; + + foreach my $file (dir_list($include_dir)) { + my $path = File::Spec->catfile($include_dir, $file); + unlink $path or croak("Could not unlink $path ($!)"); + } my $link_up = sub { my ($dir, $file) = @_; @@ -543,9 +650,11 @@ sub copy_files { $include_dir, $file); }; - foreach my $file (keys %$files) { - &$link_up($$files{$file}, $file); - } + my $files = $$config{'includes'}; + + foreach my $file (keys %$files) { + &$link_up($$files{$file}, $file); + } } sub dir_list { @@ -559,15 +668,6 @@ sub dir_list { return @listing; } -sub clean_out_dir { - my $dir = $_[0]; - - foreach my $file (dir_list($dir)) { - my $path = File::Spec->catfile($dir, $file); - unlink $path or croak("Could not unlink $path ($!)"); - } -} - sub mkdirs { my (@dirs) = @_; foreach my $dir (@dirs) { @@ -577,34 +677,21 @@ sub mkdirs { } } -sub portable_symlink { - my ($from, $to_dir, $to_fname) = @_; +sub slurp_file { + my $file = $_[0]; - my $can_symlink = 0; - my $can_link = 0; + return '' if(!defined($file) or $file eq ''); - unless($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'cygwin') { - $can_symlink = eval { symlink("",""); 1 }; - $can_link = eval { link("",""); 1 }; - } + croak("'$file': No such file") unless(-e $file); + croak("'$file': Not a regular file") unless(-f $file); - chdir $to_dir or die "Can't chdir to $to_dir ($!)\n"; + open FILE, "<$file" or croak("Couldn't read $file ($!)"); - if($can_symlink) { - symlink $from, $to_fname or die "Can't symlink $from to $to_fname ($!)"; - } - elsif($can_link) { - link $from, $to_fname or die "Can't link $from to $to_fname ($!)"; - } - else { - copy ($from, $to_fname) or die "Can't copy $from to $to_fname ($!)"; - } + my $output = ''; + while(<FILE>) { $output .= $_; } + close FILE; - my $go_up = File::Spec->splitdir($to_dir); - for(my $j = 0; $j != $go_up; $j++) # return to where we were - { - chdir File::Spec->updir(); - } + return $output; } sub which @@ -647,8 +734,8 @@ sub find_mp_bits { my %modinfo = %{ $MODULES{$modname} }; if($modinfo{'mp_bits'}) { if(defined($seen_mp_module) and $modinfo{'mp_bits'} != $mp_bits) { - croak("Inconsistent mp_bits requests from modules ", - $seen_mp_module, " and ", $modname); + croak('Inconsistent mp_bits requests from modules ', + $seen_mp_module, ' and ', $modname); } $seen_mp_module = $modname; @@ -664,10 +751,14 @@ sub find_mp_bits { sub realname { my $arg = $_[0]; - return $COMPILER{$arg}{'realname'} if defined $COMPILER{$arg}; + return $COMPILER{$arg}{'realname'} + if defined $COMPILER{$arg}; + return $OPERATING_SYSTEM{$arg}{'realname'} if defined $OPERATING_SYSTEM{$arg}; - return $CPU{$arg}{'realname'} if defined $CPU{$arg}; + + return $CPU{$arg}{'realname'} + if defined $CPU{$arg}; return $arg; } @@ -684,31 +775,27 @@ sub load_module { my $works_on = sub { my ($what, @lst) = @_; return 1 if not @lst; # empty list -> no restrictions + return 1 if $what eq 'generic'; # trust the user return in_array($what, \@lst); }; # Check to see if everything is OK WRT system requirements my $os = $$config{'os'}; - if($os ne 'generic') { - unless(&$works_on($os, @{$module{'os'}})) { - croak("Module '$modname' does not run on ", realname($os)); - } - } + + croak("Module '$modname' does not run on $os") + unless(&$works_on($os, @{$module{'os'}})); my $arch = $$config{'arch'}; - if($arch ne 'generic') { - my $sub = $$config{'submodel'}; - unless(&$works_on($arch, @{$module{'arch'}}) or - &$works_on($sub, @{$module{'arch'}})) { + my $sub = $$config{'submodel'}; - croak("Module '$modname' does not run on $arch/$sub"); - } - } + croak("Module '$modname' does not run on $arch/$sub") + unless(&$works_on($arch, @{$module{'arch'}}) or + &$works_on($sub, @{$module{'arch'}})); my $cc = $$config{'compiler'}; - unless(&$works_on($cc, @{$module{'cc'}})) { - croak("Module '$modname' does not work with ", realname($cc)); - } + + croak("Module '$modname' does not work with $cc") + unless(&$works_on($cc, @{$module{'cc'}})); sub handle_files { my($modname, $config, $lst, $func) = @_; @@ -732,52 +819,52 @@ sub load_module { ################################################## # # ################################################## +sub file_type { + my ($file) = @_; + + return ('sources', 'src') if($file =~ /\.cpp$/ or $file =~ /\.S$/); + return ('includes', 'include') if($file =~ /\.h$/); + + croak('file_type() - don\'t know what sort of file ', $file, ' is'); +} + sub add_file { my ($modname, $config, $file) = @_; + check_for_file($file, $modname, $modname); my $mod_dir = File::Spec->catdir('modules', $modname); - if($file =~ /\.cpp$/ or $file =~ /\.S$/) { - croak("File $file already added from ", $$config{'sources'}{$file}) - if(defined($$config{'sources'}{$file})); + my $do_add_file = sub { + my ($type) = @_; - $$config{'sources'}{$file} = $mod_dir; - } - elsif($file =~ /\.h$/) { - croak("File $file already added from ", $$config{'includes'}{$file}) - if(defined($$config{'includes'}{$file})); + croak("File $file already added from ", $$config{$type}{$file}) + if(defined($$config{$type}{$file})); - $$config{'includes'}{$file} = $mod_dir; - } - else { - croak("Not sure where to put $file"); - } + $$config{$type}{$file} = $mod_dir; + }; + + &$do_add_file(file_type($file)); } sub ignore_file { my ($modname, $config, $file) = @_; check_for_file($file, undef, $modname); - if($file =~ /\.cpp$/ or $file =~ /\.S$/) { - if(defined ($$config{'sources'}{$file})) { - croak("$modname - File $file modified from ", - $$config{'sources'}{$file}) - if($$config{'sources'}{$file} ne 'src'); + my $do_ignore_file = sub { + my ($type, $ok_if_from) = @_; + + if(defined ($$config{$type}{$file})) { - delete $$config{'sources'}{$file}; - } - } - elsif($file =~ /\.h$/) { - if(defined ($$config{'includes'}{$file})) { croak("$modname - File $file modified from ", - $$config{'includes'}{$file}) - if($$config{'includes'}{$file} ne 'include'); + $$config{$type}{$file}) + if($$config{$type}{$file} ne $ok_if_from); - delete $$config{'includes'}{$file}; + delete $$config{$type}{$file}; } - } - else { croak("Not sure where to put $file"); } + }; + + &$do_ignore_file(file_type($file)); } # This works because ignore file always runs on files in the main source tree, @@ -797,19 +884,14 @@ sub check_for_file { return File::Spec->catfile('modules', $modname, $file) if(defined($modname)); - return File::Spec->catfile('include', $file) - if($file =~ /\.h$/); - - return File::Spec->catfile('src', $file) - if($file =~ /\.cpp$/ or $file =~ /\.S$/); - - croak("Not sure where to put $file"); + my @typeinfo = file_type($file); + return File::Spec->catfile($typeinfo[1], $file); }; $file = &$full_path($file, $added_from); croak("Module $modname requires that file $file exist. This error\n ", - "should never occur; please contact the maintainers with details.") + 'should never occur; please contact the maintainers with details.') unless(-e $file); } @@ -839,7 +921,7 @@ sub process_template { } } - if($contents =~ /@\{var:(.*)\}/ or + if($contents =~ /@\{var:([a-z_]*)\}/ or $contents =~ /@\{if:(.*) /) { croak("Unbound variable '$1' in $in"); } @@ -916,7 +998,9 @@ sub make_reader { # # ################################################## sub read_info_files { - my ($dir,$func) = @_; + my ($dir, $func) = @_; + + $dir = File::Spec->catdir('misc', 'config', $dir); my %allinfo; foreach my $file (dir_list($dir)) { @@ -1102,191 +1186,13 @@ sub get_cc_info { return %info; } -################################################## -# # -################################################## -sub guess_cpu_from_this -{ - my $cpuinfo = lc $_[0]; - my $cpu = ''; - - $cpu = 'amd64' if($cpuinfo =~ /athlon64/); - $cpu = 'amd64' if($cpuinfo =~ /opteron/); - - $cpu = 'athlon' if($cpuinfo =~ /athlon/); - $cpu = 'pentium4' if($cpuinfo =~ /pentium 4/); - $cpu = 'pentium4' if($cpuinfo =~ /pentium\(r\) 4/); - $cpu = 'pentium3' if($cpuinfo =~ /pentium iii/); - $cpu = 'pentium2' if($cpuinfo =~ /pentium ii/); - $cpu = 'pentium3' if($cpuinfo =~ /pentium 3/); - $cpu = 'pentium2' if($cpuinfo =~ /pentium 2/); - - # The 32-bit SPARC stuff is impossible to match to arch type easily, and - # anyway the uname stuff will pick up that it's a SPARC so it doesn't - # matter. If it's an Ultra, assume a 32-bit userspace, no 64-bit code - # possible; that's the most common setup right now anyway - $cpu = 'sparc32-v9' if($cpuinfo =~ /ultrasparc/); - - # 64-bit PowerPC - $cpu = 'rs64a' if($cpuinfo =~ /rs64-/); - $cpu = 'power3' if($cpuinfo =~ /power3/); - $cpu = 'power4' if($cpuinfo =~ /power4/); - $cpu = 'power5' if($cpuinfo =~ /power5/); - $cpu = 'ppc970' if($cpuinfo =~ /ppc970/); - - # Ooh, an Alpha. Try to figure out what kind - if($cpuinfo =~ /alpha/) - { - $cpu = 'alpha-ev4' if($cpuinfo =~ /ev4/); - $cpu = 'alpha-ev5' if($cpuinfo =~ /ev5/); - $cpu = 'alpha-ev56' if($cpuinfo =~ /ev56/); - $cpu = 'alpha-pca56' if($cpuinfo =~ /pca56/); - $cpu = 'alpha-ev6' if($cpuinfo =~ /ev6/); - $cpu = 'alpha-ev67' if($cpuinfo =~ /ev67/); - $cpu = 'alpha-ev68' if($cpuinfo =~ /ev68/); - $cpu = 'alpha-ev7' if($cpuinfo =~ /ev7/); - } - - return $cpu; -} - -# Do some WAGing and see if we can figure out what system we are. Think about -# this as a really moronic config.guess -sub guess_triple -{ - # /bin/sh, good bet we're on something Unix-y (at least it'll have uname) - if(-f '/bin/sh') - { - my $os = lc `uname -s 2>/dev/null`; chomp $os; - - # Let the crappy hacks commence! - - # Cygwin's uname -s is cygwin_<windows version> - $os = 'cygwin' if($os =~ /^cygwin/); - $os = os_alias($os); - - if(!defined $OPERATING_SYSTEM{$os}) - { - warning("Unknown uname -s output: $os, falling back to 'generic'"); - $os = 'generic'; - } - - my $cpu = ''; - - # If we have /proc/cpuinfo, try to get nice specific information about - # what kind of CPU we're running on. - if(-e '/proc/cpuinfo' and -r '/proc/cpuinfo') - { - open CPUINFO, '/proc/cpuinfo' or - die "Couldn't read /proc/cpuinfo ($!)\n"; - - my $cpuinfo = join('', <CPUINFO>); - close CPUINFO; - - $cpu = guess_cpu_from_this($cpuinfo); - } - - # `umame -p` is sometimes something stupid like unknown, but in some - # cases it can be more specific (useful) than `uname -m` - if($cpu eq '') # no guess so far - { - my $uname_p = `uname -p 2>/dev/null`; - chomp $uname_p; - $cpu = guess_cpu_from_this($uname_p); - - # If guess_cpu_from_this didn't figure it out, try it plain - if($cpu eq '') { $cpu = lc $uname_p; } - - my (%SUBMODEL_ALIAS, %ARCH_ALIAS, %ARCH); - - foreach my $arch (keys %CPU) { - my %info = %{$CPU{$arch}}; - - $ARCH{$arch} = $info{'name'}; - foreach my $submodel (@{$info{'submodels'}}) { - $ARCH{$submodel} = $info{'name'}; - } - - foreach my $alias (@{$info{'aliases'}}) { - $ARCH_ALIAS{$alias} = $arch; - } - - if(defined($info{'submodel_aliases'})) { - my %submodel_aliases = %{$info{'submodel_aliases'}}; - foreach my $sm_alias (keys %submodel_aliases) { - $SUBMODEL_ALIAS{$sm_alias} = - $submodel_aliases{$sm_alias}; - } - } - } - - if(!defined $ARCH{$cpu} && !defined $SUBMODEL_ALIAS{$cpu} && - !defined $ARCH_ALIAS{$cpu}) - { - # Nope, couldn't figure out uname -p - $cpu = lc `uname -m 2>/dev/null`; - chomp $cpu; - - if(!defined $ARCH{$cpu} && !defined $SUBMODEL_ALIAS{$cpu} && - !defined $ARCH_ALIAS{$cpu}) - { - $cpu = 'generic'; - } - } - } - - my @CCS = ('gcc', 'icc', 'compaq', 'kai'); # Skips several, oh well... - - # First try the CC enviornmental variable, if it's set - if(defined($ENV{CC})) - { - my @new_CCS = ($ENV{CC}); - foreach my $cc (@CCS) { push @new_CCS, $cc; } - @CCS = @new_CCS; - } - - my $cc = ''; - foreach (@CCS) - { - my $bin_name = $COMPILER{$_}{'binary_name'}; - $cc = $_ if(which($bin_name) ne ''); - last if($cc ne ''); - } - - if($cc eq '') { - my $msg = - "Can't find a usable C++ compiler, is your PATH right?\n" . - "You might need to run with explicit compiler/system flags;\n" . - " run '$0 --help' for more information\n"; - croak($msg); - } - - return "$cc-$os-$cpu"; - } - elsif($^O eq 'MSWin32' or $^O eq 'dos') - { - my $os = 'windows'; # obviously - - # Suggestions on this? The Win32 'shell' env is not so hot. We could - # try using cpuinfo, except that will crash hard on NT/Alpha (like what - # we're doing now won't!). In my defense of choosing i686: - # a) There are maybe a few hundred Alpha/MIPS boxes running NT4 today - # b) Anyone running Windows on < Pentium Pro deserves to lose. - my $cpu = 'i686'; - - # No /bin/sh, so not cygwin. Assume VC++; again, this could be much - # smarter - my $cc = 'msvc'; - return "$cc-$os-$cpu"; - } - else - { - croak("Autoconfiguration failed (try --help)"); - } -} - sub guess_mods { - my ($cc, $os, $arch, $submodel) = @_; + my ($config) = @_; + + my $cc = $$config{'compiler'}; + my $os = $$config{'os'}; + my $arch = $$config{'arch'}; + my $submodel = $$config{'submodel'}; my @usable_modules; @@ -1338,33 +1244,17 @@ sub defines { push @defarray, split(/,/, $defs); } foreach (sort @defarray) { - next if not defined $_ or not $_; + next unless(defined $_ and $_ ne ''); $defines .= "#define BOTAN_EXT_$_\n"; } chomp($defines); return $defines; } -sub slurp_file { - my $file = $_[0]; - return '' if(!defined($file) or $file eq ''); - - croak("'$file': No such file") unless(-e $file); - croak("'$file': Not a regular file") unless(-f $file); - - open FILE, "<$file" or croak("Couldn't read $file ($!)"); - - my $output = ''; - while(<FILE>) { $output .= $_; } - close FILE; - - return $output; -} - ################################################## # # ################################################## -sub print_pkg_config { +sub write_pkg_config { my ($config) = @_; return if($$config{'os'} eq 'generic' or @@ -1374,19 +1264,80 @@ sub print_pkg_config { process_template(File::Spec->catfile('misc', 'config', 'botan-config.in'), 'botan-config', $config); + chmod 0755, 'botan-config'; delete $$config{'link_to'}; - - chmod 0755, 'botan-config'; } ################################################## # # ################################################## -sub empty_if_nil { - my $val = $_[0]; - return $val if defined($val); - return ''; +sub file_list { + my ($put_in, $from, $to, %files) = @_; + my $spaces = 16; + + my $list = ''; + + my $len = $spaces; + foreach (sort keys %files) { + my $file = $_; + + if($len > 60) { + $list .= "\\\n" . ' 'x$spaces; + $len = $spaces; + } + + $file =~ s/$from/$to/ if(defined($from) and defined($to)); + + my $dir = $files{$_}; + $dir = $put_in if defined $put_in; + + if(defined($dir)) { + $list .= File::Spec->catfile ($dir, $file) . ' '; + $len += length($file) + length($dir); + } + else { + $list .= $file . ' '; + $len += length($file); + } + } + + return $list; +} + +sub build_cmds { + my ($config, $dir, $flags, $files) = @_; + + my $output = ''; + + my $obj_suffix = $$config{'obj_suffix'}; + + my %ccinfo = my_compiler($config); + + my $inc = $ccinfo{'add_include_dir_option'}; + my $from = $ccinfo{'compile_option'}; + my $to = $ccinfo{'output_to_option'}; + + my $inc_dir = $$config{'build_include'}; + + # Probably replace by defaults to -I -c -o + croak('undef value found in build_cmds') + unless defined($inc) and defined($from) and defined($to); + + my $bld_line = "\t\$(CXX) $inc$inc_dir $flags $from\$? $to\$@"; + + foreach (sort keys %$files) { + my $src_file = File::Spec->catfile($$files{$_}, $_); + my $obj_file = File::Spec->catfile($dir, $_); + + $obj_file =~ s/\.cpp$/.$obj_suffix/; + $obj_file =~ s/\.S$/.$obj_suffix/; + + $output .= "$obj_file: $src_file\n$bld_line\n\n"; + } + chomp($output); + chomp($output); + return $output; } sub generate_makefile { @@ -1400,7 +1351,8 @@ sub generate_makefile { sub append_if { my($var,$addme,$cond) = @_; - die unless defined $var; + + croak('append_if: reference was undef') unless defined $var; if($cond and $addme ne '') { $$var .= ' ' unless($$var eq '' or $$var =~ / $/); @@ -1413,9 +1365,13 @@ sub generate_makefile { append_if($var, $addme, defined($addme)); } + my $empty_if_nil = sub { + my $val = $_[0]; + return $val if defined($val); + return ''; + }; - my $cc = $$config{'compiler'}; - my %ccinfo = %{$COMPILER{$cc}}; + my %ccinfo = my_compiler($config); my $lang_flags = ''; append_ifdef(\$lang_flags, $ccinfo{'lang_flags'}); @@ -1459,17 +1415,19 @@ sub generate_makefile { (in_array('all', $OPERATING_SYSTEM{$os}{'supports_shared'}) or in_array($arch, $OPERATING_SYSTEM{$os}{'supports_shared'}))) { - $$config{'so_obj_flags'} = empty_if_nil($ccinfo{'so_obj_flags'}); - $$config{'so_link'} = empty_if_nil($ccinfo{'so_link_flags'}{$os}); + $$config{'so_obj_flags'} = &$empty_if_nil($ccinfo{'so_obj_flags'}); + $$config{'so_link'} = &$empty_if_nil($ccinfo{'so_link_flags'}{$os}); - $$config{'so_link'} = empty_if_nil($ccinfo{'so_link_flags'}{'default'}) - if($$config{'so_link'} eq ''); + if($$config{'so_link'} eq '') { + $$config{'so_link'} = + &$empty_if_nil($ccinfo{'so_link_flags'}{'default'}) + } if($$config{'so_obj_flags'} eq '' and $$config{'so_link'} eq '') { $$config{'shared'} = 'no'; - warning("$cc has no shared object flags set for $os;\n", - " disabling creation of shared objects"); + warning($$config{'compiler'}, ' has no shared object flags set ', + "for $os; disabling shared"); } } else { @@ -1481,10 +1439,10 @@ sub generate_makefile { add_to($config, { 'cc' => $ccinfo{'binary_name'} . $abi_opts, 'lib_opt' => $lib_opt_flags, - 'check_opt' => empty_if_nil($ccinfo{'check_opt_flags'}), + 'check_opt' => &$empty_if_nil($ccinfo{'check_opt_flags'}), 'mach_opt' => mach_opt($config), 'lang_flags' => $lang_flags, - 'warn_flags' => empty_if_nil($ccinfo{'warning_flags'}), + 'warn_flags' => &$empty_if_nil($ccinfo{'warning_flags'}), 'ar_command' => $ar_command, 'ranlib_command' => $ranlib_command, @@ -1492,10 +1450,10 @@ sub generate_makefile { 'so_suffix' => os_info_for($os, 'so_suffix'), 'obj_suffix' => os_info_for($os, 'obj_suffix'), - 'install_cmd_exec' => os_install_info($os, 'install_cmd_exec'), - 'install_cmd_data' => os_install_info($os, 'install_cmd_data'), - 'install_user' => os_install_info($os, 'install_user'), - 'install_group' => os_install_info($os, 'install_group'), + 'install_cmd_exec' => os_info_for($os, 'install_cmd_exec'), + 'install_cmd_data' => os_info_for($os, 'install_cmd_data'), + 'install_user' => os_info_for($os, 'install_user'), + 'install_group' => os_info_for($os, 'install_group'), }); my $docs = file_list(undef, undef, undef, map { $_ => 'doc' } @DOCS); @@ -1534,7 +1492,6 @@ sub generate_makefile { my $make_style = $$config{'make_style'}; - if($make_style eq 'unix') { $template = File::Spec->catfile($template_dir, 'unix.in'); @@ -1558,9 +1515,8 @@ sub generate_makefile { }); } - croak("This configure script does not know how to make ", - "a makefile for makefile style \"$make_style\"") - unless(defined($template)); + croak("Don't know about makefile format '$make_style'") + unless defined $template; trace("mapped type '$make_style' to template '$template'"); @@ -1568,70 +1524,184 @@ sub generate_makefile { } ################################################## -# # +# Configuration Guessing # ################################################## -sub file_list { - my ($put_in, $from, $to, %files) = @_; - my $spaces = 16; +sub guess_cpu_from_this +{ + my $cpuinfo = lc $_[0]; + my $cpu = ''; - my $list = ''; + $cpu = 'amd64' if($cpuinfo =~ /athlon64/); + $cpu = 'amd64' if($cpuinfo =~ /opteron/); - my $len = $spaces; - foreach (sort keys %files) { - my $file = $_; + $cpu = 'athlon' if($cpuinfo =~ /athlon/); + $cpu = 'pentium4' if($cpuinfo =~ /pentium 4/); + $cpu = 'pentium4' if($cpuinfo =~ /pentium\(r\) 4/); + $cpu = 'pentium3' if($cpuinfo =~ /pentium iii/); + $cpu = 'pentium2' if($cpuinfo =~ /pentium ii/); + $cpu = 'pentium3' if($cpuinfo =~ /pentium 3/); + $cpu = 'pentium2' if($cpuinfo =~ /pentium 2/); - if($len > 60) { - $list .= "\\\n" . ' 'x$spaces; - $len = $spaces; - } + # The 32-bit SPARC stuff is impossible to match to arch type easily, and + # anyway the uname stuff will pick up that it's a SPARC so it doesn't + # matter. If it's an Ultra, assume a 32-bit userspace, no 64-bit code + # possible; that's the most common setup right now anyway + $cpu = 'sparc32-v9' if($cpuinfo =~ /ultrasparc/); - $file =~ s/$from/$to/ if(defined($from) and defined($to)); + # 64-bit PowerPC + $cpu = 'rs64a' if($cpuinfo =~ /rs64-/); + $cpu = 'power3' if($cpuinfo =~ /power3/); + $cpu = 'power4' if($cpuinfo =~ /power4/); + $cpu = 'power5' if($cpuinfo =~ /power5/); + $cpu = 'ppc970' if($cpuinfo =~ /ppc970/); - my $dir = $files{$_}; - $dir = $put_in if defined $put_in; + # Ooh, an Alpha. Try to figure out what kind + if($cpuinfo =~ /alpha/) + { + $cpu = 'alpha-ev4' if($cpuinfo =~ /ev4/); + $cpu = 'alpha-ev5' if($cpuinfo =~ /ev5/); + $cpu = 'alpha-ev56' if($cpuinfo =~ /ev56/); + $cpu = 'alpha-pca56' if($cpuinfo =~ /pca56/); + $cpu = 'alpha-ev6' if($cpuinfo =~ /ev6/); + $cpu = 'alpha-ev67' if($cpuinfo =~ /ev67/); + $cpu = 'alpha-ev68' if($cpuinfo =~ /ev68/); + $cpu = 'alpha-ev7' if($cpuinfo =~ /ev7/); + } - if(defined($dir)) { - $list .= File::Spec->catfile ($dir, $file) . ' '; - $len += length($file) + length($dir); + return $cpu; +} + +# Do some WAGing and see if we can figure out what system we are. Think about +# this as a really moronic config.guess +sub guess_triple +{ + # /bin/sh, good bet we're on something Unix-y (at least it'll have uname) + if(-f '/bin/sh') + { + my $os = lc `uname -s 2>/dev/null`; chomp $os; + + # Let the crappy hacks commence! + + # Cygwin's uname -s is cygwin_<windows version> + $os = 'cygwin' if($os =~ /^cygwin/); + $os = os_alias($os); + + if(!defined $OPERATING_SYSTEM{$os}) + { + warning("Unknown uname -s output: $os, falling back to 'generic'"); + $os = 'generic'; } - else { - $list .= $file . ' '; - $len += length($file); + + my $cpu = ''; + + # If we have /proc/cpuinfo, try to get nice specific information about + # what kind of CPU we're running on. + if(-e '/proc/cpuinfo' and -r '/proc/cpuinfo') + { + open CPUINFO, '/proc/cpuinfo' or + croak("Couldn't read /proc/cpuinfo ($!)"); + + my $cpuinfo = join('', <CPUINFO>); + close CPUINFO; + + $cpu = guess_cpu_from_this($cpuinfo); } - } - return $list; -} + # `umame -p` is sometimes something stupid like unknown, but in some + # cases it can be more specific (useful) than `uname -m` + if($cpu eq '') # no guess so far + { + my $uname_p = `uname -p 2>/dev/null`; + chomp $uname_p; + $cpu = guess_cpu_from_this($uname_p); -sub build_cmds { - my ($config, $dir, $flags, $files) = @_; + # If guess_cpu_from_this didn't figure it out, try it plain + if($cpu eq '') { $cpu = lc $uname_p; } - my $output = ''; + my (%SUBMODEL_ALIAS, %ARCH_ALIAS, %ARCH); - my $cc = $$config{'compiler'}; - my $obj_suffix = $$config{'obj_suffix'}; + foreach my $arch (keys %CPU) { + my %info = %{$CPU{$arch}}; - my $inc = $COMPILER{$cc}{'add_include_dir_option'}; - my $from = $COMPILER{$cc}{'compile_option'}; - my $to = $COMPILER{$cc}{'output_to_option'}; + $ARCH{$arch} = $info{'name'}; + foreach my $submodel (@{$info{'submodels'}}) { + $ARCH{$submodel} = $info{'name'}; + } - my $inc_dir = $$config{'build_include'}; + foreach my $alias (@{$info{'aliases'}}) { + $ARCH_ALIAS{$alias} = $arch; + } - # Probably replace by defaults to -I -c -o - die unless defined($inc) and defined($from) and defined($to); + if(defined($info{'submodel_aliases'})) { + my %submodel_aliases = %{$info{'submodel_aliases'}}; + foreach my $sm_alias (keys %submodel_aliases) { + $SUBMODEL_ALIAS{$sm_alias} = + $submodel_aliases{$sm_alias}; + } + } + } - my $bld_line = "\t\$(CXX) $inc$inc_dir $flags $from\$? $to\$@"; + if(!defined $ARCH{$cpu} && !defined $SUBMODEL_ALIAS{$cpu} && + !defined $ARCH_ALIAS{$cpu}) + { + # Nope, couldn't figure out uname -p + $cpu = lc `uname -m 2>/dev/null`; + chomp $cpu; - foreach (sort keys %$files) { - my $src_file = File::Spec->catfile($$files{$_}, $_); - my $obj_file = File::Spec->catfile($dir, $_); + if(!defined $ARCH{$cpu} && !defined $SUBMODEL_ALIAS{$cpu} && + !defined $ARCH_ALIAS{$cpu}) + { + $cpu = 'generic'; + } + } + } - $obj_file =~ s/\.cpp$/.$obj_suffix/; - $obj_file =~ s/\.S$/.$obj_suffix/; + my @CCS = ('gcc', 'icc', 'compaq', 'kai'); # Skips several, oh well... - $output .= "$obj_file: $src_file\n$bld_line\n\n"; + # First try the CC enviornmental variable, if it's set + if(defined($ENV{CC})) + { + my @new_CCS = ($ENV{CC}); + foreach my $cc (@CCS) { push @new_CCS, $cc; } + @CCS = @new_CCS; + } + + my $cc = ''; + foreach (@CCS) + { + my $bin_name = $COMPILER{$_}{'binary_name'}; + $cc = $_ if(which($bin_name) ne ''); + last if($cc ne ''); + } + + if($cc eq '') { + my $msg = + "Can't find a usable C++ compiler, is your PATH right?\n" . + "You might need to run with explicit compiler/system flags;\n" . + " run '$0 --help' for more information\n"; + croak($msg); + } + + return "$cc-$os-$cpu"; + } + elsif($^O eq 'MSWin32' or $^O eq 'dos') + { + my $os = 'windows'; # obviously + + # Suggestions on this? The Win32 'shell' env is not so hot. We could + # try using cpuinfo, except that will crash hard on NT/Alpha (like what + # we're doing now won't!). In my defense of choosing i686: + # a) There are maybe a few hundred Alpha/MIPS boxes running NT4 today + # b) Anyone running Windows on < Pentium Pro deserves to lose. + my $cpu = 'i686'; + + # No /bin/sh, so not cygwin. Assume VC++; again, this could be much + # smarter + my $cc = 'msvc'; + return "$cc-$os-$cpu"; + } + else + { + croak('Autoconfiguration failed (try --help)'); } - chomp($output); - chomp($output); - return $output; } |