Skip to content

Commit 5fb4ae2

Browse files
committed
Merge branch 'develop' into 5.0.x
2 parents bb9f41f + 3b01ba9 commit 5fb4ae2

File tree

7 files changed

+86
-33
lines changed

7 files changed

+86
-33
lines changed

easybuild/framework/easyblock.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4410,7 +4410,9 @@ def build_and_install_one(ecdict, init_env):
44104410
def ensure_writable_log_dir(log_dir):
44114411
"""Make sure we can write into the log dir"""
44124412
if build_option('read_only_installdir'):
4413-
# temporarily re-enable write permissions for copying log/easyconfig to install dir
4413+
# temporarily re-enable write permissions for copying log/easyconfig to install dir,
4414+
# ensuring that we resolve symlinks
4415+
log_dir = os.path.realpath(log_dir)
44144416
if os.path.exists(log_dir):
44154417
adjust_permissions(log_dir, stat.S_IWUSR, add=True, recursive=True)
44164418
else:

easybuild/framework/easyconfig/templates.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
'cuda_sm_comma_sep': 'Comma-separated list of sm_* values that correspond with CUDA compute capabilities',
104104
'cuda_sm_space_sep': 'Space-separated list of sm_* values that correspond with CUDA compute capabilities',
105105
'mpi_cmd_prefix': 'Prefix command for running MPI programs (with default number of ranks)',
106+
# can't be a boolean (True/False), must be a string value since it's a string template
107+
'rpath_enabled': "String value indicating whether or not RPATH linking is used ('true' or 'false')",
106108
'software_commit': "Git commit id to use for the software as specified by --software-commit command line option",
107109
'sysroot': "Location root directory of system, prefix for standard paths like /usr/lib and /usr/include"
108110
"as specify by the --sysroot configuration option",
@@ -298,6 +300,9 @@ def template_constant_dict(config, ignore=None, toolchain=None):
298300
# set 'arch' for system architecture based on 'machine' (4th) element of platform.uname() return value
299301
template_values['arch'] = platform.uname()[4]
300302

303+
# set 'rpath' template based on 'rpath' configuration option, using empty string as fallback
304+
template_values['rpath_enabled'] = 'true' if build_option('rpath') else 'false'
305+
301306
# set 'sysroot' template based on 'sysroot' configuration option, using empty string as fallback
302307
template_values['sysroot'] = build_option('sysroot') or ''
303308

easybuild/scripts/findPythonDeps.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,35 @@ def get_dep_tree(package_spec, verbose):
9595

9696
def find_deps(pkgs, dep_tree):
9797
"""Recursively resolve dependencies of the given package(s) and return them"""
98+
MAX_PACKAGES = 1000
9899
res = []
99-
for orig_pkg in pkgs:
100-
pkg = canonicalize_name(orig_pkg)
101-
matching_entries = [entry for entry in dep_tree
102-
if pkg in (entry['package']['package_name'], entry['package']['key'])]
103-
if not matching_entries:
100+
next_pkgs = set(pkgs)
101+
# Don't check any package multiple times to avoid infinite recursion
102+
seen_pkgs = set()
103+
count = 0
104+
while next_pkgs:
105+
cur_pkgs = next_pkgs - seen_pkgs
106+
seen_pkgs.update(cur_pkgs)
107+
next_pkgs = set()
108+
for orig_pkg in cur_pkgs:
109+
count += 1
110+
if count > MAX_PACKAGES:
111+
raise RuntimeError("Aborting after checking %s packages. Possibly cycle detected!" % MAX_PACKAGES)
112+
pkg = canonicalize_name(orig_pkg)
104113
matching_entries = [entry for entry in dep_tree
105-
if orig_pkg in (entry['package']['package_name'], entry['package']['key'])]
106-
if not matching_entries:
107-
raise RuntimeError("Found no installed package for '%s' in %s" % (pkg, dep_tree))
108-
if len(matching_entries) > 1:
109-
raise RuntimeError("Found multiple installed packages for '%s' in %s" % (pkg, dep_tree))
110-
entry = matching_entries[0]
111-
res.append((entry['package']['package_name'], entry['package']['installed_version']))
112-
deps = (dep['package_name'] for dep in entry['dependencies'])
113-
res.extend(find_deps(deps, dep_tree))
114+
if pkg in (entry['package']['package_name'], entry['package']['key'])]
115+
if not matching_entries:
116+
matching_entries = [entry for entry in dep_tree
117+
if orig_pkg in (entry['package']['package_name'], entry['package']['key'])]
118+
if not matching_entries:
119+
raise RuntimeError("Found no installed package for '%s' in %s" % (pkg, dep_tree))
120+
if len(matching_entries) > 1:
121+
raise RuntimeError("Found multiple installed packages for '%s' in %s" % (pkg, dep_tree))
122+
entry = matching_entries[0]
123+
res.append((entry['package']['package_name'], entry['package']['installed_version']))
124+
# Add dependencies to list of packages to check next
125+
# Could call this function recursively but that might exceed the max recursion depth
126+
next_pkgs.update(dep['package_name'] for dep in entry['dependencies'])
114127
return res
115128

116129

easybuild/toolchains/compiler/gcc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class Gcc(Compiler):
8585
COMPILER_UNIQUE_OPTION_MAP['strict'] = []
8686
COMPILER_UNIQUE_OPTION_MAP['precise'] = []
8787
COMPILER_UNIQUE_OPTION_MAP['loose'] = ['fno-math-errno']
88-
COMPILER_UNIQUE_OPTION_MAP['verloose'] = ['fno-math-errno']
88+
COMPILER_UNIQUE_OPTION_MAP['veryloose'] = ['fno-math-errno']
8989

9090
# used when 'optarch' toolchain option is enabled (and --optarch is not specified)
9191
COMPILER_OPTIMAL_ARCHITECTURE_OPTION = {

easybuild/tools/github.py

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,11 +1097,16 @@ def _easyconfigs_pr_common(paths, ecs, start_branch=None, pr_branch=None, start_
10971097
elif pr_target_repo == GITHUB_EASYBLOCKS_REPO and all(file_info['new']):
10981098
commit_msg = "adding easyblocks: %s" % ', '.join(os.path.basename(p) for p in file_info['paths_in_repo'])
10991099
else:
1100-
raise EasyBuildError(
1101-
"A meaningful commit message must be specified via --pr-commit-msg when "
1102-
"modifying/deleting files or targeting the framework repo.",
1103-
exit_code=EasyBuildExit.OPTION_ERROR
1104-
)
1100+
msg = ''
1101+
modified_files = [os.path.basename(p) for new, p in zip(file_info['new'], file_info['paths_in_repo'])
1102+
if not new]
1103+
if modified_files:
1104+
msg += '\nModified: ' + ', '.join(modified_files)
1105+
if paths['files_to_delete']:
1106+
msg += '\nDeleted: ' + ', '.join(paths['files_to_delete'])
1107+
raise EasyBuildError("A meaningful commit message must be specified via --pr-commit-msg when "
1108+
"modifying/deleting files or targeting the framework repo." + msg,
1109+
exit_code=EasyBuildExit.OPTION_ERROR)
11051110

11061111
# figure out to which software name patches relate, and copy them to the right place
11071112
if paths['patch_files']:
@@ -1144,8 +1149,8 @@ def _easyconfigs_pr_common(paths, ecs, start_branch=None, pr_branch=None, start_
11441149
# only consider new easyconfig files for dependencies (not updated ones)
11451150
for idx in range(len(all_dep_info['ecs'])):
11461151
if all_dep_info['new'][idx]:
1147-
for key, values in dep_info.items():
1148-
values.append(all_dep_info[key][idx])
1152+
for key, info in dep_info.items():
1153+
info.append(all_dep_info[key][idx])
11491154

11501155
# checkout target branch
11511156
if pr_branch is None:
@@ -1788,7 +1793,7 @@ def post_pr_labels(pr, labels):
17881793

17891794
pr_url = g.repos[pr_target_account][pr_target_repo].issues[pr]
17901795
try:
1791-
status, data = pr_url.labels.post(body=labels)
1796+
status, _ = pr_url.labels.post(body=labels)
17921797
if status == HTTP_STATUS_OK:
17931798
print_msg("Added labels %s to PR#%s" % (', '.join(labels), pr), log=_log, prefix=False)
17941799
return True
@@ -2104,13 +2109,11 @@ def new_pr(paths, ecs, title=None, descr=None, commit_msg=None):
21042109
patch = patch[0]
21052110
elif isinstance(patch, dict):
21062111
patch_info = {}
2107-
for key in patch.keys():
2108-
patch_info[key] = patch[key]
2109-
if 'name' not in patch_info.keys():
2110-
raise EasyBuildError(
2111-
"Wrong patch spec '%s', when using a dict 'name' entry must be supplied", str(patch),
2112-
exit_code=EasyBuildExit.EASYCONFIG_ERROR
2113-
)
2112+
for key, cur_patch in patch.items():
2113+
patch_info[key] = cur_patch
2114+
if 'name' not in patch_info:
2115+
raise EasyBuildError(f"Wrong patch spec '{patch}', when using a dict 'name' entry must be supplied",
2116+
exit_code=EasyBuildExit.EASYCONFIG_ERROR)
21142117
patch = patch_info['name']
21152118

21162119
if patch not in paths['patch_files'] and not os.path.isfile(os.path.join(os.path.dirname(ec_path),

test/framework/easyconfig.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,30 @@ def test_start_dir_template(self):
14421442
self.assertIn('start_dir in extension configure is %s &&' % ext_start_dir, logtxt)
14431443
self.assertIn('start_dir in extension build is %s &&' % ext_start_dir, logtxt)
14441444

1445+
def test_rpath_template(self):
1446+
"""Test the %(rpath)s template"""
1447+
test_easyconfigs = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'easyconfigs', 'test_ecs')
1448+
toy_ec = os.path.join(test_easyconfigs, 't', 'toy', 'toy-0.0.eb')
1449+
1450+
test_ec = os.path.join(self.test_prefix, 'test.eb')
1451+
test_ec_txt = read_file(toy_ec)
1452+
test_ec_txt += "configopts = '--with-rpath=%(rpath_enabled)s'"
1453+
write_file(test_ec, test_ec_txt)
1454+
1455+
ec = EasyConfig(test_ec)
1456+
expected = '--with-rpath=true' if get_os_name() == 'Linux' else '--with-rpath=false'
1457+
self.assertEqual(ec['configopts'], expected)
1458+
1459+
# force True
1460+
update_build_option('rpath', True)
1461+
ec = EasyConfig(test_ec)
1462+
self.assertEqual(ec['configopts'], "--with-rpath=true")
1463+
1464+
# force False
1465+
update_build_option('rpath', False)
1466+
ec = EasyConfig(test_ec)
1467+
self.assertEqual(ec['configopts'], "--with-rpath=false")
1468+
14451469
def test_sysroot_template(self):
14461470
"""Test the %(sysroot)s template"""
14471471

@@ -3483,6 +3507,8 @@ def test_template_constant_dict(self):
34833507

34843508
arch_regex = re.compile('^[a-z0-9_]+$')
34853509

3510+
rpath = 'true' if get_os_name() == 'Linux' else 'false'
3511+
34863512
expected = {
34873513
'bitbucket_account': 'gzip',
34883514
'github_account': 'gzip',
@@ -3492,6 +3518,7 @@ def test_template_constant_dict(self):
34923518
'nameletter': 'g',
34933519
'nameletterlower': 'g',
34943520
'parallel': None,
3521+
'rpath_enabled': rpath,
34953522
'software_commit': '',
34963523
'sysroot': '',
34973524
'toolchain_name': 'foss',
@@ -3576,6 +3603,7 @@ def test_template_constant_dict(self):
35763603
'pyminver': '7',
35773604
'pyshortver': '3.7',
35783605
'pyver': '3.7.2',
3606+
'rpath_enabled': rpath,
35793607
'software_commit': '',
35803608
'sysroot': '',
35813609
'version': '0.01',
@@ -3642,6 +3670,7 @@ def test_template_constant_dict(self):
36423670
'namelower': 'foo',
36433671
'nameletter': 'f',
36443672
'nameletterlower': 'f',
3673+
'rpath_enabled': rpath,
36453674
'software_commit': '',
36463675
'sysroot': '',
36473676
'version': '1.2.3',

test/framework/options.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4708,7 +4708,7 @@ def test_github_new_update_pr(self):
47084708
'--git-working-dirs-path=%s' % git_working_dir,
47094709
':bzip2-1.0.6.eb',
47104710
])
4711-
error_msg = "A meaningful commit message must be specified via --pr-commit-msg"
4711+
error_msg = "A meaningful commit message must be specified via --pr-commit-msg.*\nDeleted: bzip2-1.0.6.eb"
47124712

47134713
self.mock_stdout(True)
47144714
self.assertErrorRegex(EasyBuildError, error_msg, self.eb_main, args, raise_error=True, testing=False)
@@ -4787,7 +4787,8 @@ def test_github_new_update_pr(self):
47874787
gcc_ec,
47884788
'-D',
47894789
]
4790-
error_msg = "A meaningful commit message must be specified via --pr-commit-msg"
4790+
error_msg = "A meaningful commit message must be specified via --pr-commit-msg.*\n"
4791+
error_msg += "Modified: " + os.path.basename(gcc_ec)
47914792
self.mock_stdout(True)
47924793
self.assertErrorRegex(EasyBuildError, error_msg, self.eb_main, args, raise_error=True)
47934794
self.mock_stdout(False)

0 commit comments

Comments
 (0)