[NEW] Added amdfftw, amdlibflame and amdscalapack recipes (#19457)

* [NEW] Added amdfftw, amdlibflame and amdscalapack recipes

Updated base fftw, libflame and netlib-scalapack recipes
to accommodate the above listed AMD Optimizing CPU Libraries
which are a set of numerical routines optimized for AMD platforms.

Updated amdblis spack recipe

amdblis:
	1. updated with amdblis 2.2 release
amdfftw:
	1. "--enable-single" now work as synonym for "--enable-float"
amdlibflame:
	1. Added enable_or_disable_threads() to set value for "--enable-multithreading" flag
Libflame:
	1. Added enable_or_disable_threads() to set value for "--enable-multithreading" flag
	2. Corrected invocation of "enable_or_disable('threads')"

Change-Id: I9da0a2c2c4e2075b7fa2776e7cfe6548a2e0b32f

* Added amd-toolchain-support as maintainers

Added team github account amd-toolchain-support
as maintainers for all the recipes owned by
AMD Optimizing CPU Libraries (AOCL) team

Change-Id: I9a7969bd48fc42cfbb88dd7bd93e0802c6138582

* Incorporated review comments

Updated packages.yaml with aocl components
Handled Flake8 test failures

Change-Id: I0a03f02d8c9f326b2434ec907958c3de3a8e18eb

* Readded accidental removal of stream recipe

amdfftw:
	1. Updated the aocc clang selection as per spack standards
fftw:
	1. Currently apple-clang section is redundant,
	already it is handled in the conflict checks.

Change-Id: Idef4a3f61717eb81f321e0cd16e7ba9619eac846

* Fix for style and docs/validate (pull_request) test

unnumbered format placeholders from {} to {0}

Change-Id: If67a3374177ec067573e5504462d257712fafc05

* changed compiler references to Spack's compiler wrapper:spack_cc, spack_cxx, spack_fc

Change-Id: I7ae29c978fff16e37773913f14c84df232499763

* Removed 'single' variant from amdfftw recipe

Instead of conflict for apple-clang + openmp, handled this senario
via below available feature:
depends_on('llvm-openmp', when='%apple-clang +openmp')

Change-Id: I701b23d83e822a500ca3aaf2b60cc9ace09e13dc

* Added relevant info for users who prefers to use single precision

Change-Id: I3506e21da428ddef5fb7895b5aaed32c2a061ef6

* Minor changes on fftw, amdfftw and libflame

amdfftw:
	1. Removed escape symbol to the single quotes
	2. Rewording the conflict line from Recommended
	to Required

fftw:
	1. Reorded to following recommended sections:
	versions, variants, dependencies, providers,
	patches

libflame:
	1. Added provides entry for 5.1.0 version

Change-Id: I21ebff99b6dfde031763154693ecb3f1fa47b476

* Removed single quote from amdfftw docstring to fix style failures

Change-Id: Ife939a5a2f5ccbc8879b730c7bebfe2fcfef9332
This commit is contained in:
vijay kallesh 2020-10-31 22:27:17 +05:30 committed by GitHub
parent 08f4ba0c98
commit 51a9473bf8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 366 additions and 74 deletions

View file

@ -19,10 +19,10 @@ packages:
providers:
D: [ldc]
awk: [gawk]
blas: [openblas]
blas: [openblas, amdblis]
daal: [intel-daal]
elf: [elfutils]
fftw-api: [fftw]
fftw-api: [fftw, amdfftw]
gl: [mesa+opengl, mesa18+opengl, opengl]
glx: [mesa+glx, mesa18+glx, opengl]
glu: [mesa-glu, openglu]
@ -31,7 +31,7 @@ packages:
ipp: [intel-ipp]
java: [openjdk, jdk, ibm-java]
jpeg: [libjpeg-turbo, libjpeg]
lapack: [openblas]
lapack: [openblas, amdlibflame]
mariadb-client: [mariadb-c-client, mariadb]
mkl: [intel-mkl]
mpe: [mpe2]
@ -42,12 +42,13 @@ packages:
pil: [py-pillow]
pkgconfig: [pkgconf, pkg-config]
rpc: [libtirpc]
scalapack: [netlib-scalapack]
scalapack: [netlib-scalapack, amdscalapack]
sycl: [hipsycl]
szip: [libszip, libaec]
tbb: [intel-tbb]
unwind: [libunwind]
yacc: [bison, byacc]
flame: [libflame, amdlibflame]
permissions:
read: world
write: user

View file

@ -17,8 +17,9 @@ class Amdblis(BlisBase):
_name = 'amdblis'
homepage = "https://developer.amd.com/amd-aocl/blas-library/"
url = "https://github.com/amd/blis/archive/2.1.tar.gz"
url = "https://github.com/amd/blis/archive/2.2.tar.gz"
git = "https://github.com/amd/blis.git"
maintainers = ['amd-toolchain-support']
version('2.2', sha256='e1feb60ac919cf6d233c43c424f6a8a11eab2c62c2c6e3f2652c15ee9063c0c9')
version('2.1', sha256='3b1d611d46f0f13b3c0917e27012e0f789b23dbefdddcf877b20327552d72fb3')

View file

@ -0,0 +1,130 @@
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack import *
from spack.pkg.builtin.fftw import FftwBase
class Amdfftw(FftwBase):
"""FFTW (AMD Optimized version) is a comprehensive collection of
fast C routines for computing the Discrete Fourier Transform (DFT)
and various special cases thereof.
It is an open-source implementation of the Fast Fourier transform
algorithm. It can compute transforms of real and complex-values
arrays of arbitrary size and dimension.
AMD Optimized FFTW is the optimized FFTW implementation targeted
for AMD CPUs.
For single precision build, please use precision value as float.
Example : spack install amdfftw precision=float
"""
_name = 'amdfftw'
homepage = "https://developer.amd.com/amd-aocl/fftw/"
url = "https://github.com/amd/amd-fftw/archive/2.2.tar.gz"
git = "https://github.com/amd/amd-fftw.git"
maintainers = ['amd-toolchain-support']
version('2.2', sha256='de9d777236fb290c335860b458131678f75aa0799c641490c644c843f0e246f8')
variant('shared', default=True, description='Builds a shared version of the library')
variant('openmp', default=True, description="Enable OpenMP support")
variant('debug', default=False, description='Builds a debug version of the library')
depends_on('texinfo')
provides('fftw-api@3', when='@2:')
conflicts('precision=quad', when='%aocc', msg="AOCC clang doesn't support quad precision")
conflicts('+debug', when='%aocc', msg="AOCC clang doesn't support debug")
conflicts('%gcc@:7.2', when="@2.2:", msg="Required GCC version above 7.2 for AMDFFTW")
def configure(self, spec, prefix):
"""Configure function"""
# Base options
options = [
'--prefix={0}'.format(prefix),
'--enable-amd-opt',
'--enable-threads'
]
# Check if compiler is AOCC
if spec.satisfies('%aocc'):
options.append("CC={0}".format(os.path.basename(spack_cc)))
options.append("CXX={0}".format(os.path.basename(spack_cxx)))
options.append("FC={0}".format(os.path.basename(spack_fc)))
if '+shared' in spec:
options.append('--enable-shared')
else:
options.append('--disable-shared')
if '+openmp' in spec:
options.append('--enable-openmp')
else:
options.append('--disable-openmp')
if '+mpi' in spec:
options.append('--enable-mpi')
options.append('--enable-amd-mpifft')
else:
options.append('--disable-mpi')
options.append('--disable-amd-mpifft')
if not self.compiler.f77 or not self.compiler.fc:
options.append("--disable-fortran")
# Specific SIMD support.
# float and double precisions are supported
simd_features = ['sse2', 'avx', 'avx2', 'avx512', 'avx-128-fma',
'kcvi', 'vsx', 'neon']
simd_options = []
for feature in simd_features:
msg = '--enable-{0}' if feature in spec.target else '--disable-{0}'
simd_options.append(msg.format(feature))
simd_options += [
'--enable-fma' if 'fma' in spec.target else '--disable-fma'
]
float_simd_features = ['altivec', 'sse']
# When enabling configure option "--enable-amd-opt", do not use the
# configure option "--enable-generic-simd128" or
# "--enable-generic-simd256"
# Double is the default precision, for all the others we need
# to enable the corresponding option.
enable_precision = {
'float': ['--enable-float'],
'double': None,
'long_double': ['--enable-long-double'],
'quad': ['--enable-quad-precision']
}
# Different precisions must be configured and compiled one at a time
configure = Executable('../configure')
for precision in self.selected_precisions:
opts = (enable_precision[precision] or []) + options[:]
# SIMD optimizations are available only for float and double
if precision in ('float', 'double'):
opts += simd_options
# float-only acceleration
if precision == 'float':
for feature in float_simd_features:
if feature in spec.target:
msg = '--enable-{0}'
else:
msg = '--disable-{0}'
opts.append(msg.format(feature))
with working_dir(precision, create=True):
configure(*opts)

View file

@ -0,0 +1,12 @@
--- a/configure 2020-09-09 18:44:01.241188553 +0530
+++ b/configure 2020-09-09 18:46:51.672191301 +0530
@@ -6513,6 +6513,9 @@
gcc)
fla_c_openmp_flags='-fopenmp'
;;
+ clang)
+ fla_c_openmp_flags='-fopenmp'
+ ;;
pathcc)
fla_c_openmp_flags='-mp'
;;

