def configure_step(self): """Configure build: set config options and configure""" if LooseVersion(self.version) < LooseVersion("4.3"): self.cfg.update('configopts', "--enable-shared") if self.toolchain.options['pic']: self.cfg.update('configopts', '--with-pic') tup = (os.getenv('FFLAGS'), os.getenv('MPICC'), os.getenv('F90')) self.cfg.update('configopts', 'FCFLAGS="%s" CC="%s" FC="%s"' % tup) # add -DgFortran to CPPFLAGS when building with GCC if self.toolchain.comp_family( ) == toolchain.GCC: #@UndefinedVariable self.cfg.update( 'configopts', 'CPPFLAGS="%s -DgFortran"' % os.getenv('CPPFLAGS')) ConfigureMake.configure_step(self) else: hdf5 = get_software_root('HDF5') if hdf5: env.setvar('HDF5_ROOT', hdf5) CMakeMake.configure_step(self)
def configure_step(self): """Configure build: set config options and configure""" if LooseVersion(self.version) < LooseVersion("4.3"): self.cfg.update('configopts', "--enable-shared") if self.toolchain.options['pic']: self.cfg.update('configopts', '--with-pic') # tup = (os.getenv('FFLAGS'), os.getenv('MPICC'), os.getenv('F90')) tup = (os.getenv('FFLAGS'), os.getenv('CC'), os.getenv('F90')) self.cfg.update('configopts', 'FCFLAGS="%s" CC="%s" FC="%s"' % tup) # add -DgFortran to CPPFLAGS when building with GCC if self.toolchain.comp_family() == toolchain.GCC: #@UndefinedVariable self.cfg.update('configopts', 'CPPFLAGS="%s -DgFortran"' % os.getenv('CPPFLAGS')) ConfigureMake.configure_step(self) else: hdf5 = get_software_root('HDF5') if hdf5: env.setvar('HDF5_ROOT', hdf5) CMakeMake.configure_step(self)
def install_step(self): """Custom install procedure for EggLib: first build/install C++ library, then build Python library.""" # build/install C++ library cpp_subdir = os.path.join(self.builddir, 'egglib-cpp-%s' % self.version) try: os.chdir(cpp_subdir) except OSError as err: raise EasyBuildError("Failed to move to: %s", err) ConfigureMake.configure_step(self) ConfigureMake.build_step(self) ConfigureMake.install_step(self) # header files and libraries must be found when building Python library for varname, subdir in [('CPATH', 'include'), ('LIBRARY_PATH', 'lib')]: env.setvar(varname, '%s:%s' % (os.path.join(self.installdir, subdir), os.environ.get(varname, ''))) # build/install Python package py_subdir = os.path.join(self.builddir, 'egglib-py-%s' % self.version) try: os.chdir(py_subdir) except OSError as err: raise EasyBuildError("Failed to move to: %s", err) PythonPackage.build_step(self) self.cfg.update('installopts', "--install-lib %s" % os.path.join(self.installdir, self.pylibdir)) self.cfg.update('installopts', "--install-scripts %s" % os.path.join(self.installdir, 'bin')) PythonPackage.install_step(self)
def configure_step(self): """Configure build: set config options and configure""" shlib_ext = get_shared_lib_ext() if LooseVersion(self.version) < LooseVersion("4.3"): self.cfg.update('configopts', "--enable-shared") if self.toolchain.options['pic']: self.cfg.update('configopts', '--with-pic') tup = (os.getenv('FFLAGS'), os.getenv('MPICC'), os.getenv('F90')) self.cfg.update('configopts', 'FCFLAGS="%s" CC="%s" FC="%s"' % tup) # add -DgFortran to CPPFLAGS when building with GCC if self.toolchain.comp_family() == toolchain.GCC: #@UndefinedVariable self.cfg.update('configopts', 'CPPFLAGS="%s -DgFortran"' % os.getenv('CPPFLAGS')) ConfigureMake.configure_step(self) else: for (dep, libname) in [('cURL', 'curl'), ('HDF5', 'hdf5'), ('Szip', 'sz'), ('zlib', 'z'), ('PnetCDF', 'pnetcdf')]: dep_root = get_software_root(dep) dep_libdir = get_software_libdir(dep) if dep_root: incdir = os.path.join(dep_root, 'include') self.cfg.update('configopts', '-D%s_INCLUDE_DIR=%s ' % (dep.upper(), incdir)) if dep == 'HDF5': env.setvar('HDF5_ROOT', dep_root) self.cfg.update('configopts', '-DUSE_HDF5=ON') hdf5cmvars = { # library name: (cmake option suffix in netcdf<4.4, cmake option suffix in netcfd>=4.4) 'hdf5': ('LIB', 'C_LIBRARY'), 'hdf5_hl': ('HL_LIB', 'HL_LIBRARY'), } for libname in hdf5cmvars: if LooseVersion(self.version) < LooseVersion("4.4"): cmvar = hdf5cmvars[libname][0] else: cmvar = hdf5cmvars[libname][1] libhdf5 = os.path.join(dep_root, dep_libdir, 'lib%s.%s' % (libname, shlib_ext)) self.cfg.update('configopts', '-DHDF5_%s=%s ' % (cmvar, libhdf5)) # 4.4 forgot to set HDF5_<lang>_LIBRARIES if LooseVersion(self.version) == LooseVersion("4.4.0"): lang = 'HL' if cmvar[0] == 'H' else 'C' self.cfg.update('configopts', '-DHDF5_%s_LIBRARIES=%s ' % (lang, libhdf5)) elif dep == 'PnetCDF': self.cfg.update('configopts', '-DENABLE_PNETCDF=ON') else: libso = os.path.join(dep_root, dep_libdir, 'lib%s.%s' % (libname, shlib_ext)) self.cfg.update('configopts', '-D%s_LIBRARY=%s ' % (dep.upper(), libso)) CMakeMake.configure_step(self)
def configure_step(self): """ Configure and Test if python module is loaded """ if not get_software_root('Python'): raise EasyBuildError("Python module not loaded") # We will do the python bindings ourselves so force them off self.cfg.update('configopts', '--without-python') ConfigureMake.configure_step(self)
def configure_step(self): """Configure build: set config options and configure""" shlib_ext = get_shared_lib_ext() if LooseVersion(self.version) < LooseVersion("4.3"): self.cfg.update('configopts', "--enable-shared") if self.toolchain.options['pic']: self.cfg.update('configopts', '--with-pic') tup = (os.getenv('FFLAGS'), os.getenv('MPICC'), os.getenv('F90')) self.cfg.update('configopts', 'FCFLAGS="%s" CC="%s" FC="%s"' % tup) # add -DgFortran to CPPFLAGS when building with GCC if self.toolchain.comp_family( ) == toolchain.GCC: #@UndefinedVariable self.cfg.update( 'configopts', 'CPPFLAGS="%s -DgFortran"' % os.getenv('CPPFLAGS')) ConfigureMake.configure_step(self) else: self.cfg.update( 'configopts', '-DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG " ' ) for (dep, libname) in [('cURL', 'curl'), ('HDF5', 'hdf5'), ('Szip', 'sz'), ('zlib', 'z')]: dep_root = get_software_root(dep) dep_libdir = get_software_libdir(dep) if dep_root: incdir = os.path.join(dep_root, 'include') self.cfg.update( 'configopts', '-D%s_INCLUDE_DIR=%s ' % (dep.upper(), incdir)) if dep == 'HDF5': env.setvar('HDF5_ROOT', dep_root) libhdf5 = os.path.join(dep_root, dep_libdir, 'libhdf5.%s' % shlib_ext) self.cfg.update('configopts', '-DHDF5_LIB=%s ' % libhdf5) libhdf5_hl = os.path.join(dep_root, dep_libdir, 'libhdf5_hl.%s' % shlib_ext) self.cfg.update('configopts', '-DHDF5_HL_LIB=%s ' % libhdf5_hl) else: libso = os.path.join(dep_root, dep_libdir, 'lib%s.%s' % (libname, shlib_ext)) self.cfg.update( 'configopts', '-D%s_LIBRARY=%s ' % (dep.upper(), libso)) CMakeMake.configure_step(self)
def configure_step(self): """Configuration step, we set FC, F77 is already set by EasyBuild to the right compiler, FC is used for Fortan90""" environment.setvar('FC', self.toolchain.get_variable('F90')) # make sure correct config script is used for Tcl/Tk for dep in ['Tcl', 'Tk']: root = get_software_root(dep) if root: dep_config = os.path.join(root, 'lib', '%sConfig.sh' % dep.lower()) self.cfg.update('configopts', '-with-%s-config=%s' % (dep.lower(), dep_config)) ConfigureMake.configure_step(self)
def configure_step(self): """ Configure and Test if python module is loaded """ if not get_software_root('Python'): self.log.error("Python module not loaded") ConfigureMake.configure_step(self) try: os.chdir('python') PythonPackage.configure_step(self) os.chdir('..') except OSError, err: self.log.error("Failed to configure libxml2 Python bindings: %s" % err)
def configure_step(self): """ Configure libxml2 build """ # only build with Python bindings if Python is listed as a dependency python = get_software_root('Python') if python: self.with_python_bindings = True self.require_python = True if not self.toolchain.is_system_toolchain(): self.cfg.update( 'configopts', "CC='%s' CXX='%s'" % (os.getenv('CC'), os.getenv('CXX'))) if self.toolchain.options.get('pic', False): self.cfg.update('configopts', '--with-pic') zlib = get_software_root('zlib') if zlib: self.cfg.update('configopts', '--with-zlib=%s' % zlib) xz_root = get_software_root('XZ') if xz_root: self.cfg.update('configopts', '--with-lzma=%s' % xz_root) # enable building of Python bindings if Python is a dependency (or build them ourselves for old versions) # disable building of Python bindings if Python is not a dependency if self.with_python_bindings and LooseVersion( self.version) >= LooseVersion('2.9.2'): libxml2_pylibdir = os.path.join(self.installdir, self.pylibdir) self.cfg.update( 'configopts', "--with-python=%s" % os.path.join(python, 'bin', 'python')) self.cfg.update('configopts', "--with-python-install-dir=%s" % libxml2_pylibdir) else: self.cfg.update('configopts', '--without-python') ConfigureMake.configure_step(self) if self.with_python_bindings: # prepare for installing Python package PythonPackage.prepare_python(self) # test using 'make check' (done via test_step) self.cfg['runtest'] = 'check'
def configure_step(self): """ Configure and Test if python module is loaded """ if not get_software_root('Python'): raise EasyBuildError("Python module not loaded") ConfigureMake.configure_step(self) try: os.chdir('python') PythonPackage.configure_step(self) os.chdir('..') except OSError, err: raise EasyBuildError( "Failed to configure libxml2 Python bindings: %s", err)
def configure_step(self): """Custom configuration for R.""" # define $BLAS_LIBS to build R correctly against BLAS/LAPACK library # $LAPACK_LIBS should *not* be specified since that may lead to using generic LAPACK # see https://github.com/easybuilders/easybuild-easyconfigs/issues/1435 env.setvar('BLAS_LIBS', os.getenv('LIBBLAS')) self.cfg.update('configopts', "--with-blas --with-lapack") # make sure correct config script is used for Tcl/Tk for dep in ['Tcl', 'Tk']: root = get_software_root(dep) if root: dep_config = os.path.join(root, 'lib', '%sConfig.sh' % dep.lower()) self.cfg.update( 'configopts', '--with-%s-config=%s' % (dep.lower(), dep_config)) if "--with-x=" not in self.cfg['configopts'].lower(): if get_software_root('X11'): self.cfg.update('configopts', '--with-x=yes') else: self.cfg.update('configopts', '--with-x=no') # enable graphic capabilities for plotting, based on available dependencies for dep in ['Cairo', 'libjpeg-turbo', 'libpng', 'libtiff']: if get_software_root(dep): if dep == 'libjpeg-turbo': conf_opt = 'jpeglib' else: conf_opt = dep.lower() self.cfg.update('configopts', '--with-%s' % conf_opt) out = ConfigureMake.configure_step(self) # check output of configure command to verify BLAS/LAPACK settings ext_libs_regex = re.compile( "External libraries:.*BLAS\((?P<BLAS>.*)\).*LAPACK\((?P<LAPACK>.*)\)" ) res = ext_libs_regex.search(out) if res: for lib in ['BLAS', 'LAPACK']: if res.group(lib) == 'generic': warn_msg = "R will be built with generic %s, which will result in poor performance." % lib self.log.warning(warn_msg) print_warning(warn_msg) else: self.log.info("R is configured to use non-generic %s: %s", lib, res.group(lib)) else: warn_msg = "R is configured to be built without BLAS/LAPACK, which will result in (very) poor performance" self.log.warning(warn_msg) print_warning(warn_msg)
def configure_step(self): """Configure build: set config options and configure""" shlib_ext = get_shared_lib_ext() if LooseVersion(self.version) < LooseVersion("4.3"): self.cfg.update('configopts', "--enable-shared") if self.toolchain.options['pic']: self.cfg.update('configopts', '--with-pic') tup = (os.getenv('FFLAGS'), os.getenv('MPICC'), os.getenv('F90')) self.cfg.update('configopts', 'FCFLAGS="%s" CC="%s" FC="%s"' % tup) # add -DgFortran to CPPFLAGS when building with GCC if self.toolchain.comp_family() == toolchain.GCC: #@UndefinedVariable self.cfg.update('configopts', 'CPPFLAGS="%s -DgFortran"' % os.getenv('CPPFLAGS')) ConfigureMake.configure_step(self) else: self.cfg.update('configopts', '-DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG " ') for (dep, libname) in [('cURL', 'curl'), ('HDF5', 'hdf5'), ('Szip', 'sz'), ('zlib', 'z')]: dep_root = get_software_root(dep) dep_libdir = get_software_libdir(dep) if dep_root: incdir = os.path.join(dep_root, 'include') self.cfg.update('configopts', '-D%s_INCLUDE_DIR=%s ' % (dep.upper(), incdir)) if dep == 'HDF5': env.setvar('HDF5_ROOT', dep_root) libhdf5 = os.path.join(dep_root, dep_libdir, 'libhdf5.%s' % shlib_ext) self.cfg.update('configopts', '-DHDF5_LIB=%s ' % libhdf5) libhdf5_hl = os.path.join(dep_root, dep_libdir, 'libhdf5_hl.%s' % shlib_ext) self.cfg.update('configopts', '-DHDF5_HL_LIB=%s ' % libhdf5_hl) else: libso = os.path.join(dep_root, dep_libdir, 'lib%s.%s' % (libname, shlib_ext)) self.cfg.update('configopts', '-D%s_LIBRARY=%s ' % (dep.upper(), libso)) CMakeMake.configure_step(self)
def install_step(self): """Custom install procedure for EggLib: first build/install C++ library, then build Python library.""" # build/install C++ library cpp_subdir = os.path.join(self.builddir, 'egglib-cpp-%s' % self.version) try: os.chdir(cpp_subdir) except OSError as err: raise EasyBuildError("Failed to move to: %s", err) ConfigureMake.configure_step(self) ConfigureMake.build_step(self) ConfigureMake.install_step(self) # header files and libraries must be found when building Python library for varname, subdir in [('CPATH', 'include'), ('LIBRARY_PATH', 'lib')]: env.setvar( varname, '%s:%s' % (os.path.join( self.installdir, subdir), os.environ.get(varname, ''))) # build/install Python package py_subdir = os.path.join(self.builddir, 'egglib-py-%s' % self.version) try: os.chdir(py_subdir) except OSError as err: raise EasyBuildError("Failed to move to: %s", err) PythonPackage.build_step(self) self.cfg.update( 'installopts', "--install-lib %s" % os.path.join(self.installdir, self.pylibdir)) self.cfg.update( 'installopts', "--install-scripts %s" % os.path.join(self.installdir, 'bin')) PythonPackage.install_step(self)
def configure_step(self): """ Configure libxml2 build """ # only build with Python bindings if Python is listed as a dependency python = get_software_root('Python') if python: self.with_python_bindings = True if self.toolchain.name != DUMMY_TOOLCHAIN_NAME: self.cfg.update('configopts', "CC='%s' CXX='%s'" % (os.getenv('CC'), os.getenv('CXX'))) if self.toolchain.options.get('pic', False): self.cfg.update('configopts', '--with-pic') zlib = get_software_root('zlib') if zlib: self.cfg.update('configopts', '--with-zlib=%s' % zlib) # enable building of Python bindings if Python is a dependency (or build them ourselves for old versions) # disable building of Python bindings if Python is not a dependency if self.with_python_bindings and LooseVersion(self.version) >= LooseVersion('2.9.2'): libxml2_pylibdir = os.path.join(self.installdir, self.pylibdir) self.cfg.update('configopts', "--with-python=%s" % os.path.join(python, 'bin', 'python')) self.cfg.update('configopts', "--with-python-install-dir=%s" % libxml2_pylibdir) else: self.cfg.update('configopts', '--without-python') ConfigureMake.configure_step(self) if self.with_python_bindings: # prepare for installing Python package PythonPackage.prepare_python(self) # test using 'make check' (done via test_step) self.cfg['runtest'] = 'check'
def configure_step(self): """Custom configuration for R.""" # define $BLAS_LIBS to build R correctly against BLAS/LAPACK library # $LAPACK_LIBS should *not* be specified since that may lead to using generic LAPACK # see https://github.com/easybuilders/easybuild-easyconfigs/issues/1435 env.setvar('BLAS_LIBS', os.getenv('LIBBLAS')) self.cfg.update('configopts', "--with-blas --with-lapack") # make sure correct config script is used for Tcl/Tk for dep in ['Tcl', 'Tk']: root = get_software_root(dep) if root: dep_config = os.path.join(root, 'lib', '%sConfig.sh' % dep.lower()) self.cfg.update('configopts', '--with-%s-config=%s' % (dep.lower(), dep_config)) if "--with-x=" not in self.cfg['configopts'].lower(): if get_software_root('X11'): self.cfg.update('configopts', '--with-x=yes') else: self.cfg.update('configopts', '--with-x=no') # enable graphic capabilities for plotting, based on available dependencies for dep in ['Cairo', 'libjpeg-turbo', 'libpng', 'libtiff']: if get_software_root(dep): if dep == 'libjpeg-turbo': conf_opt = 'jpeglib' else: conf_opt = dep.lower() self.cfg.update('configopts', '--with-%s' % conf_opt) out = ConfigureMake.configure_step(self) # check output of configure command to verify BLAS/LAPACK settings ext_libs_regex = re.compile("External libraries:.*BLAS\((?P<BLAS>.*)\).*LAPACK\((?P<LAPACK>.*)\)") res = ext_libs_regex.search(out) if res: for lib in ['BLAS', 'LAPACK']: if res.group(lib) == 'generic': warn_msg = "R will be built with generic %s, which will result in poor performance." % lib self.log.warning(warn_msg) print_warning(warn_msg) else: self.log.info("R is configured to use non-generic %s: %s", lib, res.group(lib)) else: warn_msg = "R is configured to be built without BLAS/LAPACK, which will result in (very) poor performance" self.log.warning(warn_msg) print_warning(warn_msg)
class EB_EggLib(PythonPackage, ConfigureMake): """Support for building/installing EggLib.""" def configure_step(self): """Configure EggLib build/install procedure.""" # only need to configure Python library here, configuration of C++ library is done in install step PythonPackage.configure_step(self) def build_step(self): """No custom build procedure for EggLib; build/install is done in install_step.""" pass def install_step(self): """Custom install procedure for EggLib: first build/install C++ library, then build Python library.""" # build/install C++ library cpp_subdir = os.path.join(self.builddir, 'egglib-cpp-%s' % self.version) try: os.chdir(cpp_subdir) except OSError, err: raise EasyBuildError("Failed to move to: %s", err) ConfigureMake.configure_step(self) ConfigureMake.build_step(self) ConfigureMake.install_step(self) # header files and libraries must be found when building Python library for varname, subdir in [('CPATH', 'include'), ('LIBRARY_PATH', 'lib')]: env.setvar( varname, '%s:%s' % (os.path.join( self.installdir, subdir), os.environ.get(varname, ''))) # build/install Python package py_subdir = os.path.join(self.builddir, 'egglib-py-%s' % self.version) try: os.chdir(py_subdir) except OSError, err: raise EasyBuildError("Failed to move to: %s", err)
def configure_step(self): """Custom configuration procedure for NEURON.""" if LooseVersion(self.version) < LooseVersion('7.8.1'): # make sure we're using the correct configure command # (required because custom easyconfig parameters from CMakeMake are picked up) self.cfg['configure_cmd'] = "./configure" # enable support for distributed simulations if desired if self.cfg['paranrn']: self.cfg.update('configopts', '--with-paranrn') # specify path to InterViews if it is available as a dependency interviews_root = get_software_root('InterViews') if interviews_root: self.cfg.update('configopts', "--with-iv=%s" % interviews_root) else: self.cfg.update('configopts', "--without-iv") # optionally enable support for Python as alternative interpreter python_root = get_software_root('Python') if python_root: self.with_python = True self.cfg.update('configopts', "--with-nrnpython=%s/bin/python" % python_root) # determine host CPU type cmd = "./config.guess" (out, ec) = run_cmd(cmd, simple=False) self.hostcpu = out.split('\n')[0].split('-')[0] self.log.debug("Determined host CPU type as %s" % self.hostcpu) # determine Python lib dir self.pylibdir = det_pylibdir() # complete configuration with configure_method of parent ConfigureMake.configure_step(self) else: # enable support for distributed simulations if desired if self.cfg['paranrn']: self.cfg.update('configopts', '-DNRN_ENABLE_MPI=ON') else: self.cfg.update('configopts', '-DNRN_ENABLE_MPI=OFF') # specify path to InterViews if it is available as a dependency interviews_root = get_software_root('InterViews') if interviews_root: self.cfg.update('configopts', "-DIV_DIR=%s -DNRN_ENABLE_INTERVIEWS=ON" % interviews_root) else: self.cfg.update('configopts', "-DNRN_ENABLE_INTERVIEWS=OFF") # no longer used it seems self.hostcpu = '' # optionally enable support for Python as alternative interpreter python_root = get_software_root('Python') if python_root: self.with_python = True self.cfg.update('configopts', "-DNRN_ENABLE_PYTHON=ON -DPYTHON_EXECUTABLE=%s/bin/python" % python_root) self.cfg.update('configopts', "-DNRN_ENABLE_MODULE_INSTALL=ON " "-DNRN_MODULE_INSTALL_OPTIONS='--prefix=%s'" % self.installdir) else: self.cfg.update('configopts', "-DNRN_ENABLE_PYTHON=OFF") # determine Python lib dir self.pylibdir = det_pylibdir() # complete configuration with configure_method of parent CMakeMake.configure_step(self)
def configure_step(self): """Dedicated configure step for Mono: install Mono from RPM (if provided), then run configure.""" # install Mono from RPMs if provided (because we need Mono to build Mono) if self.rpms: # prepare path for installing RPMs in monorpms_path = os.path.join(self.builddir, "monorpms") try: os.makedirs(os.path.join(monorpms_path, 'rpm')) except OSError as err: raise EasyBuildError( "Failed to create directories for installing Mono RPMs in: %s", err) self.src = self.rpms self.rebuildRPM = True # rebuild RPMs to make them relocatable Rpm.configure_step(self) # prepare to install RPMs self.log.debug( "Initializing temporary RPM repository to install to...") cmd = "rpm --initdb --dbpath /rpm --root %s" % monorpms_path run_cmd(cmd, log_all=True, simple=True) # install RPMs one by one for rpm in self.src: self.log.debug("Installing RPM %s ..." % rpm['name']) if os.path.exists(rpm['path']): cmd = ' '.join([ "rpm -i", "--dbpath %(inst)s/rpm", "--force", "--relocate /=%(inst)s", "--badreloc", "--nodeps --nopost", "%(rpm)s", ]) % { 'inst': monorpms_path, 'rpm': rpm['path'], } run_cmd(cmd, log_all=True, simple=True) else: raise EasyBuildError("RPM file %s not found", rpm['path']) # create patched version of gmcs command self.log.debug("Making our own copy of gmcs (one that works).") mygmcs_path = os.path.join(monorpms_path, 'usr', 'bin', 'mygmcs') try: shutil.copy(os.path.join(monorpms_path, 'usr', 'bin', 'gmcs'), mygmcs_path) except OSError as err: raise EasyBuildError("Failed to copy gmcs to %s: %s", mygmcs_path, err) rpls = [ ("exec /usr/bin/mono", "exec %s/usr/bin/mono" % monorpms_path), ("`/usr/bin/monodir`", "%s/usr/lib64/mono" % monorpms_path), ] apply_regex_substitutions(mygmcs_path, rpls) self.log.debug("Patched version of gmcs (%s): %s" % (mygmcs_path, read_file(mygmcs_path))) # initiate bootstrap: build/install Mono with installed RPMs to temporary path tmp_mono_path = os.path.join(self.builddir, "tmp_mono") self.log.debug( "Build/install temporary Mono version in %s using installed RPMs..." % tmp_mono_path) par = '' if self.cfg['parallel']: par = "-j %s" % self.cfg['parallel'] config_cmd = "%s ./configure --prefix=%s %s" % ( self.cfg['preconfigopts'], tmp_mono_path, self.cfg['configopts']) build_cmd = ' '.join([ "%(prebuildopts)s" "make %(par)s", "EXTERNAL_MCS=%(path)s/usr/bin/mygmcs", "EXTERNAL_RUNTIME=%(path)s/usr/bin/mono", "%(buildopts)s", ]) % { 'prebuildopts': self.cfg['prebuildopts'], 'par': par, 'path': monorpms_path, 'buildopts': self.cfg['buildopts'], } install_cmd = "make install" for cmd in [config_cmd, build_cmd, install_cmd]: run_cmd(cmd, log_all=True, simple=True) more_buildopts = ' '.join([ "EXTERNAL_MCS=%(path)s/bin/gmcs", "EXTERNAL_RUNTIME=%(path)s/bin/mono", ]) % { 'path': tmp_mono_path } self.cfg.update('buildopts', more_buildopts) self.src = self.mono_srcs # continue with normal configure, and subsequent make, make install ConfigureMake.configure_step(self)
def configure_step(self): """ Configure build outside of source directory. """ try: objdir = os.path.join(self.builddir, 'obj') os.makedirs(objdir) os.chdir(objdir) except OSError as err: raise EasyBuildError( "Failed to prepare for configuration of PSI build: %s", err) env.setvar('F77FLAGS', os.getenv('F90FLAGS')) # In order to create new plugins with PSI, it needs to know the location of the source # and the obj dir after install. These env vars give that information to the configure script. self.psi_srcdir = os.path.basename(self.cfg['start_dir'].rstrip( os.sep)) self.install_psi_objdir = os.path.join(self.installdir, 'obj') self.install_psi_srcdir = os.path.join(self.installdir, self.psi_srcdir) env.setvar('PSI_OBJ_INSTALL_DIR', self.install_psi_objdir) env.setvar('PSI_SRC_INSTALL_DIR', self.install_psi_srcdir) # explicitely specify Python binary to use pythonroot = get_software_root('Python') if not pythonroot: raise EasyBuildError("Python module not loaded.") # pre 4.0b5, they were using autotools, on newer it's CMake if LooseVersion( self.version) <= LooseVersion("4.0b5") and self.name == "PSI": # Use EB Boost boostroot = get_software_root('Boost') if not boostroot: raise EasyBuildError("Boost module not loaded.") self.log.info("Using configure based build") env.setvar('PYTHON', os.path.join(pythonroot, 'bin', 'python')) env.setvar('USE_SYSTEM_BOOST', 'TRUE') if self.toolchain.options.get('usempi', None): # PSI doesn't require a Fortran compiler itself, but may require it to link to BLAS/LAPACK correctly # we should always specify the sequential Fortran compiler, # to avoid problems with -lmpi vs -lmpi_mt during linking fcompvar = 'F77_SEQ' else: fcompvar = 'F77' # update configure options # using multi-threaded BLAS/LAPACK is important for performance, # cfr. http://sirius.chem.vt.edu/psi4manual/latest/installfile.html#sec-install-iii opt_vars = [ ('cc', 'CC'), ('cxx', 'CXX'), ('fc', fcompvar), ('libdirs', 'LDFLAGS'), ('blas', 'LIBBLAS_MT'), ('lapack', 'LIBLAPACK_MT'), ] for (opt, var) in opt_vars: self.cfg.update('configopts', "--with-%s='%s'" % (opt, os.getenv(var))) # -DMPICH_IGNORE_CXX_SEEK dances around problem with order of stdio.h and mpi.h headers # both define SEEK_SET, this makes the one for MPI be ignored self.cfg.update( 'configopts', "--with-opt='%s -DMPICH_IGNORE_CXX_SEEK'" % os.getenv('CFLAGS')) # specify location of Boost self.cfg.update('configopts', "--with-boost=%s" % boostroot) # enable support for plugins self.cfg.update('configopts', "--with-plugins") ConfigureMake.configure_step(self, cmd_prefix=self.cfg['start_dir']) else: self.log.info("Using CMake based build") self.cfg.update( 'configopts', ' -DPYTHON_INTERPRETER=%s' % os.path.join(pythonroot, 'bin', 'python')) if self.name == 'PSI4' and LooseVersion( self.version) >= LooseVersion("1.2"): self.log.info( "Remove the CMAKE_BUILD_TYPE test in PSI4 source and the downloaded dependencies!" ) self.log.info( "Use PATCH_COMMAND in the corresponding CMakeLists.txt") self.cfg.update('configopts', ' -DCMAKE_BUILD_TYPE=EasyBuildRelease') else: self.cfg.update('configopts', ' -DCMAKE_BUILD_TYPE=Release') if self.toolchain.options.get('usempi', None): self.cfg.update('configopts', " -DENABLE_MPI=ON") if get_software_root('imkl'): self.cfg.update('configopts', " -DENABLE_CSR=ON -DBLAS_TYPE=MKL") if self.name == 'PSI4': pcmsolverroot = get_software_root('PCMSolver') if pcmsolverroot: self.cfg.update('configopts', " -DENABLE_PCMSOLVER=ON") if LooseVersion(self.version) < LooseVersion("1.2"): self.cfg.update('configopts', " -DPCMSOLVER_ROOT=%s" % pcmsolverroot) else: self.cfg.update( 'configopts', " -DCMAKE_INSIST_FIND_PACKAGE_PCMSolver=ON " "-DPCMSolver_DIR=%s/share/cmake/PCMSolver" % pcmsolverroot) chempsroot = get_software_root('CheMPS2') if chempsroot: self.cfg.update('configopts', " -DENABLE_CHEMPS2=ON") if LooseVersion(self.version) < LooseVersion("1.2"): self.cfg.update('configopts', " -DCHEMPS2_ROOT=%s" % chempsroot) else: self.cfg.update( 'configopts', " -DCMAKE_INSIST_FIND_PACKAGE_CheMPS2=ON " "-DCheMPS2_DIR=%s/share/cmake/CheMPS2" % chempsroot) # Be aware, PSI4 wants exact versions of the following deps! built with CMake!! # If you want to use non-CMake build versions, the you have to provide the # corresponding Find<library-name>.cmake scripts # In PSI4 version 1.2.1, you can check the corresponding CMakeLists.txt file # in external/upstream/<library-name>/ if LooseVersion(self.version) >= LooseVersion("1.2"): for dep in ['libxc', 'Libint', 'pybind11', 'gau2grid']: deproot = get_software_root(dep) if deproot: self.cfg.update( 'configopts', " -DCMAKE_INSIST_FIND_PACKAGE_%s=ON" % dep) dep_dir = os.path.join(deproot, 'share', 'cmake', dep) self.cfg.update('configopts', " -D%s_DIR=%s " % (dep, dep_dir)) CMakeMake.configure_step(self, srcdir=self.cfg['start_dir'])
def configure_step(self): """Custom configuration procedure for GROMACS: set configure options for configure or cmake.""" if LooseVersion(self.version) >= LooseVersion('4.6'): cuda = get_software_root('CUDA') if cuda: # CUDA with double precision is currently not supported in GROMACS yet # If easyconfig explicitly have double_precision=True error out, # otherwise warn about it and skip the double precision build if self.cfg.get('double_precision'): raise EasyBuildError("Double precision is not available for GPU build. " + "Please explicitly set \"double_precision = False\" " + "or remove it in the easyconfig file.") if self.double_prec_pattern in self.cfg['configopts']: if self.cfg.get('double_precision') is None: # Only print warning once when trying double precision # build the first time self.cfg['double_precision'] = False self.log.info("Double precision is not available for " + "GPU build. Skipping the double precision build.") self.log.info("skipping configure step") return if LooseVersion(self.version) >= LooseVersion('2021'): self.cfg.update('configopts', "-DGMX_GPU=CUDA -DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda) else: self.cfg.update('configopts', "-DGMX_GPU=ON -DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda) else: # explicitly disable GPU support if CUDA is not available, # to avoid that GROMACS find and uses a system-wide CUDA compiler self.cfg.update('configopts', "-DGMX_GPU=OFF") # check whether PLUMED is loaded as a dependency plumed_root = get_software_root('PLUMED') if plumed_root: # Need to check if PLUMED has an engine for this version engine = 'gromacs-%s' % self.version (out, _) = run_cmd("plumed-patch -l", log_all=True, simple=False) if not re.search(engine, out): raise EasyBuildError("There is no support in PLUMED version %s for GROMACS %s: %s", get_software_version('PLUMED'), self.version, out) # PLUMED patching must be done at different stages depending on # version of GROMACS. Just prepare first part of cmd here plumed_cmd = "plumed-patch -p -e %s" % engine if LooseVersion(self.version) < LooseVersion('4.6'): self.log.info("Using configure script for configuring GROMACS build.") if self.cfg['build_shared_libs']: self.cfg.update('configopts', "--enable-shared --disable-static") else: self.cfg.update('configopts', "--enable-static") # Use external BLAS and LAPACK self.cfg.update('configopts', "--with-external-blas --with-external-lapack") env.setvar('LIBS', "%s %s" % (os.environ['LIBLAPACK'], os.environ['LIBS'])) # Don't use the X window system self.cfg.update('configopts', "--without-x") # OpenMP is not supported for versions older than 4.5. if LooseVersion(self.version) >= LooseVersion('4.5'): # enable OpenMP support if desired if self.toolchain.options.get('openmp', None): self.cfg.update('configopts', "--enable-threads") else: self.cfg.update('configopts', "--disable-threads") elif self.toolchain.options.get('openmp', None): raise EasyBuildError("GROMACS version %s does not support OpenMP" % self.version) # GSL support if get_software_root('GSL'): self.cfg.update('configopts', "--with-gsl") else: self.cfg.update('configopts', "--without-gsl") # actually run configure via ancestor (not direct parent) self.cfg['configure_cmd'] = "./configure" ConfigureMake.configure_step(self) # Now patch GROMACS for PLUMED between configure and build if plumed_root: run_cmd(plumed_cmd, log_all=True, simple=True) else: if '-DGMX_MPI=ON' in self.cfg['configopts']: mpi_numprocs = self.cfg.get('mpi_numprocs', 0) if mpi_numprocs == 0: self.log.info("No number of test MPI tasks specified -- using default: %s", self.cfg['parallel']) mpi_numprocs = self.cfg['parallel'] elif mpi_numprocs > self.cfg['parallel']: self.log.warning("Number of test MPI tasks (%s) is greater than value for 'parallel': %s", mpi_numprocs, self.cfg['parallel']) mpiexec = self.cfg.get('mpiexec') if mpiexec: mpiexec_path = which(mpiexec) if mpiexec_path: self.cfg.update('configopts', "-DMPIEXEC=%s" % mpiexec_path) self.cfg.update('configopts', "-DMPIEXEC_NUMPROC_FLAG=%s" % self.cfg.get('mpiexec_numproc_flag')) self.cfg.update('configopts', "-DNUMPROC=%s" % mpi_numprocs) elif self.cfg['runtest']: raise EasyBuildError("'%s' not found in $PATH", mpiexec) else: raise EasyBuildError("No value found for 'mpiexec'") self.log.info("Using %s as MPI executable when testing, with numprocs flag '%s' and %s tasks", mpiexec_path, self.cfg.get('mpiexec_numproc_flag'), mpi_numprocs) if LooseVersion(self.version) >= LooseVersion('2019'): # Building the gmxapi interface requires shared libraries, # this is handled in the class initialisation so --module-only works self.cfg.update('configopts', "-DGMXAPI=ON") if LooseVersion(self.version) >= LooseVersion('2020'): # build Python bindings if Python is loaded as a dependency python_root = get_software_root('Python') if python_root: bin_python = os.path.join(python_root, 'bin', 'python') self.cfg.update('configopts', "-DPYTHON_EXECUTABLE=%s" % bin_python) self.cfg.update('configopts', "-DGMX_PYTHON_PACKAGE=ON") # Now patch GROMACS for PLUMED before cmake if plumed_root: if LooseVersion(self.version) >= LooseVersion('5.1'): # Use shared or static patch depending on # setting of self.cfg['build_shared_libs'] # and adapt cmake flags accordingly as per instructions # from "plumed patch -i" if self.cfg['build_shared_libs']: mode = 'shared' else: mode = 'static' plumed_cmd = plumed_cmd + ' -m %s' % mode run_cmd(plumed_cmd, log_all=True, simple=True) # prefer static libraries, if available if self.cfg['build_shared_libs']: self.cfg.update('configopts', "-DGMX_PREFER_STATIC_LIBS=OFF") else: self.cfg.update('configopts', "-DGMX_PREFER_STATIC_LIBS=ON") # always specify to use external BLAS/LAPACK self.cfg.update('configopts', "-DGMX_EXTERNAL_BLAS=ON -DGMX_EXTERNAL_LAPACK=ON") # disable GUI tools self.cfg.update('configopts', "-DGMX_X11=OFF") # convince to build for an older architecture than present on the build node by setting GMX_SIMD CMake flag # it does not make sense for Cray, because OPTARCH is defined by the Cray Toolchain if self.toolchain.toolchain_family() != toolchain.CRAYPE: gmx_simd = self.get_gromacs_arch() if gmx_simd: if LooseVersion(self.version) < LooseVersion('5.0'): self.cfg.update('configopts', "-DGMX_CPU_ACCELERATION=%s" % gmx_simd) else: self.cfg.update('configopts', "-DGMX_SIMD=%s" % gmx_simd) # set regression test path prefix = 'regressiontests' if any([src['name'].startswith(prefix) for src in self.src]): self.cfg.update('configopts', "-DREGRESSIONTEST_PATH='%%(builddir)s/%s-%%(version)s' " % prefix) # enable OpenMP support if desired if self.toolchain.options.get('openmp', None): self.cfg.update('configopts', "-DGMX_OPENMP=ON") else: self.cfg.update('configopts', "-DGMX_OPENMP=OFF") imkl_root = get_software_root('imkl') if imkl_root: # using MKL for FFT, so it will also be used for BLAS/LAPACK imkl_include = os.path.join(os.getenv('MKLROOT'), 'mkl', 'include') self.cfg.update('configopts', '-DGMX_FFT_LIBRARY=mkl -DMKL_INCLUDE_DIR="%s" ' % imkl_include) libs = os.getenv('LAPACK_STATIC_LIBS').split(',') mkl_libs = [os.path.join(os.getenv('LAPACK_LIB_DIR'), lib) for lib in libs if lib != 'libgfortran.a'] mkl_libs = ['-Wl,--start-group'] + mkl_libs + ['-Wl,--end-group -lpthread -lm -ldl'] self.cfg.update('configopts', '-DMKL_LIBRARIES="%s" ' % ';'.join(mkl_libs)) else: for libname in ['BLAS', 'LAPACK']: libdir = os.getenv('%s_LIB_DIR' % libname) if self.toolchain.toolchain_family() == toolchain.CRAYPE: libsci_mpi_mp_lib = glob.glob(os.path.join(libdir, 'libsci_*_mpi_mp.a')) if libsci_mpi_mp_lib: self.cfg.update('configopts', '-DGMX_%s_USER=%s' % (libname, libsci_mpi_mp_lib[0])) else: raise EasyBuildError("Failed to find libsci library to link with for %s", libname) else: # -DGMX_BLAS_USER & -DGMX_LAPACK_USER require full path to library # prefer shared libraries when using FlexiBLAS-based toolchain if self.toolchain.blas_family() == toolchain.FLEXIBLAS: libs = os.getenv('%s_SHARED_LIBS' % libname).split(',') else: libs = os.getenv('%s_STATIC_LIBS' % libname).split(',') libpaths = [os.path.join(libdir, lib) for lib in libs if not lib.startswith('libgfortran')] self.cfg.update('configopts', '-DGMX_%s_USER="******"' % (libname, ';'.join(libpaths))) # if libgfortran.a is listed, make sure it gets linked in too to avoiding linking issues if 'libgfortran.a' in libs: env.setvar('LDFLAGS', "%s -lgfortran -lm" % os.environ.get('LDFLAGS', '')) # no more GSL support in GROMACS 5.x, see http://redmine.gromacs.org/issues/1472 if LooseVersion(self.version) < LooseVersion('5.0'): # enable GSL when it's provided if get_software_root('GSL'): self.cfg.update('configopts', "-DGMX_GSL=ON") else: self.cfg.update('configopts', "-DGMX_GSL=OFF") # include flags for linking to zlib/XZ in $LDFLAGS if they're listed as a dep; # this is important for the tests, to correctly link against libxml2 for dep, link_flag in [('XZ', '-llzma'), ('zlib', '-lz')]: root = get_software_root(dep) if root: libdir = get_software_libdir(dep) ldflags = os.environ.get('LDFLAGS', '') env.setvar('LDFLAGS', "%s -L%s %s" % (ldflags, os.path.join(root, libdir), link_flag)) # complete configuration with configure_method of parent out = super(EB_GROMACS, self).configure_step() # for recent GROMACS versions, make very sure that a decent BLAS, LAPACK and FFT is found and used if LooseVersion(self.version) >= LooseVersion('4.6.5'): patterns = [ r"Using external FFT library - \S*", r"Looking for dgemm_ - found", r"Looking for cheev_ - found", ] for pattern in patterns: regex = re.compile(pattern, re.M) if not regex.search(out): raise EasyBuildError("Pattern '%s' not found in GROMACS configuration output.", pattern)
def configure_step(self): """ Configure build outside of source directory. """ try: objdir = os.path.join(self.builddir, 'obj') os.makedirs(objdir) os.chdir(objdir) except OSError as err: raise EasyBuildError("Failed to prepare for configuration of PSI build: %s", err) env.setvar('F77FLAGS', os.getenv('F90FLAGS')) # In order to create new plugins with PSI, it needs to know the location of the source # and the obj dir after install. These env vars give that information to the configure script. self.psi_srcdir = os.path.basename(self.cfg['start_dir'].rstrip(os.sep)) self.install_psi_objdir = os.path.join(self.installdir, 'obj') self.install_psi_srcdir = os.path.join(self.installdir, self.psi_srcdir) env.setvar('PSI_OBJ_INSTALL_DIR', self.install_psi_objdir) env.setvar('PSI_SRC_INSTALL_DIR', self.install_psi_srcdir) # explicitely specify Python binary to use pythonroot = get_software_root('Python') if not pythonroot: raise EasyBuildError("Python module not loaded.") # pre 4.0b5, they were using autotools, on newer it's CMake if LooseVersion(self.version) <= LooseVersion("4.0b5") and self.name == "PSI": # Use EB Boost boostroot = get_software_root('Boost') if not boostroot: raise EasyBuildError("Boost module not loaded.") self.log.info("Using configure based build") env.setvar('PYTHON', os.path.join(pythonroot, 'bin', 'python')) env.setvar('USE_SYSTEM_BOOST', 'TRUE') if self.toolchain.options.get('usempi', None): # PSI doesn't require a Fortran compiler itself, but may require it to link to BLAS/LAPACK correctly # we should always specify the sequential Fortran compiler, # to avoid problems with -lmpi vs -lmpi_mt during linking fcompvar = 'F77_SEQ' else: fcompvar = 'F77' # update configure options # using multi-threaded BLAS/LAPACK is important for performance, # cfr. http://sirius.chem.vt.edu/psi4manual/latest/installfile.html#sec-install-iii opt_vars = [ ('cc', 'CC'), ('cxx', 'CXX'), ('fc', fcompvar), ('libdirs', 'LDFLAGS'), ('blas', 'LIBBLAS_MT'), ('lapack', 'LIBLAPACK_MT'), ] for (opt, var) in opt_vars: self.cfg.update('configopts', "--with-%s='%s'" % (opt, os.getenv(var))) # -DMPICH_IGNORE_CXX_SEEK dances around problem with order of stdio.h and mpi.h headers # both define SEEK_SET, this makes the one for MPI be ignored self.cfg.update('configopts', "--with-opt='%s -DMPICH_IGNORE_CXX_SEEK'" % os.getenv('CFLAGS')) # specify location of Boost self.cfg.update('configopts', "--with-boost=%s" % boostroot) # enable support for plugins self.cfg.update('configopts', "--with-plugins") ConfigureMake.configure_step(self, cmd_prefix=self.cfg['start_dir']) else: self.log.info("Using CMake based build") self.cfg.update('configopts', ' -DPYTHON_INTERPRETER=%s' % os.path.join(pythonroot, 'bin', 'python')) if self.name == 'PSI4' and LooseVersion(self.version) >= LooseVersion("1.2"): self.log.info("Remove the CMAKE_BUILD_TYPE test in PSI4 source and the downloaded dependencies!") self.log.info("Use PATCH_COMMAND in the corresponding CMakeLists.txt") self.cfg.update('configopts', ' -DCMAKE_BUILD_TYPE=EasyBuildRelease') else: self.cfg.update('configopts', ' -DCMAKE_BUILD_TYPE=Release') if self.toolchain.options.get('usempi', None): self.cfg.update('configopts', " -DENABLE_MPI=ON") if get_software_root('imkl'): self.cfg.update('configopts', " -DENABLE_CSR=ON -DBLAS_TYPE=MKL") if self.name == 'PSI4': pcmsolverroot = get_software_root('PCMSolver') if pcmsolverroot: self.cfg.update('configopts', " -DENABLE_PCMSOLVER=ON") if LooseVersion(self.version) < LooseVersion("1.2"): self.cfg.update('configopts', " -DPCMSOLVER_ROOT=%s" % pcmsolverroot) else: self.cfg.update('configopts', " -DCMAKE_INSIST_FIND_PACKAGE_PCMSolver=ON " "-DPCMSolver_DIR=%s/share/cmake/PCMSolver" % pcmsolverroot) chempsroot = get_software_root('CheMPS2') if chempsroot: self.cfg.update('configopts', " -DENABLE_CHEMPS2=ON") if LooseVersion(self.version) < LooseVersion("1.2"): self.cfg.update('configopts', " -DCHEMPS2_ROOT=%s" % chempsroot) else: self.cfg.update('configopts', " -DCMAKE_INSIST_FIND_PACKAGE_CheMPS2=ON " "-DCheMPS2_DIR=%s/share/cmake/CheMPS2" % chempsroot) # Be aware, PSI4 wants exact versions of the following deps! built with CMake!! # If you want to use non-CMake build versions, the you have to provide the # corresponding Find<library-name>.cmake scripts # In PSI4 version 1.2.1, you can check the corresponding CMakeLists.txt file # in external/upstream/<library-name>/ if LooseVersion(self.version) >= LooseVersion("1.2"): for dep in ['libxc', 'Libint', 'pybind11', 'gau2grid']: deproot = get_software_root(dep) if deproot: self.cfg.update('configopts', " -DCMAKE_INSIST_FIND_PACKAGE_%s=ON" % dep) dep_dir = os.path.join(deproot, 'share', 'cmake', dep) self.cfg.update('configopts', " -D%s_DIR=%s " % (dep, dep_dir)) CMakeMake.configure_step(self, srcdir=self.cfg['start_dir'])
def configure_step(self): """Custom configuration procedure for GROMACS: set configure options for configure or cmake.""" # check whether PLUMED is loaded as a dependency plumed_root = get_software_root('PLUMED') if plumed_root: # Need to check if PLUMED has an engine for this version engine = 'gromacs-%s' % self.version (out, _) = run_cmd("plumed-patch -l", log_all=True, simple=False) if not re.search(engine, out): raise EasyBuildError( "There is no support in PLUMED version %s for GROMACS %s: %s", get_software_version('PLUMED'), self.version, out) # PLUMED patching must be done at different stages depending on # version of GROMACS. Just prepare first part of cmd here plumed_cmd = "plumed-patch -p -e %s" % engine if LooseVersion(self.version) < LooseVersion('4.6'): self.log.info( "Using configure script for configuring GROMACS build.") # Use static libraries if possible self.cfg.update('configopts', "--enable-static") # Use external BLAS and LAPACK self.cfg.update('configopts', "--with-external-blas --with-external-lapack") env.setvar('LIBS', "%s %s" % (os.environ['LIBLAPACK'], os.environ['LIBS'])) # Don't use the X window system self.cfg.update('configopts', "--without-x") # OpenMP is not supported for versions older than 4.5. if LooseVersion(self.version) >= LooseVersion('4.5'): # enable OpenMP support if desired if self.toolchain.options.get('openmp', None): self.cfg.update('configopts', "--enable-threads") else: self.cfg.update('configopts', "--disable-threads") elif self.toolchain.options.get('openmp', None): raise EasyBuildError( "GROMACS version %s does not support OpenMP" % self.version) # GSL support if get_software_root('GSL'): self.cfg.update('configopts', "--with-gsl") else: self.cfg.update('configopts', "--without-gsl") # actually run configure via ancestor (not direct parent) self.cfg['configure_cmd'] = "./configure" ConfigureMake.configure_step(self) # Now patch GROMACS for PLUMED between configure and build if plumed_root: run_cmd(plumed_cmd, log_all=True, simple=True) else: # Now patch GROMACS for PLUMED before cmake if plumed_root: if LooseVersion(self.version) >= LooseVersion('5.1'): # Use shared or static patch depending on # setting of self.toolchain.options.get('dynamic') # and adapt cmake flags accordingly as per instructions # from "plumed patch -i" if self.toolchain.options.get('dynamic', False): mode = 'shared' else: mode = 'static' plumed_cmd = plumed_cmd + ' -m %s' % mode run_cmd(plumed_cmd, log_all=True, simple=True) # Select debug or release build if self.toolchain.options.get('debug', None): self.cfg.update('configopts', "-DCMAKE_BUILD_TYPE=Debug") else: self.cfg.update('configopts', "-DCMAKE_BUILD_TYPE=Release") # prefer static libraries, if available if self.toolchain.options.get('dynamic', False): self.cfg.update('configopts', "-DGMX_PREFER_STATIC_LIBS=OFF") else: self.cfg.update('configopts', "-DGMX_PREFER_STATIC_LIBS=ON") if plumed_root: self.cfg.update('configopts', "-DBUILD_SHARED_LIBS=OFF") if self.cfg['double_precision']: self.cfg.update('configopts', "-DGMX_DOUBLE=ON") # always specify to use external BLAS/LAPACK self.cfg.update('configopts', "-DGMX_EXTERNAL_BLAS=ON -DGMX_EXTERNAL_LAPACK=ON") # disable GUI tools self.cfg.update('configopts', "-DGMX_X11=OFF") # convince to build for an older architecture than present on the build node by setting GMX_SIMD CMake flag gmx_simd = self.get_gromacs_arch() if gmx_simd: if LooseVersion(self.version) < LooseVersion('5.0'): self.cfg.update('configopts', "-DGMX_CPU_ACCELERATION=%s" % gmx_simd) else: self.cfg.update('configopts', "-DGMX_SIMD=%s" % gmx_simd) # set regression test path prefix = 'regressiontests' if any([src['name'].startswith(prefix) for src in self.src]): major_minor_version = '.'.join(self.version.split('.')[:2]) self.cfg.update( 'configopts', "-DREGRESSIONTEST_PATH='%%(builddir)s/%s-%%(version)s' " % prefix) # enable OpenMP support if desired if self.toolchain.options.get('openmp', None): self.cfg.update('configopts', "-DGMX_OPENMP=ON") else: self.cfg.update('configopts', "-DGMX_OPENMP=OFF") # disable MPI support for initial, serial/SMP build; actual MPI build is done later self.cfg.update('configopts', "-DGMX_MPI=OFF") # explicitly disable GPU support if CUDA is not available, # to avoid that GROMACS find and uses a system-wide CUDA compiler cuda = get_software_root('CUDA') if cuda: self.cfg.update( 'configopts', "-DGMX_GPU=ON -DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda) else: self.cfg.update('configopts', "-DGMX_GPU=OFF") if get_software_root('imkl'): # using MKL for FFT, so it will also be used for BLAS/LAPACK self.cfg.update( 'configopts', '-DGMX_FFT_LIBRARY=mkl -DMKL_INCLUDE_DIR="$EBROOTMKL/mkl/include" ' ) libs = os.getenv('LAPACK_STATIC_LIBS').split(',') mkl_libs = [ os.path.join(os.getenv('LAPACK_LIB_DIR'), lib) for lib in libs if lib != 'libgfortran.a' ] mkl_libs = ['-Wl,--start-group' ] + mkl_libs + ['-Wl,--end-group'] self.cfg.update('configopts', '-DMKL_LIBRARIES="%s" ' % ';'.join(mkl_libs)) else: shlib_ext = get_shared_lib_ext() for libname in ['BLAS', 'LAPACK']: libdir = os.getenv('%s_LIB_DIR' % libname) if self.toolchain.toolchain_family() == toolchain.CRAYPE: libsci_mpi_mp_lib = glob.glob( os.path.join(libdir, 'libsci_*_mpi_mp.a')) if libsci_mpi_mp_lib: self.cfg.update( 'configopts', '-DGMX_%s_USER=%s' % (libname, libsci_mpi_mp_lib[0])) else: raise EasyBuildError( "Failed to find libsci library to link with for %s", libname) else: # -DGMX_BLAS_USER & -DGMX_LAPACK_USER require full path to library libs = os.getenv('%s_STATIC_LIBS' % libname).split(',') libpaths = [ os.path.join(libdir, lib) for lib in libs if lib != 'libgfortran.a' ] self.cfg.update( 'configopts', '-DGMX_%s_USER="******"' % (libname, ';'.join(libpaths))) # if libgfortran.a is listed, make sure it gets linked in too to avoiding linking issues if 'libgfortran.a' in libs: env.setvar( 'LDFLAGS', "%s -lgfortran -lm" % os.environ.get('LDFLAGS', '')) # no more GSL support in GROMACS 5.x, see http://redmine.gromacs.org/issues/1472 if LooseVersion(self.version) < LooseVersion('5.0'): # enable GSL when it's provided if get_software_root('GSL'): self.cfg.update('configopts', "-DGMX_GSL=ON") else: self.cfg.update('configopts', "-DGMX_GSL=OFF") # include flags for linking to zlib/XZ in $LDFLAGS if they're listed as a dep; # this is important for the tests, to correctly link against libxml2 for dep, link_flag in [('XZ', '-llzma'), ('zlib', '-lz')]: root = get_software_root(dep) if root: libdir = get_software_libdir(dep) ldflags = os.environ.get('LDFLAGS', '') env.setvar( 'LDFLAGS', "%s -L%s %s" % (ldflags, os.path.join(root, libdir), link_flag)) # complete configuration with configure_method of parent self.cfg['separate_build_dir'] = True out = super(EB_GROMACS, self).configure_step() # for recent GROMACS versions, make very sure that a decent BLAS, LAPACK and FFT is found and used if LooseVersion(self.version) >= LooseVersion('4.6.5'): patterns = [ r"Using external FFT library - \S*", r"Looking for dgemm_ - found", r"Looking for cheev_ - found", ] for pattern in patterns: regex = re.compile(pattern, re.M) if not regex.search(out): raise EasyBuildError( "Pattern '%s' not found in GROMACS configuration output.", pattern)
def install_step(self): """ Custom install step for GROMACS; figure out where libraries were installed to. Also, install the MPI version of the executable in a separate step. """ # run 'make install' in parallel since it involves more compilation self.cfg.update('installopts', "-j %s" % self.cfg['parallel']) super(EB_GROMACS, self).install_step() # the GROMACS libraries get installed in different locations (deeper subdirectory), depending on the platform; # this is determined by the GNUInstallDirs CMake module; # rather than trying to replicate the logic, we just figure out where the library was placed if self.toolchain.options.get('dynamic', False): self.libext = get_shared_lib_ext() else: self.libext = 'a' if LooseVersion(self.version) < LooseVersion('5.0'): libname = 'libgmx*.%s' % self.libext else: libname = 'libgromacs*.%s' % self.libext for libdir in ['lib', 'lib64']: if os.path.exists(os.path.join(self.installdir, libdir)): for subdir in [libdir, os.path.join(libdir, '*')]: libpaths = glob.glob( os.path.join(self.installdir, subdir, libname)) if libpaths: self.lib_subdir = os.path.dirname( libpaths[0])[len(self.installdir) + 1:] self.log.info( "Found lib subdirectory that contains %s: %s", libname, self.lib_subdir) break if not self.lib_subdir: raise EasyBuildError("Failed to determine lib subdirectory in %s", self.installdir) # Install a version with the MPI suffix if self.toolchain.options.get('usempi', None): if LooseVersion(self.version) < LooseVersion('4.6'): cmd = "make distclean" (out, _) = run_cmd(cmd, log_all=True, simple=False) self.cfg.update( 'configopts', "--enable-mpi --program-suffix={0}".format( self.cfg['mpisuffix'])) ConfigureMake.configure_step(self) super(EB_GROMACS, self).build_step() super(EB_GROMACS, self).install_step() else: self.cfg['configopts'] = re.sub(r'-DGMX_MPI=OFF', r'', self.cfg['configopts']) if self.cfg['mpi_numprocs'] == 0: self.log.info( "No number of test MPI tasks specified -- using default: %s" % self.cfg['parallel']) self.cfg['mpi_numprocs'] = self.cfg['parallel'] elif self.cfg['mpi_numprocs'] > self.cfg['parallel']: self.log.warning( "Number of test MPI tasks (%s) is greater than value for 'parallel': %s", self.cfg['mpi_numprocs'], self.cfg['parallel']) self.cfg.update('configopts', "-DGMX_MPI=ON -DGMX_THREAD_MPI=OFF") mpiexec = which(self.cfg['mpiexec']) if mpiexec: self.cfg.update('configopts', "-DMPIEXEC=%s" % mpiexec) self.cfg.update( 'configopts', "-DMPIEXEC_NUMPROC_FLAG=%s" % self.cfg['mpiexec_numproc_flag']) self.cfg.update('configopts', "-DNUMPROC=%s" % self.cfg['mpi_numprocs']) elif self.cfg['runtest']: raise EasyBuildError("'%s' not found in $PATH", self.cfg['mpiexec']) self.log.info( "Using %s as MPI executable when testing, with numprocs flag '%s' and %s tasks", self.cfg['mpiexec'], self.cfg['mpiexec_numproc_flag'], self.cfg['mpi_numprocs']) # clean up obj dir before reconfiguring shutil.rmtree(os.path.join(self.builddir, 'easybuild_obj')) # rebuild/test/install with MPI options super(EB_GROMACS, self).configure_step() super(EB_GROMACS, self).build_step() super(EB_GROMACS, self).test_step() super(EB_GROMACS, self).install_step() self.log.info( "A full regression test suite is available from the GROMACS web site" )
def configure_step(self): """Add some extra configure options.""" if LooseVersion(self.version) >= LooseVersion('2.6.0'): # Libint 2.6.0 requires first compiling the Libint compiler, # by running configure with appropriate options, followed by 'make export' # and unpacking the resulting source tarball; # see https://github.com/evaleev/libint/wiki#compiling-libint-compiler # CMake is recommended, but configuring with Fortran support doesn't work correctly yet in Libint 2.6.0 # so stick to traditional configure script for now print_msg("configuring Libint compiler...") # first run autogen.sh script to generate initial configure script run_cmd("./autogen.sh") cmd = ' '.join([ self.cfg['preconfigopts'], './configure', self.cfg['configopts'], self.cfg['libint_compiler_configopts'], ]) run_cmd(cmd) print_msg("generating Libint library...") run_cmd("make export") source_fn = 'libint-%s.tgz' % self.version if os.path.exists(source_fn): extract_file(source_fn, os.getcwd(), change_into_dir=False) change_dir('libint-%s' % self.version) else: raise EasyBuildError( "Could not find generated source tarball after 'make export'!" ) # Libint < 2.7.0 can be configured using configure script, # Libint >= 2.7.0 should be configured via cmake if LooseVersion(self.version) < LooseVersion('2.7.0'): # also build shared libraries (not enabled by default) self.cfg.update('configopts', "--enable-shared") if self.toolchain.options['pic']: # Enforce consistency. self.cfg.update('configopts', "--with-pic") if LooseVersion( self.version) >= LooseVersion('2.0') and LooseVersion( self.version) < LooseVersion('2.1'): # the code in libint is automatically generated and hence it is in some # parts so complex that -O2 or -O3 compiler optimization takes forever self.cfg.update('configopts', "--with-cxx-optflags='-O1'") elif LooseVersion(self.version) >= LooseVersion('2.1'): # pass down $CXXFLAGS to --with-cxxgen-optflags configure option; # mainly to avoid warning about it not being set (but $CXXFLAGS is picked up anyway in practice) self.cfg.update( 'configopts', "--with-cxxgen-optflags='%s'" % os.getenv('CXXFLAGS')) # --enable-fortran is only a known configure option for Libint library, not for Libint compiler, # so only add --enable-fortran *after* configuring & generating Libint compiler if self.cfg['with_fortran']: self.cfg.update('configopts', '--enable-fortran') self.cfg['configure_cmd'] = DEFAULT_CONFIGURE_CMD ConfigureMake.configure_step(self) else: if self.cfg['with_fortran']: self.cfg.update('configopts', '-DENABLE_FORTRAN=ON') # also build shared libraries (not enabled by default) self.cfg.update('configopts', "-DLIBINT2_BUILD_SHARED_AND_STATIC_LIBS=ON") # specify current directory as source directory (that contains CMakeLists.txt), # since that's the path to the unpacked source tarball for Libint library (created by 'make export') super(EB_Libint, self).configure_step(srcdir=os.getcwd())
def configure_step(self): """Dedicated configure step for Mono: install Mono from RPM (if provided), then run configure.""" # install Mono from RPMs if provided (because we need Mono to build Mono) if self.rpms: # prepare path for installing RPMs in monorpms_path = os.path.join(self.builddir, "monorpms") try: os.makedirs(os.path.join(monorpms_path, 'rpm')) except OSError as err: raise EasyBuildError("Failed to create directories for installing Mono RPMs in: %s", err) self.src = self.rpms self.rebuildRPM = True # rebuild RPMs to make them relocatable Rpm.configure_step(self) # prepare to install RPMs self.log.debug("Initializing temporary RPM repository to install to...") cmd = "rpm --initdb --dbpath /rpm --root %s" % monorpms_path run_cmd(cmd, log_all=True, simple=True) # install RPMs one by one for rpm in self.src: self.log.debug("Installing RPM %s ..." % rpm['name']) if os.path.exists(rpm['path']): cmd = ' '.join([ "rpm -i", "--dbpath %(inst)s/rpm", "--force", "--relocate /=%(inst)s", "--badreloc", "--nodeps --nopost", "%(rpm)s", ]) % { 'inst': monorpms_path, 'rpm': rpm['path'], } run_cmd(cmd,log_all=True,simple=True) else: raise EasyBuildError("RPM file %s not found", rpm['path']) # create patched version of gmcs command self.log.debug("Making our own copy of gmcs (one that works).") mygmcs_path = os.path.join(monorpms_path, 'usr', 'bin', 'mygmcs') try: shutil.copy(os.path.join(monorpms_path, 'usr' ,'bin', 'gmcs'), mygmcs_path) except OSError as err: raise EasyBuildError("Failed to copy gmcs to %s: %s", mygmcs_path, err) rpls = [ ("exec /usr/bin/mono", "exec %s/usr/bin/mono" % monorpms_path), ("`/usr/bin/monodir`", "%s/usr/lib64/mono" % monorpms_path), ] apply_regex_substitutions(mygmcs_path, rpls) self.log.debug("Patched version of gmcs (%s): %s" % (mygmcs_path, read_file(mygmcs_path))) # initiate bootstrap: build/install Mono with installed RPMs to temporary path tmp_mono_path = os.path.join(self.builddir, "tmp_mono") self.log.debug("Build/install temporary Mono version in %s using installed RPMs..." % tmp_mono_path) par = '' if self.cfg['parallel']: par = "-j %s" % self.cfg['parallel'] config_cmd = "%s ./configure --prefix=%s %s" % (self.cfg['preconfigopts'], tmp_mono_path, self.cfg['configopts']) build_cmd = ' '.join([ "%(prebuildopts)s" "make %(par)s", "EXTERNAL_MCS=%(path)s/usr/bin/mygmcs", "EXTERNAL_RUNTIME=%(path)s/usr/bin/mono", "%(buildopts)s", ]) %{ 'prebuildopts': self.cfg['prebuildopts'], 'par': par, 'path': monorpms_path, 'buildopts': self.cfg['buildopts'], } install_cmd = "make install" for cmd in [config_cmd, build_cmd, install_cmd]: run_cmd(cmd, log_all=True, simple=True) more_buildopts = ' '.join([ "EXTERNAL_MCS=%(path)s/bin/gmcs", "EXTERNAL_RUNTIME=%(path)s/bin/mono", ]) % {'path': tmp_mono_path} self.cfg.update('buildopts', more_buildopts) self.src = self.mono_srcs # continue with normal configure, and subsequent make, make install ConfigureMake.configure_step(self)
def configure_step(self): """Configuration step, we set FC, F77 is already set by EasyBuild to the right compiler, FC is used for Fortan90""" environment.setvar("FC", self.toolchain.get_variable('F90')) ConfigureMake.configure_step(self)
class EB_PSI(CMakeMake): """ Support for building and installing PSI """ def __init__(self, *args, **kwargs): """Initialize class variables custom to PSI.""" super(EB_PSI, self).__init__(*args, **kwargs) self.psi_srcdir = None self.install_psi_objdir = None self.install_psi_srcdir = None @staticmethod def extra_options(): """Extra easyconfig parameters specific to PSI.""" extra_vars = { # always include running PSI unit tests (takes about 2h or less) 'runtest': ["tests TESTFLAGS='-u -q'", "Run tests included with PSI, without interruption.", BUILD], } return CMakeMake.extra_options(extra_vars) def configure_step(self): """ Configure build outside of source directory. """ try: objdir = os.path.join(self.builddir, 'obj') os.makedirs(objdir) os.chdir(objdir) except OSError, err: raise EasyBuildError("Failed to prepare for configuration of PSI build: %s", err) env.setvar('F77FLAGS', os.getenv('F90FLAGS')) # In order to create new plugins with PSI, it needs to know the location of the source # and the obj dir after install. These env vars give that information to the configure script. self.psi_srcdir = os.path.basename(self.cfg['start_dir'].rstrip(os.sep)) self.install_psi_objdir = os.path.join(self.installdir, 'obj') self.install_psi_srcdir = os.path.join(self.installdir, self.psi_srcdir) env.setvar('PSI_OBJ_INSTALL_DIR', self.install_psi_objdir) env.setvar('PSI_SRC_INSTALL_DIR', self.install_psi_srcdir) # explicitely specify Python binary to use pythonroot = get_software_root('Python') if not pythonroot: raise EasyBuildError("Python module not loaded.") # Use EB Boost boostroot = get_software_root('Boost') if not boostroot: raise EasyBuildError("Boost module not loaded.") # pre 4.0b5, they were using autotools, on newer it's CMake if LooseVersion(self.version) <= LooseVersion("4.0b5"): env.setvar('PYTHON', os.path.join(pythonroot, 'bin', 'python')) env.setvar('USE_SYSTEM_BOOST', 'TRUE') if self.toolchain.options.get('usempi', None): # PSI doesn't require a Fortran compiler itself, but may require it to link to BLAS/LAPACK correctly # we should always specify the sequential Fortran compiler, # to avoid problems with -lmpi vs -lmpi_mt during linking fcompvar = 'F77_SEQ' else: fcompvar = 'F77' # update configure options # using multi-threaded BLAS/LAPACK is important for performance, # cfr. http://sirius.chem.vt.edu/psi4manual/latest/installfile.html#sec-install-iii opt_vars = [ ('cc', 'CC'), ('cxx', 'CXX'), ('fc', fcompvar), ('libdirs', 'LDFLAGS'), ('blas', 'LIBBLAS_MT'), ('lapack', 'LIBLAPACK_MT'), ] for (opt, var) in opt_vars: self.cfg.update('configopts', "--with-%s='%s'" % (opt, os.getenv(var))) # -DMPICH_IGNORE_CXX_SEEK dances around problem with order of stdio.h and mpi.h headers # both define SEEK_SET, this makes the one for MPI be ignored self.cfg.update('configopts', "--with-opt='%s -DMPICH_IGNORE_CXX_SEEK'" % os.getenv('CFLAGS')) # specify location of Boost self.cfg.update('configopts', "--with-boost=%s" % boostroot) # enable support for plugins self.cfg.update('configopts', "--with-plugins") ConfigureMake.configure_step(self, cmd_prefix=self.cfg['start_dir']) else: self.cfg['configopts'] += "-DPYTHON_INTERPRETER=%s " % os.path.join(pythonroot, 'bin', 'python') self.cfg['configopts'] += "-DCMAKE_BUILD_TYPE=Release " if self.toolchain.options.get('usempi', None): self.cfg['configopts'] += "-DENABLE_MPI=ON " if get_software_root('impi'): self.cfg['configopts'] += "-DENABLE_CSR=ON -DBLAS_TYPE=MKL " CMakeMake.configure_step(self, srcdir=self.cfg['start_dir'])
def install_step(self): """ Custom install step for GROMACS; figure out where libraries were installed to. Also, install the MPI version of the executable in a separate step. """ # run 'make install' in parallel since it involves more compilation self.cfg.update('installopts', "-j %s" % self.cfg['parallel']) super(EB_GROMACS, self).install_step() # the GROMACS libraries get installed in different locations (deeper subdirectory), depending on the platform; # this is determined by the GNUInstallDirs CMake module; # rather than trying to replicate the logic, we just figure out where the library was placed if self.toolchain.options.get('dynamic', False): self.libext = get_shared_lib_ext() else: self.libext = 'a' if LooseVersion(self.version) < LooseVersion('5.0'): libname = 'libgmx*.%s' % self.libext else: libname = 'libgromacs*.%s' % self.libext for libdir in ['lib', 'lib64']: if os.path.exists(os.path.join(self.installdir, libdir)): for subdir in [libdir, os.path.join(libdir, '*')]: libpaths = glob.glob(os.path.join(self.installdir, subdir, libname)) if libpaths: self.lib_subdir = os.path.dirname(libpaths[0])[len(self.installdir)+1:] self.log.info("Found lib subdirectory that contains %s: %s", libname, self.lib_subdir) break if not self.lib_subdir: raise EasyBuildError("Failed to determine lib subdirectory in %s", self.installdir) # Install a version with the MPI suffix if self.toolchain.options.get('usempi', None): if LooseVersion(self.version) < LooseVersion('4.6'): cmd = "make distclean" (out, _) = run_cmd(cmd, log_all=True, simple=False) self.cfg.update('configopts', "--enable-mpi --program-suffix={0}".format(self.cfg['mpisuffix'])) ConfigureMake.configure_step(self) super(EB_GROMACS, self).build_step() super(EB_GROMACS, self).install_step() else: self.cfg['configopts'] = re.sub(r'-DGMX_MPI=OFF', r'', self.cfg['configopts']) if self.cfg['mpi_numprocs'] == 0: self.log.info("No number of test MPI tasks specified -- using default: %s" % self.cfg['parallel']) self.cfg['mpi_numprocs'] = self.cfg['parallel'] elif self.cfg['mpi_numprocs'] > self.cfg['parallel']: self.log.warning("Number of test MPI tasks (%s) is greater than value for 'parallel': %s", self.cfg['mpi_numprocs'], self.cfg['parallel']) self.cfg.update('configopts', "-DGMX_MPI=ON -DGMX_THREAD_MPI=OFF") mpiexec = which(self.cfg['mpiexec']) if mpiexec: self.cfg.update('configopts', "-DMPIEXEC=%s" % mpiexec) self.cfg.update('configopts', "-DMPIEXEC_NUMPROC_FLAG=%s" % self.cfg['mpiexec_numproc_flag']) self.cfg.update('configopts', "-DNUMPROC=%s" % self.cfg['mpi_numprocs']) elif self.cfg['runtest']: raise EasyBuildError("'%s' not found in $PATH", self.cfg['mpiexec']) self.log.info("Using %s as MPI executable when testing, with numprocs flag '%s' and %s tasks", self.cfg['mpiexec'], self.cfg['mpiexec_numproc_flag'], self.cfg['mpi_numprocs']) # clean up obj dir before reconfiguring shutil.rmtree(os.path.join(self.builddir, 'easybuild_obj')) # rebuild/test/install with MPI options super(EB_GROMACS, self).configure_step() super(EB_GROMACS, self).build_step() super(EB_GROMACS, self).test_step() super(EB_GROMACS, self).install_step() self.log.info("A full regression test suite is available from the GROMACS web site")
def configure_step(self): """Custom configuration procedure for GROMACS: set configure options for configure or cmake.""" if LooseVersion(self.version) < LooseVersion('4.6'): self.log.info("Using configure script for configuring GROMACS build.") # Use static libraries if possible self.cfg.update('configopts', "--enable-static") # Use external BLAS and LAPACK self.cfg.update('configopts', "--with-external-blas --with-external-lapack") env.setvar('LIBS', "%s %s" % (os.environ['LIBLAPACK'], os.environ['LIBS'])) # Don't use the X window system self.cfg.update('configopts', "--without-x") # OpenMP is not supported for versions older than 4.5. if LooseVersion(self.version) >= LooseVersion('4.5'): # enable OpenMP support if desired if self.toolchain.options.get('openmp', None): self.cfg.update('configopts', "--enable-threads") else: self.cfg.update('configopts', "--disable-threads") elif self.toolchain.options.get('openmp', None): raise EasyBuildError("GROMACS version %s does not support OpenMP" % self.version) # GSL support if get_software_root('GSL'): self.cfg.update('configopts', "--with-gsl") else: self.cfg.update('configopts', "--without-gsl") # actually run configure via ancestor (not direct parent) ConfigureMake.configure_step(self) else: # build a release build self.cfg.update('configopts', "-DCMAKE_BUILD_TYPE=Release") # prefer static libraries, if available if self.toolchain.options.get('dynamic', False): self.cfg.update('configopts', "-DGMX_PREFER_STATIC_LIBS=OFF") else: self.cfg.update('configopts', "-DGMX_PREFER_STATIC_LIBS=ON") if self.cfg['double_precision']: self.cfg.update('configopts', "-DGMX_DOUBLE=ON") # always specify to use external BLAS/LAPACK self.cfg.update('configopts', "-DGMX_EXTERNAL_BLAS=ON -DGMX_EXTERNAL_LAPACK=ON") # disable GUI tools self.cfg.update('configopts', "-DGMX_X11=OFF") # set regression test path prefix = 'regressiontests' if any([src['name'].startswith(prefix) for src in self.src]): major_minor_version = '.'.join(self.version.split('.')[:2]) self.cfg.update('configopts', "-DREGRESSIONTEST_PATH='%%(builddir)s/%s-%%(version)s' " % prefix) # enable OpenMP support if desired if self.toolchain.options.get('openmp', None): self.cfg.update('configopts', "-DGMX_OPENMP=ON") else: self.cfg.update('configopts', "-DGMX_OPENMP=OFF") # disable MPI support for initial, serial/SMP build; actual MPI build is done later self.cfg.update('configopts', "-DGMX_MPI=OFF") # explicitly disable GPU support if CUDA is not available, # to avoid that GROMACS find and uses a system-wide CUDA compiler cuda = get_software_root('CUDA') if cuda: self.cfg.update('configopts', "-DGMX_GPU=ON -DCUDA_TOOLKIT_ROOT_DIR=%s" % cuda) else: self.cfg.update('configopts', "-DGMX_GPU=OFF") if get_software_root('imkl'): # using MKL for FFT, so it will also be used for BLAS/LAPACK self.cfg.update('configopts', '-DGMX_FFT_LIBRARY=mkl -DMKL_INCLUDE_DIR="$EBROOTMKL/mkl/include" ') mkl_libs = [os.path.join(os.getenv('LAPACK_LIB_DIR'), lib) for lib in ['libmkl_lapack.a']] self.cfg.update('configopts', '-DMKL_LIBRARIES="%s" ' % ';'.join(mkl_libs)) else: shlib_ext = get_shared_lib_ext() for libname in ['BLAS', 'LAPACK']: libdir = os.getenv('%s_LIB_DIR' % libname) if self.toolchain.toolchain_family() == toolchain.CRAYPE: libsci_mpi_mp_lib = glob.glob(os.path.join(libdir, 'libsci_*_mpi_mp.a')) if libsci_mpi_mp_lib: self.cfg.update('configopts', '-DGMX_%s_USER=%s' % (libname, libsci_mpi_mp_lib[0])) else: raise EasyBuildError("Failed to find libsci library to link with for %s", libname) else: # -DGMX_BLAS_USER & -DGMX_LAPACK_USER require full path to library libs = os.getenv('%s_STATIC_LIBS' % libname).split(',') libpaths = [os.path.join(libdir, lib) for lib in libs if lib != 'libgfortran.a'] self.cfg.update('configopts', '-DGMX_%s_USER="******"' % (libname, ';'.join(libpaths))) # if libgfortran.a is listed, make sure it gets linked in too to avoiding linking issues if 'libgfortran.a' in libs: env.setvar('LDFLAGS', "%s -lgfortran -lm" % os.environ.get('LDFLAGS', '')) # no more GSL support in GROMACS 5.x, see http://redmine.gromacs.org/issues/1472 if LooseVersion(self.version) < LooseVersion('5.0'): # enable GSL when it's provided if get_software_root('GSL'): self.cfg.update('configopts', "-DGMX_GSL=ON") else: self.cfg.update('configopts', "-DGMX_GSL=OFF") # include flags for linking to zlib/XZ in $LDFLAGS if they're listed as a dep; # this is important for the tests, to correctly link against libxml2 for dep, link_flag in [('XZ', '-llzma'), ('zlib', '-lz')]: root = get_software_root(dep) if root: libdir = get_software_libdir(dep) ldflags = os.environ.get('LDFLAGS', '') env.setvar('LDFLAGS', "%s -L%s %s" % (ldflags, os.path.join(root, libdir), link_flag)) # complete configuration with configure_method of parent self.cfg['separate_build_dir'] = True out = super(EB_GROMACS, self).configure_step() # for recent GROMACS versions, make very sure that a decent BLAS, LAPACK and FFT is found and used if LooseVersion(self.version) >= LooseVersion('4.6.5'): patterns = [ r"Using external FFT library - \S*", r"Looking for dgemm_ - found", r"Looking for cheev_ - found", ] for pattern in patterns: regex = re.compile(pattern, re.M) if not regex.search(out): raise EasyBuildError("Pattern '%s' not found in GROMACS configuration output.", pattern)