Skip to content

Implementing a new LLVM based toolchain #4914

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
187 changes: 187 additions & 0 deletions easybuild/toolchains/compiler/llvm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
##
# Copyright 2013-2025 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/>.
##
"""
EasyBuild support for Clang + Flang compiler toolchain.

Authors:

* Dmitri Gribenko (National Technical University of Ukraine "KPI")
* Davide Grassano (CECAM EPFL)
"""

from easybuild.tools import LooseVersion
import easybuild.tools.systemtools as systemtools
from easybuild.tools.toolchain.compiler import Compiler, DEFAULT_OPT_LEVEL
from easybuild.tools.toolchain.toolchain import SYSTEM_TOOLCHAIN_NAME

TC_CONSTANT_LLVM = "LLVM"


class LLVM(Compiler):
"""Compiler toolchain with Clang and GFortran compilers."""
# NAME = 'LLVMcore'
# COMPILER_MODULE_NAME = [NAME]
COMPILER_FAMILY = TC_CONSTANT_LLVM
SUBTOOLCHAIN = SYSTEM_TOOLCHAIN_NAME

# List of flags that are supported by Clang but not yet by Flang and should be filtered out
# The element of the list are tuples with the following structure:
# (min_version, max_version, [list of flags])
# Where min_version and max_version are strings representing a left-inclusive and right-exclusive version range,
# [min_version, max_version) respectively.
# This is used to specify general `clang`-accepted flags and remove them from `flang` compiler flags if
# not supported for a particular version of LLVM
FLANG_UNSUPPORTED_VARS = [
('19', '21', [
'-fmath-errno', '-fno-math-errno',
'-fslp-vectorize',
'-fvectorize', '-fno-vectorize',
'-fno-unsafe-math-optimizations',
])
]

FORTRAN_FLAGS = ['FCFLAGS', 'FFLAGS', 'F90FLAGS']

COMPILER_UNIQUE_OPTS = {
'loop-vectorize': (False, "Loop vectorization"),
'basic-block-vectorize': (False, "Basic block vectorization"),

# https://github.com/madler/zlib/issues/856
'lld_undefined_version': (True, "-Wl,--undefined-version - Allow unused version in version script"),
'no_unused_args': (
True,
(
"-Wno-unused-command-line-argument - Avoid some failures in CMake correctly recognizing "
"feature due to linker warnings"
)
),
'no_int_conversion_error': (
True,
"-Wno-error=int-conversion - Avoid some failures that are normally ignored by GCC"
),
}

COMPILER_UNIQUE_OPTION_MAP = {
'unroll': '-funroll-loops',
'loop-vectorize': ['-fvectorize'],
'basic-block-vectorize': ['-fslp-vectorize'],
'optarch': '',
# 'optarch': '-march=native',
# Clang's options do not map well onto these precision modes. The flags enable and disable certain classes of
# optimizations.
#
# -fassociative-math: allow re-association of operands in series of floating-point operations, violates the
# ISO C and C++ language standard by possibly changing computation result.
# -freciprocal-math: allow optimizations to use the reciprocal of an argument rather than perform division.
# -fsigned-zeros: do not allow optimizations to treat the sign of a zero argument or result as insignificant.
# -fhonor-infinities: disallow optimizations to assume that arguments and results are not +/- Infs.
# -fhonor-nans: disallow optimizations to assume that arguments and results are not +/- NaNs.
# -ffinite-math-only: allow optimizations for floating-point arithmetic that assume that arguments and results
# are not NaNs or +-Infs (equivalent to -fno-honor-nans -fno-honor-infinities)
# -funsafe-math-optimizations: allow unsafe math optimizations (implies -fassociative-math, -fno-signed-zeros,
# -freciprocal-math).
# -ffast-math: an umbrella flag that enables all optimizations listed above, provides preprocessor macro
# __FAST_MATH__.
#
# Using -fno-fast-math is equivalent to disabling all individual optimizations, see
# http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?view=markup (lines 2100 and following)
#
# 'strict', 'precise' and 'defaultprec' are all ISO C++ and IEEE complaint, but we explicitly specify details
# flags for strict and precise for robustness against future changes.
'strict': ['-fno-fast-math'],
'precise': ['-fno-unsafe-math-optimizations'],
'defaultprec': [],
'loose': ['-ffast-math', '-fno-unsafe-math-optimizations'],
'veryloose': ['-ffast-math'],
'vectorize': {False: '-fno-vectorize', True: '-fvectorize'},
DEFAULT_OPT_LEVEL: ['-O2'],

'lld_undefined_version': ['-Wl,--undefined-version'],
'no_unused_args': ['-Wno-unused-command-line-argument'],
'no_int_conversion_error': ['-Wno-error=int-conversion'],
}

COMPILER_OPTIONS = [
'lld_undefined_version',
]

# Options only available for Clang compiler
COMPILER_C_OPTIONS = [
'no_unused_args',
'no_int_conversion_error'
]

# Options only available for Flang compiler
COMPILER_F_OPTIONS = []

# used when 'optarch' toolchain option is enabled (and --optarch is not specified)
COMPILER_OPTIMAL_ARCHITECTURE_OPTION = {
(systemtools.POWER, systemtools.POWER): '-mcpu=native', # no support for march=native on POWER
(systemtools.POWER, systemtools.POWER_LE): '-mcpu=native', # no support for march=native on POWER
(systemtools.X86_64, systemtools.AMD): '-march=native',
(systemtools.X86_64, systemtools.INTEL): '-march=native',
}
# used with --optarch=GENERIC
COMPILER_GENERIC_OPTION = {
(systemtools.RISCV64, systemtools.RISCV): '-march=rv64gc -mabi=lp64d', # default for -mabi is system-dependent
(systemtools.X86_64, systemtools.AMD): '-march=x86-64 -mtune=generic',
(systemtools.X86_64, systemtools.INTEL): '-march=x86-64 -mtune=generic',
}

