Repository: easybuilders/easybuild-easyblocks

Issue:
The Rosetta EasyBlock is broken with regards to --module-only
When regenerating module files with --module-only, EasyBuild fails with (formatted for readability):

```
EasyBuild crashed with an error (at ?:124 in __init__):
Sanity check failed:
no file of ('bin/AbinitioRelax.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/backrub.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/cluster.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/combine_silent.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/extract_pdbs.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/idealize_jd2.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/packstat.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/relax.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/score_jd2.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20,
no file of ('bin/score.mpi.linuxNonerelease',) in .../software/Rosetta/3.7-goolf-PReSTO-1.7.20
(at easybuild/framework/easyblock.py:2062 in _sanity_check_step)
```

This is because of the use of `self.cxx` in the sanity check:
```python
    def sanity_check_step(self):
        """Custom sanity check for Rosetta."""

        infix = ''
        if self.toolchain.options.get('usempi', None):
            infix = 'mpi.'

        binaries = ["AbinitioRelax", "backrub", "cluster", "combine_silent", "extract_pdbs",
                    "idealize_jd2", "packstat", "relax", "score_jd2", "score"]
        custom_paths = {
            'files':["bin/%s.%slinux%srelease" % (x, infix, self.cxx) for x in binaries],
            'dirs':[],
        }
        super(EB_Rosetta, self).sanity_check_step(custom_paths=custom_paths)
```

which is only set in the configure step (which is not executed when running with --module-only):
```python
    def configure_step(self):
        """
        Configure build by creating tools/build/user.settings from configure options.
        """
        # construct build options
        defines = ['NDEBUG']
        self.cfg.update('buildopts', "mode=release")

        self.cxx = os.getenv('CC_SEQ')
        if self.cxx is None:
            self.cxx = os.getenv('CC')
        cxx_ver = None
        if self.toolchain.comp_family() in [toolchain.GCC]:  #@UndefinedVariable
            cxx_ver = '.'.join(get_software_version('GCC').split('.')[:2])
        elif self.toolchain.comp_family() in [toolchain.INTELCOMP]:  #@UndefinedVariable
            cxx_ver = '.'.join(get_icc_version().split('.')[:2])
        else:
            raise EasyBuildError("Don't know how to determine C++ compiler version.")
        self.cfg.update('buildopts', "cxx=%s cxx_ver=%s" % (self.cxx, cxx_ver))

        [...]
```


Discussion:
Thanks for the bug report @tobbez!

Are you up for looking into a fix yourself for this?

The best way would probably be to put the code that defines `self.cxx` in a dedicated method, and check in `sanity_check_step` whether `self.cxx` is `None`; if it is, the method that defines `self.cxx` should be called first.

Resolving patch:
diff --git a/easybuild/easyblocks/r/rosetta.py b/easybuild/easyblocks/r/rosetta.py
--- a/easybuild/easyblocks/r/rosetta.py
+++ b/easybuild/easyblocks/r/rosetta.py
@@ -81,6 +81,12 @@ def extract_step(self):
         except OSError, err:
             raise EasyBuildError("Getting Rosetta sources dir ready failed: %s", err)
 
+    def detect_cxx(self):
+        """Detect compiler name"""
+        self.cxx = os.getenv('CC_SEQ')
+        if self.cxx is None:
+            self.cxx = os.getenv('CC')
+
     def configure_step(self):
         """
         Configure build by creating tools/build/user.settings from configure options.
@@ -89,9 +95,7 @@ def configure_step(self):
         defines = ['NDEBUG']
         self.cfg.update('buildopts', "mode=release")
 
-        self.cxx = os.getenv('CC_SEQ')
-        if self.cxx is None:
-            self.cxx = os.getenv('CC')
+        self.detect_cxx()
         cxx_ver = None
         if self.toolchain.comp_family() in [toolchain.GCC]:  #@UndefinedVariable
             cxx_ver = '.'.join(get_software_version('GCC').split('.')[:2])
@@ -258,6 +262,11 @@ def extract_and_copy(dirname_tmpl, optional=False):
     def sanity_check_step(self):
         """Custom sanity check for Rosetta."""
 
+        # self.cxx is usually set by the configure step, but if configure is
+        # not executed (e.g. with --module-only), we need to set it here.
+        if self.cxx is None:
+            self.detect_cxx()
+
         infix = ''
         if self.toolchain.options.get('usempi', None):
             infix = 'mpi.'


Test patch: