Merge branch 'features/python' into develop

This commit is contained in:
Todd Gamblin 2014-11-03 14:20:37 -08:00
commit 488a6737b7
16 changed files with 552 additions and 248 deletions

420
lib/spack/env/cc vendored
View file

@ -1,140 +1,326 @@
#!/usr/bin/env python #!/bin/bash
import sys ##############################################################################
if not sys.version_info[:2] >= (2,6): # Copyright (c) 2013, Lawrence Livermore National Security, LLC.
sys.exit("Spack requires Python 2.6. Version was %s." % sys.version_info) # 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://scalability-llnl.github.io/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
##############################################################################
#
# Spack compiler wrapper script.
#
# Compiler commands go through this compiler wrapper in Spack builds.
# The compiler wrapper is a thin layer around the standard compilers.
# It enables several key pieces of functionality:
#
# 1. It allows Spack to swap compilers into and out of builds easily.
# 2. It adds several options to the compile line so that spack
# packages can find their dependencies at build time and run time:
# -I arguments for dependency /include directories.
# -L arguments for dependency /lib directories.
# -Wl,-rpath arguments for dependency /lib directories.
#
import os # This is the list of environment variables that need to be set before
import re # the script runs. They are set by routines in spack.build_environment
import subprocess # as part of spack.package.Package.do_install().
from contextlib import closing parameters="
SPACK_PREFIX
SPACK_ENV_PATH
SPACK_DEBUG_LOG_DIR
SPACK_COMPILER_SPEC
SPACK_SHORT_SPEC"
# Import spack parameters through the build environment. # The compiler input variables are checked for sanity later:
spack_lib = os.environ.get("SPACK_LIB") # SPACK_CC, SPACK_CXX, SPACK_F77, SPACK_FC
if not spack_lib: # Debug flag is optional; set to true for debug logging:
print "Spack compiler must be run from spack!" # SPACK_DEBUG
sys.exit(1) # Test command is used to unit test the compiler script.
# SPACK_TEST_COMMAND
# Dependencies can be empty for pkgs with no deps:
# SPACK_DEPENDENCIES
# Grab a minimal set of spack packages # die()
sys.path.append(spack_lib) # Prints a message and exits with error 1.
from spack.compilation import * function die {
from external import argparse echo "$@"
import llnl.util.tty as tty exit 1
}
spack_prefix = get_env_var("SPACK_PREFIX") for param in $parameters; do
spack_debug = get_env_flag("SPACK_DEBUG") if [ -z "${!param}" ]; then
spack_deps = get_path("SPACK_DEPENDENCIES") die "Spack compiler must be run from spack! Input $param was missing!"
spack_env_path = get_path("SPACK_ENV_PATH") fi
spack_debug_log_dir = get_env_var("SPACK_DEBUG_LOG_DIR") done
spack_spec = get_env_var("SPACK_SPEC")
compiler_spec = get_env_var("SPACK_COMPILER_SPEC") #
spack_cc = get_env_var("SPACK_CC", required=False) # Figure out the type of compiler, the language, and the mode so that
spack_cxx = get_env_var("SPACK_CXX", required=False) # the compiler script knows what to do.
spack_f77 = get_env_var("SPACK_F77", required=False) #
spack_fc = get_env_var("SPACK_FC", required=False) # Possible languages are C, C++, Fortran 77, and Fortran 90.
# 'command' is set based on the input command to $SPACK_[CC|CXX|F77|F90]
#
# 'mode' is set to one of:
# cc compile
# ld link
# ccld compile & link
# cpp preprocessor
# vcheck version check
#
command=$(basename "$0")
case "$command" in
cc|gcc|c89|c99|clang)
command="$SPACK_CC"
language="C"
;;
c++|CC|g++|clang++)
command="$SPACK_CXX"
language="C++"
;;
f77)
command="$SPACK_F77"
language="Fortran 77"
;;
fc|f90|f95)
command="$SPACK_FC"
language="Fortran 90"
;;
cpp)
mode=cpp
;;
ld)
mode=ld
;;
*)
die "Unkown compiler: $command"
;;
esac
# Figure out what type of operation we're doing # Finish setting up the mode.
command = os.path.basename(sys.argv[0]) if [ -z "$mode" ]; then
mode=ccld
for arg in "$@"; do
if [ "$arg" = -v -o "$arg" = -V -o "$arg" = --version -o "$arg" = -dumpversion ]; then
mode=vcheck
break
elif [ "$arg" = -E ]; then
mode=cpp
break
elif [ "$arg" = -c ]; then
mode=cc
break
fi
done
fi
cpp, cc, ccld, ld, version_check = range(5) # Dump the version and exist if we're in testing mode.
if [ "$SPACK_TEST_COMMAND" = "dump-mode" ]; then
echo "$mode"
exit
fi
if command == 'cpp': # Check that at least one of the real commands was actually selected,
mode = cpp # otherwise we don't know what to execute.
elif command == 'ld': if [ -z "$command" ]; then
mode = ld die "ERROR: Compiler '$SPACK_COMPILER_SPEC' does not support compiling $language programs."
elif '-E' in sys.argv: fi
mode = cpp
elif '-c' in sys.argv:
mode = cc
else:
mode = ccld
# Save original command for debug logging
input_command="$@"
if command in ('cc', 'gcc', 'c89', 'c99', 'clang'): #
command = spack_cc # Now do real parsing of the command line args, trying hard to keep
language = "C" # non-rpath linker arguments in the proper order w.r.t. other command
elif command in ('c++', 'CC', 'g++', 'clang++'): # line arguments. This is important for things like groups.
command = spack_cxx #
language = "C++" includes=()
elif command in ('f77'): libraries=()
command = spack_f77 libs=()
language = "Fortran 77" rpaths=()
elif command in ('fc', 'f90', 'f95'): other_args=()
command = spack_fc
language = "Fortran 90"
elif command in ('ld', 'cpp'):
pass # leave it the same. TODO: what's the right thing?
else:
raise Exception("Unknown compiler: %s" % command)
if command is None: while [ -n "$1" ]; do
print "ERROR: Compiler '%s' does not support compiling %s programs." % ( case "$1" in
compiler_spec, language) -I*)
sys.exit(1) arg="${1#-I}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
includes+=("$arg")
;;
-L*)
arg="${1#-L}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
libraries+=("$arg")
;;
-l*)
arg="${1#-l}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
libs+=("$arg")
;;
-Wl,*)
arg="${1#-Wl,}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
if [[ "$arg" = -rpath=* ]]; then
rpaths+=("${arg#-rpath=}")
elif [[ "$arg" = -rpath ]]; then
shift; arg="$1"
if [[ "$arg" != -Wl,* ]]; then
die "-Wl,-rpath was not followed by -Wl,*"
fi
rpaths+=("${arg#-Wl,}")
else
other_args+=("-Wl,$arg")
fi
;;
-Xlinker,*)
arg="${1#-Xlinker,}"
if [ -z "$arg" ]; then shift; arg="$1"; fi
if [[ "$arg" = -rpath=* ]]; then
rpaths+=("${arg#-rpath=}")
elif [[ "$arg" = -rpath ]]; then
shift; arg="$1"
if [[ "$arg" != -Xlinker,* ]]; then
die "-Xlinker,-rpath was not followed by -Xlinker,*"
fi
rpaths+=("${arg#-Xlinker,}")
else
other_args+=("-Xlinker,$arg")
fi
;;
*)
other_args+=("$1")
;;
esac
shift
done
version_args = ['-V', '-v', '--version', '-dumpversion'] # Dump parsed values for unit testing if asked for
if any(arg in sys.argv for arg in version_args): if [ -n "$SPACK_TEST_COMMAND" ]; then
mode = version_check IFS=$'\n'
case "$SPACK_TEST_COMMAND" in
dump-includes) echo "${includes[*]}";;
dump-libraries) echo "${libraries[*]}";;
dump-libs) echo "${libs[*]}";;
dump-rpaths) echo "${rpaths[*]}";;
dump-other-args) echo "${other_args[*]}";;
dump-all)
echo "INCLUDES:"
echo "${includes[*]}"
echo
echo "LIBRARIES:"
echo "${libraries[*]}"
echo
echo "LIBS:"
echo "${libs[*]}"
echo
echo "RPATHS:"
echo "${rpaths[*]}"
echo
echo "ARGS:"
echo "${other_args[*]}"
;;
*)
echo "ERROR: Unknown test command"
exit 1 ;;
esac
exit
fi
# Parse out the includes, libs, etc. so we can adjust them if need be. # Read spack dependencies from the path environment variable
parser = argparse.ArgumentParser(add_help=False) IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES"
parser.add_argument("-I", action='append', default=[], dest='include_path') for dep in "${deps[@]}"; do
parser.add_argument("-L", action='append', default=[], dest='lib_path') if [ -d "$dep/include" ]; then
parser.add_argument("-l", action='append', default=[], dest='libs') includes+=("$dep/include")
fi
options, other_args = parser.parse_known_args() if [ -d "$dep/lib" ]; then
rpaths, other_args = parse_rpaths(other_args) libraries+=("$dep/lib")
rpaths+=("$dep/lib")
fi
# Add dependencies' include and lib paths to our compiler flags. if [ -d "$dep/lib64" ]; then
def add_if_dir(path_list, directory, index=None): libraries+=("$dep/lib64")
if os.path.isdir(directory): rpaths+=("$dep/lib64")
if index is None: fi
path_list.append(directory) done
else:
path_list.insert(index, directory)
for dep_dir in spack_deps: # Include all -L's and prefix/whatever dirs in rpath
add_if_dir(options.include_path, os.path.join(dep_dir, "include")) for dir in "${libraries[@]}"; do
add_if_dir(options.lib_path, os.path.join(dep_dir, "lib")) [ "$dir" != "." ] && rpaths+=("$dir")
add_if_dir(options.lib_path, os.path.join(dep_dir, "lib64")) done
rpaths+=("$SPACK_PREFIX/lib")
rpaths+=("$SPACK_PREFIX/lib64")
# Add our modified arguments to it. # Put the arguments together
arguments = ['-I%s' % path for path in options.include_path] args=()
arguments += other_args for dir in "${includes[@]}"; do args+=("-I$dir"); done
arguments += ['-L%s' % path for path in options.lib_path] args+=("${other_args[@]}")
arguments += ['-l%s' % path for path in options.libs] for dir in "${libraries[@]}"; do args+=("-L$dir"); done
for lib in "${libs[@]}"; do args+=("-l$lib"); done
# Add rpaths to install dir and its dependencies. We add both lib and lib64 if [ "$mode" = ccld ]; then
# here because we don't know which will be created. for dir in "${rpaths[@]}"; do args+=("-Wl,-rpath=$dir"); done
rpaths.extend(options.lib_path) elif [ "$mode" = ld ]; then
rpaths.append('%s/lib' % spack_prefix) for dir in "${rpaths[@]}"; do args+=("-rpath=$dir"); done
rpaths.append('%s/lib64' % spack_prefix) fi
if mode == ccld:
arguments += ['-Wl,-rpath,%s' % p for p in rpaths]
elif mode == ld:
pairs = [('-rpath', '%s' % p) for p in rpaths]
arguments += [item for sublist in pairs for item in sublist]
# Unset some pesky environment variables #
for var in ["LD_LIBRARY_PATH", "LD_RUN_PATH", "DYLD_LIBRARY_PATH"]: # Unset pesky environment variables that could affect build sanity.
if var in os.environ: #
os.environ.pop(var) unset LD_LIBRARY_PATH
unset LD_RUN_PATH
unset DYLD_LIBRARY_PATH
# Ensure that the delegated command doesn't just call this script again. #
remove_paths = ['.'] + spack_env_path # Filter '.' and Spack environment directories out of PATH so that
path = [p for p in get_path("PATH") if p not in remove_paths] # this script doesn't just call itself
os.environ["PATH"] = ":".join(path) #
IFS=':' read -ra env_path <<< "$PATH"
IFS=':' read -ra spack_env_dirs <<< "$SPACK_ENV_PATH"
spack_env_dirs+=(".")
PATH=""
for dir in "${env_path[@]}"; do
remove=""
for rm_dir in "${spack_env_dirs[@]}"; do
if [ "$dir" = "$rm_dir" ]; then remove=True; fi
done
if [ -z "$remove" ]; then
if [ -z "$PATH" ]; then
PATH="$dir"
else
PATH="$PATH:$dir"
fi
fi
done
export PATH
full_command = [command] + arguments full_command=("$command")
full_command+=("${args[@]}")
if spack_debug: #
input_log = os.path.join(spack_debug_log_dir, 'spack-cc-%s.in.log' % spack_spec) # Write the input and output commands to debug logs if it's asked for.
output_log = os.path.join(spack_debug_log_dir, 'spack-cc-%s.out.log' % spack_spec) #
with closing(open(input_log, 'a')) as log: if [ "$SPACK_DEBUG" = "TRUE" ]; then
args = [os.path.basename(sys.argv[0])] + sys.argv[1:] input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.in.log"
log.write("%s\n" % " ".join(arg.replace(' ', r'\ ') for arg in args)) output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.out.log"
with closing(open(output_log, 'a')) as log: echo "$input_command" >> $input_log
log.write("%s\n" % " ".join(full_command)) echo "$mode ${full_command[@]}" >> $output_log
fi
rcode = subprocess.call(full_command) exec "${full_command[@]}"
sys.exit(rcode)

View file

@ -48,12 +48,11 @@
# set_build_environment_variables and used to pass parameters to # set_build_environment_variables and used to pass parameters to
# Spack's compiler wrappers. # Spack's compiler wrappers.
# #
SPACK_LIB = 'SPACK_LIB'
SPACK_ENV_PATH = 'SPACK_ENV_PATH' SPACK_ENV_PATH = 'SPACK_ENV_PATH'
SPACK_DEPENDENCIES = 'SPACK_DEPENDENCIES' SPACK_DEPENDENCIES = 'SPACK_DEPENDENCIES'
SPACK_PREFIX = 'SPACK_PREFIX' SPACK_PREFIX = 'SPACK_PREFIX'
SPACK_DEBUG = 'SPACK_DEBUG' SPACK_DEBUG = 'SPACK_DEBUG'
SPACK_SPEC = 'SPACK_SPEC' SPACK_SHORT_SPEC = 'SPACK_SHORT_SPEC'
SPACK_DEBUG_LOG_DIR = 'SPACK_DEBUG_LOG_DIR' SPACK_DEBUG_LOG_DIR = 'SPACK_DEBUG_LOG_DIR'
@ -108,9 +107,6 @@ def set_compiler_environment_variables(pkg):
def set_build_environment_variables(pkg): def set_build_environment_variables(pkg):
"""This ensures a clean install environment when we build packages. """This ensures a clean install environment when we build packages.
""" """
# This tells the compiler script where to find the Spack installation.
os.environ[SPACK_LIB] = spack.lib_path
# Add spack build environment path with compiler wrappers first in # Add spack build environment path with compiler wrappers first in
# the path. We handle case sensitivity conflicts like "CC" and # the path. We handle case sensitivity conflicts like "CC" and
# "cc" by putting one in the <build_env_path>/case-insensitive # "cc" by putting one in the <build_env_path>/case-insensitive
@ -140,7 +136,7 @@ def set_build_environment_variables(pkg):
# Working directory for the spack command itself, for debug logs. # Working directory for the spack command itself, for debug logs.
if spack.debug: if spack.debug:
os.environ[SPACK_DEBUG] = "TRUE" os.environ[SPACK_DEBUG] = "TRUE"
os.environ[SPACK_SPEC] = str(pkg.spec) os.environ[SPACK_SHORT_SPEC] = pkg.spec.short_spec
os.environ[SPACK_DEBUG_LOG_DIR] = spack.spack_working_dir os.environ[SPACK_DEBUG_LOG_DIR] = spack.spack_working_dir
# Add dependencies to CMAKE_PREFIX_PATH # Add dependencies to CMAKE_PREFIX_PATH

