Below is the file 'configure.pl' from this revision. You can also download the file.

#!/usr/bin/perl -w

# Warning: This file is machine-generated; any changes will be lost. Instead,
# change mkconfig.pl and the system description files. If you find a bug in
# this program (such as generation of incorrect options), please mail
# lloyd@randombit.net with details.

# This file is in the public domain.

# It actually runs on a lot of 5.005 installs, but not all...
require 5.006;

use strict;
use DirHandle;
use Getopt::Long;
use File::Spec;
use File::Copy;

my $PROJECT_NAME    = 'Botan';
my $PROJECT_NAME_LC = lc $PROJECT_NAME;

my $MAJOR_VERSION = 1;
my $MINOR_VERSION = 5;
my $PATCH_VERSION = 8;

# If 1, then we always copy include files, without attempting to make symlinks
# or hardlinks. It seems that link("","") will succeed on Windows, but the
# actual operation will fail (FAT32 doesn't support any kind of links).
# This is automatically forced if $^O is 'dos', 'MSWin32', or 'cygwin'
my $FORCE_COPY = 0;

# A whole buncha filenames
my $INCLUDE_DIR = 'include';
my $SRC_DIR = 'src';
my $MOD_DIR = 'modules';
my $CHECK_DIR = 'checks';
my $DOC_DIR = 'doc';
my $BUILD_DIR = 'build';
my $BUILD_DIR_LIB = 'lib';
my $BUILD_DIR_CHECKS = 'checks';
my $MAKE_FILE = 'Makefile';
my $BUILD_INCLUDE_DIR = 'build/include';

my $CONFIG_HEADER = 'config.h';

my $CPP_INCLUDE_DIR_DIRNAME = $PROJECT_NAME_LC;

# Available module sets
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' ],
);

# Documentation list
my %DOCS = (
   'readme.txt' => undef, # undef = file is in top level directory

   'pgpkeys.asc' => $DOC_DIR,

   'api.pdf' => $DOC_DIR,
   'tutorial.pdf' => $DOC_DIR,
   'fips140.pdf' => $DOC_DIR,

   'api.tex' => $DOC_DIR,
   'tutorial.tex' => $DOC_DIR,
   'fips140.tex' => $DOC_DIR,

   'botan.rc' => $DOC_DIR,

   'credits.txt' => $DOC_DIR,
#   'deprecated.txt' => $DOC_DIR,
   'info.txt' => $DOC_DIR,
   'license.txt' => $DOC_DIR,
   'log.txt' => $DOC_DIR,
   'thanks.txt' => $DOC_DIR,
   'todo.txt' => $DOC_DIR
   );
my %ARCH = (
   '68020'          => 'm68k',
   '68030'          => 'm68k',
   '68040'          => 'm68k',
   '68060'          => 'm68k',
   'alpha'          => 'alpha',
   'alpha-ev4'      => 'alpha',
   'alpha-ev5'      => 'alpha',
   'alpha-ev56'     => 'alpha',
   'alpha-ev6'      => 'alpha',
   'alpha-ev67'     => 'alpha',
   'alpha-ev68'     => 'alpha',
   'alpha-ev7'      => 'alpha',
   'alpha-pca56'    => 'alpha',
   'amd64'          => 'amd64',
   'arm'            => 'arm',
   'arm2'           => 'arm',
   'arm3'           => 'arm',
   'arm6'           => 'arm',
   'arm7'           => 'arm',
   'arm8'           => 'arm',
   'arm9'           => 'arm',
   'athlon'         => 'ia32',
   'athlon64'       => 'amd64',
   'em64t'          => 'amd64',
   'hppa'           => 'hppa',
   'hppa1.0'        => 'hppa',
   'hppa1.1'        => 'hppa',
   'hppa2.0'        => 'hppa',
   'i386'           => 'ia32',
   'i486'           => 'ia32',
   'i586'           => 'ia32',
   'i686'           => 'ia32',
   'ia32'           => 'ia32',
   'ia64'           => 'ia64',
   'k6'             => 'ia32',
   'm68k'           => 'm68k',
   'mip32-r3000'    => 'mips32',
   'mip32-r6000'    => 'mips32',
   'mips32'         => 'mips32',
   'mips64'         => 'mips64',
   'mips64-r10000'  => 'mips64',
   'mips64-r4000'   => 'mips64',
   'mips64-r4100'   => 'mips64',
   'mips64-r4300'   => 'mips64',
   'mips64-r4400'   => 'mips64',
   'mips64-r4560'   => 'mips64',
   'mips64-r4600'   => 'mips64',
   'mips64-r5000'   => 'mips64',
   'mips64-r8000'   => 'mips64',
   'opteron'        => 'amd64',
   'pentium4'       => 'ia32',
   'power3'         => 'ppc64',
   'power4'         => 'ppc64',
   'power5'         => 'ppc64',
   'ppc'            => 'ppc',
   'ppc601'         => 'ppc',
   'ppc603'         => 'ppc',
   'ppc604'         => 'ppc',
   'ppc64'          => 'ppc64',
   'ppc740'         => 'ppc',
   'ppc7400'        => 'ppc',
   'ppc7450'        => 'ppc',
   'ppc750'         => 'ppc',
   'ppc970'         => 'ppc64',
   'rs64a'          => 'ppc64',
   's390'           => 's390',
   's390x'          => 's390x',
   'sh'             => 'sh',
   'sh1'            => 'sh',
   'sh2'            => 'sh',
   'sh3'            => 'sh',
   'sh3e'           => 'sh',
   'sh4'            => 'sh',
   'sparc32'        => 'sparc32',
   'sparc32-v7'     => 'sparc32',
   'sparc32-v8'     => 'sparc32',
   'sparc32-v9'     => 'sparc32',
   'sparc64'        => 'sparc64',
   'sparc64-ultra'  => 'sparc64',
   'sparc64-ultra2' => 'sparc64',
   'sparc64-ultra3' => 'sparc64',
   'strongarm'      => 'arm',
   'strongarm110'   => 'arm',
   'strongarm1100'  => 'arm',
   'xscale'         => 'arm',
);

