summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2014-11-02 23:53:45 -0800
committerTodd Gamblin <tgamblin@llnl.gov>2014-11-03 14:12:16 -0800
commit0f3b80cddbfd775c10f68423444aca792525f856 (patch)
tree2c0d62d062de4b0ed1f79bba8d43bf60ccac8cee /lib
parent1656f62a125232b30235da01e816a3ade4481b8a (diff)
downloadspack-0f3b80cddbfd775c10f68423444aca792525f856.tar.gz
spack-0f3b80cddbfd775c10f68423444aca792525f856.tar.bz2
spack-0f3b80cddbfd775c10f68423444aca792525f856.tar.xz
spack-0f3b80cddbfd775c10f68423444aca792525f856.zip
Fix for SPACK-11: Spack compiler wrapper is now in bash.
- Startup is much faster - Added test for compiler wrapper parsing. - Removed old compilation module that had to be imported by old cc. - Removed cc from python version checks now that it's bash.
Diffstat (limited to 'lib')
-rwxr-xr-xlib/spack/env/cc466
-rw-r--r--lib/spack/spack/build_environment.py8
-rw-r--r--lib/spack/spack/cmd/compiler.py2
-rw-r--r--lib/spack/spack/compilation.py117
-rw-r--r--lib/spack/spack/compiler.py2
-rw-r--r--lib/spack/spack/compilers/__init__.py2
-rw-r--r--lib/spack/spack/test/__init__.py3
-rw-r--r--lib/spack/spack/test/cc.py130
-rw-r--r--lib/spack/spack/test/python_version.py1
-rw-r--r--lib/spack/spack/util/environment.py9
10 files changed, 472 insertions, 268 deletions
diff --git a/lib/spack/env/cc b/lib/spack/env/cc
index 266e41cb48..f68cb0b2cd 100755
--- a/lib/spack/env/cc
+++ b/lib/spack/env/cc
@@ -1,140 +1,326 @@
-#!/usr/bin/env python
-import sys
-if not sys.version_info[:2] >= (2,6):
- sys.exit("Spack requires Python 2.6. Version was %s." % sys.version_info)
-
-import os
-import re
-import subprocess
-from contextlib import closing
-
-# Import spack parameters through the build environment.
-spack_lib = os.environ.get("SPACK_LIB")
-if not spack_lib:
- print "Spack compiler must be run from spack!"
- sys.exit(1)
-
-# Grab a minimal set of spack packages
-sys.path.append(spack_lib)
-from spack.compilation import *
-from external import argparse
-import llnl.util.tty as tty
-
-spack_prefix = get_env_var("SPACK_PREFIX")
-spack_debug = get_env_flag("SPACK_DEBUG")
-spack_deps = get_path("SPACK_DEPENDENCIES")
-spack_env_path = get_path("SPACK_ENV_PATH")
-spack_debug_log_dir = get_env_var("SPACK_DEBUG_LOG_DIR")
-spack_spec = get_env_var("SPACK_SPEC")
-
-compiler_spec = get_env_var("SPACK_COMPILER_SPEC")
-spack_cc = get_env_var("SPACK_CC", required=False)
-spack_cxx = get_env_var("SPACK_CXX", required=False)
-spack_f77 = get_env_var("SPACK_F77", required=False)
-spack_fc = get_env_var("SPACK_FC", required=False)
-
-# Figure out what type of operation we're doing
-command = os.path.basename(sys.argv[0])
-
-cpp, cc, ccld, ld, version_check = range(5)
-
-if command == 'cpp':
- mode = cpp
-elif command == 'ld':
- mode = ld
-elif '-E' in sys.argv:
- mode = cpp
-elif '-c' in sys.argv:
- mode = cc
-else:
- mode = ccld
-
-
-if command in ('cc', 'gcc', 'c89', 'c99', 'clang'):
- command = spack_cc
- language = "C"
-elif command in ('c++', 'CC', 'g++', 'clang++'):
- command = spack_cxx
- language = "C++"
-elif command in ('f77'):
- command = spack_f77
- language = "Fortran 77"
-elif command in ('fc', 'f90', 'f95'):
- 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:
- print "ERROR: Compiler '%s' does not support compiling %s programs." % (
- compiler_spec, language)
- sys.exit(1)
-
-version_args = ['-V', '-v', '--version', '-dumpversion']
-if any(arg in sys.argv for arg in version_args):
- mode = version_check
-
-# Parse out the includes, libs, etc. so we can adjust them if need be.
-parser = argparse.ArgumentParser(add_help=False)
-parser.add_argument("-I", action='append', default=[], dest='include_path')
-parser.add_argument("-L", action='append', default=[], dest='lib_path')
-parser.add_argument("-l", action='append', default=[], dest='libs')
-
-options, other_args = parser.parse_known_args()
-rpaths, other_args = parse_rpaths(other_args)
-
-# Add dependencies' include and lib paths to our compiler flags.
-def add_if_dir(path_list, directory, index=None):
- if os.path.isdir(directory):
- if index is None:
- path_list.append(directory)
- else:
- path_list.insert(index, directory)
-
-for dep_dir in spack_deps:
- add_if_dir(options.include_path, os.path.join(dep_dir, "include"))
- add_if_dir(options.lib_path, os.path.join(dep_dir, "lib"))
- add_if_dir(options.lib_path, os.path.join(dep_dir, "lib64"))
-
-# Add our modified arguments to it.
-arguments = ['-I%s' % path for path in options.include_path]
-arguments += other_args
-arguments += ['-L%s' % path for path in options.lib_path]
-arguments += ['-l%s' % path for path in options.libs]
-
-# Add rpaths to install dir and its dependencies. We add both lib and lib64
-# here because we don't know which will be created.
-rpaths.extend(options.lib_path)
-rpaths.append('%s/lib' % spack_prefix)
-rpaths.append('%s/lib64' % spack_prefix)
-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"]:
- if var in os.environ:
- os.environ.pop(var)
-
-# Ensure that the delegated command doesn't just call this script again.
-remove_paths = ['.'] + spack_env_path
-path = [p for p in get_path("PATH") if p not in remove_paths]
-os.environ["PATH"] = ":".join(path)
-
-full_command = [command] + arguments
-
-if spack_debug:
- input_log = os.path.join(spack_debug_log_dir, 'spack-cc-%s.in.log' % spack_spec)
- output_log = os.path.join(spack_debug_log_dir, 'spack-cc-%s.out.log' % spack_spec)
- with closing(open(input_log, 'a')) as log:
- args = [os.path.basename(sys.argv[0])] + sys.argv[1:]
- log.write("%s\n" % " ".join(arg.replace(' ', r'\ ') for arg in args))
- with closing(open(output_log, 'a')) as log:
- log.write("%s\n" % " ".join(full_command))
-
-rcode = subprocess.call(full_command)
-sys.exit(rcode)
+#!/bin/bash
+##############################################################################
+# 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
+##############################################################################
+#
+# 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.
+#
+
+# This is the list 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"
+
+# The compiler input variables are checked for sanity later:
+# SPACK_CC, SPACK_CXX, SPACK_F77, SPACK_FC
+# Debug flag is optional; set to true for debug logging:
+# SPACK_DEBUG
+# Test command is used to unit test the compiler script.
+# SPACK_TEST_COMMAND
+# Dependencies can be empty for pkgs with no deps:
+# SPACK_DEPENDENCIES
+
+# die()
+# Prints a message and exits with error 1.
+function die {
+ echo "$@"
+ exit 1
+}
+
+for param in $parameters; do
+ if [ -z "${!param}" ]; then
+ die "Spack compiler must be run from spack! Input $param was missing!"
+ fi
+done
+
+#
+# Figure out the type of compiler, the language, and the mode so that
+# the compiler script knows what to do.
+#
+# 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
+
+# Finish setting up the mode.
+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
+
+# Dump the version and exist if we're in testing mode.
+if [ "$SPACK_TEST_COMMAND" = "dump-mode" ]; then
+ echo "$mode"
+ exit
+fi
+
+# Check that at least one of the real commands was actually selected,
+# otherwise we don't know what to execute.
+if [ -z "$command" ]; then
+ die "ERROR: Compiler '$SPACK_COMPILER_SPEC' does not support compiling $language programs."
+fi
+
+# Save original command for debug logging
+input_command="$@"
+
+#
+# Now do real parsing of the command line args, trying hard to keep
+# non-rpath linker arguments in the proper order w.r.t. other command
+# line arguments. This is important for things like groups.
+#
+includes=()
+libraries=()
+libs=()
+rpaths=()
+other_args=()
+
+while [ -n "$1" ]; do
+ case "$1" in
+ -I*)
+ arg="${1#-I}"
+ if [ -z "$arg" ]; then shift; arg="$1"; fi
+ includes+=("$arg")
+ ;;
+ -L*)
+ arg="${1#-L}"
+ if [ -z "$arg" ]; then shift; arg="$1"; fi
+ libraries+=("$arg")
+ ;;
+ -l*)
+ arg="${1#-l}"
+ if [ -z "$arg" ]; then shift; arg="$1"; fi
+ libs+=("$arg")
+ ;;
+ -Wl,*)
+ arg="${1#-Wl,}"
+ 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
+
+# Dump parsed values for unit testing if asked for
+if [ -n "$SPACK_TEST_COMMAND" ]; then
+ IFS=$'\n'
+ case "$SPACK_TEST_COMMAND" in
+ dump-includes) echo "${includes[*]}";;
+ dump-libraries) echo "${libraries[*]}";;
+ dump-libs) echo "${libs[*]}";;
+ dump-rpaths) echo "${rpaths[*]}";;
+ dump-other-args) echo "${other_args[*]}";;
+ dump-all)
+ echo "INCLUDES:"
+ echo "${includes[*]}"
+ echo
+ echo "LIBRARIES:"
+ echo "${libraries[*]}"
+ echo
+ echo "LIBS:"
+ echo "${libs[*]}"
+ echo
+ echo "RPATHS:"
+ echo "${rpaths[*]}"
+ echo
+ echo "ARGS:"
+ echo "${other_args[*]}"
+ ;;
+ *)
+ echo "ERROR: Unknown test command"
+ exit 1 ;;
+ esac
+ exit
+fi
+
+# Read spack dependencies from the path environment variable
+IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES"
+for dep in "${deps[@]}"; do
+ if [ -d "$dep/include" ]; then
+ includes+=("$dep/include")
+ fi
+
+ if [ -d "$dep/lib" ]; then
+ libraries+=("$dep/lib")
+ rpaths+=("$dep/lib")
+ fi
+
+ if [ -d "$dep/lib64" ]; then
+ libraries+=("$dep/lib64")
+ rpaths+=("$dep/lib64")
+ fi
+done
+
+# Include all -L's and prefix/whatever dirs in rpath
+for dir in "${libraries[@]}"; do
+ [ "$dir" != "." ] && rpaths+=("$dir")
+done
+rpaths+=("$SPACK_PREFIX/lib")
+rpaths+=("$SPACK_PREFIX/lib64")
+
+# Put the arguments together
+args=()
+for dir in "${includes[@]}"; do args+=("-I$dir"); done
+args+=("${other_args[@]}")
+for dir in "${libraries[@]}"; do args+=("-L$dir"); done
+for lib in "${libs[@]}"; do args+=("-l$lib"); done
+
+if [ "$mode" = ccld ]; then
+ for dir in "${rpaths[@]}"; do args+=("-Wl,-rpath=$dir"); done
+elif [ "$mode" = ld ]; then
+ for dir in "${rpaths[@]}"; do args+=("-rpath=$dir"); done
+fi
+
+#
+# Unset pesky environment variables that could affect build sanity.
+#
+unset LD_LIBRARY_PATH
+unset LD_RUN_PATH
+unset DYLD_LIBRARY_PATH
+
+#
+# Filter '.' and Spack environment directories out of PATH so that
+# this script doesn't just call itself
+#
+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")
+full_command+=("${args[@]}")
+
+#
+# Write the input and output commands to debug logs if it's asked for.
+#
+if [ "$SPACK_DEBUG" = "TRUE" ]; then
+ input_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.in.log"
+ output_log="$SPACK_DEBUG_LOG_DIR/spack-cc-$SPACK_SHORT_SPEC.out.log"
+ echo "$input_command" >> $input_log
+ echo "$mode ${full_command[@]}" >> $output_log
+fi
+
+exec "${full_command[@]}"
diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py
index b71c543e5d..a2fcff1f10 100644
--- a/lib/spack/spack/build_environment.py
+++ b/lib/spack/spack/build_environment.py
@@ -48,12 +48,11 @@ SPACK_NO_PARALLEL_MAKE = 'SPACK_NO_PARALLEL_MAKE'
# set_build_environment_variables and used to pass parameters to
# Spack's compiler wrappers.
#
-SPACK_LIB = 'SPACK_LIB'
SPACK_ENV_PATH = 'SPACK_ENV_PATH'
SPACK_DEPENDENCIES = 'SPACK_DEPENDENCIES'
SPACK_PREFIX = 'SPACK_PREFIX'
SPACK_DEBUG = 'SPACK_DEBUG'
-SPACK_SPEC = 'SPACK_SPEC'
+SPACK_SHORT_SPEC = 'SPACK_SHORT_SPEC'
SPACK_DEBUG_LOG_DIR = 'SPACK_DEBUG_LOG_DIR'
@@ -108,9 +107,6 @@ def set_compiler_environment_variables(pkg):
def set_build_environment_variables(pkg):
"""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
# the path. We handle case sensitivity conflicts like "CC" and
# "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.
if spack.debug:
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
# Add dependencies to CMAKE_PREFIX_PATH
diff --git a/lib/spack/spack/cmd/compiler.py b/lib/spack/spack/cmd/compiler.py
index ac9c844a4c..5c46a3536d 100644
--- a/lib/spack/spack/cmd/compiler.py
+++ b/lib/spack/spack/cmd/compiler.py
@@ -31,7 +31,7 @@ from llnl.util.lang import index_by
import spack.compilers
import spack.spec
import spack.config
-from spack.compilation import get_path
+from spack.util.environment import get_path
from spack.spec import CompilerSpec
description = "Manage compilers"
diff --git a/lib/spack/spack/compilation.py b/lib/spack/spack/compilation.py
deleted file mode 100644
index 3a469376a8..0000000000
--- a/lib/spack/spack/compilation.py
+++ /dev/null
@@ -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
diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
index 8debf518c7..646050d267 100644
--- a/lib/spack/spack/compiler.py
+++ b/lib/spack/spack/compiler.py
@@ -35,8 +35,8 @@ import spack.error
import spack.spec
from spack.util.multiproc import parmap
from spack.util.executable import *
+from spack.util.environment import get_path
from spack.version import Version
-from spack.compilation import get_path
__all__ = ['Compiler', 'get_compiler_version']
diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py
index 467472cced..e572cd89b6 100644
--- a/lib/spack/spack/compilers/__init__.py
+++ b/lib/spack/spack/compilers/__init__.py
@@ -40,7 +40,7 @@ from spack.util.multiproc import parmap
from spack.compiler import Compiler
from spack.util.executable import which
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'
_required_instance_vars = ['cc', 'cxx', 'f77', 'fc']
diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py
index 9eae3261c2..c6a371fd0d 100644
--- a/lib/spack/spack/test/__init__.py
+++ b/lib/spack/spack/test/__init__.py
@@ -53,7 +53,8 @@ test_names = ['versions',
'svn_fetch',
'hg_fetch',
'mirror',
- 'url_extrapolate']
+ 'url_extrapolate',
+ 'cc']
def list_tests():
diff --git a/lib/spack/spack/test/cc.py b/lib/spack/spack/test/cc.py
new file mode 100644
index 0000000000..aa16f9b351
--- /dev/null
+++ b/lib/spack/spack/test/cc.py
@@ -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"]))
diff --git a/lib/spack/spack/test/python_version.py b/lib/spack/spack/test/python_version.py
index 04b4eadf34..f814df3226 100644
--- a/lib/spack/spack/test/python_version.py
+++ b/lib/spack/spack/test/python_version.py
@@ -45,7 +45,6 @@ class PythonVersionTest(unittest.TestCase):
def spack_python_files(self):
# first file is the spack script.
yield spack.spack_file
- yield os.path.join(spack.build_env_path, 'cc')
# Next files are all the source files and package files.
search_paths = [spack.lib_path, spack.var_path]
diff --git a/lib/spack/spack/util/environment.py b/lib/spack/spack/util/environment.py
index 435d912185..afdf51c707 100644
--- a/lib/spack/spack/util/environment.py
+++ b/lib/spack/spack/util/environment.py
@@ -24,6 +24,15 @@
##############################################################################
import os
+
+def get_path(name):
+ path = os.environ.get(name, "").strip()
+ if path:
+ return path.split(":")
+ else:
+ return []
+
+
def env_flag(name):
if name in os.environ:
return os.environ[name].lower() == "true"