View file

@ -31,7 +31,7 @@
import spack.compilers import spack.compilers
import spack.spec import spack.spec
import spack.config import spack.config
from spack.compilation import get_path from spack.util.environment import get_path
from spack.spec import CompilerSpec from spack.spec import CompilerSpec
description = "Manage compilers" description = "Manage compilers"

View file

@ -37,6 +37,10 @@ def setup_parser(subparser):
sp = subparser.add_subparsers( sp = subparser.add_subparsers(
metavar='SUBCOMMAND', dest='pkg_command') metavar='SUBCOMMAND', dest='pkg_command')
add_parser = sp.add_parser('add', help=pkg_add.__doc__)
add_parser.add_argument('packages', nargs=argparse.REMAINDER,
help="Names of packages to add to git repo.")
list_parser = sp.add_parser('list', help=pkg_list.__doc__) list_parser = sp.add_parser('list', help=pkg_list.__doc__)
list_parser.add_argument('rev', default='HEAD', nargs='?', list_parser.add_argument('rev', default='HEAD', nargs='?',
help="Revision to list packages for.") help="Revision to list packages for.")
@ -79,6 +83,16 @@ def list_packages(rev):
return sorted(line[len(relpath):] for line in output.split('\n') if line) return sorted(line[len(relpath):] for line in output.split('\n') if line)
def pkg_add(args):
for pkg_name in args.packages:
filename = spack.db.filename_for_package_name(pkg_name)
if not os.path.isfile(filename):
tty.die("No such package: %s. Path does not exist:" % pkg_name, filename)
git = get_git()
git('-C', spack.packages_path, 'add', filename)
def pkg_list(args): def pkg_list(args):
"""List packages associated with a particular spack git revision.""" """List packages associated with a particular spack git revision."""
colify(list_packages(args.rev)) colify(list_packages(args.rev))
@ -117,7 +131,8 @@ def pkg_added(args):
def pkg(parser, args): def pkg(parser, args):
action = { 'diff' : pkg_diff, action = { 'add' : pkg_add,
'diff' : pkg_diff,
'list' : pkg_list, 'list' : pkg_list,
'removed' : pkg_removed, 'removed' : pkg_removed,
'added' : pkg_added } 'added' : pkg_added }

View file

@ -1,117 +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://scalability-llnl.github.io/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
##############################################################################
"""\
The ``compilation`` module contains utility functions used by the compiler
wrapper script.
.. todo::
Think about moving this into the script to increase compilation
speed.
"""
import os
import sys
def get_env_var(name, required=True):
value = os.environ.get(name)
if required and value is None:
print "%s must be run from spack." % os.path.abspath(sys.argv[0])
sys.exit(1)
return value
def get_env_flag(name, required=False):
value = get_env_var(name, required)
if value:
return value.lower() == "true"
return False
def get_path(name):
path = os.environ.get(name, "").strip()
if path:
return path.split(":")
else:
return []
def parse_rpaths(arguments):
"""argparse, for all its features, cannot understand most compilers'
rpath arguments. This handles '-Wl,', '-Xlinker', and '-R'"""
def get_next(arg, args):
"""Get an expected next value of an iterator, or die if it's not there"""
try:
return next(args)
except StopIteration:
# quietly ignore -rpath and -Xlinker without args.
return None
other_args = []
def linker_args():
"""This generator function allows us to parse the linker args separately
from the compiler args, so that we can handle them more naturally.
"""
args = iter(arguments)
for arg in args:
if arg.startswith('-Wl,'):
sub_args = [sub for sub in arg.replace('-Wl,', '', 1).split(',')]
for arg in sub_args:
yield arg
elif arg == '-Xlinker':
target = get_next(arg, args)
if target is not None:
yield target
else:
other_args.append(arg)
# Extract all the possible ways rpath can appear in linker args, then
# append non-rpaths to other_args. This happens in-line as the linker
# args are extracted, so we preserve the original order of arguments.
# This is important for args like --whole-archive, --no-whole-archive,
# and others that tell the linker how to handle the next few libraries
# it encounters on the command line.
rpaths = []
largs = linker_args()
for arg in largs:
if arg == '-rpath':
target = get_next(arg, largs)
if target is not None:
rpaths.append(target)
elif arg.startswith('-R'):
target = arg.replace('-R', '', 1)
if not target:
target = get_next(arg, largs)
if target is None: break
if os.path.isdir(target):
rpaths.append(target)
else:
other_args.extend(['-Wl,' + arg, '-Wl,' + target])
else:
other_args.append('-Wl,' + arg)
return rpaths, other_args