my %ARCH_ALIAS = (
   '680x0'          => 'm68k',
   '68k'            => 'm68k',
   '80x86'          => 'ia32',
   'alphaaxp'       => 'alpha',
   'athlon64'       => 'amd64',
   'axp'            => 'alpha',
   'hp-pa'          => 'hppa',
   'hp-pa-risc'     => 'hppa',
   'hp-parisc'      => 'hppa',
   'i86pc'          => 'ia32',
   'itanium'        => 'ia64',
   'ix86'           => 'ia32',
   'merced'         => 'ia64',
   'mips'           => 'mips32',
   'opteron'        => 'amd64',
   'pa-risc'        => 'hppa',
   'parisc'         => 'hppa',
   'powerpc'        => 'ppc',
   'sparc'          => 'sparc32',
   'x86'            => 'ia32',
   'x86-64'         => 'amd64',
   'x86_64'         => 'amd64',
);

my %DEFAULT_SUBMODEL = (
   'alpha'          => 'alpha-ev5',
   'amd64'          => 'amd64',
   'arm'            => 'arm2',
   'hppa'           => 'hppa1.1',
   'ia32'           => 'i586',
   'ia64'           => 'ia64',
   'm68k'           => '68040',
   'mips32'         => 'r3000',
   'mips64'         => 'r4400',
   'ppc'            => 'ppc740',
   'ppc64'          => 'power4',
   's390'           => 's390',
   's390x'          => 's390x',
   'sh'             => 'sh1',
   'sparc32'        => 'sparc32-v8',
   'sparc64'        => 'sparc64-ultra',
);

my %SUBMODEL_ALIAS = (
   'alphaev4'       => 'alpha-ev4',
   'alphaev5'       => 'alpha-ev5',
   'alphaev56'      => 'alpha-ev56',
   'alphaev6'       => 'alpha-ev6',
   'alphaev67'      => 'alpha-ev67',
   'alphaev68'      => 'alpha-ev68',
   'alphaev7'       => 'alpha-ev7',
   'alphapca56'     => 'alpha-pca56',
   'athlon-xp'      => 'athlon',
   'cypress'        => 'sparc32-v7',
   'duron'          => 'athlon',
   'g3'             => 'ppc740',
   'g4'             => 'ppc7450',
   'g5'             => 'ppc970',
   'hypersparc'     => 'sparc32-v8',
   'k7'             => 'athlon',
   'microsparc'     => 'sparc32-v8',
   'mipsbe'         => 'mips3000',
   'mipsle'         => 'mips3000',
   'p2'             => 'i686',
   'p3'             => 'i686',
   'p4'             => 'pentium4',
   'pentium'        => 'i586',
   'pentium2'       => 'i686',
   'pentium3'       => 'i686',
   'pentium_pro'    => 'i686',
   'pentiumpro'     => 'i686',
   'r10000'         => 'mips64-r10000',
   'r10k'           => 'mips64-r10000',
   'r3000'          => 'mips32-r3000',
   'r3k'            => 'mips32-r3000',
   'r4000'          => 'mips64-r4000',
   'r4100'          => 'mips64-r4100',
   'r4300'          => 'mips64-r4300',
   'r4400'          => 'mips64-r4400',
   'r4560'          => 'mips64-r4560',
   'r4600'          => 'mips64-r4600',
   'r4k'            => 'mips64-r4000',
   'r5000'          => 'mips64-r5000',
   'r5k'            => 'mips64-r5000',
   'r6000'          => 'mips32-r6000',
   'r6k'            => 'mips32-r6000',
   'r8000'          => 'mips64-r8000',
   'r8k'            => 'mips64-r8000',
   'sa110'          => 'strongarm110',
   'sa1100'         => 'strongarm1100',
   'sparc-v7'       => 'sparc32-v7',
   'sparc-v8'       => 'sparc32-v8',
   'sparc-v9'       => 'sparc32-v9',
   'sparclite'      => 'sparc32-v8',
   'sparcv7'        => 'sparc32-v7',
   'sparcv8'        => 'sparc32-v8',
   'sparcv9'        => 'sparc32-v9',
   'strongarm1110'  => 'strongarm1100',
   'supersparc'     => 'sparc32-v8',
   'ultrasparc'     => 'sparc64-ultra',
   'ultrasparc2'    => 'sparc64-ultra2',
   'ultrasparc3'    => 'sparc64-ultra3',
);

my %OS_SUPPORTS_ARCH = (
   'aix'        => [ 'ia64', 'ppc', 'ppc64', ],
   'beos'       => [ 'ia32', 'ppc', ],
   'cygwin'     => [ 'amd64', 'ia32', 'ia64', ],
   'darwin'     => [ 'ia32', 'ppc', 'ppc64', ],
   'freebsd'    => [ 'alpha', 'amd64', 'ia32', 'ia64', 'powerpc', 'sparc64',
                     ],
   'hpux'       => [ 'hppa', 'ia64', ],
   'irix'       => [ 'mips32', 'mips64', ],
   'linux'      => [ 'alpha', 'amd64', 'arm', 'hppa', 'ia32', 'ia64', 'm68k',
                     'mips32', 'mips64', 'ppc', 'ppc64', 's390', 's390x', 'sh',
                     'sparc32', 'sparc64', ],
   'netbsd'     => [ 'alpha', 'amd64', 'arm', 'hppa', 'ia32', 'ia64', 'm68k',
                     'mips32', 'mips64', 'ppc', 'sparc32', ],
   'openbsd'    => [ 'alpha', 'ia32', 'm68k', 'mips32', 'ppc', 'sparc32', 'sparc64',
                     ],
   'qnx'        => [ 'arm', 'ia32', 'mips32', 'ppc', 'sh', ],
   'solaris'    => [ 'ia32', 'sparc32', 'sparc64', ],
   'tru64'      => [ 'alpha', ],
   'windows'    => [ 'amd64', 'ia32', 'ia64', ],
);

my %OS_SUPPORTS_SHARED = (
   'aix'        => [ 'all', ],
   'beos'       => [ 'all', ],
   'darwin'     => [ 'all', ],
   'freebsd'    => [ 'all', ],
   'hpux'       => [ 'all', ],
   'irix'       => [ 'all', ],
   'linux'      => [ 'all', ],
   'netbsd'     => [ 'all', ],
   'openbsd'    => [ 'all', ],
   'qnx'        => [ 'all', ],
   'solaris'    => [ 'all', ],
   'tru64'      => [ 'all', ],
);

my %OS_TYPE = (
   'aix'            => 'unix',
   'beos'           => 'beos',
   'cygwin'         => 'unix',
   'darwin'         => 'unix',
   'freebsd'        => 'unix',
   'hpux'           => 'unix',
   'irix'           => 'unix',
   'linux'          => 'unix',
   'netbsd'         => 'unix',
   'openbsd'        => 'unix',
   'qnx'            => 'unix',
   'solaris'        => 'unix',
   'tru64'          => 'unix',
   'windows'        => 'windows',
);

my %OS_OBJ_SUFFIX = (
   'defaults'       => 'o',
   'windows'        => 'obj',
);

my %OS_SHARED_SUFFIX = (
   'darwin'         => 'dylib',
   'defaults'       => 'so',
   'hpux'           => 'sl',
   'windows'        => 'dll',
);

my %OS_STATIC_SUFFIX = (
   'defaults'       => 'a',
   'windows'        => 'lib',
);

my %OS_AR_COMMAND = (
   'darwin'         => 'ar cr',
   'defaults'       => 'ar crs',
);

my %OS_AR_NEEDS_RANLIB = (
   'darwin'         => '1',
   'defaults'       => '0',
);

my %OS_ALIAS = (
   'haiku'          => 'beos',
   'hp-ux'          => 'hpux',
   'macosx'         => 'darwin',
   'osf1'           => 'tru64',
   'sunos'          => 'solaris',
);

my %INSTALL_INFO = (
   'beos'       => {
      'docs'       => 'documentation',
      'headers'    => '../develop/headers',
      'libs'       => 'system/lib',
      'root'       => '/boot/beos',
      },
   'cygwin'     => {
      'docs'       => 'docs',
      'root'       => 'c:\Botan',
      },
   'darwin'     => {
      'docs'       => 'doc',
      'group'      => 'wheel',
      },
   'defaults'   => {
      'command'    => 'install -o OWNER -g GROUP -m MODE',
      'docs'       => 'share/doc',
      'group'      => 'root',
      'headers'    => 'include',
      'libs'       => 'lib',
      'root'       => '/usr/local',
      'user'       => 'root',
      },
   'freebsd'    => {
      'group'      => 'wheel',
      },
   'netbsd'     => {
      'group'      => 'wheel',
      },
   'openbsd'    => {
      'group'      => 'wheel',
      },
   'solaris'    => {
      'command'    => 'install -u OWNER -g GROUP -m MODE',
      },
   'windows'    => {
      'docs'       => 'docs',
      'root'       => 'c:\Botan',
      },
);

