# Copyright 2013-2024 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.package import * class NetlibLapack(CMakePackage): """LAPACK version 3.X is a comprehensive FORTRAN library that does linear algebra operations including matrix inversions, least squared solutions to linear sets of equations, eigenvector analysis, singular value decomposition, etc. It is a very comprehensive and reputable package that has found extensive use in the scientific community. """ homepage = "http://www.netlib.org/lapack/" url = "http://www.netlib.org/lapack/lapack-3.5.0.tgz" version( "3.8.0", "96591affdbf58c450d45c1daa540dbd2", url="http://www.netlib.org/lapack/lapack-3.8.0.tar.gz", ) version("3.7.1", md5="dcdeeed73de152c4643ccc5b1aeb453c") version("3.7.0", md5="697bb8d67c7d336a0f339cc9dd0fa72f") version("3.6.1", md5="421b2cb72e15f237e144428f9c460ee0") version("3.6.0", md5="f2f6c67134e851fe189bb3ca1fbb5101") version("3.5.0", md5="b1d3e3e425b2e44a06760ff173104bdf") version("3.4.2", md5="61bf1a8a4469d4bdb7604f5897179478") version("3.4.1", md5="44c3869c38c8335c2b9c2a8bb276eb55") version("3.4.0", md5="02d5706ec03ba885fc246e5fa10d8c70") version("3.3.1", md5="d0d533ec9a5b74933c2a1e84eedc58b4") variant("shared", default=True, description="Build shared library version") variant("external-blas", default=False, description="Build lapack with an external blas") variant("lapacke", default=True, description="Activates the build of the LAPACKE C interface") variant("xblas", default=False, description="Builds extended precision routines using XBLAS") patch("ibm-xl.patch", when="@3.7: %xl") patch("ibm-xl.patch", when="@3.7: %xl_r") # https://github.com/Reference-LAPACK/lapack/issues/228 # TODO: update 'when' once the version of lapack # containing the fix is released and added to Spack. patch("undefined_declarations.patch", when="@3.8.0:") # https://github.com/Reference-LAPACK/lapack/pull/268 # TODO: update 'when' once the version of lapack # containing the fix is released and added to Spack. patch("testing.patch", when="@3.7.0:") # virtual dependency provides("blas", when="~external-blas") provides("lapack") depends_on("blas", when="+external-blas") depends_on("netlib-xblas+fortran+plain_blas", when="+xblas") depends_on("python@2.7:", type="test") # We need to run every phase twice in order to get static and shared # versions of the libraries. When ~shared, we run the default # implementations of the CMakePackage's phases and get only one building # directory 'spack-build-static' with -DBUILD_SHARED_LIBS:BOOL=OFF (see # implementations of self.build_directory and self.cmake_args() below). # When +shared, we run the overridden methods for the phases, each # running the default implementation twice with different values for # self._building_shared. As a result, we get two building directories: # 'spack-build-static' with -DBUILD_SHARED_LIBS:BOOL=OFF and # 'spack-build-shared' with -DBUILD_SHARED_LIBS:BOOL=ON. _building_shared = False def patch(self): # Fix cblas CMakeLists.txt -- has wrong case for subdirectory name. if self.spec.satisfies("@3.6.0:"): filter_file( "${CMAKE_CURRENT_SOURCE_DIR}/CMAKE/", "${CMAKE_CURRENT_SOURCE_DIR}/cmake/", "CBLAS/CMakeLists.txt", string=True, ) @property def blas_libs(self): shared = True if "+shared" in self.spec else False query_parameters = self.spec.last_query.extra_parameters query2libraries = { tuple(): ["libblas"], ("c", "fortran"): ["libcblas", "libblas"], ("c",): ["libcblas"], ("fortran",): ["libblas"], } key = tuple(sorted(query_parameters)) libraries = query2libraries[key] return find_libraries(libraries, root=self.prefix, shared=shared, recursive=True) # TUTORIAL: add a proper `lapack_lib` property, along the lines # of the `blas_lib` property above. The library that provides # the lapack API is called `liblapack`. @property def headers(self): include_dir = self.spec.prefix.include cblas_h = join_path(include_dir, "cblas.h") lapacke_h = join_path(include_dir, "lapacke.h") return HeaderList([cblas_h, lapacke_h]) @property def build_directory(self): return join_path( self.stage.source_path, "spack-build-shared" if self._building_shared else "spack-build-static", ) def cmake_args(self): args = ["-DBUILD_SHARED_LIBS:BOOL=" + ("ON" if self._building_shared else "OFF")] if self.spec.satisfies("+lapacke"): args.extend(["-DLAPACKE:BOOL=ON", "-DLAPACKE_WITH_TMG:BOOL=ON"]) else: args.extend(["-DLAPACKE:BOOL=OFF", "-DLAPACKE_WITH_TMG:BOOL=OFF"]) if self.spec.satisfies("@3.6.0:"): args.append("-DCBLAS=ON") # always build CBLAS if self.spec.satisfies("%intel"): # Intel compiler finds serious syntax issues when trying to # build CBLAS and LapackE args.extend(["-DCBLAS=OFF", "-DLAPACKE:BOOL=OFF"]) if self.spec.satisfies("%xl") or self.spec.satisfies("%xl_r"): # use F77 compiler if IBM XL args.extend( [ "-DCMAKE_Fortran_COMPILER=" + self.compiler.f77, "-DCMAKE_Fortran_FLAGS=" + (" ".join(self.spec.compiler_flags["fflags"])) + " -O3 -qnohot", ] ) # deprecated routines are commonly needed by, for example, suitesparse # Note that OpenBLAS spack is built with deprecated routines args.append("-DBUILD_DEPRECATED:BOOL=ON") if self.spec.satisfies("+external-blas"): args.extend( [ "-DUSE_OPTIMIZED_BLAS:BOOL=ON", "-DBLAS_LIBRARIES:PATH=" + self.spec["blas"].libs.joined(";"), ] ) if self.spec.satisfies("+xblas"): args.extend( [ "-DXBLAS_INCLUDE_DIR=" + self.spec["netlib-xblas"].prefix.include, "-DXBLAS_LIBRARY=" + self.spec["netlib-xblas"].libs.joined(";"), ] ) args.append("-DBUILD_TESTING:BOOL=" + ("ON" if self.run_tests else "OFF")) return args # Build, install, and check both static and shared versions of the # libraries when +shared @when("+shared") def cmake(self, spec, prefix): for self._building_shared in (False, True): super().cmake(spec, prefix) @when("+shared") def build(self, spec, prefix): for self._building_shared in (False, True): super().build(spec, prefix) @when("+shared") def install(self, spec, prefix): for self._building_shared in (False, True): super().install(spec, prefix) @when("+shared") def check(self): for self._building_shared in (False, True): super().check()