Source code for pycif.plugins.models.chimere.compile

import os
import subprocess
from logging import debug
from shutil import copy, copytree, ignore_patterns, rmtree


[docs] def compile(self): comp_dir = "{}/model".format(self.workdir) # Copying the executables try: # If force-recompile = True, return IOError to avoid copying if getattr(self, "force-recompile"): raise IOError # Otherwise, try copying executables source = "{}/src/fwdchimere.e".format(self.direxec) copy(source, comp_dir) source = "{}/src_tl/tlchimere.e".format(self.direxec) copy(source, comp_dir) source = "{}/src_ad/achimere.e".format(self.direxec) copy(source, comp_dir) return except IOError as e: if not getattr(self, "auto-recompile"): raise RuntimeError( f"CHIMERE could not find executables ({self.direxec}) and was not asked to " "compile them; specify auto-recompile = True in Yaml to do so" ) from e # Otherwise, re-compile # Copying sources locally; overwrite folder if exists if os.path.isdir("{}/sources".format(comp_dir)): rmtree("{}/sources".format(comp_dir)) dir_sources = self.dir_sources if self.dir_sources != "" else self.direxec copytree( dir_sources, "{}/sources".format(comp_dir), ignore=ignore_patterns("*.a"), ) # Modifying LDFLAGS if needed if hasattr(self, "LDFLAGS"): for fld in ["src", "src_tl", "src_ad"]: old_lines = open( "{}/sources/{}/Makefile_chimere".format(comp_dir, fld), "r" ).readlines() old_lines = [ln.rstrip() for ln in old_lines] for k, ln in enumerate(old_lines): if ln[:7] == "LDFLAGS": old_lines[k] = "LDFLAGS =\t{}".format(self.LDFLAGS) with open("{}/sources/{}/Makefile_chimere".format(comp_dir, fld), "w") as f: f.write("\n".join(old_lines)) # Modifying Makefile header if needed makefile_sed = os.path.join(comp_dir, "sources", "Makefile.hdr.sed") with open(makefile_sed, "r") as f: lines = [line.strip() for line in f.readlines()] # Join lines that are split with a backslash (keep backslash and newline characters) joined_lines = [] join = False for line in lines: if join: joined_lines[-1] = joined_lines[-1] + "\n" + line # append line to previous else: joined_lines.append(line) # new line # Join next line if current line ends with a backslash join = line.endswith("\\") gfortran_line = False new_lines = [] for line in joined_lines: if gfortran_line: gfortran_line = False # Reset flag if line.startswith("MF77") and hasattr(self, "gfortran_executable"): line = f"MF77\t=\t{self.gfortran_executable}" # Replace line with new value elif line.startswith("F77FLAGS1") and hasattr(self, "COMPILOPTIONS"): line = line + " " + self.COMPILOPTIONS # append value to line elif line == "REALFC\t=\tgfortran": gfortran_line = True # Replace next line else: for varname in ("NETCDFLIB", "NETCDFINC", "GRIBLIB", "GRIBINC"): if line.startswith(varname) and hasattr(self, varname): line = f"{varname}\t=\t{getattr(self, varname)}" # Replace line with new value break new_lines.append(line) with open(makefile_sed, "w") as f: f.write("\n".join(new_lines)) # Now compiling comp_mode = "" if getattr(self, "compile-mode") == "PROD" else "--debug" comp_clean = "--clean" if getattr(self, "compile-clean") else "" compiler = "--{}".format(getattr(self, "compiler", "ifort")) for mode, pref, suff in zip( ["A", "L", "D"], ["a", "tl", "fwd"], ["_ad", "_tl", ""] ): if not mode in getattr(self, "compile-only"): continue debug("Compiling CHIMERE {}".format(mode)) with open("{}/CHIMERE_compiling_{}.log" .format(comp_dir, mode), "w") as log: process = subprocess.Popen( f"./compile-chimere -m " f"{mode} {comp_mode} {comp_clean} {compiler}", shell=True, stdout=log, cwd="{}/sources/".format(comp_dir), stderr=subprocess.PIPE, ) _, stderr = process.communicate() # Print errors if no executable created (or if forced to) exe_file = "{}/sources/src{}/{}chimere.e".format(comp_dir, suff, pref) if not os.path.isfile(exe_file) or getattr(self, "force-compile-stderr"): debug("CHIMERE returned errors during compiling.") debug("There might be some bugs in the Fortran or in the " "libraries loaded in the system:") debug("### START OF CHIMERE ERROR MESSAGE ###") for ln in stderr.decode().split("\n"): debug(ln) debug("### END OF CHIMERE ERROR MESSAGE ###") # Copy executable at model root directory copy(exe_file, comp_dir)