Skip to content

Commit 71cc6eb

Browse files
authored
Merge pull request #47 from boegel/export_rpath_wrappers
remove `--rpath-wrapper-dir` configuration option + copy `rpath_args.py` script to avoid that RPATH wrapper scripts rely on external script
2 parents ef951d9 + f6f5e93 commit 71cc6eb

File tree

6 files changed

+42
-19
lines changed

6 files changed

+42
-19
lines changed

easybuild/framework/easyblock.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,13 +2902,12 @@ def prepare_step(self, start_dir=True, load_tc_deps_modules=True):
29022902
])
29032903

29042904
# Location to store RPATH wrappers
2905-
self.rpath_wrappers_dir = build_option('rpath_wrappers_dir')
29062905
if self.rpath_wrappers_dir is not None:
29072906
# Verify the path given is absolute
29082907
if os.path.isabs(self.rpath_wrappers_dir):
2909-
_log.debug("Using %s to store/use RPATH wrappers" % self.rpath_wrappers_dir)
2908+
_log.info(f"Using {self.rpath_wrappers_dir} to store/use RPATH wrappers")
29102909
else:
2911-
raise EasyBuildError("Path used for rpath_wrappers_dir is not an absolute path: %s", path)
2910+
raise EasyBuildError(f"Path used for rpath_wrappers_dir is not an absolute path: {path}")
29122911

29132912
if self.iter_idx > 0:
29142913
# reset toolchain for iterative runs before preparing it again
@@ -2925,9 +2924,11 @@ def prepare_step(self, start_dir=True, load_tc_deps_modules=True):
29252924
self.modules_tool.prepend_module_path(full_mod_path)
29262925

29272926
# prepare toolchain: load toolchain module and dependencies, set up build environment
2928-
self.toolchain.prepare(self.cfg['onlytcmod'], deps=self.cfg.dependencies(), silent=self.silent,
2929-
loadmod=load_tc_deps_modules, rpath_filter_dirs=self.rpath_filter_dirs,
2930-
rpath_include_dirs=self.rpath_include_dirs, rpath_wrappers_dir=self.rpath_wrappers_dir)
2927+
self.toolchain.prepare(onlymod=self.cfg['onlytcmod'], deps=self.cfg.dependencies(),
2928+
silent=self.silent, loadmod=load_tc_deps_modules,
2929+
rpath_filter_dirs=self.rpath_filter_dirs,
2930+
rpath_include_dirs=self.rpath_include_dirs,
2931+
rpath_wrappers_dir=self.rpath_wrappers_dir)
29312932

29322933
# keep track of environment variables that were tweaked and need to be restored after environment got reset
29332934
# $TMPDIR may be tweaked for OpenMPI 2.x, which doesn't like long $TMPDIR paths...

easybuild/scripts/rpath_wrapper_template.sh.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ function log {
4242

4343
# command name
4444
CMD=`basename $0`
45+
TOPDIR=`dirname $0`
4546

4647
log "found CMD: $CMD | original command: %(orig_cmd)s | orig args: '$(echo \"$@\")'"
4748

easybuild/tools/config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,6 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX):
277277
'regtest_output_dir',
278278
'rpath_filter',
279279
'rpath_override_dirs',
280-
'rpath_wrappers_dir',
281280
'required_linked_shared_libs',
282281
'search_path_cpp_headers',
283282
'search_path_linker',

easybuild/tools/options.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,6 @@ def override_options(self):
524524
'rpath-filter': ("List of regex patterns to use for filtering out RPATH paths", 'strlist', 'store', None),
525525
'rpath-override-dirs': ("Path(s) to be prepended when linking with RPATH (string, colon-separated)",
526526
None, 'store', None),
527-
'rpath-wrappers-dir': ("Absolute path to directory to use for RPATH wrappers creation/use",
528-
None, 'store', None),
529527
'sanity-check-only': ("Only run sanity check (module is expected to be installed already",
530528
None, 'store_true', False),
531529
'set-default-module': ("Set the generated module as default", None, 'store_true', False),

