diff options
Diffstat (limited to 'src/detect.pl')
-rw-r--r-- | src/detect.pl | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/src/detect.pl b/src/detect.pl new file mode 100644 index 0000000..e598f7b --- /dev/null +++ b/src/detect.pl @@ -0,0 +1,303 @@ +#!/usr/bin/perl +use Carp; +use strict; +use FileHandle; +use Cwd; +$/ = undef; + +################################################################################ +# Prepare +################################################################################ + +# Set up shell +my $verbose = 0; +$verbose = 1 if $ENV{VERBOSE} =~ /^yes$/i; + +################################################################################ +# Check for old mechanism +################################################################################ + +if (defined($ENV{MPI})) { + error("Setting the option \"MPI\" is incompatible with the MPI thorn. Please remove the option MPI = $ENV{MPI}.", 2); +} + +################################################################################ +# Determine whether to build and/or search +################################################################################ + +my $info = undef; +my $mpi_info_set = 0; +my $mpi_dir = undef; +my $mpi_cmd = undef; +my $mpi_search = 1; +my $mpi_build = 0; +my $mpi_manual = 0; + +my @mpicxx_names = ("mpic++", "mpiCC", "mpicxx", "mpicxx-openmpi-mp", "mpicc"); + +if (!is_set("MPI_DIR")) { + message("MPI selected, but MPI_DIR is not set. Computing settings..."); + $mpi_build = 1; + $mpi_search = 1; +} elsif ($ENV{MPI_DIR} eq "NO_BUILD") { + $mpi_dir = $ENV{MPI_DIR}; + $mpi_build = 0; + $mpi_search = 1; +} elsif ($ENV{MPI_DIR} eq "BUILD") { + $mpi_build = 1; + $mpi_search = 0; +} elsif ($ENV{MPI_DIR} eq "NONE") { + $mpi_build = 0; + $mpi_search = 0; + $mpi_info_set = 1; + $mpi_dir = ''; + $info = ''; +} else { + if (!-d $ENV{MPI_DIR}) { + message("MPI_DIR is set to a directory that does not exist (MPI_DIR = $ENV{MPI_DIR}); continuing anyway"); + } + $mpi_dir = $ENV{MPI_DIR}; + $mpi_build = 0; + $mpi_search = 0; + if (is_set("MPI_INC_DIRS") or is_set("MPI_LIB_DIRS") or is_set("MPI_LIBS")) + { + # If some of the MPI variables are set, this is a completely + # manual configuration. + $mpi_manual = 1; + } else { + # If none of the MPI variables are set, check for the compiler + # wrapper under MPI_DIR + $mpi_manual = 0; + for my $name (@mpicxx_names) { + my $full_name = "$ENV{MPI_DIR}/bin/$name"; + if (-x $full_name) { + $mpi_cmd = $full_name; + last; + } + } + if (defined($mpi_cmd)) { + message("Found MPI compiler wrapper at $mpi_cmd!"); + mpi_get_info(); + } else { + message("No MPI compiler wrapper found beneath MPI_DIR (MPI_DIR = $ENV{MPI_DIR})"); + } + } +} + +################################################################################ +# Search +################################################################################ +if ($mpi_search and !defined($mpi_cmd)) { + for my $name (@mpicxx_names) { + last if defined($mpi_cmd); + $mpi_cmd = which($name); + } + if (defined($mpi_cmd)) { + $mpi_dir = $mpi_cmd; + $mpi_dir =~ s{/mpi(c\+\+|CC|cc|cxx)[^/]*$}{}; + $mpi_dir =~ s{/bin$}{}; + message("Found MPI compiler wrapper at $mpi_cmd!"); + mpi_get_info(); + } +} + +################################################################################ +# Build +################################################################################ + +if ($mpi_build and !$mpi_info_set) { + # Check for required tools. Do this here so that we don't require + # them when using the system library. + unless(defined($ENV{TAR}) and $ENV{TAR} =~ /\S/ and -x which($ENV{TAR})) { + error( + "ENV{TAR} = $ENV{TAR}\n" . + "Could not find tar command. Please make sure that (GNU) tar is present,\n" . + "and that the TAR variable is set to its location.\n", 3); + } + unless(defined($ENV{PATCH}) and $ENV{PATCH} =~ /\S/ and + -x which($ENV{PATCH})) + { + error( + "Could not find patch command. Please make sure that (GNU) patch is present,\n" . + "and that the PATCH variable is set to its location.\n", 4); + } + + # Set locations + my $THORN = "MPI"; + my $NAME = "openmpi-1.6.5"; + my $INSTALL_DIR = undef; + my $BUILD_DIR = undef; + my $SRCDIR = $0; + $SRCDIR =~ s{(.*)/.*}{$1}; + ${BUILD_DIR} = "$ENV{SCRATCH_BUILD}/build/${THORN}"; + if (defined($ENV{MPI_INSTALL_DIR}) and $ENV{MPI_INSTALL_DIR} =~ /\S/) { + $INSTALL_DIR = "$ENV{MPI_INSTALL_DIR}/${THORN}"; + } else { + $INSTALL_DIR = "$ENV{SCRATCH_BUILD}/external/${THORN}"; + } + message("Installing MPI into ${INSTALL_DIR}"); + $mpi_dir = ${INSTALL_DIR}; + + $mpi_manual = 1; + $ENV{MPI_DIR} = $mpi_dir; + $ENV{MPI_INC_DIRS} = "$mpi_dir/include"; + $ENV{MPI_LIB_DIRS} = "$mpi_dir/lib"; + $ENV{MPI_LIBS} = "mpi"; +} + +################################################################################ +# Configure MPI options +################################################################################ + +if ($mpi_info_set) { + my @incdirs = (); + my @libdirs = (); + my @libs = (); + while($info =~ /\s-I\s*(\S+)/g) { + push @incdirs, $1; + } + while($info =~ /\s-L\s*(\S+)/g) { + push @libdirs, $1; + } + while($info =~ /\s-l(\S+)/g) { + push @libs, $1; + } + + $ENV{MPI_DIR} = $mpi_dir; + $ENV{MPI_INC_DIRS} = join(" ",@incdirs); + $ENV{MPI_LIB_DIRS} = join(" ",@libdirs); + $ENV{MPI_LIBS} = join(" ",@libs); + + message("Successfully configured MPI."); +} elsif ($mpi_manual) { + my @incdirs = (); + my @libdirs = (); + my @libs = (); + if (is_set("MPI_INC_DIRS")) { + push @incdirs, $ENV{MPI_INC_DIRS}; + } else { + push @incdirs, "$ENV{MPI_DIR}/include"; + } + if (is_set("MPI_LIB_DIRS")) { + push @libdirs, $ENV{MPI_LIB_DIRS}; + } else { + push @libdirs, "$ENV{MPI_DIR}/lib64"; + push @libdirs, "$ENV{MPI_DIR}/lib"; + } + if (is_set("MPI_LIBS")) { + push @libs, $ENV{MPI_LIBS}; + } else { + # do nothing + } + + $ENV{MPI_INC_DIRS} = join(" ",@incdirs); + $ENV{MPI_LIB_DIRS} = join(" ",@libdirs); + $ENV{MPI_LIBS} = join(" ",@libs); + + message("MPI was manually configured."); +} else { + error("MPI could not be configured: neither automatic nor manual configuration succeeded",5); +} + +################################################################################ +# Configure Cactus +################################################################################ + +# Strip standard paths +$ENV{MPI_INC_DIRS} = strip_inc_dirs($ENV{MPI_INC_DIRS}); +$ENV{MPI_LIB_DIRS} = strip_lib_dirs($ENV{MPI_LIB_DIRS}); + +# Pass options to Cactus + +print "BEGIN DEFINE\n"; +print "CCTK_MPI 1\n"; +print "END DEFINE\n"; + +print "BEGIN MAKE_DEFINITION\n"; +print "CCTK_MPI = 1\n"; +print "MPI_DIR = $ENV{MPI_DIR}\n"; +print "MPI_INC_DIRS = $ENV{MPI_INC_DIRS}\n"; +print "MPI_LIB_DIRS = $ENV{MPI_LIB_DIRS}\n"; +print "MPI_LIBS = $ENV{MPI_LIBS}\n"; +print "END MAKE_DEFINITION\n"; + +print "INCLUDE_DIRECTORY \$(MPI_INC_DIRS)\n"; +print "LIBRARY_DIRECTORY \$(MPI_LIB_DIRS)\n"; +print "LIBRARY \$(MPI_LIBS)\n"; + +################################################################################ +# Functions +################################################################################ + +sub which { + my $cmd = shift; + for my $path (split(/:/,$ENV{PATH})) { + my $full_cmd = "$path/$cmd"; + if (-x $full_cmd) { + return $full_cmd; + } + } + return undef; +} + +sub mpi_get_info { + my $fd = new FileHandle; + open($fd,"$mpi_cmd -compile_info 2>/dev/null|"); + $info = <$fd>; + close($fd); + if ($info eq "") { + open($fd,"$mpi_cmd --showme 2>/dev/null|"); + $info = <$fd>; + close($fd); + } + if ($info eq "") { + # The command, mpicc, is quite often a shell script. + # Run it with -x to trace, and find the compile command. + open($fd,"sh -x $mpi_cmd /dev/null 2>/dev/null|"); + my $contents = <$fd>; + if ($contents =~ /\w+cc.*-I\/.*-lmpi.*/) { + $info = $&; + } + } + if ($info =~ /^\s*$/) { + $mpi_info_set = 0; + } else { + $mpi_info_set = 1; + } +} + +sub message { + my $msg = shift; + $msg =~ s/\n$//; + print "BEGIN MESSAGE\n"; + print "$msg\n"; + print "END MESSAGE\n"; +} +sub error { + my ($msg,$errno) = @_; + $msg =~ s/\n$//; + print "BEGIN ERROR\n"; + print "$msg\n"; + print "END ERROR\n"; + exit $errno; +} + +sub is_set { + my $var = shift; + return (defined($ENV{$var}) and !($ENV{$var} =~ /^\s*$/)); +} + +sub strip_inc_dirs { + my $dirlist = shift; + my @dirs = split / /, $dirlist; + map { s{//}{/}g } @dirs; + @dirs = grep { !m{^/(usr/(local/)?)?include/?$} } @dirs; + return join ' ', @dirs; +} +sub strip_lib_dirs { + my $dirlist = shift; + my @dirs = split / /, $dirlist; + map { s{//}{/}g } @dirs; + @dirs = grep { !m{^/(usr/(local/)?)?lib(64?)/?$} } @dirs; + return join ' ', @dirs; +} |