my %CC_SUPPORTS_OS = (
   'bcc'        => [ 'windows', ],
   'compaq'     => [ 'linux', 'tru64', ],
   'ekopath'    => [ 'linux', ],
   'gcc'        => [ 'aix', 'beos', 'cygwin', 'darwin', 'freebsd', 'hpux', 'irix',
                     'linux', 'netbsd', 'openbsd', 'qnx', 'solaris', 'tru64',
                     'windows', ],
   'hpcc'       => [ 'hpux', ],
   'icc'        => [ 'linux', ],
   'kai'        => [ 'hpux', 'irix', 'linux', 'solaris', 'tru64', ],
   'mipspro'    => [ 'irix', ],
   'msvc'       => [ 'windows', ],
   'pgi'        => [ 'linux', 'solaris', ],
   'sgipro64'   => [ 'linux', ],
   'sunwspro'   => [ 'solaris', ],
);

my %CC_SUPPORTS_ARCH = (
   'bcc'        => [ 'ia32', ],
   'compaq'     => [ 'alpha', ],
   'ekopath'    => [ 'amd64', 'ia32', ],
   'gcc'        => [ 'alpha', 'amd64', 'arm', 'hppa', 'ia32', 'ia64', 'm68k',
                     'mips32', 'mips64', 'ppc', 'ppc64', 's390', 's390x', 'sh',
                     'sparc32', 'sparc64', ],
   'hpcc'       => [ 'hppa', ],
   'icc'        => [ 'ia32', 'ia64', ],
   'kai'        => [ 'alpha', 'hppa', 'ia32', 'mips32', 'mips64', 'sparc32',
                     'sparc64', ],
   'mipspro'    => [ 'mips32', 'mips64', ],
   'msvc'       => [ 'ia32', ],
   'pgi'        => [ 'ia32', ],
   'sgipro64'   => [ 'ia64', ],
   'sunwspro'   => [ 'ia32', 'sparc32', 'sparc64', ],
);

my %CC_BINARY_NAME = (
   'bcc'            => 'bcc32',
   'compaq'         => 'cxx',
   'ekopath'        => 'pathCC',
   'gcc'            => 'g++',
   'hpcc'           => 'aCC',
   'icc'            => 'icc',
   'kai'            => 'KCC',
   'mipspro'        => 'CC',
   'msvc'           => 'cl /nologo',
   'pgi'            => 'pgCC',
   'sgipro64'       => 'sgiCC',
   'sunwspro'       => 'CC',
);

my %CC_LIB_OPT_FLAGS = (
   'bcc'            => '-O2',
   'compaq'         => '-O2',
   'ekopath'        => '-O3 -OPT:Ofast:alias=disjoint',
   'gcc'            => '-O2 -finline-functions',
   'hpcc'           => '+O2',
   'icc'            => '-O3 -ip -unroll',
   'kai'            => '+K3 --inline_auto_space_time=65 --abstract_pointer',
   'mipspro'        => '-O3 -OPT:alias=TYPED',
   'msvc'           => '/O2 /Ob2',
   'pgi'            => '-fast -Minline',
   'sgipro64'       => '-O3 -OPT:alias=TYPED',
   'sunwspro'       => '-xO2',
);

my %CC_CHECK_OPT_FLAGS = (
   'bcc'            => '-O2',
   'compaq'         => '-O2',
   'ekopath'        => '-O2',
   'gcc'            => '-O2',
   'hpcc'           => '+O2',
   'icc'            => '-O2',
   'kai'            => '+K3',
   'mipspro'        => '-O3 -OPT:alias=TYPED',
   'msvc'           => '/O2',
   'pgi'            => '-fast',
   'sgipro64'       => '-O3 -OPT:alias=TYPED',
   'sunwspro'       => '-xO2',
);

my %CC_WARN_FLAGS = (
   'bcc'            => '-w',
   'compaq'         => '',
   'ekopath'        => '-W -Wall',
   'gcc'            => '-W -Wall',
   'hpcc'           => '',
   'icc'            => '-w1',
   'kai'            => '',
   'mipspro'        => '',
   'msvc'           => '',
   'pgi'            => '',
   'sgipro64'       => '-Wall -W',
   'sunwspro'       => '+w',
);

my %CC_LANG_FLAGS = (
   'bcc'            => '',
   'compaq'         => '-std ansi -D__USE_STD_IOSTREAM',
   'ekopath'        => '-D_REENTRANT -ansi -Wno-long-long',
   'gcc'            => '-D_REENTRANT -ansi -Wno-long-long',
   'hpcc'           => '-AA -ext +eh -z',
   'icc'            => '',
   'kai'            => '-D__KAI_STRICT',
   'mipspro'        => '-ansi -LANG:ansi-for-init-scope=ON',
   'msvc'           => '/EHsc /GR /D_CONSOLE',
   'pgi'            => '',
   'sgipro64'       => '-ansi -LANG:ansi-for-init-scope=ON',
   'sunwspro'       => '+p -D__EXTENSIONS__',
);

my %CC_DEBUG_FLAGS = (
   'bcc'            => '',
   'compaq'         => '-g',
   'ekopath'        => '-g',
   'gcc'            => '-g',
   'hpcc'           => '-g',
   'icc'            => '-g',
   'kai'            => '-g',
   'mipspro'        => '-g3',
   'msvc'           => '',
   'pgi'            => '',
   'sgipro64'       => '-g3',
   'sunwspro'       => '-g',
);

my %CC_NO_DEBUG_FLAGS = (
   'bcc'            => '',
   'compaq'         => '',
   'ekopath'        => '',
   'gcc'            => '',
   'hpcc'           => '',
   'icc'            => '',
   'kai'            => '',
   'mipspro'        => '',
   'msvc'           => '',
   'pgi'            => '',
   'sgipro64'       => '',
   'sunwspro'       => '',
);

my %CC_MACHINE_OPT_FLAGS = (
   'bcc'        => {
      'athlon'     => '/G6',
      'i486'       => '/G4',
      'i586'       => '/G5',
      'i686'       => '/G6',
      'pentium4'   => '/G6',
      },
   'compaq'     => {
      'alpha'      => '-arch=SUBMODEL',
      },
   'ekopath'    => {
      'amd64'      => '-mcpu=athlon64',
      'athlon'     => '-mcpu=athlon',
      'athlon64'   => '-mcpu=athlon64',
      'em64t'      => '-mcpu=em64t',
      'i386'       => '-mcpu=anyx86',
      'opteron'    => '-mcpu=opteron',
      'pentium4'   => '-mcpu=pentium4',
      },
   'gcc'        => {
      'alpha'      => '-mcpu=SUBMODEL',
      'alpha-ev67' => '-mcpu=ev6',
      'alpha-ev68' => '-mcpu=ev6',
      'alpha-ev7'  => '-mcpu=ev6',
      'amd64'      => '',
      'arm'        => '-mcpu=SUBMODEL',
      'hppa'       => '-march=SUBMODEL',
      'i386'       => '-mcpu=i686',
      'ia32'       => '-march=SUBMODEL',
      'm68k'       => '-mSUBMODEL',
      'mips32'     => '-mips1 -mcpu=SUBMODEL',
      'mips64'     => '-mips3 -mcpu=SUBMODEL',
      'ppc'        => '-mcpu=SUBMODEL',
      'ppc601'     => '-mpowerpc -mcpu=601',
      'ppc64'      => '-mcpu=SUBMODEL',
      'r10000'     => '-mips4',
      'sh'         => '-mSUBMODEL',
      'sparc32'    => '-mcpu=SUBMODEL -Wa,-xarch=v8plus',
      'sparc64'    => '-mcpu=v9 -mtune=ultrasparc',
      'sparc64-ultra3' => '-mcpu=v9 -mtune=ultrasparc3',
      },
   'icc'        => {
      'athlon'     => '-tpp6 -xiM',
      'i586'       => '-tpp5',
      'i686'       => '-tpp6 -xiM',
      'pentium4'   => '-tpp7 -xiMW',
      },
   'mipspro'    => {
      'mips32'     => '-mips1',
      'mips64'     => '-mips3',
      'mips64-r10000' => '-mips4 -r10000',
      'mips64-r5000' => '-mips4 -r5000',
      'mips64-r8000' => '-mips4 -r8000',
      },
   'msvc'       => {
      'athlon'     => '/G6',
      'i486'       => '/G4',
      'i586'       => '/G5',
      'i686'       => '/G6',
      'pentium4'   => '/G6',
      },
   'pgi'        => {
      'athlon'     => '-tp k7',
      'i586'       => '-tp p5',
      'i686'       => '-tp p6',
      'ia32'       => '-tp px',
      'pentium4'   => '-tp p6',
      },
   'sunwspro'   => {
      'i386'       => '-xtarget=486',
      'i486'       => '-xtarget=486',
      'i586'       => '-xtarget=pentium',
      'i686'       => '-xtarget=pentium_pro',
      'k6'         => '-xtarget=pentium',
      'pentium4'   => '-xtarget=pentium_pro',
      'sparc32'    => '-xchip=ultra -xarch=SUBMODEL',
      'sparc32-v9' => '-xchip=ultra -xarch=v8',
      'sparc64'    => '-xchip=SUBMODEL',
      },
);

my %CC_MACHINE_OPT_FLAGS_RE = (
   'compaq'     => {
      'alpha'      => 'alpha-',
      },
   'gcc'        => {
      'alpha'      => 'alpha-',
      'hppa'       => 'hppa',
      'mips32'     => 'mips32-',
      'mips64'     => 'mips64-',
      'ppc'        => 'ppc',
      'ppc64'      => 'ppc',
      'sh'         => 'sh',
      'sparc32'    => 'sparc32-',
      },
   'sunwspro'   => {
      'sparc32'    => 'sparc32-',
      'sparc64'    => 'sparc64-',
      },
);

my %CC_SO_OBJ_FLAGS = (
   'bcc'            => '',
   'compaq'         => '',
   'ekopath'        => '-fPIC',
   'gcc'            => '-fPIC',
   'hpcc'           => '+Z',
   'icc'            => '-KPIC',
   'kai'            => '',
   'mipspro'        => '-KPIC',
   'msvc'           => '',
   'pgi'            => '-fPIC',
   'sgipro64'       => '-KPIC',
   'sunwspro'       => '-KPIC',
);

my %CC_ABI_FLAGS = (
   'gcc'        => {
      'amd64'      => '-m64',
      'freebsd'    => '-pthread',
      'mips32'     => '-mabi=n32',
      'mips64'     => '-mabi=64',
      'netbsd'     => '-pthread',
      'openbsd'    => '-pthread',
      'ppc64'      => '-m64',
      'qnx'        => '-fexceptions',
      's390'       => '-m31',
      's390x'      => '-m64',
      'sparc32'    => '-m32 -mno-app-regs',
      'sparc64'    => '-m64 -mno-app-regs',
      },
   'hpcc'       => {
      'hppa1.0'    => '+DAportable',
      'hppa1.1'    => '+DA1.1',
      'hppa2.0'    => '+DA2.0W',
      },
   'kai'        => {
      'all'        => '--one_per',
      },
   'mipspro'    => {
      'mips32'     => '-n32',
      'mips64'     => '-64',
      },
   'sunwspro'   => {
      'sparc64'    => '-xarch=v9',
      },
);

my %CC_SO_LINK_FLAGS = (
   'compaq'     => {
      'default'    => '$(CXX) -shared -soname $(SONAME)',
      },
   'ekopath'    => {
      'default'    => '$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)',
      },
   'gcc'        => {
      'aix'        => '$(CXX) -shared -fPIC',
      'beos'       => 'ld -shared -h $(SONAME)',
      'darwin'     => '$(CXX) -dynamiclib -fPIC -install_name $(SONAME)',
      'default'    => '$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)',
      'hpux'       => '$(CXX) -shared -fPIC -Wl,+h,$(SONAME)',
      'solaris'    => '$(CXX) -shared -fPIC -Wl,-h,$(SONAME)',
      },
   'hpcc'       => {
      'default'    => '$(CXX) +Z -b -Wl,+h,$(SONAME)',
      },
   'icc'        => {
      'default'    => '$(CXX) -KPIC -shared',
      },
   'kai'        => {
      'default'    => '$(CXX) --soname $(SONAME)',
      },
   'mipspro'    => {
      'default'    => '$(CXX) -shared -Wl,-soname,$(SONAME)',
      },
   'pgi'        => {
      'linux'      => '$(CXX) -shared -fPIC -Wl,-soname,$(SONAME)',
      'solaris'    => '$(CXX) -G -fPIC -Wl,-h,$(SONAME)',
      },
   'sgipro64'   => {
      'default'    => '$(CXX) -shared -Wl,-soname,$(SONAME)',
      },
   'sunwspro'   => {
      'default'    => '$(CXX) -G -h$(SONAME)',
      },
);

my %CC_AR_COMMAND = (
   'bcc'            => 'tlib /C /P256',
   'compaq'         => '',
   'ekopath'        => '',
   'gcc'            => '',
   'hpcc'           => '',
   'icc'            => '',
   'kai'            => 'KCC -o',
   'mipspro'        => '',
   'msvc'           => 'link /lib',
   'pgi'            => '',
   'sgipro64'       => '',
   'sunwspro'       => '',
);

my %MAKEFILE_STYLE = (
   'bcc'            => 'nmake',
   'compaq'         => 'unix',
   'ekopath'        => 'unix',
   'gcc'            => 'unix',
   'hpcc'           => 'unix',
   'icc'            => 'unix',
   'kai'            => 'unix',
   'mipspro'        => 'unix',
   'msvc'           => 'nmake',
   'pgi'            => 'unix',
   'sgipro64'       => 'unix',
   'sunwspro'       => 'unix',
);