View file

@ -35,8 +35,8 @@
import spack.spec import spack.spec
from spack.util.multiproc import parmap from spack.util.multiproc import parmap
from spack.util.executable import * from spack.util.executable import *
from spack.util.environment import get_path
from spack.version import Version from spack.version import Version
from spack.compilation import get_path
__all__ = ['Compiler', 'get_compiler_version'] __all__ = ['Compiler', 'get_compiler_version']

View file

@ -40,7 +40,7 @@
from spack.compiler import Compiler from spack.compiler import Compiler
from spack.util.executable import which from spack.util.executable import which
from spack.util.naming import mod_to_class from spack.util.naming import mod_to_class
from spack.compilation import get_path from spack.util.environment import get_path
_imported_compilers_module = 'spack.compilers' _imported_compilers_module = 'spack.compilers'
_required_instance_vars = ['cc', 'cxx', 'f77', 'fc'] _required_instance_vars = ['cc', 'cxx', 'f77', 'fc']

View file

@ -53,7 +53,8 @@
'svn_fetch', 'svn_fetch',
'hg_fetch', 'hg_fetch',
'mirror', 'mirror',
'url_extrapolate'] 'url_extrapolate',
'cc']
def list_tests(): def list_tests():

130
lib/spack/spack/test/cc.py Normal file
View file

