diff options
-rwxr-xr-x | lib/spack/env/cc | 231 | ||||
-rw-r--r-- | lib/spack/llnl/util/filesystem.py | 30 | ||||
-rw-r--r-- | lib/spack/spack/modules.py | 4 | ||||
-rw-r--r-- | lib/spack/spack/test/cc.py | 127 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/boost/package.py | 50 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/hypre/package.py | 5 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/metis/package.py | 6 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/mumps/Makefile.inc | 5 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/mumps/package.py | 60 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/netcdf-cxx/package.py | 15 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/netlib-scalapack/package.py | 5 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/oce/package.py | 6 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/parmetis/package.py | 6 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/petsc/package.py | 48 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/py-netcdf/package.py | 16 | ||||
-rw-r--r-- | var/spack/repos/builtin/packages/superlu-dist/package.py | 11 |
16 files changed, 385 insertions, 240 deletions
diff --git a/lib/spack/env/cc b/lib/spack/env/cc index 4a3e6eddc9..2eb6f46afe 100755 --- a/lib/spack/env/cc +++ b/lib/spack/env/cc @@ -65,7 +65,7 @@ function die { } for param in $parameters; do - if [ -z "${!param}" ]; then + if [[ -z ${!param} ]]; then die "Spack compiler must be run from spack! Input $param was missing!" fi done @@ -78,12 +78,17 @@ done # 'command' is set based on the input command to $SPACK_[CC|CXX|F77|F90] # # 'mode' is set to one of: +# cpp preprocess # cc compile +# as assemble # ld link # ccld compile & link -# cpp preprocessor # vcheck version check # +# Depending on the mode, we may or may not add extra rpaths. +# This variable controls whether they are added. +add_rpaths=true + command=$(basename "$0") case "$command" in cc|c89|c99|gcc|clang|icc|pgcc|xlc) @@ -107,13 +112,26 @@ case "$command" in ;; ld) mode=ld + + # Darwin's linker has a -r argument that merges object files + # together. It doesn't work with -rpath. + if [[ $OSTYPE = darwin* ]]; then + for arg in "$@"; do + if [ "$arg" = -r ]; then + add_rpaths=false + break + fi + done + fi ;; *) die "Unkown compiler: $command" ;; esac -# If any of the arguments below is present then the mode is vcheck. In vcheck mode nothing is added in terms of extra search paths or libraries +# If any of the arguments below is present then the mode is vcheck. In +# vcheck mode nothing is added in terms of extra search paths or +# libraries if [ -z "$mode" ]; then for arg in "$@"; do if [ "$arg" = -v -o "$arg" = -V -o "$arg" = --version -o "$arg" = -dumpversion ]; then @@ -124,13 +142,15 @@ if [ -z "$mode" ]; then fi # Finish setting up the mode. - if [ -z "$mode" ]; then mode=ccld for arg in "$@"; do if [ "$arg" = -E ]; then mode=cpp break + elif [ "$arg" = -S ]; then + mode=as + break elif [ "$arg" = -c ]; then mode=cc break @@ -146,168 +166,56 @@ fi # Check that at least one of the real commands was actually selected, # otherwise we don't know what to execute. -if [ -z "$command" ]; then +if [[ -z $command ]]; then die "ERROR: Compiler '$SPACK_COMPILER_SPEC' does not support compiling $language programs." fi -# Save original command for debug logging -input_command="$@" - if [ "$mode" == vcheck ] ; then exec ${command} "$@" fi -# -# Now do real parsing of the command line args, trying hard to keep -# non-rpath linker arguments in the proper order w.r.t. other command -# line arguments. This is important for things like groups. -# -includes=() -libraries=() -libs=() -rpaths=() -other_args=() - -while [ -n "$1" ]; do - case "$1" in - -I*) - arg="${1#-I}" - if [ -z "$arg" ]; then shift; arg="$1"; fi - includes+=("$arg") - ;; - -L*) - arg="${1#-L}" - if [ -z "$arg" ]; then shift; arg="$1"; fi - libraries+=("$arg") - ;; - -l*) - arg="${1#-l}" - if [ -z "$arg" ]; then shift; arg="$1"; fi - libs+=("$arg") - ;; - -Wl,*) - arg="${1#-Wl,}" - # TODO: Handle multiple -Wl, continuations of -Wl,-rpath - if [[ $arg == -rpath=* ]]; then - arg="${arg#-rpath=}" - for rpath in ${arg//,/ }; do - rpaths+=("$rpath") - done - elif [[ $arg == -rpath,* ]]; then - arg="${arg#-rpath,}" - for rpath in ${arg//,/ }; do - rpaths+=("$rpath") - done - elif [[ $arg == -rpath ]]; then - shift; arg="$1" - if [[ $arg != '-Wl,'* ]]; then - die "-Wl,-rpath was not followed by -Wl,*" - fi - arg="${arg#-Wl,}" - for rpath in ${arg//,/ }; do - rpaths+=("$rpath") - done - else - other_args+=("-Wl,$arg") - fi - ;; - -Xlinker) - shift; arg="$1"; - if [[ $arg = -rpath=* ]]; then - rpaths+=("${arg#-rpath=}") - elif [[ $arg = -rpath ]]; then - shift; arg="$1" - if [[ $arg != -Xlinker ]]; then - die "-Xlinker -rpath was not followed by -Xlinker <arg>" - fi - shift; arg="$1" - rpaths+=("$arg") - else - other_args+=("-Xlinker") - other_args+=("$arg") - fi - ;; - *) - other_args+=("$1") - ;; - esac - shift -done - -# Dump parsed values for unit testing if asked for -if [ -n "$SPACK_TEST_COMMAND" ]; then - IFS=$'\n' - case "$SPACK_TEST_COMMAND" in - dump-includes) echo "${includes[*]}";; - dump-libraries) echo "${libraries[*]}";; - dump-libs) echo "${libs[*]}";; - dump-rpaths) echo "${rpaths[*]}";; - dump-other-args) echo "${other_args[*]}";; - dump-all) - echo "INCLUDES:" - echo "${includes[*]}" - echo - echo "LIBRARIES:" - echo "${libraries[*]}" - echo - echo "LIBS:" - echo "${libs[*]}" - echo - echo "RPATHS:" - echo "${rpaths[*]}" - echo - echo "ARGS:" - echo "${other_args[*]}" - ;; - *) - echo "ERROR: Unknown test command" - exit 1 ;; - esac - exit -fi +# Save original command for debug logging +input_command="$@" +args=("$@") # Read spack dependencies from the path environment variable IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES" for dep in "${deps[@]}"; do - if [ -d "$dep/include" ]; then - includes+=("$dep/include") + # Prepend include directories + if [[ -d $dep/include ]]; then + if [[ $mode = cpp || $mode = cc || $mode = as || $mode = ccld ]]; then + args=("-I$dep/include" "${args[@]}") + fi fi - if [ -d "$dep/lib" ]; then - libraries+=("$dep/lib") - rpaths+=("$dep/lib") + # Prepend lib and RPATH directories + if [[ -d $dep/lib ]]; then + if [[ $mode = ccld ]]; then + $add_rpaths && args=("-Wl,-rpath,$dep/lib" "${args[@]}") + args=("-L$dep/lib" "${args[@]}") + elif [[ $mode = ld ]]; then + $add_rpaths && args=("-rpath" "$dep/lib" "${args[@]}") + args=("-L$dep/lib" "${args[@]}") + fi fi - if [ -d "$dep/lib64" ]; then - libraries+=("$dep/lib64") - rpaths+=("$dep/lib64") + # Prepend lib64 and RPATH directories + if [[ -d $dep/lib64 ]]; then + if [[ $mode = ccld ]]; then + $add_rpaths && args=("-Wl,-rpath,$dep/lib64" "${args[@]}") + args=("-L$dep/lib64" "${args[@]}") + elif [[ $mode = ld ]]; then + $add_rpaths && args=("-rpath" "$dep/lib64" "${args[@]}") + args=("-L$dep/lib64" "${args[@]}") + fi fi done # Include all -L's and prefix/whatever dirs in rpath -for dir in "${libraries[@]}"; do - [[ dir = $SPACK_INSTALL* ]] && rpaths+=("$dir") -done -rpaths+=("$SPACK_PREFIX/lib") -rpaths+=("$SPACK_PREFIX/lib64") - -# Put the arguments together -args=() -for dir in "${includes[@]}"; do args+=("-I$dir"); done -args+=("${other_args[@]}") -for dir in "${libraries[@]}"; do args+=("-L$dir"); done -for lib in "${libs[@]}"; do args+=("-l$lib"); done - -if [ "$mode" = ccld ]; then - for dir in "${rpaths[@]}"; do - args+=("-Wl,-rpath") - args+=("-Wl,$dir"); - done -elif [ "$mode" = ld ]; then - for dir in "${rpaths[@]}"; do - args+=("-rpath") - args+=("$dir"); - done +if [[ $mode = ccld ]]; then + $add_rpaths && args=("-Wl,-rpath,$SPACK_PREFIX/lib" "-Wl,-rpath,$SPACK_PREFIX/lib64" "${args[@]}") +elif [[ $mode = ld ]]; then + $add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "-rpath" "$SPACK_PREFIX/lib64" "${args[@]}") fi # @@ -323,34 +231,37 @@ unset DYLD_LIBRARY_PATH # IFS=':' read -ra env_path <<< "$PATH" IFS=':' read -ra spack_env_dirs <<< "$SPACK_ENV_PATH" -spack_env_dirs+=(".") +spack_env_dirs+=("" ".") PATH="" for dir in "${env_path[@]}"; do remove="" for rm_dir in "${spack_env_dirs[@]}"; do - if [ "$dir" = "$rm_dir" ]; then remove=True; fi + if [[ $dir = $rm_dir ]]; then remove=True; fi done - if [ -z "$remove" ]; then - if [ -z "$PATH" ]; then - PATH="$dir" - else - PATH="$PATH:$dir" - fi + if [[ -z $remove ]]; then + PATH="${PATH:+$PATH:}$dir" fi done export PATH -full_command=("$command") -full_command+=("${args[@]}") +full_command=("$command" "${args[@]}") + +# In test command mode, write out full command for Spack tests. +if [[ $SPACK_TEST_COMMAND = dump-args ]]; then + echo "${full_command[@]}" + exit +elif [[ -n $SPACK_TEST_COMMAND ]]; then + die "ERROR: Unknown test command" +fi # # Write the input and output commands to debug logs if it's asked for. # -if [ "$SPACK_DEBUG" = "TRUE" ]; then +if [[ $SPACK_DEBUG = TRUE ]]; then input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.in.log" output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.out.log" - echo "$input_command" >> $input_log - echo "$mode ${full_command[@]}" >> $output_log + echo "[$mode] $command $input_command" >> $input_log + echo "[$mode] ${full_command[@]}" >> $output_log fi exec "${full_command[@]}" diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py index c4665c284c..46ca03bec4 100644 --- a/lib/spack/llnl/util/filesystem.py +++ b/lib/spack/llnl/util/filesystem.py @@ -27,9 +27,10 @@ __all__ = ['set_install_permissions', 'install', 'install_tree', 'traverse_tree' 'force_remove', 'join_path', 'ancestor', 'can_access', 'filter_file', 'FileFilter', 'change_sed_delimiter', 'is_exe', 'force_symlink', 'set_executable', 'copy_mode', 'unset_executable_mode', - 'remove_dead_links', 'remove_linked_tree'] + 'remove_dead_links', 'remove_linked_tree', 'fix_darwin_install_name'] import os +import glob import sys import re import shutil @@ -38,6 +39,7 @@ import errno import getpass from contextlib import contextmanager, closing from tempfile import NamedTemporaryFile +import subprocess import llnl.util.tty as tty from spack.util.compression import ALLOWED_ARCHIVE_TYPES @@ -392,3 +394,29 @@ def remove_linked_tree(path): os.unlink(path) else: shutil.rmtree(path, True) + +def fix_darwin_install_name(path): + """ + Fix install name of dynamic libraries on Darwin to have full path. + There are two parts of this task: + (i) use install_name('-id',...) to change install name of a single lib; + (ii) use install_name('-change',...) to change the cross linking between libs. + The function assumes that all libraries are in one folder and currently won't + follow subfolders. + + Args: + path: directory in which .dylib files are alocated + + """ + libs = glob.glob(join_path(path,"*.dylib")) + for lib in libs: + # fix install name first: + subprocess.Popen(["install_name_tool", "-id",lib,lib], stdout=subprocess.PIPE).communicate()[0] + long_deps = subprocess.Popen(["otool", "-L",lib], stdout=subprocess.PIPE).communicate()[0].split('\n') + deps = [dep.partition(' ')[0][1::] for dep in long_deps[2:-1]] + # fix all dependencies: + for dep in deps: + for loc in libs: + if dep == os.path.basename(loc): + subprocess.Popen(["install_name_tool", "-change",dep,loc,lib], stdout=subprocess.PIPE).communicate()[0] + break diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py index d45fdde703..f6a11c92e3 100644 --- a/lib/spack/spack/modules.py +++ b/lib/spack/spack/modules.py @@ -278,6 +278,6 @@ class TclModule(EnvModule): # Long description if self.long_description: module_file.write('proc ModulesHelp { } {\n') - doc = re.sub(r'"', '\"', self.long_description) - module_file.write("puts stderr \"%s\"\n" % doc) + for line in textwrap.wrap(self.long_description, 72): + module_file.write("puts stderr \"%s\"\n" % line) module_file.write('}\n\n') diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py index f3f6d4a22e..0b1aeb2a8f 100644 --- a/lib/spack/spack/test/cc.py +++ b/lib/spack/spack/test/cc.py @@ -28,6 +28,8 @@ arguments correctly. """ import os import unittest +import tempfile +import shutil from llnl.util.filesystem import * import spack @@ -55,13 +57,40 @@ class CompilerTest(unittest.TestCase): self.ld = Executable(join_path(spack.build_env_path, "ld")) self.cpp = Executable(join_path(spack.build_env_path, "cpp")) - os.environ['SPACK_CC'] = "/bin/mycc" - os.environ['SPACK_PREFIX'] = "/usr" + self.realcc = "/bin/mycc" + self.prefix = "/spack-test-prefix" + + os.environ['SPACK_CC'] = self.realcc + os.environ['SPACK_PREFIX'] = self.prefix os.environ['SPACK_ENV_PATH']="test" os.environ['SPACK_DEBUG_LOG_DIR'] = "." os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7" os.environ['SPACK_SHORT_SPEC'] = "foo@1.2" + # Make some fake dependencies + self.tmp_deps = tempfile.mkdtemp() + self.dep1 = join_path(self.tmp_deps, 'dep1') + self.dep2 = join_path(self.tmp_deps, 'dep2') + self.dep3 = join_path(self.tmp_deps, 'dep3') + self.dep4 = join_path(self.tmp_deps, 'dep4') + + mkdirp(join_path(self.dep1, 'include')) + mkdirp(join_path(self.dep1, 'lib')) + + mkdirp(join_path(self.dep2, 'lib64')) + + mkdirp(join_path(self.dep3, 'include')) + mkdirp(join_path(self.dep3, 'lib64')) + + mkdirp(join_path(self.dep4, 'include')) + + if 'SPACK_DEPENDENCIES' in os.environ: + del os.environ['SPACK_DEPENDENCIES'] + + + def tearDown(self): + shutil.rmtree(self.tmp_deps, True) + def check_cc(self, command, args, expected): os.environ['SPACK_TEST_COMMAND'] = command @@ -92,6 +121,10 @@ class CompilerTest(unittest.TestCase): self.check_cpp('dump-mode', [], "cpp") + def test_as_mode(self): + self.check_cc('dump-mode', ['-S'], "as") + + def test_ccld_mode(self): self.check_cc('dump-mode', [], "ccld") self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld") @@ -104,27 +137,85 @@ class CompilerTest(unittest.TestCase): self.check_ld('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath,foo'], "ld") - def test_includes(self): - self.check_cc('dump-includes', test_command, - "\n".join(["/test/include", "/other/include"])) + def test_dep_rpath(self): + """Ensure RPATHs for root package are added.""" + self.check_cc('dump-args', test_command, + self.realcc + ' ' + + '-Wl,-rpath,' + self.prefix + '/lib ' + + '-Wl,-rpath,' + self.prefix + '/lib64 ' + + ' '.join(test_command)) + + + def test_dep_include(self): + """Ensure a single dependency include directory is added.""" + os.environ['SPACK_DEPENDENCIES'] = self.dep4 + self.check_cc('dump-args', test_command, + self.realcc + ' ' + + '-Wl,-rpath,' + self.prefix + '/lib ' + + '-Wl,-rpath,' + self.prefix + '/lib64 ' + + '-I' + self.dep4 + '/include ' + + ' '.join(test_command)) + + + def test_dep_lib(self): + """Ensure a single dependency RPATH is added.""" + os.environ['SPACK_DEPENDENCIES'] = self.dep2 + self.check_cc('dump-args', test_command, + self.realcc + ' ' + + '-Wl,-rpath,' + self.prefix + '/lib ' + + '-Wl,-rpath,' + self.prefix + '/lib64 ' + + '-L' + self.dep2 + '/lib64 ' + + '-Wl,-rpath,' + self.dep2 + '/lib64 ' + + ' '.join(test_command)) + + + def test_all_deps(self): + """Ensure includes and RPATHs for all deps are added. """ + os.environ['SPACK_DEPENDENCIES'] = ':'.join([ + self.dep1, self.dep2, self.dep3, self.dep4]) + + # This is probably more constrained than it needs to be; it + # checks order within prepended args and doesn't strictly have + # to. We could loosen that if it becomes necessary + self.check_cc('dump-args', test_command, + self.realcc + ' ' + + '-Wl,-rpath,' + self.prefix + '/lib ' + + '-Wl,-rpath,' + self.prefix + '/lib64 ' + + + '-I' + self.dep4 + '/include ' + + + '-L' + self.dep3 + '/lib64 ' + + '-Wl,-rpath,' + self.dep3 + '/lib64 ' + + '-I' + self.dep3 + '/include ' + + + '-L' + self.dep2 + '/lib64 ' + + '-Wl,-rpath,' + self.dep2 + '/lib64 ' + + + '-L' + self.dep1 + '/lib ' + + '-Wl,-rpath,' + self.dep1 + '/lib ' + + '-I' + self.dep1 + '/include ' + + + ' '.join(test_command)) - def test_libraries(self): - self.check_cc('dump-libraries', test_command, - "\n".join(["/test/lib", "/other/lib"])) + def test_ld_deps(self): + """Ensure no (extra) -I args or -Wl, are passed in ld mode.""" + os.environ['SPACK_DEPENDENCIES'] = ':'.join([ + self.dep1, self.dep2, self.dep3, self.dep4]) + self.check_ld('dump-args', test_command, + 'ld ' + + '-rpath ' + self.prefix + '/lib ' + + '-rpath ' + self.prefix + '/lib64 ' + - def test_libs(self): - self.check_cc('dump-libs', test_command, - "\n".join(["lib1", "lib2", "lib3", "lib4"])) + '-L' + self.dep3 + '/lib64 ' + + '-rpath ' + self.dep3 + '/lib64 ' + + '-L' + self.dep2 + '/lib64 ' + + '-rpath ' + self.dep2 + '/lib64 ' + - def test_rpaths(self): - self.check_cc('dump-rpaths', test_command, - "\n".join(["/first/rpath", "/second/rpath", "/third/rpath", "/fourth/rpath"])) + '-L' + self.dep1 + '/lib ' + + '-rpath ' + self.dep1 + '/lib ' + + ' '.join(test_command)) - def test_other_args(self): - self.check_cc('dump-other-args', test_command, - "\n".join(["arg1", "-Wl,--start-group", "arg2", "arg3", "arg4", - "-Wl,--end-group", "arg5", "arg6"])) diff --git a/var/spack/repos/builtin/packages/boost/package.py b/var/spack/repos/builtin/packages/boost/package.py index fb1f5daee7..82ce6fbb74 100644 --- a/var/spack/repos/builtin/packages/boost/package.py +++ b/var/spack/repos/builtin/packages/boost/package.py @@ -1,5 +1,6 @@ from spack import * import spack +import sys class Boost(Package): """Boost provides free peer-reviewed portable C++ source @@ -45,34 +46,34 @@ class Boost(Package): version('1.34.1', '2d938467e8a448a2c9763e0a9f8ca7e5') version('1.34.0', 'ed5b9291ffad776f8757a916e1726ad0') - default_install_libs = set(['atomic', - 'chrono', - 'date_time', - 'filesystem', + default_install_libs = set(['atomic', + 'chrono', + 'date_time', + 'filesystem', 'graph', 'iostreams', 'locale', 'log', - 'math', + 'math', 'program_options', - 'random', - 'regex', - 'serialization', - 'signals', - 'system', - 'test', - 'thread', + 'random', + 'regex', + 'serialization', + 'signals', + 'system', + 'test', + 'thread', 'wave']) - # mpi/python are not installed by default because they pull in many - # dependencies and/or because there is a great deal of customization + # mpi/python are not installed by default because they pull in many + # dependencies and/or because there is a great deal of customization # possible (and it would be difficult to choose sensible defaults) default_noinstall_libs = set(['mpi', 'python']) all_libs = default_install_libs | default_noinstall_libs for lib in all_libs: - variant(lib, default=(lib not in default_noinstall_libs), + variant(lib, default=(lib not in default_noinstall_libs), description="Compile with {0} library".format(lib)) variant('debug', default=False, description='Switch to the debug version of Boost') @@ -124,9 +125,9 @@ class Boost(Package): with open('user-config.jam', 'w') as f: compiler_wrapper = join_path(spack.build_env_path, 'c++') - f.write("using {0} : : {1} ;\n".format(boostToolsetId, + f.write("using {0} : : {1} ;\n".format(boostToolsetId, compiler_wrapper)) - + if '+mpi' in spec: f.write('using mpi : %s ;\n' % join_path(spec['mpi'].prefix.bin, 'mpicxx')) @@ -155,7 +156,7 @@ class Boost(Package): linkTypes = ['static'] if '+shared' in spec: linkTypes.append('shared') - + threadingOpts = [] if '+multithreaded' in spec: threadingOpts.append('multi') @@ -163,12 +164,12 @@ class Boost(Package): threadingOpts.append('single') if not threadingOpts: raise RuntimeError("At least one of {singlethreaded, multithreaded} must be enabled") - + options.extend([ 'toolset=%s' % self.determine_toolset(spec), 'link=%s' % ','.join(linkTypes), '--layout=tagged']) - + return threadingOpts def install(self, spec, prefix): @@ -177,14 +178,14 @@ class Boost(Package): if "+{0}".format(lib) in spec: withLibs.append(lib) if not withLibs: - # if no libraries are specified for compilation, then you dont have + # if no libraries are specified for compilation, then you dont have # to configure/build anything, just copy over to the prefix directory. src = join_path(self.stage.source_path, 'boost') mkdirp(join_path(prefix, 'include')) dst = join_path(prefix, 'include', 'boost') install_tree(src, dst) return - + # to make Boost find the user-config.jam env['BOOST_BUILD_PATH'] = './' @@ -207,4 +208,7 @@ class Boost(Package): # Boost.MPI if the threading options are not separated. for threadingOpt in threadingOpts: b2('install', 'threading=%s' % threadingOpt, *b2_options) - + + # The shared libraries are not installed correctly on Darwin; correct this + if (sys.platform == 'darwin') and ('+shared' in spec): + fix_darwin_install_name(prefix.lib) diff --git a/var/spack/repos/builtin/packages/hypre/package.py b/var/spack/repos/builtin/packages/hypre/package.py index 8d93d48d1f..0e99553293 100644 --- a/var/spack/repos/builtin/packages/hypre/package.py +++ b/var/spack/repos/builtin/packages/hypre/package.py @@ -14,6 +14,8 @@ class Hypre(Package): # hypre does not know how to build shared libraries on Darwin variant('shared', default=sys.platform!='darwin', description="Build shared library version (disables static library)") + # SuperluDist have conflicting headers with those in Hypre + variant('internal-superlu', default=True, description="Use internal Superlu routines") depends_on("mpi") depends_on("blas") @@ -38,6 +40,9 @@ class Hypre(Package): if '+shared' in self.spec: configure_args.append("--enable-shared") + if '~internal-superlu' in self.spec: + configure_args.append("--without-superlu") + # Hypre's source is staged under ./src so we'll have to manually # cd into it. with working_dir("src"): diff --git a/var/spack/repos/builtin/packages/metis/package.py b/var/spack/repos/builtin/packages/metis/package.py index 68b9f6fd30..9301135f9f 100644 --- a/var/spack/repos/builtin/packages/metis/package.py +++ b/var/spack/repos/builtin/packages/metis/package.py @@ -24,7 +24,7 @@ ############################################################################## from spack import * -import glob +import glob,sys class Metis(Package): """ @@ -90,3 +90,7 @@ class Metis(Package): fs = glob.glob(join_path(source_directory,'GKlib',"*.h")) for f in fs: install(f, GKlib_dist) + + # The shared library is not installed correctly on Darwin; correct this + if (sys.platform == 'darwin') and ('+shared' in spec): + fix_darwin_install_name(prefix.lib) diff --git a/var/spack/repos/builtin/packages/mumps/Makefile.inc b/var/spack/repos/builtin/packages/mumps/Makefile.inc index 2e6a041878..22d8f5518a 100644 --- a/var/spack/repos/builtin/packages/mumps/Makefile.inc +++ b/var/spack/repos/builtin/packages/mumps/Makefile.inc @@ -8,12 +8,9 @@ IORDERINGSF = $(ISCOTCH) IORDERINGSC = $(IMETIS) $(IPORD) $(ISCOTCH) PLAT = -LIBEXT = .a -OUTC = -o +OUTC = -o OUTF = -o RM = /bin/rm -f -AR = ar vr -RANLIB = ranlib INCSEQ = -I$(topdir)/libseq LIBSEQ = -L$(topdir)/libseq -lmpiseq diff --git a/var/spack/repos/builtin/packages/mumps/package.py b/var/spack/repos/builtin/packages/mumps/package.py index 5a254dfd00..26440ab7c8 100644 --- a/var/spack/repos/builtin/packages/mumps/package.py +++ b/var/spack/repos/builtin/packages/mumps/package.py @@ -1,6 +1,5 @@ from spack import * -import os - +import os, sys class Mumps(Package): """MUMPS: a MUltifrontal Massively Parallel sparse direct Solver""" @@ -19,6 +18,7 @@ class Mumps(Package): variant('float', default=True, description='Activate the compilation of smumps') variant('complex', default=True, description='Activate the compilation of cmumps and/or zmumps') variant('idx64', default=False, description='Use int64_t/integer*8 as default index type') + variant('shared', default=True, description='Build shared libraries') depends_on('scotch + esmumps', when='~ptscotch+scotch') @@ -70,6 +70,9 @@ class Mumps(Package): makefile_conf.append("ORDERINGSF = %s" % (' '.join(orderings))) + # when building shared libs need -fPIC, otherwise + # /usr/bin/ld: graph.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC + fpic = '-fPIC' if '+shared' in self.spec else '' # TODO: test this part, it needs a full blas, scalapack and # partitionning environment with 64bit integers if '+idx64' in self.spec: @@ -77,14 +80,14 @@ class Mumps(Package): # the fortran compilation flags most probably are # working only for intel and gnu compilers this is # perhaps something the compiler should provide - ['OPTF = -O -DALLOW_NON_INIT %s' % '-fdefault-integer-8' if self.compiler.name == "gcc" else '-i8', - 'OPTL = -O ', - 'OPTC = -O -DINTSIZE64']) + ['OPTF = %s -O -DALLOW_NON_INIT %s' % (fpic,'-fdefault-integer-8' if self.compiler.name == "gcc" else '-i8'), + 'OPTL = %s -O ' % fpic, + 'OPTC = %s -O -DINTSIZE64' % fpic]) else: makefile_conf.extend( - ['OPTF = -O -DALLOW_NON_INIT', - 'OPTL = -O ', - 'OPTC = -O ']) + ['OPTF = %s -O -DALLOW_NON_INIT' % fpic, + 'OPTL = %s -O ' % fpic, + 'OPTC = %s -O ' % fpic]) if '+mpi' in self.spec: @@ -105,6 +108,27 @@ class Mumps(Package): # compiler possible values are -DAdd_, -DAdd__ and/or -DUPPER makefile_conf.append("CDEFS = -DAdd_") + if '+shared' in self.spec: + if sys.platform == 'darwin': + # Building dylibs with mpif90 causes segfaults on 10.8 and 10.10. Use gfortran. (Homebrew) + makefile_conf.extend([ + 'LIBEXT=.dylib', + 'AR=%s -dynamiclib -Wl,-install_name -Wl,%s/$(notdir $@) -undefined dynamic_lookup -o ' % (os.environ['FC'],prefix.lib), + 'RANLIB=echo' + ]) + else: + makefile_conf.extend([ + 'LIBEXT=.so', + 'AR=$(FL) -shared -Wl,-soname -Wl,%s/$(notdir $@) -o' % prefix.lib, + 'RANLIB=echo' + ]) + else: + makefile_conf.extend([ + 'LIBEXT = .a', + 'AR = ar vr', + 'RANLIB = ranlib' + ]) + makefile_inc_template = join_path(os.path.dirname(self.module.__file__), 'Makefile.inc') @@ -121,7 +145,7 @@ class Mumps(Package): def install(self, spec, prefix): make_libs = [] - # the coice to compile ?examples is to have kind of a sanity + # the choice to compile ?examples is to have kind of a sanity # check on the libraries generated. if '+float' in spec: make_libs.append('sexamples') @@ -135,10 +159,24 @@ class Mumps(Package): self.write_makefile_inc() - # Build fails in parallel, at least on OS-X + # Build fails in parallel make(*make_libs, parallel=False) install_tree('lib', prefix.lib) install_tree('include', prefix.include) if '~mpi' in spec: - install('libseq/libmpiseq.a', prefix.lib) + lib_dsuffix = '.dylib' if sys.platform == 'darwin' else '.so' + lib_suffix = lib_dsuffix if '+shared' in spec else '.a' + install('libseq/libmpiseq%s' % lib_suffix, prefix.lib) + + # FIXME: extend the tests to mpirun -np 2 (or alike) when build with MPI + # FIXME: use something like numdiff to compare blessed output with the current + with working_dir('examples'): + if '+float' in spec: + os.system('./ssimpletest < input_simpletest_real') + if '+complex' in spec: + os.system('./csimpletest < input_simpletest_real') + if '+double' in spec: + os.system('./dsimpletest < input_simpletest_real') + if '+complex' in spec: + os.system('./zsimpletest < input_simpletest_cmplx') diff --git a/var/spack/repos/builtin/packages/netcdf-cxx/package.py b/var/spack/repos/builtin/packages/netcdf-cxx/package.py new file mode 100644 index 0000000000..5334dfb853 --- /dev/null +++ b/var/spack/repos/builtin/packages/netcdf-cxx/package.py @@ -0,0 +1,15 @@ +from spack import * + +class NetcdfCxx(Package): + """C++ compatibility bindings for NetCDF""" + homepage = "http://www.unidata.ucar.edu/software/netcdf" + url = "http://www.unidata.ucar.edu/downloads/netcdf/ftp/netcdf-cxx-4.2.tar.gz" + + version('4.2', 'd32b20c00f144ae6565d9e98d9f6204c') + + depends_on('netcdf') + + def install(self, spec, prefix): + configure('--prefix=%s' % prefix) + make() + make("install") diff --git a/var/spack/repos/builtin/packages/netlib-scalapack/package.py b/var/spack/repos/builtin/packages/netlib-scalapack/package.py index c3e6822cdf..d59f8e41fe 100644 --- a/var/spack/repos/builtin/packages/netlib-scalapack/package.py +++ b/var/spack/repos/builtin/packages/netlib-scalapack/package.py @@ -41,6 +41,11 @@ class NetlibScalapack(Package): make() make("install") + # The shared libraries are not installed correctly on Darwin; correct this + if (sys.platform == 'darwin') and ('+shared' in spec): + fix_darwin_install_name(prefix.lib) + + def setup_dependent_package(self, module, dependent_spec): spec = self.spec lib_dsuffix = '.dylib' if sys.platform == 'darwin' else '.so' diff --git a/var/spack/repos/builtin/packages/oce/package.py b/var/spack/repos/builtin/packages/oce/package.py index 06acb96736..4d5081ac9d 100644 --- a/var/spack/repos/builtin/packages/oce/package.py +++ b/var/spack/repos/builtin/packages/oce/package.py @@ -1,5 +1,5 @@ from spack import * -import platform +import platform, sys class Oce(Package): """ @@ -45,3 +45,7 @@ class Oce(Package): cmake('.', *options) make("install/strip") + + # The shared libraries are not installed correctly on Darwin; correct this + if (sys.platform == 'darwin'): + fix_darwin_install_name(prefix.lib) diff --git a/var/spack/repos/builtin/packages/parmetis/package.py b/var/spack/repos/builtin/packages/parmetis/package.py index f5b8b6de91..ff4370aa4b 100644 --- a/var/spack/repos/builtin/packages/parmetis/package.py +++ b/var/spack/repos/builtin/packages/parmetis/package.py @@ -24,7 +24,7 @@ ############################################################################## from spack import * - +import sys class Parmetis(Package): """ @@ -83,3 +83,7 @@ class Parmetis(Package): cmake(source_directory, *options) make() make("install") + + # The shared library is not installed correctly on Darwin; correct this + if (sys.platform == 'darwin') and ('+shared' in spec): + fix_darwin_install_name(prefix.lib) diff --git a/var/spack/repos/builtin/packages/petsc/package.py b/var/spack/repos/builtin/packages/petsc/package.py index 3dd117eed1..e9b7c8a732 100644 --- a/var/spack/repos/builtin/packages/petsc/package.py +++ b/var/spack/repos/builtin/packages/petsc/package.py @@ -17,14 +17,18 @@ class Petsc(Package): version('3.5.1', 'a557e029711ebf425544e117ffa44d8f') version('3.4.4', '7edbc68aa6d8d6a3295dd5f6c2f6979d') - variant('shared', default=True, description='Enables the build of shared libraries') - variant('mpi', default=True, description='Activates MPI support') - variant('double', default=True, description='Switches between single and double precision') - - variant('metis', default=True, description='Activates support for metis and parmetis') - variant('hdf5', default=True, description='Activates support for HDF5 (only parallel)') - variant('boost', default=True, description='Activates support for Boost') - variant('hypre', default=True, description='Activates support for Hypre') + variant('shared', default=True, description='Enables the build of shared libraries') + variant('mpi', default=True, description='Activates MPI support') + variant('double', default=True, description='Switches between single and double precision') + variant('complex', default=False, description='Build with complex numbers') + variant('debug', default=False, description='Compile in debug mode') + + variant('metis', default=True, description='Activates support for metis and parmetis') + variant('hdf5', default=True, description='Activates support for HDF5 (only parallel)') + variant('boost', default=True, description='Activates support for Boost') + variant('hypre', default=True, description='Activates support for Hypre (only parallel)') + variant('mumps', default=True, description='Activates support for MUMPS (only parallel)') + variant('superlu-dist', default=True, description='Activates support for SuperluDist (only parallel)') # Virtual dependencies depends_on('blas') @@ -40,7 +44,13 @@ class Petsc(Package): depends_on('hdf5+mpi', when='+hdf5+mpi') depends_on('parmetis', when='+metis+mpi') - depends_on('hypre', when='+hypre+mpi') + # Hypre does not support complex numbers. + # Also PETSc prefer to build it without internal superlu, likely due to conflict in headers + # see https://bitbucket.org/petsc/petsc/src/90564b43f6b05485163c147b464b5d6d28cde3ef/config/BuildSystem/config/packages/hypre.py + depends_on('hypre~internal-superlu', when='+hypre+mpi~complex') + depends_on('superlu-dist', when='+superlu-dist+mpi') + depends_on('mumps+mpi', when='+mumps+mpi') + depends_on('scalapack', when='+mumps+mpi') def mpi_dependent_options(self): if '~mpi' in self.spec: @@ -55,7 +65,7 @@ class Petsc(Package): # If mpi is disabled (~mpi), it's an error to have any of these enabled. # This generates a list of any such errors. errors = [error_message_fmt.format(library=x) - for x in ('hdf5', 'hypre', 'parmetis') + for x in ('hdf5', 'hypre', 'parmetis','mumps','superlu-dist') if ('+'+x) in self.spec] if errors: errors = ['incompatible variants given'] + errors @@ -77,16 +87,17 @@ class Petsc(Package): return compiler_opts def install(self, spec, prefix): - options = ['--with-debugging=0', - '--with-ssl=0'] + options = ['--with-ssl=0'] options.extend(self.mpi_dependent_options()) options.extend([ '--with-precision=%s' % ('double' if '+double' in spec else 'single'), + '--with-scalar-type=%s' % ('complex' if '+complex' in spec else 'real'), '--with-shared-libraries=%s' % ('1' if '+shared' in spec else '0'), + '--with-debugging=%s' % ('1' if '+debug' in spec else '0'), '--with-blas-lapack-dir=%s' % spec['lapack'].prefix ]) # Activates library support if needed - for library in ('metis', 'boost', 'hdf5', 'hypre', 'parmetis'): + for library in ('metis', 'boost', 'hdf5', 'hypre', 'parmetis','mumps','scalapack'): options.append( '--with-{library}={value}'.format(library=library, value=('1' if library in spec else '0')) ) @@ -94,6 +105,17 @@ class Petsc(Package): options.append( '--with-{library}-dir={path}'.format(library=library, path=spec[library].prefix) ) + # PETSc does not pick up SuperluDist from the dir as they look for superlu_dist_4.1.a + if 'superlu-dist' in spec: + options.extend([ + '--with-superlu_dist-include=%s' % spec['superlu-dist'].prefix.include, + '--with-superlu_dist-lib=%s' % join_path(spec['superlu-dist'].prefix.lib, 'libsuperlu_dist.a'), + '--with-superlu_dist=1' + ]) + else: + options.append( + '--with-superlu_dist=0' + ) configure('--prefix=%s' % prefix, *options) diff --git a/var/spack/repos/builtin/packages/py-netcdf/package.py b/var/spack/repos/builtin/packages/py-netcdf/package.py new file mode 100644 index 0000000000..7faa15ad25 --- /dev/null +++ b/var/spack/repos/builtin/packages/py-netcdf/package.py @@ -0,0 +1,16 @@ +from spack import * + +class PyNetcdf(Package): + """Python interface to the netCDF Library.""" + homepage = "http://unidata.github.io/netcdf4-python" + url = "https://github.com/Unidata/netcdf4-python/tarball/v1.2.3.1rel" + + version('1.2.3.1', '4fc4320d4f2a77b894ebf8da1c9895af') + + extends('python') + depends_on('py-numpy') + depends_on('py-cython') + depends_on('netcdf') + + def install(self, spec, prefix): + python('setup.py', 'install', '--prefix=%s' % prefix) diff --git a/var/spack/repos/builtin/packages/superlu-dist/package.py b/var/spack/repos/builtin/packages/superlu-dist/package.py index 9a94de8ba5..ddcb7f9225 100644 --- a/var/spack/repos/builtin/packages/superlu-dist/package.py +++ b/var/spack/repos/builtin/packages/superlu-dist/package.py @@ -1,4 +1,5 @@ from spack import * +import glob class SuperluDist(Package): """A general purpose library for the direct solution of large, sparse, nonsymmetric systems of linear equations on high performance machines.""" @@ -52,13 +53,13 @@ class SuperluDist(Package): # system "make" # need to install by hand - headers_location = join_path(self.prefix.include,'superlu_dist') + headers_location = self.prefix.include mkdirp(headers_location) mkdirp(prefix.lib) - # FIXME: fetch all headers in the folder automatically - for header in ['Cnames.h','cublas_utils.h','dcomplex.h','html_mainpage.h','machines.h','old_colamd.h','psymbfact.h','superlu_ddefs.h','superlu_defs.h','superlu_enum_consts.h','superlu_zdefs.h','supermatrix.h','util_dist.h']: - superludist_header = join_path(self.stage.source_path, 'SRC/',header) - install(superludist_header, headers_location) + + headers = glob.glob(join_path(self.stage.source_path, 'SRC','*.h')) + for h in headers: + install(h,headers_location) superludist_lib = join_path(self.stage.source_path, 'lib/libsuperlu_dist.a') install(superludist_lib,self.prefix.lib) |