spack/lib/spack/env/cc

269 lines
7.9 KiB
Plaintext
Raw Normal View History

#!/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://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
##############################################################################
#
# 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
2016-03-18 09:53:13 +08:00
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:
2016-03-18 09:53:13 +08:00
# cpp preprocess
# cc compile
2016-03-18 09:53:13 +08:00
# as assemble
# ld link
# ccld compile & link
# vcheck version check
command=$(basename "$0")
case "$command" in
2016-04-05 02:33:48 +08:00
cpp)
mode=cpp
;;
cc|c89|c99|gcc|clang|icc|pgcc|xlc)
command="$SPACK_CC"
language="C"
;;
2016-03-04 06:50:51 +08:00
c++|CC|g++|clang++|icpc|pgc++|xlc++)
command="$SPACK_CXX"
language="C++"
;;
2016-03-04 06:50:51 +08:00
f90|fc|f95|gfortran|ifort|pgfortran|xlf90|nagfor)
command="$SPACK_FC"
language="Fortran 90"
;;
2016-03-04 06:50:51 +08:00
f77|gfortran|ifort|pgfortran|xlf|nagfor)
command="$SPACK_F77"
language="Fortran 77"
;;
ld)
mode=ld
;;
*)
die "Unkown compiler: $command"
;;
esac
# If any of the arguments below is present then the mode is vcheck. In
2016-04-05 02:33:48 +08:00
# vcheck mode, nothing is added in terms of extra search paths or
# libraries.
if [[ -z $mode ]]; then
for arg in "$@"; do
2016-04-05 02:33:48 +08:00
if [[ $arg = -v || $arg = -V || $arg = --version || $arg = -dumpversion ]]; then
mode=vcheck
break
2016-03-10 21:35:09 +08:00
fi
done
fi
# Finish setting up the mode.
2016-04-05 02:33:48 +08:00
if [[ -z $mode ]]; then
mode=ccld
for arg in "$@"; do
2016-04-05 02:33:48 +08:00
if [[ $arg = -E ]]; then
mode=cpp
break
2016-04-05 02:33:48 +08:00
elif [[ $arg = -S ]]; then
2016-03-18 09:53:13 +08:00
mode=as
break
2016-04-05 02:33:48 +08:00
elif [[ $arg = -c ]]; then
mode=cc
break
fi
done
fi
2016-03-02 05:53:53 +08:00
# Dump the version and exit if we're in testing mode.
2016-04-05 02:33:48 +08:00
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.
2016-03-18 09:53:13 +08:00
if [[ -z $command ]]; then
die "ERROR: Compiler '$SPACK_COMPILER_SPEC' does not support compiling $language programs."
fi
2016-04-05 02:33:48 +08:00
if [[ $mode == vcheck ]]; then
2016-03-18 09:53:13 +08:00
exec ${command} "$@"
fi
2016-04-05 02:33:48 +08:00
# Darwin's linker has a -r argument that merges object files together.
# It doesn't work with -rpath.
# This variable controls whether they are added.
add_rpaths=true
if [[ mode = ld && $OSTYPE = darwin* ]]; then
for arg in "$@"; do
if [[ $arg = -r ]]; then
add_rpaths=false
break
fi
done
fi
# Save original command for debug logging
input_command="$@"
2015-12-21 23:21:33 +08:00
args=("$@")
# Read spack dependencies from the path environment variable
IFS=':' read -ra deps <<< "$SPACK_DEPENDENCIES"
for dep in "${deps[@]}"; do
# Prepend include directories
2016-03-18 09:53:13 +08:00
if [[ -d $dep/include ]]; then
if [[ $mode = cpp || $mode = cc || $mode = as || $mode = ccld ]]; then
args=("-I$dep/include" "${args[@]}")
fi
fi
# Prepend lib and RPATH directories
2016-03-18 09:53:13 +08:00
if [[ -d $dep/lib ]]; then
2015-12-23 04:49:14 +08:00
if [[ $mode = ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$dep/lib" "${args[@]}")
args=("-L$dep/lib" "${args[@]}")
2015-12-21 23:21:33 +08:00
elif [[ $mode = ld ]]; then
$add_rpaths && args=("-rpath" "$dep/lib" "${args[@]}")
args=("-L$dep/lib" "${args[@]}")
2015-12-21 23:21:33 +08:00
fi
fi
# Prepend lib64 and RPATH directories
2016-03-18 09:53:13 +08:00
if [[ -d $dep/lib64 ]]; then
2015-12-21 23:21:33 +08:00
if [[ $mode = ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$dep/lib64" "${args[@]}")
args=("-L$dep/lib64" "${args[@]}")
2015-12-21 23:21:33 +08:00
elif [[ $mode = ld ]]; then
$add_rpaths && args=("-rpath" "$dep/lib64" "${args[@]}")
args=("-L$dep/lib64" "${args[@]}")
2015-12-21 23:21:33 +08:00
fi
fi
done
# Include all -L's and prefix/whatever dirs in rpath
2015-12-21 23:21:33 +08:00
if [[ $mode = ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$SPACK_PREFIX/lib" "-Wl,-rpath,$SPACK_PREFIX/lib64" "${args[@]}")
2015-12-21 23:21:33 +08:00
elif [[ $mode = ld ]]; then
$add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "-rpath" "$SPACK_PREFIX/lib64" "${args[@]}")
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"
2015-12-21 23:21:33 +08:00
spack_env_dirs+=("" ".")
PATH=""
for dir in "${env_path[@]}"; do
2016-04-05 02:33:48 +08:00
addpath=true
for env_dir in "${spack_env_dirs[@]}"; do
if [[ $dir = $env_dir ]]; then
addpath=false
break
fi
done
2016-04-05 02:33:48 +08:00
if $addpath; then
2016-03-18 09:53:13 +08:00
PATH="${PATH:+$PATH:}$dir"
fi
done
export PATH
2016-03-18 09:53:13 +08:00
full_command=("$command" "${args[@]}")
# In test command mode, write out full command for Spack tests.
if [[ $SPACK_TEST_COMMAND = dump-args ]]; then
echo "${full_command[@]}"
exit
elif [[ -n $SPACK_TEST_COMMAND ]]; then
die "ERROR: Unknown test command"
fi
#
# Write the input and output commands to debug logs if it's asked for.
#
2016-03-18 09:53:13 +08:00
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
fi
exec "${full_command[@]}"