Skip to content
Snippets Groups Projects
Commit 42edb684 authored by Todd Gamblin's avatar Todd Gamblin
Browse files

Merge pull request #905 from adamjstewart/features/rpath_flag

Allow compilers to specify their own rpath linking flags
parents a2528a86 6665a996
No related branches found
No related tags found
No related merge requests found
...@@ -1803,15 +1803,15 @@ Compile-time library search paths ...@@ -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 ...@@ -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 ...@@ -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``.
......
...@@ -38,15 +38,20 @@ ...@@ -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 { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
# #
......
...@@ -98,21 +98,27 @@ def set_compiler_environment_variables(pkg, env): ...@@ -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
......
...@@ -91,8 +91,22 @@ class Compiler(object): ...@@ -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):
......
...@@ -31,6 +31,17 @@ def cxx11_flag(self): ...@@ -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.
......
...@@ -67,6 +67,11 @@ def setUp(self): ...@@ -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')
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment