Skip to content

Commit 825e22f

Browse files
authored
Merge pull request #3047 from bear-rsg/arch-specific-deps-for-java
add support for specifying different dependency version based on architecture
2 parents 752ce42 + 37b3421 commit 825e22f

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

easybuild/framework/easyconfig/easyconfig.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
from easybuild.tools.module_naming_scheme.utilities import det_hidden_modname, is_valid_module_name
6969
from easybuild.tools.modules import modules_tool
7070
from easybuild.tools.py2vs3 import OrderedDict, create_base_metaclass, string_type
71-
from easybuild.tools.systemtools import check_os_dependency
71+
from easybuild.tools.systemtools import check_os_dependency, get_cpu_architecture
7272
from easybuild.tools.toolchain.toolchain import SYSTEM_TOOLCHAIN_NAME, is_system_toolchain
7373
from easybuild.tools.toolchain.toolchain import TOOLCHAIN_CAPABILITIES, TOOLCHAIN_CAPABILITY_CUDA
7474
from easybuild.tools.toolchain.utilities import get_toolchain, search_toolchain
@@ -1229,6 +1229,31 @@ def get_parsed_multi_deps(self):
12291229

12301230
return multi_deps
12311231

1232+
def find_dep_version_match(self, dep_version):
1233+
"""Identify the correct version for this system from the choices provided. This returns the version to use."""
1234+
if isinstance(dep_version, string_type):
1235+
self.log.debug("Version is already a string ('%s'), OK", dep_version)
1236+
return dep_version
1237+
elif dep_version is None:
1238+
self.log.debug("Version is None, OK")
1239+
return None
1240+
elif isinstance(dep_version, dict):
1241+
# figure out matches based on dict keys (after splitting on '=')
1242+
my_arch_key = 'arch=%s' % get_cpu_architecture()
1243+
arch_keys = [x for x in dep_version.keys() if x.startswith('arch=')]
1244+
other_keys = [x for x in dep_version.keys() if x not in arch_keys]
1245+
if other_keys:
1246+
raise EasyBuildError("Unexpected keys in version: %s. Only 'arch=' keys are supported", other_keys)
1247+
if arch_keys:
1248+
if my_arch_key in dep_version:
1249+
ver = dep_version[my_arch_key]
1250+
self.log.info("Version selected from %s using key %s: %s", dep_version, my_arch_key, ver)
1251+
return ver
1252+
else:
1253+
raise EasyBuildError("No matches for version in %s (looking for %s)", dep_version, my_arch_key)
1254+
1255+
raise EasyBuildError("Unknown value type for version: %s", dep_version)
1256+
12321257
# private method
12331258
def _parse_dependency(self, dep, hidden=False, build_only=False):
12341259
"""
@@ -1272,6 +1297,7 @@ def _parse_dependency(self, dep, hidden=False, build_only=False):
12721297
# provides information on what this module represents (software name/version, install prefix, ...)
12731298
'external_module_metadata': {},
12741299
}
1300+
12751301
if isinstance(dep, dict):
12761302
dependency.update(dep)
12771303

@@ -1308,6 +1334,9 @@ def _parse_dependency(self, dep, hidden=False, build_only=False):
13081334
else:
13091335
raise EasyBuildError("Dependency %s of unsupported type: %s", dep, type(dep))
13101336

1337+
# Find the version to use on this system
1338+
dependency['version'] = self.find_dep_version_match(dependency['version'])
1339+
13111340
if dependency['external_module']:
13121341
# check whether the external module is hidden
13131342
if dependency['full_mod_name'].split('/')[-1].startswith('.'):

test/framework/easyconfig.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,50 @@ def test_local_vars_detection(self):
32003200
expected_error += "an_unknown_key, foobar, test_list, zzz_test"
32013201
self.assertErrorRegex(EasyBuildError, expected_error, EasyConfig, test_ec, local_var_naming_check='error')
32023202

3203+
def test_arch_specific_dependency(self):
3204+
"""Tests that the correct version is chosen for this architecture"""
3205+
3206+
my_arch = st.get_cpu_architecture()
3207+
expected_version = '1.2.3'
3208+
dep_str = "[('foo', {'arch=%s': '%s', 'arch=Foo': 'bar'})]" % (my_arch, expected_version)
3209+
3210+
test_ec = os.path.join(self.test_prefix, 'test.eb')
3211+
test_ectxt = '\n'.join([
3212+
"easyblock = 'ConfigureMake'",
3213+
"name = 'test'",
3214+
"version = '0.2'",
3215+
"homepage = 'https://example.com'",
3216+
"description = 'test'",
3217+
"toolchain = SYSTEM",
3218+
"dependencies = %s" % dep_str,
3219+
])
3220+
write_file(test_ec, test_ectxt)
3221+
3222+
ec = EasyConfig(test_ec)
3223+
self.assertEqual(ec.dependencies()[0]['version'], expected_version)
3224+
3225+
def test_unexpected_version_keys_caught(self):
3226+
"""Tests that unexpected keys in a version dictionary are caught"""
3227+
3228+
my_arch = st.get_cpu_architecture()
3229+
expected_version = '1.2.3'
3230+
3231+
for dep_str in ("[('foo', {'bar=%s': '%s', 'arch=Foo': 'bar'})]" % (my_arch, expected_version),
3232+
"[('foo', {'blah': 'bar'})]"):
3233+
test_ec = os.path.join(self.test_prefix, 'test.eb')
3234+
test_ectxt = '\n'.join([
3235+
"easyblock = 'ConfigureMake'",
3236+
"name = 'test'",
3237+
"version = '0.2'",
3238+
"homepage = 'https://example.com'",
3239+
"description = 'test'",
3240+
"toolchain = SYSTEM",
3241+
"dependencies = %s" % dep_str,
3242+
])
3243+
write_file(test_ec, test_ectxt)
3244+
3245+
self.assertRaises(EasyBuildError, EasyConfig, test_ec)
3246+
32033247

32043248
def suite():
32053249
""" returns all the testcases in this module """

0 commit comments

Comments
 (0)