summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rwxr-xr-xlib/spack/env/cc4
-rw-r--r--lib/spack/llnl/util/filesystem.py76
-rw-r--r--lib/spack/spack/hooks/sbang.py8
-rw-r--r--lib/spack/spack/test/cmd/test_compiler_cmd.py67
4 files changed, 108 insertions, 47 deletions
diff --git a/lib/spack/env/cc b/lib/spack/env/cc
index 1e405ae6e9..bf98b4c354 100755
--- a/lib/spack/env/cc
+++ b/lib/spack/env/cc
@@ -324,8 +324,8 @@ fi
if [[ $SPACK_DEBUG == TRUE ]]; then
input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.in.log"
output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.out.log"
- echo "[$mode] $command $input_command" >> $input_log
- echo "[$mode] ${full_command[@]}" >> $output_log
+ echo "[$mode] $command $input_command" >> "$input_log"
+ echo "[$mode] ${full_command[@]}" >> "$output_log"
fi
exec "${full_command[@]}"
diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py
index 6661a80f27..d72e8bae92 100644
--- a/lib/spack/llnl/util/filesystem.py
+++ b/lib/spack/llnl/util/filesystem.py
@@ -22,28 +22,28 @@
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
-__all__ = ['set_install_permissions', 'install', 'install_tree', 'traverse_tree',
- 'expand_user', 'working_dir', 'touch', 'touchp', 'mkdirp',
- 'force_remove', 'join_path', 'ancestor', 'can_access', 'filter_file',
- 'FileFilter', 'change_sed_delimiter', 'is_exe', 'force_symlink',
- 'set_executable', 'copy_mode', 'unset_executable_mode',
- 'remove_dead_links', 'remove_linked_tree', 'find_library_path',
- 'fix_darwin_install_name']
-
import os
import glob
-import sys
import re
import shutil
import stat
import errno
import getpass
from contextlib import contextmanager, closing
-from tempfile import NamedTemporaryFile
import subprocess
import llnl.util.tty as tty
-from spack.util.compression import ALLOWED_ARCHIVE_TYPES
+
+__all__ = ['set_install_permissions', 'install', 'install_tree',
+ 'traverse_tree',
+ 'expand_user', 'working_dir', 'touch', 'touchp', 'mkdirp',
+ 'force_remove', 'join_path', 'ancestor', 'can_access',
+ 'filter_file',
+ 'FileFilter', 'change_sed_delimiter', 'is_exe', 'force_symlink',
+ 'set_executable', 'copy_mode', 'unset_executable_mode',
+ 'remove_dead_links', 'remove_linked_tree', 'find_library_path',
+ 'fix_darwin_install_name', 'to_link_flags']
+
def filter_file(regex, repl, *filenames, **kwargs):
"""Like sed, but uses python regular expressions.
@@ -69,6 +69,7 @@ def filter_file(regex, repl, *filenames, **kwargs):
# Allow strings to use \1, \2, etc. for replacement, like sed
if not callable(repl):
unescaped = repl.replace(r'\\', '\\')
+
def replace_groups_with_groupid(m):
def groupid_to_group(x):
return m.group(int(x.group(1)))
@@ -157,9 +158,12 @@ def set_install_permissions(path):
def copy_mode(src, dest):
src_mode = os.stat(src).st_mode
dest_mode = os.stat(dest).st_mode
- if src_mode & stat.S_IXUSR: dest_mode |= stat.S_IXUSR
- if src_mode & stat.S_IXGRP: dest_mode |= stat.S_IXGRP
- if src_mode & stat.S_IXOTH: dest_mode |= stat.S_IXOTH
+ if src_mode & stat.S_IXUSR:
+ dest_mode |= stat.S_IXUSR
+ if src_mode & stat.S_IXGRP:
+ dest_mode |= stat.S_IXGRP
+ if src_mode & stat.S_IXOTH:
+ dest_mode |= stat.S_IXOTH
os.chmod(dest, dest_mode)
@@ -224,9 +228,10 @@ def force_remove(*paths):
for path in paths:
try:
os.remove(path)
- except OSError, e:
+ except OSError:
pass
+
@contextmanager
def working_dir(dirname, **kwargs):
if kwargs.get('create', False):
@@ -240,7 +245,7 @@ def working_dir(dirname, **kwargs):
def touch(path):
"""Creates an empty file at the specified path."""
- with open(path, 'a') as file:
+ with open(path, 'a'):
os.utime(path, None)
@@ -253,7 +258,7 @@ def touchp(path):
def force_symlink(src, dest):
try:
os.symlink(src, dest)
- except OSError as e:
+ except OSError:
os.remove(dest)
os.symlink(src, dest)
@@ -275,7 +280,7 @@ def ancestor(dir, n=1):
def can_access(file_name):
"""True if we have read/write access to the file."""
- return os.access(file_name, os.R_OK|os.W_OK)
+ return os.access(file_name, os.R_OK | os.W_OK)
def traverse_tree(source_root, dest_root, rel_path='', **kwargs):
@@ -343,13 +348,14 @@ def traverse_tree(source_root, dest_root, rel_path='', **kwargs):
# Treat as a directory
if os.path.isdir(source_child) and (
- follow_links or not os.path.islink(source_child)):
+ follow_links or not os.path.islink(source_child)):
# When follow_nonexisting isn't set, don't descend into dirs
# in source that do not exist in dest
if follow_nonexisting or os.path.exists(dest_child):
- tuples = traverse_tree(source_root, dest_root, rel_child, **kwargs)
- for t in tuples: yield t
+ tuples = traverse_tree(source_root, dest_root, rel_child, **kwargs) # NOQA: ignore=E501
+ for t in tuples:
+ yield t
# Treat as a file.
elif not ignore(os.path.join(rel_path, f)):
@@ -379,6 +385,7 @@ def remove_dead_links(root):
if not os.path.exists(real_path):
os.unlink(path)
+
def remove_linked_tree(path):
"""
Removes a directory and its contents. If the directory is a
@@ -402,28 +409,41 @@ def fix_darwin_install_name(path):
Fix install name of dynamic libraries on Darwin to have full path.
There are two parts of this task:
(i) use install_name('-id',...) to change install name of a single lib;
- (ii) use install_name('-change',...) to change the cross linking between libs.
- The function assumes that all libraries are in one folder and currently won't
- follow subfolders.
+ (ii) use install_name('-change',...) to change the cross linking between
+ libs. The function assumes that all libraries are in one folder and
+ currently won't follow subfolders.
Args:
path: directory in which .dylib files are alocated
"""
- libs = glob.glob(join_path(path,"*.dylib"))
+ libs = glob.glob(join_path(path, "*.dylib"))
for lib in libs:
# fix install name first:
- subprocess.Popen(["install_name_tool", "-id",lib,lib], stdout=subprocess.PIPE).communicate()[0]
- long_deps = subprocess.Popen(["otool", "-L",lib], stdout=subprocess.PIPE).communicate()[0].split('\n')
+ subprocess.Popen(["install_name_tool", "-id", lib, lib], stdout=subprocess.PIPE).communicate()[0] # NOQA: ignore=E501
+ long_deps = subprocess.Popen(["otool", "-L", lib], stdout=subprocess.PIPE).communicate()[0].split('\n') # NOQA: ignore=E501
deps = [dep.partition(' ')[0][1::] for dep in long_deps[2:-1]]
# fix all dependencies:
for dep in deps:
for loc in libs:
if dep == os.path.basename(loc):
- subprocess.Popen(["install_name_tool", "-change",dep,loc,lib], stdout=subprocess.PIPE).communicate()[0]
+ subprocess.Popen(["install_name_tool", "-change", dep, loc, lib], stdout=subprocess.PIPE).communicate()[0] # NOQA: ignore=E501
break
+def to_link_flags(library):
+ """Transforms a path to a <library> into linking flags -L<dir> -l<name>.
+
+ Return:
+ A string of linking flags.
+ """
+ dir = os.path.dirname(library)
+ # Asume libXYZ.suffix
+ name = os.path.basename(library)[3:].split(".")[0]
+ res = '-L%s -l%s' % (dir, name)
+ return res
+
+
def find_library_path(libname, *paths):
"""Searches for a file called <libname> in each path.
diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py
index 83d67ea225..cb0ad42b14 100644
--- a/lib/spack/spack/hooks/sbang.py
+++ b/lib/spack/spack/hooks/sbang.py
@@ -24,7 +24,6 @@
##############################################################################
import os
-from llnl.util.filesystem import *
import llnl.util.tty as tty
import spack
@@ -34,6 +33,7 @@ import spack.modules
# here, as it is the shortest I could find on a modern OS.
shebang_limit = 127
+
def shebang_too_long(path):
"""Detects whether a file has a shebang line that is too long."""
with open(path, 'r') as script:
@@ -57,16 +57,10 @@ def filter_shebang(path):
if original.startswith(new_sbang_line):
return
- backup = path + ".shebang.bak"
- os.rename(path, backup)
-
with open(path, 'w') as new_file:
new_file.write(new_sbang_line)
new_file.write(original)
- copy_mode(backup, path)
- unset_executable_mode(backup)
-
tty.warn("Patched overly long shebang in %s" % path)
diff --git a/lib/spack/spack/test/cmd/test_compiler_cmd.py b/lib/spack/spack/test/cmd/test_compiler_cmd.py
index 81bc7aacf2..d89814154b 100644
--- a/lib/spack/spack/test/cmd/test_compiler_cmd.py
+++ b/lib/spack/spack/test/cmd/test_compiler_cmd.py
@@ -1,8 +1,16 @@
+import os
+import shutil
+from tempfile import mkdtemp
+
+from llnl.util.filesystem import set_executable, mkdirp
+
import spack.spec
import spack.cmd.compiler
import spack.compilers
+from spack.version import Version
from spack.test.mock_packages_test import *
+test_version = '4.5-spacktest'
class MockArgs(object):
def __init__(self, add_paths=[], scope=None, compiler_spec=None, all=None):
@@ -12,23 +20,62 @@ class MockArgs(object):
self.all = all
+def make_mock_compiler():
+ """Make a directory containing a fake, but detectable compiler."""
+ mock_compiler_dir = mkdtemp()
+ bin_dir = os.path.join(mock_compiler_dir, 'bin')
+ mkdirp(bin_dir)
+
+ gcc_path = os.path.join(bin_dir, 'gcc')
+ gxx_path = os.path.join(bin_dir, 'g++')
+ gfortran_path = os.path.join(bin_dir, 'gfortran')
+
+ with open(gcc_path, 'w') as f:
+ f.write("""\
+#!/bin/sh
+
+for arg in "$@"; do
+ if [ "$arg" = -dumpversion ]; then
+ echo '%s'
+ fi
+done
+""" % test_version)
+
+ # Create some mock compilers in the temporary directory
+ set_executable(gcc_path)
+ shutil.copy(gcc_path, gxx_path)
+ shutil.copy(gcc_path, gfortran_path)
+
+ return mock_compiler_dir
+
+
class CompilerCmdTest(MockPackagesTest):
""" Test compiler commands for add and remove """
+
def test_compiler_remove(self):
args = MockArgs(all=True, compiler_spec='gcc@4.5.0')
spack.cmd.compiler.compiler_remove(args)
compilers = spack.compilers.all_compilers()
self.assertTrue(spack.spec.CompilerSpec("gcc@4.5.0") not in compilers)
+
def test_compiler_add(self):
- # Probably not a good a assumption but might try finding local
- # compilers
- # installed in /usr
- compilers = spack.compilers.all_compilers()
- s = set(compilers)
- args = MockArgs(add_paths=["/usr"])
- spack.cmd.compiler.compiler_find(args)
- new_compilers = spack.compilers.all_compilers()
- new_compiler = [x for x in new_compilers if x not in s]
- self.assertTrue(new_compiler)
+ # compilers available by default.
+ old_compilers = set(spack.compilers.all_compilers())
+
+ # add our new compiler and find again.
+ compiler_dir = make_mock_compiler()
+
+ try:
+ args = MockArgs(add_paths=[compiler_dir])
+ spack.cmd.compiler.compiler_find(args)
+
+ # ensure new compiler is in there
+ new_compilers = set(spack.compilers.all_compilers())
+ new_compiler = new_compilers - old_compilers
+ self.assertTrue(new_compiler)
+ self.assertTrue(new_compiler.pop().version == Version(test_version))
+
+ finally:
+ shutil.rmtree(compiler_dir, ignore_errors=True)