@ -0,0 +1,130 @@
##############################################################################
# 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://scalability-llnl.github.io/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
##############################################################################
"""
This test checks that the Spack cc compiler wrapper is parsing
arguments correctly.
"""
import os
import unittest
from llnl.util.filesystem import *
import spack
from spack.util.executable import *
# Complicated compiler test command
test_command = [
'-I/test/include', '-L/test/lib', '-L/other/lib', '-I/other/include',
'arg1',
'-Wl,--start-group',
'arg2',
'-Wl,-rpath=/first/rpath', 'arg3', '-Wl,-rpath', '-Wl,/second/rpath',
'-llib1', '-llib2',
'arg4',
'-Wl,--end-group',
'-Xlinker,-rpath', '-Xlinker,/third/rpath', '-Xlinker,-rpath=/fourth/rpath',
'-llib3', '-llib4',
'arg5', 'arg6']
class CompilerTest(unittest.TestCase):
def setUp(self):
self.cc = Executable(join_path(spack.build_env_path, "cc"))
self.ld = Executable(join_path(spack.build_env_path, "ld"))
self.cpp = Executable(join_path(spack.build_env_path, "cpp"))
os.environ['SPACK_CC'] = "/bin/mycc"
os.environ['SPACK_PREFIX'] = "/usr"
os.environ['SPACK_ENV_PATH']="test"
os.environ['SPACK_DEBUG_LOG_DIR'] = "."
os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7"
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2"
def check_cc(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.cc(*args, return_output=True).strip(), expected)
def check_ld(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.ld(*args, return_output=True).strip(), expected)
def check_cpp(self, command, args, expected):
os.environ['SPACK_TEST_COMMAND'] = command
self.assertEqual(self.cpp(*args, return_output=True).strip(), expected)
def test_vcheck_mode(self):
self.check_cc('dump-mode', ['-I/include', '--version'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-V'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-v'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-dumpversion'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '--version', '-c'], "vcheck")
self.check_cc('dump-mode', ['-I/include', '-V', '-o', 'output'], "vcheck")
def test_cpp_mode(self):
self.check_cc('dump-mode', ['-E'], "cpp")
self.check_cpp('dump-mode', [], "cpp")
def test_ccld_mode(self):
self.check_cc('dump-mode', [], "ccld")
self.check_cc('dump-mode', ['foo.c', '-o', 'foo'], "ccld")
self.check_cc('dump-mode', ['foo.c', '-o', 'foo', '-Wl,-rpath=foo'], "ccld")
self.check_cc('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath=foo'], "ccld")
def test_ld_mode(self):
self.check_ld('dump-mode', [], "ld")
self.check_ld('dump-mode', ['foo.o', 'bar.o', 'baz.o', '-o', 'foo', '-Wl,-rpath=foo'], "ld")
def test_includes(self):
self.check_cc('dump-includes', test_command,
"\n".join(["/test/include", "/other/include"]))
def test_libraries(self):
self.check_cc('dump-libraries', test_command,
"\n".join(["/test/lib", "/other/lib"]))
def test_libs(self):
self.check_cc('dump-libs', test_command,
"\n".join(["lib1", "lib2", "lib3", "lib4"]))
def test_rpaths(self):
self.check_cc('dump-rpaths', test_command,
"\n".join(["/first/rpath", "/second/rpath", "/third/rpath", "/fourth/rpath"]))
def test_other_args(self):
self.check_cc('dump-other-args', test_command,
"\n".join(["arg1", "-Wl,--start-group", "arg2", "arg3", "arg4",
"-Wl,--end-group", "arg5", "arg6"]))

View file

@ -45,7 +45,6 @@ class PythonVersionTest(unittest.TestCase):
def spack_python_files(self): def spack_python_files(self):
# first file is the spack script. # first file is the spack script.
yield spack.spack_file yield spack.spack_file
yield os.path.join(spack.build_env_path, 'cc')
# Next files are all the source files and package files. # Next files are all the source files and package files.
search_paths = [spack.lib_path, spack.var_path] search_paths = [spack.lib_path, spack.var_path]

View file

@ -24,6 +24,15 @@
############################################################################## ##############################################################################
import os import os
def get_path(name):
path = os.environ.get(name, "").strip()
if path:
return path.split(":")
else:
return []
def env_flag(name): def env_flag(name):
if name in os.environ: if name in os.environ:
return os.environ[name].lower() == "true" return os.environ[name].lower() == "true"

View file

@ -0,0 +1,19 @@
from spack import *
class Bzip2(Package):
"""bzip2 is a freely available, patent free high-quality data
compressor. It typically compresses files to within 10% to 15%
of the best available techniques (the PPM family of statistical
compressors), whilst being around twice as fast at compression
and six times faster at decompression."""
homepage = "http://www.bzip.org"
url = "http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz"
version('1.0.6', '00b516f4704d4a7cb50a1d97e6e8e15b')
def install(self, spec, prefix):
# No configure system -- have to filter the makefile for this package.
filter_file(r'CC=gcc', 'CC=cc', 'Makefile', string=True)
make()
make("install", "PREFIX=%s" % prefix)

View file

@ -0,0 +1,16 @@
from spack import *
class Libffi(Package):
"""The libffi library provides a portable, high level programming
interface to various calling conventions. This allows a programmer
to call any function specified by a call interface description at
run time."""
homepage = "https://sourceware.org/libffi/"
url = "ftp://sourceware.org/pub/libffi/libffi-3.1.tar.gz"
version('3.1', 'f5898b29bbfd70502831a212d9249d10')
def install(self, spec, prefix):
configure("--prefix=%s" % prefix)
make()
make("install")

View file

@ -10,10 +10,14 @@ class Ncurses(Package):
homepage = "http://invisible-island.net/ncurses/ncurses.html" homepage = "http://invisible-island.net/ncurses/ncurses.html"
version('5.9', '8cb9c412e5f2d96bc6f459aa8c6282a1', version('5.9', '8cb9c412e5f2d96bc6f459aa8c6282a1',
url='http://invisible-island.net/datafiles/release/ncurses.tar.gz') url='http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.9.tar.gz')
def install(self, spec, prefix): def install(self, spec, prefix):
configure("--prefix=%s" % prefix) configure("--prefix=%s" % prefix,
"--with-shared",
"--enable-widec",
"--enable-pc-files",
"--without-ada")
make() make()
make("install") make("install")

View file

@ -0,0 +1,25 @@
from spack import *
class Python(Package):
"""The Python programming language."""
homepage = "http://www.python.org"
url = "http://www.python.org/ftp/python/2.7.8/Python-2.7.8.tar.xz"
version('2.7.8', 'd235bdfa75b8396942e360a70487ee00')
depends_on("openssl")
depends_on("bzip2")
depends_on("readline")
depends_on("ncurses")
depends_on("sqlite")
def install(self, spec, prefix):
# Need this to allow python build to find the Python installation.
env['PYTHONHOME'] = prefix
# Rest of install is pretty standard.
configure("--prefix=%s" % prefix,
"--with-threads",
"--enable-shared")
make()
make("install")

View file

@ -0,0 +1,21 @@
from spack import *
class Readline(Package):
"""The GNU Readline library provides a set of functions for use by
applications that allow users to edit command li nes as they
are typed in. Both Emacs and vi editing modes are
available. The Readline library includes additional functions
to maintain a list of previously-entered command lines, to
recall and perhaps reedit those lines, and perform csh-like
history expansion on previous commands. """
homepage = "http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html"
url = "ftp://ftp.cwru.edu/pub/bash/readline-6.3.tar.gz"
version('6.3', '33c8fb279e981274f485fd91da77e94a')
depends_on("ncurses")
def install(self, spec, prefix):
configure("--prefix=%s" % prefix)
make("SHLIB_LIBS=-lncurses")
make("install")