easybuild/tools/toolchain/toolchain.py

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
from easybuild.tools.build_log import EasyBuildError, dry_run_msg, print_warning
6363
from easybuild.tools.config import build_option, install_path
6464
from easybuild.tools.environment import setvar
65-
from easybuild.tools.filetools import adjust_permissions, find_eb_script, read_file, which, write_file
65+
from easybuild.tools.filetools import adjust_permissions, copy_file, find_eb_script, mkdir, read_file, which, write_file
6666
from easybuild.tools.module_generator import dependencies_for
6767
from easybuild.tools.modules import get_software_root, get_software_root_env_var_name
6868
from easybuild.tools.modules import get_software_version, get_software_version_env_var_name
@@ -985,6 +985,8 @@ def prepare_rpath_wrappers(self, rpath_filter_dirs=None, rpath_include_dirs=None
985985
Put RPATH wrapper script in place for compiler and linker commands
986986
987987
:param rpath_filter_dirs: extra directories to include in RPATH filter (e.g. build dir, tmpdir, ...)
988+
:param rpath_include_dirs: extra directories to include in RPATH
989+
:param rpath_wrappers_dir: directory in which to create RPATH wrappers (tmpdir is created if None)
988990
"""
989991
if get_os_type() == LINUX:
990992
self.log.info("Putting RPATH wrappers in place...")
@@ -994,6 +996,11 @@ def prepare_rpath_wrappers(self, rpath_filter_dirs=None, rpath_include_dirs=None
994996
if rpath_filter_dirs is None:
995997
rpath_filter_dirs = []
996998

999+
# only enable logging by RPATH wrapper scripts in debug mode
1000+
enable_wrapper_log = build_option('debug')
1001+
1002+
copy_rpath_args_py = False
1003+
9971004
# always include filter for 'stubs' library directory,
9981005
# cfr. https://github.com/easybuilders/easybuild-framework/issues/2683
9991006
# (since CUDA 11.something the stubs are in $EBROOTCUDA/stubs/lib64)
@@ -1002,19 +1009,35 @@ def prepare_rpath_wrappers(self, rpath_filter_dirs=None, rpath_include_dirs=None
10021009
if lib_stubs_pattern not in rpath_filter_dirs:
10031010
rpath_filter_dirs.append(lib_stubs_pattern)
10041011

1005-
# directory where all wrappers will be placed
1006-
disable_wrapper_log = False
1012+
# directory where all RPATH wrapper script will be placed;
10071013
if rpath_wrappers_dir is None:
1008-
wrappers_dir = os.path.join(tempfile.mkdtemp(), RPATH_WRAPPERS_SUBDIR)
1014+
wrappers_dir = tempfile.mkdtemp()
10091015
else:
1010-
wrappers_dir = os.path.join(rpath_wrappers_dir, RPATH_WRAPPERS_SUBDIR)
1011-
# No logging when we may be exporting wrappers
1012-
disable_wrapper_log = True
1016+
wrappers_dir = rpath_wrappers_dir
1017+
# disable logging in RPATH wrapper scripts when they may be exported for use outside of EasyBuild
1018+
enable_wrapper_log = False
1019+
# copy rpath_args.py script to sit alongside RPATH wrapper scripts
1020+
copy_rpath_args_py = True
1021+
1022+
# it's important to honor RPATH_WRAPPERS_SUBDIR, see is_rpath_wrapper method
1023+
wrappers_dir = os.path.join(wrappers_dir, RPATH_WRAPPERS_SUBDIR)
1024+
mkdir(wrappers_dir, parents=True)
10131025

10141026
# must also wrap compilers commands, required e.g. for Clang ('gcc' on OS X)?
10151027
c_comps, fortran_comps = self.compilers()
10161028

10171029
rpath_args_py = find_eb_script('rpath_args.py')
1030+
1031+
# copy rpath_args.py script along RPATH wrappers, if desired
1032+
if copy_rpath_args_py:
1033+
copy_file(rpath_args_py, wrappers_dir)
1034+
# use path for %(rpath_args)s template value relative to location of the RPATH wrapper script,
1035+
# to avoid that the RPATH wrapper scripts rely on a script that's located elsewhere;
1036+
# that's mostly important when RPATH wrapper scripts are retained to be used outside of EasyBuild;
1037+
# we assume that each RPATH wrapper script is created in a separate subdirectory (see wrapper_dir below);
1038+
# ${TOPDIR} is defined in template for RPATH wrapper scripts, refers to parent dir of RPATH wrapper script
1039+
rpath_args_py = os.path.join('${TOPDIR}', '..', os.path.basename(rpath_args_py))
1040+
10181041
rpath_wrapper_template = find_eb_script('rpath_wrapper_template.sh.in')
10191042

10201043
# figure out list of patterns to use in rpath filter
@@ -1056,8 +1079,8 @@ def prepare_rpath_wrappers(self, rpath_filter_dirs=None, rpath_include_dirs=None
10561079
raise EasyBuildError("Refusing to create a fork bomb, which(%s) == %s", cmd, orig_cmd)
10571080

10581081
# enable debug mode in wrapper script by specifying location for log file
1059-
if build_option('debug') and not disable_wrapper_log:
1060-
rpath_wrapper_log = os.path.join(tempfile.gettempdir(), 'rpath_wrapper_%s.log' % cmd)
1082+
if enable_wrapper_log:
1083+
rpath_wrapper_log = os.path.join(tempfile.gettempdir(), f'rpath_wrapper_{cmd}.log')
10611084
else:
10621085
rpath_wrapper_log = '/dev/null'
10631086

test/framework/toolchain.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3153,7 +3153,8 @@ def test_toolchain_prepare_rpath_external(self):
31533153
tc = self.get_toolchain('gompi', version='2018a')
31543154
tc.set_options({'rpath': True})
31553155
# allow the underlying toolchain to be in a prepared state (which may include rpath wrapping)
3156-
tc.prepare(rpath_wrappers_dir=target_wrapper_dir)
3156+
with self.mocked_stdout_stderr():
3157+
tc.prepare(rpath_wrappers_dir=target_wrapper_dir)
31573158

31583159
# check that wrapper was created
31593160
target_wrapper = os.path.join(target_wrapper_dir, RPATH_WRAPPERS_SUBDIR, 'gxx_wrapper', 'g++')

0 commit comments

Comments
 (0)