From 8770957b7ad26f9697663c39b43f493ac8ecd79c Mon Sep 17 00:00:00 2001
From: Sergey Kosukhin <skosukhin@gmail.com>
Date: Mon, 9 Jul 2018 20:21:55 +0200
Subject: [PATCH] Make 'netlib-lapack' a CMakePackage. (#8661)

* Make 'netlib-lapack' a CMakePackage.

* Add a comment.

* Some refactoring.
---
 .../builtin/packages/netlib-lapack/package.py | 118 +++++++++++-------
 1 file changed, 70 insertions(+), 48 deletions(-)

diff --git a/var/spack/repos/builtin/packages/netlib-lapack/package.py b/var/spack/repos/builtin/packages/netlib-lapack/package.py
index c99b3fc91a..28e6b6374f 100644
--- a/var/spack/repos/builtin/packages/netlib-lapack/package.py
+++ b/var/spack/repos/builtin/packages/netlib-lapack/package.py
@@ -25,7 +25,7 @@
 from spack import *
 
 
-class NetlibLapack(Package):
+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
@@ -48,8 +48,6 @@ class NetlibLapack(Package):
     version('3.4.0', '02d5706ec03ba885fc246e5fa10d8c70')
     version('3.3.1', 'd0d533ec9a5b74933c2a1e84eedc58b4')
 
-    variant('debug', default=False,
-            description='Activates the Debug build type')
     variant('shared', default=True, description="Build shared library version")
     variant('external-blas', default=False,
             description='Build lapack with an external blas')
@@ -66,9 +64,21 @@ class NetlibLapack(Package):
     provides('blas', when='~external-blas')
     provides('lapack')
 
-    depends_on('cmake', type='build')
     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.
@@ -131,61 +141,73 @@ def headers(self):
         lapacke_h = join_path(include_dir, 'lapacke.h')
         return HeaderList([cblas_h, lapacke_h])
 
-    def install_one(self, spec, prefix, shared):
-        cmake_args = [
-            '-DBUILD_SHARED_LIBS:BOOL=%s' % ('ON' if shared else 'OFF'),
-            '-DCMAKE_BUILD_TYPE:STRING=%s' % (
-                'Debug' if '+debug' in spec else 'Release'),
-            '-DLAPACKE:BOOL=%s' % (
-                'ON' if '+lapacke' in spec else 'OFF'),
-            '-DLAPACKE_WITH_TMG:BOOL=%s' % (
-                'ON' if '+lapacke' in spec else 'OFF')]
-        if spec.satisfies('@3.6.0:'):
-            cmake_args.extend(['-DCBLAS=ON'])  # always build CBLAS
-
-        if self.compiler.name == 'intel':
+    @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
-            cmake_args.extend(['-DCBLAS=OFF'])
-            cmake_args.extend(['-DLAPACKE:BOOL=OFF'])
+            args.extend(['-DCBLAS=OFF', '-DLAPACKE:BOOL=OFF'])
 
-        if self.compiler.name == 'xl' or self.compiler.name == 'xl_r':
+        if self.spec.satisfies('%xl') or self.spec.satisfies('%xl_r'):
             # use F77 compiler if IBM XL
-            cmake_args.extend([
-                '-DCMAKE_Fortran_COMPILER=%s' % self.compiler.f77,
-                '-DCMAKE_Fortran_FLAGS=%s' % (
-                    ' '.join(self.spec.compiler_flags['fflags'])),
-            ])
+            args.extend(['-DCMAKE_Fortran_COMPILER=' + self.compiler.f77,
+                         '-DCMAKE_Fortran_FLAGS=' +
+                         (' '.join(self.spec.compiler_flags['fflags']))])
 
         # deprecated routines are commonly needed by, for example, suitesparse
         # Note that OpenBLAS spack is built with deprecated routines
-        cmake_args.extend(['-DBUILD_DEPRECATED:BOOL=ON'])
+        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(';')])
 
-        if '+external-blas' in spec:
-            cmake_args.extend([
-                '-DUSE_OPTIMIZED_BLAS:BOOL=ON',
-                '-DBLAS_LIBRARIES:PATH=%s' % spec['blas'].libs.joined(';')
-            ])
+        args.append('-DBUILD_TESTING:BOOL=' +
+                    ('ON' if self.run_tests else 'OFF'))
 
-        if spec.satisfies('+xblas'):
-            xblas_include_dir = spec['netlib-xblas'].prefix.include
-            xblas_library = spec['netlib-xblas'].libs.joined(';')
-            cmake_args.extend([
-                '-DXBLAS_INCLUDE_DIR={0}'.format(xblas_include_dir),
-                '-DXBLAS_LIBRARY={0}'.format(xblas_library)])
+        return args
 
-        cmake_args.extend(std_cmake_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(NetlibLapack, self).cmake(spec, prefix)
 
-        build_dir = 'spack-build' + ('-shared' if shared else '-static')
-        with working_dir(build_dir, create=True):
-            cmake('..', *cmake_args)
-            make()
-            make("install")
+    @when('+shared')
+    def build(self, spec, prefix):
+        for self._building_shared in (False, True):
+            super(NetlibLapack, self).build(spec, prefix)
 
+    @when('+shared')
     def install(self, spec, prefix):
-        # Always build static libraries.
-        self.install_one(spec, prefix, False)
+        for self._building_shared in (False, True):
+            super(NetlibLapack, self).install(spec, prefix)
 
-        # Build shared libraries if requested.
-        if '+shared' in spec:
-            self.install_one(spec, prefix, True)
+    @when('+shared')
+    def check(self):
+        for self._building_shared in (False, True):
+            super(NetlibLapack, self).check()
-- 
GitLab