def prepare_step(self, *args, **kwargs): """Do compiler appropriate prepare step, determine system compiler version and prefix.""" if self.cfg['generate_standalone_module']: if self.cfg['name'] in ['GCC', 'GCCcore']: EB_GCC.prepare_step(self, *args, **kwargs) elif self.cfg['name'] in ['icc']: EB_icc.prepare_step(self, *args, **kwargs) elif self.cfg['name'] in ['ifort']: EB_ifort.prepare_step(self, *args, **kwargs) else: raise EasyBuildError( "I don't know how to do the prepare_step for %s", self.cfg['name']) else: Bundle.prepare_step(self, *args, **kwargs) # Determine compiler path (real path, with resolved symlinks) compiler_name = self.cfg['name'].lower() if compiler_name == 'gcccore': compiler_name = 'gcc' path_to_compiler = which(compiler_name) if path_to_compiler: path_to_compiler = resolve_path(path_to_compiler) self.log.info( "Found path to compiler '%s' (with symlinks resolved): %s", compiler_name, path_to_compiler) else: raise EasyBuildError("%s not found in $PATH", compiler_name) # Determine compiler version self.compiler_version = extract_compiler_version(compiler_name) # Determine installation prefix if compiler_name == 'gcc': # strip off 'bin/gcc' self.compiler_prefix = os.path.dirname( os.path.dirname(path_to_compiler)) elif compiler_name in ['icc', 'ifort']: intelvars_fn = path_to_compiler + 'vars.sh' if os.path.isfile(intelvars_fn): self.log.debug( "Trying to determine compiler install prefix from %s", intelvars_fn) intelvars_txt = read_file(intelvars_fn) prod_dir_regex = re.compile(r'^PROD_DIR=(.*)$', re.M) res = prod_dir_regex.search(intelvars_txt) if res: self.compiler_prefix = res.group(1) else: raise EasyBuildError( "Failed to determine %s installation prefix from %s", compiler_name, intelvars_fn) else: # strip off 'bin/intel*/icc' self.compiler_prefix = os.path.dirname( os.path.dirname(os.path.dirname(path_to_compiler))) # For versions 2016+ of Intel compilers they changed the installation path so must shave off 2 more # directories from result of the above if LooseVersion(self.compiler_version) >= LooseVersion('2016'): self.compiler_prefix = os.path.dirname( os.path.dirname(self.compiler_prefix)) else: raise EasyBuildError("Unknown system compiler %s" % self.cfg['name']) if not os.path.exists(self.compiler_prefix): raise EasyBuildError( "Path derived for system compiler (%s) does not exist: %s!", compiler_name, self.compiler_prefix) self.log.debug( "Derived version/install prefix for system compiler %s: %s, %s", compiler_name, self.compiler_version, self.compiler_prefix) # If EasyConfig specified "real" version (not 'system' which means 'derive automatically'), check it if self.cfg['version'] == 'system': self.log.info( "Found specified version '%s', going with derived compiler version '%s'", self.cfg['version'], self.compiler_version) elif self.cfg['version'] != self.compiler_version: raise EasyBuildError( "Specified version (%s) does not match version reported by compiler (%s)" % (self.cfg['version'], self.compiler_version))
class EB_DOLFIN(CMakePythonPackage): """Support for building and installing DOLFIN.""" def __init__(self, *args, **kwargs): """Initialize class variables.""" super(EB_DOLFIN, self).__init__(*args, **kwargs) self.boost_dir = None self.saved_configopts = None def configure_step(self): """Set DOLFIN-specific configure options and configure with CMake.""" # compilers self.cfg.update('configopts', "-DCMAKE_C_COMPILER='%s' " % os.getenv('CC')) self.cfg.update('configopts', "-DCMAKE_CXX_COMPILER='%s' " % os.getenv('CXX')) self.cfg.update('configopts', "-DCMAKE_Fortran_COMPILER='%s' " % os.getenv('F90')) # compiler flags cflags = os.getenv('CFLAGS') cxxflags = os.getenv('CXXFLAGS') fflags = os.getenv('FFLAGS') # fix for "SEEK_SET is #defined but must not be for the C++ binding of MPI. Include mpi.h before stdio.h" if self.toolchain.mpi_family() in [ toolchain.INTELMPI, toolchain.MPICH, toolchain.MPICH2, toolchain.MVAPICH2 ]: cflags += " -DMPICH_IGNORE_CXX_SEEK" cxxflags += " -DMPICH_IGNORE_CXX_SEEK" fflags += " -DMPICH_IGNORE_CXX_SEEK" self.cfg.update('configopts', '-DCMAKE_C_FLAGS="%s"' % cflags) self.cfg.update('configopts', '-DCMAKE_CXX_FLAGS="%s"' % cxxflags) self.cfg.update('configopts', '-DCMAKE_Fortran_FLAGS="%s"' % fflags) # run cmake in debug mode self.cfg.update('configopts', ' -DCMAKE_BUILD_TYPE=Debug') # set correct compilers to be used at runtime self.cfg.update('configopts', ' -DMPI_C_COMPILER="$MPICC"') self.cfg.update('configopts', ' -DMPI_CXX_COMPILER="$MPICXX"') # specify MPI library self.cfg.update('configopts', ' -DMPI_COMPILER="%s"' % os.getenv('MPICC')) if os.getenv('MPI_LIB_SHARED') and os.getenv('MPI_INC_DIR'): self.cfg.update( 'configopts', ' -DMPI_LIBRARY="%s"' % os.getenv('MPI_LIB_SHARED')) self.cfg.update( 'configopts', ' -DMPI_INCLUDE_PATH="%s"' % os.getenv('MPI_INC_DIR')) else: raise EasyBuildError( "MPI_LIB_SHARED or MPI_INC_DIR not set, could not determine MPI-related paths." ) # save config options to reuse them later (e.g. for sanity check commands) self.saved_configopts = self.cfg['configopts'] # make sure that required dependencies are loaded deps = [ 'Armadillo', 'Boost', 'CGAL', 'MTL4', 'ParMETIS', 'PETSc', 'Python', 'SCOTCH', 'Sphinx', 'SLEPc', 'SuiteSparse', 'Trilinos', 'UFC', 'zlib' ] depsdict = {} for dep in deps: deproot = get_software_root(dep) if not deproot: raise EasyBuildError("Dependency %s not available.", dep) else: depsdict.update({dep: deproot}) # zlib self.cfg.update( 'configopts', '-DZLIB_INCLUDE_DIR=%s' % os.path.join(depsdict['zlib'], "include")) self.cfg.update( 'configopts', '-DZLIB_LIBRARY=%s' % os.path.join(depsdict['zlib'], "lib", "libz.a")) # set correct openmp options openmp = self.toolchain.get_flag('openmp') self.cfg.update('configopts', ' -DOpenMP_CXX_FLAGS="%s"' % openmp) self.cfg.update('configopts', ' -DOpenMP_C_FLAGS="%s"' % openmp) # Boost config parameters self.cfg.update('configopts', " -DBOOST_INCLUDEDIR=%s/include" % depsdict['Boost']) self.cfg.update( 'configopts', " -DBoost_DEBUG=ON -DBOOST_ROOT=%s" % depsdict['Boost']) self.boost_dir = depsdict['Boost'] # UFC and Armadillo config params self.cfg.update('configopts', " -DUFC_DIR=%s" % depsdict['UFC']) self.cfg.update('configopts', "-DARMADILLO_DIR:PATH=%s " % depsdict['Armadillo']) # specify Python paths python_short_ver = ".".join( get_software_version('Python').split(".")[0:2]) self.cfg.update( 'configopts', " -DPYTHON_INCLUDE_PATH=%s/include/python%s" % (depsdict['Python'], python_short_ver)) self.cfg.update( 'configopts', " -DPYTHON_LIBRARY=%s/lib/libpython%s.so" % (depsdict['Python'], python_short_ver)) # SuiteSparse config params suitesparse = depsdict['SuiteSparse'] umfpack_params = [ ' -DUMFPACK_DIR="%(sp)s/UMFPACK"', '-DUMFPACK_INCLUDE_DIRS="%(sp)s/UMFPACK/include;%(sp)s/UFconfig"', '-DAMD_DIR="%(sp)s/UMFPACK"', '-DCHOLMOD_DIR="%(sp)s/CHOLMOD"', '-DCHOLMOD_INCLUDE_DIRS="%(sp)s/CHOLMOD/include;%(sp)s/UFconfig"', '-DUFCONFIG_DIR="%(sp)s/UFconfig"', '-DCAMD_LIBRARY:PATH="%(sp)s/CAMD/lib/libcamd.a"', '-DCCOLAMD_LIBRARY:PATH="%(sp)s/CCOLAMD/lib/libccolamd.a"', '-DCOLAMD_LIBRARY:PATH="%(sp)s/COLAMD/lib/libcolamd.a"' ] self.cfg.update('configopts', ' '.join(umfpack_params) % {'sp': suitesparse}) # ParMETIS and SCOTCH self.cfg.update('configopts', '-DPARMETIS_DIR="%s"' % depsdict['ParMETIS']) self.cfg.update( 'configopts', '-DSCOTCH_DIR="%s" -DSCOTCH_DEBUG:BOOL=ON' % depsdict['SCOTCH']) # BLACS and LAPACK self.cfg.update('configopts', '-DBLAS_LIBRARIES:PATH="%s"' % os.getenv('LIBBLAS')) self.cfg.update( 'configopts', '-DLAPACK_LIBRARIES:PATH="%s"' % os.getenv('LIBLAPACK')) # CGAL self.cfg.update('configopts', '-DCGAL_DIR:PATH="%s"' % depsdict['CGAL']) # PETSc # need to specify PETSC_ARCH explicitely (env var alone is not sufficient) for env_var in ["PETSC_DIR", "PETSC_ARCH"]: val = os.getenv(env_var) if val: self.cfg.update('configopts', '-D%s=%s' % (env_var, val)) # MTL4 self.cfg.update('configopts', '-DMTL4_DIR:PATH="%s"' % depsdict['MTL4']) # configure out = super(EB_DOLFIN, self).configure_step() # make sure that all optional packages are found not_found_re = re.compile( "The following optional packages could not be found") if not_found_re.search(out): raise EasyBuildError( "Optional packages could not be found, this should not happen..." ) # enable verbose build, so we have enough information if something goes wrong self.cfg.update('buildopts', "VERBOSE=1") def make_module_extra(self): """Set extra environment variables for DOLFIN.""" txt = super(EB_DOLFIN, self).make_module_extra() # Dolfin needs to find Boost txt += self.module_generator.set_environment('BOOST_DIR', self.boost_dir) envvars = ['I_MPI_CXX', 'I_MPI_CC'] for envvar in envvars: envar_val = os.getenv(envvar) # if environment variable is set, also set it in module if envar_val: txt += self.module_generator.set_environment(envvar, envar_val) return txt def sanity_check_step(self): """Custom sanity check for DOLFIN.""" # custom sanity check paths custom_paths = { 'files': [ 'bin/dolfin-%s' % x for x in ['version', 'convert', 'order', 'plot'] ] + ['include/dolfin.h'], 'dirs': ['%s/dolfin' % self.pylibdir] } # custom sanity check commands # set cache/error dirs for Instant tmpdir = tempfile.mkdtemp() instant_cache_dir = os.path.join(tmpdir, '.instant', 'cache') instant_error_dir = os.path.join(tmpdir, '.instant', 'error') try: os.makedirs(instant_cache_dir) os.makedirs(instant_error_dir) except OSError, err: raise EasyBuildError( "Failed to create Instant cache/error dirs: %s", err) # keep track of $LDFLAGS, so we can restore them for the sanity check commands # this is required to make sure that linking of libraries (OpenBLAS, etc.) works as expected ldflags = os.getenv('LDFLAGS') # we need to explicitely set the following environment variables as a part of the sanity check command, # because the environment is reset and only the environment variables set by the DOLFIN module are there env_vars = [ ('LDFLAGS', ldflags), ('INSTANT_CACHE_DIR', instant_cache_dir), ('INSTANT_ERROR_DIR', instant_error_dir), ] env_var_cmds = ' && '.join( ['export %s="%s"' % (var, val) for (var, val) in env_vars]) pref = os.path.join('share', 'dolfin', 'demo') # test command templates cmd_template_python = " && ".join([ env_var_cmds, "cd %(dir)s", "python demo_%(name)s.py", "cd -", ]) cmd_template_cpp = " && ".join([ env_var_cmds, "cd %(dir)s", "cmake . %s" % self.saved_configopts, "make VERBOSE=1", "./demo_%(name)s", "cd -", ]) # list based on demos available for DOLFIN v1.0.0 pde_demos = [ 'biharmonic', 'cahn-hilliard', 'hyperelasticity', 'mixed-poisson', 'navier-stokes', 'poisson', 'stokes-iterative' ] demos = [os.path.join('la', 'eigenvalue') ] + [os.path.join('pde', x) for x in pde_demos] # construct commands cmds = [ tmpl % { 'dir': os.path.join(pref, d, subdir), 'name': os.path.basename(d), } for d in demos for (tmpl, subdir) in [(cmd_template_cpp, 'cpp')] ] # exclude Python tests for now, because they 'hang' sometimes (unclear why) # they can be reinstated once run_cmd (or its equivalent) has support for timeouts # see https://github.com/hpcugent/easybuild-framework/issues/581 #for (tmpl, subdir) in [(cmd_template_python, 'python'), (cmd_template_cpp, 'cpp')]] # subdomains-poisson has no C++ get_version, only Python # Python tests excluded, see above #name = 'subdomains-poisson' #path = os.path.join(pref, 'pde', name, 'python') #cmds += [cmd_template_python % {'dir': path, 'name': name}] # supply empty argument to each command custom_commands = [(cmd, "") for cmd in cmds] super(EB_DOLFIN, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands) # clean up temporary dir try: rmtree2(tmpdir) except OSError, err: raise EasyBuildError( "Failed to remove Instant cache/error dirs: %s", err)
class EB_imkl(IntelBase): """ Class that can be used to install mkl - tested with 10.2.1.017 -- will fail for all older versions (due to newer silent installer) """ @staticmethod def extra_options(): """Add easyconfig parameters custom to imkl (e.g. interfaces).""" extra_vars = { 'interfaces': [True, "Indicates whether interfaces should be built", CUSTOM], } return IntelBase.extra_options(extra_vars) def __init__(self, *args, **kwargs): super(EB_imkl, self).__init__(*args, **kwargs) # make sure $MKLROOT isn't set, it's known to cause problems with the installation self.cfg.update('unwanted_env_vars', ['MKLROOT']) self.cdftlibs = [] self.mpi_spec = None def prepare_step(self, *args, **kwargs): if LooseVersion(self.version) >= LooseVersion('2017.2.174'): kwargs['requires_runtime_license'] = False super(EB_imkl, self).prepare_step(*args, **kwargs) else: super(EB_imkl, self).prepare_step(*args, **kwargs) # build the mkl interfaces, if desired if self.cfg['interfaces']: self.cdftlibs = ['fftw2x_cdft'] if LooseVersion(self.version) >= LooseVersion('10.3'): self.cdftlibs.append('fftw3x_cdft') # check whether MPI_FAMILY constant is defined, so mpi_family() can be used if hasattr(self.toolchain, 'MPI_FAMILY') and self.toolchain.MPI_FAMILY is not None: mpi_spec_by_fam = { toolchain.MPICH: 'mpich2', # MPICH is MPICH v3.x, which is MPICH2 compatible toolchain.MPICH2: 'mpich2', toolchain.MVAPICH2: 'mpich2', toolchain.OPENMPI: 'openmpi', } mpi_fam = self.toolchain.mpi_family() self.mpi_spec = mpi_spec_by_fam.get(mpi_fam) debugstr = "MPI toolchain component" else: # can't use toolchain.mpi_family, because of dummy toolchain if get_software_root('MPICH2') or get_software_root( 'MVAPICH2'): self.mpi_spec = 'mpich2' elif get_software_root('OpenMPI'): self.mpi_spec = 'openmpi' elif not get_software_root('impi'): # no compatible MPI found: do not build cdft self.cdftlibs = [] debugstr = "loaded MPI module" if self.mpi_spec: self.log.debug("Determined MPI specification based on %s: %s", debugstr, self.mpi_spec) else: self.log.debug( "No MPI or no compatible MPI found: do not build CDFT") def install_step(self): """ Actual installation - create silent cfg file - execute command """ silent_cfg_names_map = None silent_cfg_extras = None if LooseVersion(self.version) < LooseVersion('11.1'): # since imkl v11.1, silent.cfg has been slightly changed to be 'more standard' silent_cfg_names_map = { 'activation_name': ACTIVATION_NAME_2012, 'license_file_name': LICENSE_FILE_NAME_2012, } if LooseVersion(self.version) >= LooseVersion( '11.1') and self.install_components is None: silent_cfg_extras = { 'COMPONENTS': 'ALL', } super(EB_imkl, self).install_step(silent_cfg_names_map=silent_cfg_names_map, silent_cfg_extras=silent_cfg_extras) def make_module_req_guess(self): """ A dictionary of possible directories to look for """ if LooseVersion(self.version) >= LooseVersion('10.3'): if self.cfg['m32']: raise EasyBuildError( "32-bit not supported yet for IMKL v%s (>= 10.3)", self.version) else: retdict = { 'PATH': [ 'bin', 'mkl/bin', 'mkl/bin/intel64', 'composerxe-2011/bin' ], 'LD_LIBRARY_PATH': ['lib/intel64', 'mkl/lib/intel64'], 'LIBRARY_PATH': ['lib/intel64', 'mkl/lib/intel64'], 'MANPATH': ['man', 'man/en_US'], 'CPATH': ['mkl/include', 'mkl/include/fftw'], } if LooseVersion(self.version) >= LooseVersion('11.0'): if LooseVersion(self.version) >= LooseVersion('11.3'): retdict['MIC_LD_LIBRARY_PATH'] = [ 'lib/intel64_lin_mic', 'mkl/lib/mic' ] elif LooseVersion(self.version) >= LooseVersion('11.1'): retdict['MIC_LD_LIBRARY_PATH'] = [ 'lib/mic', 'mkl/lib/mic' ] else: retdict['MIC_LD_LIBRARY_PATH'] = [ 'compiler/lib/mic', 'mkl/lib/mic' ] return retdict else: if self.cfg['m32']: return { 'PATH': ['bin', 'bin/ia32', 'tbb/bin/ia32'], 'LD_LIBRARY_PATH': ['lib', 'lib/32'], 'LIBRARY_PATH': ['lib', 'lib/32'], 'MANPATH': ['man', 'share/man', 'man/en_US'], 'CPATH': ['include'], } else: return { 'PATH': ['bin', 'bin/intel64', 'tbb/bin/em64t'], 'LD_LIBRARY_PATH': ['lib', 'lib/em64t'], 'LIBRARY_PATH': ['lib', 'lib/em64t'], 'MANPATH': ['man', 'share/man', 'man/en_US'], 'CPATH': ['include'], } def make_module_extra(self): """Overwritten from Application to add extra txt""" txt = super(EB_imkl, self).make_module_extra() txt += self.module_generator.set_environment( 'MKLROOT', os.path.join(self.installdir, 'mkl')) return txt def post_install_step(self): """ Install group libraries and interfaces (if desired). """ super(EB_imkl, self).post_install_step() shlib_ext = get_shared_lib_ext() # reload the dependencies self.load_dependency_modules() if self.cfg['m32']: extra = { 'libmkl.%s' % shlib_ext: 'GROUP (-lmkl_intel -lmkl_intel_thread -lmkl_core)', 'libmkl_em64t.a': 'GROUP (libmkl_intel.a libmkl_intel_thread.a libmkl_core.a)', 'libmkl_solver.a': 'GROUP (libmkl_solver.a)', 'libmkl_scalapack.a': 'GROUP (libmkl_scalapack_core.a)', 'libmkl_lapack.a': 'GROUP (libmkl_intel.a libmkl_intel_thread.a libmkl_core.a)', 'libmkl_cdft.a': 'GROUP (libmkl_cdft_core.a)' } else: extra = { 'libmkl.%s' % shlib_ext: 'GROUP (-lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core)', 'libmkl_em64t.a': 'GROUP (libmkl_intel_lp64.a libmkl_intel_thread.a libmkl_core.a)', 'libmkl_solver.a': 'GROUP (libmkl_solver_lp64.a)', 'libmkl_scalapack.a': 'GROUP (libmkl_scalapack_lp64.a)', 'libmkl_lapack.a': 'GROUP (libmkl_intel_lp64.a libmkl_intel_thread.a libmkl_core.a)', 'libmkl_cdft.a': 'GROUP (libmkl_cdft_core.a)' } if LooseVersion(self.version) >= LooseVersion('10.3'): libsubdir = os.path.join('mkl', 'lib', 'intel64') else: if self.cfg['m32']: libsubdir = os.path.join('lib', '32') else: libsubdir = os.path.join('lib', 'em64t') for fil, txt in extra.items(): dest = os.path.join(self.installdir, libsubdir, fil) if not os.path.exists(dest): try: f = open(dest, 'w') f.write(txt) f.close() self.log.info("File %s written" % dest) except IOError, err: raise EasyBuildError("Can't write file %s: %s", dest, err) # build the mkl interfaces, if desired if self.cfg['interfaces']: if LooseVersion(self.version) >= LooseVersion('10.3'): intsubdir = os.path.join('mkl', 'interfaces') inttarget = 'libintel64' else: intsubdir = 'interfaces' if self.cfg['m32']: inttarget = 'lib32' else: inttarget = 'libem64t' cmd = "make -f makefile %s" % inttarget # blas95 and lapack95 need more work, ignore for now # blas95 and lapack also need include/.mod to be processed fftw2libs = ['fftw2xc', 'fftw2xf'] fftw3libs = ['fftw3xc', 'fftw3xf'] interfacedir = os.path.join(self.installdir, intsubdir) try: os.chdir(interfacedir) self.log.info("Changed to interfaces directory %s" % interfacedir) except OSError, err: raise EasyBuildError("Can't change to interfaces directory %s", interfacedir) compopt = None # determine whether we're using a non-Intel GCC-based or PGI-based toolchain # can't use toolchain.comp_family, because of dummy toolchain used when installing imkl if get_software_root('icc') is None: # check for PGI first, since there's a GCC underneath PGI too... if get_software_root('PGI'): compopt = 'compiler=pgi' elif get_software_root('GCC'): compopt = 'compiler=gnu' else: raise EasyBuildError( "Not using Intel/GCC/PGI compilers, don't know how to build wrapper libs" ) else: compopt = 'compiler=intel' # patch makefiles for cdft wrappers when PGI is used as compiler if get_software_root('PGI'): regex_subs = [ # pgi should be considered as a valid compiler ("intel gnu", "intel gnu pgi"), # transform 'gnu' case to 'pgi' case (r"ifeq \(\$\(compiler\),gnu\)", "ifeq ($(compiler),pgi)"), ('=gcc', '=pgcc'), # correct flag to use C99 standard ('-std=c99', '-c99'), # -Wall and -Werror are not valid options for pgcc, no close equivalent ('-Wall', ''), ('-Werror', ''), ] for lib in self.cdftlibs: apply_regex_substitutions( os.path.join(interfacedir, lib, 'makefile'), regex_subs) for lib in fftw2libs + fftw3libs + self.cdftlibs: buildopts = [compopt] if lib in fftw3libs: buildopts.append('install_to=$INSTALL_DIR') elif lib in self.cdftlibs: if self.mpi_spec is not None: buildopts.append('mpi=%s' % self.mpi_spec) precflags = [''] if lib.startswith('fftw2x') and not self.cfg['m32']: # build both single and double precision variants precflags = [ 'PRECISION=MKL_DOUBLE', 'PRECISION=MKL_SINGLE' ] intflags = [''] if lib in self.cdftlibs and not self.cfg['m32']: # build both 32-bit and 64-bit interfaces intflags = ['interface=lp64', 'interface=ilp64'] allopts = [ list(opts) for opts in itertools.product(intflags, precflags) ] for flags, extraopts in itertools.product(['', '-fPIC'], allopts): tup = (lib, flags, buildopts, extraopts) self.log.debug( "Building lib %s with: flags %s, buildopts %s, extraopts %s" % tup) tmpbuild = tempfile.mkdtemp(dir=self.builddir) self.log.debug("Created temporary directory %s" % tmpbuild) # always set INSTALL_DIR, SPEC_OPT, COPTS and CFLAGS # fftw2x(c|f): use $INSTALL_DIR, $CFLAGS and $COPTS # fftw3x(c|f): use $CFLAGS # fftw*cdft: use $INSTALL_DIR and $SPEC_OPT env.setvar('INSTALL_DIR', tmpbuild) env.setvar('SPEC_OPT', flags) env.setvar('COPTS', flags) env.setvar('CFLAGS', flags) try: intdir = os.path.join(interfacedir, lib) os.chdir(intdir) self.log.info("Changed to interface %s directory %s" % (lib, intdir)) except OSError, err: raise EasyBuildError( "Can't change to interface %s directory %s: %s", lib, intdir, err) fullcmd = "%s %s" % (cmd, ' '.join(buildopts + extraopts)) res = run_cmd(fullcmd, log_all=True, simple=True) if not res: raise EasyBuildError( "Building %s (flags: %s, fullcmd: %s) failed", lib, flags, fullcmd) for fn in os.listdir(tmpbuild): src = os.path.join(tmpbuild, fn) if flags == '-fPIC': # add _pic to filename ff = fn.split('.') fn = '.'.join(ff[:-1]) + '_pic.' + ff[-1] dest = os.path.join(self.installdir, libsubdir, fn) try: if os.path.isfile(src): shutil.move(src, dest) self.log.info("Moved %s to %s" % (src, dest)) except OSError, err: raise EasyBuildError("Failed to move %s to %s: %s", src, dest, err) rmtree2(tmpbuild)
class EB_SciPy_minus_Stack(EB_Python): """Support for building/installing SciPy-Stack""" def install_step(self): """Extend make install to make sure that the 'python' command is present.""" super(EB_Python, self).install_step() python_binary_path = os.path.join(self.installdir, 'bin', 'python') if not os.path.isfile(python_binary_path): if os.path.isfile(python_binary_path + '2'): pyver = '2' elif os.path.isfile(python_binary_path + '3'): pyver = '3' else: raise EasyBuildError("Can't find a python binary in %s", os.path.join(self.installdir, 'bin')) symlink(python_binary_path + pyver, python_binary_path) def sanity_check_step(self): """Custom sanity check for SciPy-Stack.""" pyver = 'python' + '.'.join(self.version.split('.')[:2]) shlib_ext = get_shared_lib_ext() try: fake_mod_data = self.load_fake_module() except EasyBuildError, err: raise EasyBuildError("Loading fake module failed: %s", err) abiflags = '' if LooseVersion(self.version) >= LooseVersion("3"): run_cmd("which python", log_all=True, simple=False) cmd = 'python -c "import sysconfig; print(sysconfig.get_config_var(\'abiflags\'));"' (abiflags, _) = run_cmd(cmd, log_all=True, simple=False) if not abiflags: raise EasyBuildError("Failed to determine abiflags: %s", abiflags) else: abiflags = abiflags.strip() custom_paths = { 'files': [ os.path.join('bin', pyver), os.path.join('lib', 'lib' + pyver + abiflags + '.' + shlib_ext) ], 'dirs': [ os.path.join('include', pyver + abiflags), os.path.join('lib', pyver) ], } # cleanup self.clean_up_fake_module(fake_mod_data) custom_commands = [ "python --version", "python -c 'import _ctypes'", # make sure that foreign function interface (libffi) works "python -c 'import _ssl'", # make sure SSL support is enabled one way or another "python -c 'import readline'", # make sure readline support was built correctly ] super(EB_Python, self).sanity_check_step(custom_paths=custom_paths, custom_commands=custom_commands)
def configure_step(self): """Set some extra environment variables before configuring.""" # enable verbose output if desired if self.cfg['verbose']: for x in ["CONFIGURE", "MAKEFILE"]: self.cfg.update('configopts', "-DTrilinos_VERBOSE_%s:BOOL=ON" % x) # compiler flags cflags = [os.getenv('CFLAGS')] cxxflags = [os.getenv('CXXFLAGS')] fflags = [os.getenv('FFLAGS')] ignore_cxx_seek_mpis = [toolchain.INTELMPI, toolchain.MPICH, toolchain.MPICH2, toolchain.MVAPICH2] # @UndefinedVariable ignore_cxx_seek_flag = "-DMPICH_IGNORE_CXX_SEEK" if self.toolchain.mpi_family() in ignore_cxx_seek_mpis: cflags.append(ignore_cxx_seek_flag) cxxflags.append(ignore_cxx_seek_flag) fflags.append(ignore_cxx_seek_flag) self.cfg.update('configopts', '-DCMAKE_C_FLAGS="%s"' % ' '.join(cflags)) self.cfg.update('configopts', '-DCMAKE_CXX_FLAGS="%s"' % ' '.join(cxxflags)) self.cfg.update('configopts', '-DCMAKE_Fortran_FLAGS="%s"' % ' '.join(fflags)) # Make sure Tpetra/Kokkos Serial mode is enabled regardless of OpenMP self.cfg.update('configopts', "-DKokkos_ENABLE_Serial:BOOL=ON") self.cfg.update('configopts', "-DTpetra_INST_SERIAL:BOOL=ON") # OpenMP if self.cfg['openmp']: self.cfg.update('configopts', "-DTrilinos_ENABLE_OpenMP:BOOL=ON") self.cfg.update('configopts', "-DKokkos_ENABLE_OpenMP:BOOL=ON") # MPI if self.toolchain.options.get('usempi', None): self.cfg.update('configopts', "-DTPL_ENABLE_MPI:BOOL=ON") # enable full testing self.cfg.update('configopts', "-DTrilinos_ENABLE_TESTS:BOOL=ON") self.cfg.update('configopts', "-DTrilinos_ENABLE_ALL_FORWARD_DEP_PACKAGES:BOOL=ON") lib_re = re.compile("^lib(.*).a$") # BLAS, LAPACK for dep in ["BLAS", "LAPACK"]: self.cfg.update('configopts', '-DTPL_ENABLE_%s:BOOL=ON' % dep) libdirs = os.getenv('%s_LIB_DIR' % dep) if self.toolchain.comp_family() == toolchain.GCC: # @UndefinedVariable libdirs += ";%s/lib64" % get_software_root('GCC') self.cfg.update('configopts', '-D%s_LIBRARY_DIRS="%s"' % (dep, libdirs)) if self.cfg['openmp']: libs = os.getenv('%s_MT_STATIC_LIBS' % dep).split(',') else: libs = os.getenv('%s_STATIC_LIBS' % dep).split(',') lib_names = ';'.join([lib_re.search(x).group(1) for x in libs]) if self.toolchain.comp_family() == toolchain.GCC: # @UndefinedVariable # explicitely specify static lib! lib_names += ";libgfortran.a" self.cfg.update('configopts', '-D%s_LIBRARY_NAMES="%s"' % (dep, lib_names)) # MKL if get_software_root('imkl') and LooseVersion(self.version) >= LooseVersion('12.12'): self.cfg.update('configopts', "-DTPL_ENABLE_MKL:BOOL=ON") self.cfg.update('configopts', '-DMKL_LIBRARY_DIRS:PATH="%s/lib/intel64"' % os.getenv('MKLROOT')) self.cfg.update('configopts', '-DMKL_INCLUDE_DIRS:PATH="%s/include"' % os.getenv('MKLROOT')) # UMFPACK is part of SuiteSparse suitesparse = get_software_root('SuiteSparse') if suitesparse: self.cfg.update('configopts', "-DTPL_ENABLE_UMFPACK:BOOL=ON") self.cfg.update('configopts', "-DTPL_ENABLE_Cholmod:BOOL=ON") incdirs, libdirs, libnames = [], [], [] for lib in ["UMFPACK", "CHOLMOD", "COLAMD", "AMD", "CCOLAMD", "CAMD"]: incdirs.append(os.path.join(suitesparse, lib, "Include")) libdirs.append(os.path.join(suitesparse, lib, "Lib")) libnames.append(lib.lower()) # add SuiteSparse config lib, it is in recent versions of suitesparse libdirs.append(os.path.join(suitesparse, 'SuiteSparse_config')) libnames.append('suitesparseconfig') # because of "SuiteSparse_config.c:function SuiteSparse_tic: error: undefined reference to 'clock_gettime'" libnames.append('rt') # required to resolve METIS symbols in SuiteSparse's libcholmod.a # doesn't need to be full location, probably because it can be found via $LIBRARY_PATH # not easy to know whether it should come from METIS or ParMETIS... # see https://answers.launchpad.net/dorsal/+question/223167 libnames.append('libmetis.a') self.cfg.update('configopts', '-DUMFPACK_INCLUDE_DIRS:PATH="%s"' % ';'.join(incdirs)) self.cfg.update('configopts', '-DUMFPACK_LIBRARY_DIRS:PATH="%s"' % ';'.join(libdirs)) self.cfg.update('configopts', '-DUMFPACK_LIBRARY_NAMES:STRING="%s"' % ';'.join(libnames)) self.cfg.update('configopts', '-DCholmod_INCLUDE_DIRS:PATH="%s"' % ';'.join(incdirs)) self.cfg.update('configopts', '-DCholmod_LIBRARY_DIRS:PATH="%s"' % ';'.join(libdirs)) self.cfg.update('configopts', '-DCholmod_LIBRARY_NAMES:STRING="%s"' % ';'.join(libnames)) # BLACS if get_software_root('BLACS'): self.cfg.update('configopts', "-DTPL_ENABLE_BLACS:BOOL=ON") self.cfg.update('configopts', '-DBLACS_INCLUDE_DIRS:PATH="%s"' % os.getenv('BLACS_INC_DIR')) self.cfg.update('configopts', '-DBLACS_LIBRARY_DIRS:PATH="%s"' % os.getenv('BLACS_LIB_DIR')) blacs_lib_names = os.getenv('BLACS_STATIC_LIBS').split(',') blacs_lib_names = [lib_re.search(x).group(1) for x in blacs_lib_names] self.cfg.update('configopts', '-DBLACS_LIBRARY_NAMES:STRING="%s"' % (';'.join(blacs_lib_names))) # ScaLAPACK if get_software_root('ScaLAPACK'): self.cfg.update('configopts', "-DTPL_ENABLE_SCALAPACK:BOOL=ON") self.cfg.update('configopts', '-DSCALAPACK_INCLUDE_DIRS:PATH="%s"' % os.getenv('SCALAPACK_INC_DIR')) self.cfg.update('configopts', '-DSCALAPACK_LIBRARY_DIRS:PATH="%s;%s"' % (os.getenv('SCALAPACK_LIB_DIR'), os.getenv('BLACS_LIB_DIR'))) # PETSc petsc = get_software_root('PETSc') if petsc: self.cfg.update('configopts', "-DTPL_ENABLE_PETSC:BOOL=ON") incdirs = [os.path.join(petsc, "include")] self.cfg.update('configopts', '-DPETSC_INCLUDE_DIRS:PATH="%s"' % ';'.join(incdirs)) petsc_libdirs = [ os.path.join(petsc, "lib"), os.path.join(suitesparse, "UMFPACK", "Lib"), os.path.join(suitesparse, "CHOLMOD", "Lib"), os.path.join(suitesparse, "COLAMD", "Lib"), os.path.join(suitesparse, "AMD", "Lib"), os.getenv('FFTW_LIB_DIR'), os.path.join(get_software_root('ParMETIS'), "Lib") ] self.cfg.update('configopts', '-DPETSC_LIBRARY_DIRS:PATH="%s"' % ';'.join(petsc_libdirs)) petsc_libnames = ["petsc", "umfpack", "cholmod", "colamd", "amd", "parmetis", "metis"] petsc_libnames += [lib_re.search(x).group(1) for x in os.getenv('FFTW_STATIC_LIBS').split(',')] self.cfg.update('configopts', '-DPETSC_LIBRARY_NAMES:STRING="%s"' % ';'.join(petsc_libnames)) # other Third-Party Libraries (TPLs) deps = self.cfg.dependencies() builddeps = [d['name'] for d in self.cfg.builddependencies()] + ["SuiteSparse"] deps = [dep['name'] for dep in deps if not dep['name'] in builddeps] for dep in deps: deproot = get_software_root(dep) if deproot: depmap = { 'SCOTCH': 'Scotch', } dep = depmap.get(dep, dep) self.cfg.update('configopts', "-DTPL_ENABLE_%s:BOOL=ON" % dep) incdir = os.path.join(deproot, "include") self.cfg.update('configopts', '-D%s_INCLUDE_DIRS:PATH="%s"' % (dep, incdir)) libdir = os.path.join(deproot, "lib") self.cfg.update('configopts', '-D%s_LIBRARY_DIRS:PATH="%s"' % (dep, libdir)) # extensions_step if self.cfg['all_exts']: self.cfg.update('configopts', "-DTrilinos_ENABLE_ALL_PACKAGES:BOOL=ON") else: for ext in self.cfg['exts_list']: self.cfg.update('configopts', "-DTrilinos_ENABLE_%s=ON" % ext) # packages to skip skip_exts = self.cfg['skip_exts'] if skip_exts: for ext in skip_exts: self.cfg.update('configopts', "-DTrilinos_ENABLE_%s:BOOL=OFF" % ext) # building in source dir not supported # + if the build directory is a long path, problems like "Argument list too long" may occur # cfr. https://github.com/trilinos/Trilinos/issues/2434 # so, try to create build directory with shorter path length to build in salt = ''.join(random.choice(ascii_letters) for _ in range(5)) self.short_start_dir = os.path.join(build_path(), self.name + '-' + salt) if os.path.exists(self.short_start_dir): raise EasyBuildError("Short start directory %s for Trilinos already exists?!", self.short_start_dir) self.log.info("Length of path to original start directory: %s", len(self.start_dir)) self.log.info("Short start directory: %s (length: %d)", self.short_start_dir, len(self.short_start_dir)) mkdir(self.short_start_dir) short_src_dir = os.path.join(self.short_start_dir, 'src') symlink(self.start_dir, short_src_dir) short_build_dir = os.path.join(self.short_start_dir, 'obj') obj_dir = os.path.join(self.builddir, 'obj') mkdir(obj_dir) symlink(obj_dir, short_build_dir) # configure using cmake super(EB_Trilinos, self).configure_step(srcdir=short_src_dir, builddir=short_build_dir)
def sanity_check_step(self): """Custom sanity check paths for Intel MKL.""" shlib_ext = get_shared_lib_ext() mklfiles = None mkldirs = None ver = LooseVersion(self.version) libs = [ 'libmkl_core.%s' % shlib_ext, 'libmkl_gnu_thread.%s' % shlib_ext, 'libmkl_intel_thread.%s' % shlib_ext, 'libmkl_sequential.%s' % shlib_ext ] extralibs = [ 'libmkl_blacs_intelmpi_%(suff)s.' + shlib_ext, 'libmkl_scalapack_%(suff)s.' + shlib_ext ] if self.cfg['interfaces']: compsuff = '_intel' if get_software_root('icc') is None: # check for PGI first, since there's a GCC underneath PGI too... if get_software_root('PGI'): compsuff = '_pgi' elif get_software_root('GCC'): compsuff = '_gnu' else: raise EasyBuildError( "Not using Intel/GCC/PGI, don't know compiler suffix for FFTW libraries." ) precs = ['_double', '_single'] if ver < LooseVersion('11'): # no precision suffix in libfftw2 libs before imkl v11 precs = [''] fftw_vers = [ '2x%s%s' % (x, prec) for x in ['c', 'f'] for prec in precs ] + ['3xc', '3xf'] pics = ['', '_pic'] libs += [ 'libfftw%s%s%s.a' % (fftwver, compsuff, pic) for fftwver in fftw_vers for pic in pics ] if self.cdftlibs: fftw_cdft_vers = ['2x_cdft_DOUBLE'] if not self.cfg['m32']: fftw_cdft_vers.append('2x_cdft_SINGLE') if ver >= LooseVersion('10.3'): fftw_cdft_vers.append('3x_cdft') if ver >= LooseVersion('11.0.2'): bits = ['_lp64'] if not self.cfg['m32']: bits.append('_ilp64') else: # no bits suffix in cdft libs before imkl v11.0.2 bits = [''] libs += [ 'libfftw%s%s%s.a' % x for x in itertools.product(fftw_cdft_vers, bits, pics) ] if ver >= LooseVersion('10.3'): if self.cfg['m32']: raise EasyBuildError( "Sanity check for 32-bit not implemented yet for IMKL v%s (>= 10.3)", self.version) else: mkldirs = ['bin', 'mkl/bin', 'mkl/lib/intel64', 'mkl/include'] if ver < LooseVersion('11.3'): mkldirs.append('mkl/bin/intel64') libs += [ lib % { 'suff': suff } for lib in extralibs for suff in ['lp64', 'ilp64'] ] mklfiles = ['mkl/lib/intel64/libmkl.%s' % shlib_ext, 'mkl/include/mkl.h'] + \ ['mkl/lib/intel64/%s' % lib for lib in libs] if ver >= LooseVersion('10.3.4') and ver < LooseVersion( '11.1'): mkldirs += ['compiler/lib/intel64'] else: if ver >= LooseVersion('2017.0.0'): mkldirs += ['lib/intel64_lin'] else: mkldirs += ['lib/intel64'] else: if self.cfg['m32']: mklfiles = ['lib/32/libmkl.%s' % shlib_ext, 'include/mkl.h'] + \ ['lib/32/%s' % lib for lib in libs] mkldirs = ['lib/32', 'include/32', 'interfaces'] else: libs += [ lib % { 'suff': suff } for lib in extralibs for suff in ['lp64', 'ilp64'] ] mklfiles = ['lib/em64t/libmkl.%s' % shlib_ext, 'include/mkl.h'] + \ ['lib/em64t/%s' % lib for lib in libs] mkldirs = ['lib/em64t', 'include/em64t', 'interfaces'] custom_paths = { 'files': mklfiles, 'dirs': mkldirs, } super(EB_imkl, self).sanity_check_step(custom_paths=custom_paths)
def fixup_hardcoded_paths(self): """Patch out hard coded paths to compiler and binutils tools""" binutils_root = get_software_root('binutils') gcc_root = get_software_root('GCCcore') or get_software_root('GCC') gcc_ver = get_software_version('GCCcore') or get_software_version( 'GCC') # only patch Bazel scripts if binutils & GCC installation prefix could be determined if not binutils_root or not gcc_root: self.log.info( "Not patching Bazel build scripts, installation prefix for binutils/GCC not found" ) return # replace hardcoded paths in (unix_)cc_configure.bzl # hard-coded paths in (unix_)cc_configure.bzl were removed in 0.19.0 if LooseVersion(self.version) < LooseVersion('0.19.0'): regex_subs = [ (r'-B/usr/bin', '-B%s' % os.path.join(binutils_root, 'bin')), (r'"/usr/bin', '"' + os.path.join(binutils_root, 'bin')), ] for conf_bzl in ['cc_configure.bzl', 'unix_cc_configure.bzl']: filepath = os.path.join('tools', 'cpp', conf_bzl) if os.path.exists(filepath): apply_regex_substitutions(filepath, regex_subs) # replace hardcoded paths in CROSSTOOL # CROSSTOOL script is no longer there in Bazel 0.24.0 if LooseVersion(self.version) < LooseVersion('0.24.0'): res = glob.glob( os.path.join(gcc_root, 'lib', 'gcc', '*', gcc_ver, 'include')) if res and len(res) == 1: gcc_lib_inc = res[0] else: raise EasyBuildError( "Failed to pinpoint location of GCC include files: %s", res) gcc_lib_inc_bis = os.path.join(os.path.dirname(gcc_lib_inc), 'include-fixed') if not os.path.exists(gcc_lib_inc_bis): self.log.info( "Derived directory %s does not exist, falling back to %s", gcc_lib_inc_bis, gcc_lib_inc) gcc_lib_inc_bis = gcc_lib_inc gcc_cplusplus_inc = os.path.join(gcc_root, 'include', 'c++', gcc_ver) if not os.path.exists(gcc_cplusplus_inc): raise EasyBuildError("Derived directory %s does not exist", gcc_cplusplus_inc) regex_subs = [ (r'-B/usr/bin', '-B%s' % os.path.join(binutils_root, 'bin')), (r'(cxx_builtin_include_directory:.*)/usr/lib/gcc', r'\1%s' % gcc_lib_inc), (r'(cxx_builtin_include_directory:.*)/usr/local/include', r'\1%s' % gcc_lib_inc_bis), (r'(cxx_builtin_include_directory:.*)/usr/include', r'\1%s' % gcc_cplusplus_inc), ] for tool in ['ar', 'cpp', 'dwp', 'gcc', 'ld']: path = which(tool) if path: regex_subs.append((os.path.join('/usr', 'bin', tool), path)) else: raise EasyBuildError("Failed to determine path to '%s'", tool) apply_regex_substitutions( os.path.join('tools', 'cpp', 'CROSSTOOL'), regex_subs)
def configure_intel_based(self): """Configure for Intel based toolchains""" # based on guidelines available at # http://software.intel.com/en-us/articles/build-cp2k-using-intel-fortran-compiler-professional-edition/ intelurl = ''.join(["http://software.intel.com/en-us/articles/", "build-cp2k-using-intel-fortran-compiler-professional-edition/"]) options = self.configure_common() extrainc = '' if self.modincpath: extrainc = '-I%s' % self.modincpath options.update({ # -Vaxlib : older options 'FREE': '-fpp -free', # SAFE = -assume protect_parens -fp-model precise -ftz # causes problems, so don't use this 'SAFE': '-assume protect_parens -no-unroll-aggressive', 'INCFLAGS': '$(DFLAGS) -I$(INTEL_INC) -I$(INTEL_INCF) %s' % extrainc, 'LDFLAGS': '$(INCFLAGS) -i-static', 'OBJECTS_ARCHITECTURE': 'machine_intel.o', }) options['DFLAGS'] += ' -D__INTEL' optarch = '' if self.toolchain.options['optarch']: optarch = '-xHOST' options['FCFLAGSOPT'] += ' $(INCFLAGS) %s -heap-arrays 64' % optarch options['FCFLAGSOPT2'] += ' $(INCFLAGS) %s -heap-arrays 64' % optarch ifortver = LooseVersion(get_software_version('ifort')) failmsg = "CP2K won't build correctly with the Intel %%s compilers prior to %%s, see %s" % intelurl if ifortver >= LooseVersion("2011") and ifortver < LooseVersion("2012"): # don't allow using Intel compiler 2011 prior to release 8, because of known issue (see Intel URL) if ifortver >= LooseVersion("2011.8"): # add additional make instructions to Makefile self.make_instructions += "et_coupling.o: et_coupling.F\n\t$(FC) -c $(FCFLAGS2) $<\n" self.make_instructions += "qs_vxc_atom.o: qs_vxc_atom.F\n\t$(FC) -c $(FCFLAGS2) $<\n" else: raise EasyBuildError(failmsg, "v12", "v2011.8") elif ifortver >= LooseVersion("11"): if LooseVersion(get_software_version('ifort')) >= LooseVersion("11.1.072"): self.make_instructions += "qs_vxc_atom.o: qs_vxc_atom.F\n\t$(FC) -c $(FCFLAGS2) $<\n" else: raise EasyBuildError(failmsg, "v11", "v11.1.072") else: raise EasyBuildError("Intel compilers version %s not supported yet.", ifortver) return options
def configure_common(self): """Common configuration for all toolchains""" # openmp introduces 2 major differences # -automatic is default: -noautomatic -auto-scalar # some mem-bandwidth optimisation if self.cfg['type'] == 'psmp': self.openmp = self.toolchain.get_flag('openmp') # determine which opt flags to use if self.cfg['typeopt']: optflags = 'OPT' regflags = 'OPT2' else: optflags = 'NOOPT' regflags = 'NOOPT' # make sure a MPI-2 able MPI lib is used mpi2 = False if hasattr(self.toolchain, 'MPI_FAMILY') and self.toolchain.MPI_FAMILY is not None: known_mpi2_fams = [toolchain.MPICH, toolchain.MPICH2, toolchain.MVAPICH2, toolchain.OPENMPI, toolchain.INTELMPI] mpi_fam = self.toolchain.mpi_family() if mpi_fam in known_mpi2_fams: mpi2 = True self.log.debug("Determined MPI2 compatibility based on MPI toolchain component: %s" % mpi_fam) else: self.log.debug("Cannot determine MPI2 compatibility based on MPI toolchain component: %s" % mpi_fam) else: # can't use toolchain.mpi_family, because of dummy toolchain mpi2libs = ['impi', 'MVAPICH2', 'OpenMPI', 'MPICH2', 'MPICH'] for mpi2lib in mpi2libs: if get_software_root(mpi2lib): mpi2 = True self.log.debug("Determined MPI2 compatibility based on loaded MPI module: %s") else: self.log.debug("MPI-2 supporting MPI library %s not loaded.") if not mpi2: raise EasyBuildError("CP2K needs MPI-2, no known MPI-2 supporting library loaded?") options = { 'CC': os.getenv('MPICC'), 'CPP': '', 'FC': '%s %s' % (os.getenv('MPIF90'), self.openmp), 'LD': '%s %s' % (os.getenv('MPIF90'), self.openmp), 'AR': 'ar -r', 'CPPFLAGS': '', 'FPIC': self.fpic, 'DEBUG': self.debug, 'FCFLAGS': '$(FCFLAGS%s)' % optflags, 'FCFLAGS2': '$(FCFLAGS%s)' % regflags, 'CFLAGS': ' %s %s $(FPIC) $(DEBUG) %s ' % (os.getenv('CPPFLAGS'), os.getenv('LDFLAGS'), self.cfg['extracflags']), 'DFLAGS': ' -D__parallel -D__BLACS -D__SCALAPACK -D__FFTSG %s' % self.cfg['extradflags'], 'LIBS': os.getenv('LIBS', ''), 'FCFLAGSNOOPT': '$(DFLAGS) $(CFLAGS) -O0 $(FREE) $(FPIC) $(DEBUG)', 'FCFLAGSOPT': '-O2 $(FREE) $(SAFE) $(FPIC) $(DEBUG)', 'FCFLAGSOPT2': '-O1 $(FREE) $(SAFE) $(FPIC) $(DEBUG)' } libint = get_software_root('LibInt') if libint: options['DFLAGS'] += ' -D__LIBINT' libintcompiler = "%s %s" % (os.getenv('CC'), os.getenv('CFLAGS')) # Build libint-wrapper, if required libint_wrapper = '' # required for old versions of GCC if not self.compilerISO_C_BINDING: options['DFLAGS'] += ' -D__HAS_NO_ISO_C_BINDING' # determine path for libint_tools dir libinttools_paths = ['libint_tools', 'tools/hfx_tools/libint_tools'] libinttools_path = None for path in libinttools_paths: path = os.path.join(self.cfg['start_dir'], path) if os.path.isdir(path): libinttools_path = path os.chdir(libinttools_path) if not libinttools_path: raise EasyBuildError("No libinttools dir found") # build libint wrapper cmd = "%s -c libint_cpp_wrapper.cpp -I%s/include" % (libintcompiler, libint) if not run_cmd(cmd, log_all=True, simple=True): raise EasyBuildError("Building the libint wrapper failed") libint_wrapper = '%s/libint_cpp_wrapper.o' % libinttools_path # determine LibInt libraries based on major version number libint_maj_ver = get_software_version('LibInt').split('.')[0] if libint_maj_ver == '1': libint_libs = "$(LIBINTLIB)/libderiv.a $(LIBINTLIB)/libint.a $(LIBINTLIB)/libr12.a" elif libint_maj_ver == '2': libint_libs = "$(LIBINTLIB)/libint2.a" else: raise EasyBuildError("Don't know how to handle libint version %s", libint_maj_ver) self.log.info("Using LibInt version %s" % (libint_maj_ver)) options['LIBINTLIB'] = '%s/lib' % libint options['LIBS'] += ' %s -lstdc++ %s' % (libint_libs, libint_wrapper) else: # throw a warning, since CP2K without LibInt doesn't make much sense self.log.warning("LibInt module not loaded, so building without LibInt support") libxc = get_software_root('libxc') if libxc: cur_libxc_version = get_software_version('libxc') if LooseVersion(cur_libxc_version) < LooseVersion(LIBXC_MIN_VERSION): raise EasyBuildError("CP2K only works with libxc v%s (or later)", LIBXC_MIN_VERSION) options['DFLAGS'] += ' -D__LIBXC2' if LooseVersion(cur_libxc_version) >= LooseVersion('2.2'): options['LIBS'] += ' -L%s/lib -lxcf90 -lxc' % libxc else: options['LIBS'] += ' -L%s/lib -lxc' % libxc self.log.info("Using Libxc-%s" % cur_libxc_version) else: self.log.info("libxc module not loaded, so building without libxc support") return options
def configure_step(self): """Configure build - build Libint wrapper - generate Makefile """ known_types = ['popt', 'psmp'] if self.cfg['type'] not in known_types: raise EasyBuildError("Unknown build type specified: '%s', known types are %s", self.cfg['type'], known_types) # correct start dir, if needed # recent CP2K versions have a 'cp2k' dir in the unpacked 'cp2k' dir cp2k_path = os.path.join(self.cfg['start_dir'], 'cp2k') if os.path.exists(cp2k_path): self.cfg['start_dir'] = cp2k_path self.log.info("Corrected start_dir to %s" % self.cfg['start_dir']) # set compilers options according to toolchain config # full debug: -g -traceback -check all -fp-stack-check # -g links to mpi debug libs if self.toolchain.options['debug']: self.debug = '-g' self.log.info("Debug build") if self.toolchain.options['pic']: self.fpic = "-fPIC" self.log.info("Using fPIC") # report on extra flags being used if self.cfg['extracflags']: self.log.info("Using extra CFLAGS: %s" % self.cfg['extracflags']) if self.cfg['extradflags']: self.log.info("Using extra CFLAGS: %s" % self.cfg['extradflags']) # lib(x)smm support libsmm = get_software_root('libsmm') libxsmm = get_software_root('libxsmm') if libxsmm: self.cfg.update('extradflags', '-D__LIBXSMM') self.libsmm = '-lxsmm' self.log.debug('Using libxsmm %s' % libxsmm) elif libsmm: libsmms = glob.glob(os.path.join(libsmm, 'lib', 'libsmm_*nn.a')) dfs = [os.path.basename(os.path.splitext(x)[0]).replace('lib', '-D__HAS_') for x in libsmms] moredflags = ' ' + ' '.join(dfs) self.cfg.update('extradflags', moredflags) self.libsmm = ' '.join(libsmms) self.log.debug('Using libsmm %s (extradflags %s)' % (self.libsmm, moredflags)) # obtain list of modinc's to use if self.cfg["modinc"]: self.modincpath = self.prepmodinc() # set typearch self.typearch = "Linux-x86-64-%s" % self.toolchain.name # extra make instructions self.make_instructions = '' # "graphcon.o: graphcon.F\n\t$(FC) -c $(FCFLAGS2) $<\n" # compiler toolchain specific configuration comp_fam = self.toolchain.comp_family() if comp_fam == toolchain.INTELCOMP: options = self.configure_intel_based() elif comp_fam == toolchain.GCC: options = self.configure_GCC_based() else: raise EasyBuildError("Don't know how to tweak configuration for compiler family %s" % comp_fam) # BLAS/FFTW if get_software_root('IMKL'): options = self.configure_MKL(options) else: # BLAS if get_software_root('ACML'): options = self.configure_ACML(options) else: options = self.configure_BLAS_lib(options) # FFTW (no MKL involved) if 'fftw3' in os.getenv('LIBFFT', ''): options = self.configure_FFTW3(options) # LAPACK if os.getenv('LIBLAPACK_MT', None) is not None: options = self.configure_LAPACK(options) if os.getenv('LIBSCALAPACK', None) is not None: options = self.configure_ScaLAPACK(options) # PLUMED if self.cfg["plumed"]: if not get_software_root('PLUMED'): raise EasyBuildError("The PLUMED module needs to be loaded to build CP2K with PLUMED support") options['LIBS'] += ' -lplumed' options['DFLAGS'] += ' -D__PLUMED2' # CUDA cuda = get_software_root('CUDA') if cuda: options['DFLAGS'] += ' -D__ACC -D__DBCSR_ACC' options['LIBS'] += ' -lcudart -lcublas -lcufft -lrt' options['NVCC'] = ' nvcc' # avoid group nesting options['LIBS'] = options['LIBS'].replace('-Wl,--start-group', '').replace('-Wl,--end-group', '') options['LIBS'] = "-Wl,--start-group %s -Wl,--end-group" % options['LIBS'] # create arch file using options set archfile = os.path.join(self.cfg['start_dir'], 'arch', '%s.%s' % (self.typearch, self.cfg['type'])) try: txt = self._generate_makefile(options) f = open(archfile, 'w') f.write(txt) f.close() self.log.info("Content of makefile (%s):\n%s" % (archfile, txt)) except IOError, err: raise EasyBuildError("Writing makefile %s failed: %s", archfile, err)
raise EasyBuildError("F77 environment variable not set, can't continue.") # create modinc files for f in modfiles: if f77.endswith('ifort'): cmd = "%s -module %s -c %s" % (f77, modincpath, f) elif f77 in ['gfortran', 'mpif77']: cmd = "%s -J%s -c %s" % (f77, modincpath, f) else: raise EasyBuildError("prepmodinc: Unknown value specified for F77 (%s)", f77) run_cmd(cmd, log_all=True, simple=True) return modincpath else: raise EasyBuildError("Don't know how to prepare modinc, IMKL not found") def configure_common(self): """Common configuration for all toolchains""" # openmp introduces 2 major differences # -automatic is default: -noautomatic -auto-scalar # some mem-bandwidth optimisation if self.cfg['type'] == 'psmp': self.openmp = self.toolchain.get_flag('openmp') # determine which opt flags to use if self.cfg['typeopt']: optflags = 'OPT' regflags = 'OPT2' else: