Merge branch 'develop' of https://github.com/LLNL/spack into bugfix/compiler_find
Forgot to pull branch changes before
This commit is contained in:
4
lib/spack/env/cc
vendored
4
lib/spack/env/cc
vendored
@@ -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[@]}"
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -24,7 +24,6 @@
|
||||
##############################################################################
|
||||
import os
|
||||
|
||||
from llnl.util.filesystem import *
|
||||
import llnl.util.tty as tty
|
||||
|
||||
import spack
|
||||
@@ -34,6 +33,7 @@
|
||||
# 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)
|
||||
|
||||
|
||||
|
@@ -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 @@ def __init__(self, add_paths=[], scope=None, compiler_spec=None, all=None):
|
||||
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)
|
||||
|
Reference in New Issue
Block a user