Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
356 changes: 185 additions & 171 deletions easybuild/easyblocks/i/imkl.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,151 +278,157 @@ def post_install_step(self):
else:
libsubdir = os.path.join('lib', 'em64t')

libdir = os.path.join(self.installdir, libsubdir)
for fil, txt in extra.items():
dest = os.path.join(self.installdir, libsubdir, fil)
dest = os.path.join(libdir, fil)
if not os.path.exists(dest):
write_file(dest, txt)

# build the mkl interfaces, if desired
if self.cfg['interfaces']:
self.build_interfaces(os.path.join(self.installdir, libdir))

if loosever >= LooseVersion('10.3'):
intsubdir = os.path.join(self.mkl_basedir, '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)
change_dir(interfacedir)
self.log.info("Changed to interfaces directory %s", interfacedir)

compopt = None
# determine whether we're using a non-Intel GCC-based or PGI/NVHPC-based toolchain
# can't use toolchain.comp_family, because of system toolchain used when installing imkl
if get_software_root('icc') or get_software_root('intel-compilers'):
compopt = 'compiler=intel'
elif get_software_root('PGI'):
compopt = 'compiler=pgi'
elif get_software_root('NVHPC'):
compopt = 'compiler=nvhpc'
# GCC should be the last as the above compilers also have an underlying GCC
elif get_software_root('GCC'):
compopt = 'compiler=gnu'
else:
raise EasyBuildError("Not using Intel/GCC/PGI/NVHPC compilers, "
"don't know how to build wrapper libs")

# patch makefiles for cdft wrappers when PGI or NVHPC is used as compiler
if get_software_root('NVHPC'):
regex_subs = [
# nvhpc should be considered as a valid compiler
("intel gnu", "intel gnu nvhpc"),
# transform 'gnu' case to 'nvhpc' case
(r"ifeq \(\$\(compiler\),gnu\)", "ifeq ($(compiler),nvhpc)"),
('=gcc', '=nvc'),
]
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'),
]
if get_software_root('PGI') or get_software_root('NVHPC'):
regex_subs += [
# 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)

if get_software_root('NVHPC'):
regex_nvc_subs = [
('pgcc', 'nvc'),
('pgf95', 'nvfortran'),
('pgi', 'nvhpc'),
]
for liball in glob.glob(os.path.join(interfacedir, '*', 'makefile')):
apply_regex_substitutions(liball, regex_nvc_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)
def build_interfaces(self, libdir):
"""Build the mkl interfaces, if desired"""

loosever = LooseVersion(self.version)

if loosever >= LooseVersion('10.3'):
intsubdir = os.path.join(self.mkl_basedir, '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)
change_dir(interfacedir)
self.log.info("Changed to interfaces directory %s", interfacedir)

compopt = None
# determine whether we're using a non-Intel GCC-based or PGI/NVHPC-based toolchain
# can't use toolchain.comp_family, because of system toolchain used when installing imkl
if get_software_root('icc') or get_software_root('intel-compilers'):
compopt = 'compiler=intel'
elif get_software_root('PGI'):
compopt = 'compiler=pgi'
elif get_software_root('NVHPC'):
compopt = 'compiler=nvhpc'
# GCC should be the last as the above compilers also have an underlying GCC
elif get_software_root('GCC'):
compopt = 'compiler=gnu'
else:
raise EasyBuildError("Not using Intel/GCC/PGI/NVHPC compilers, "
"don't know how to build wrapper libs")

# patch makefiles for cdft wrappers when PGI or NVHPC is used as compiler
if get_software_root('NVHPC'):
regex_subs = [
# nvhpc should be considered as a valid compiler
("intel gnu", "intel gnu nvhpc"),
# transform 'gnu' case to 'nvhpc' case
(r"ifeq \(\$\(compiler\),gnu\)", "ifeq ($(compiler),nvhpc)"),
('=gcc', '=nvc'),
]
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'),
]
if get_software_root('PGI') or get_software_root('NVHPC'):
regex_subs += [
# 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)

if get_software_root('NVHPC'):
regex_nvc_subs = [
('pgcc', 'nvc'),
('pgf95', 'nvfortran'),
('pgi', 'nvhpc'),
]
for liball in glob.glob(os.path.join(interfacedir, '*', 'makefile')):
apply_regex_substitutions(liball, regex_nvc_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 as 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(libdir, fn)
try:
intdir = os.path.join(interfacedir, lib)
os.chdir(intdir)
self.log.info("Changed to interface %s directory %s" % (lib, intdir))
if os.path.isfile(src):
shutil.move(src, dest)
self.log.info("Moved %s to %s" % (src, dest))
except OSError as 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 as err:
raise EasyBuildError("Failed to move %s to %s: %s", src, dest, err)

remove_dir(tmpbuild)
raise EasyBuildError("Failed to move %s to %s: %s", src, dest, err)

remove_dir(tmpbuild)

def sanity_check_step(self):
"""Custom sanity check paths for Intel MKL."""
Expand All @@ -436,41 +442,7 @@ def sanity_check_step(self):
extralibs = ['libmkl_blacs_intelmpi_%(suff)s.' + shlib_ext, 'libmkl_scalapack_%(suff)s.' + shlib_ext]

if self.cfg['interfaces']:
if get_software_root('icc') or get_software_root('intel-compilers'):
compsuff = '_intel'
# check for PGI and NVHPC first, since there's a GCC underneath PGI and NVHPC too...
elif get_software_root('PGI'):
compsuff = '_pgi'
elif get_software_root('NVHPC'):
compsuff = '_nvhpc'
elif get_software_root('GCC'):
compsuff = '_gnu'
else:
raise EasyBuildError("Not using Intel/GCC/PGI/NVHPC, "
"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)]
libs += self.get_interface_libs()

if ver >= LooseVersion('10.3') and self.cfg['m32']:
raise EasyBuildError("Sanity check for 32-bit not implemented yet for IMKL v%s (>= 10.3)", self.version)
Expand Down Expand Up @@ -523,3 +495,45 @@ def sanity_check_step(self):
}

super(EB_imkl, self).sanity_check_step(custom_paths=custom_paths)

def get_interface_libs(self):
"""Returns list of library names produced by build_interface()"""

if get_software_root('icc') or get_software_root('intel-compilers'):
compsuff = '_intel'
# check for PGI and NVHPC first, since there's a GCC underneath PGI and NVHPC too...
elif get_software_root('PGI'):
compsuff = '_pgi'
elif get_software_root('NVHPC'):
compsuff = '_nvhpc'
elif get_software_root('GCC'):
compsuff = '_gnu'
else:
raise EasyBuildError("Not using Intel/GCC/PGI/NVHPC, "
"don't know compiler suffix for FFTW libraries.")

precs = ['_double', '_single']
ver = LooseVersion(self.version)
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)]

return libs
Loading