my %REALNAME = (
   'aix'            => 'AIX',
   'alpha'          => 'DEC Alpha',
   'amd64'          => 'AMD64',
   'arm'            => 'ARM',
   'bcc'            => 'Borland C++',
   'beos'           => 'BeOS',
   'compaq'         => 'Compaq C++',
   'cygwin'         => 'Cygwin',
   'darwin'         => 'Darwin / MacOS X',
   'ekopath'        => 'PathScale EKOPath C++',
   'freebsd'        => 'FreeBSD',
   'gcc'            => 'GNU C++',
   'hpcc'           => 'HP-UX C++',
   'hppa'           => 'HP-PA',
   'hpux'           => 'HP-UX',
   'ia32'           => 'IA-32',
   'ia64'           => 'IA-64',
   'icc'            => 'Intel C++',
   'irix'           => 'IRIX',
   'kai'            => 'KAI C++',
   'linux'          => 'Linux',
   'm68k'           => 'Motorola 680x0',
   'mips32'         => 'MIPS',
   'mips64'         => 'MIPS64',
   'mipspro'        => 'SGI MIPSPro C++',
   'msvc'           => 'Visual C++ 2000/2003',
   'netbsd'         => 'NetBSD',
   'openbsd'        => 'OpenBSD',
   'pgi'            => 'Portland Group C++',
   'ppc'            => 'PowerPC',
   'ppc64'          => 'PowerPC 64',
   'qnx'            => 'QNX',
   's390'           => 'S/390 31-bit',
   's390x'          => 'S/390 64-bit',
   'sgipro64'       => 'SGI Pro64',
   'sh'             => 'Hitachi SH',
   'solaris'        => 'Solaris',
   'sparc32'        => 'SPARC',
   'sparc64'        => 'SPARC64',
   'sunwspro'       => 'Sun Workshop Pro C++',
   'tru64'          => 'Tru64',
   'windows'        => 'MS Windows',
);

# if($#ARGV < 0) { help(); }

my $debug = 0;
my $no_shared = 0;
my $make_style = '';
my $module_set = '';
my $dumb_gcc = 0;
my $autoconfig = 1;
my $user_set_root = '';
my @using_mods;
my ($doc_dir, $lib_dir);

my %MODULES = get_modules_list($MOD_DIR);

##################################################
# Parse command line options                     #
##################################################
GetOptions('debug' => sub { $debug = 1; },
           'disable-shared' => sub { $no_shared = 1; },
           'noauto' => sub { $autoconfig = 0 },
           'gcc295x' => sub { $dumb_gcc = 1; },
           'dumb-gcc' => sub { $dumb_gcc = 1; },
           'make-style=s' => \$make_style,
           'modules=s' => \@using_mods,
           'module-set=s' => \$module_set,
           'prefix=s' => \$user_set_root,
           'docdir=s' => \$doc_dir,
           'libdir=s' => \$lib_dir,
           'help' => sub { help(); }
           );

if($^O eq 'MSWin32' or $^O eq 'dos' or $^O eq 'cygwin') {
  print "Disabling use of symlink()/link() due to Win32 FS limitations\n";
  $FORCE_COPY = 1;
}

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);
if(!defined($cc) or !defined($os) or !defined($submodel)) { help(); }

##################################################
# Some special hacks                             #
##################################################
#warn "(warning): OpenBSD's GCC 2.95.3 is often buggy with -O2\n" .
#     "         :    Run 'make check' before installing!\n"
#    if($os eq 'openbsd' && $cc eq 'gcc');

if($cc eq 'gcc' && $dumb_gcc != 1)
{
    my $gcc_version = '';

    # Stupid Apple. At least they fixed it after 10.2
    if($os eq 'darwin') { $gcc_version = `c++ -v 2>&1`; }
    else { $gcc_version = `g++ -v 2>&1`; }

    $gcc_version = '' if not defined $gcc_version;

    # GCC 2.95.x and 3.[34] are busted in handling long long in C++. The third
    # check is because on Cygwin (at least for me) $gcc_version doesn't get the
    # output from g++, not sure what's up with that. If it's Cygwin and we
    # didn't get output, assume it's a buggy GCC. There is no reduction in code
    # quality, etc, so even if we're wrong it's no big deal.

    if(($gcc_version =~ /4\.[01]/) ||
       ($gcc_version =~ /3\.[34]/) ||
       ($gcc_version =~ /2\.95\.[0-4]/) ||
       ($gcc_version eq '' && $^O eq 'cygwin'))
    {
        warn "(note): Enabling -fpermissive to work around possible GCC issues\n";
        $dumb_gcc = 1;
    }
    if($gcc_version =~ /2\.95\.[0-4]/)
    {
        print "(note): GCC 2.95.x issues a lot of warnings for things in\n" .
              "      Botan; either ignore the warnings or upgrade to 3.x\n";
    }
}

##################################################
# Check input                                    #
##################################################
$os = $OS_ALIAS{$os} if(defined $OS_ALIAS{$os});

die "(error): Compiler $cc isn't known\n" unless defined($CC_BINARY_NAME{$cc});

die "(error): OS $os isn't known\n" unless
    (defined($OS_SUPPORTS_ARCH{$os}) or $os eq 'generic');

# Get the canonical submodel name (like r8k -> r8000)
$submodel = $SUBMODEL_ALIAS{$submodel} if(defined($SUBMODEL_ALIAS{$submodel}));

my $arch = undef;
# Convert an arch alias to it's real name (like axp -> alpha)
if(defined($ARCH_ALIAS{$submodel}))
   { $arch = $ARCH_ALIAS{$submodel}; $submodel = $arch; }
# If it's a regular submodel type, figure out what arch it is
elsif(defined($ARCH{$submodel}))
   { $arch = $ARCH{$submodel}; }
