diff --git a/easybuild/scripts/rpath_args.py b/easybuild/scripts/rpath_args.py index 611c6a414c..b1831dfb42 100755 --- a/easybuild/scripts/rpath_args.py +++ b/easybuild/scripts/rpath_args.py @@ -27,7 +27,9 @@ Utility script used by RPATH wrapper script; output is statements that define the following environment variables * $CMD_ARGS: new list of command line arguments to pass -* $RPATH_ARGS: command line option to specify list of paths to RPATH + +Usage: + rpath_args.py author: Kenneth Hoste (HPC-UGent) """ @@ -38,22 +40,17 @@ def is_new_existing_path(new_path, paths): """ - Check whether specified path exists and is a new path compared to provided list of paths. + Check whether specified path exists and is a new path compared to provided list of paths (that surely exist as they + were checked before). """ + if not os.path.exists(new_path): + return False - # assume path is new, until proven otherwise - res = True - - if os.path.exists(new_path): - for path in paths: - if os.path.exists(path) and os.path.samefile(new_path, path): - res = False - break - else: - # path doesn't exist - res = False + for path in paths: + if os.path.exists(path) and os.path.samefile(new_path, path): + return False - return res + return True cmd = sys.argv[1] @@ -63,9 +60,9 @@ def is_new_existing_path(new_path, paths): # determine whether or not to use -Wl to pass options to the linker based on name of command if cmd in ['ld', 'ld.gold', 'ld.bfd']: - flag_prefix = '' + ldflag_prefix = '' else: - flag_prefix = '-Wl,' + ldflag_prefix = '-Wl,' rpath_filter = rpath_filter.split(',') if rpath_filter: @@ -124,7 +121,7 @@ def is_new_existing_path(new_path, paths): if is_new_existing_path(lib_path, rpath_lib_paths): # inject -rpath flag in front for every -L with an absolute path, rpath_lib_paths.append(lib_path) - cmd_args_rpath.append(flag_prefix + '-rpath=%s' % lib_path) + cmd_args_rpath.append(ldflag_prefix + '-rpath=%s' % lib_path) # always retain -L flag (without reordering!) cmd_args.append('-L%s' % lib_path) @@ -135,8 +132,12 @@ def is_new_existing_path(new_path, paths): # --enable-new-dtags is not removed but replaced to prevent issues when linker flag is forwarded from the compiler # to the linker with an extra prefixed flag (either -Xlinker or -Wl,). # In that case, the compiler would erroneously pass the next random argument to the linker. - elif arg == flag_prefix + '--enable-new-dtags': - cmd_args.append(flag_prefix + '--disable-new-dtags') + elif arg == '-Xlinker' and args[idx+1] == '--enable-new-dtags': # detect '-Xlinker --enable-new-dtags' + cmd_args.append(ldflag_prefix + '--disable-new-dtags') + idx += 1 + elif arg == ldflag_prefix + '--enable-new-dtags': # detect '--enable-new-dtags' or '-Wl,--enable-new-dtags' + cmd_args.append(ldflag_prefix + '--disable-new-dtags') + else: cmd_args.append(arg) @@ -149,14 +150,14 @@ def is_new_existing_path(new_path, paths): # avoid using duplicate library paths if is_new_existing_path(lib_path, rpath_lib_paths): rpath_lib_paths.append(lib_path) - cmd_args_rpath.append(flag_prefix + '-rpath=%s' % lib_path) + cmd_args_rpath.append(ldflag_prefix + '-rpath=%s' % lib_path) if add_rpath_args: # try to make sure that RUNPATH is not used by always injecting --disable-new-dtags - cmd_args_rpath.insert(0, flag_prefix + '--disable-new-dtags') + cmd_args_rpath.insert(0, ldflag_prefix + '--disable-new-dtags') # add -rpath options for paths listed in rpath_include - cmd_args_rpath = [flag_prefix + '-rpath=%s' % inc for inc in rpath_include] + cmd_args_rpath + cmd_args_rpath = [ldflag_prefix + '-rpath=%s' % inc for inc in rpath_include] + cmd_args_rpath # add -rpath flags in front cmd_args = cmd_args_rpath + cmd_args @@ -164,5 +165,5 @@ def is_new_existing_path(new_path, paths): # wrap all arguments into single quotes to avoid further bash expansion cmd_args = ["'%s'" % a.replace("'", "''") for a in cmd_args] -# output: statement to define $CMD_ARGS and $RPATH_ARGS +# output: statement to define $CMD_ARGS print("CMD_ARGS=(%s)" % ' '.join(cmd_args)) diff --git a/test/framework/toolchain.py b/test/framework/toolchain.py index 6e6910a640..82c7146ce9 100644 --- a/test/framework/toolchain.py +++ b/test/framework/toolchain.py @@ -2546,6 +2546,22 @@ def test_rpath_args_script(self): ] self.assertEqual(res.output.strip(), "CMD_ARGS=(%s)" % ' '.join(cmd_args)) + # compiler command, -Xlinker --enable-new-dtags should be replaced with -Wl,--disable-new-dtags + with self.mocked_stdout_stderr(): + res = run_shell_cmd(f"{script} gcc '' '{rpath_inc}' -Xlinker --enable-new-dtags foo.c") + self.assertEqual(res.exit_code, 0) + cmd_args = [ + "'-Wl,-rpath=%s/lib'" % self.test_prefix, + "'-Wl,-rpath=%s/lib64'" % self.test_prefix, + "'-Wl,-rpath=$ORIGIN'", + "'-Wl,-rpath=$ORIGIN/../lib'", + "'-Wl,-rpath=$ORIGIN/../lib64'", + "'-Wl,--disable-new-dtags'", + "'-Wl,--disable-new-dtags'", + "'foo.c'", + ] + self.assertEqual(res.output.strip(), "CMD_ARGS=(%s)" % ' '.join(cmd_args)) + # test passing no arguments with self.mocked_stdout_stderr(): res = run_shell_cmd(f"{script} gcc '' '{rpath_inc}'")