View file

@ -0,0 +1,62 @@
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
# ----------------------------------------------------------------------------\
from spack.pkg.builtin.libflame import LibflameBase
class Amdlibflame(LibflameBase):
"""libFLAME (AMD Optimized version) is a portable library for
dense matrix computations, providing much of the functionality
present in Linear Algebra Package (LAPACK). It includes a
compatibility layer, FLAPACK, which includes complete LAPACK
implementation.
The library provides scientific and numerical computing communities
with a modern, high-performance dense linear algebra library that is
extensible, easy to use, and available under an open source
license. libFLAME is a C-only implementation and does not
depend on any external FORTRAN libraries including LAPACK.
There is an optional backward compatibility layer, lapack2flame
that maps LAPACK routine invocations to their corresponding
native C implementations in libFLAME. This allows legacy
applications to start taking advantage of libFLAME with
virtually no changes to their source code.
In combination with BLIS library which includes optimizations
for the AMD EPYC processor family, libFLAME enables running
high performing LAPACK functionalities on AMD platform.
"""
_name = 'amdlibflame'
homepage = "http://developer.amd.com/amd-cpu-libraries/blas-library/#libflame"
url = "https://github.com/amd/libflame/archive/2.2.tar.gz"
git = "https://github.com/amd/libflame.git"
maintainers = ['amd-toolchain-support']
version('2.2', sha256='12b9c1f92d2c2fa637305aaa15cf706652406f210eaa5cbc17aaea9fcfa576dc')
patch('aocc-2.2.0.patch', when="@:2.999", level=1)
provides('flame@5.2', when='@2:')
@property
def lapack_libs(self):
"""find lapack_libs function"""
shared = True if '+shared' in self.spec else False
return find_libraries(
'libflame', root=self.prefix, shared=shared, recursive=True
)
def configure_args(self):
"""configure_args function"""
args = super(Amdlibflame, self).configure_args()
args.append("--enable-external-lapack-interfaces")
return args
def install(self, spec, prefix):
"""make install function"""
# make install in parallel fails with message 'File already exists'
make("install", parallel=False)

View file

@ -0,0 +1,54 @@
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack import *
from spack.pkg.builtin.netlib_scalapack import ScalapackBase
class Amdscalapack(ScalapackBase):
"""
ScaLAPACK is a library of high-performance linear algebra routines
for parallel distributed memory machines. It depends on external
libraries including BLAS and LAPACK for Linear Algebra computations.
AMD's optimized version of ScaLAPACK enables using BLIS and
LibFLAME library that have optimized dense matrix functions and
solvers for AMD EPYC processor family CPUs.
"""
_name = 'amdscalapack'
homepage = "https://developer.amd.com/amd-aocl/scalapack/"
url = "https://github.com/amd/scalapack/archive/2.2.tar.gz"
git = "https://github.com/amd/scalapack.git"
maintainers = ['amd-toolchain-support']
version('2.2', sha256='2d64926864fc6d12157b86e3f88eb1a5205e7fc157bf67e7577d0f18b9a7484c')
variant(
'build_type',
default='Release',
description='CMake build type',
values=('Release', 'RelWithDebInfo'))
def cmake_args(self):
""" cmake_args function"""
args = super(Amdscalapack, self).cmake_args()
spec = self.spec
args.extend([
"-DUSE_DOTC_WRAPPER:BOOL=%s" % (
'ON' if '%aocc ^amdblis' in spec else 'OFF'
)
])
args.extend([
'-DUSE_F2C=ON',
'-DLAPACK_FOUND=true',
'-DCMAKE_C_COMPILER=%s' % spec['mpi'].mpicc,
'-DCMAKE_Fortran_COMPILER=%s' % spec['mpi'].mpifc,
])
return args

View file

@ -5,35 +5,14 @@
import os
import os.path
import llnl.util.lang
from spack import *
class Fftw(AutotoolsPackage):
"""FFTW is a C subroutine library for computing the discrete Fourier
transform (DFT) in one or more dimensions, of arbitrary input
size, and of both real and complex data (as well as of even/odd
data, i.e. the discrete cosine/sine transforms or DCT/DST). We
believe that FFTW, which is free software, should become the FFT
library of choice for most applications."""
homepage = "http://www.fftw.org"
url = "http://www.fftw.org/fftw-3.3.4.tar.gz"
list_url = "http://www.fftw.org/download.html"
version('3.3.8', sha256='6113262f6e92c5bd474f2875fa1b01054c4ad5040f6b0da7c03c98821d9ae303')
version('3.3.7', sha256='3b609b7feba5230e8f6dd8d245ddbefac324c5a6ae4186947670d9ac2cd25573')
version('3.3.6-pl2', sha256='a5de35c5c824a78a058ca54278c706cdf3d4abba1c56b63531c2cb05f5d57da2')
version('3.3.5', sha256='8ecfe1b04732ec3f5b7d279fdb8efcad536d555f9d1e8fabd027037d45ea8bcf')
version('3.3.4', sha256='8f0cde90929bc05587c3368d2f15cd0530a60b8a9912a8e2979a72dbe5af0982')
version('2.1.5', sha256='f8057fae1c7df8b99116783ef3e94a6a44518d49c72e2e630c24b689c6022630')
patch('pfft-3.3.5.patch', when="@3.3.5:+pfft_patches", level=0)
patch('pfft-3.3.4.patch', when="@3.3.4+pfft_patches", level=0)
patch('pgi-3.3.6-pl2.patch', when="@3.3.6-pl2%pgi", level=0)
patch('intel-configure.patch', when="@3:3.3.8%intel", level=0)
class FftwBase(AutotoolsPackage):
"""Base class for building Fftw, shared with the AMD optimized version
of the library in the 'amdfftw' package.
"""
variant(
'precision', values=any_combination_of(
@ -43,14 +22,9 @@ class Fftw(AutotoolsPackage):
)
variant('openmp', default=False, description="Enable OpenMP support.")
variant('mpi', default=True, description='Activate MPI support')
variant(
'pfft_patches', default=False,
description='Add extra transpose functions for PFFT compatibility')
depends_on('mpi', when='+mpi')
depends_on('automake', type='build', when='+pfft_patches')
depends_on('autoconf', type='build', when='+pfft_patches')
depends_on('libtool', type='build', when='+pfft_patches')
depends_on('llvm-openmp', when='%apple-clang +openmp')
# https://github.com/FFTW/fftw3/commit/902d0982522cdf6f0acd60f01f59203824e8e6f3
conflicts('%gcc@8:8.9999', when="@3.3.7")
@ -58,10 +32,6 @@ class Fftw(AutotoolsPackage):
msg='Long double precision is not supported in FFTW 2')
conflicts('precision=quad', when='@2.1.5',
msg='Quad precision is not supported in FFTW 2')
conflicts('+openmp', when='%apple-clang', msg="Apple's clang does not support OpenMP")
provides('fftw-api@2', when='@2.1.5')
provides('fftw-api@3', when='@3:')
@property
def libs(self):
@ -218,3 +188,39 @@ def check(self):
def install(self, spec, prefix):
self.for_each_precision_make('install')
class Fftw(FftwBase):
"""FFTW is a C subroutine library for computing the discrete Fourier
transform (DFT) in one or more dimensions, of arbitrary input
size, and of both real and complex data (as well as of even/odd
data, i.e. the discrete cosine/sine transforms or DCT/DST). We
believe that FFTW, which is free software, should become the FFT
library of choice for most applications."""
homepage = "http://www.fftw.org"
url = "http://www.fftw.org/fftw-3.3.4.tar.gz"
list_url = "http://www.fftw.org/download.html"
version('3.3.8', sha256='6113262f6e92c5bd474f2875fa1b01054c4ad5040f6b0da7c03c98821d9ae303')
version('3.3.7', sha256='3b609b7feba5230e8f6dd8d245ddbefac324c5a6ae4186947670d9ac2cd25573')
version('3.3.6-pl2', sha256='a5de35c5c824a78a058ca54278c706cdf3d4abba1c56b63531c2cb05f5d57da2')
version('3.3.5', sha256='8ecfe1b04732ec3f5b7d279fdb8efcad536d555f9d1e8fabd027037d45ea8bcf')
version('3.3.4', sha256='8f0cde90929bc05587c3368d2f15cd0530a60b8a9912a8e2979a72dbe5af0982')
version('2.1.5', sha256='f8057fae1c7df8b99116783ef3e94a6a44518d49c72e2e630c24b689c6022630')
variant(
'pfft_patches', default=False,
description='Add extra transpose functions for PFFT compatibility')
depends_on('automake', type='build', when='+pfft_patches')
depends_on('autoconf', type='build', when='+pfft_patches')
depends_on('libtool', type='build', when='+pfft_patches')
provides('fftw-api@2', when='@2.1.5')
provides('fftw-api@3', when='@3:')
patch('pfft-3.3.5.patch', when="@3.3.5:+pfft_patches", level=0)
patch('pfft-3.3.4.patch', when="@3.3.4+pfft_patches", level=0)
patch('pgi-3.3.6-pl2.patch', when="@3.3.6-pl2%pgi", level=0)
patch('intel-configure.patch', when="@3:3.3.8%intel", level=0)

View file

@ -6,22 +6,9 @@
from spack import *
class Libflame(AutotoolsPackage):
"""libflame is a portable library for dense matrix computations,
providing much of the functionality present in LAPACK, developed
by current and former members of the Science of High-Performance
Computing (SHPC) group in the Institute for Computational
Engineering and Sciences at The University of Texas at Austin.
libflame includes a compatibility layer, lapack2flame, which
includes a complete LAPACK implementation."""
homepage = "https://www.cs.utexas.edu/~flame/web/libFLAME.html"
url = "https://github.com/flame/libflame/archive/5.1.0.tar.gz"
git = "https://github.com/flame/libflame.git"
version('master', branch='master')
version('5.2.0', sha256='997c860f351a5c7aaed8deec00f502167599288fd0559c92d5bfd77d0b4d475c')
version('5.1.0', sha256='e7189b750890bd781fe773f366b374518dd1d89a6513d3d6261bf549826384d1')
class LibflameBase(AutotoolsPackage):
"""Base class for building Libflame, shared with the AMD
optimized version of the library in the 'libflame' package"""
provides('lapack', when='+lapack2flame')
@ -70,9 +57,9 @@ def flag_handler(self, name, flags):
flags.append('-std=gnu99')
return (flags, None, None)
def enable_or_disable_threads(self, variant, options):
def enable_or_disable_threads(self):
opt_val = self.spec.variants['threads'].value
if variant_val == 'none':
if opt_val == 'none':
opt_val = 'no'
return ['--enable-multithreading={0}'.format(opt_val)]
@ -102,9 +89,9 @@ def configure_args(self):
else:
config_args.append("--disable-debug")
config_args.extend(self.enable_or_disable('threads'))
config_args.extend(self.enable_or_disable_threads())
if 'none' != self.spec.variants['threads'].value:
if self.spec.variants['threads'].value != 'none':
config_args.append("--enable-supermatrix")
else:
config_args.append("--disable-supermatrix")
@ -119,3 +106,24 @@ def darwin_fix(self):
# The shared library is not installed correctly on Darwin; fix this
if self.spec.satisfies('platform=darwin'):
fix_darwin_install_name(self.prefix.lib)
class Libflame(LibflameBase):
"""libflame is a portable library for dense matrix computations,
providing much of the functionality present in LAPACK, developed
by current and former members of the Science of High-Performance
Computing (SHPC) group in the Institute for Computational
Engineering and Sciences at The University of Texas at Austin.
libflame includes a compatibility layer, lapack2flame, which
includes a complete LAPACK implementation."""
homepage = "https://www.cs.utexas.edu/~flame/web/libFLAME.html"
url = "https://github.com/flame/libflame/archive/5.1.0.tar.gz"
git = "https://github.com/flame/libflame.git"
version('master', branch='master')
version('5.2.0', sha256='997c860f351a5c7aaed8deec00f502167599288fd0559c92d5bfd77d0b4d475c')
version('5.1.0', sha256='e7189b750890bd781fe773f366b374518dd1d89a6513d3d6261bf549826384d1')
provides('flame@5.2', when='@5.2.0')
provides('flame@5.1', when='@5.1.0')

