Repository: easybuilders/easybuild-framework

Issue:
imkl listed multiple times in --list-toolchains
Is it normal that imkl is listed a multiple times in each of the toolchains it's part of? I don't recall that was the case in previous versions.

```
$ eb --list-toolchains | grep mkl
    gimkl: GCC, imkl, imkl, imkl, imkl, imkl, impi
    ictce: icc, ifort, imkl, imkl, imkl, imkl, imkl, impi
    impmkl: MPICH2, icc, ifort, imkl, imkl, imkl, imkl, imkl
    intel: icc, ifort, imkl, imkl, imkl, imkl, imkl, impi
    iomkl: OpenMPI, icc, ifort, imkl, imkl, imkl, imkl, imkl
    ismkl: MPICH2, icc, ifort, imkl, imkl, imkl, imkl, imkl
$ eb --version
This is EasyBuild 1.14.0 (framework: 1.14.0, easyblocks: 1.14.0) on host localhost
```



Discussion:
Yeah, that's a bug. 1.13 doesn't have that.


Resolving patch:
diff --git a/easybuild/toolchains/iimpi.py b/easybuild/toolchains/iimpi.py
new file mode 100755
--- /dev/null
+++ b/easybuild/toolchains/iimpi.py
@@ -0,0 +1,42 @@
+##
+# Copyright 2012-2014 Ghent University
+#
+# This file is part of EasyBuild,
+# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
+# with support of Ghent University (http://ugent.be/hpc),
+# the Flemish Supercomputer Centre (VSC) (https://vscentrum.be/nl/en),
+# the Hercules foundation (http://www.herculesstichting.be/in_English)
+# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
+#
+# http://github.com/hpcugent/easybuild
+#
+# EasyBuild is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation v2.
+#
+# EasyBuild is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with EasyBuild.  If not, see <http://www.gnu.org/licenses/>.
+##
+"""
+EasyBuild support for intel compiler toolchain (includes Intel compilers (icc, ifort), Intel MPI).
+
+@author: Stijn De Weirdt (Ghent University)
+@author: Kenneth Hoste (Ghent University)
+"""
+
+from easybuild.toolchains.compiler.inteliccifort import IntelIccIfort
+from easybuild.toolchains.fft.intelfftw import IntelFFTW
+from easybuild.toolchains.mpi.intelmpi import IntelMPI
+from easybuild.toolchains.linalg.intelmkl import IntelMKL
+
+
+class Iimpi(IntelIccIfort, IntelMPI):
+    """
+    Compiler toolchain with Intel compilers (icc/ifort), Intel MPI.
+    """
+    NAME = 'iimpi'
diff --git a/easybuild/tools/options.py b/easybuild/tools/options.py
--- a/easybuild/tools/options.py
+++ b/easybuild/tools/options.py
@@ -37,6 +37,7 @@
 import re
 import sys
 from distutils.version import LooseVersion
+from vsc.utils.missing import nub
 
 from easybuild.framework.easyblock import EasyBlock
 from easybuild.framework.easyconfig.constants import constant_documentation
@@ -572,8 +573,8 @@ def avail_toolchains(self):
 
         for (tcname, tcc) in tclist:
             tc = tcc(version='1.2.3')  # version doesn't matter here, but something needs to be there
-            tc_elems = [e for es in tc.definition().values() for e in es]
-            txt.append("\t%s: %s" % (tcname, ', '.join(sorted(tc_elems))))
+            tc_elems = nub(sorted([e for es in tc.definition().values() for e in es]))
+            txt.append("\t%s: %s" % (tcname, ', '.join(tc_elems)))
 
         return '\n'.join(txt)
 


Test patch:
diff --git a/test/framework/options.py b/test/framework/options.py
--- a/test/framework/options.py
+++ b/test/framework/options.py
@@ -396,12 +396,20 @@ def test__list_toolchains(self):
 
         info_msg = r"INFO List of known toolchains \(toolchainname: module\[,module\.\.\.\]\):"
         self.assertTrue(re.search(info_msg, outtxt), "Info message with list of known compiler toolchains")
-        for tc in ["dummy", "goalf", "ictce"]:
-            res = re.findall("^\s*%s: " % tc, outtxt, re.M)
+        # toolchain elements should be in alphabetical order
+        tcs = {
+            'dummy': [],
+            'goalf': ['ATLAS', 'BLACS', 'FFTW', 'GCC', 'OpenMPI', 'ScaLAPACK'],
+            'ictce': ['icc', 'ifort', 'imkl', 'impi'],
+        }
+        for tc, tcelems in tcs.items():
+            res = re.findall("^\s*%s: .*" % tc, outtxt, re.M)
             self.assertTrue(res, "Toolchain %s is included in list of known compiler toolchains" % tc)
             # every toolchain should only be mentioned once
             n = len(res)
             self.assertEqual(n, 1, "Toolchain %s is only mentioned once (count: %d)" % (tc, n))
+            # make sure definition is correct (each element only named once, in alphabetical order)
+            self.assertEqual("\t%s: %s" % (tc, ', '.join(tcelems)), res[0])
 
         if os.path.exists(dummylogfn):
             os.remove(dummylogfn)