Skip to content

Commit 7515263

Browse files
authored
Merge pull request #4914 from Crivella/exp-LLVMtoolchain
Implementing a new LLVM based toolchain
2 parents 9a184b2 + d95636f commit 7515263

File tree

11 files changed

+548
-6
lines changed

11 files changed

+548
-6
lines changed

easybuild/scripts/rpath_args.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@
3737
import re
3838
import sys
3939

40+
LINKER_COMMANDS = (
41+
# binutils
42+
'ld', 'ld.gold', 'ld.bfd',
43+
# LLVM
44+
'lld', 'ld.lld', 'ld64.lld',
45+
)
46+
4047

4148
def is_new_existing_path(new_path, paths):
4249
"""
@@ -80,7 +87,7 @@ def add_rpath_flag(lib_path, rpath_filter, rpath_lib_paths, cmd_args_rpath, ldfl
8087
args = sys.argv[4:]
8188

8289
# determine whether or not to use -Wl to pass options to the linker based on name of command
83-
if cmd in ['ld', 'ld.gold', 'ld.bfd']:
90+
if cmd in LINKER_COMMANDS:
8491
ldflag_prefix = ''
8592
else:
8693
ldflag_prefix = '-Wl,'
@@ -116,6 +123,11 @@ def add_rpath_flag(lib_path, rpath_filter, rpath_lib_paths, cmd_args_rpath, ldfl
116123
add_rpath_args = False
117124
cmd_args.append(arg)
118125

126+
# preprocess only mode, no linking is done
127+
elif arg == '-E' and cmd not in LINKER_COMMANDS:
128+
add_rpath_args = False
129+
cmd_args.append(arg)
130+
119131
# compiler options like "-x c++header" imply no linking is done (similar to -c),
120132
# so then we must not inject -Wl,-rpath option since they *enable* linking;
121133
# see https://github.com/easybuilders/easybuild-framework/issues/3371
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
##
2+
# Copyright 2013-2025 Ghent University
3+
#
4+
# This file is triple-licensed under GPLv2 (see below), MIT, and
5+
# BSD three-clause licenses.
6+
#
7+
# This file is part of EasyBuild,
8+
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
9+
# with support of Ghent University (http://ugent.be/hpc),
10+
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
11+
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
12+
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
13+
#
14+
# https://github.com/easybuilders/easybuild
15+
#
16+
# EasyBuild is free software: you can redistribute it and/or modify
17+
# it under the terms of the GNU General Public License as published by
18+
# the Free Software Foundation v2.
19+
#
20+
# EasyBuild is distributed in the hope that it will be useful,
21+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
# GNU General Public License for more details.
24+
#
25+
# You should have received a copy of the GNU General Public License
26+
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
27+
##
28+
"""
29+
EasyBuild support for Clang + Flang compiler toolchain.
30+
31+
Authors:
32+
33+
* Dmitri Gribenko (National Technical University of Ukraine "KPI")
34+
* Davide Grassano (CECAM EPFL)
35+
"""
36+
37+
from easybuild.tools import LooseVersion
38+
import easybuild.tools.systemtools as systemtools
39+
from easybuild.tools.toolchain.compiler import Compiler, DEFAULT_OPT_LEVEL
40+
from easybuild.tools.toolchain.toolchain import SYSTEM_TOOLCHAIN_NAME
41+
42+
TC_CONSTANT_LLVM = "LLVM"
43+
44+
45+
class LLVMCompilers(Compiler):
46+
"""Compiler toolchain with LLVM compilers (clang/flang)."""
47+
COMPILER_FAMILY = TC_CONSTANT_LLVM
48+
SUBTOOLCHAIN = SYSTEM_TOOLCHAIN_NAME
49+
50+
# List of flags that are supported by Clang but not yet by Flang and should be filtered out
51+
# The element of the list are tuples with the following structure:
52+
# (min_version, max_version, [list of flags])
53+
# Where min_version and max_version are strings representing a left-inclusive and right-exclusive version range,
54+
# [min_version, max_version) respectively.
55+
# This is used to specify general `clang`-accepted flags and remove them from `flang` compiler flags if
56+
# not supported for a particular version of LLVM
57+
FLANG_UNSUPPORTED_VARS = [
58+
('19', '21', [
59+
'-fmath-errno', '-fno-math-errno',
60+
'-fslp-vectorize',
61+
'-fvectorize', '-fno-vectorize',
62+
'-fno-unsafe-math-optimizations',
63+
]),
64+
('21', '22', [
65+
'-fmath-errno', '-fno-math-errno',
66+
'-fno-unsafe-math-optimizations',
67+
]),
68+
]
69+
70+
FORTRAN_FLAGS = ['FCFLAGS', 'FFLAGS', 'F90FLAGS']
71+
72+
COMPILER_UNIQUE_OPTS = {
73+
'loop-vectorize': (False, "Loop vectorization"),
74+
'basic-block-vectorize': (False, "Basic block vectorization"),
75+
76+
# https://github.com/madler/zlib/issues/856
77+
'lld_undefined_version': (False, "-Wl,--undefined-version - Allow unused version in version script"),
78+
'no_unused_args': (
79+
True,
80+
"-Wno-unused-command-line-argument - Avoid some failures in CMake correctly recognizing "
81+
"feature due to linker warnings"
82+
),
83+
'no_int_conversion_error': (
84+
True,
85+
"-Wno-error=int-conversion - Avoid some failures that are normally ignored by GCC"
86+
),
87+
}
88+
89+
COMPILER_UNIQUE_OPTION_MAP = {
90+
'unroll': '-funroll-loops',
91+
'loop-vectorize': ['-fvectorize'],
92+
'basic-block-vectorize': ['-fslp-vectorize'],
93+
# Clang's options do not map well onto these precision modes. The flags enable and disable certain classes of
94+
# optimizations.
95+
#
96+
# -fassociative-math: allow re-association of operands in series of floating-point operations, violates the
97+
# ISO C and C++ language standard by possibly changing computation result.
98+
# -freciprocal-math: allow optimizations to use the reciprocal of an argument rather than perform division.
99+
# -fsigned-zeros: do not allow optimizations to treat the sign of a zero argument or result as insignificant.
100+
# -fhonor-infinities: disallow optimizations to assume that arguments and results are not +/- Infs.
101+
# -fhonor-nans: disallow optimizations to assume that arguments and results are not +/- NaNs.
102+
# -ffinite-math-only: allow optimizations for floating-point arithmetic that assume that arguments and results
103+
# are not NaNs or +-Infs (equivalent to -fno-honor-nans -fno-honor-infinities)
104+
# -funsafe-math-optimizations: allow unsafe math optimizations (implies -fassociative-math, -fno-signed-zeros,
105+
# -freciprocal-math).
106+
# -ffast-math: an umbrella flag that enables all optimizations listed above, provides preprocessor macro
107+
# __FAST_MATH__.
108+
#
109+
# Using -fno-fast-math is equivalent to disabling all individual optimizations, see
110+
# http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?view=markup (lines 2100 and following)
111+
#
112+
# 'strict', 'precise' and 'defaultprec' are all ISO C++ and IEEE complaint, but we explicitly specify details
113+
# flags for strict and precise for robustness against future changes.
114+
'strict': ['-fno-fast-math'],
115+
'precise': ['-fno-unsafe-math-optimizations'],
116+
'defaultprec': [],
117+
'loose': ['-ffast-math', '-fno-unsafe-math-optimizations'],
118+
'veryloose': ['-ffast-math'],
119+
'vectorize': {False: '-fno-vectorize', True: '-fvectorize'},
120+
DEFAULT_OPT_LEVEL: ['-O2'],
121+
122+
'lld_undefined_version': ['-Wl,--undefined-version'],
123+
'no_unused_args': ['-Wno-unused-command-line-argument'],
124+
'no_int_conversion_error': ['-Wno-error=int-conversion'],
125+
}
126+
127+
# Ensure that compiler options only appear once, so that arguments do not appear multiple times when compiling.
128+
COMPILER_OPTIONS = list({
129+
*(Compiler.COMPILER_OPTIONS or []),
130+
'lld_undefined_version'
131+
})
132+
133+
# Options only available for Clang compiler
134+
COMPILER_C_UNIQUE_OPTIONS = list({
135+
*(Compiler.COMPILER_C_UNIQUE_OPTIONS or []),
136+
'no_unused_args',
137+
'no_int_conversion_error'
138+
})
139+
140+
# Options only available for Flang compiler
141+
COMPILER_F_UNIQUE_OPTIONS = Compiler.COMPILER_F_UNIQUE_OPTIONS
142+
143+
# used when 'optarch' toolchain option is enabled (and --optarch is not specified)
144+
COMPILER_OPTIMAL_ARCHITECTURE_OPTION = {
145+
**(Compiler.COMPILER_OPTIMAL_ARCHITECTURE_OPTION or {}),
146+
(systemtools.AARCH64, systemtools.ARM): '-march=native',
147+
(systemtools.POWER, systemtools.POWER): '-mcpu=native', # no support for march=native on POWER
148+
(systemtools.POWER, systemtools.POWER_LE): '-mcpu=native', # no support for march=native on POWER
149+
(systemtools.X86_64, systemtools.AMD): '-march=native',
150+
(systemtools.X86_64, systemtools.INTEL): '-march=native',
151+
}
152+
153+
# used with --optarch=GENERIC
154+
COMPILER_GENERIC_OPTION = {
155+
**(Compiler.COMPILER_GENERIC_OPTION or {}),
156+
(systemtools.AARCH64, systemtools.ARM): '-mcpu=generic -mtune=generic',
157+
(systemtools.RISCV64, systemtools.RISCV): '-march=rv64gc -mabi=lp64d', # default for -mabi is system-dependent
158+
(systemtools.X86_64, systemtools.AMD): '-march=x86-64 -mtune=generic',
159+
(systemtools.X86_64, systemtools.INTEL): '-march=x86-64 -mtune=generic',
160+
}
161+
162+
COMPILER_CC = 'clang'
163+
COMPILER_CXX = 'clang++'
164+
165+
COMPILER_F77 = 'flang'
166+
COMPILER_F90 = 'flang'
167+
COMPILER_FC = 'flang'
168+
169+
LINKERS = ('lld', 'ld.lld', 'ld64.lld')
170+
171+
LIB_MULTITHREAD = ['pthread']
172+
LIB_MATH = ['m']
173+
174+
def _set_compiler_flags(self):
175+
super()._set_compiler_flags()
176+
177+
unsupported_fortran_flags = None
178+
for v_min, v_max, flags in self.FLANG_UNSUPPORTED_VARS:
179+
if LooseVersion(self.version) >= LooseVersion(v_min) and LooseVersion(self.version) < LooseVersion(v_max):
180+
unsupported_fortran_flags = flags
181+
break
182+
else:
183+
self.log.debug("No unsupported flags found for LLVM version %s", self.version)
184+
185+
if unsupported_fortran_flags is not None:
186+
self.log.debug(
187+
f"Ensuring unsupported Fortran flags `{unsupported_fortran_flags}` are removed from variables"
188+
)
189+
for key, lst in self.variables.items():
190+
if key not in self.FORTRAN_FLAGS:
191+
continue
192+
for item in lst:
193+
item.try_remove(unsupported_fortran_flags)

easybuild/toolchains/lfbf.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
##
2+
# Copyright 2021-2025 Ghent University
3+
#
4+
# This file is part of EasyBuild,
5+
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
6+
# with support of Ghent University (http://ugent.be/hpc),
7+
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
8+
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
9+
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
10+
#
11+
# https://github.com/easybuilders/easybuild
12+
#
13+
# EasyBuild is free software: you can redistribute it and/or modify
14+
# it under the terms of the GNU General Public License as published by
15+
# the Free Software Foundation v2.
16+
#
17+
# EasyBuild is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
24+
##
25+
"""
26+
EasyBuild support for gfbf compiler toolchain (includes GCC, FlexiBLAS and FFTW)
27+
28+
Authors:
29+
30+
* Kenneth Hoste (Ghent University)
31+
* Bart Oldeman (McGill University, Calcul Quebec, Compute Canada)
32+
* Davide Grassano (CECAM EPFL)
33+
"""
34+
35+
from easybuild.toolchains.llvm_compilers import LLVMCompilersToolchain
36+
from easybuild.toolchains.fft.fftw import Fftw
37+
from easybuild.toolchains.linalg.flexiblas import FlexiBLAS
38+
39+
40+
class Lfbf(LLVMCompilersToolchain, FlexiBLAS, Fftw):
41+
"""Compiler toolchain with GCC, FlexiBLAS and FFTW."""
42+
NAME = 'lfbf'
43+
SUBTOOLCHAIN = LLVMCompilersToolchain.NAME
44+
OPTIONAL = True

easybuild/toolchains/lfoss.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
##
2+
# Copyright 2013-2025 Ghent University
3+
#
4+
# This file is part of EasyBuild,
5+
# originally created by the HPC team of Ghent University (http://ugent.be/hpc/en),
6+
# with support of Ghent University (http://ugent.be/hpc),
7+
# the Flemish Supercomputer Centre (VSC) (https://www.vscentrum.be),
8+
# Flemish Research Foundation (FWO) (http://www.fwo.be/en)
9+
# and the Department of Economy, Science and Innovation (EWI) (http://www.ewi-vlaanderen.be/en).
10+
#
11+
# https://github.com/easybuilders/easybuild
12+
#
13+
# EasyBuild is free software: you can redistribute it and/or modify
14+
# it under the terms of the GNU General Public License as published by
15+
# the Free Software Foundation v2.
16+
#
17+
# EasyBuild is distributed in the hope that it will be useful,
18+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+
# GNU General Public License for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with EasyBuild. If not, see <http://www.gnu.org/licenses/>.
24+
##
25+
"""
26+
EasyBuild support for foss compiler toolchain (includes GCC, OpenMPI, OpenBLAS, LAPACK, ScaLAPACK and FFTW).
27+
28+
Authors:
29+
30+
* Kenneth Hoste (Ghent University)
31+
* Davide Grassano (CECAM EPFL)
32+
"""
33+
from easybuild.toolchains.lompi import Lompi
34+
from easybuild.toolchains.lfbf import Lfbf
35+
from easybuild.toolchains.fft.fftw import Fftw
36+
from easybuild.toolchains.linalg.flexiblas import FlexiBLAS
37+
from easybuild.toolchains.linalg.scalapack import ScaLAPACK
38+
from easybuild.tools import LooseVersion
39+
40+
41+
class LFoss(Lompi, FlexiBLAS, ScaLAPACK, Fftw):
42+
"""Compiler toolchain with LLVM, OpenMPI, FlexiBLAS, ScaLAPACK and FFTW."""
43+
NAME = 'lfoss'
44+
SUBTOOLCHAIN = [
45+
Lompi.NAME,
46+
Lfbf.NAME
47+
]
48+
49+
def __init__(self, *args, **kwargs):
50+
"""Toolchain constructor."""
51+
super(LFoss, self).__init__(*args, **kwargs)
52+
53+
# need to transform a version like '2018b' with something that is safe to compare with '2019'
54+
# comparing subversions that include letters causes TypeErrors in Python 3
55+
# 'a' is assumed to be equivalent with '.01' (January), and 'b' with '.07' (June) (good enough for this purpose)
56+
version = self.version.replace('a', '.01').replace('b', '.07')
57+
58+
self.looseversion = LooseVersion(version)
59+
60+
constants = ('BLAS_MODULE_NAME', 'BLAS_LIB', 'BLAS_LIB_MT', 'BLAS_FAMILY',
61+
'LAPACK_MODULE_NAME', 'LAPACK_IS_BLAS', 'LAPACK_FAMILY')
62+
63+
for constant in constants:
64+
setattr(self, constant, getattr(FlexiBLAS, constant))
65+
66+
def banned_linked_shared_libs(self):
67+
"""
68+
List of shared libraries (names, file names, paths) which are
69+
not allowed to be linked in any installed binary/library.
70+
"""
71+
res = []
72+
res.extend(Lompi.banned_linked_shared_libs(self))
73+
res.extend(FlexiBLAS.banned_linked_shared_libs(self))
74+
res.extend(ScaLAPACK.banned_linked_shared_libs(self))
75+
res.extend(Fftw.banned_linked_shared_libs(self))
76+
77+
return res
78+
79+
def is_deprecated(self):
80+
"""Return whether or not this toolchain is deprecated."""
81+
82+
# lfoss toolchains older than 2023b should not exist (need GCC >= 13)
83+
if self.looseversion < LooseVersion('2023'):
84+
deprecated = True
85+
else:
86+
deprecated = False
87+
88+
return deprecated

0 commit comments

Comments
 (0)