elsif($submodel eq 'generic') { $arch = 'generic'; }
else { die "(error): Arch $submodel isn't known\n"; }

# If we got a generic family name as the model type
if($submodel eq $arch and $submodel ne 'generic') {
   $submodel = $DEFAULT_SUBMODEL{$arch};

   warn "(note): Using $submodel as default type for family ",
        $REALNAME{$arch},"\n" if($submodel ne $arch);
}

$make_style = $MAKEFILE_STYLE{$cc} unless($make_style);

die "(error): Module set $module_set isn't known\n"
    if($module_set && !defined($MODULE_SETS{$module_set}));

if($module_set) {
   foreach (@{ $MODULE_SETS{$module_set} }) { push @using_mods,$_; }
}

@using_mods = grep {/./} split(/,/,join(',',@using_mods));

if($autoconfig)
{
    foreach (guess_mods($cc,$os,$arch,$submodel))
    {
        # Print a notice, *unless* it was enabled explicitly or via module set
        my $picked_by_user = 0;
        foreach my $x (@using_mods) { $picked_by_user = 1 if($_ eq $x); }

        print "  (autoconfig): Enabling module $_\n" if(!$picked_by_user);
        push @using_mods, $_;
    }
}

# Uniqify @using_mods
my %uniqed_mods;
foreach my $mod (@using_mods) { $uniqed_mods{$mod} = 0; }
@using_mods = sort keys %uniqed_mods;

foreach (@using_mods) {
   die "(error): Module $_ isn't known (try --help)\n"
      unless(exists($MODULES{$_}));
}

##################################################
# Does the OS support the arch?                  #
##################################################
die "(error): $REALNAME{$os} doesn't run on $arch ($submodel)\n"
    unless($arch eq 'generic' or $os eq 'generic' or
           in_array($OS_SUPPORTS_ARCH{$os}, $arch));

##################################################
# Does the compiler support the arch?            #
##################################################
die "(error): $REALNAME{$cc} doesn't run on $arch ($submodel)\n"
    unless($arch eq 'generic' or (in_array($CC_SUPPORTS_ARCH{$cc}, $arch)));

##################################################
# Does the compiler support the OS?              #
##################################################
die "(error): $REALNAME{$cc} doesn't run on $REALNAME{$os}\n"
    unless($os eq 'generic' or (in_array($CC_SUPPORTS_OS{$cc}, $os)));

##################################################
# Check for conflicts in the module selections   #
##################################################
check_for_conflicts(@using_mods);
my (%ignored_src, %ignored_include, %added_src, %added_include);
foreach (@using_mods) {
   load_module($_, $cc, $os, $arch, $submodel, %{ $MODULES{$_} });
}

##################################################
# Print some source files                        #
##################################################
print_pkg_config($os, $MAJOR_VERSION, $MINOR_VERSION, $PATCH_VERSION,
                 using_libs($os, @using_mods));

##################################################
# Figure out the files involved                  #
##################################################
my $CPP_INCLUDE_DIR = catdir($BUILD_INCLUDE_DIR, $CPP_INCLUDE_DIR_DIRNAME);
my $BUILD_LIB_DIR = catdir($BUILD_DIR, $BUILD_DIR_LIB);
my $BUILD_CHECK_DIR = catdir($BUILD_DIR, $BUILD_DIR_CHECKS);

my %lib_src = list_dir($SRC_DIR, \%ignored_src);
my %check_src = list_dir($CHECK_DIR, undef);

my %include = list_dir($INCLUDE_DIR, \%ignored_include);

##################################################
# Set up the build tree                          #
##################################################
mkdirs(($BUILD_DIR,
        $BUILD_INCLUDE_DIR, $CPP_INCLUDE_DIR,
        $BUILD_LIB_DIR, $BUILD_CHECK_DIR));
clean_out_dirs(($CPP_INCLUDE_DIR));

##################################################
# Generate the config.h header                   #
##################################################
my $CONFIG_H_FILE = catfile($BUILD_DIR, $CONFIG_HEADER);

print_config_h($MAJOR_VERSION, $MINOR_VERSION, $PATCH_VERSION,
               $os, $arch, $submodel,
               find_mp_bits(@using_mods), defines(@using_mods),
               defines_base(@using_mods));

$added_include{$CONFIG_HEADER} = $BUILD_DIR;

##################################################
# Copy all headers                               #
##################################################
copy_files($CPP_INCLUDE_DIR, \%include, \%added_include);

##################################################
# Print the makefile                             #
##################################################
my %all_includes = list_dir($CPP_INCLUDE_DIR);

generate_makefile($make_style,
                  $cc, $os, $submodel, $arch,
                  $debug, $no_shared, $dumb_gcc,
                  \%lib_src, \%check_src, \%all_includes,
                  \%added_src, using_libs($os, @using_mods));

exit;

sub catfile {
      return File::Spec->catfile(@_);
}

sub catdir {
      return File::Spec->catdir(@_);
}

sub process {
   my $l = $_[0];
   chomp