-
Notifications
You must be signed in to change notification settings - Fork 202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RPATH support using ld wrapper (WIP) #1613
Changes from 5 commits
8e41d66
2dadc9d
d71b391
5c2b6e5
f83ab79
1ee637d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#!/bin/bash | ||
# | ||
# Chandan Basu, cbasu@nsc.liu.se. | ||
# Consider this piece of script GPL. | ||
# | ||
# Time-stamp: <2015-02-12 16:00:00> | ||
|
||
# This is a linker-wrapper. | ||
# | ||
# The wrapped linker gets lib paths from compiler | ||
# (e.g., gcc, gfortran, icc, ifort etc.) and adds | ||
# rpaths to binary. | ||
|
||
SCRIPTNAME=$(basename $0) | ||
ALLSCRIPTS=( $( which -a $SCRIPTNAME ) ) | ||
$EB_LD_VERBOSE && echo "found scriptname: $SCRIPTNAME allscripts: ${ALLSCRIPTS[1]}" | ||
LDORIG=${ALLSCRIPTS[1]} | ||
LDWRAPPER=$EB_LD_FLAG | ||
LINKER=$EB_LINKER_NAME ## not yet implemented | ||
EB_LD_VERBOSE=${EB_LD_VERBOSE:-false} | ||
|
||
|
||
$EB_LD_VERBOSE && echo "INFO: linking with rpath " | ||
|
||
if [ -z "$LDWRAPPER" ] || [ "$LDWRAPPER" == 0 ]; then | ||
## call the system linker | ||
$LDORIG "$@" | ||
exit | ||
elif [ "$LDWRAPPER" == 1 ]; then | ||
## Default rpath-ing option. | ||
exclude_lib_paths=("/lib" "/lib64" "/usr" "/home" "/tmp" "/opt" "/proj") | ||
elif [ "$LDWRAPPER" == 2 ]; then | ||
## More aggressive rpath-ing | ||
exclude_lib_paths=("/tmp" "/opt") | ||
fi | ||
|
||
L="" | ||
lib_array=() | ||
dir=`pwd` | ||
for (( i=${#@}; i >= 0; i-- )); do | ||
if [[ ${!i} == "--enable-new-dtags" ]]; then | ||
## we are removing this flag if passed as it creates a copy of rpath to runpath. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't we at the mercy of what the default is set to here? We probably should (always) be adding |
||
## If runpath exists in the binary it can be controlled by LD_LIBRARY_PATH. | ||
## We want only rpath in the binary and no runpath. | ||
## If the user wants to use runpath he should disable linker warpper | ||
## by using EB_LD_FLAG=0 | ||
set -- "${@:1:$(( $i - 1 ))}" "${@:$(( $i + 1 ))}" | ||
fi | ||
done | ||
|
||
for i in `echo $*` | ||
do | ||
x=`echo $i| cut -c -3` | ||
if [ "$x" == "-L/" -o "$x" == "-L." ] ; then | ||
x=`echo $i| cut -c 3-` | ||
if [ -d "$x" ]; then | ||
p=`cd $x; pwd -P` | ||
lib_array=( "${lib_array[@]}" "$p" ) | ||
fi | ||
fi | ||
done | ||
|
||
lib_array=( $(for x in "${lib_array[@]}" | ||
do | ||
echo "$x" | ||
done | sort -u) ) | ||
|
||
for y in "${exclude_lib_paths[@]}" | ||
do | ||
lib_array=( $(for x in "${lib_array[@]}" | ||
do | ||
if [[ "${x:0:${#y}}" != "$y" ]]; then | ||
echo "$x" | ||
fi | ||
done)) | ||
done | ||
|
||
#### check extra libpaths and add to the lib_array #### | ||
extra_lib_paths=(${NSC_LD_EXTRA_LIBPATH//:/ }) | ||
lib_array=( "${lib_array[@]}" "${extra_lib_paths[@]}" ) | ||
####################################################### | ||
|
||
RPATH="" | ||
for x in "${lib_array[@]}" | ||
do | ||
if [ "$RPATH" == "" ]; then | ||
L=$x | ||
RPATH="-rpath=$x" | ||
else | ||
L=$L:$x | ||
RPATH="$RPATH -rpath=$x" | ||
fi | ||
done | ||
|
||
$EB_LD_VERBOSE && echo "INFO: linking with rpath and NSC symbols " | ||
$EB_LD_VERBOSE && echo "INFO: LDORIG: $LDORIG RPATH : $RPATH @: $@ ::" | ||
$LDORIG "-rpath=$L" "$@" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -433,6 +433,16 @@ def package_options(self): | |
self.log.debug("package_options: descr %s opts %s" % (descr, opts)) | ||
self.add_group_parser(opts, descr) | ||
|
||
def rpath_options(self): | ||
# rpath Options | ||
descr = ("RPATH options", "changes linking to include rpaths") | ||
|
||
opts = OrderedDict({ | ||
'rpath': ("Enable RPATH support", None, 'store_true', False), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you expect other options here? if not, this shouldn't be an option group by itself? |
||
}) | ||
self.log.debug("rpath_options: descr %s opts %s" % (descr, opts)) | ||
self.add_group_parser(opts, descr) | ||
|
||
def easyconfig_options(self): | ||
# easyconfig options (to be passed to easyconfig instance) | ||
descr = ("Options for Easyconfigs", "Options to be passed to all Easyconfig.") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
"""A module to setup and use an ld wrapper to support RPATH""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing license header + author |
||
|
||
import os | ||
import copy | ||
import shutil | ||
import stat | ||
import tempfile | ||
from vsc.utils import fancylogger | ||
from easybuild.tools.filetools import adjust_permissions | ||
|
||
_log = fancylogger.getLogger('tools.package') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not package, rpath |
||
|
||
orig_os_environ = copy.deepcopy(os.environ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have copies of the original environment in various places already, no need to keep another? |
||
# RPATH is linux only | ||
ld_wrapper_script_loc = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "scripts", "ld_wrapper.sh")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a constant, so name it |
||
|
||
DEBUG = True | ||
|
||
|
||
def prepare_ld_wrapper(): | ||
""" | ||
Copy wrapper from framework for each iteration, a bit expensive, but might give flexibility | ||
""" | ||
_log.debug("rpath: preparing ld wrapper script") | ||
wrapper_dir = tempfile.mkdtemp(prefix='eb-ldwrapper-') | ||
# copy wrapper script from framework | ||
wrapper_ld = os.path.join(wrapper_dir, "ld") | ||
wrapper_ld_gold = os.path.join(wrapper_dir, "ld.gold") | ||
shutil.copy(ld_wrapper_script_loc, wrapper_ld) | ||
shutil.copy(ld_wrapper_script_loc, wrapper_ld_gold) | ||
adjust_permissions(wrapper_ld, stat.S_IXUSR, add=True) | ||
adjust_permissions(wrapper_ld_gold, stat.S_IXUSR, add=True) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for linker in ['ld', 'ld.gold']:
wrapper = os.path.join(wrapper_dir, linker)
shutil.copy(ld_wrapper_script_loc, wrapper)
adjust_permissions(wrapper, stat.S_IXUSR, add=True) |
||
|
||
# put wrapper script in PATH | ||
# TODO: get path to existing ld and put it in EB_LD | ||
os.environ['PATH'] = os.pathsep.join([wrapper_dir] + | ||
[x for x in os.environ.get('PATH', '').split(os.pathsep) if len(x) > 0]) | ||
|
||
os.environ['EB_LD_FLAG'] = "1" | ||
if DEBUG: | ||
os.environ['EB_LD_VERBOSE'] = 'true' | ||
|
||
|
||
def teardown_ld_wrapper(): | ||
""" | ||
Return environment | ||
""" | ||
os.environ = copy.deepcopy(orig_os_environ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the environment is reset for every new build already, I don't think we need to worry about this? |
||
|
||
|
||
def check_rpath_support(): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not called anywhere? |
||
""" | ||
If there are any special checks we need to do to make sure this will work they should | ||
go here. Incuding whether experimental enabled to begin with. | ||
""" | ||
|
||
_log.experimental("Support for setting RPATH for dependencies.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, shouldn't we do this in the
toolchain.prepare()
itself? keep things nicely together?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see
easybuild/tools/toolchain/toolchain.py:prepare