aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreschnett <eschnett@043a8217-7a68-40fe-abfd-36aa7d4fa6a8>2014-12-03 22:15:29 +0000
committereschnett <eschnett@043a8217-7a68-40fe-abfd-36aa7d4fa6a8>2014-12-03 22:15:29 +0000
commit1733ae55513e79d1e96a233bf6eeb799aabf8e4b (patch)
treec894176b0ab96d02b6998997423186c371d3c7c9
parent254833ea41c437564b165f1adbda53d85aec07a5 (diff)
Build MPI at build time
git-svn-id: http://svn.cactuscode.org/projects/ExternalLibraries/MPI/trunk@58 043a8217-7a68-40fe-abfd-36aa7d4fa6a8
-rw-r--r--configuration.ccl5
-rw-r--r--configure.pl420
-rw-r--r--src/build.pl82
-rw-r--r--src/detect.pl303
-rw-r--r--src/make.code.deps7
5 files changed, 396 insertions, 421 deletions
diff --git a/configuration.ccl b/configuration.ccl
index e65a2fd..d094783 100644
--- a/configuration.ccl
+++ b/configuration.ccl
@@ -2,7 +2,10 @@
PROVIDES MPI
{
- SCRIPT configure.pl
+ SCRIPT src/detect.pl
LANG perl
OPTIONS MPI MPI_DIR MPI_INC_DIRS MPI_LIB_DIRS MPI_LIBS MPI_INSTALL_DIR
}
+
+# Pass configuration options to build script
+REQUIRES MPI
diff --git a/configure.pl b/configure.pl
deleted file mode 100644
index a17921e..0000000
--- a/configure.pl
+++ /dev/null
@@ -1,420 +0,0 @@
-#!/usr/bin/perl
-use Carp;
-use strict;
-use FileHandle;
-use Cwd;
-$/ = undef;
-
-# Used by pushd/popd
-my @push_dirs = ();
-
-# Used by begin/end message
-my @messages = ();
-
-# Used by sys()
-my $aborted = 0;
-
-################################################################################
-# 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 $NAME=openmpi-1.7.1
- 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}");
- my $DONE_FILE="$ENV{SCRATCH_BUILD}/done/${THORN}";
- $mpi_dir=${INSTALL_DIR};
-
- # Setting $mpi_cmd enables the generic
- # search method below to configure the
- # various MPI variables.
- $mpi_cmd="$mpi_dir/bin/mpicc";
-
- if(-r ${DONE_FILE}) {
- message("MPI has already been built; doing nothing");
- } else {
- message("Building MPI");
- message("Using bundled MPI...");
-
- chdir($ENV{SCRATCH_BUILD});
-
-# Set up environment
-# Disable ccache: remove "ccache" and all options that follow
-# Note: we can use only basic sed regexps here
-#export CC=$(echo '' ${CC} '' |
-# sed -e 's/ ccache *\(-[^ ]* *\)*/ /g;s/^ //;s/ $//')
-#export CXX=$(echo '' ${CXX} '' |
-# sed -e 's/ ccache *\(-[^ ]* *\)*/ /g;s/^ //;s/ $//')
- $ENV{CC} =~ s/ ccache .*//;
- $ENV{CXX} =~ s/ ccache .*//;
- if($ENV{F90} =~ /none/) {
- message("No Fortran 90 compiler available. Building MPI library without Fortran support.");
- $ENV{FC}=undef;
- $ENV{FCFLAGS}=undef;
- } else {
- $ENV{FC} = $ENV{F90};
- $ENV{FCFLAGS} = $ENV{F90FLAGS};
- }
- $ENV{LIBS}=undef;
- $ENV{RPATH}=undef;
- if($ENV{ARFLAGS} =~ /64/) {
- $ENV{OBJECT_MODE}="64";
- }
-
- message("MPI: Preparing directory structure...");
- mkdir("external");
- mkdir("done");
- sys("rm -rf ${BUILD_DIR} ${INSTALL_DIR}");
- mkdir(${BUILD_DIR});
- mkdir(${INSTALL_DIR});
- error("${INSTALL_DIR} does not exist.",6) unless(-e ${INSTALL_DIR});
- error("${INSTALL_DIR} is not a directory.",6) unless(-d ${INSTALL_DIR});
- error("${INSTALL_DIR} is not readabile.",7) unless(-r ${INSTALL_DIR});
- error("${INSTALL_DIR} is not writeable.",8) unless(-w ${INSTALL_DIR});
- error("${INSTALL_DIR} is not executable.",8) unless(-x ${INSTALL_DIR});
- $mpi_dir = $ENV{MPI_DIR} = ${INSTALL_DIR};
-
- message("MPI: Unpacking archive...");
- pushd(${BUILD_DIR});
- sys("$ENV{TAR} xzf ${SRCDIR}/dist/${NAME}.tar.gz");
- sys("$ENV{PATCH} -p0 < ${SRCDIR}/dist/default_outfile-1.6.5.patch");
- chdir(${NAME});
- sys("$ENV{PATCH} -p0 < ${SRCDIR}/dist/cuda_build_fix__svn29754");
-
- message("MPI: Configuring...");
-# Cannot have a memory manager with a static library on some
-# systems (e.g. Linux); see
-# <http://www.open-mpi.org/faq/?category=mpi-apps#static-mpi-apps>
- sys("./configure --prefix=$mpi_dir --without-memory-manager --without-libnuma --enable-shared=no --enable-static=yes");
-
- message("MPI: Building...");
- sys("$ENV{MAKE}");
-
- message("MPI: Installing...");
- sys("$ENV{MAKE} install");
- popd();
-
- message("MPI: Cleaning up...");
- sys("rm -rf ${BUILD_DIR}");
-
- sys("date > ${DONE_FILE}");
- message("MPI: Done.");
- }
- mpi_get_info();
-}
-
-################################################################################
-# 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
-
-begin_message("DEFINE");
-print "CCTK_MPI 1\n";
-# print "HAVE_MPI 1\n";
-end_message();
-
-begin_message("MAKE_DEFINITION");
-print "CCTK_MPI = 1\n";
-# print "HAVE_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";
-end_message();
-
-print "INCLUDE_DIRECTORY \$(MPI_INC_DIRS)\n";
-print "LIBRARY_DIRECTORY \$(MPI_LIB_DIRS)\n";
-print "LIBRARY \$(MPI_LIBS)\n";
-
-################################################################################
-# Functions
-################################################################################
-
-sub pushd {
- push @push_dirs, Cwd::getcwd();
- chdir(shift);
-}
-sub popd {
- chdir(shift @push_dirs);
-}
-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 sys {
- my $cmd = shift;
- return unless($aborted == 0);
- $aborted = system("$cmd 1>&2");
-}
-
-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 error {
- my ($msg,$errno) = @_;
- $msg =~ s/\n$//;
- begin_message("ERROR");
- print $msg,"\n";
- end_message("ERROR");
- exit $errno;
-}
-sub message {
- my $msg = shift;
- $msg =~ s/\n$//;
- begin_message();
- print $msg,"\n";
- end_message();
-}
-sub begin_message {
- my $msg = shift;
- my $oldmsg = "";
- $msg = "MESSAGE" unless(defined($msg));
- $oldmsg = $messages[$#messages] if($#messages >= 0);
- push @messages, $msg;
- Carp::carp() unless(defined($msg));
- Carp::carp() unless(length($msg)>3);
- unless($oldmsg eq $msg) {
- print "END $oldmsg\n" unless($oldmsg eq "");
- print "BEGIN $msg\n";
- }
-}
-sub end_message {
- my $msg = pop @messages;
- my $oldmsg = "";
- $oldmsg = $messages[$#messages] if($#messages >= 0);
- Carp::carp() unless(defined($msg));
- Carp::carp() unless(length($msg)>3);
- unless($oldmsg eq $msg) {
- print "END $msg\n";
- print "BEGIN $oldmsg\n" unless($oldmsg eq "");
- }
-}
-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;
-}
diff --git a/src/build.pl b/src/build.pl
new file mode 100644
index 0000000..58ab021
--- /dev/null
+++ b/src/build.pl
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+use Carp;
+use strict;
+use FileHandle;
+use Cwd;
+$/ = undef;
+
+# 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}";
+}
+print "Installing MPI into ${INSTALL_DIR}\n";
+my $DONE_FILE = "$ENV{SCRATCH_BUILD}/done/${THORN}";
+my $mpi_dir = ${INSTALL_DIR};
+
+chdir($ENV{SCRATCH_BUILD});
+
+# Set up environment
+# Disable ccache: remove "ccache" and all options that follow
+$ENV{CC} =~ s/^\s*ccache\s+(-\S*\s+)*//;
+$ENV{CXX} =~ s/^\s*ccache\s+(-\S*\s+)*//;
+if ($ENV{F90} eq 'none') {
+ print "No Fortran 90 compiler available. Building MPI library without Fortran support.\n";
+ $ENV{FC} = undef;
+ $ENV{FCFLAGS} = undef;
+} else {
+ $ENV{FC} = $ENV{F90};
+ $ENV{FCFLAGS} = $ENV{F90FLAGS};
+}
+$ENV{LIBS} = undef;
+$ENV{RPATH} = undef;
+if ($ENV{ARFLAGS} =~ /64/) {
+ $ENV{OBJECT_MODE} = "64";
+}
+
+print "MPI: Preparing directory structure...\n";
+mkdir("build");
+mkdir("external");
+mkdir("done");
+system("rm -rf ${BUILD_DIR} ${INSTALL_DIR}") == 0 or die;
+mkdir(${BUILD_DIR});
+mkdir(${INSTALL_DIR});
+error("${INSTALL_DIR} does not exist.",6) unless(-e ${INSTALL_DIR});
+error("${INSTALL_DIR} is not a directory.",6) unless(-d ${INSTALL_DIR});
+error("${INSTALL_DIR} is not readable.",7) unless(-r ${INSTALL_DIR});
+error("${INSTALL_DIR} is not writeable.",8) unless(-w ${INSTALL_DIR});
+error("${INSTALL_DIR} is not executable.",8) unless(-x ${INSTALL_DIR});
+
+print "MPI: Unpacking archive...\n";
+chdir(${BUILD_DIR});
+system("$ENV{TAR} xzf ${SRCDIR}/../dist/${NAME}.tar.gz") == 0 or die;
+system("$ENV{PATCH} -p0 < ${SRCDIR}/../dist/default_outfile-1.6.5.patch") == 0 or die;
+chdir(${NAME});
+system("$ENV{PATCH} -p0 < ${SRCDIR}/../dist/cuda_build_fix__svn29754") == 0 or die;
+
+print "MPI: Configuring...\n";
+# Cannot have a memory manager with a static library on some systems
+# (e.g. Linux); see
+# <http://www.open-mpi.org/faq/?category=mpi-apps#static-mpi-apps>
+system("./configure --prefix=$mpi_dir --without-memory-manager --without-libnuma --enable-shared=no --enable-static=yes") == 0 or die;
+
+print "MPI: Building...\n";
+system("$ENV{MAKE}") == 0 or die;
+
+print "MPI: Installing...\n";
+system("$ENV{MAKE} install") == 0 or die;
+chdir($ENV{SCRATCH_BUILD});
+
+print "MPI: Cleaning up...\n";
+system("rm -rf ${BUILD_DIR}") == 0 or die;
+
+system("date > ${DONE_FILE}") == 0 or die;
+print "MPI: Done.\n";
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;
+}
diff --git a/src/make.code.deps b/src/make.code.deps
new file mode 100644
index 0000000..65c2302
--- /dev/null
+++ b/src/make.code.deps
@@ -0,0 +1,7 @@
+# Main make.code.deps file for thorn MPI
+
+export MPI_INSTALL_DIR
+
+$(CCTK_TARGET) $(OBJS) $(SRCS:%=%.d): $(SCRATCH_BUILD)/done/$(THORN)
+$(SCRATCH_BUILD)/done/$(THORN): $(SRCDIR)/build.pl
+ $(PERL) $(SRCDIR)/build.pl