COMPILER_CC = 'clang'
COMPILER_CXX = 'clang++'
COMPILER_C_UNIQUE_OPTIONS = []

COMPILER_F77 = 'flang'
COMPILER_F90 = 'flang'
COMPILER_FC = 'flang'
COMPILER_F_UNIQUE_OPTIONS = []

LIB_MULTITHREAD = ['pthread']
LIB_MATH = ['m']

def _set_compiler_flags(self):
super()._set_compiler_flags()

unsupported_fortran_flags = None
for v_min, v_max, flags in self.FLANG_UNSUPPORTED_VARS:
if LooseVersion(self.version) >= LooseVersion(v_min) and LooseVersion(self.version) < LooseVersion(v_max):
unsupported_fortran_flags = flags
break
else:
self.log.debug("No unsupported flags found for LLVM version %s", self.version)

if unsupported_fortran_flags is not None:
self.log.debug(
f"Ensuring usupported Fortran flags `{unsupported_fortran_flags}` are removed from variables"
)
for key, lst in self.variables.items():
if key not in self.FORTRAN_FLAGS:
continue
for item in lst:
item.try_remove(unsupported_fortran_flags)
44 changes: 44 additions & 0 deletions easybuild/toolchains/lfbf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
##
# Copyright 2021-2025 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 gfbf compiler toolchain (includes GCC, FlexiBLAS and FFTW)

Authors:

* Kenneth Hoste (Ghent University)
* Bart Oldeman (McGill University, Calcul Quebec, Compute Canada)
* Davide Grassano (CECAM EPFL)
"""

from easybuild.toolchains.llvm import LLVMtc
from easybuild.toolchains.fft.fftw import Fftw
from easybuild.toolchains.linalg.flexiblas import FlexiBLAS


class Lfbf(LLVMtc, FlexiBLAS, Fftw):
"""Compiler toolchain with GCC, FlexiBLAS and FFTW."""
NAME = 'lfbf'
SUBTOOLCHAIN = LLVMtc.NAME
OPTIONAL = True
90 changes: 90 additions & 0 deletions easybuild/toolchains/lfoss.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
##
# Copyright 2013-2025 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 foss compiler toolchain (includes GCC, OpenMPI, OpenBLAS, LAPACK, ScaLAPACK and FFTW).

Authors:

* Kenneth Hoste (Ghent University)
* Davide Grassano (CECAM EPFL)
"""
from easybuild.toolchains.lompi import Lompi
from easybuild.toolchains.lfbf import Lfbf
from easybuild.toolchains.lolf import Lolf
from easybuild.toolchains.fft.fftw import Fftw
from easybuild.toolchains.linalg.flexiblas import FlexiBLAS
from easybuild.toolchains.linalg.scalapack import ScaLAPACK
from easybuild.tools import LooseVersion


class LFoss(Lompi, FlexiBLAS, ScaLAPACK, Fftw):
"""Compiler toolchain with GCC, OpenMPI, FlexiBLAS, ScaLAPACK and FFTW."""
NAME = 'lfoss'
SUBTOOLCHAIN = [
Lompi.NAME,
Lolf.NAME,
Lfbf.NAME
]

def __init__(self, *args, **kwargs):
"""Toolchain constructor."""
super(LFoss, self).__init__(*args, **kwargs)

# need to transform a version like '2018b' with something that is safe to compare with '2019'
# comparing subversions that include letters causes TypeErrors in Python 3
# 'a' is assumed to be equivalent with '.01' (January), and 'b' with '.07' (June) (good enough for this purpose)
version = self.version.replace('a', '.01').replace('b', '.07')

self.looseversion = LooseVersion(version)

constants = ('BLAS_MODULE_NAME', 'BLAS_LIB', 'BLAS_LIB_MT', 'BLAS_FAMILY',
'LAPACK_MODULE_NAME', 'LAPACK_IS_BLAS', 'LAPACK_FAMILY')

for constant in constants:
setattr(self, constant, getattr(FlexiBLAS, constant))

def banned_linked_shared_libs(self):
"""
List of shared libraries (names, file names, paths) which are
not allowed to be linked in any installed binary/library.
"""
res = []
res.extend(Lompi.banned_linked_shared_libs(self))
res.extend(FlexiBLAS.banned_linked_shared_libs(self))
res.extend(ScaLAPACK.banned_linked_shared_libs(self))
res.extend(Fftw.banned_linked_shared_libs(self))

return res

def is_deprecated(self):
"""Return whether or not this toolchain is deprecated."""

# lfoss toolchains older than 2023b should not exist (need GCC >= 13)
if self.looseversion < LooseVersion('2023'):
deprecated = True
else:
deprecated = False

return deprecated
45 changes: 45 additions & 0 deletions easybuild/toolchains/llvm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
##
# Copyright 2013-2025 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/>.
##
"""
EasyBuild support for Clang + Flang compiler toolchain.

Authors:

* Davide Grassano (CECAM EPFL)
"""

from easybuild.toolchains.gcccore import GCCcore
from easybuild.toolchains.compiler.llvm import LLVM
from easybuild.tools.toolchain.toolchain import SYSTEM_TOOLCHAIN_NAME


class LLVMtc(LLVM):
"""Compiler toolchain with Clang and Flang compilers."""
NAME = 'LLVMtc' # Using `...tc` to distinguish toolchain from package
COMPILER_MODULE_NAME = [NAME]
SUBTOOLCHAIN = [GCCcore.NAME, SYSTEM_TOOLCHAIN_NAME]
Loading
Loading