View file

@ -7,20 +7,15 @@
import sys
class NetlibScalapack(CMakePackage):
"""ScaLAPACK is a library of high-performance linear algebra routines for
parallel distributed memory machines
class ScalapackBase(CMakePackage):
"""Base class for building ScaLAPACK, shared with the AMD optimized version
of the library in the 'amdscalapack' package.
"""
homepage = "http://www.netlib.org/scalapack/"
url = "http://www.netlib.org/scalapack/scalapack-2.0.2.tgz"
version('2.1.0', sha256='61d9216cf81d246944720cfce96255878a3f85dec13b9351f1fa0fd6768220a6')
version('2.0.2', sha256='0c74aeae690fe5ee4db7926f49c5d0bb69ce09eea75beb915e00bba07530395c')
version('2.0.1', sha256='a9b34278d4e10b40cbe084c6d87d09af8845e874250719bfbbc497b2a88bfde1')
version('2.0.0', sha256='e51fbd9c3ef3a0dbd81385b868e2355900148eea689bf915c5383d72daf73114')
# versions before 2.0.0 are not using cmake and requires blacs as
# a separated package
variant(
'build_type',
default='Release',
description='CMake build type',
values=('Debug', 'Release', 'RelWithDebInfo', 'MinSizeRel'))
variant(
'shared',
@ -91,3 +86,26 @@ def fix_darwin_install(self):
# The shared libraries are not installed correctly on Darwin:
if (sys.platform == 'darwin') and ('+shared' in self.spec):
fix_darwin_install_name(self.spec.prefix.lib)
class NetlibScalapack(ScalapackBase):
"""ScaLAPACK is a library of high-performance linear algebra routines for
parallel distributed memory machines
"""
homepage = "http://www.netlib.org/scalapack/"
url = "http://www.netlib.org/scalapack/scalapack-2.0.2.tgz"
version('2.1.0', sha256='61d9216cf81d246944720cfce96255878a3f85dec13b9351f1fa0fd6768220a6')
version('2.0.2', sha256='0c74aeae690fe5ee4db7926f49c5d0bb69ce09eea75beb915e00bba07530395c')
version('2.0.1', sha256='a9b34278d4e10b40cbe084c6d87d09af8845e874250719bfbbc497b2a88bfde1')
version('2.0.0', sha256='e51fbd9c3ef3a0dbd81385b868e2355900148eea689bf915c5383d72daf73114')
# versions before 2.0.0 are not using cmake and requires blacs as
# a separated package
# See: https://github.com/Reference-ScaLAPACK/scalapack/issues/9
patch("cmake_fortran_mangle.patch", when='@2.0.2:2.0.99')
# See: https://github.com/Reference-ScaLAPACK/scalapack/pull/10
patch("mpi2-compatibility.patch", when='@2.0.2:2.0.99')
# See: https://github.com/Reference-ScaLAPACK/scalapack/pull/16
patch("int_overflow.patch", when='@2.0.0:2.1.0')