libint + cp2k: 2-stage build with 'tune' and 'fortran' variants (#12475)
* libint: switch to 2-stage build for 2.6.0+ * libint: add tune and fortran variants * cp2k: add support for libint >= 2.0 * cp2k: use pkg-config for linking libxc
This commit is contained in:
		 Tiziano Müller
					Tiziano Müller
				
			
				
					committed by
					
						 Massimiliano Culpo
						Massimiliano Culpo
					
				
			
			
				
	
			
			
			 Massimiliano Culpo
						Massimiliano Culpo
					
				
			
						parent
						
							da18ac3a0f
						
					
				
				
					commit
					d99b92febd
				
			| @@ -61,6 +61,14 @@ class Cp2k(MakefilePackage, CudaPackage): | ||||
|     variant('cuda_blas', default=False, | ||||
|             description=('Use CUBLAS for general matrix operations in DBCSR')) | ||||
|  | ||||
|     HFX_LMAX_RANGE = range(4, 8) | ||||
|  | ||||
|     variant('lmax', | ||||
|             description='Maximum supported angular momentum (HFX and others)', | ||||
|             default='5', | ||||
|             values=list(HFX_LMAX_RANGE), | ||||
|             multi=False) | ||||
|  | ||||
|     depends_on('python', type='build') | ||||
|  | ||||
|     depends_on('fftw@3:', when='~openmp') | ||||
| @@ -80,11 +88,19 @@ class Cp2k(MakefilePackage, CudaPackage): | ||||
|     depends_on('libxsmm@1.11:~header-only', when='smm=libxsmm') | ||||
|     # use pkg-config (support added in libxsmm-1.10) to link to libxsmm | ||||
|     depends_on('pkgconfig', type='build', when='smm=libxsmm') | ||||
|     # ... and in CP2K 7.0+ for linking to libint2 | ||||
|     depends_on('pkgconfig', type='build', when='@7.0:') | ||||
|  | ||||
|     # libint & libxc are always statically linked | ||||
|     depends_on('libint@1.1.4:1.2', when='@3.0:', type='build') | ||||
|     depends_on('libint@1.1.4:1.2', when='@3.0:6.9', type='build') | ||||
|     for lmax in HFX_LMAX_RANGE: | ||||
|         # libint2 can be linked dynamically again | ||||
|         depends_on('libint@2.6.0:+fortran tune=cp2k-lmax-{0}'.format(lmax), | ||||
|                    when='@7.0: lmax={0}'.format(lmax)) | ||||
|  | ||||
|     depends_on('libxc@2.2.2:', when='+libxc@:5.5999', type='build') | ||||
|     depends_on('libxc@4.0.3:', when='+libxc@6.0:', type='build') | ||||
|     depends_on('libxc@4.0.3:', when='+libxc@6.0:6.9', type='build') | ||||
|     depends_on('libxc@4.0.3:', when='+libxc@7.0:') | ||||
|  | ||||
|     depends_on('mpi@2:', when='+mpi') | ||||
|     depends_on('scalapack', when='+mpi') | ||||
| @@ -169,13 +185,17 @@ def edit(self, spec, prefix): | ||||
|  | ||||
|         dflags = ['-DNDEBUG'] | ||||
|         cppflags = [ | ||||
|             '-D__FFTW3', | ||||
|             '-D__LIBINT', | ||||
|             '-D__LIBINT_MAX_AM=6', | ||||
|             '-D__LIBDERIV_MAX_AM1=5', | ||||
|             '-D__FFTW3', | ||||
|             fftw.headers.cpp_flags, | ||||
|         ] | ||||
|  | ||||
|         if '@:6.9' in spec: | ||||
|             cppflags += [ | ||||
|                 '-D__LIBINT_MAX_AM=6', | ||||
|                 '-D__LIBDERIV_MAX_AM1=5', | ||||
|             ] | ||||
|  | ||||
|         if '^mpi@3:' in spec: | ||||
|             cppflags.append('-D__MPI_VERSION=3') | ||||
|         elif '^mpi@2:' in spec: | ||||
| @@ -220,14 +240,18 @@ def edit(self, spec, prefix): | ||||
|         if 'superlu-dist@4.3' in spec: | ||||
|             ldflags.insert(0, '-Wl,--allow-multiple-definition') | ||||
|  | ||||
|         # libint-1.x.y has to be linked statically to work around | ||||
|         # inconsistencies in its Fortran interface definition | ||||
|         # (short-int vs int) which otherwise causes segfaults at runtime | ||||
|         # due to wrong offsets into the shared library symbols. | ||||
|         libs.extend([ | ||||
|             os.path.join(spec['libint'].libs.directories[0], 'libderiv.a'), | ||||
|             os.path.join(spec['libint'].libs.directories[0], 'libint.a'), | ||||
|         ]) | ||||
|         if '@:6.9' in spec: | ||||
|             # libint-1.x.y has to be linked statically to work around | ||||
|             # inconsistencies in its Fortran interface definition | ||||
|             # (short-int vs int) which otherwise causes segfaults at runtime | ||||
|             # due to wrong offsets into the shared library symbols. | ||||
|             libs.extend([ | ||||
|                 os.path.join(spec['libint'].libs.directories[0], 'libderiv.a'), | ||||
|                 os.path.join(spec['libint'].libs.directories[0], 'libint.a'), | ||||
|             ]) | ||||
|         else: | ||||
|             fcflags += ['$(shell pkg-config --cflags libint2)'] | ||||
|             libs += ['$(shell pkg-config --libs libint2)'] | ||||
|  | ||||
|         if '+plumed' in self.spec: | ||||
|             dflags.extend(['-D__PLUMED2']) | ||||
| @@ -286,14 +310,16 @@ def edit(self, spec, prefix): | ||||
|                 libs.append(wannier) | ||||
|  | ||||
|         if '+libxc' in spec: | ||||
|             libxc = spec['libxc:fortran,static'] | ||||
|             cppflags += [ | ||||
|                 '-D__LIBXC', | ||||
|                 libxc.headers.cpp_flags | ||||
|             ] | ||||
|             cppflags += ['-D__LIBXC'] | ||||
|  | ||||
|             ldflags.append(libxc.libs.search_flags) | ||||
|             libs.append(str(libxc.libs)) | ||||
|             if '@:6.9' in spec: | ||||
|                 libxc = spec['libxc:fortran,static'] | ||||
|                 cppflags += [libxc.headers.cpp_flags] | ||||
|                 ldflags.append(libxc.libs.search_flags) | ||||
|                 libs.append(str(libxc.libs)) | ||||
|             else: | ||||
|                 fcflags += ['$(shell pkg-config --cflags libxcf03)'] | ||||
|                 libs += ['$(shell pkg-config --libs libxcf03)'] | ||||
|  | ||||
|         if '+pexsi' in self.spec: | ||||
|             cppflags.append('-D__LIBPEXSI') | ||||
|   | ||||
| @@ -3,9 +3,19 @@ | ||||
| # | ||||
| # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||
|  | ||||
| import os | ||||
| from spack import * | ||||
|  | ||||
|  | ||||
| TUNE_VARIANTS = ( | ||||
|     'none', | ||||
|     'cp2k-lmax-4', | ||||
|     'cp2k-lmax-5', | ||||
|     'cp2k-lmax-6', | ||||
|     'cp2k-lmax-7', | ||||
| ) | ||||
|  | ||||
|  | ||||
| class Libint(AutotoolsPackage): | ||||
|     """Libint is a high-performance library for computing | ||||
|     Gaussian integrals in quantum mechanics. | ||||
| @@ -14,6 +24,7 @@ class Libint(AutotoolsPackage): | ||||
|     homepage = "https://github.com/evaleev/libint" | ||||
|     url = "https://github.com/evaleev/libint/archive/v2.1.0.tar.gz" | ||||
|  | ||||
|     version('2.6.0', sha256='4ae47e8f0b5632c3d2a956469a7920896708e9f0e396ec10071b8181e4c8d9fa') | ||||
|     version('2.4.2', sha256='86dff38065e69a3a51d15cfdc638f766044cb87e5c6682d960c14f9847e2eac3') | ||||
|     version('2.4.1', sha256='0513be124563fdbbc7cd3c7043e221df1bda236a037027ba9343429a27db8ce4') | ||||
|     version('2.4.0', sha256='52eb16f065406099dcfaceb12f9a7f7e329c9cfcf6ed9bfacb0cff7431dd6019') | ||||
| @@ -22,6 +33,12 @@ class Libint(AutotoolsPackage): | ||||
|     version('1.1.6', sha256='f201b0c621df678cfe8bdf3990796b8976ff194aba357ae398f2f29b0e2985a6') | ||||
|     version('1.1.5', sha256='ec8cd4a4ba1e1a98230165210c293632372f0e573acd878ed62e5ec6f8b6174b') | ||||
|  | ||||
|     variant('fortran', default=False, | ||||
|             description='Build & install Fortran bindings') | ||||
|     variant('tune', default='none', multi=False, | ||||
|             values=TUNE_VARIANTS, | ||||
|             description='Tune libint for use with the given package') | ||||
|  | ||||
|     # Build dependencies | ||||
|     depends_on('autoconf@2.52:', type='build') | ||||
|     depends_on('automake', type='build') | ||||
| @@ -31,6 +48,11 @@ class Libint(AutotoolsPackage): | ||||
|     depends_on('boost', when='@2:') | ||||
|     depends_on('gmp', when='@2:') | ||||
|  | ||||
|     for tvariant in TUNE_VARIANTS[1:]: | ||||
|         conflicts('tune={0}'.format(tvariant), when='@:2.5.99', | ||||
|                   msg=('for versions prior to 2.6, tuning for specific' | ||||
|                        'codes/configurations is not supported')) | ||||
|  | ||||
|     def url_for_version(self, version): | ||||
|         base_url = "https://github.com/evaleev/libint/archive" | ||||
|         if version == Version('1.0.0'): | ||||
| @@ -45,6 +67,10 @@ def autoreconf(self, spec, prefix): | ||||
|         aclocal('-I', 'lib/autoconf') | ||||
|         autoconf() | ||||
|  | ||||
|         if '@2.6.0:' in spec: | ||||
|             # skip tarball creation and removal of dir with generated code | ||||
|             filter_file(r'^(export::.*)\s+tgz$', r'\1', 'export/Makefile') | ||||
|  | ||||
|     @property | ||||
|     def optflags(self): | ||||
|         flags = '-O2' | ||||
| @@ -89,4 +115,60 @@ def configure_args(self): | ||||
|                 '--with-libint-max-am=5', | ||||
|                 '--with-libderiv-max-am1=4' | ||||
|             ]) | ||||
|  | ||||
|         if '@2.6.0:' in self.spec: | ||||
|             config_args += ['--with-libint-exportdir=generated'] | ||||
|  | ||||
|             tune_value = self.spec.variants['tune'].value | ||||
|             if tune_value.startswith('cp2k'): | ||||
|                 lmax = int(tune_value.split('-lmax-')[1]) | ||||
|                 config_args += [ | ||||
|                     '--enable-eri=1', | ||||
|                     '--enable-eri2=1', | ||||
|                     '--enable-eri3=1', | ||||
|                     '--with-max-am={0}'.format(lmax), | ||||
|                     '--with-eri-max-am={0},{1}'.format(lmax, lmax - 1), | ||||
|                     '--with-eri2-max-am={0},{1}'.format(lmax + 2, lmax + 1), | ||||
|                     '--with-eri3-max-am={0},{1}'.format(lmax + 2, lmax + 1), | ||||
|                     '--with-opt-am=3', | ||||
|                     # keep code-size at an acceptable limit, | ||||
|                     # cf. https://github.com/evaleev/libint/wiki#program-specific-notes: | ||||
|                     '--enable-generic-code', | ||||
|                     '--disable-unrolling', | ||||
|                 ] | ||||
|  | ||||
|         return config_args | ||||
|  | ||||
|     @property | ||||
|     def build_targets(self): | ||||
|         if '@2.6.0:' in self.spec: | ||||
|             return ['export'] | ||||
|  | ||||
|         return [] | ||||
|  | ||||
|     @when('@2.6.0:') | ||||
|     def install(self, spec, prefix): | ||||
|         """ | ||||
|         Starting from libint 2.6.0 we're using the 2-stage build | ||||
|         to get support for the Fortran bindings, required by some | ||||
|         packages (CP2K notably). | ||||
|         """ | ||||
|  | ||||
|         # upstream says that using configure/make for the generated code | ||||
|         # is deprecated and one should use CMake, but with the currently | ||||
|         # recent 2.7.0.b1 it still doesn't work | ||||
|         with working_dir(os.path.join(self.build_directory, 'generated')): | ||||
|             # straight from the AutotoolsPackage class: | ||||
|             options = [ | ||||
|                 '--prefix={0}'.format(prefix), | ||||
|                 '--enable-shared', | ||||
|                 '--with-cxx-optflags={0}'.format(self.optflags), | ||||
|             ] | ||||
|  | ||||
|             if '+fortran' in spec: | ||||
|                 options += ['--enable-fortran'] | ||||
|  | ||||
|             configure = Executable('./configure') | ||||
|             configure(*options) | ||||
|             make() | ||||
|             make('install') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user