Skip to content

Commit 0f78649

Browse files
authored
Merge pull request #3319 from akesandgren/fix-crayce-problems
Fix problems with CrayCCE processing when there are no actual external modules
2 parents ed5ba4a + 1a58c28 commit 0f78649

File tree

7 files changed

+156
-48
lines changed

7 files changed

+156
-48
lines changed

easybuild/toolchains/mpi/craympich.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class CrayMPICH(Mpi):
4040
"""Generic support for using Cray compiler wrappers"""
4141
# MPI support
4242
# no separate module, Cray compiler drivers always provide MPI support
43-
MPI_MODULE_NAME = []
43+
MPI_MODULE_NAME = None
4444
MPI_FAMILY = TC_CONSTANT_MPICH
4545
MPI_TYPE = TC_CONSTANT_MPI_TYPE_MPICH
4646

easybuild/tools/module_naming_scheme/hierarchical_mns.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141
CORE = 'Core'
4242
COMPILER = 'Compiler'
4343
MPI = 'MPI'
44+
TOOLCHAIN = 'Toolchain'
4445

4546
MODULECLASS_COMPILER = 'compiler'
4647
MODULECLASS_MPI = 'mpi'
48+
MODULECLASS_TOOLCHAIN = 'toolchain'
4749

4850
GCCCORE = GCCcore.NAME
4951

@@ -107,7 +109,11 @@ def det_toolchain_compilers_name_version(self, tc_comps):
107109
# no compiler in toolchain, system toolchain
108110
res = None
109111
elif len(tc_comps) == 1:
110-
res = (tc_comps[0]['name'], self.det_full_version(tc_comps[0]))
112+
tc_comp = tc_comps[0]
113+
if tc_comp is None:
114+
res = None
115+
else:
116+
res = (tc_comp['name'], self.det_full_version(tc_comp))
111117
else:
112118
comp_versions = dict([(comp['name'], self.det_full_version(comp)) for comp in tc_comps])
113119
comp_names = comp_versions.keys()
@@ -135,6 +141,10 @@ def det_module_subdir(self, ec):
135141
if tc_comps is None:
136142
# no compiler in toolchain, system toolchain => Core module
137143
subdir = CORE
144+
elif tc_comps == [None]:
145+
# no info on toolchain compiler (cfr. Cray toolchains),
146+
# then use toolchain name/version
147+
subdir = os.path.join(TOOLCHAIN, ec.toolchain.name, ec.toolchain.version)
138148
else:
139149
tc_comp_name, tc_comp_ver = self.det_toolchain_compilers_name_version(tc_comps)
140150
tc_mpi = det_toolchain_mpi(ec)
@@ -223,6 +233,10 @@ def det_modpath_extensions(self, ec):
223233
fullver = self.det_full_version(ec)
224234
paths.append(os.path.join(MPI, tc_comp_name, tc_comp_ver, ec['name'], fullver))
225235

236+
# special case for Cray toolchains
237+
elif modclass == MODULECLASS_TOOLCHAIN and tc_comp_info is None and ec.name.startswith('Cray'):
238+
paths.append(os.path.join(TOOLCHAIN, ec.name, ec.version))
239+
226240
return paths
227241

228242
def expand_toolchain_load(self, ec=None):

easybuild/tools/toolchain/mpi.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ def _set_mpi_variables(self):
242242
if not self.options.get('32bit', None):
243243
suffix = '64'
244244

245-
for root in self.get_software_root(self.MPI_MODULE_NAME):
245+
# take into account that MPI_MODULE_NAME could be None (see Cray toolchains)
246+
for root in self.get_software_root(self.MPI_MODULE_NAME or []):
246247
self.variables.append_exists('MPI_LIB_STATIC', root, lib_dir, filename="lib%s.a" % self.MPI_LIBRARY_NAME,
247248
suffix=suffix)
248249
self.variables.append_exists('MPI_LIB_SHARED', root, lib_dir, filename="lib%s.so" % self.MPI_LIBRARY_NAME,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
easyblock = 'ConfigureMake'
2+
3+
name = 'HPL'
4+
version = '2.1'
5+
6+
homepage = 'http://www.netlib.org/benchmark/hpl/'
7+
description = "HPL, you know, LINPACK"
8+
9+
toolchain = {'name': 'CrayCCE', 'version': '5.1.29'}
10+
11+
source_urls = ['http://www.netlib.org/benchmark/%(namelower)s']
12+
sources = [SOURCELOWER_TAR_GZ]
13+
14+
moduleclass = 'tools'

test/framework/filetools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,7 @@ def test_index_functions(self):
18161816
# test with specified path with and without trailing '/'s
18171817
for path in [test_ecs, test_ecs + '/', test_ecs + '//']:
18181818
index = ft.create_index(path)
1819-
self.assertEqual(len(index), 81)
1819+
self.assertEqual(len(index), 82)
18201820

18211821
expected = [
18221822
os.path.join('b', 'bzip2', 'bzip2-1.0.6-GCC-4.9.2.eb'),

test/framework/module_generator.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,11 @@ def test_ec(ecfile, short_modname, mod_subdir, modpath_exts, user_modpath_exts,
12731273
['MPI/intel-CUDA/%s-5.5.22/impi/5.1.2.150' % iccver],
12741274
['MPI/intel-CUDA/%s-5.5.22/impi/5.1.2.150' % iccver],
12751275
['Core']),
1276+
'CrayCCE-5.1.29.eb': ('CrayCCE/5.1.29', 'Core',
1277+
['Toolchain/CrayCCE/5.1.29'],
1278+
['Toolchain/CrayCCE/5.1.29'],
1279+
['Core']),
1280+
'HPL-2.1-CrayCCE-5.1.29.eb': ('HPL/2.1', 'Toolchain/CrayCCE/5.1.29', [], [], ['Core']),
12761281
}
12771282
for ecfile, mns_vals in test_ecs.items():
12781283
test_ec(ecfile, *mns_vals)

test/framework/options.py

Lines changed: 118 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4265,54 +4265,128 @@ def test_list_prs(self):
42654265

42664266
def test_list_software(self):
42674267
"""Test --list-software and --list-installed-software."""
4268-
test_ecs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'v1.0')
4269-
args = [
4270-
'--list-software',
4271-
'--robot-paths=%s' % test_ecs,
4272-
]
4273-
txt, _ = self._run_mock_eb(args, do_build=True, raise_error=True, testing=False)
4274-
expected = '\n'.join([
4275-
"== Processed 5/5 easyconfigs...",
4276-
"== Found 2 different software packages",
4277-
'',
4278-
"* GCC",
4279-
"* gzip",
4280-
'',
4268+
4269+
# copy selected test easyconfigs for testing --list-*software options with;
4270+
# full test is a nuisance, because all dependencies must be available and toolchains like intel must have
4271+
# all expected components when testing with HierarchicalMNS (which the test easyconfigs don't always have)
4272+
topdir = os.path.dirname(os.path.abspath(__file__))
4273+
4274+
cray_ec = os.path.join(topdir, 'easyconfigs', 'test_ecs', 'c', 'CrayCCE', 'CrayCCE-5.1.29.eb')
4275+
gcc_ec = os.path.join(topdir, 'easyconfigs', 'test_ecs', 'g', 'GCC', 'GCC-4.6.3.eb')
4276+
gzip_ec = os.path.join(topdir, 'easyconfigs', 'v1.0', 'g', 'gzip', 'gzip-1.4-GCC-4.6.3.eb')
4277+
gzip_system_ec = os.path.join(topdir, 'easyconfigs', 'v1.0', 'g', 'gzip', 'gzip-1.4.eb')
4278+
4279+
test_ecs = os.path.join(self.test_prefix, 'test_ecs')
4280+
for ec in [cray_ec, gcc_ec, gzip_ec, gzip_system_ec]:
4281+
subdirs = os.path.dirname(ec).split(os.path.sep)[-2:]
4282+
target_dir = os.path.join(test_ecs, *subdirs)
4283+
mkdir(target_dir, parents=True)
4284+
copy_file(ec, target_dir)
4285+
4286+
# add (fake) HPL easyconfig using CrayCCE toolchain
4287+
# (required to trigger bug reported in https://github.com/easybuilders/easybuild-framework/issues/3265)
4288+
hpl_cray_ec_txt = '\n'.join([
4289+
'easyblock = "ConfigureMake"',
4290+
'name = "HPL"',
4291+
'version = "2.3"',
4292+
"homepage = 'http://www.netlib.org/benchmark/hpl/'",
4293+
'description = "HPL"',
4294+
'toolchain = {"name": "CrayCCE", "version": "5.1.29"}',
42814295
])
4282-
self.assertTrue(txt.endswith(expected))
4296+
hpl_cray_ec = os.path.join(self.test_prefix, 'test_ecs', 'h', 'HPL', 'HPL-2.3-CrayCCE-5.1.29.eb')
4297+
write_file(hpl_cray_ec, hpl_cray_ec_txt)
42834298

4284-
args = [
4285-
'--list-software=detailed',
4286-
'--output-format=rst',
4287-
'--robot-paths=%s' % test_ecs,
4288-
]
4289-
txt, _ = self._run_mock_eb(args, testing=False)
4290-
self.assertTrue(re.search(r'^\*GCC\*', txt, re.M))
4291-
self.assertTrue(re.search(r'^``4.6.3``\s+``system``', txt, re.M))
4292-
self.assertTrue(re.search(r'^\*gzip\*', txt, re.M))
4293-
self.assertTrue(re.search(r'^``1.5``\s+``foss/2018a``,\s+``intel/2018a``', txt, re.M))
4299+
# put dummy Core/GCC/4.6.3 in place
4300+
modpath = os.path.join(self.test_prefix, 'modules')
4301+
write_file(os.path.join(modpath, 'Core', 'GCC', '4.6.3'), '#%Module')
4302+
self.modtool.use(modpath)
42944303

4295-
args = [
4296-
'--list-installed-software',
4297-
'--output-format=rst',
4298-
'--robot-paths=%s' % test_ecs,
4299-
]
4300-
txt, _ = self._run_mock_eb(args, testing=False, raise_error=True)
4301-
self.assertTrue(re.search(r'== Processed 5/5 easyconfigs...', txt, re.M))
4302-
self.assertTrue(re.search(r'== Found 2 different software packages', txt, re.M))
4303-
self.assertTrue(re.search(r'== Retained 1 installed software packages', txt, re.M))
4304-
self.assertTrue(re.search(r'^\* GCC', txt, re.M))
4305-
self.assertFalse(re.search(r'gzip', txt, re.M))
4304+
# test with different module naming scheme active
4305+
# (see https://github.com/easybuilders/easybuild-framework/issues/3265)
4306+
for mns in ['EasyBuildMNS', 'HierarchicalMNS']:
43064307

4307-
args = [
4308-
'--list-installed-software=detailed',
4309-
'--robot-paths=%s' % test_ecs,
4310-
]
4311-
txt, _ = self._run_mock_eb(args, testing=False)
4312-
self.assertTrue(re.search(r'^== Retained 1 installed software packages', txt, re.M))
4313-
self.assertTrue(re.search(r'^\* GCC', txt, re.M))
4314-
self.assertTrue(re.search(r'^\s+\* GCC v4.6.3: system', txt, re.M))
4315-
self.assertFalse(re.search(r'gzip', txt, re.M))
4308+
args = [
4309+
'--list-software',
4310+
'--robot-paths=%s' % test_ecs,
4311+
'--module-naming-scheme=%s' % mns,
4312+
]
4313+
txt, _ = self._run_mock_eb(args, do_build=True, raise_error=True, testing=False, verbose=True)
4314+
4315+
patterns = [
4316+
r"^.*\s*== Processed 5/5 easyconfigs...",
4317+
r"^== Found 4 different software packages",
4318+
r"^\* CrayCCE",
4319+
r"^\* GCC",
4320+
r"^\* gzip",
4321+
r"^\* HPL",
4322+
]
4323+
for pattern in patterns:
4324+
regex = re.compile(pattern, re.M)
4325+
self.assertTrue(regex.search(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt))
4326+
4327+
args = [
4328+
'--list-software=detailed',
4329+
'--output-format=rst',
4330+
'--robot-paths=%s' % test_ecs,
4331+
'--module-naming-scheme=%s' % mns,
4332+
]
4333+
txt, _ = self._run_mock_eb(args, testing=False, raise_error=True, verbose=True)
4334+
4335+
patterns = [
4336+
r"^.*\s*== Processed 5/5 easyconfigs...",
4337+
r"^== Found 4 different software packages",
4338+
r'^\*CrayCCE\*',
4339+
r'^``5.1.29``\s+``system``',
4340+
r'^\*GCC\*',
4341+
r'^``4.6.3``\s+``system``',
4342+
r'^\*gzip\*',
4343+
r'^``1.4`` ``GCC/4.6.3``, ``system``',
4344+
]
4345+
for pattern in patterns:
4346+
regex = re.compile(pattern, re.M)
4347+
self.assertTrue(regex.search(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt))
4348+
4349+
args = [
4350+
'--list-installed-software',
4351+
'--output-format=rst',
4352+
'--robot-paths=%s' % test_ecs,
4353+
'--module-naming-scheme=%s' % mns,
4354+
]
4355+
txt, _ = self._run_mock_eb(args, testing=False, raise_error=True, verbose=True)
4356+
4357+
patterns = [
4358+
r"^.*\s*== Processed 5/5 easyconfigs...",
4359+
r"^== Found 4 different software packages",
4360+
r"^== Retained 1 installed software packages",
4361+
r'^\* GCC',
4362+
]
4363+
for pattern in patterns:
4364+
regex = re.compile(pattern, re.M)
4365+
self.assertTrue(regex.search(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt))
4366+
4367+
self.assertFalse(re.search(r'gzip', txt, re.M))
4368+
self.assertFalse(re.search(r'CrayCCE', txt, re.M))
4369+
4370+
args = [
4371+
'--list-installed-software=detailed',
4372+
'--robot-paths=%s' % test_ecs,
4373+
'--module-naming-scheme=%s' % mns,
4374+
]
4375+
txt, _ = self._run_mock_eb(args, testing=False, raise_error=True, verbose=True)
4376+
4377+
patterns = [
4378+
r"^.*\s*== Processed 5/5 easyconfigs...",
4379+
r"^== Found 4 different software packages",
4380+
r"^== Retained 1 installed software packages",
4381+
r'^\* GCC',
4382+
r'^\s+\* GCC v4.6.3: system',
4383+
]
4384+
for pattern in patterns:
4385+
regex = re.compile(pattern, re.M)
4386+
self.assertTrue(regex.search(txt), "Pattern '%s' found in: %s" % (regex.pattern, txt))
4387+
4388+
self.assertFalse(re.search(r'gzip', txt, re.M))
4389+
self.assertFalse(re.search(r'CrayCCE', txt, re.M))
43164390

43174391
def test_parse_optarch(self):
43184392
"""Test correct parsing of optarch option."""

0 commit comments

Comments
 (0)