From fbabfc593d10a7fc35944e72e2eb8b1ebf4818eb Mon Sep 17 00:00:00 2001 From: Glenn Johnson Date: Wed, 6 Apr 2016 16:44:22 -0500 Subject: Make R extensable and add a couple of packages for verification. Added R as a build system so that the create template will have the correct configure line. Added a regex for version parsing as the R URLs are a little odd. --- lib/spack/spack/cmd/create.py | 8 +++++++- lib/spack/spack/url.py | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/create.py b/lib/spack/spack/cmd/create.py index f0cd50b8df..e3a31806ab 100644 --- a/lib/spack/spack/cmd/create.py +++ b/lib/spack/spack/cmd/create.py @@ -124,10 +124,12 @@ class ConfigureGuesser(object): autotools = "configure('--prefix=%s' % prefix)" cmake = "cmake('.', *std_cmake_args)" python = "python('setup.py', 'install', '--prefix=%s' % prefix)" + r = "R('CMD', 'INSTALL', '--library=%s' % self.module.r_lib_dir, '%s' % self.stage.archive_file)" config_lines = ((r'/configure$', 'autotools', autotools), (r'/CMakeLists.txt$', 'cmake', cmake), - (r'/setup.py$', 'python', python)) + (r'/setup.py$', 'python', python), + (r'/NAMESPACE$', 'r', r)) # Peek inside the tarball. tar = which('tar') @@ -272,6 +274,10 @@ def create(parser, args): if guesser.build_system == 'python': name = 'py-%s' % name + # Prepend 'r-' to R package names, by convention. + if guesser.build_system == 'r': + name = 'r-%s' % name + # Create a directory for the new package. pkg_path = repo.filename_for_package_name(name) if os.path.exists(pkg_path) and not args.force: diff --git a/lib/spack/spack/url.py b/lib/spack/spack/url.py index f51f05cad7..b4fb70d6fb 100644 --- a/lib/spack/spack/url.py +++ b/lib/spack/spack/url.py @@ -206,6 +206,9 @@ def parse_version_offset(path): # e.g. lame-398-1 (r'-((\d)+-\d)', stem), + # e.g. foobar_1.2-3 + (r'_((\d+\.)+\d+(-\d+)?)', stem), + # e.g. foobar-4.5.1 (r'-((\d+\.)*\d+)$', stem), -- cgit v1.2.3-70-g09d2 From b19d6ab9c5e4b7a8289e057826b498dd93ea7e08 Mon Sep 17 00:00:00 2001 From: Glenn Johnson Date: Wed, 6 Apr 2016 19:08:01 -0500 Subject: Check for non-numeric bits in the stem. --- lib/spack/spack/url.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/url.py b/lib/spack/spack/url.py index b4fb70d6fb..ad51da9d47 100644 --- a/lib/spack/spack/url.py +++ b/lib/spack/spack/url.py @@ -207,7 +207,7 @@ def parse_version_offset(path): (r'-((\d)+-\d)', stem), # e.g. foobar_1.2-3 - (r'_((\d+\.)+\d+(-\d+)?)', stem), + (r'_((\d+\.)+\d+(-\d+)?[a-z]?)', stem), # e.g. foobar-4.5.1 (r'-((\d+\.)*\d+)$', stem), -- cgit v1.2.3-70-g09d2 From 80678b2188acb30638e33b86a894d133ce4b4796 Mon Sep 17 00:00:00 2001 From: alalazo Date: Tue, 12 Apr 2016 16:54:51 +0200 Subject: fix : proper update of config file (before it was discarding architectures that were not the current one) fixes #774 --- bin/spack | 2 +- lib/spack/spack/cmd/compiler.py | 13 ++++++------- lib/spack/spack/config.py | 10 ++++++---- 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/bin/spack b/bin/spack index 31165bba9d..f51cb8a4ec 100755 --- a/bin/spack +++ b/bin/spack @@ -152,7 +152,7 @@ def main(): command = spack.cmd.get_command(args.command) try: return_val = command(parser, args) - except SpackError, e: + except SpackError as e: e.die() except KeyboardInterrupt: sys.stderr.write('\n') diff --git a/lib/spack/spack/cmd/compiler.py b/lib/spack/spack/cmd/compiler.py index 3e58e82184..786b3b8eb4 100644 --- a/lib/spack/spack/cmd/compiler.py +++ b/lib/spack/spack/cmd/compiler.py @@ -22,19 +22,18 @@ # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## -import sys import argparse +import sys import llnl.util.tty as tty -from llnl.util.tty.color import colorize -from llnl.util.tty.colify import colify -from llnl.util.lang import index_by - import spack.compilers -import spack.spec import spack.config -from spack.util.environment import get_path +import spack.spec +from llnl.util.lang import index_by +from llnl.util.tty.colify import colify +from llnl.util.tty.color import colorize from spack.spec import CompilerSpec +from spack.util.environment import get_path description = "Manage compilers" diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py index 14e5aaf4fb..336d47cbb7 100644 --- a/lib/spack/spack/config.py +++ b/lib/spack/spack/config.py @@ -539,14 +539,16 @@ def update_config(section, update_data, scope=None): other yaml-ish structure. """ + validate_section_name(section) # validate section name + scope = validate_scope(scope) # get ConfigScope object from string. + # read in the config to ensure we've got current data - get_config(section) + configuration = get_config(section) - validate_section_name(section) # validate section name - scope = validate_scope(scope) # get ConfigScope object from string. + configuration.update(update_data) # read only the requested section's data. - scope.sections[section] = { section : update_data } + scope.sections[section] = {section: configuration} scope.write_section(section) -- cgit v1.2.3-70-g09d2 From 27280ea8be8e108b8d128ab518d4562ec0368684 Mon Sep 17 00:00:00 2001 From: alalazo Date: Tue, 12 Apr 2016 17:21:54 +0200 Subject: fix : added regression tests --- lib/spack/spack/test/config.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/test/config.py b/lib/spack/spack/test/config.py index 0562d2d620..3977f0e7d4 100644 --- a/lib/spack/spack/test/config.py +++ b/lib/spack/spack/test/config.py @@ -33,7 +33,7 @@ from spack.test.mock_packages_test import * # Some sample compiler config data a_comps = { - "all": { + "x86_64_E5v2_IntelIB": { "gcc@4.7.3" : { "cc" : "/gcc473", "cxx": "/g++473", @@ -53,7 +53,7 @@ a_comps = { } b_comps = { - "all": { + "x86_64_E5v3": { "icc@10.0" : { "cc" : "/icc100", "cxx": "/icc100", @@ -85,27 +85,24 @@ class ConfigTest(MockPackagesTest): super(ConfigTest, self).tearDown() shutil.rmtree(self.tmp_dir, True) - - def check_config(self, comps, *compiler_names): + def check_config(self, comps, arch, *compiler_names): """Check that named compilers in comps match Spack's config.""" config = spack.config.get_config('compilers') compiler_list = ['cc', 'cxx', 'f77', 'fc'] for key in compiler_names: for c in compiler_list: - expected = comps['all'][key][c] - actual = config['all'][key][c] + expected = comps[arch][key][c] + actual = config[arch][key][c] self.assertEqual(expected, actual) - def test_write_key_in_memory(self): # Write b_comps "on top of" a_comps. spack.config.update_config('compilers', a_comps, 'test_low_priority') spack.config.update_config('compilers', b_comps, 'test_high_priority') # Make sure the config looks how we expect. - self.check_config(a_comps, 'gcc@4.7.3', 'gcc@4.5.0') - self.check_config(b_comps, 'icc@10.0', 'icc@11.1', 'clang@3.3') - + self.check_config(a_comps, 'x86_64_E5v2_IntelIB', 'gcc@4.7.3', 'gcc@4.5.0') + self.check_config(b_comps, 'x86_64_E5v3', 'icc@10.0', 'icc@11.1', 'clang@3.3') def test_write_key_to_disk(self): # Write b_comps "on top of" a_comps. @@ -116,5 +113,17 @@ class ConfigTest(MockPackagesTest): spack.config.clear_config_caches() # Same check again, to ensure consistency. - self.check_config(a_comps, 'gcc@4.7.3', 'gcc@4.5.0') - self.check_config(b_comps, 'icc@10.0', 'icc@11.1', 'clang@3.3') + self.check_config(a_comps, 'x86_64_E5v2_IntelIB', 'gcc@4.7.3', 'gcc@4.5.0') + self.check_config(b_comps, 'x86_64_E5v3', 'icc@10.0', 'icc@11.1', 'clang@3.3') + + def test_write_to_same_priority_file(self): + # Write b_comps in the same file as a_comps. + spack.config.update_config('compilers', a_comps, 'test_low_priority') + spack.config.update_config('compilers', b_comps, 'test_low_priority') + + # Clear caches so we're forced to read from disk. + spack.config.clear_config_caches() + + # Same check again, to ensure consistency. + self.check_config(a_comps, 'x86_64_E5v2_IntelIB', 'gcc@4.7.3', 'gcc@4.5.0') + self.check_config(b_comps, 'x86_64_E5v3', 'icc@10.0', 'icc@11.1', 'clang@3.3') -- cgit v1.2.3-70-g09d2 From e92da6a6ba02bdc3c879f9df8be6ee4aac2583d3 Mon Sep 17 00:00:00 2001 From: Adam Lyon Date: Mon, 8 Feb 2016 02:34:24 -0600 Subject: Handle c++11 and c++14 correctly --- lib/spack/spack/compiler.py | 3 +++ lib/spack/spack/compilers/gcc.py | 11 +++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index d38c0b00b1..20896f9eec 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -97,6 +97,9 @@ class Compiler(object): # argument used to get C++11 options cxx11_flag = "-std=c++11" + # argument used to get C++14 options + cxx14_flag = "-std=c++1y" + def __init__(self, cspec, cc, cxx, f77, fc): def check(exe): diff --git a/lib/spack/spack/compilers/gcc.py b/lib/spack/spack/compilers/gcc.py index 64214db32d..2e57e44856 100644 --- a/lib/spack/spack/compilers/gcc.py +++ b/lib/spack/spack/compilers/gcc.py @@ -54,9 +54,16 @@ class Gcc(Compiler): if self.version < ver('4.3'): tty.die("Only gcc 4.3 and above support c++11.") elif self.version < ver('4.7'): - return "-std=gnu++0x" + return "-std=c++0x" else: - return "-std=gnu++11" + return "-std=c++11" + + @property + def cxx14_flag(self): + if self.version < ver('4.8'): + tty.die("Only gcc 4.8 and above support c++14.") + else: + return "-std=c++14" @classmethod def fc_version(cls, fc): -- cgit v1.2.3-70-g09d2 From d5d1e89cbdc64a072096db89c2d78e3e1ddc7700 Mon Sep 17 00:00:00 2001 From: Patrick Gartung Date: Thu, 21 Apr 2016 21:15:54 -0500 Subject: remove use of unknown environment variable in lib/spack/env/cc (#821) --- lib/spack/env/cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/env/cc b/lib/spack/env/cc index 18fd8f7bdb..cb07a2ffea 100755 --- a/lib/spack/env/cc +++ b/lib/spack/env/cc @@ -162,7 +162,7 @@ fi # It doesn't work with -rpath. # This variable controls whether they are added. add_rpaths=true -if [[ mode == ld && $OSTYPE == darwin* ]]; then +if [[ $mode == ld && "$SPACK_SHORT_SPEC" =~ "darwin" ]]; then for arg in "$@"; do if [[ $arg == -r ]]; then add_rpaths=false -- cgit v1.2.3-70-g09d2 From a0989ad672bd22afe89ee2c2f50b32003ebb2764 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Fri, 22 Apr 2016 04:26:19 +0200 Subject: minor cleanup of environment-modules documentation (#814) * minor cleanup of environment-modules documentation * environment modules: update usage instructions --- lib/spack/docs/basic_usage.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/spack/docs/basic_usage.rst b/lib/spack/docs/basic_usage.rst index 68f3d07b29..0e603813e1 100644 --- a/lib/spack/docs/basic_usage.rst +++ b/lib/spack/docs/basic_usage.rst @@ -807,17 +807,22 @@ Environment Modules, you can get it with Spack: 1. Install with:: +.. code-block:: sh + spack install environment-modules 2. Activate with:: - MODULES_HOME=`spack location -i environment-modules` - MODULES_VERSION=`ls -1 $MODULES_HOME/Modules | head -1` - ${MODULES_HOME}/Modules/${MODULES_VERSION}/bin/add.modules +Add the following two lines to your ``.bashrc`` profile (or similar): + +.. code-block:: sh + + MODULES_HOME=`spack location -i environment-modules` + source ${MODULES_HOME}/Modules/init/bash + +In case you use a Unix shell other than bash, substitute ``bash`` by +the appropriate file in ``${MODULES_HOME}/Modules/init/``. -This adds to your ``.bashrc`` (or similar) files, enabling Environment -Modules when you log in. It will ask your permission before changing -any files. Spack and Environment Modules ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3-70-g09d2 From fa02f94ca4bada75cca4248665bbc007412294c5 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Thu, 21 Apr 2016 23:10:10 -0700 Subject: Regression test for not adding RPATHs with `ld -r` (#809, #821) - ld -r is only broken with rpaths on OSX; this tests that specific case. - test should still work cross-platform. --- lib/spack/spack/test/cc.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py index 0b1aeb2a8f..594cd6efe9 100644 --- a/lib/spack/spack/test/cc.py +++ b/lib/spack/spack/test/cc.py @@ -219,3 +219,27 @@ class CompilerTest(unittest.TestCase): ' '.join(test_command)) + def test_ld_deps_reentrant(self): + """Make sure ld -r is handled correctly on OS's where it doesn't + support rpaths.""" + os.environ['SPACK_DEPENDENCIES'] = ':'.join([self.dep1]) + + os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=linux-x86_64" + reentrant_test_command = ['-r'] + test_command + self.check_ld('dump-args', reentrant_test_command, + 'ld ' + + '-rpath ' + self.prefix + '/lib ' + + '-rpath ' + self.prefix + '/lib64 ' + + + '-L' + self.dep1 + '/lib ' + + '-rpath ' + self.dep1 + '/lib ' + + + '-r ' + + ' '.join(test_command)) + + os.environ['SPACK_SHORT_SPEC'] = "foo@1.2=darwin-x86_64" + self.check_ld('dump-args', reentrant_test_command, + 'ld ' + + '-L' + self.dep1 + '/lib ' + + '-r ' + + ' '.join(test_command)) -- cgit v1.2.3-70-g09d2 From ed16bd133afd4c4da48f9d92e0d8578fd3719c72 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 23 Apr 2016 16:34:51 -0400 Subject: compiler: add "find" subcommand (#818) And make "add" an alias to it. Fixes #713. --- lib/spack/spack/cmd/compiler.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/compiler.py b/lib/spack/spack/cmd/compiler.py index 3e58e82184..a8e9e2a7a5 100644 --- a/lib/spack/spack/cmd/compiler.py +++ b/lib/spack/spack/cmd/compiler.py @@ -44,10 +44,10 @@ def setup_parser(subparser): scopes = spack.config.config_scopes - # Add - add_parser = sp.add_parser('add', help='Add compilers to the Spack configuration.') - add_parser.add_argument('add_paths', nargs=argparse.REMAINDER) - add_parser.add_argument('--scope', choices=scopes, default=spack.cmd.default_modify_scope, + # Find + find_parser = sp.add_parser('find', aliases=['add'], help='Search the system for compilers to add to the Spack configuration.') + find_parser.add_argument('add_paths', nargs=argparse.REMAINDER) + find_parser.add_argument('--scope', choices=scopes, default=spack.cmd.default_modify_scope, help="Configuration scope to modify.") # Remove @@ -70,7 +70,7 @@ def setup_parser(subparser): help="Configuration scope to read from.") -def compiler_add(args): +def compiler_find(args): """Search either $PATH or a list of paths for compilers and add them to Spack's configuration.""" paths = args.add_paths @@ -136,7 +136,8 @@ def compiler_list(args): def compiler(parser, args): - action = { 'add' : compiler_add, + action = { 'add' : compiler_find, + 'find' : compiler_find, 'remove' : compiler_remove, 'rm' : compiler_remove, 'info' : compiler_info, -- cgit v1.2.3-70-g09d2 From ff9145f8a5a95808d43db1dbc40414e644448419 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 30 Mar 2016 16:08:09 -0400 Subject: executable: quote arguments This allows command line arguments with spaces to be shown. The quoting madness is because a single quote cannot appear within a single quoted argument on the command line. To do so, you have to stop the single quote argument, double quote the single quote, then open the single quote again: $ echo 'before'"'"'after' before'after Fixes #174 --- lib/spack/spack/util/executable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/util/executable.py b/lib/spack/spack/util/executable.py index fc27b789d0..25819b6fc7 100644 --- a/lib/spack/spack/util/executable.py +++ b/lib/spack/spack/util/executable.py @@ -144,7 +144,7 @@ class Executable(object): cmd = self.exe + list(args) - cmd_line = ' '.join(cmd) + cmd_line = "'%s'" % "' '".join(map(lambda arg: arg.replace("'", "'\"'\"'"), cmd)) tty.debug(cmd_line) try: -- cgit v1.2.3-70-g09d2 From 99b52e6e719efcee14cbba0a338c6593aad53422 Mon Sep 17 00:00:00 2001 From: alalazo Date: Tue, 26 Apr 2016 16:41:33 +0200 Subject: test-install : wip to add other information --- lib/spack/spack/cmd/test-install.py | 114 ++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 51 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/test-install.py b/lib/spack/spack/cmd/test-install.py index 656873a2f0..733b58f252 100644 --- a/lib/spack/spack/cmd/test-install.py +++ b/lib/spack/spack/cmd/test-install.py @@ -23,36 +23,39 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## import argparse -import xml.etree.ElementTree as ET +import codecs import itertools -import re import os -import codecs +import re +import time +import xml.etree.ElementTree as ET import llnl.util.tty as tty -from llnl.util.filesystem import * - import spack +import spack.cmd +from llnl.util.filesystem import * from spack.build_environment import InstallError from spack.fetch_strategy import FetchError -import spack.cmd description = "Run package installation as a unit test, output formatted results." + def setup_parser(subparser): - subparser.add_argument( - '-j', '--jobs', action='store', type=int, - help="Explicitly set number of make jobs. Default is #cpus.") + subparser.add_argument('-j', + '--jobs', + action='store', + type=int, + help="Explicitly set number of make jobs. Default is #cpus.") - subparser.add_argument( - '-n', '--no-checksum', action='store_true', dest='no_checksum', - help="Do not check packages against checksum") + subparser.add_argument('-n', + '--no-checksum', + action='store_true', + dest='no_checksum', + help="Do not check packages against checksum") - subparser.add_argument( - '-o', '--output', action='store', help="test output goes in this file") + subparser.add_argument('-o', '--output', action='store', help="test output goes in this file") - subparser.add_argument( - 'package', nargs=argparse.REMAINDER, help="spec of package to install") + subparser.add_argument('package', nargs=argparse.REMAINDER, help="spec of package to install") class JunitResultFormat(object): @@ -102,8 +105,7 @@ class BuildId(object): if not isinstance(other, BuildId): return False - return ((self.name, self.version, self.hashId) == - (other.name, other.version, other.hashId)) + return ((self.name, self.version, self.hashId) == (other.name, other.version, other.hashId)) def fetch_log(path): @@ -114,14 +116,13 @@ def fetch_log(path): def failed_dependencies(spec): - return set(childSpec for childSpec in spec.dependencies.itervalues() if not - spack.repo.get(childSpec).installed) + return set(childSpec for childSpec in spec.dependencies.itervalues() if not spack.repo.get(childSpec).installed) -def create_test_output(topSpec, newInstalls, output, getLogFunc=fetch_log): +def create_test_output(top_spec, newInstalls, output, getLogFunc=fetch_log): # Post-order traversal is not strictly required but it makes sense to output # tests for dependencies first. - for spec in topSpec.traverse(order='post'): + for spec in top_spec.traverse(order='post'): if spec not in newInstalls: continue @@ -131,20 +132,17 @@ def create_test_output(topSpec, newInstalls, output, getLogFunc=fetch_log): result = TestResult.SKIPPED dep = iter(failedDeps).next() depBID = BuildId(dep) - errOutput = "Skipped due to failed dependency: {0}".format( - depBID.stringId()) + errOutput = "Skipped due to failed dependency: {0}".format(depBID.stringId()) elif (not package.installed) and (not package.stage.source_path): result = TestResult.FAILED errOutput = "Failure to fetch package resources." elif not package.installed: result = TestResult.FAILED lines = getLogFunc(package.build_log_path) - errMessages = list(line for line in lines if - re.search('error:', line, re.IGNORECASE)) + errMessages = list(line for line in lines if re.search('error:', line, re.IGNORECASE)) errOutput = errMessages if errMessages else lines[-10:] - errOutput = '\n'.join(itertools.chain( - [spec.to_yaml(), "Errors:"], errOutput, - ["Build Log:", package.build_log_path])) + errOutput = '\n'.join(itertools.chain([spec.to_yaml(), "Errors:"], errOutput, ["Build Log:", + package.build_log_path])) else: result = TestResult.PASSED errOutput = None @@ -153,7 +151,16 @@ def create_test_output(topSpec, newInstalls, output, getLogFunc=fetch_log): output.add_test(bId, result, errOutput) +def get_top_spec_or_die(args): + specs = spack.cmd.parse_specs(args.package, concretize=True) + if len(specs) > 1: + tty.die("Only 1 top-level package can be specified") + top_spec = iter(specs).next() + return top_spec + + def test_install(parser, args): + # Check the input if not args.package: tty.die("install requires a package argument") @@ -162,21 +169,13 @@ def test_install(parser, args): tty.die("The -j option must be a positive integer!") if args.no_checksum: - spack.do_checksum = False # TODO: remove this global. + spack.do_checksum = False # TODO: remove this global. - specs = spack.cmd.parse_specs(args.package, concretize=True) - if len(specs) > 1: - tty.die("Only 1 top-level package can be specified") - topSpec = iter(specs).next() - - newInstalls = set() - for spec in topSpec.traverse(): - package = spack.repo.get(spec) - if not package.installed: - newInstalls.add(spec) + # Get the one and only top spec + top_spec = get_top_spec_or_die(args) if not args.output: - bId = BuildId(topSpec) + bId = BuildId(top_spec) outputDir = join_path(os.getcwd(), "test-output") if not os.path.exists(outputDir): os.mkdir(outputDir) @@ -184,20 +183,27 @@ def test_install(parser, args): else: outputFpath = args.output - for spec in topSpec.traverse(order='post'): + new_installs = set() + for spec in top_spec.traverse(order='post'): # Calling do_install for the top-level package would be sufficient but # this attempts to keep going if any package fails (other packages which # are not dependents may succeed) package = spack.repo.get(spec) + + if not package.installed: + new_installs.add(spec) + + duration = 0.0 if (not failed_dependencies(spec)) and (not package.installed): try: - package.do_install( - keep_prefix=False, - keep_stage=True, - ignore_deps=False, - make_jobs=args.jobs, - verbose=True, - fake=False) + start_time = time.time() + package.do_install(keep_prefix=False, + keep_stage=True, + ignore_deps=False, + make_jobs=args.jobs, + verbose=True, + fake=False) + duration = time.time() - start_time except InstallError: pass except FetchError: @@ -205,7 +211,13 @@ def test_install(parser, args): jrf = JunitResultFormat() handled = {} - create_test_output(topSpec, newInstalls, jrf) + create_test_output(top_spec, new_installs, jrf) with open(outputFpath, 'wb') as F: - jrf.write_to(F) + jrf.write_to(F) + + # with JunitTestSuite(filename) as test_suite: + # for spec in top_spec.traverse(order='post'): + # test_case = install_test(spec) + # test_suite.append( test_case ) + # -- cgit v1.2.3-70-g09d2 From 603467785b5ea00a1dac43e64e1565a6bdc732ef Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 26 Apr 2016 13:00:54 -0400 Subject: Compiler find docs (#831) * docs: mention `spack compiler find` * docs: fix some weird wording. --- lib/spack/docs/basic_usage.rst | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/spack/docs/basic_usage.rst b/lib/spack/docs/basic_usage.rst index 0e603813e1..29791d98c4 100644 --- a/lib/spack/docs/basic_usage.rst +++ b/lib/spack/docs/basic_usage.rst @@ -372,25 +372,32 @@ how this is done is in :ref:`sec-specs`. ``spack compiler add`` ~~~~~~~~~~~~~~~~~~~~~~~ +An alias for ``spack compiler find``. + +.. _spack-compiler-find: + +``spack compiler find`` +~~~~~~~~~~~~~~~~~~~~~~~ + If you do not see a compiler in this list, but you want to use it with -Spack, you can simply run ``spack compiler add`` with the path to +Spack, you can simply run ``spack compiler find`` with the path to where the compiler is installed. For example:: - $ spack compiler add /usr/local/tools/ic-13.0.079 + $ spack compiler find /usr/local/tools/ic-13.0.079 ==> Added 1 new compiler to /Users/gamblin2/.spack/compilers.yaml intel@13.0.079 -Or you can run ``spack compiler add`` with no arguments to force +Or you can run ``spack compiler find`` with no arguments to force auto-detection. This is useful if you do not know where compilers are installed, but you know that new compilers have been added to your ``PATH``. For example, using dotkit, you might do this:: $ module load gcc-4.9.0 - $ spack compiler add + $ spack compiler find ==> Added 1 new compiler to /Users/gamblin2/.spack/compilers.yaml gcc@4.9.0 -This loads the environment module for gcc-4.9.0 to get it into the +This loads the environment module for gcc-4.9.0 to add it to ``PATH``, and then it adds the compiler to Spack. .. _spack-compiler-info: -- cgit v1.2.3-70-g09d2 From b7c064142e6e4beb960aa979815471c3889ec925 Mon Sep 17 00:00:00 2001 From: Benedikt Hegner Date: Wed, 27 Apr 2016 01:23:53 +0200 Subject: preserve lookup order in PATH when invoking 'spack compiler add' --- lib/spack/spack/compiler.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index d38c0b00b1..2f89ec6144 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -202,6 +202,10 @@ class Compiler(object): return None successful = [key for key in parmap(check, checks) if key is not None] + # The 'successful' list is ordered like the input paths. + # Reverse it here so that the dict creation (last insert wins) + # does not spoil the intented precedence. + successful.reverse() return dict(((v, p, s), path) for v, p, s, path in successful) @classmethod -- cgit v1.2.3-70-g09d2 From 12dbd65f4cbf3218155b86b5f9b1281198a2453d Mon Sep 17 00:00:00 2001 From: alalazo Date: Wed, 27 Apr 2016 13:56:32 +0200 Subject: test-install : first draft that works --- lib/spack/spack/cmd/test-install.py | 249 ++++++++++++++++++------------------ 1 file changed, 125 insertions(+), 124 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/test-install.py b/lib/spack/spack/cmd/test-install.py index 733b58f252..c214cd3f66 100644 --- a/lib/spack/spack/cmd/test-install.py +++ b/lib/spack/spack/cmd/test-install.py @@ -24,10 +24,9 @@ ############################################################################## import argparse import codecs -import itertools import os -import re import time +import xml.dom.minidom import xml.etree.ElementTree as ET import llnl.util.tty as tty @@ -58,54 +57,72 @@ def setup_parser(subparser): subparser.add_argument('package', nargs=argparse.REMAINDER, help="spec of package to install") -class JunitResultFormat(object): - def __init__(self): - self.root = ET.Element('testsuite') - self.tests = [] - - def add_test(self, buildId, testResult, buildInfo=None): - self.tests.append((buildId, testResult, buildInfo)) - - def write_to(self, stream): - self.root.set('tests', '{0}'.format(len(self.tests))) - for buildId, testResult, buildInfo in self.tests: - testcase = ET.SubElement(self.root, 'testcase') - testcase.set('classname', buildId.name) - testcase.set('name', buildId.stringId()) - if testResult == TestResult.FAILED: - failure = ET.SubElement(testcase, 'failure') - failure.set('type', "Build Error") - failure.text = buildInfo - elif testResult == TestResult.SKIPPED: - skipped = ET.SubElement(testcase, 'skipped') - skipped.set('type', "Skipped Build") - skipped.text = buildInfo - ET.ElementTree(self.root).write(stream) - - class TestResult(object): PASSED = 0 FAILED = 1 SKIPPED = 2 + ERRORED = 3 -class BuildId(object): - def __init__(self, spec): - self.name = spec.name - self.version = spec.version - self.hashId = spec.dag_hash() - - def stringId(self): - return "-".join(str(x) for x in (self.name, self.version, self.hashId)) - - def __hash__(self): - return hash((self.name, self.version, self.hashId)) - - def __eq__(self, other): - if not isinstance(other, BuildId): - return False +class TestSuite(object): + def __init__(self, filename): + self.filename = filename + self.root = ET.Element('testsuite') + self.tests = [] - return ((self.name, self.version, self.hashId) == (other.name, other.version, other.hashId)) + def __enter__(self): + return self + + def append(self, item): + if not isinstance(item, TestCase): + raise TypeError('only TestCase instances may be appended to a TestSuite instance') + self.tests.append(item) # Append the item to the list of tests + + def __exit__(self, exc_type, exc_val, exc_tb): + # Prepare the header for the entire test suite + number_of_errors = sum(x.result_type == TestResult.ERRORED for x in self.tests) + self.root.set('errors', str(number_of_errors)) + number_of_failures = sum(x.result_type == TestResult.FAILED for x in self.tests) + self.root.set('failures', str(number_of_failures)) + self.root.set('tests', str(len(self.tests))) + + for item in self.tests: + self.root.append(item.element) + + with open(self.filename, 'wb') as file: + xml_string = ET.tostring(self.root) + xml_string = xml.dom.minidom.parseString(xml_string).toprettyxml() + file.write(xml_string) + + +class TestCase(object): + + results = { + TestResult.PASSED: None, + TestResult.SKIPPED: 'skipped', + TestResult.FAILED: 'failure', + TestResult.ERRORED: 'error', + } + + def __init__(self, classname, name, time=None): + self.element = ET.Element('testcase') + self.element.set('classname', str(classname)) + self.element.set('name', str(name)) + if time is not None: + self.element.set('time', str(time)) + self.result_type = None + + def set_result(self, result_type, message=None, error_type=None, text=None): + self.result_type = result_type + result = TestCase.results[self.result_type] + if result is not None: + subelement = ET.SubElement(self.element, result) + if error_type is not None: + subelement.set('type', error_type) + if message is not None: + subelement.set('message', str(message)) + if text is not None: + subelement.text = text def fetch_log(path): @@ -116,39 +133,7 @@ def fetch_log(path): def failed_dependencies(spec): - return set(childSpec for childSpec in spec.dependencies.itervalues() if not spack.repo.get(childSpec).installed) - - -def create_test_output(top_spec, newInstalls, output, getLogFunc=fetch_log): - # Post-order traversal is not strictly required but it makes sense to output - # tests for dependencies first. - for spec in top_spec.traverse(order='post'): - if spec not in newInstalls: - continue - - failedDeps = failed_dependencies(spec) - package = spack.repo.get(spec) - if failedDeps: - result = TestResult.SKIPPED - dep = iter(failedDeps).next() - depBID = BuildId(dep) - errOutput = "Skipped due to failed dependency: {0}".format(depBID.stringId()) - elif (not package.installed) and (not package.stage.source_path): - result = TestResult.FAILED - errOutput = "Failure to fetch package resources." - elif not package.installed: - result = TestResult.FAILED - lines = getLogFunc(package.build_log_path) - errMessages = list(line for line in lines if re.search('error:', line, re.IGNORECASE)) - errOutput = errMessages if errMessages else lines[-10:] - errOutput = '\n'.join(itertools.chain([spec.to_yaml(), "Errors:"], errOutput, ["Build Log:", - package.build_log_path])) - else: - result = TestResult.PASSED - errOutput = None - - bId = BuildId(spec) - output.add_test(bId, result, errOutput) + return set(item for item in spec.dependencies.itervalues() if not spack.repo.get(item).installed) def get_top_spec_or_die(args): @@ -159,6 +144,62 @@ def get_top_spec_or_die(args): return top_spec +def install_single_spec(spec, number_of_jobs): + package = spack.repo.get(spec) + + # If it is already installed, skip the test + if spack.repo.get(spec).installed: + testcase = TestCase(package.name, package.spec.short_spec, time=0.0) + testcase.set_result(TestResult.SKIPPED, message='Skipped [already installed]', error_type='already_installed') + return testcase + + # If it relies on dependencies that did not install, skip + if failed_dependencies(spec): + testcase = TestCase(package.name, package.spec.short_spec, time=0.0) + testcase.set_result(TestResult.SKIPPED, message='Skipped [failed dependencies]', error_type='dep_failed') + return testcase + + # Otherwise try to install the spec + try: + start_time = time.time() + package.do_install(keep_prefix=False, + keep_stage=True, + ignore_deps=False, + make_jobs=number_of_jobs, + verbose=True, + fake=False) + duration = time.time() - start_time + testcase = TestCase(package.name, package.spec.short_spec, duration) + except InstallError: + # An InstallError is considered a failure (the recipe didn't work correctly) + duration = time.time() - start_time + # Try to get the log + lines = fetch_log(package.build_log_path) + text = '\n'.join(lines) + testcase = TestCase(package.name, package.spec.short_spec, duration) + testcase.set_result(TestResult.FAILED, message='Installation failure', text=text) + + except FetchError: + # A FetchError is considered an error (we didn't even start building) + duration = time.time() - start_time + testcase = TestCase(package.name, package.spec.short_spec, duration) + testcase.set_result(TestResult.ERRORED, message='Unable to fetch package') + + return testcase + + +def get_filename(args, top_spec): + if not args.output: + fname = 'test-{x.name}-{x.version}-{hash}.xml'.format(x=top_spec, hash=top_spec.dag_hash()) + output_directory = join_path(os.getcwd(), 'test-output') + if not os.path.exists(output_directory): + os.mkdir(output_directory) + output_filename = join_path(output_directory, fname) + else: + output_filename = args.output + return output_filename + + def test_install(parser, args): # Check the input if not args.package: @@ -173,51 +214,11 @@ def test_install(parser, args): # Get the one and only top spec top_spec = get_top_spec_or_die(args) - - if not args.output: - bId = BuildId(top_spec) - outputDir = join_path(os.getcwd(), "test-output") - if not os.path.exists(outputDir): - os.mkdir(outputDir) - outputFpath = join_path(outputDir, "test-{0}.xml".format(bId.stringId())) - else: - outputFpath = args.output - - new_installs = set() - for spec in top_spec.traverse(order='post'): - # Calling do_install for the top-level package would be sufficient but - # this attempts to keep going if any package fails (other packages which - # are not dependents may succeed) - package = spack.repo.get(spec) - - if not package.installed: - new_installs.add(spec) - - duration = 0.0 - if (not failed_dependencies(spec)) and (not package.installed): - try: - start_time = time.time() - package.do_install(keep_prefix=False, - keep_stage=True, - ignore_deps=False, - make_jobs=args.jobs, - verbose=True, - fake=False) - duration = time.time() - start_time - except InstallError: - pass - except FetchError: - pass - - jrf = JunitResultFormat() - handled = {} - create_test_output(top_spec, new_installs, jrf) - - with open(outputFpath, 'wb') as F: - jrf.write_to(F) - - # with JunitTestSuite(filename) as test_suite: - # for spec in top_spec.traverse(order='post'): - # test_case = install_test(spec) - # test_suite.append( test_case ) - # + # Get the filename of the test + output_filename = get_filename(args, top_spec) + # TEST SUITE + with TestSuite(output_filename) as test_suite: + # Traverse in post order : each spec is a test case + for spec in top_spec.traverse(order='post'): + test_case = install_single_spec(spec, args.jobs) + test_suite.append(test_case) -- cgit v1.2.3-70-g09d2 From 42fab1591d9fc0b140d33d68ef27d3fe401178e4 Mon Sep 17 00:00:00 2001 From: alalazo Date: Wed, 27 Apr 2016 17:19:03 +0200 Subject: test-install : fixed unit tests --- lib/spack/spack/cmd/test-install.py | 3 +- lib/spack/spack/test/__init__.py | 3 +- lib/spack/spack/test/cmd/test_install.py | 191 +++++++++++++++++++++++++++++++ lib/spack/spack/test/unit_install.py | 126 -------------------- 4 files changed, 195 insertions(+), 128 deletions(-) create mode 100644 lib/spack/spack/test/cmd/test_install.py delete mode 100644 lib/spack/spack/test/unit_install.py (limited to 'lib') diff --git a/lib/spack/spack/cmd/test-install.py b/lib/spack/spack/cmd/test-install.py index c214cd3f66..e323969634 100644 --- a/lib/spack/spack/cmd/test-install.py +++ b/lib/spack/spack/cmd/test-install.py @@ -115,7 +115,7 @@ class TestCase(object): def set_result(self, result_type, message=None, error_type=None, text=None): self.result_type = result_type result = TestCase.results[self.result_type] - if result is not None: + if result is not None or result is not TestResult.PASSED: subelement = ET.SubElement(self.element, result) if error_type is not None: subelement.set('type', error_type) @@ -170,6 +170,7 @@ def install_single_spec(spec, number_of_jobs): fake=False) duration = time.time() - start_time testcase = TestCase(package.name, package.spec.short_spec, duration) + testcase.set_result(TestResult.PASSED) except InstallError: # An InstallError is considered a failure (the recipe didn't work correctly) duration = time.time() - start_time diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py index 175a49428c..bea41a4adf 100644 --- a/lib/spack/spack/test/__init__.py +++ b/lib/spack/spack/test/__init__.py @@ -68,7 +68,8 @@ test_names = ['versions', 'yaml', 'sbang', 'environment', - 'cmd.uninstall'] + 'cmd.uninstall', + 'cmd.test_install'] def list_tests(): diff --git a/lib/spack/spack/test/cmd/test_install.py b/lib/spack/spack/test/cmd/test_install.py new file mode 100644 index 0000000000..1860622ad6 --- /dev/null +++ b/lib/spack/spack/test/cmd/test_install.py @@ -0,0 +1,191 @@ +############################################################################## +# Copyright (c) 2013, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License (as published by +# the Free Software Foundation) version 2.1 dated February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +import collections +from contextlib import contextmanager + +import StringIO + +FILE_REGISTRY = collections.defaultdict(StringIO.StringIO) + +# Monkey-patch open to write module files to a StringIO instance +@contextmanager +def mock_open(filename, mode): + if not mode == 'wb': + raise RuntimeError('test.test_install : unexpected opening mode for monkey-patched open') + + FILE_REGISTRY[filename] = StringIO.StringIO() + + try: + yield FILE_REGISTRY[filename] + finally: + handle = FILE_REGISTRY[filename] + FILE_REGISTRY[filename] = handle.getvalue() + handle.close() + +import os +import itertools +import unittest + +import spack +import spack.cmd + + +# The use of __import__ is necessary to maintain a name with hyphen (which cannot be an identifier in python) +test_install = __import__("spack.cmd.test-install", fromlist=['test_install']) + + +class MockSpec(object): + def __init__(self, name, version, hashStr=None): + self.dependencies = {} + self.name = name + self.version = version + self.hash = hashStr if hashStr else hash((name, version)) + + def traverse(self, order=None): + for _, spec in self.dependencies.items(): + yield spec + yield self + #allDeps = itertools.chain.from_iterable(i.traverse() for i in self.dependencies.itervalues()) + #return set(itertools.chain([self], allDeps)) + + def dag_hash(self): + return self.hash + + @property + def short_spec(self): + return '-'.join([self.name, str(self.version), str(self.hash)]) + + +class MockPackage(object): + def __init__(self, spec, buildLogPath): + self.name = spec.name + self.spec = spec + self.installed = False + self.build_log_path = buildLogPath + + def do_install(self, *args, **kwargs): + self.installed = True + + +class MockPackageDb(object): + def __init__(self, init=None): + self.specToPkg = {} + if init: + self.specToPkg.update(init) + + def get(self, spec): + return self.specToPkg[spec] + + +def mock_fetch_log(path): + return [] + +specX = MockSpec('X', "1.2.0") +specY = MockSpec('Y', "2.3.8") +specX.dependencies['Y'] = specY +pkgX = MockPackage(specX, 'logX') +pkgY = MockPackage(specY, 'logY') + + +class MockArgs(object): + def __init__(self, package): + self.package = package + self.jobs = None + self.no_checksum = False + self.output = None + + +class TestInstallTest(unittest.TestCase): + """ + Tests test-install where X->Y + """ + + def setUp(self): + super(TestInstallTest, self).setUp() + + # Monkey patch parse specs + def monkey_parse_specs(x, concretize): + if x == 'X': + return [specX] + elif x == 'Y': + return [specY] + return [] + + self.parse_specs = spack.cmd.parse_specs + spack.cmd.parse_specs = monkey_parse_specs + + # Monkey patch os.mkdirp + self.os_mkdir = os.mkdir + os.mkdir = lambda x: True + + # Monkey patch open + test_install.open = mock_open + + # Clean FILE_REGISTRY + FILE_REGISTRY = collections.defaultdict(StringIO.StringIO) + + pkgX.installed = False + pkgY.installed = False + + # Monkey patch pkgDb + self.saved_db = spack.repo + pkgDb = MockPackageDb({specX: pkgX, specY: pkgY}) + spack.repo = pkgDb + + def tearDown(self): + # Remove the monkey patched test_install.open + test_install.open = open + + # Remove the monkey patched os.mkdir + os.mkdir = self.os_mkdir + del self.os_mkdir + + # Remove the monkey patched parse_specs + spack.cmd.parse_specs = self.parse_specs + del self.parse_specs + super(TestInstallTest, self).tearDown() + + spack.repo = self.saved_db + + def test_installing_both(self): + test_install.test_install(None, MockArgs('X') ) + self.assertEqual(len(FILE_REGISTRY), 1) + for _, content in FILE_REGISTRY.items(): + self.assertTrue('tests="2"' in content) + self.assertTrue('failures="0"' in content) + self.assertTrue('errors="0"' in content) + + def test_dependency_already_installed(self): + pkgX.installed = True + pkgY.installed = True + test_install.test_install(None, MockArgs('X')) + self.assertEqual(len(FILE_REGISTRY), 1) + for _, content in FILE_REGISTRY.items(): + self.assertTrue('tests="2"' in content) + self.assertTrue('failures="0"' in content) + self.assertTrue('errors="0"' in content) + self.assertEqual(sum('skipped' in line for line in content.split('\n')), 2) + + #TODO: add test(s) where Y fails to install \ No newline at end of file diff --git a/lib/spack/spack/test/unit_install.py b/lib/spack/spack/test/unit_install.py deleted file mode 100644 index 18615b7efe..0000000000 --- a/lib/spack/spack/test/unit_install.py +++ /dev/null @@ -1,126 +0,0 @@ -############################################################################## -# Copyright (c) 2013, Lawrence Livermore National Security, LLC. -# Produced at the Lawrence Livermore National Laboratory. -# -# This file is part of Spack. -# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. -# LLNL-CODE-647188 -# -# For details, see https://github.com/llnl/spack -# Please also see the LICENSE file for our notice and the LGPL. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License (as published by -# the Free Software Foundation) version 2.1 dated February 1999. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and -# conditions of the GNU General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################## -import itertools -import unittest - -import spack - -test_install = __import__("spack.cmd.test-install", - fromlist=["BuildId", "create_test_output", "TestResult"]) - -class MockOutput(object): - def __init__(self): - self.results = {} - - def add_test(self, buildId, passed=True, buildInfo=None): - self.results[buildId] = passed - - def write_to(self, stream): - pass - -class MockSpec(object): - def __init__(self, name, version, hashStr=None): - self.dependencies = {} - self.name = name - self.version = version - self.hash = hashStr if hashStr else hash((name, version)) - - def traverse(self, order=None): - allDeps = itertools.chain.from_iterable(i.traverse() for i in - self.dependencies.itervalues()) - return set(itertools.chain([self], allDeps)) - - def dag_hash(self): - return self.hash - - def to_yaml(self): - return "<<>>".format(test_install.BuildId(self).stringId()) - -class MockPackage(object): - def __init__(self, buildLogPath): - self.installed = False - self.build_log_path = buildLogPath - -specX = MockSpec("X", "1.2.0") -specY = MockSpec("Y", "2.3.8") -specX.dependencies['Y'] = specY -pkgX = MockPackage('logX') -pkgY = MockPackage('logY') -bIdX = test_install.BuildId(specX) -bIdY = test_install.BuildId(specY) - -class UnitInstallTest(unittest.TestCase): - """Tests test-install where X->Y""" - - def setUp(self): - super(UnitInstallTest, self).setUp() - - pkgX.installed = False - pkgY.installed = False - - self.saved_db = spack.repo - pkgDb = MockPackageDb({specX:pkgX, specY:pkgY}) - spack.repo = pkgDb - - - def tearDown(self): - super(UnitInstallTest, self).tearDown() - - spack.repo = self.saved_db - - def test_installing_both(self): - mo = MockOutput() - - pkgX.installed = True - pkgY.installed = True - test_install.create_test_output(specX, [specX, specY], mo, getLogFunc=mock_fetch_log) - - self.assertEqual(mo.results, - {bIdX:test_install.TestResult.PASSED, - bIdY:test_install.TestResult.PASSED}) - - - def test_dependency_already_installed(self): - mo = MockOutput() - - pkgX.installed = True - pkgY.installed = True - test_install.create_test_output(specX, [specX], mo, getLogFunc=mock_fetch_log) - self.assertEqual(mo.results, {bIdX:test_install.TestResult.PASSED}) - - #TODO: add test(s) where Y fails to install - - -class MockPackageDb(object): - def __init__(self, init=None): - self.specToPkg = {} - if init: - self.specToPkg.update(init) - - def get(self, spec): - return self.specToPkg[spec] - -def mock_fetch_log(path): - return [] -- cgit v1.2.3-70-g09d2 From ec5bb88820e42b2cf4c839cf134e18a167a52255 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Wed, 27 Apr 2016 18:06:41 +0200 Subject: test-install : unit tests (hopefully) fixed for real --- lib/spack/spack/test/__init__.py | 1 - 1 file changed, 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py index bea41a4adf..3c5edde66b 100644 --- a/lib/spack/spack/test/__init__.py +++ b/lib/spack/spack/test/__init__.py @@ -61,7 +61,6 @@ test_names = ['versions', 'optional_deps', 'make_executable', 'configure_guess', - 'unit_install', 'lock', 'database', 'namespace_trie', -- cgit v1.2.3-70-g09d2 From 4846ab70d8c805c6533d90b9345295c4160b4e35 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Wed, 27 Apr 2016 18:21:36 +0200 Subject: test-install : python 2.6 compatibility --- lib/spack/spack/test/cmd/test_install.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/test/cmd/test_install.py b/lib/spack/spack/test/cmd/test_install.py index 1860622ad6..2206c7bea1 100644 --- a/lib/spack/spack/test/cmd/test_install.py +++ b/lib/spack/spack/test/cmd/test_install.py @@ -117,6 +117,7 @@ class MockArgs(object): self.output = None +# TODO: add test(s) where Y fails to install class TestInstallTest(unittest.TestCase): """ Tests test-install where X->Y @@ -187,5 +188,3 @@ class TestInstallTest(unittest.TestCase): self.assertTrue('failures="0"' in content) self.assertTrue('errors="0"' in content) self.assertEqual(sum('skipped' in line for line in content.split('\n')), 2) - - #TODO: add test(s) where Y fails to install \ No newline at end of file -- cgit v1.2.3-70-g09d2 From b1ba869b37803ba9cda28ab64b7f0052e8eda11d Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Wed, 27 Apr 2016 19:28:13 +0200 Subject: test-install : fixed error in logic exposed by tests --- lib/spack/spack/cmd/test-install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/cmd/test-install.py b/lib/spack/spack/cmd/test-install.py index e323969634..3277e15548 100644 --- a/lib/spack/spack/cmd/test-install.py +++ b/lib/spack/spack/cmd/test-install.py @@ -115,7 +115,7 @@ class TestCase(object): def set_result(self, result_type, message=None, error_type=None, text=None): self.result_type = result_type result = TestCase.results[self.result_type] - if result is not None or result is not TestResult.PASSED: + if result is not None and result is not TestResult.PASSED: subelement = ET.SubElement(self.element, result) if error_type is not None: subelement.set('type', error_type) -- cgit v1.2.3-70-g09d2 From b5ebd12fe2708997b63fea1a0f1cac43c3e8e847 Mon Sep 17 00:00:00 2001 From: Brett Viren Date: Wed, 27 Apr 2016 13:42:59 -0400 Subject: Add to sub dirs checked for pkg-config files. This lets me build against the pure-include package Eigen. --- lib/spack/spack/build_environment.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index eb72f2a6b4..cd9f647ddf 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -175,8 +175,8 @@ def set_build_environment_variables(pkg, env): # Add any pkgconfig directories to PKG_CONFIG_PATH pkg_config_dirs = [] for p in dep_prefixes: - for libdir in ('lib', 'lib64'): - pcdir = join_path(p, libdir, 'pkgconfig') + for maybe in ('lib', 'lib64', 'share'): + pcdir = join_path(p, maybe, 'pkgconfig') if os.path.isdir(pcdir): pkg_config_dirs.append(pcdir) env.set_path('PKG_CONFIG_PATH', pkg_config_dirs) -- cgit v1.2.3-70-g09d2 From e53571d2f00d2640005a10d69edbad838cb38fef Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 27 Apr 2016 14:46:57 -0400 Subject: fetch_strategy: download to temporary files This supports graceful recovery if spack is killed via a signal (e.g., SIGINT) while downloading a file. Fixes #287. --- lib/spack/spack/fetch_strategy.py | 24 ++++++++++++++++++++++-- lib/spack/spack/stage.py | 12 ++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/fetch_strategy.py b/lib/spack/spack/fetch_strategy.py index 4ea87bea7e..ce2c4e30c7 100644 --- a/lib/spack/spack/fetch_strategy.py +++ b/lib/spack/spack/fetch_strategy.py @@ -157,12 +157,26 @@ class URLFetchStrategy(FetchStrategy): tty.msg("Already downloaded %s" % self.archive_file) return + possible_files = self.stage.expected_archive_files + save_file = None + partial_file = None + if possible_files: + save_file = self.stage.expected_archive_files[0] + partial_file = self.stage.expected_archive_files[0] + '.part' + tty.msg("Trying to fetch from %s" % self.url) - curl_args = ['-O', # save file to disk + if partial_file: + save_args = ['-C', '-', # continue partial downloads + '-o', partial_file] # use a .part file + else: + save_args = ['-O'] + + curl_args = save_args + [ '-f', # fail on >400 errors '-D', '-', # print out HTML headers - '-L', self.url, ] + '-L', # resolve 3xx redirects + self.url, ] if sys.stdout.isatty(): curl_args.append('-#') # status bar when using a tty @@ -178,6 +192,9 @@ class URLFetchStrategy(FetchStrategy): if self.archive_file: os.remove(self.archive_file) + if partial_file and os.path.exists(partial_file): + os.remove(partial_file) + if spack.curl.returncode == 22: # This is a 404. Curl will print the error. raise FailedDownloadError( @@ -209,6 +226,9 @@ class URLFetchStrategy(FetchStrategy): "'spack clean ' to remove the bad archive, then fix", "your internet gateway issue and install again.") + if save_file: + os.rename(partial_file, save_file) + if not self.archive_file: raise FailedDownloadError(self.url) diff --git a/lib/spack/spack/stage.py b/lib/spack/spack/stage.py index d711752c20..84c47ee660 100644 --- a/lib/spack/spack/stage.py +++ b/lib/spack/spack/stage.py @@ -210,6 +210,18 @@ class Stage(object): return False + @property + def expected_archive_files(self): + """Possible archive file paths.""" + paths = [] + if isinstance(self.fetcher, fs.URLFetchStrategy): + paths.append(os.path.join(self.path, os.path.basename(self.fetcher.url))) + + if self.mirror_path: + paths.append(os.path.join(self.path, os.path.basename(self.mirror_path))) + + return paths + @property def archive_file(self): """Path to the source archive within this stage directory.""" -- cgit v1.2.3-70-g09d2 From c3317819cb89abdcd9fe1cb9431436c4e4ef8702 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Wed, 4 May 2016 10:37:52 +0200 Subject: mpi: add self.spec.[mpicc|mpicxx|mpifc|mpif77] to avoid hardcoding MPI wrappers names --- lib/spack/docs/packaging_guide.rst | 17 +++++++++++++++++ var/spack/repos/builtin/packages/mpich/package.py | 5 +++++ var/spack/repos/builtin/packages/openmpi/package.py | 5 +++++ 3 files changed, 27 insertions(+) (limited to 'lib') diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index 519c0da232..34d11308f5 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -1831,6 +1831,23 @@ successfully find ``libdwarf.h`` and ``libdwarf.so``, without the packager having to provide ``--with-libdwarf=/path/to/libdwarf`` on the command line. +Message Parsing Interface (MPI) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is common for high performance computing software/packages to use ``MPI``. +As a result of conretization, a given package can be built using different +implementations of MPI such as ``Openmpi``, ``MPICH`` or ``IntelMPI``. +In some scenarios to configure a package one have to provide it with appropriate MPI +compiler wrappers such as ``mpicc``, ``mpic++``. +However different implementations of ``MPI`` may have different names for those +wrappers. In order to make package's ``install()`` method indifferent to the +choice ``MPI`` implementation, each package which implements ``MPI`` sets up +``self.spec.mpicc``, ``self.spec.mpicxx``, ``self.spec.mpifc`` and ``self.spec.mpif77`` +to point to ``C``, ``C++``, ``Fortran 90`` and ``Fortran 77`` ``MPI`` wrappers. +Package developers are advised to use these variables, for example ``self.spec['mpi'].mpicc`` +instead of hard-coding ``join_path(self.spec['mpi'].prefix.bin, 'mpicc')`` for +the reasons outlined above. + + Forking ``install()`` ~~~~~~~~~~~~~~~~~~~~~ diff --git a/var/spack/repos/builtin/packages/mpich/package.py b/var/spack/repos/builtin/packages/mpich/package.py index b317ec6651..aaa6386df7 100644 --- a/var/spack/repos/builtin/packages/mpich/package.py +++ b/var/spack/repos/builtin/packages/mpich/package.py @@ -54,6 +54,11 @@ class Mpich(Package): spack_env.set('MPICH_F90', spack_fc) spack_env.set('MPICH_FC', spack_fc) + self.spec.mpicc = join_path(self.prefix.bin, 'mpicc') + self.spec.mpicxx = join_path(self.prefix.bin, 'mpic++') + self.spec.mpifc = join_path(self.prefix.bin, 'mpif90') + self.spec.mpif77 = join_path(self.prefix.bin, 'mpif77') + def setup_dependent_package(self, module, dep_spec): """For dependencies, make mpicc's use spack wrapper.""" # FIXME : is this necessary ? Shouldn't this be part of a contract with MPI providers? diff --git a/var/spack/repos/builtin/packages/openmpi/package.py b/var/spack/repos/builtin/packages/openmpi/package.py index 3cb9b0be21..89a21e869c 100644 --- a/var/spack/repos/builtin/packages/openmpi/package.py +++ b/var/spack/repos/builtin/packages/openmpi/package.py @@ -45,6 +45,11 @@ class Openmpi(Package): spack_env.set('OMPI_FC', spack_fc) spack_env.set('OMPI_F77', spack_f77) + self.spec.mpicc = join_path(self.prefix.bin, 'mpicc') + self.spec.mpicxx = join_path(self.prefix.bin, 'mpic++') + self.spec.mpifc = join_path(self.prefix.bin, 'mpif90') + self.spec.mpif77 = join_path(self.prefix.bin, 'mpif77') + def install(self, spec, prefix): config_args = ["--prefix=%s" % prefix, -- cgit v1.2.3-70-g09d2 From 2cdfe14e5a8cbdefd3533d3bb0b0ac09fa9e4fa6 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 10:47:39 +0200 Subject: compilers: make sure cxx11_flag() is defined for all compilers --- lib/spack/spack/compilers/clang.py | 11 +++++++++++ lib/spack/spack/compilers/nag.py | 6 ++++++ lib/spack/spack/compilers/pgi.py | 7 ++++++- 3 files changed, 23 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index e406d86a24..8a60ebcaed 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -47,6 +47,17 @@ class Clang(Compiler): 'f77' : 'f77', 'fc' : 'f90' } + @property + def cxx11_flag(self): + if ver.endswith('-apple'): + # FIXME: figure out from which version Apple's clang supports c++11 + return "-std=c++11" + else: + if self.version < ver('3.3'): + tty.die("Only Clang 3.3 and above support c++11.") + else: + return "-std=c++11" + @classmethod def default_version(self, comp): """The '--version' option works for clang compilers. diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py index 527a05a090..1df6b1c591 100644 --- a/lib/spack/spack/compilers/nag.py +++ b/lib/spack/spack/compilers/nag.py @@ -20,6 +20,12 @@ class Nag(Compiler): 'f77' : 'nag/nagfor', 'fc' : 'nag/nagfor' } + @property + def cxx11_flag(self): + tty.die("cxx11_flag() is not implemented for nag. Consider creating a pull-request.") + return "-std=c++11" + + @classmethod def default_version(self, comp): """The '-V' option works for nag compilers. diff --git a/lib/spack/spack/compilers/pgi.py b/lib/spack/spack/compilers/pgi.py index c6a1078bd9..ebf644404b 100644 --- a/lib/spack/spack/compilers/pgi.py +++ b/lib/spack/spack/compilers/pgi.py @@ -43,6 +43,12 @@ class Pgi(Compiler): 'f77' : 'pgi/pgfortran', 'fc' : 'pgi/pgfortran' } + @property + def cxx11_flag(self): + tty.die("cxx11_flag() is not implemented for pgi. Consider creating a pull-request.") + return "-std=c++11" + + @classmethod def default_version(cls, comp): """The '-V' option works for all the PGI compilers. @@ -54,4 +60,3 @@ class Pgi(Compiler): """ return get_compiler_version( comp, '-V', r'pg[^ ]* ([^ ]+) \d\d\d?-bit target') - -- cgit v1.2.3-70-g09d2 From 9776dc0433fee264ae1fd2cbff9b16fd499fdb1a Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 10:49:04 +0200 Subject: compilers: add openmp_flag() method --- lib/spack/spack/compilers/clang.py | 8 ++++++++ lib/spack/spack/compilers/gcc.py | 4 ++++ lib/spack/spack/compilers/intel.py | 6 ++++-- lib/spack/spack/compilers/nag.py | 4 ++++ lib/spack/spack/compilers/pgi.py | 4 ++++ lib/spack/spack/compilers/xl.py | 4 ++++ 6 files changed, 28 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index 8a60ebcaed..44de77af4f 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -47,6 +47,14 @@ class Clang(Compiler): 'f77' : 'f77', 'fc' : 'f90' } + @property + def openmp_flag(self): + ver = '%s' % self.version + if ver.endswith('-apple'): + tty.die("Clang from Apple does not support Openmp yet.") + else: + return "-fopenmp" + @property def cxx11_flag(self): if ver.endswith('-apple'): diff --git a/lib/spack/spack/compilers/gcc.py b/lib/spack/spack/compilers/gcc.py index 2e57e44856..91c498ac82 100644 --- a/lib/spack/spack/compilers/gcc.py +++ b/lib/spack/spack/compilers/gcc.py @@ -49,6 +49,10 @@ class Gcc(Compiler): 'f77' : 'gcc/gfortran', 'fc' : 'gcc/gfortran' } + @property + def openmp_flag(self): + return "-fopenmp" + @property def cxx11_flag(self): if self.version < ver('4.3'): diff --git a/lib/spack/spack/compilers/intel.py b/lib/spack/spack/compilers/intel.py index 69e9764790..f04a6aa899 100644 --- a/lib/spack/spack/compilers/intel.py +++ b/lib/spack/spack/compilers/intel.py @@ -43,6 +43,10 @@ class Intel(Compiler): 'f77' : 'intel/ifort', 'fc' : 'intel/ifort' } + @property + def openmp_flag(self): + return "-openmp" + @property def cxx11_flag(self): if self.version < ver('11.1'): @@ -68,5 +72,3 @@ class Intel(Compiler): """ return get_compiler_version( comp, '--version', r'\((?:IFORT|ICC)\) ([^ ]+)') - - diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py index 1df6b1c591..61486f22bd 100644 --- a/lib/spack/spack/compilers/nag.py +++ b/lib/spack/spack/compilers/nag.py @@ -20,6 +20,10 @@ class Nag(Compiler): 'f77' : 'nag/nagfor', 'fc' : 'nag/nagfor' } + @property + def openmp_flag(self): + return "-openmp" + @property def cxx11_flag(self): tty.die("cxx11_flag() is not implemented for nag. Consider creating a pull-request.") diff --git a/lib/spack/spack/compilers/pgi.py b/lib/spack/spack/compilers/pgi.py index ebf644404b..299b9a7016 100644 --- a/lib/spack/spack/compilers/pgi.py +++ b/lib/spack/spack/compilers/pgi.py @@ -43,6 +43,10 @@ class Pgi(Compiler): 'f77' : 'pgi/pgfortran', 'fc' : 'pgi/pgfortran' } + @property + def openmp_flag(self): + return "-mp" + @property def cxx11_flag(self): tty.die("cxx11_flag() is not implemented for pgi. Consider creating a pull-request.") diff --git a/lib/spack/spack/compilers/xl.py b/lib/spack/spack/compilers/xl.py index c1d55109a3..657309fe06 100644 --- a/lib/spack/spack/compilers/xl.py +++ b/lib/spack/spack/compilers/xl.py @@ -44,6 +44,10 @@ class Xl(Compiler): 'f77' : 'xl/xlf', 'fc' : 'xl/xlf90' } + @property + def openmp_flag(self): + return "-qsmp=omp" + @property def cxx11_flag(self): if self.version < ver('13.1'): -- cgit v1.2.3-70-g09d2 From c078deaab1d62d881bbed8efece779ca01c504c7 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 11:08:44 +0200 Subject: compilers: add missing import statements --- lib/spack/spack/compilers/clang.py | 2 ++ lib/spack/spack/compilers/intel.py | 2 ++ lib/spack/spack/compilers/nag.py | 1 + lib/spack/spack/compilers/pgi.py | 1 + lib/spack/spack/compilers/xl.py | 1 + 5 files changed, 7 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index 44de77af4f..799b92b20d 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -26,6 +26,8 @@ import re import spack.compiler as cpr from spack.compiler import * from spack.util.executable import * +import llnl.util.tty as tty +from spack.version import ver class Clang(Compiler): # Subclasses use possible names of C compiler diff --git a/lib/spack/spack/compilers/intel.py b/lib/spack/spack/compilers/intel.py index f04a6aa899..bc13db5dc7 100644 --- a/lib/spack/spack/compilers/intel.py +++ b/lib/spack/spack/compilers/intel.py @@ -23,6 +23,8 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## from spack.compiler import * +import llnl.util.tty as tty +from spack.version import ver class Intel(Compiler): # Subclasses use possible names of C compiler diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py index 61486f22bd..729aed0caf 100644 --- a/lib/spack/spack/compilers/nag.py +++ b/lib/spack/spack/compilers/nag.py @@ -1,4 +1,5 @@ from spack.compiler import * +import llnl.util.tty as tty class Nag(Compiler): # Subclasses use possible names of C compiler diff --git a/lib/spack/spack/compilers/pgi.py b/lib/spack/spack/compilers/pgi.py index 299b9a7016..5ab4a9d109 100644 --- a/lib/spack/spack/compilers/pgi.py +++ b/lib/spack/spack/compilers/pgi.py @@ -23,6 +23,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## from spack.compiler import * +import llnl.util.tty as tty class Pgi(Compiler): # Subclasses use possible names of C compiler diff --git a/lib/spack/spack/compilers/xl.py b/lib/spack/spack/compilers/xl.py index 657309fe06..fd78abd091 100644 --- a/lib/spack/spack/compilers/xl.py +++ b/lib/spack/spack/compilers/xl.py @@ -24,6 +24,7 @@ # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## from spack.compiler import * +import llnl.util.tty as tty class Xl(Compiler): # Subclasses use possible names of C compiler -- cgit v1.2.3-70-g09d2 From 3cd3052c564451f375977522e23a458edd25611a Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 11:26:03 +0200 Subject: compilers: minor fixes to Clang::cxx11_flag() and Clang::openmp_flag() --- lib/spack/spack/compilers/clang.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index 799b92b20d..1f0eda3220 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -51,15 +51,16 @@ class Clang(Compiler): @property def openmp_flag(self): - ver = '%s' % self.version - if ver.endswith('-apple'): + ver_string = '%s' % self.version + if ver_string.endswith('-apple'): tty.die("Clang from Apple does not support Openmp yet.") else: return "-fopenmp" @property def cxx11_flag(self): - if ver.endswith('-apple'): + ver_string = '%s' % self.version + if ver_string.endswith('-apple'): # FIXME: figure out from which version Apple's clang supports c++11 return "-std=c++11" else: -- cgit v1.2.3-70-g09d2 From 592045cd5453f3214737de04ce489126287f52dc Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 11:28:49 +0200 Subject: compilers: make Intel::openmp_flag() return -openmp and -qopenmp based on the compiler version --- lib/spack/spack/compilers/intel.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/intel.py b/lib/spack/spack/compilers/intel.py index bc13db5dc7..9b1cf07c36 100644 --- a/lib/spack/spack/compilers/intel.py +++ b/lib/spack/spack/compilers/intel.py @@ -47,7 +47,10 @@ class Intel(Compiler): @property def openmp_flag(self): - return "-openmp" + if self.version < ver('16.0'): + return "-openmp" + else: + return "-qopenmp" @property def cxx11_flag(self): -- cgit v1.2.3-70-g09d2 From 07fd0ccc9aeb1fb47ce6bbb1353a5c5fe7cf7e9a Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 12:13:31 +0200 Subject: compiler: add Clang.is_apple property which checks if Clang is from Apple or not using version --- lib/spack/spack/compilers/clang.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index 1f0eda3220..a6c9a69505 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -50,17 +50,23 @@ class Clang(Compiler): 'fc' : 'f90' } @property - def openmp_flag(self): + def is_apple(self): ver_string = '%s' % self.version if ver_string.endswith('-apple'): + return True + else: + return False + + @property + def openmp_flag(self): + if self.is_apple: tty.die("Clang from Apple does not support Openmp yet.") else: return "-fopenmp" @property def cxx11_flag(self): - ver_string = '%s' % self.version - if ver_string.endswith('-apple'): + if self.is_apple: # FIXME: figure out from which version Apple's clang supports c++11 return "-std=c++11" else: -- cgit v1.2.3-70-g09d2 From f2f1c49c90de5c1b620d7bdb7cd5ff85173fcb22 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 15:21:33 +0200 Subject: compilers: one more missing import statement --- lib/spack/spack/compilers/xl.py | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/spack/spack/compilers/xl.py b/lib/spack/spack/compilers/xl.py index fd78abd091..61a2e730dc 100644 --- a/lib/spack/spack/compilers/xl.py +++ b/lib/spack/spack/compilers/xl.py @@ -25,6 +25,7 @@ ############################################################################## from spack.compiler import * import llnl.util.tty as tty +from spack.version import ver class Xl(Compiler): # Subclasses use possible names of C compiler -- cgit v1.2.3-70-g09d2 From 6a418cfb8d60a26d1195aeb74b2d54ae9cb38616 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 17:09:49 +0200 Subject: compiler: simplify Clang.is_apple --- lib/spack/spack/compilers/clang.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/clang.py b/lib/spack/spack/compilers/clang.py index a6c9a69505..8c646905c7 100644 --- a/lib/spack/spack/compilers/clang.py +++ b/lib/spack/spack/compilers/clang.py @@ -51,11 +51,8 @@ class Clang(Compiler): @property def is_apple(self): - ver_string = '%s' % self.version - if ver_string.endswith('-apple'): - return True - else: - return False + ver_string = str(self.version) + return ver_string.endswith('-apple') @property def openmp_flag(self): -- cgit v1.2.3-70-g09d2 From d5a760776a47552aab7b8575e7ad9ac9eaba9384 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 17:26:43 +0200 Subject: compiler: add default implementation of openmp_flag() and css11_flag() --- lib/spack/spack/compiler.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index 20896f9eec..a707b2e3aa 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -120,6 +120,20 @@ class Compiler(object): def version(self): return self.spec.version + # default implementation of OpenMP linking flag. + # Override in derived classes if needed + @property + def openmp_flag(self): + return "-fopenmp" + + + # default implementation of c++11 linking flag. + # raise an error to force derived classes implement it when used + @property + def cxx11_flag(self): + return "-std=c++11" + + # # Compiler classes have methods for querying the version of # specific compiler executables. This is used when discovering compilers. -- cgit v1.2.3-70-g09d2 From e28ca3922feaba84f5bc2e1b8bf6ababe964ace3 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 17:27:46 +0200 Subject: compiler: cleanup Nag.cxx11_flag and Pgi.cxx11_flag --- lib/spack/spack/compilers/nag.py | 5 ----- lib/spack/spack/compilers/pgi.py | 1 - 2 files changed, 6 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py index 729aed0caf..bbc291d7b6 100644 --- a/lib/spack/spack/compilers/nag.py +++ b/lib/spack/spack/compilers/nag.py @@ -25,11 +25,6 @@ class Nag(Compiler): def openmp_flag(self): return "-openmp" - @property - def cxx11_flag(self): - tty.die("cxx11_flag() is not implemented for nag. Consider creating a pull-request.") - return "-std=c++11" - @classmethod def default_version(self, comp): diff --git a/lib/spack/spack/compilers/pgi.py b/lib/spack/spack/compilers/pgi.py index 5ab4a9d109..94c6b8365c 100644 --- a/lib/spack/spack/compilers/pgi.py +++ b/lib/spack/spack/compilers/pgi.py @@ -50,7 +50,6 @@ class Pgi(Compiler): @property def cxx11_flag(self): - tty.die("cxx11_flag() is not implemented for pgi. Consider creating a pull-request.") return "-std=c++11" -- cgit v1.2.3-70-g09d2 From 30b65d3114e20506fb2d36c0aa7f34babf3c4f72 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 17:29:37 +0200 Subject: fix comment in Compiler class --- lib/spack/spack/compiler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index a707b2e3aa..1f1cf97ce9 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -120,15 +120,15 @@ class Compiler(object): def version(self): return self.spec.version - # default implementation of OpenMP linking flag. + # Default implementation of OpenMP linking flag. # Override in derived classes if needed @property def openmp_flag(self): return "-fopenmp" - # default implementation of c++11 linking flag. - # raise an error to force derived classes implement it when used + # Default implementation of c++11 linking flag. + # Override in derived classes if needed @property def cxx11_flag(self): return "-std=c++11" -- cgit v1.2.3-70-g09d2 From 473a5542bed01e2f70370ddd5ceb70ac41fe178e Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 18:04:08 +0200 Subject: compiler: make default openmp_flag() and cxx11_flag() die when these properties are not implemented in a derived class --- lib/spack/spack/compiler.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index 1f1cf97ce9..622eed6c10 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -120,19 +120,20 @@ class Compiler(object): def version(self): return self.spec.version - # Default implementation of OpenMP linking flag. - # Override in derived classes if needed + # This property should be overridden in the compiler subclass if + # OpenMP is supported by that compiler @property def openmp_flag(self): - return "-fopenmp" + # If it is not overridden, assume it is not supported and warn the user + tty.die("The compiler you have chosen does not currently support OpenMP. If you think it should, please edit the compiler subclass and submit a pull request or issue.") - # Default implementation of c++11 linking flag. - # Override in derived classes if needed + # This property should be overridden in the compiler subclass if + # C++11 is supported by that compiler @property def cxx11_flag(self): - return "-std=c++11" - + # If it is not overridden, assume it is not supported and warn the user + tty.die("The compiler you have chosen does not currently support C++11. If you think it should, please edit the compiler subclass and submit a pull request or issue.") # # Compiler classes have methods for querying the version of -- cgit v1.2.3-70-g09d2 From ddcb97f9531c65bfc370177dfd2090c9e82a4cb3 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 19:04:42 +0200 Subject: add a temporary Nag.cxx11_flag property --- lib/spack/spack/compilers/nag.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'lib') diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py index bbc291d7b6..e9038c1039 100644 --- a/lib/spack/spack/compilers/nag.py +++ b/lib/spack/spack/compilers/nag.py @@ -25,6 +25,11 @@ class Nag(Compiler): def openmp_flag(self): return "-openmp" + @property + def cxx11_flag(self): + # NAG does not have a C++ compiler + # However, it can be mixed with a compiler that does support it + return "-std=c++11" @classmethod def default_version(self, comp): -- cgit v1.2.3-70-g09d2 From c6fb6bde40798903dcdd5d503c32368068a0f8e4 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Tue, 3 May 2016 19:07:16 +0200 Subject: remove cxx11_flag from Compiler as it is now substituted by a property with the same name --- lib/spack/spack/compiler.py | 3 --- 1 file changed, 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index 622eed6c10..42529777bc 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -94,9 +94,6 @@ class Compiler(object): # Names of generic arguments used by this compiler arg_rpath = '-Wl,-rpath,%s' - # argument used to get C++11 options - cxx11_flag = "-std=c++11" - # argument used to get C++14 options cxx14_flag = "-std=c++1y" -- cgit v1.2.3-70-g09d2 From f84f04591be44ba6c1aa5bef50d5efa872cfb1c9 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Thu, 5 May 2016 10:48:31 +0200 Subject: substitute cxx14_flag by a property with the same name to be overridden in derived classes --- lib/spack/spack/compiler.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index 42529777bc..a28d7302aa 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -94,9 +94,6 @@ class Compiler(object): # Names of generic arguments used by this compiler arg_rpath = '-Wl,-rpath,%s' - # argument used to get C++14 options - cxx14_flag = "-std=c++1y" - def __init__(self, cspec, cc, cxx, f77, fc): def check(exe): @@ -132,6 +129,14 @@ class Compiler(object): # If it is not overridden, assume it is not supported and warn the user tty.die("The compiler you have chosen does not currently support C++11. If you think it should, please edit the compiler subclass and submit a pull request or issue.") + # This property should be overridden in the compiler subclass if + # C++14 is supported by that compiler + @property + def cxx14_flag(self): + # If it is not overridden, assume it is not supported and warn the user + tty.die("The compiler you have chosen does not currently support C++14. If you think it should, please edit the compiler subclass and submit a pull request or issue.") + + # # Compiler classes have methods for querying the version of # specific compiler executables. This is used when discovering compilers. -- cgit v1.2.3-70-g09d2 From c37ea9aff548bfdf106aa141b8d6e6adec2ffd01 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Thu, 5 May 2016 11:56:58 +0200 Subject: document usage of compiler flags properties --- lib/spack/docs/packaging_guide.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'lib') diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index 34d11308f5..31c676d4f5 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -1831,6 +1831,25 @@ successfully find ``libdwarf.h`` and ``libdwarf.so``, without the packager having to provide ``--with-libdwarf=/path/to/libdwarf`` on the command line. +Compiler flags +~~~~~~~~~~~~~~ +In rare circumstances such as compiling and running small unit tests, a package +developer may need to know what are the appropriate compiler flags to enable +features like ``OpenMP``, ``c++11``, ``c++14`` and alike. To that end the +compiler classes in ``spack`` implement the following _properties_ : +``openmp_flag``, ``cxx11_flag``, ``cxx14_flag``, which can be accessed in a +package by ``self.compiler.cxx11_flag`` and alike. Note that the implementation +is such that if a given compiler version does not support this feature, an +error will be produced. Therefore package developers can also use these properties +to assert that a compiler supports the requested feature. This is handy when a +package supports additional variants like + +.. code-block:: python + + variant('openmp', default=True, description="Enable OpenMP support.") + + + Message Parsing Interface (MPI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is common for high performance computing software/packages to use ``MPI``. -- cgit v1.2.3-70-g09d2 From 7a2d65967ce60efef1a5cce4969f3607915427f5 Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Mon, 9 May 2016 22:04:34 +0200 Subject: wrap tty.die to 80 chars --- lib/spack/spack/compiler.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index a28d7302aa..b53c17494c 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -119,7 +119,9 @@ class Compiler(object): @property def openmp_flag(self): # If it is not overridden, assume it is not supported and warn the user - tty.die("The compiler you have chosen does not currently support OpenMP. If you think it should, please edit the compiler subclass and submit a pull request or issue.") + tty.die("The compiler you have chosen does not currently support OpenMP.", + "If you think it should, please edit the compiler subclass and", + "submit a pull request or issue.") # This property should be overridden in the compiler subclass if @@ -127,14 +129,20 @@ class Compiler(object): @property def cxx11_flag(self): # If it is not overridden, assume it is not supported and warn the user - tty.die("The compiler you have chosen does not currently support C++11. If you think it should, please edit the compiler subclass and submit a pull request or issue.") + tty.die("The compiler you have chosen does not currently support C++11.", + "If you think it should, please edit the compiler subclass and", + "submit a pull request or issue.") + # This property should be overridden in the compiler subclass if # C++14 is supported by that compiler @property def cxx14_flag(self): # If it is not overridden, assume it is not supported and warn the user - tty.die("The compiler you have chosen does not currently support C++14. If you think it should, please edit the compiler subclass and submit a pull request or issue.") + tty.die("The compiler you have chosen does not currently support C++14.", + "If you think it should, please edit the compiler subclass and", + "submit a pull request or issue.") + # -- cgit v1.2.3-70-g09d2 From 4473311bdbddb6abe2f1ad9748536db89f79081d Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Thu, 5 May 2016 10:50:07 -0500 Subject: Allow compilers to specify their own rpath linking flags --- lib/spack/env/cc | 39 +++++++++++++++++++++++++----------- lib/spack/spack/build_environment.py | 14 +++++++++---- lib/spack/spack/compiler.py | 18 +++++++++++++++-- lib/spack/spack/compilers/nag.py | 11 ++++++++++ lib/spack/spack/test/cc.py | 5 +++++ 5 files changed, 69 insertions(+), 18 deletions(-) (limited to 'lib') diff --git a/lib/spack/env/cc b/lib/spack/env/cc index cb07a2ffea..4564e84bd2 100755 --- a/lib/spack/env/cc +++ b/lib/spack/env/cc @@ -38,15 +38,20 @@ # -Wl,-rpath arguments for dependency /lib directories. # -# This is the list of environment variables that need to be set before +# This is an array of environment variables that need to be set before # the script runs. They are set by routines in spack.build_environment # as part of spack.package.Package.do_install(). -parameters=" -SPACK_PREFIX -SPACK_ENV_PATH -SPACK_DEBUG_LOG_DIR -SPACK_COMPILER_SPEC -SPACK_SHORT_SPEC" +parameters=( + SPACK_PREFIX + SPACK_ENV_PATH + SPACK_DEBUG_LOG_DIR + SPACK_COMPILER_SPEC + SPACK_CC_RPATH_ARG + SPACK_CXX_RPATH_ARG + SPACK_F77_RPATH_ARG + SPACK_FC_RPATH_ARG + SPACK_SHORT_SPEC +) # The compiler input variables are checked for sanity later: # SPACK_CC, SPACK_CXX, SPACK_F77, SPACK_FC @@ -64,7 +69,7 @@ function die { exit 1 } -for param in $parameters; do +for param in ${parameters[@]}; do if [[ -z ${!param} ]]; then die "Spack compiler must be run from Spack! Input '$param' is missing." fi @@ -85,6 +90,7 @@ done # ccld compile & link command=$(basename "$0") +comp="CC" case "$command" in cpp) mode=cpp @@ -92,18 +98,22 @@ case "$command" in cc|c89|c99|gcc|clang|icc|pgcc|xlc) command="$SPACK_CC" language="C" + comp="CC" ;; c++|CC|g++|clang++|icpc|pgc++|xlc++) command="$SPACK_CXX" language="C++" + comp="CXX" ;; f90|fc|f95|gfortran|ifort|pgfortran|xlf90|nagfor) command="$SPACK_FC" language="Fortran 90" + comp="FC" ;; f77|gfortran|ifort|pgfortran|xlf|nagfor) command="$SPACK_F77" language="Fortran 77" + comp="F77" ;; ld) mode=ld @@ -142,6 +152,9 @@ if [[ -z $mode ]]; then done fi +# Set up rpath variable according to language. +eval rpath=\$SPACK_${comp}_RPATH_ARG + # Dump the version and exit if we're in testing mode. if [[ $SPACK_TEST_COMMAND == dump-mode ]]; then echo "$mode" @@ -188,7 +201,7 @@ for dep in "${deps[@]}"; do # Prepend lib and RPATH directories if [[ -d $dep/lib ]]; then if [[ $mode == ccld ]]; then - $add_rpaths && args=("-Wl,-rpath,$dep/lib" "${args[@]}") + $add_rpaths && args=("$rpath$dep/lib" "${args[@]}") args=("-L$dep/lib" "${args[@]}") elif [[ $mode == ld ]]; then $add_rpaths && args=("-rpath" "$dep/lib" "${args[@]}") @@ -199,7 +212,7 @@ for dep in "${deps[@]}"; do # Prepend lib64 and RPATH directories if [[ -d $dep/lib64 ]]; then if [[ $mode == ccld ]]; then - $add_rpaths && args=("-Wl,-rpath,$dep/lib64" "${args[@]}") + $add_rpaths && args=("$rpath$dep/lib64" "${args[@]}") args=("-L$dep/lib64" "${args[@]}") elif [[ $mode == ld ]]; then $add_rpaths && args=("-rpath" "$dep/lib64" "${args[@]}") @@ -210,9 +223,11 @@ done # Include all -L's and prefix/whatever dirs in rpath if [[ $mode == ccld ]]; then - $add_rpaths && args=("-Wl,-rpath,$SPACK_PREFIX/lib" "-Wl,-rpath,$SPACK_PREFIX/lib64" "${args[@]}") + $add_rpaths && args=("$rpath$SPACK_PREFIX/lib64" "${args[@]}") + $add_rpaths && args=("$rpath$SPACK_PREFIX/lib" "${args[@]}") elif [[ $mode == ld ]]; then - $add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "-rpath" "$SPACK_PREFIX/lib64" "${args[@]}") + $add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib64" "${args[@]}") + $add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "${args[@]}") fi # diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index eb72f2a6b4..411425549a 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -98,21 +98,27 @@ def set_compiler_environment_variables(pkg, env): # and return it # TODO : add additional kwargs for better diagnostics, like requestor, ttyout, ttyerr, etc. link_dir = spack.build_env_path - env.set('CC', join_path(link_dir, pkg.compiler.link_paths['cc'])) + env.set('CC', join_path(link_dir, pkg.compiler.link_paths['cc'])) env.set('CXX', join_path(link_dir, pkg.compiler.link_paths['cxx'])) env.set('F77', join_path(link_dir, pkg.compiler.link_paths['f77'])) - env.set('FC', join_path(link_dir, pkg.compiler.link_paths['fc'])) + env.set('FC', join_path(link_dir, pkg.compiler.link_paths['fc'])) # Set SPACK compiler variables so that our wrapper knows what to call compiler = pkg.compiler if compiler.cc: - env.set('SPACK_CC', compiler.cc) + env.set('SPACK_CC', compiler.cc) if compiler.cxx: env.set('SPACK_CXX', compiler.cxx) if compiler.f77: env.set('SPACK_F77', compiler.f77) if compiler.fc: - env.set('SPACK_FC', compiler.fc) + env.set('SPACK_FC', compiler.fc) + + # Set SPACK compiler rpath flags so that our wrapper knows what to use + env.set('SPACK_CC_RPATH_ARG', compiler.cc_rpath_arg) + env.set('SPACK_CXX_RPATH_ARG', compiler.cxx_rpath_arg) + env.set('SPACK_F77_RPATH_ARG', compiler.f77_rpath_arg) + env.set('SPACK_FC_RPATH_ARG', compiler.fc_rpath_arg) env.set('SPACK_COMPILER_SPEC', str(pkg.spec.compiler)) return env diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index b53c17494c..8c197520b5 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -91,8 +91,22 @@ class Compiler(object): # version suffix for gcc. suffixes = [r'-.*'] - # Names of generic arguments used by this compiler - arg_rpath = '-Wl,-rpath,%s' + # Flags used by this compiler to set an rpath + @property + def cc_rpath_arg(self): + return '-Wl,-rpath,' + + @property + def cxx_rpath_arg(self): + return '-Wl,-rpath,' + + @property + def f77_rpath_arg(self): + return '-Wl,-rpath,' + + @property + def fc_rpath_arg(self): + return '-Wl,-rpath,' def __init__(self, cspec, cc, cxx, f77, fc): diff --git a/lib/spack/spack/compilers/nag.py b/lib/spack/spack/compilers/nag.py index e9038c1039..49b77eae6b 100644 --- a/lib/spack/spack/compilers/nag.py +++ b/lib/spack/spack/compilers/nag.py @@ -31,6 +31,17 @@ class Nag(Compiler): # However, it can be mixed with a compiler that does support it return "-std=c++11" + # Unlike other compilers, the NAG compiler passes options to GCC, which + # then passes them to the linker. Therefore, we need to doubly wrap the + # options with '-Wl,-Wl,,' + @property + def f77_rpath_arg(self): + return '-Wl,-Wl,,-rpath,' + + @property + def fc_rpath_arg(self): + return '-Wl,-Wl,,-rpath,' + @classmethod def default_version(self, comp): """The '-V' option works for nag compilers. diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py index 594cd6efe9..cdac319088 100644 --- a/lib/spack/spack/test/cc.py +++ b/lib/spack/spack/test/cc.py @@ -67,6 +67,11 @@ class CompilerTest(unittest.TestCase): os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7" os.environ['SPACK_SHORT_SPEC'] = "foo@1.2" + os.environ['SPACK_CC_RPATH_ARG'] = "-Wl,-rpath" + os.environ['SPACK_CXX_RPATH_ARG'] = "-Wl,-rpath" + os.environ['SPACK_F77_RPATH_ARG'] = "-Wl,-rpath" + os.environ['SPACK_FC_RPATH_ARG'] = "-Wl,-rpath" + # Make some fake dependencies self.tmp_deps = tempfile.mkdtemp() self.dep1 = join_path(self.tmp_deps, 'dep1') -- cgit v1.2.3-70-g09d2 From b211829fb137994fbd7467c713fd026bc29cef3f Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Thu, 5 May 2016 13:54:10 -0500 Subject: Testing typo --- lib/spack/spack/test/cc.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py index cdac319088..35392d9d6d 100644 --- a/lib/spack/spack/test/cc.py +++ b/lib/spack/spack/test/cc.py @@ -67,10 +67,10 @@ class CompilerTest(unittest.TestCase): os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7" os.environ['SPACK_SHORT_SPEC'] = "foo@1.2" - os.environ['SPACK_CC_RPATH_ARG'] = "-Wl,-rpath" - os.environ['SPACK_CXX_RPATH_ARG'] = "-Wl,-rpath" - os.environ['SPACK_F77_RPATH_ARG'] = "-Wl,-rpath" - os.environ['SPACK_FC_RPATH_ARG'] = "-Wl,-rpath" + os.environ['SPACK_CC_RPATH_ARG'] = "-Wl,-rpath," + os.environ['SPACK_CXX_RPATH_ARG'] = "-Wl,-rpath," + os.environ['SPACK_F77_RPATH_ARG'] = "-Wl,-rpath," + os.environ['SPACK_FC_RPATH_ARG'] = "-Wl,-rpath," # Make some fake dependencies self.tmp_deps = tempfile.mkdtemp() -- cgit v1.2.3-70-g09d2 From 58733eb26a734fd00cac40ca2ff7422ccf7669fa Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Fri, 6 May 2016 09:57:59 -0500 Subject: Comment change --- lib/spack/spack/compiler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py index 8c197520b5..976d96825c 100644 --- a/lib/spack/spack/compiler.py +++ b/lib/spack/spack/compiler.py @@ -91,7 +91,7 @@ class Compiler(object): # version suffix for gcc. suffixes = [r'-.*'] - # Flags used by this compiler to set an rpath + # Default flags used by a compiler to set an rpath @property def cc_rpath_arg(self): return '-Wl,-rpath,' -- cgit v1.2.3-70-g09d2 From 6665a996e62e2097b68392afaa45d01305bcc399 Mon Sep 17 00:00:00 2001 From: "Adam J. Stewart" Date: Mon, 9 May 2016 14:08:11 -0500 Subject: Add documentation for rpath_flag handling --- lib/spack/docs/packaging_guide.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index 31c676d4f5..1b7941ab24 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -1803,15 +1803,15 @@ Compile-time library search paths * ``-L$dep_prefix/lib`` * ``-L$dep_prefix/lib64`` Runtime library search paths (RPATHs) - * ``-Wl,-rpath,$dep_prefix/lib`` - * ``-Wl,-rpath,$dep_prefix/lib64`` + * ``$rpath_flag$dep_prefix/lib`` + * ``$rpath_flag$dep_prefix/lib64`` Include search paths * ``-I$dep_prefix/include`` An example of this would be the ``libdwarf`` build, which has one dependency: ``libelf``. Every call to ``cc`` in the ``libdwarf`` build will have ``-I$LIBELF_PREFIX/include``, -``-L$LIBELF_PREFIX/lib``, and ``-Wl,-rpath,$LIBELF_PREFIX/lib`` +``-L$LIBELF_PREFIX/lib``, and ``$rpath_flag$LIBELF_PREFIX/lib`` inserted on the command line. This is done transparently to the project's build system, which will just think it's using a system where ``libelf`` is readily available. Because of this, you **do @@ -1831,6 +1831,14 @@ successfully find ``libdwarf.h`` and ``libdwarf.so``, without the packager having to provide ``--with-libdwarf=/path/to/libdwarf`` on the command line. +.. note:: + + For most compilers, ``$rpath_flag`` is ``-Wl,-rpath,``. However, NAG + passes its flags to GCC instead of passing them directly to the linker. + Therefore, its ``$rpath_flag`` is doubly wrapped: ``-Wl,-Wl,,-rpath,``. + ``$rpath_flag`` can be overriden on a compiler specific basis in + ``lib/spack/spack/compilers/$compiler.py``. + Compiler flags ~~~~~~~~~~~~~~ In rare circumstances such as compiling and running small unit tests, a package @@ -1848,8 +1856,6 @@ package supports additional variants like variant('openmp', default=True, description="Enable OpenMP support.") - - Message Parsing Interface (MPI) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It is common for high performance computing software/packages to use ``MPI``. -- cgit v1.2.3-70-g09d2