Repository: easybuilders/easybuild-easyblocks

Issue:
Sanity check fails for the d3q plugin in QE 6.4 and later as the list of binaries is wrong.
https://github.com/easybuilders/easybuild-easyblocks/blob/1caabcf71974c608084f6fe238993eeec0afa25c/easybuild/easyblocks/q/quantumespresso.py#L487

Versions of d3q used in QE 6.4 (1.1.4 and 1.1.5), QE6.5 and QE 6.6 (1.1.7 in both versions) don't contain d3_import3py.x so the sanity check fails for those versions of QuantumESPRESSO when build with d3q (I didn't try yet with 6.6 which was released just a couple of days ago, but I did check the version of d3q).

Other executables have been added throughout versions and are missing in the list, but that is not so much a problem as it doesn't break the sanity check.


Discussion:

Resolving patch:
diff --git a/easybuild/easyblocks/q/quantumespresso.py b/easybuild/easyblocks/q/quantumespresso.py
--- a/easybuild/easyblocks/q/quantumespresso.py
+++ b/easybuild/easyblocks/q/quantumespresso.py
@@ -204,6 +204,13 @@ def configure_step(self):
         # always include -w to supress warnings
         dflags.append('-w')
 
+        if LooseVersion(self.version) >= LooseVersion("6.6"):
+            dflags.append(" -Duse_beef")
+            libbeef = get_software_root("libbeef")
+            if libbeef:
+                repls.append(('BEEF_LIBS_SWITCH', 'external', False))
+                repls.append(('BEEF_LIBS', '%s/lib/libbeef.a' % libbeef, False))
+
         repls.append(('DFLAGS', ' '.join(dflags), False))
 
         # complete C/Fortran compiler and LD flags
@@ -266,6 +273,15 @@ def configure_step(self):
                                       "\t$(MPIF90) $(F90FLAGS) -c $*.F90 -o $*.o",
                                       line)
 
+                if LooseVersion(self.version) >= LooseVersion("6.6"):
+                    # fix order of BEEF_LIBS in QE_LIBS
+                    line = re.sub(r"^(QELIBS\s*=[ \t]*)(.*) \$\(BEEF_LIBS\) (.*)$",
+                                  r"QELIBS = $(BEEF_LIBS) \2 \3", line)
+
+                    # use FCCPP instead of CPP for Fortran headers
+                    line = re.sub(r"\t\$\(CPP\) \$\(CPPFLAGS\) \$< -o \$\*\.fh",
+                                  "\t$(FCCPP) $(CPPFLAGS) $< -o $*.fh", line)
+
                 sys.stdout.write(line)
         except IOError as err:
             raise EasyBuildError("Failed to patch %s: %s", fn, err)
@@ -367,7 +383,11 @@ def copy_binaries(path):
                         copy_file(full_path, bindir)
 
         if 'upf' in targets or 'all' in targets:
-            copy_binaries('upftools')
+            if LooseVersion(self.version) < LooseVersion("6.6"):
+                copy_binaries('upftools')
+            else:
+                copy_binaries('upflib')
+                copy_file(os.path.join(self.cfg['start_dir'], 'upflib', 'fixfiles.py'), bindir)
 
         if 'want' in targets:
             copy_binaries('WANT')
@@ -446,16 +466,19 @@ def sanity_check_step(self):
 
         upftools = []
         if 'upf' in targets or 'all' in targets:
-            upftools = ["casino2upf.x", "cpmd2upf.x", "fhi2upf.x", "fpmd2upf.x", "ncpp2upf.x",
-                        "oldcp2upf.x", "read_upf_tofile.x", "rrkj2upf.x", "uspp2upf.x", "vdb2upf.x"]
-            if LooseVersion(self.version) > LooseVersion("5"):
-                upftools.extend(["interpolate.x", "upf2casino.x"])
-            if LooseVersion(self.version) >= LooseVersion("6.3"):
-                upftools.extend(["fix_upf.x"])
-            if LooseVersion(self.version) < LooseVersion("6.4"):
-                upftools.extend(["virtual.x"])
+            if LooseVersion(self.version) < LooseVersion("6.6"):
+                upftools = ["casino2upf.x", "cpmd2upf.x", "fhi2upf.x", "fpmd2upf.x", "ncpp2upf.x",
+                            "oldcp2upf.x", "read_upf_tofile.x", "rrkj2upf.x", "uspp2upf.x", "vdb2upf.x"]
+                if LooseVersion(self.version) > LooseVersion("5"):
+                    upftools.extend(["interpolate.x", "upf2casino.x"])
+                if LooseVersion(self.version) >= LooseVersion("6.3"):
+                    upftools.extend(["fix_upf.x"])
+                if LooseVersion(self.version) < LooseVersion("6.4"):
+                    upftools.extend(["virtual.x"])
+                else:
+                    upftools.extend(["virtual_v2.x"])
             else:
-                upftools.extend(["virtual_v2.x"])
+                upftools = ["upfconv.x", "virtual_v2.x", "fixfiles.py"]
 
         if 'vdw' in targets:  # only for v4.x, not in v5.0 anymore
             bins.extend(["vdw.x"])
@@ -484,9 +507,11 @@ def sanity_check_step(self):
 
         d3q_bins = []
         if 'd3q' in targets:
-            d3q_bins = ['d3_asr3.x', 'd3_import3py.x', 'd3_lw.x', 'd3_q2r.x',
+            d3q_bins = ['d3_asr3.x', 'd3_lw.x', 'd3_q2r.x',
                         'd3_qq2rr.x', 'd3q.x', 'd3_r2q.x', 'd3_recenter.x',
                         'd3_sparse.x', 'd3_sqom.x', 'd3_tk.x']
+            if LooseVersion(self.version) < LooseVersion("6.4"):
+                d3q_bins.append('d3_import3py.x')
 
         custom_paths = {
             'files': [os.path.join('bin', x) for x in bins + upftools + want_bins + yambo_bins + d3q_bins],


Test patch: