Merge pull request #905 from adamjstewart/features/rpath_flag

Allow compilers to specify their own rpath linking flags
This commit is contained in:
Todd Gamblin 2016-05-10 01:56:49 -07:00
commit 42edb6840e
6 changed files with 80 additions and 23 deletions

View File

@ -1803,15 +1803,15 @@ Compile-time library search paths
* ``-L$dep_prefix/lib`` * ``-L$dep_prefix/lib``
* ``-L$dep_prefix/lib64`` * ``-L$dep_prefix/lib64``
Runtime library search paths (RPATHs) Runtime library search paths (RPATHs)
* ``-Wl,-rpath,$dep_prefix/lib`` * ``$rpath_flag$dep_prefix/lib``
* ``-Wl,-rpath,$dep_prefix/lib64`` * ``$rpath_flag$dep_prefix/lib64``
Include search paths Include search paths
* ``-I$dep_prefix/include`` * ``-I$dep_prefix/include``
An example of this would be the ``libdwarf`` build, which has one An example of this would be the ``libdwarf`` build, which has one
dependency: ``libelf``. Every call to ``cc`` in the ``libdwarf`` dependency: ``libelf``. Every call to ``cc`` in the ``libdwarf``
build will have ``-I$LIBELF_PREFIX/include``, build will have ``-I$LIBELF_PREFIX/include``,
``-L$LIBELF_PREFIX/lib``, and ``-Wl,-rpath,$LIBELF_PREFIX/lib`` ``-L$LIBELF_PREFIX/lib``, and ``$rpath_flag$LIBELF_PREFIX/lib``
inserted on the command line. This is done transparently to the inserted on the command line. This is done transparently to the
project's build system, which will just think it's using a system project's build system, which will just think it's using a system
where ``libelf`` is readily available. Because of this, you **do where ``libelf`` is readily available. Because of this, you **do
@ -1831,6 +1831,14 @@ successfully find ``libdwarf.h`` and ``libdwarf.so``, without the
packager having to provide ``--with-libdwarf=/path/to/libdwarf`` on packager having to provide ``--with-libdwarf=/path/to/libdwarf`` on
the command line. the command line.
.. note::
For most compilers, ``$rpath_flag`` is ``-Wl,-rpath,``. However, NAG
passes its flags to GCC instead of passing them directly to the linker.
Therefore, its ``$rpath_flag`` is doubly wrapped: ``-Wl,-Wl,,-rpath,``.
``$rpath_flag`` can be overriden on a compiler specific basis in
``lib/spack/spack/compilers/$compiler.py``.
Compiler flags Compiler flags
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
In rare circumstances such as compiling and running small unit tests, a package In rare circumstances such as compiling and running small unit tests, a package
@ -1848,8 +1856,6 @@ package supports additional variants like
variant('openmp', default=True, description="Enable OpenMP support.") variant('openmp', default=True, description="Enable OpenMP support.")
Message Parsing Interface (MPI) Message Parsing Interface (MPI)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is common for high performance computing software/packages to use ``MPI``. It is common for high performance computing software/packages to use ``MPI``.

39
lib/spack/env/cc vendored
View File

@ -38,15 +38,20 @@
# -Wl,-rpath 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 # This is an array of environment variables that need to be set before
# the script runs. They are set by routines in spack.build_environment # the script runs. They are set by routines in spack.build_environment
# as part of spack.package.Package.do_install(). # as part of spack.package.Package.do_install().
parameters=" parameters=(
SPACK_PREFIX SPACK_PREFIX
SPACK_ENV_PATH SPACK_ENV_PATH
SPACK_DEBUG_LOG_DIR SPACK_DEBUG_LOG_DIR
SPACK_COMPILER_SPEC SPACK_COMPILER_SPEC
SPACK_SHORT_SPEC" SPACK_CC_RPATH_ARG
SPACK_CXX_RPATH_ARG
SPACK_F77_RPATH_ARG
SPACK_FC_RPATH_ARG
SPACK_SHORT_SPEC
)
# The compiler input variables are checked for sanity later: # The compiler input variables are checked for sanity later:
# SPACK_CC, SPACK_CXX, SPACK_F77, SPACK_FC # SPACK_CC, SPACK_CXX, SPACK_F77, SPACK_FC
@ -64,7 +69,7 @@ function die {
exit 1 exit 1
} }
for param in $parameters; do for param in ${parameters[@]}; do
if [[ -z ${!param} ]]; then if [[ -z ${!param} ]]; then
die "Spack compiler must be run from Spack! Input '$param' is missing." die "Spack compiler must be run from Spack! Input '$param' is missing."
fi fi
@ -85,6 +90,7 @@ done
# ccld compile & link # ccld compile & link
command=$(basename "$0") command=$(basename "$0")
comp="CC"
case "$command" in case "$command" in
cpp) cpp)
mode=cpp mode=cpp
@ -92,18 +98,22 @@ case "$command" in
cc|c89|c99|gcc|clang|icc|pgcc|xlc) cc|c89|c99|gcc|clang|icc|pgcc|xlc)
command="$SPACK_CC" command="$SPACK_CC"
language="C" language="C"
comp="CC"
;; ;;
c++|CC|g++|clang++|icpc|pgc++|xlc++) c++|CC|g++|clang++|icpc|pgc++|xlc++)
command="$SPACK_CXX" command="$SPACK_CXX"
language="C++" language="C++"
comp="CXX"
;; ;;
f90|fc|f95|gfortran|ifort|pgfortran|xlf90|nagfor) f90|fc|f95|gfortran|ifort|pgfortran|xlf90|nagfor)
command="$SPACK_FC" command="$SPACK_FC"
language="Fortran 90" language="Fortran 90"
comp="FC"
;; ;;
f77|gfortran|ifort|pgfortran|xlf|nagfor) f77|gfortran|ifort|pgfortran|xlf|nagfor)
command="$SPACK_F77" command="$SPACK_F77"
language="Fortran 77" language="Fortran 77"
comp="F77"
;; ;;
ld) ld)
mode=ld mode=ld
@ -142,6 +152,9 @@ if [[ -z $mode ]]; then
done done
fi fi
# Set up rpath variable according to language.
eval rpath=\$SPACK_${comp}_RPATH_ARG
# Dump the version and exit if we're in testing mode. # Dump the version and exit if we're in testing mode.
if [[ $SPACK_TEST_COMMAND == dump-mode ]]; then if [[ $SPACK_TEST_COMMAND == dump-mode ]]; then
echo "$mode" echo "$mode"
@ -188,7 +201,7 @@ for dep in "${deps[@]}"; do
# Prepend lib and RPATH directories # Prepend lib and RPATH directories
if [[ -d $dep/lib ]]; then if [[ -d $dep/lib ]]; then
if [[ $mode == ccld ]]; then if [[ $mode == ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$dep/lib" "${args[@]}") $add_rpaths && args=("$rpath$dep/lib" "${args[@]}")
args=("-L$dep/lib" "${args[@]}") args=("-L$dep/lib" "${args[@]}")
elif [[ $mode == ld ]]; then elif [[ $mode == ld ]]; then
$add_rpaths && args=("-rpath" "$dep/lib" "${args[@]}") $add_rpaths && args=("-rpath" "$dep/lib" "${args[@]}")
@ -199,7 +212,7 @@ for dep in "${deps[@]}"; do
# Prepend lib64 and RPATH directories # Prepend lib64 and RPATH directories
if [[ -d $dep/lib64 ]]; then if [[ -d $dep/lib64 ]]; then
if [[ $mode == ccld ]]; then if [[ $mode == ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$dep/lib64" "${args[@]}") $add_rpaths && args=("$rpath$dep/lib64" "${args[@]}")
args=("-L$dep/lib64" "${args[@]}") args=("-L$dep/lib64" "${args[@]}")
elif [[ $mode == ld ]]; then elif [[ $mode == ld ]]; then
$add_rpaths && args=("-rpath" "$dep/lib64" "${args[@]}") $add_rpaths && args=("-rpath" "$dep/lib64" "${args[@]}")
@ -210,9 +223,11 @@ done
# Include all -L's and prefix/whatever dirs in rpath # Include all -L's and prefix/whatever dirs in rpath
if [[ $mode == ccld ]]; then if [[ $mode == ccld ]]; then
$add_rpaths && args=("-Wl,-rpath,$SPACK_PREFIX/lib" "-Wl,-rpath,$SPACK_PREFIX/lib64" "${args[@]}") $add_rpaths && args=("$rpath$SPACK_PREFIX/lib64" "${args[@]}")
$add_rpaths && args=("$rpath$SPACK_PREFIX/lib" "${args[@]}")
elif [[ $mode == ld ]]; then elif [[ $mode == ld ]]; then
$add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "-rpath" "$SPACK_PREFIX/lib64" "${args[@]}") $add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib64" "${args[@]}")
$add_rpaths && args=("-rpath" "$SPACK_PREFIX/lib" "${args[@]}")
fi fi
# #

View File

@ -98,21 +98,27 @@ def set_compiler_environment_variables(pkg, env):
# and return it # and return it
# TODO : add additional kwargs for better diagnostics, like requestor, ttyout, ttyerr, etc. # TODO : add additional kwargs for better diagnostics, like requestor, ttyout, ttyerr, etc.
link_dir = spack.build_env_path link_dir = spack.build_env_path
env.set('CC', join_path(link_dir, pkg.compiler.link_paths['cc'])) env.set('CC', join_path(link_dir, pkg.compiler.link_paths['cc']))
env.set('CXX', join_path(link_dir, pkg.compiler.link_paths['cxx'])) env.set('CXX', join_path(link_dir, pkg.compiler.link_paths['cxx']))
env.set('F77', join_path(link_dir, pkg.compiler.link_paths['f77'])) env.set('F77', join_path(link_dir, pkg.compiler.link_paths['f77']))
env.set('FC', join_path(link_dir, pkg.compiler.link_paths['fc'])) env.set('FC', join_path(link_dir, pkg.compiler.link_paths['fc']))
# Set SPACK compiler variables so that our wrapper knows what to call # Set SPACK compiler variables so that our wrapper knows what to call
compiler = pkg.compiler compiler = pkg.compiler
if compiler.cc: if compiler.cc:
env.set('SPACK_CC', compiler.cc) env.set('SPACK_CC', compiler.cc)
if compiler.cxx: if compiler.cxx:
env.set('SPACK_CXX', compiler.cxx) env.set('SPACK_CXX', compiler.cxx)
if compiler.f77: if compiler.f77:
env.set('SPACK_F77', compiler.f77) env.set('SPACK_F77', compiler.f77)
if compiler.fc: if compiler.fc:
env.set('SPACK_FC', compiler.fc) env.set('SPACK_FC', compiler.fc)
# Set SPACK compiler rpath flags so that our wrapper knows what to use
env.set('SPACK_CC_RPATH_ARG', compiler.cc_rpath_arg)
env.set('SPACK_CXX_RPATH_ARG', compiler.cxx_rpath_arg)
env.set('SPACK_F77_RPATH_ARG', compiler.f77_rpath_arg)
env.set('SPACK_FC_RPATH_ARG', compiler.fc_rpath_arg)
env.set('SPACK_COMPILER_SPEC', str(pkg.spec.compiler)) env.set('SPACK_COMPILER_SPEC', str(pkg.spec.compiler))
return env return env

View File

@ -91,8 +91,22 @@ class Compiler(object):
# version suffix for gcc. # version suffix for gcc.
suffixes = [r'-.*'] suffixes = [r'-.*']
# Names of generic arguments used by this compiler # Default flags used by a compiler to set an rpath
arg_rpath = '-Wl,-rpath,%s' @property
def cc_rpath_arg(self):
return '-Wl,-rpath,'
@property
def cxx_rpath_arg(self):
return '-Wl,-rpath,'
@property
def f77_rpath_arg(self):
return '-Wl,-rpath,'
@property
def fc_rpath_arg(self):
return '-Wl,-rpath,'
def __init__(self, cspec, cc, cxx, f77, fc): def __init__(self, cspec, cc, cxx, f77, fc):

View File

@ -31,6 +31,17 @@ def cxx11_flag(self):
# However, it can be mixed with a compiler that does support it # However, it can be mixed with a compiler that does support it
return "-std=c++11" return "-std=c++11"
# Unlike other compilers, the NAG compiler passes options to GCC, which
# then passes them to the linker. Therefore, we need to doubly wrap the
# options with '-Wl,-Wl,,'
@property
def f77_rpath_arg(self):
return '-Wl,-Wl,,-rpath,'
@property
def fc_rpath_arg(self):
return '-Wl,-Wl,,-rpath,'
@classmethod @classmethod
def default_version(self, comp): def default_version(self, comp):
"""The '-V' option works for nag compilers. """The '-V' option works for nag compilers.

View File

@ -67,6 +67,11 @@ def setUp(self):
os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7" os.environ['SPACK_COMPILER_SPEC'] = "gcc@4.4.7"
os.environ['SPACK_SHORT_SPEC'] = "foo@1.2" os.environ['SPACK_SHORT_SPEC'] = "foo@1.2"
os.environ['SPACK_CC_RPATH_ARG'] = "-Wl,-rpath,"
os.environ['SPACK_CXX_RPATH_ARG'] = "-Wl,-rpath,"
os.environ['SPACK_F77_RPATH_ARG'] = "-Wl,-rpath,"
os.environ['SPACK_FC_RPATH_ARG'] = "-Wl,-rpath,"
# Make some fake dependencies # Make some fake dependencies
self.tmp_deps = tempfile.mkdtemp() self.tmp_deps = tempfile.mkdtemp()
self.dep1 = join_path(self.tmp_deps, 'dep1') self.dep1 = join_path(self.tmp_deps, 'dep1')