Skip to content
Snippets Groups Projects
Select Git revision
  • master
1 result

Makefile.in_intel-gcc

Blame
  • cpmd.py 13.22 KiB
    ##
    # Copyright 2016 Landcare Research NZ Ltd
    #
    # 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 building and installing CPMD, implemented as an easyblock
    
    @author: Benjamin Roberts (Landcare Research NZ Ltd)
    @author: Damian Alvarez (Forschungszentrum Juelich GmbH)
    """
    
    from distutils.version import LooseVersion
    import glob
    import os
    import platform
    import re
    import shutil
    import sys
    
    from easybuild.easyblocks.generic.configuremake import ConfigureMake
    from easybuild.framework.easyconfig import CUSTOM
    from easybuild.tools.build_log import EasyBuildError
    import easybuild.tools.environment as env
    from easybuild.tools.filetools import apply_regex_substitutions, extract_file
    from easybuild.tools.modules import get_software_root, get_software_version
    from easybuild.tools.run import run_cmd
    from easybuild.tools.systemtools import get_os_type
    import easybuild.tools.toolchain as toolchain
    
    class EB_CPMD(ConfigureMake):
        """
        Support for building CPMD
        """
    
        @staticmethod
        def extra_options():
            """Custom easyconfig parameters for CPMD."""
            extra_vars = {
                'base_configuration': [None, "Base configuration from which to start (file name)", CUSTOM],
            }
            return ConfigureMake.extra_options(extra_vars)
    
        def prepare_step(self):
            super(EB_CPMD, self).prepare_step()
    
            # create install directory and make sure it does not get cleaned up again in the install step;
            # the first configure iteration already puts things in place in the install directory,
            # so that shouldn't get cleaned up afterwards...
            self.log.info("Creating install dir %s before starting configure-build-install iterations", self.installdir)
            self.make_installdir()
            self.cfg['keeppreviousinstall'] = True
    
        def configure_step(self, cmd_prefix=''):
            """
            Configure step
            """
    
            config_file_candidates = []
    
            for confdirname in ["configure", "CONFIGURE"]:
                config_file_prefix = os.path.join(self.builddir, "CPMD", confdirname)
                if os.path.isdir(config_file_prefix):
                    break
            else:
                raise EasyBuildError("No directory containing configuration files. Please review source tarball contents, and amend the EasyBlock if necessary")
    
            # Work out a starting configuration file if one is not supplied in the easyconfig
            if self.cfg['base_configuration']:
                config_file_base = self.cfg['base_configuration']
            else:
                os_type_mappings = {
                    "LINUX"  : "LINUX",
                    "DARWIN" : "MACOSX",
                }
                os_type = os_type_mappings[get_os_type().upper()]
                machine = ""
                if os_type != "MACOSX":
                    machine = platform.machine().upper()
           
                config_file_base = os_type
                if len(machine) > 0:
                    config_file_base += "-" + machine
                
                if self.toolchain.comp_family() in [toolchain.INTELCOMP]:
                    config_file_base += "-INTEL"
    
                # enable MPI support if desired
                if self.toolchain.options.get('usempi', None):
                    config_file_base += "-MPI"
               
                # Note that the -FFTW and -FFTW3 options are always at the end
                # of the configuration file name, so this block needs to come
                # last within the "else".
                # Also, only version 3 or greater of FFTW is useful for CPMD.
                if get_software_root('imkl') or (get_software_root('FFTW') and LooseVersion(get_software_version('FFTW')) >= LooseVersion('3.0')):
                    config_file_base += "-FFTW"
                    config_file_candidates.append(config_file_base + "3")
    
            config_file_candidates.append(config_file_base)
    
            selected_base_config = None
            selected_full_config = None
            for cfc in config_file_candidates:
                self.log.info("Trying configuration file: %s", cfc)
                config_file_full = os.path.join(config_file_prefix, cfc)
                if os.path.isfile(config_file_full):
                    selected_base_config = cfc
                    selected_full_config = config_file_full
                    self.log.info("Selected %s as base configuration file", cfc)
                    break
    
            if selected_base_config is None:
                raise EasyBuildError("Base configuration file does not exist. Please edit base_configuration or review the CPMD easyblock.")
    
            try:
                apply_regex_substitutions(selected_full_config, [
                    # Better to get CC and FC from the EasyBuild environment in this instance
                    (r"^(\s*CC=.*)", r"#\1"),
                    (r"^(\s*FC=.*)", r"#\1"),
                    (r"^(\s*LD)=.*", r"\1='$(FC)'"),
                ])
            except IOError, err:
                raise EasyBuildError("Failed to patch %s: %s", selected_base_config, err)
    
            if self.cfg['configure_cmd_prefix']:
                if cmd_prefix:
                    tup = (cmd_prefix, self.cfg['configure_cmd_prefix'])
                    self.log.debug("Specified cmd_prefix '%s' is overruled by configure_cmd_prefix '%s'" % tup)
                cmd_prefix = self.cfg['configure_cmd_prefix']
    
            if self.cfg['tar_config_opts']:
                # setting am_cv_prog_tar_ustar avoids that configure tries to figure out
                # which command should be used for tarring/untarring
                # am__tar and am__untar should be set to something decent (tar should work)
                tar_vars = {
                    'am__tar': 'tar chf - "$$tardir"',
                    'am__untar': 'tar xf -',
                    'am_cv_prog_tar_ustar': 'easybuild_avoid_ustar_testing'
                }
                for (key, val) in tar_vars.items():
                    self.cfg.update('preconfigopts', "%s='%s'" % (key, val))
    
            options = [self.cfg['configopts']]
    
            # enable OpenMP support if desired
            if self.toolchain.options.get('openmp', None) and LooseVersion(self.version) >= LooseVersion('4.0'):
                options.append("-omp")
    
            # This "option" has to come last as it's the chief argument, coming after
            # all flags and so forth.
            options.append(selected_base_config)
    
            # I'm not sure when mkconfig.sh changed to configure.sh. Assuming 4.0
            # for the sake of the argument.
            if LooseVersion(self.version) >= LooseVersion('4.0'):
                config_exe = 'configure.sh'
            else:
                config_exe = 'mkconfig.sh'
                options.append('-BIN={0}'.format(os.path.join(self.installdir, "bin")))
                options.append('>')
                options.append(os.path.join(self.installdir, "Makefile"))
    
            cmd = "%(preconfigopts)s %(cmd_prefix)s./%(config_exe)s %(prefix_opt)s%(installdir)s %(configopts)s" % {
                'preconfigopts': self.cfg['preconfigopts'],
                'cmd_prefix': cmd_prefix,
                'config_exe': config_exe,
                'prefix_opt': self.cfg['prefix_opt'],
                'installdir': self.installdir,
                'configopts': ' '.join(options),
            }
    
            (out, _) = run_cmd(cmd, log_all=True, simple=False)
    
            return out
    
        def build_step(self):
    
            """
            Make some changes to files in order to make the build process more EasyBuild-friendly
            """
            os.chdir(self.installdir)
            if LooseVersion(self.version) < LooseVersion('4.0'):
                os.mkdir("bin")
            # Master configure script
            makefile = os.path.join(self.installdir, "Makefile")
            try:
                apply_regex_substitutions(makefile, [
                    (r"^(\s*LFLAGS\s*=.*[^\w-])-L/usr/lib64/atlas/([^\w-].*)$", r"\1\2"),
                    (r"^(\s*LFLAGS\s*=.*[^\w-])-llapack([^\w-].*)$", r"\1\2"),
                    (r"^(\s*LFLAGS\s*=.*[^\w-])-lblas([^\w-].*)$", r"\1\2"),
                    (r"^(\s*LFLAGS\s*=.*[^\w-])-lfftw([^\w-].*)$", r"\1\2"),
                ])
                if self.toolchain.comp_family() in [toolchain.INTELCOMP]:
                    preproc_flag = "-fpp"
                    ar_exe = "xiar -ruv"
                    apply_regex_substitutions(makefile, [
                        (r"^(\s*AR\s*=).*", r"\1 {0}".format(ar_exe))
                    ])
                    if LooseVersion(self.version) < LooseVersion('4.0'):
                        apply_regex_substitutions(makefile, [
                            (r"^(\s*CFLAGS\s*=.*[^\w-])-O2([^\w-].*)$", r"\1\2"),
                            (r"^(\s*CFLAGS\s*=.*[^\w-])-Wall([^\w-].*)$", r"\1\2"),
                            (r"^(\s*CPPFLAGS\s*=.*[^\w-])-D__PGI([^\w-].*)$", r"\1\2"),
                            (r"^(\s*CPPFLAGS\s*=.*[^\w-])-D__GNU([^\w-].*)$", r"\1\2"),
                            (r"^(\s*FFLAGS\s*=.*[^\w-])-O2([^\w-].*)$", r"\1\2"),
                            (r"^(\s*FFLAGS\s*=.*[^\w-])-fcray-pointer([^\w-].*)$", r"\1\2"),
                        ])
    
                if preproc_flag is None:
                    preproc_flag = ''
    
                apply_regex_substitutions(makefile, [
                    (r"^(\s*CPPFLAGS\s*=.*)", r"\1 {0}".format(os.getenv('CPPFLAGS'))),
                    (r"^(\s*CFLAGS\s*=.*)",   r"\1 {0}".format(os.getenv('CFLAGS'))),
                    (r"^(\s*FFLAGS\s*=.*)",   r"\1 {0}".format(os.getenv('FFLAGS'))),
                    (r"^(\s*LFLAGS\s*=.*)",   r"\1 {0}".format(os.getenv('LDFLAGS'))),
    
                    # Allow to define own XFLAGS
                    (r"# CPPFLAGS =", r"CPPFLAGS +="),
                    (r"# CFLAGS =", r"CFLAGS +="),
                    (r"# FFLAGS =", r"FFLAGS +="),
                    (r"# LFLAGS =", r"LFLAGS +="),
                    
                    # Add preprocessing options to FFLAGS and NOOPT_FLAG
                    (r"NOOPT_FLAG =", r"NOOPT_FLAG = {0}".format(preproc_flag)),
                    (r"FFLAGS =", r"FFLAGS = {0}".format(preproc_flag)),
    
                ])
                if self.toolchain.options.get('openmp', None):
                    apply_regex_substitutions(makefile, [
                        (r"^(\s*LFLAGS\s*=.*)",   r"\1 {0} {1}".format(os.getenv('LIBLAPACK_MT'), os.getenv('LIBBLAS_MT')))
                    ])
                else:
                    apply_regex_substitutions(makefile, [
                        (r"^(\s*LFLAGS\s*=.*)",   r"\1 {0} {1}".format(os.getenv('LIBLAPACK'), os.getenv('LIBBLAS')))
                    ])
                apply_regex_substitutions(makefile, [
                    (r"^(\s*LFLAGS\s*=.*)",   r"\1 {0}".format(os.getenv('LIBFFT'))),
                ])
    
                if get_software_root('imkl'):
                    if LooseVersion(self.version) < LooseVersion('4.0'):
                        apply_regex_substitutions(makefile, [
                            (r"(\s+)-DFFT_FFTW(\s+)", r"\1-DFFT_DEFAULT -DINTEL_MKL\2"),
                        ])
                if LooseVersion(self.version) >= LooseVersion('4.0'):
                    apply_regex_substitutions(makefile, [
                        (r"^(\s*CC\s*=.*)",       r"#\1"),
                        (r"^(\s*FC\s*=.*)",       r"#\1"),
                    ])
            except IOError, err:
                raise EasyBuildError("Failed to patch %s: %s", makefile, err)
    
            super(EB_CPMD, self).build_step()
    
        def extract_step(self):
            """
            Unpack the source files.
            """
            for src in self.src:
                if 'pseudo' not in src['name']:
                    self.log.info("Unpacking source %s" % src['name'])
                    srcdir = extract_file(src['path'], self.builddir, cmd=src['cmd'], extra_options=self.cfg['unpack_options'])
                    if srcdir:
                        self.src[self.src.index(src)]['finalpath'] = srcdir
                    else:
                        raise EasyBuildError("Unpacking source %s failed", src['name'])
                else:
                    self.log.info("Not extracting %s, treating it as pseudopotentials to be installed separately" % src['name'])
    
        # No need for a separate install step as the software is built in situ.
        # In fact, an install step throws away the entire package.
        # However, we consider the pseudopotentials and extract them in lib/
        def install_step(self):
            """
            Unpack the pseudopotentials if listed as source
            """
            for src in self.src:
                if 'pseudo' in src['name']:
                    self.log.info("Unpacking pseudopotentials file %s" % src['name'])
                    srcdir = extract_file(src['path'], '/'.join([self.installdir, 'lib']), cmd=src['cmd'], extra_options=self.cfg['unpack_options'])
                    if srcdir:
                        self.src[self.src.index(src)]['finalpath'] = srcdir
                    else:
                        raise EasyBuildError("Unpacking source %s failed", src['name'])