Skip to content
Snippets Groups Projects
Commit c2298dad authored by Lukáš Krupčík's avatar Lukáš Krupčík
Browse files

Merge branch 'it4i-salomon' into 'master'

It4i salomon

See merge request !1
parents a7328deb 189342f6
No related branches found
No related tags found
1 merge request!1It4i salomon
##
# Copyright 2013 Dmitri Gribenko
# Copyright 2013-2017 Ghent University
# Copyright 2017 IT4Innovations
#
# This file is triple-licensed under GPLv2 (see below), MIT, and
# BSD three-clause licenses.
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
Support for building and installing Clang, implemented as an easyblock.
@author: Dmitri Gribenko (National Technical University of Ukraine "KPI")
@author: Ward Poelmans (Ghent University)
@author: Josef Hrabal, Lukas Krupcik (IT4innovations, Czechia)
"""
import fileinput
import glob
import os
import re
import shutil
import sys
from distutils.version import LooseVersion
from easybuild.easyblocks.generic.cmakemake import CMakeMake
from easybuild.framework.easyconfig import CUSTOM
from easybuild.tools import run
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.filetools import mkdir
from easybuild.tools.modules import get_software_root
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_os_name, get_os_version, get_shared_lib_ext
# List of all possible build targets for Clang
CLANG_TARGETS = ["all", "AArch64", "ARM", "CppBackend", "Hexagon", "Mips",
"MBlaze", "MSP430", "NVPTX", "PowerPC", "R600", "Sparc",
"SystemZ", "X86", "XCore"]
class EB_Clang(CMakeMake):
"""Support for bootstrapping Clang."""
@staticmethod
def extra_options():
extra_vars = {
'assertions': [True, "Enable assertions. Helps to catch bugs in Clang.", CUSTOM],
'build_targets': [["X86"], "Build targets for LLVM. Possible values: " + ', '.join(CLANG_TARGETS), CUSTOM],
'bootstrap': [True, "Bootstrap Clang using GCC", CUSTOM],
'usepolly': [False, "Build Clang with polly", CUSTOM],
'static_analyzer': [True, "Install the static analyser of Clang", CUSTOM],
# The sanitizer tests often fail on HPC systems due to the 'weird' environment.
'skip_sanitizer_tests': [False, "Do not run the sanitizer tests", CUSTOM],
}
return CMakeMake.extra_options(extra_vars)
def __init__(self, *args, **kwargs):
"""Initialize custom class variables for Clang."""
super(EB_Clang, self).__init__(*args, **kwargs)
self.llvm_src_dir = None
self.llvm_obj_dir_stage1 = None
self.llvm_obj_dir_stage2 = None
self.llvm_obj_dir_stage3 = None
self.make_parallel_opts = ""
unknown_targets = [target for target in self.cfg['build_targets'] if target not in CLANG_TARGETS]
if unknown_targets:
raise EasyBuildError("Some of the chosen build targets (%s) are not in %s.",
', '.join(unknown_targets), ', '.join(CLANG_TARGETS))
if LooseVersion(self.version) < LooseVersion('3.4') and "R600" in self.cfg['build_targets']:
raise EasyBuildError("Build target R600 not supported in < Clang-3.4")
if LooseVersion(self.version) > LooseVersion('3.3') and "MBlaze" in self.cfg['build_targets']:
raise EasyBuildError("Build target MBlaze is not supported anymore in > Clang-3.3")
def check_readiness_step(self):
"""Fail early on RHEL 5.x and derivatives because of known bug in libc."""
super(EB_Clang, self).check_readiness_step()
# RHEL 5.x have a buggy libc. Building stage 2 will fail.
if get_os_name() in ['redhat', 'RHEL', 'centos', 'SL'] and get_os_version().startswith('5.'):
raise EasyBuildError("Can not build Clang on %s v5.x: libc is buggy, building stage 2 will fail. "
"See http://stackoverflow.com/questions/7276828/", get_os_name())
def extract_step(self):
"""
Prepare a combined LLVM source tree. The layout is:
llvm/ Unpack llvm-*.tar.gz here
projects/
compiler-rt/ Unpack compiler-rt-*.tar.gz here
openmp/ Unpack openmp-*.tar.xz here
libcxx/ Unpack libcxx-*.tar.xz here
libcxxabi/ Unpack libcxxapbi-*.tar.xz here
tools/
clang/ Unpack cfe-*.tar.gz here
tools/extra Unpack clang-*.tar.gz here
polly/ Unpack polly-*.tar.gz here
"""
# Extract everything into separate directories.
super(EB_Clang, self).extract_step()
# Find the full path to the directory that was unpacked from llvm-*.tar.gz.
for tmp in self.src:
if tmp['name'].startswith("llvm-"):
self.llvm_src_dir = tmp['finalpath']
break
if self.llvm_src_dir is None:
raise EasyBuildError("Could not determine LLVM source root (LLVM source was not unpacked?)")
src_dirs = {}
def find_source_dir(globpatterns, targetdir):
"""Search for directory with globpattern and rename it to targetdir"""
if not isinstance(globpatterns, list):
globpatterns = [globpatterns]
glob_src_dirs = [glob_dir for globpattern in globpatterns for glob_dir in glob.glob(globpattern)]
if len(glob_src_dirs) != 1:
raise EasyBuildError("Failed to find exactly one source directory for pattern %s: %s", globpatterns,
glob_src_dirs)
src_dirs[glob_src_dirs[0]] = targetdir
find_source_dir('compiler-rt-*', os.path.join(self.llvm_src_dir, 'projects', 'compiler-rt'))
if self.cfg["usepolly"]:
find_source_dir('polly-*', os.path.join(self.llvm_src_dir, 'tools', 'polly'))
find_source_dir('cfe-*', os.path.join(self.llvm_src_dir, 'tools', 'clang'))
find_source_dir('clang-*', os.path.join(self.llvm_src_dir, 'tools', 'clang', 'tools', 'extra'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libcxx-*', os.path.join(self.llvm_src_dir, 'projects', 'libcxx'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libcxxabi-*', os.path.join(self.llvm_src_dir, 'projects', 'libcxxabi'))
if LooseVersion(self.version) >= LooseVersion('3.8'):
find_source_dir('openmp-*', os.path.join(self.llvm_src_dir, 'projects', 'openmp'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('ldd-*', os.path.join(self.llvm_src_dir, 'tools', 'ldd'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('lddb-*', os.path.join(self.llvm_src_dir, 'tools', 'lddb'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libunwind-*', os.path.join(self.llvm_src_dir, 'tools', 'libunwind'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('test-*', os.path.join(self.llvm_src_dir, 'tools', 'testsuite'))
for src in self.src:
for (dirname, new_path) in src_dirs.items():
if src['name'].startswith(dirname):
old_path = os.path.join(src['finalpath'], dirname)
try:
shutil.move(old_path, new_path)
except IOError, err:
raise EasyBuildError("Failed to move %s to %s: %s", old_path, new_path, err)
src['finalpath'] = new_path
break
def configure_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).configure_step()
return
"""Run CMake for stage 1 Clang."""
self.llvm_obj_dir_stage1 = os.path.join(self.builddir, 'llvm.obj.1')
if self.cfg['bootstrap']:
self.llvm_obj_dir_stage2 = os.path.join(self.builddir, 'llvm.obj.2')
self.llvm_obj_dir_stage3 = os.path.join(self.builddir, 'llvm.obj.3')
if LooseVersion(self.version) >= LooseVersion('3.3'):
disable_san_tests = False
# all sanitizer tests will fail when there's a limit on the vmem
# this is ugly but I haven't found a cleaner way so far
(vmemlim, ec) = run_cmd("ulimit -v", regexp=False)
if not vmemlim.startswith("unlimited"):
disable_san_tests = True
self.log.warn("There is a virtual memory limit set of %s KB. The tests of the "
"sanitizers will be disabled as they need unlimited virtual "
"memory unless --strict=error is used." % vmemlim.strip())
# the same goes for unlimited stacksize
(stacklim, ec) = run_cmd("ulimit -s", regexp=False)
if stacklim.startswith("unlimited"):
disable_san_tests = True
self.log.warn("The stacksize limit is set to unlimited. This causes the ThreadSanitizer "
"to fail. The sanitizers tests will be disabled unless --strict=error is used.")
if (disable_san_tests or self.cfg['skip_sanitizer_tests']) and build_option('strict') != run.ERROR:
self.log.debug("Disabling the sanitizer tests")
self.disable_sanitizer_tests()
# Create and enter build directory.
mkdir(self.llvm_obj_dir_stage1)
os.chdir(self.llvm_obj_dir_stage1)
# GCC and Clang are installed in different prefixes and Clang will not
# find the GCC installation on its own.
# First try with GCCcore, as GCC built on top of GCCcore is just a wrapper for GCCcore and binutils,
# instead of a full-fledge compiler
gcc_prefix = get_software_root('GCCcore')
# If that doesn't work, try with GCC
if gcc_prefix is None:
gcc_prefix = get_software_root('GCC')
# If that doesn't work either, print error and exit
if gcc_prefix is None:
raise EasyBuildError("Can't find GCC or GCCcore to use")
self.cfg.update('configopts', "-DGCC_INSTALL_PREFIX='%s' " % gcc_prefix)
self.log.debug("Using %s as GCC_INSTALL_PREFIX", gcc_prefix)
self.cfg['configopts'] += "-DCMAKE_BUILD_TYPE=Release "
if self.cfg['assertions']:
self.cfg['configopts'] += "-DLLVM_ENABLE_ASSERTIONS=ON "
else:
self.cfg['configopts'] += "-DLLVM_ENABLE_ASSERTIONS=OFF "
self.cfg['configopts'] += '-DLLVM_TARGETS_TO_BUILD="%s" ' % ';'.join(self.cfg['build_targets'])
if self.cfg['parallel']:
self.make_parallel_opts = "-j %s" % self.cfg['parallel']
self.log.info("Configuring")
super(EB_Clang, self).configure_step(srcdir=self.llvm_src_dir)
def disable_sanitizer_tests(self):
"""Disable the tests of all the sanitizers by removing the test directories from the build system"""
if LooseVersion(self.version) < LooseVersion('3.6'):
# for Clang 3.5 and lower, the tests are scattered over several CMakeLists.
# We loop over them, and patch out the rule that adds the sanitizers tests to the testsuite
patchfiles = [
"lib/asan",
"lib/dfsan",
"lib/lsan",
"lib/msan",
"lib/tsan",
"lib/ubsan",
]
for patchfile in patchfiles:
patchfile_fp = os.path.join(self.llvm_src_dir, "projects/compiler-rt", patchfile, "CMakeLists.txt")
if os.path.exists(patchfile_fp):
self.log.debug("Patching %s in %s" % (patchfile, self.llvm_src_dir))
try:
for line in fileinput.input(patchfile_fp, inplace=1, backup='.orig'):
if "add_subdirectory(lit_tests)" not in line:
sys.stdout.write(line)
except (IOError, OSError), err:
raise EasyBuildError("Failed to patch %s: %s", patchfile_fp, err)
else:
self.log.debug("Not patching non-existent %s in %s" % (patchfile, self.llvm_src_dir))
# There is a common part seperate for the specific saniters, we disable all
# the common tests
patchfile = "projects/compiler-rt/lib/sanitizer_common/CMakeLists.txt"
try:
for line in fileinput.input("%s/%s" % (self.llvm_src_dir, patchfile), inplace=1, backup='.orig'):
if "add_subdirectory(tests)" not in line:
sys.stdout.write(line)
except IOError, err:
raise EasyBuildError("Failed to patch %s/%s: %s", self.llvm_src_dir, patchfile, err)
else:
# In Clang 3.6, the sanitizer tests are grouped together in one CMakeLists
# We patch out adding the subdirectories with the sanitizer tests
patchfile = "projects/compiler-rt/test/CMakeLists.txt"
patchfile_fp = os.path.join(self.llvm_src_dir, patchfile)
self.log.debug("Patching %s in %s" % (patchfile, self.llvm_src_dir))
patch_regex = re.compile(r'add_subdirectory\((.*san|sanitizer_common)\)')
try:
for line in fileinput.input(patchfile_fp, inplace=1, backup='.orig'):
if not patch_regex.search(line):
sys.stdout.write(line)
except IOError, err:
raise EasyBuildError("Failed to patch %s: %s", patchfile_fp, err)
def build_with_prev_stage(self, prev_obj, next_obj):
"""Build Clang stage N using Clang stage N-1"""
# Create and enter build directory.
mkdir(next_obj)
os.chdir(next_obj)
# Configure.
CC = os.path.join(prev_obj, 'bin', 'clang')
CXX = os.path.join(prev_obj, 'bin', 'clang++')
options = "-DCMAKE_INSTALL_PREFIX=%s " % self.installdir
options += "-DCMAKE_C_COMPILER='%s' " % CC
options += "-DCMAKE_CXX_COMPILER='%s' " % CXX
options += self.cfg['configopts']
self.log.info("Configuring")
run_cmd("cmake %s %s" % (options, self.llvm_src_dir), log_all=True)
self.log.info("Building")
run_cmd("make %s" % self.make_parallel_opts, log_all=True)
def run_clang_tests(self, obj_dir):
os.chdir(obj_dir)
self.log.info("Running tests")
run_cmd("make %s check-all" % self.make_parallel_opts, log_all=True)
def build_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).build_step()
return
"""Build Clang stage 1, 2, 3"""
# Stage 1: build using system compiler.
self.log.info("Building stage 1")
os.chdir(self.llvm_obj_dir_stage1)
super(EB_Clang, self).build_step()
if self.cfg['bootstrap']:
# Stage 1: run tests.
self.run_clang_tests(self.llvm_obj_dir_stage1)
self.log.info("Building stage 2")
self.build_with_prev_stage(self.llvm_obj_dir_stage1, self.llvm_obj_dir_stage2)
self.run_clang_tests(self.llvm_obj_dir_stage2)
self.log.info("Building stage 3")
self.build_with_prev_stage(self.llvm_obj_dir_stage2, self.llvm_obj_dir_stage3)
# Don't run stage 3 tests here, do it in the test step.
def test_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).test_step()
return
if self.cfg['bootstrap']:
self.run_clang_tests(self.llvm_obj_dir_stage3)
else:
self.run_clang_tests(self.llvm_obj_dir_stage1)
def install_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).install_step()
return
"""Install stage 3 binaries."""
if self.cfg['bootstrap']:
os.chdir(self.llvm_obj_dir_stage3)
else:
os.chdir(self.llvm_obj_dir_stage1)
super(EB_Clang, self).install_step()
# the static analyzer is not installed by default
# we do it by hand
if self.cfg['static_analyzer'] and LooseVersion(self.version) < LooseVersion('3.8'):
try:
tools_src_dir = os.path.join(self.llvm_src_dir, 'tools', 'clang', 'tools')
analyzer_target_dir = os.path.join(self.installdir, 'libexec', 'clang-analyzer')
bindir = os.path.join(self.installdir, 'bin')
for scan_dir in ['scan-build', 'scan-view']:
shutil.copytree(os.path.join(tools_src_dir, scan_dir), os.path.join(analyzer_target_dir, scan_dir))
os.symlink(os.path.relpath(bindir, os.path.join(analyzer_target_dir, scan_dir)),
os.path.join(analyzer_target_dir, scan_dir, 'bin'))
os.symlink(os.path.relpath(os.path.join(analyzer_target_dir, scan_dir, scan_dir), bindir),
os.path.join(bindir, scan_dir))
mandir = os.path.join(self.installdir, 'share', 'man', 'man1')
os.makedirs(mandir)
shutil.copy2(os.path.join(tools_src_dir, 'scan-build', 'scan-build.1'), mandir)
except OSError, err:
raise EasyBuildError("Failed to copy static analyzer dirs to install dir: %s", err)
def sanity_check_step(self):
"""Custom sanity check for Clang."""
shlib_ext = get_shared_lib_ext()
custom_paths = {
'files': [
"bin/clang", "bin/clang++", "bin/llvm-ar", "bin/llvm-nm", "bin/llvm-as", "bin/opt", "bin/llvm-link",
"bin/llvm-config", "bin/llvm-symbolizer", "include/llvm-c/Core.h", "include/clang-c/Index.h",
"lib/libclang.%s" % shlib_ext, "lib/clang/%s/include/stddef.h" % self.version,
],
'dirs': ["include/clang", "include/llvm", "lib/clang/%s/lib" % self.version],
}
if self.cfg['static_analyzer']:
custom_paths['files'].extend(["bin/scan-build", "bin/scan-view"])
if self.cfg["usepolly"]:
custom_paths['files'].extend(["lib/LLVMPolly.%s" % shlib_ext])
custom_paths['dirs'].extend(["include/polly"])
if LooseVersion(self.version) >= LooseVersion('3.8'):
custom_paths['files'].extend(["lib/libomp.%s" % shlib_ext, "lib/clang/%s/include/omp.h" % self.version])
super(EB_Clang, self).sanity_check_step(custom_paths=custom_paths)
def make_module_extra(self):
"""Custom variables for Clang module."""
txt = super(EB_Clang, self).make_module_extra()
# we set the symbolizer path so that asan/tsan give meanfull output by default
asan_symbolizer_path = os.path.join(self.installdir, 'bin', 'llvm-symbolizer')
txt += self.module_generator.set_environment('ASAN_SYMBOLIZER_PATH', asan_symbolizer_path)
return txt
##
# Copyright 2013 Dmitri Gribenko
# Copyright 2013-2017 Ghent University
# Copyright 2017 IT4Innovations
#
# This file is triple-licensed under GPLv2 (see below), MIT, and
# BSD three-clause licenses.
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
Support for building and installing Clang, implemented as an easyblock.
@author: Dmitri Gribenko (National Technical University of Ukraine "KPI")
@author: Ward Poelmans (Ghent University)
@author: Josef Hrabal, Lukas Krupcik (IT4innovations, Czechia)
"""
import fileinput
import glob
import os
import re
import shutil
import sys
from distutils.version import LooseVersion
from easybuild.easyblocks.generic.cmakemake import CMakeMake
from easybuild.framework.easyconfig import CUSTOM
from easybuild.tools import run
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.filetools import mkdir
from easybuild.tools.modules import get_software_root
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_os_name, get_os_version, get_shared_lib_ext
# List of all possible build targets for Clang
CLANG_TARGETS = ["all", "AArch64", "ARM", "CppBackend", "Hexagon", "Mips",
"MBlaze", "MSP430", "NVPTX", "PowerPC", "R600", "Sparc",
"SystemZ", "X86", "XCore"]
class EB_Clang(CMakeMake):
"""Support for bootstrapping Clang."""
@staticmethod
def extra_options():
extra_vars = {
'assertions': [True, "Enable assertions. Helps to catch bugs in Clang.", CUSTOM],
'build_targets': [["X86"], "Build targets for LLVM. Possible values: " + ', '.join(CLANG_TARGETS), CUSTOM],
'bootstrap': [True, "Bootstrap Clang using GCC", CUSTOM],
'usepolly': [False, "Build Clang with polly", CUSTOM],
'static_analyzer': [True, "Install the static analyser of Clang", CUSTOM],
# The sanitizer tests often fail on HPC systems due to the 'weird' environment.
'skip_sanitizer_tests': [False, "Do not run the sanitizer tests", CUSTOM],
}
return CMakeMake.extra_options(extra_vars)
def __init__(self, *args, **kwargs):
"""Initialize custom class variables for Clang."""
super(EB_Clang, self).__init__(*args, **kwargs)
self.llvm_src_dir = None
self.llvm_obj_dir_stage1 = None
self.llvm_obj_dir_stage2 = None
self.llvm_obj_dir_stage3 = None
self.make_parallel_opts = ""
unknown_targets = [target for target in self.cfg['build_targets'] if target not in CLANG_TARGETS]
if unknown_targets:
raise EasyBuildError("Some of the chosen build targets (%s) are not in %s.",
', '.join(unknown_targets), ', '.join(CLANG_TARGETS))
if LooseVersion(self.version) < LooseVersion('3.4') and "R600" in self.cfg['build_targets']:
raise EasyBuildError("Build target R600 not supported in < Clang-3.4")
if LooseVersion(self.version) > LooseVersion('3.3') and "MBlaze" in self.cfg['build_targets']:
raise EasyBuildError("Build target MBlaze is not supported anymore in > Clang-3.3")
def check_readiness_step(self):
"""Fail early on RHEL 5.x and derivatives because of known bug in libc."""
super(EB_Clang, self).check_readiness_step()
# RHEL 5.x have a buggy libc. Building stage 2 will fail.
if get_os_name() in ['redhat', 'RHEL', 'centos', 'SL'] and get_os_version().startswith('5.'):
raise EasyBuildError("Can not build Clang on %s v5.x: libc is buggy, building stage 2 will fail. "
"See http://stackoverflow.com/questions/7276828/", get_os_name())
def extract_step(self):
"""
Prepare a combined LLVM source tree. The layout is:
llvm/ Unpack llvm-*.tar.gz here
projects/
compiler-rt/ Unpack compiler-rt-*.tar.gz here
openmp/ Unpack openmp-*.tar.xz here
libcxx/ Unpack libcxx-*.tar.xz here
libcxxabi/ Unpack libcxxapbi-*.tar.xz here
tools/
clang/ Unpack cfe-*.tar.gz here
tools/extra Unpack clang-*.tar.gz here
polly/ Unpack polly-*.tar.gz here
"""
# Extract everything into separate directories.
super(EB_Clang, self).extract_step()
# Find the full path to the directory that was unpacked from llvm-*.tar.gz.
for tmp in self.src:
if tmp['name'].startswith("llvm-"):
self.llvm_src_dir = tmp['finalpath']
break
if self.llvm_src_dir is None:
raise EasyBuildError("Could not determine LLVM source root (LLVM source was not unpacked?)")
src_dirs = {}
def find_source_dir(globpatterns, targetdir):
"""Search for directory with globpattern and rename it to targetdir"""
if not isinstance(globpatterns, list):
globpatterns = [globpatterns]
glob_src_dirs = [glob_dir for globpattern in globpatterns for glob_dir in glob.glob(globpattern)]
if len(glob_src_dirs) != 1:
raise EasyBuildError("Failed to find exactly one source directory for pattern %s: %s", globpatterns,
glob_src_dirs)
src_dirs[glob_src_dirs[0]] = targetdir
find_source_dir('compiler-rt-*', os.path.join(self.llvm_src_dir, 'projects', 'compiler-rt'))
if self.cfg["usepolly"]:
find_source_dir('polly-*', os.path.join(self.llvm_src_dir, 'tools', 'polly'))
find_source_dir('cfe-*', os.path.join(self.llvm_src_dir, 'tools', 'clang'))
find_source_dir('clang-*', os.path.join(self.llvm_src_dir, 'tools', 'clang', 'tools', 'extra'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libcxx-*', os.path.join(self.llvm_src_dir, 'projects', 'libcxx'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libcxxabi-*', os.path.join(self.llvm_src_dir, 'projects', 'libcxxabi'))
if LooseVersion(self.version) >= LooseVersion('3.8'):
find_source_dir('openmp-*', os.path.join(self.llvm_src_dir, 'projects', 'openmp'))
for src in self.src:
for (dirname, new_path) in src_dirs.items():
if src['name'].startswith(dirname):
old_path = os.path.join(src['finalpath'], dirname)
try:
shutil.move(old_path, new_path)
except IOError, err:
raise EasyBuildError("Failed to move %s to %s: %s", old_path, new_path, err)
src['finalpath'] = new_path
break
def configure_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).configure_step()
return
"""Run CMake for stage 1 Clang."""
self.llvm_obj_dir_stage1 = os.path.join(self.builddir, 'llvm.obj.1')
if self.cfg['bootstrap']:
self.llvm_obj_dir_stage2 = os.path.join(self.builddir, 'llvm.obj.2')
self.llvm_obj_dir_stage3 = os.path.join(self.builddir, 'llvm.obj.3')
if LooseVersion(self.version) >= LooseVersion('3.3'):
disable_san_tests = False
# all sanitizer tests will fail when there's a limit on the vmem
# this is ugly but I haven't found a cleaner way so far
(vmemlim, ec) = run_cmd("ulimit -v", regexp=False)
if not vmemlim.startswith("unlimited"):
disable_san_tests = True
self.log.warn("There is a virtual memory limit set of %s KB. The tests of the "
"sanitizers will be disabled as they need unlimited virtual "
"memory unless --strict=error is used." % vmemlim.strip())
# the same goes for unlimited stacksize
(stacklim, ec) = run_cmd("ulimit -s", regexp=False)
if stacklim.startswith("unlimited"):
disable_san_tests = True
self.log.warn("The stacksize limit is set to unlimited. This causes the ThreadSanitizer "
"to fail. The sanitizers tests will be disabled unless --strict=error is used.")
if (disable_san_tests or self.cfg['skip_sanitizer_tests']) and build_option('strict') != run.ERROR:
self.log.debug("Disabling the sanitizer tests")
self.disable_sanitizer_tests()
# Create and enter build directory.
mkdir(self.llvm_obj_dir_stage1)
os.chdir(self.llvm_obj_dir_stage1)
# GCC and Clang are installed in different prefixes and Clang will not
# find the GCC installation on its own.
# First try with GCCcore, as GCC built on top of GCCcore is just a wrapper for GCCcore and binutils,
# instead of a full-fledge compiler
gcc_prefix = get_software_root('GCCcore')
# If that doesn't work, try with GCC
if gcc_prefix is None:
gcc_prefix = get_software_root('GCC')
# If that doesn't work either, print error and exit
if gcc_prefix is None:
raise EasyBuildError("Can't find GCC or GCCcore to use")
self.cfg.update('configopts', "-DGCC_INSTALL_PREFIX='%s' " % gcc_prefix)
self.log.debug("Using %s as GCC_INSTALL_PREFIX", gcc_prefix)
self.cfg['configopts'] += "-DCMAKE_BUILD_TYPE=Release "
if self.cfg['assertions']:
self.cfg['configopts'] += "-DLLVM_ENABLE_ASSERTIONS=ON "
else:
self.cfg['configopts'] += "-DLLVM_ENABLE_ASSERTIONS=OFF "
self.cfg['configopts'] += '-DLLVM_TARGETS_TO_BUILD="%s" ' % ';'.join(self.cfg['build_targets'])
if self.cfg['parallel']:
self.make_parallel_opts = "-j %s" % self.cfg['parallel']
self.log.info("Configuring")
super(EB_Clang, self).configure_step(srcdir=self.llvm_src_dir)
def disable_sanitizer_tests(self):
"""Disable the tests of all the sanitizers by removing the test directories from the build system"""
if LooseVersion(self.version) < LooseVersion('3.6'):
# for Clang 3.5 and lower, the tests are scattered over several CMakeLists.
# We loop over them, and patch out the rule that adds the sanitizers tests to the testsuite
patchfiles = [
"lib/asan",
"lib/dfsan",
"lib/lsan",
"lib/msan",
"lib/tsan",
"lib/ubsan",
]
for patchfile in patchfiles:
patchfile_fp = os.path.join(self.llvm_src_dir, "projects/compiler-rt", patchfile, "CMakeLists.txt")
if os.path.exists(patchfile_fp):
self.log.debug("Patching %s in %s" % (patchfile, self.llvm_src_dir))
try:
for line in fileinput.input(patchfile_fp, inplace=1, backup='.orig'):
if "add_subdirectory(lit_tests)" not in line:
sys.stdout.write(line)
except (IOError, OSError), err:
raise EasyBuildError("Failed to patch %s: %s", patchfile_fp, err)
else:
self.log.debug("Not patching non-existent %s in %s" % (patchfile, self.llvm_src_dir))
# There is a common part seperate for the specific saniters, we disable all
# the common tests
patchfile = "projects/compiler-rt/lib/sanitizer_common/CMakeLists.txt"
try:
for line in fileinput.input("%s/%s" % (self.llvm_src_dir, patchfile), inplace=1, backup='.orig'):
if "add_subdirectory(tests)" not in line:
sys.stdout.write(line)
except IOError, err:
raise EasyBuildError("Failed to patch %s/%s: %s", self.llvm_src_dir, patchfile, err)
else:
# In Clang 3.6, the sanitizer tests are grouped together in one CMakeLists
# We patch out adding the subdirectories with the sanitizer tests
patchfile = "projects/compiler-rt/test/CMakeLists.txt"
patchfile_fp = os.path.join(self.llvm_src_dir, patchfile)
self.log.debug("Patching %s in %s" % (patchfile, self.llvm_src_dir))
patch_regex = re.compile(r'add_subdirectory\((.*san|sanitizer_common)\)')
try:
for line in fileinput.input(patchfile_fp, inplace=1, backup='.orig'):
if not patch_regex.search(line):
sys.stdout.write(line)
except IOError, err:
raise EasyBuildError("Failed to patch %s: %s", patchfile_fp, err)
def build_with_prev_stage(self, prev_obj, next_obj):
"""Build Clang stage N using Clang stage N-1"""
# Create and enter build directory.
mkdir(next_obj)
os.chdir(next_obj)
# Configure.
CC = os.path.join(prev_obj, 'bin', 'clang')
CXX = os.path.join(prev_obj, 'bin', 'clang++')
options = "-DCMAKE_INSTALL_PREFIX=%s " % self.installdir
options += "-DCMAKE_C_COMPILER='%s' " % CC
options += "-DCMAKE_CXX_COMPILER='%s' " % CXX
options += self.cfg['configopts']
self.log.info("Configuring")
run_cmd("cmake %s %s" % (options, self.llvm_src_dir), log_all=True)
self.log.info("Building")
run_cmd("make %s" % self.make_parallel_opts, log_all=True)
def run_clang_tests(self, obj_dir):
os.chdir(obj_dir)
self.log.info("Running tests")
run_cmd("make %s check-all" % self.make_parallel_opts, log_all=True)
def build_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).build_step()
return
"""Build Clang stage 1, 2, 3"""
# Stage 1: build using system compiler.
self.log.info("Building stage 1")
os.chdir(self.llvm_obj_dir_stage1)
super(EB_Clang, self).build_step()
if self.cfg['bootstrap']:
# Stage 1: run tests.
self.run_clang_tests(self.llvm_obj_dir_stage1)
self.log.info("Building stage 2")
self.build_with_prev_stage(self.llvm_obj_dir_stage1, self.llvm_obj_dir_stage2)
self.run_clang_tests(self.llvm_obj_dir_stage2)
self.log.info("Building stage 3")
self.build_with_prev_stage(self.llvm_obj_dir_stage2, self.llvm_obj_dir_stage3)
# Don't run stage 3 tests here, do it in the test step.
def test_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).test_step()
return
if self.cfg['bootstrap']:
self.run_clang_tests(self.llvm_obj_dir_stage3)
else:
self.run_clang_tests(self.llvm_obj_dir_stage1)
def install_step(self):
if LooseVersion(self.version) >= LooseVersion('5.0'):
super(EB_Clang, self).install_step()
return
"""Install stage 3 binaries."""
if self.cfg['bootstrap']:
os.chdir(self.llvm_obj_dir_stage3)
else:
os.chdir(self.llvm_obj_dir_stage1)
super(EB_Clang, self).install_step()
# the static analyzer is not installed by default
# we do it by hand
if self.cfg['static_analyzer'] and LooseVersion(self.version) < LooseVersion('3.8'):
try:
tools_src_dir = os.path.join(self.llvm_src_dir, 'tools', 'clang', 'tools')
analyzer_target_dir = os.path.join(self.installdir, 'libexec', 'clang-analyzer')
bindir = os.path.join(self.installdir, 'bin')
for scan_dir in ['scan-build', 'scan-view']:
shutil.copytree(os.path.join(tools_src_dir, scan_dir), os.path.join(analyzer_target_dir, scan_dir))
os.symlink(os.path.relpath(bindir, os.path.join(analyzer_target_dir, scan_dir)),
os.path.join(analyzer_target_dir, scan_dir, 'bin'))
os.symlink(os.path.relpath(os.path.join(analyzer_target_dir, scan_dir, scan_dir), bindir),
os.path.join(bindir, scan_dir))
mandir = os.path.join(self.installdir, 'share', 'man', 'man1')
os.makedirs(mandir)
shutil.copy2(os.path.join(tools_src_dir, 'scan-build', 'scan-build.1'), mandir)
except OSError, err:
raise EasyBuildError("Failed to copy static analyzer dirs to install dir: %s", err)
def sanity_check_step(self):
"""Custom sanity check for Clang."""
shlib_ext = get_shared_lib_ext()
custom_paths = {
'files': [
"bin/clang", "bin/clang++", "bin/llvm-ar", "bin/llvm-nm", "bin/llvm-as", "bin/opt", "bin/llvm-link",
"bin/llvm-config", "bin/llvm-symbolizer", "include/llvm-c/Core.h", "include/clang-c/Index.h",
"lib/libclang.%s" % shlib_ext, "lib/clang/%s/include/stddef.h" % self.version,
],
'dirs': ["include/clang", "include/llvm", "lib/clang/%s/lib" % self.version],
}
if self.cfg['static_analyzer']:
custom_paths['files'].extend(["bin/scan-build", "bin/scan-view"])
if self.cfg["usepolly"]:
custom_paths['files'].extend(["lib/LLVMPolly.%s" % shlib_ext])
custom_paths['dirs'].extend(["include/polly"])
if LooseVersion(self.version) >= LooseVersion('3.8'):
custom_paths['files'].extend(["lib/libomp.%s" % shlib_ext, "lib/clang/%s/include/omp.h" % self.version])
super(EB_Clang, self).sanity_check_step(custom_paths=custom_paths)
def make_module_extra(self):
"""Custom variables for Clang module."""
txt = super(EB_Clang, self).make_module_extra()
# we set the symbolizer path so that asan/tsan give meanfull output by default
asan_symbolizer_path = os.path.join(self.installdir, 'bin', 'llvm-symbolizer')
txt += self.module_generator.set_environment('ASAN_SYMBOLIZER_PATH', asan_symbolizer_path)
return txt
##
# Copyright 2013 Dmitri Gribenko
# Copyright 2013-2017 Ghent University
#
# This file is triple-licensed under GPLv2 (see below), MIT, and
# BSD three-clause licenses.
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
Support for building and installing Clang, implemented as an easyblock.
@author: Dmitri Gribenko (National Technical University of Ukraine "KPI")
@author: Ward Poelmans (Ghent University)
"""
import fileinput
import glob
import os
import re
import shutil
import sys
from distutils.version import LooseVersion
from easybuild.easyblocks.generic.cmakemake import CMakeMake
from easybuild.framework.easyconfig import CUSTOM
from easybuild.tools import run
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.config import build_option
from easybuild.tools.filetools import mkdir
from easybuild.tools.modules import get_software_root
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_os_name, get_os_version, get_shared_lib_ext
# List of all possible build targets for Clang
CLANG_TARGETS = ["all", "AArch64", "ARM", "CppBackend", "Hexagon", "Mips",
"MBlaze", "MSP430", "NVPTX", "PowerPC", "R600", "Sparc",
"SystemZ", "X86", "XCore"]
class EB_Clang(CMakeMake):
"""Support for bootstrapping Clang."""
@staticmethod
def extra_options():
extra_vars = {
'assertions': [True, "Enable assertions. Helps to catch bugs in Clang.", CUSTOM],
'build_targets': [["X86"], "Build targets for LLVM. Possible values: " + ', '.join(CLANG_TARGETS), CUSTOM],
'bootstrap': [True, "Bootstrap Clang using GCC", CUSTOM],
'usepolly': [False, "Build Clang with polly", CUSTOM],
'static_analyzer': [True, "Install the static analyser of Clang", CUSTOM],
# The sanitizer tests often fail on HPC systems due to the 'weird' environment.
'skip_sanitizer_tests': [False, "Do not run the sanitizer tests", CUSTOM],
}
return CMakeMake.extra_options(extra_vars)
def __init__(self, *args, **kwargs):
"""Initialize custom class variables for Clang."""
super(EB_Clang, self).__init__(*args, **kwargs)
self.llvm_src_dir = None
self.llvm_obj_dir_stage1 = None
self.llvm_obj_dir_stage2 = None
self.llvm_obj_dir_stage3 = None
self.make_parallel_opts = ""
unknown_targets = [target for target in self.cfg['build_targets'] if target not in CLANG_TARGETS]
if unknown_targets:
raise EasyBuildError("Some of the chosen build targets (%s) are not in %s.",
', '.join(unknown_targets), ', '.join(CLANG_TARGETS))
if LooseVersion(self.version) < LooseVersion('3.4') and "R600" in self.cfg['build_targets']:
raise EasyBuildError("Build target R600 not supported in < Clang-3.4")
if LooseVersion(self.version) > LooseVersion('3.3') and "MBlaze" in self.cfg['build_targets']:
raise EasyBuildError("Build target MBlaze is not supported anymore in > Clang-3.3")
def check_readiness_step(self):
"""Fail early on RHEL 5.x and derivatives because of known bug in libc."""
super(EB_Clang, self).check_readiness_step()
# RHEL 5.x have a buggy libc. Building stage 2 will fail.
if get_os_name() in ['redhat', 'RHEL', 'centos', 'SL'] and get_os_version().startswith('5.'):
raise EasyBuildError("Can not build Clang on %s v5.x: libc is buggy, building stage 2 will fail. "
"See http://stackoverflow.com/questions/7276828/", get_os_name())
def extract_step(self):
"""
Prepare a combined LLVM source tree. The layout is:
llvm/ Unpack llvm-*.tar.gz here
projects/
compiler-rt/ Unpack compiler-rt-*.tar.gz here
openmp/ Unpack openmp-*.tar.xz here
libcxx/
libcxxabi/
tools/
clang/ Unpack clang-*.tar.gz here
clang/tools/extra
polly/ Unpack polly-*.tar.gz here
"""
# Extract everything into separate directories.
super(EB_Clang, self).extract_step()
# Find the full path to the directory that was unpacked from llvm-*.tar.gz.
for tmp in self.src:
if tmp['name'].startswith("llvm-"):
self.llvm_src_dir = tmp['finalpath']
break
if self.llvm_src_dir is None:
raise EasyBuildError("Could not determine LLVM source root (LLVM source was not unpacked?)")
src_dirs = {}
def find_source_dir(globpatterns, targetdir):
"""Search for directory with globpattern and rename it to targetdir"""
if not isinstance(globpatterns, list):
globpatterns = [globpatterns]
glob_src_dirs = [glob_dir for globpattern in globpatterns for glob_dir in glob.glob(globpattern)]
if len(glob_src_dirs) != 1:
raise EasyBuildError("Failed to find exactly one source directory for pattern %s: %s", globpatterns,
glob_src_dirs)
src_dirs[glob_src_dirs[0]] = targetdir
find_source_dir('compiler-rt-*', os.path.join(self.llvm_src_dir, 'projects', 'compiler-rt'))
if self.cfg["usepolly"]:
find_source_dir('polly-*', os.path.join(self.llvm_src_dir, 'tools', 'polly'))
find_source_dir('cfe-*', os.path.join(self.llvm_src_dir, 'tools', 'clang'))
find_source_dir('clang-*', os.path.join(self.llvm_src_dir, 'tools', 'clang', 'tools', 'extra'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libcxx-*', os.path.join(self.llvm_src_dir, 'projects', 'libcxx'))
if LooseVersion(self.version) >= LooseVersion('5.0'):
find_source_dir('libcxxabi-*', os.path.join(self.llvm_src_dir, 'projects', 'libcxxabi'))
if LooseVersion(self.version) >= LooseVersion('3.8'):
find_source_dir('openmp-*', os.path.join(self.llvm_src_dir, 'projects', 'openmp'))
for src in self.src:
for (dirname, new_path) in src_dirs.items():
if src['name'].startswith(dirname):
old_path = os.path.join(src['finalpath'], dirname)
try:
shutil.move(old_path, new_path)
except IOError, err:
raise EasyBuildError("Failed to move %s to %s: %s", old_path, new_path, err)
src['finalpath'] = new_path
break
def configure_step(self):
"""Run CMake for stage 1 Clang."""
self.llvm_obj_dir_stage1 = os.path.join(self.builddir, 'llvm.obj.1')
if self.cfg['bootstrap']:
self.llvm_obj_dir_stage2 = os.path.join(self.builddir, 'llvm.obj.2')
self.llvm_obj_dir_stage3 = os.path.join(self.builddir, 'llvm.obj.3')
if LooseVersion(self.version) >= LooseVersion('3.3'):
disable_san_tests = False
# all sanitizer tests will fail when there's a limit on the vmem
# this is ugly but I haven't found a cleaner way so far
(vmemlim, ec) = run_cmd("ulimit -v", regexp=False)
if not vmemlim.startswith("unlimited"):
disable_san_tests = True
self.log.warn("There is a virtual memory limit set of %s KB. The tests of the "
"sanitizers will be disabled as they need unlimited virtual "
"memory unless --strict=error is used." % vmemlim.strip())
# the same goes for unlimited stacksize
(stacklim, ec) = run_cmd("ulimit -s", regexp=False)
if stacklim.startswith("unlimited"):
disable_san_tests = True
self.log.warn("The stacksize limit is set to unlimited. This causes the ThreadSanitizer "
"to fail. The sanitizers tests will be disabled unless --strict=error is used.")
if (disable_san_tests or self.cfg['skip_sanitizer_tests']) and build_option('strict') != run.ERROR:
self.log.debug("Disabling the sanitizer tests")
self.disable_sanitizer_tests()
# Create and enter build directory.
mkdir(self.llvm_obj_dir_stage1)
os.chdir(self.llvm_obj_dir_stage1)
# GCC and Clang are installed in different prefixes and Clang will not
# find the GCC installation on its own.
# First try with GCCcore, as GCC built on top of GCCcore is just a wrapper for GCCcore and binutils,
# instead of a full-fledge compiler
gcc_prefix = get_software_root('GCCcore')
# If that doesn't work, try with GCC
if gcc_prefix is None:
gcc_prefix = get_software_root('GCC')
# If that doesn't work either, print error and exit
if gcc_prefix is None:
raise EasyBuildError("Can't find GCC or GCCcore to use")
self.cfg.update('configopts', "-DGCC_INSTALL_PREFIX='%s' " % gcc_prefix)
self.log.debug("Using %s as GCC_INSTALL_PREFIX", gcc_prefix)
self.cfg['configopts'] += "-DCMAKE_BUILD_TYPE=Release "
if self.cfg['assertions']:
self.cfg['configopts'] += "-DLLVM_ENABLE_ASSERTIONS=ON "
else:
self.cfg['configopts'] += "-DLLVM_ENABLE_ASSERTIONS=OFF "
self.cfg['configopts'] += '-DLLVM_TARGETS_TO_BUILD="%s" ' % ';'.join(self.cfg['build_targets'])
if self.cfg['parallel']:
self.make_parallel_opts = "-j %s" % self.cfg['parallel']
self.log.info("Configuring")
super(EB_Clang, self).configure_step(srcdir=self.llvm_src_dir)
def disable_sanitizer_tests(self):
"""Disable the tests of all the sanitizers by removing the test directories from the build system"""
if LooseVersion(self.version) < LooseVersion('3.6'):
# for Clang 3.5 and lower, the tests are scattered over several CMakeLists.
# We loop over them, and patch out the rule that adds the sanitizers tests to the testsuite
patchfiles = [
"lib/asan",
"lib/dfsan",
"lib/lsan",
"lib/msan",
"lib/tsan",
"lib/ubsan",
]
for patchfile in patchfiles:
patchfile_fp = os.path.join(self.llvm_src_dir, "projects/compiler-rt", patchfile, "CMakeLists.txt")
if os.path.exists(patchfile_fp):
self.log.debug("Patching %s in %s" % (patchfile, self.llvm_src_dir))
try:
for line in fileinput.input(patchfile_fp, inplace=1, backup='.orig'):
if "add_subdirectory(lit_tests)" not in line:
sys.stdout.write(line)
except (IOError, OSError), err:
raise EasyBuildError("Failed to patch %s: %s", patchfile_fp, err)
else:
self.log.debug("Not patching non-existent %s in %s" % (patchfile, self.llvm_src_dir))
# There is a common part seperate for the specific saniters, we disable all
# the common tests
patchfile = "projects/compiler-rt/lib/sanitizer_common/CMakeLists.txt"
try:
for line in fileinput.input("%s/%s" % (self.llvm_src_dir, patchfile), inplace=1, backup='.orig'):
if "add_subdirectory(tests)" not in line:
sys.stdout.write(line)
except IOError, err:
raise EasyBuildError("Failed to patch %s/%s: %s", self.llvm_src_dir, patchfile, err)
else:
# In Clang 3.6, the sanitizer tests are grouped together in one CMakeLists
# We patch out adding the subdirectories with the sanitizer tests
patchfile = "projects/compiler-rt/test/CMakeLists.txt"
patchfile_fp = os.path.join(self.llvm_src_dir, patchfile)
self.log.debug("Patching %s in %s" % (patchfile, self.llvm_src_dir))
patch_regex = re.compile(r'add_subdirectory\((.*san|sanitizer_common)\)')
try:
for line in fileinput.input(patchfile_fp, inplace=1, backup='.orig'):
if not patch_regex.search(line):
sys.stdout.write(line)
except IOError, err:
raise EasyBuildError("Failed to patch %s: %s", patchfile_fp, err)
def build_with_prev_stage(self, prev_obj, next_obj):
"""Build Clang stage N using Clang stage N-1"""
# Create and enter build directory.
mkdir(next_obj)
os.chdir(next_obj)
# Configure.
CC = os.path.join(prev_obj, 'bin', 'clang')
CXX = os.path.join(prev_obj, 'bin', 'clang++')
options = "-DCMAKE_INSTALL_PREFIX=%s " % self.installdir
options += "-DCMAKE_C_COMPILER='%s' " % CC
options += "-DCMAKE_CXX_COMPILER='%s' " % CXX
options += self.cfg['configopts']
self.log.info("Configuring")
run_cmd("cmake %s %s" % (options, self.llvm_src_dir), log_all=True)
self.log.info("Building")
run_cmd("make %s" % self.make_parallel_opts, log_all=True)
def run_clang_tests(self, obj_dir):
os.chdir(obj_dir)
self.log.info("Running tests")
run_cmd("make %s check-all" % self.make_parallel_opts, log_all=True)
def build_step(self):
"""Build Clang stage 1, 2, 3"""
# Stage 1: build using system compiler.
self.log.info("Building stage 1")
os.chdir(self.llvm_obj_dir_stage1)
super(EB_Clang, self).build_step()
if self.cfg['bootstrap']:
# Stage 1: run tests.
self.run_clang_tests(self.llvm_obj_dir_stage1)
self.log.info("Building stage 2")
self.build_with_prev_stage(self.llvm_obj_dir_stage1, self.llvm_obj_dir_stage2)
self.run_clang_tests(self.llvm_obj_dir_stage2)
self.log.info("Building stage 3")
self.build_with_prev_stage(self.llvm_obj_dir_stage2, self.llvm_obj_dir_stage3)
# Don't run stage 3 tests here, do it in the test step.
def test_step(self):
if self.cfg['bootstrap']:
self.run_clang_tests(self.llvm_obj_dir_stage3)
else:
self.run_clang_tests(self.llvm_obj_dir_stage1)
def install_step(self):
"""Install stage 3 binaries."""
if self.cfg['bootstrap']:
os.chdir(self.llvm_obj_dir_stage3)
else:
os.chdir(self.llvm_obj_dir_stage1)
super(EB_Clang, self).install_step()
# the static analyzer is not installed by default
# we do it by hand
if self.cfg['static_analyzer'] and LooseVersion(self.version) < LooseVersion('3.8'):
try:
tools_src_dir = os.path.join(self.llvm_src_dir, 'tools', 'clang', 'tools')
analyzer_target_dir = os.path.join(self.installdir, 'libexec', 'clang-analyzer')
bindir = os.path.join(self.installdir, 'bin')
for scan_dir in ['scan-build', 'scan-view']:
shutil.copytree(os.path.join(tools_src_dir, scan_dir), os.path.join(analyzer_target_dir, scan_dir))
os.symlink(os.path.relpath(bindir, os.path.join(analyzer_target_dir, scan_dir)),
os.path.join(analyzer_target_dir, scan_dir, 'bin'))
os.symlink(os.path.relpath(os.path.join(analyzer_target_dir, scan_dir, scan_dir), bindir),
os.path.join(bindir, scan_dir))
mandir = os.path.join(self.installdir, 'share', 'man', 'man1')
os.makedirs(mandir)
shutil.copy2(os.path.join(tools_src_dir, 'scan-build', 'scan-build.1'), mandir)
except OSError, err:
raise EasyBuildError("Failed to copy static analyzer dirs to install dir: %s", err)
def sanity_check_step(self):
"""Custom sanity check for Clang."""
shlib_ext = get_shared_lib_ext()
custom_paths = {
'files': [
"bin/clang", "bin/clang++", "bin/llvm-ar", "bin/llvm-nm", "bin/llvm-as", "bin/opt", "bin/llvm-link",
"bin/llvm-config", "bin/llvm-symbolizer", "include/llvm-c/Core.h", "include/clang-c/Index.h",
"lib/libclang.%s" % shlib_ext, "lib/clang/%s/include/stddef.h" % self.version,
],
'dirs': ["include/clang", "include/llvm", "lib/clang/%s/lib" % self.version],
}
if self.cfg['static_analyzer']:
custom_paths['files'].extend(["bin/scan-build", "bin/scan-view"])
if self.cfg["usepolly"]:
custom_paths['files'].extend(["lib/LLVMPolly.%s" % shlib_ext])
custom_paths['dirs'].extend(["include/polly"])
if LooseVersion(self.version) >= LooseVersion('3.8'):
custom_paths['files'].extend(["lib/libomp.%s" % shlib_ext, "lib/clang/%s/include/omp.h" % self.version])
super(EB_Clang, self).sanity_check_step(custom_paths=custom_paths)
def make_module_extra(self):
"""Custom variables for Clang module."""
txt = super(EB_Clang, self).make_module_extra()
# we set the symbolizer path so that asan/tsan give meanfull output by default
asan_symbolizer_path = os.path.join(self.installdir, 'bin', 'llvm-symbolizer')
txt += self.module_generator.set_environment('ASAN_SYMBOLIZER_PATH', asan_symbolizer_path)
return txt
##
# Copyright 2009-2017 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# http://github.com/hpcugent/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
EasyBuild support for building and installing Doris, implemented as an easyblock
author: Kenneth Hoste (HPC-UGent)
"""
import os
from easybuild.easyblocks.generic.configuremake import ConfigureMake
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.filetools import change_dir, mkdir
from easybuild.tools.modules import get_software_root
from easybuild.tools.run import run_cmd_qa
class EB_Doris(ConfigureMake):
"""Support for building/installing Doris."""
def configure_step(self):
"""Custom configuration procedure for Doris."""
fftw = get_software_root('FFTW')
if fftw is None:
raise EasyBuildError("Required dependency FFTW is missing")
# create installation directory (and /bin subdirectory) early, make sure it doesn't get removed later
self.make_installdir()
mkdir(os.path.join(self.installdir, 'bin'))
self.cfg['keeppreviousinstall'] = True
# configure/build/install should be done from 'doris_core' subdirectory
change_dir(os.path.join(self.cfg['start_dir'], 'doris_core'))
qa = {
"===> Press enter to continue.": '',
"===> What is your C++ compiler? [g++]": os.getenv('CXX'),
"===> Do you have the FFTW library (y/n)? [n]": 'y',
"===> What is the path to the FFTW library (libfftw3f.a or libfftw3f.so)? []": os.path.join(fftw, 'lib'),
"===> What is the path to the FFTW include file (fftw3.h)? []": os.path.join(fftw, 'include'),
"===> Do you have the VECLIB library (y/n)? [n]": 'n',
#"===> Do you have the LAPACK library (y/n)? [n]": 'y',
#"===> What is the path to the LAPACK library liblapack.a? []": os.path.join(lapack, 'lib'),
"==> Do you have the LAPACK library (y/n)? [n]": 'n',
"===> Are you working on a Little Endian (X86 PC, Intel) machine (y/n)? [y]": 'y',
"===> Installation of Doris in directory: /usr/local/bin (y/n)? [y]": 'n',
"===> Enter installation directory (use absolute path):": os.path.join(self.installdir, 'bin'),
"===> Press enter to continue (CTRL-C to exit).": '',
}
std_qa = {
"===> Do you want to compile a more verbose DEBUG version \(y/n\)\? \[n\](.|\n)*expected results\)": 'n',
}
run_cmd_qa('./configure', qa, std_qa=std_qa, log_all=True, simple=True)
def build_step(self):
"""Custom build procedure for Doris."""
common_buildopts = self.cfg['buildopts']
# build Doris
change_dir(os.path.join(self.cfg['start_dir'], 'doris_core'))
super(EB_Doris, self).build_step()
# build SARtools
change_dir(os.path.join(self.cfg['start_dir'], 'sar_tools'))
self.cfg['buildopts'] = common_buildopts
self.cfg.update('buildopts', 'CC="%s"' % os.getenv('CXX'))
cflags = os.getenv('CXXFLAGS') + " -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"
self.cfg.update('buildopts', 'CFLAGS="%s"' % cflags)
super(EB_Doris, self).build_step()
# build ENVISAT_TOOLS
change_dir(os.path.join(self.cfg['start_dir'], 'envisat_tools'))
self.cfg['buildopts'] = common_buildopts
self.cfg.update('buildopts', 'CC="%s"' % os.getenv('CC'))
self.cfg.update('buildopts', 'CFLAGS="%s"' % os.getenv('CFLAGS'))
super(EB_Doris, self).build_step()
def install_step(self):
"""Custom build procedure for Doris."""
# install Doris
change_dir(os.path.join(self.cfg['start_dir'], 'doris_core'))
super(EB_Doris, self).install_step()
# install SARtools
self.cfg.update('installopts', 'INSTALL_DIR=%s' % os.path.join(self.installdir, 'bin'))
change_dir(os.path.join(self.cfg['start_dir'], 'sar_tools'))
super(EB_Doris, self).install_step()
# install ENVISAT_TOOLS
change_dir(os.path.join(self.cfg['start_dir'], 'envisat_tools'))
self.cfg.update('installopts', 'CC="%s"' % os.getenv('CC'))
self.cfg.update('installopts', 'CFLAGS="%s"' % os.getenv('CFLAGS'))
super(EB_Doris, self).install_step()
def sanity_check_step(self):
"""Custom sanity check for Doris."""
doris_bins = ['cpx2ps', 'doris', 'plotcpm', 'run']
sartools_bins = ['bkconvert', 'cpxfiddle', 'flapjack', 'floatmult', 'wrap']
envisat_tools_bins = ['envisat_dump_header', 'envisat_dump_data']
custom_paths = {
'files': [os.path.join('bin', x) for x in doris_bins + sartools_bins + envisat_tools_bins],
'dirs': [],
}
super(EB_Doris, self).sanity_check_step(custom_paths=custom_paths)
# #
# Copyright 2009-2016 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://vscentrum.be/nl/en),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# http://github.com/hpcugent/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
# #
"""
EasyBuild support for installing the Intel Math Kernel Library (MKL), implemented as an easyblock
@author: Stijn De Weirdt (Ghent University)
@author: Dries Verdegem (Ghent University)
@author: Kenneth Hoste (Ghent University)
@author: Pieter De Baets (Ghent University)
@author: Jens Timmerman (Ghent University)
@author: Ward Poelmans (Ghent University)
@author: Lumir Jasiok (IT4Innovations)
"""
import itertools
import os
import shutil
import tempfile
from distutils.version import LooseVersion
import easybuild.tools.environment as env
import easybuild.tools.toolchain as toolchain
from easybuild.easyblocks.generic.intelbase import IntelBase, ACTIVATION_NAME_2012, LICENSE_FILE_NAME_2012
from easybuild.framework.easyconfig import CUSTOM
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.filetools import rmtree2
from easybuild.tools.modules import get_software_root
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_shared_lib_ext
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'])
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'):
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'],
'FPATH': ['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'],
'FPATH': ['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'],
'FPATH': ['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']
cdftlibs = ['fftw2x_cdft']
if LooseVersion(self.version) >= LooseVersion('10.3'):
cdftlibs.append('fftw3x_cdft')
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 toolchain
# can't use toolchain.comp_family, because of dummy toolchain used when installing imkl
if get_software_root('icc') is None:
if get_software_root('GCC'):
compopt = 'compiler=gnu'
else:
raise EasyBuildError("Not using either Intel compilers nor GCC, "
"don't know how to build wrapper libs")
else:
compopt = 'compiler=intel'
for lib in fftw2libs + fftw3libs + cdftlibs:
buildopts = [compopt]
if lib in fftw3libs:
buildopts.append('install_to=$INSTALL_DIR')
elif lib in cdftlibs:
mpi_spec = None
# 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()
mpi_spec = mpi_spec_by_fam.get(mpi_fam)
self.log.debug("Determined MPI specification based on MPI toolchain component: %s" % mpi_spec)
else:
# can't use toolchain.mpi_family, because of dummy toolchain
if get_software_root('MPICH2') or get_software_root('MVAPICH2'):
mpi_spec = 'mpich2'
elif get_software_root('OpenMPI'):
mpi_spec = 'openmpi'
self.log.debug("Determined MPI specification based on loaded MPI module: %s" % mpi_spec)
if mpi_spec is not None:
buildopts.append('mpi=%s' % 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 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)
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:
if get_software_root('GCC'):
compsuff = '_gnu'
else:
raise EasyBuildError("Not using Intel/GCC, 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]
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:
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)
# #
# Copyright 2009-2017 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
# #
"""
EasyBuild support for installing the Intel MPI library, implemented as an easyblock
@author: Stijn De Weirdt (Ghent University)
@author: Dries Verdegem (Ghent University)
@author: Kenneth Hoste (Ghent University)
@author: Pieter De Baets (Ghent University)
@author: Jens Timmerman (Ghent University)
@author: Damian Alvarez (Forschungszentrum Juelich GmbH)
"""
import fileinput
import os
import sys
from distutils.version import LooseVersion
from easybuild.easyblocks.generic.intelbase import IntelBase, ACTIVATION_NAME_2012, LICENSE_FILE_NAME_2012
from easybuild.framework.easyconfig import CUSTOM
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.filetools import apply_regex_substitutions
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_shared_lib_ext
class EB_impi(IntelBase):
"""
Support for installing Intel MPI library
"""
@staticmethod
def extra_options():
extra_vars = {
'set_mpi_wrappers_compiler': [False, 'Override default compiler used by MPI wrapper commands', CUSTOM],
'set_mpi_wrapper_aliases_gcc': [False, 'Set compiler for mpigcc/mpigxx via aliases', CUSTOM],
'set_mpi_wrapper_aliases_intel': [False, 'Set compiler for mpiicc/mpiicpc/mpiifort via aliases', CUSTOM],
'set_mpi_wrappers_all': [False, 'Set (default) compiler for all MPI wrapper commands', CUSTOM],
}
return IntelBase.extra_options(extra_vars)
def prepare_step(self, *args, **kwargs):
if LooseVersion(self.version) >= LooseVersion('2017.2.174'):
kwargs['requires_runtime_license'] = False
super(EB_impi, self).prepare_step(*args, **kwargs)
else:
super(EB_impi, self).prepare_step(*args, **kwargs)
def install_step(self):
"""
Actual installation
- create silent cfg file
- execute command
"""
impiver = LooseVersion(self.version)
if impiver >= LooseVersion('4.0.1'):
# impi starting from version 4.0.1.x uses standard installation procedure.
silent_cfg_names_map = {}
if impiver < LooseVersion('4.1.1'):
# since impi v4.1.1, silent.cfg has been slightly changed to be 'more standard'
silent_cfg_names_map.update({
'activation_name': ACTIVATION_NAME_2012,
'license_file_name': LICENSE_FILE_NAME_2012,
})
super(EB_impi, self).install_step(silent_cfg_names_map=silent_cfg_names_map)
# impi v4.1.1 and v5.0.1 installers create impi/<version> subdir, so stuff needs to be moved afterwards
if impiver == LooseVersion('4.1.1.036') or impiver >= LooseVersion('5.0.1.035'):
super(EB_impi, self).move_after_install()
else:
# impi up until version 4.0.0.x uses custom installation procedure.
silent = \
"""
[mpi]
INSTALLDIR=%(ins)s
LICENSEPATH=%(lic)s
INSTALLMODE=NONRPM
INSTALLUSER=NONROOT
UPDATE_LD_SO_CONF=NO
PROCEED_WITHOUT_PYTHON=yes
AUTOMOUNTED_CLUSTER=yes
EULA=accept
[mpi-rt]
INSTALLDIR=%(ins)s
LICENSEPATH=%(lic)s
INSTALLMODE=NONRPM
INSTALLUSER=NONROOT
UPDATE_LD_SO_CONF=NO
PROCEED_WITHOUT_PYTHON=yes
AUTOMOUNTED_CLUSTER=yes
EULA=accept
""" % {'lic': self.license_file, 'ins': self.installdir}
# already in correct directory
silentcfg = os.path.join(os.getcwd(), "silent.cfg")
try:
f = open(silentcfg, 'w')
f.write(silent)
f.close()
except:
raise EasyBuildError("Writing silent cfg file %s failed.", silent)
self.log.debug("Contents of %s: %s" % (silentcfg, silent))
tmpdir = os.path.join(os.getcwd(), self.version, 'mytmpdir')
try:
os.makedirs(tmpdir)
except:
raise EasyBuildError("Directory %s can't be created", tmpdir)
cmd = "./install.sh --tmp-dir=%s --silent=%s" % (tmpdir, silentcfg)
run_cmd(cmd, log_all=True, simple=True)
def post_install_step(self):
"""Custom post install step for IMPI, fix broken env scripts after moving installed files."""
super(EB_impi, self).post_install_step()
impiver = LooseVersion(self.version)
if impiver == LooseVersion('4.1.1.036') or impiver >= LooseVersion('5.0.1.035'):
if impiver >= LooseVersion('2018.0.128'):
script_paths = [os.path.join('intel64', 'bin')]
else:
script_paths = [os.path.join('intel64', 'bin'), os.path.join('mic', 'bin')]
# fix broken env scripts after the move
regex_subs = [(r"^setenv I_MPI_ROOT.*", r"setenv I_MPI_ROOT %s" % self.installdir)]
for script in [os.path.join(script_path,'mpivars.csh') for script_path in script_paths]:
apply_regex_substitutions(os.path.join(self.installdir, script), regex_subs)
regex_subs = [(r"^I_MPI_ROOT=.*", r"I_MPI_ROOT=%s; export I_MPI_ROOT" % self.installdir)]
for script in [os.path.join(script_path,'mpivars.sh') for script_path in script_paths]:
apply_regex_substitutions(os.path.join(self.installdir, script), regex_subs)
def sanity_check_step(self):
"""Custom sanity check paths for IMPI."""
suff = "64"
if self.cfg['m32']:
suff = ""
mpi_mods = ['mpi.mod']
if LooseVersion(self.version) > LooseVersion('4.0'):
mpi_mods.extend(["mpi_base.mod", "mpi_constants.mod", "mpi_sizeofs.mod"])
custom_paths = {
'files': ["bin%s/mpi%s" % (suff, x) for x in ["icc", "icpc", "ifort"]] +
["include%s/mpi%s.h" % (suff, x) for x in ["cxx", "f", "", "o", "of"]] +
["include%s/%s" % (suff, x) for x in ["i_malloc.h"] + mpi_mods] +
["lib%s/libmpi.%s" % (suff, get_shared_lib_ext()), "lib%s/libmpi.a" % suff],
'dirs': [],
}
super(EB_impi, self).sanity_check_step(custom_paths=custom_paths)
def make_module_req_guess(self):
"""
A dictionary of possible directories to look for
"""
if self.cfg['m32']:
lib_dirs = ['lib', 'lib/ia32', 'ia32/lib']
include_dirs = ['include']
return {
'PATH': ['bin', 'bin/ia32', 'ia32/bin'],
'LD_LIBRARY_PATH': lib_dirs,
'LIBRARY_PATH': lib_dirs,
'CPATH': include_dirs,
'MIC_LD_LIBRARY_PATH' : ['mic/lib'],
}
else:
lib_dirs = ['lib/em64t', 'lib64']
include_dirs = ['include64']
return {
'PATH': ['bin/intel64', 'bin64'],
'LD_LIBRARY_PATH': lib_dirs,
'LIBRARY_PATH': lib_dirs,
'CPATH': include_dirs,
'MIC_LD_LIBRARY_PATH' : ['mic/lib'],
}
def make_module_extra(self):
"""Overwritten from Application to add extra txt"""
txt = super(EB_impi, self).make_module_extra()
txt += self.module_generator.set_environment('I_MPI_ROOT', self.installdir)
if self.cfg['set_mpi_wrappers_compiler'] or self.cfg['set_mpi_wrappers_all']:
for var in ['CC', 'CXX', 'F77', 'F90', 'FC']:
if var == 'FC':
# $FC isn't defined by EasyBuild framework, so use $F90 instead
src_var = 'F90'
else:
src_var = var
target_var = 'I_MPI_%s' % var
val = os.getenv(src_var)
if val:
txt += self.module_generator.set_environment(target_var, val)
else:
raise EasyBuildError("Environment variable $%s not set, can't define $%s", src_var, target_var)
if self.cfg['set_mpi_wrapper_aliases_gcc'] or self.cfg['set_mpi_wrappers_all']:
# force mpigcc/mpigxx to use GCC compilers, as would be expected based on their name
txt += self.module_generator.set_alias('mpigcc', 'mpigcc -cc=gcc')
txt += self.module_generator.set_alias('mpigxx', 'mpigxx -cxx=g++')
if self.cfg['set_mpi_wrapper_aliases_intel'] or self.cfg['set_mpi_wrappers_all']:
# do the same for mpiicc/mpiipc/mpiifort to be consistent, even if they may not exist
txt += self.module_generator.set_alias('mpiicc', 'mpiicc -cc=icc')
txt += self.module_generator.set_alias('mpiicpc', 'mpiicpc -cxx=icpc')
# -fc also works, but -f90 takes precedence
txt += self.module_generator.set_alias('mpiifort', 'mpiifort -f90=ifort')
return txt
##
# Copyright 2009-2017 Ghent University
#
# This file is part of EasyBuild,
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
# with support of Ghent University (http://ugent.be/hpc),
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
#
# https://github.com/easybuilders/easybuild
#
# EasyBuild is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation v2.
#
# EasyBuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
##
"""
EasyBuild support for Trilinos, implemented as an easyblock
@author: Kenneth Hoste (Ghent University)
"""
import os
import re
from distutils.version import LooseVersion
import easybuild.tools.toolchain as toolchain
from easybuild.easyblocks.generic.cmakemake import CMakeMake
from easybuild.framework.easyconfig import CUSTOM
from easybuild.tools.build_log import EasyBuildError
from easybuild.tools.modules import get_software_root
class EB_Trilinos(CMakeMake):
"""Support for building Trilinos."""
# see http://trilinos.sandia.gov/Trilinos10CMakeQuickstart.txt
@staticmethod
def extra_options():
"""Add extra config options specific to Trilinos."""
extra_vars = {
'shared_libs': [False, "Build shared libs; if False, build static libs", CUSTOM],
'openmp': [True, "Enable OpenMP support", CUSTOM],
'all_exts': [True, "Enable all Trilinos packages", CUSTOM],
'skip_exts': [[], "List of Trilinos packages to skip", CUSTOM],
'verbose': [False, "Configure for verbose output", CUSTOM],
}
return CMakeMake.extra_options(extra_vars)
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))
# OpenMP
if self.cfg['openmp']:
self.cfg.update('configopts', "-DTrilinos_ENABLE_OpenMP:BOOL=ON")
# MPI
if self.toolchain.options.get('usempi', None):
self.cfg.update('configopts', "-DTPL_ENABLE_MPI:BOOL=ON")
# shared libraries
if self.cfg['shared_libs']:
self.cfg.update('configopts', "-DBUILD_SHARED_LIBS:BOOL=ON")
else:
self.cfg.update('configopts', "-DBUILD_SHARED_LIBS:BOOL=OFF")
# release or debug get_version
if self.toolchain.options['debug']:
self.cfg.update('configopts', "-DCMAKE_BUILD_TYPE:STRING=DEBUG")
else:
self.cfg.update('configopts', "-DCMAKE_BUILD_TYPE:STRING=RELEASE")
# 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))
libs = os.getenv('%s_MT_STATIC_LIBS' % dep).split(',')
lib_names = ';'.join([lib_re.search(l).group(1) for l 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))
# UMFPACK is part of SuiteSparse
suitesparse = get_software_root('SuiteSparse')
if suitesparse:
self.cfg.update('configopts', "-DTPL_ENABLE_UMFPACK:BOOL=ON")
incdirs, libdirs, libnames = [], [], []
for lib in ["UMFPACK", "CHOLMOD", "COLAMD", "AMD"]:
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')
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))
# 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 = 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
try:
build_dir = "BUILD"
os.mkdir(build_dir)
os.chdir(build_dir)
except OSError, err:
raise EasyBuildError("Failed to create and move into build directory: %s", err)
# configure using cmake
super(EB_Trilinos, self).configure_step(srcdir="..")
def build_step(self):
"""Build with make (verbose logging enabled)."""
super(EB_Trilinos, self).build_step(verbose=True)
def sanity_check_step(self):
"""Custom sanity check for Trilinos."""
# selection of libraries
libs = ["Amesos", "Anasazi", "AztecOO", "Belos", "Epetra", "Galeri",
"GlobiPack", "Ifpack", "Intrepid", "Isorropia", "Kokkos",
"Komplex", "LOCA", "Mesquite", "ML", "Moertel", "MOOCHO", "NOX",
"Pamgen", "RTOp", "Rythmos", "Sacado", "Shards", "Stratimikos",
"Teuchos", "Tpetra", "Triutils", "Zoltan"]
libs = [l for l in libs if not l in self.cfg['skip_exts']]
# Teuchos was refactored in 11.2
if LooseVersion(self.version) >= LooseVersion('11.2') and 'Teuchos' in libs:
libs.remove('Teuchos')
libs.extend(['teuchoscomm', 'teuchoscore', 'teuchosnumerics', 'teuchosparameterlist', 'teuchosremainder'])
# Kokkos was refactored in 12.x, check for libkokkoscore.a rather than libkokkos.a
if LooseVersion(self.version) >= LooseVersion('12') and 'Kokkos' in libs:
libs.remove('Kokkos')
libs.append('kokkoscore')
if LooseVersion(self.version) >= LooseVersion('12.10') and 'Galeri' in libs:
libs.remove('Galeri')
libs.append('galeri-epetra')
libs.append('galeri-xpetra')
custom_paths = {
'files': [os.path.join('lib', 'lib%s.a' % x.lower()) for x in libs],
'dirs': ['bin', 'include']
}
super(EB_Trilinos, self).sanity_check_step(custom_paths=custom_paths)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment