File: cmakeboot.py

package info (click to toggle)
slepc 3.10.1%2Bdfsg1-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 29,068 kB
  • sloc: ansic: 92,160; python: 4,121; makefile: 2,931; fortran: 1,694; f90: 1,442; sh: 285
file content (191 lines) | stat: -rwxr-xr-x 9,213 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env python

# This file initializes a CMake build in $SLEPC_DIR/$PETSC_ARCH using
# the compilers and flags determined by BuildSystem. It is imported and
# called by configure.py during configures in which CMake was detected,
# but it can also be run as a stand-alone program. The library paths and
# flags should have been written to
#
#     $PETSC_DIR/$PETSC_ARCH/lib/petsc/conf/PETScBuildInternal.cmake
#     $SLEPC_DIR/$PETSC_ARCH/lib/slepc/conf/SLEPcBuildInternal.cmake
#
# by configure before running this script.

from __future__ import print_function
import os,sys,string
from collections import deque
sys.path.insert(0, os.path.join(os.environ['PETSC_DIR'],'config'))
sys.path.insert(0, os.path.join(os.environ['PETSC_DIR'],'config','BuildSystem'))
import script

def noCheck(command, status, output, error):
  return

def quoteIfNeeded(path):
  "Don't need quotes unless the path has bits that would confuse the shell"
  safe = string.letters + string.digits + os.path.sep + os.path.pardir + '-_'
  if set(path).issubset(safe):
    return path
  else:
    return '"' + path + '"'

class StdoutLogger(object):
  def write(self,str):
    print(str)

class PETScMaker(script.Script):
 def __init__(self, slepcdir, petscdir, petscarch, argDB = None, framework = None):
   import RDict

   if not argDB:
     argDB = RDict.RDict(None, None, 0, 0, readonly = True)
     argDB.saveFilename = os.path.join(petscdir,petscarch,'lib','petsc','conf','RDict.db')
     argDB.load()
   script.Script.__init__(self, argDB = argDB)
   self.framework = framework
   self.slepcdir  = slepcdir

 def __str__(self):
   return ''

 def setupModules(self):
   self.mpi           = self.framework.require('config.packages.MPI',         None)
   self.base          = self.framework.require('config.base',                 None)
   self.setCompilers  = self.framework.require('config.setCompilers',         None)
   self.arch          = self.framework.require('PETSc.options.arch',        None)
   self.petscdir      = self.framework.require('PETSc.options.petscdir',    None)
   self.languages     = self.framework.require('PETSc.options.languages',   None)
   self.debugging     = self.framework.require('PETSc.options.debugging',   None)
   self.cmake         = self.framework.require('config.packages.cmake',       None)
   self.compilers     = self.framework.require('config.compilers',            None)
   self.types         = self.framework.require('config.types',                None)
   self.headers       = self.framework.require('config.headers',              None)
   self.functions     = self.framework.require('config.functions',            None)
   self.libraries     = self.framework.require('config.libraries',            None)
   self.scalarType    = self.framework.require('PETSc.options.scalarTypes', None)
   self.memAlign      = self.framework.require('PETSc.options.memAlign',    None)
   self.compilerFlags = self.framework.require('config.compilerFlags', self)
   return

 def setup(self):
   script.Script.setup(self)
   if not self.framework:
     self.framework = self.loadConfigure()
   self.setupModules()

 def cmakeboot(self, args, log):
   import shlex
   self.setup()
   options = deque()

   output,error,retcode = self.executeShellCommand([self.cmake.cmake, '--version'], checkCommand=noCheck, log=log)
   import re
   m = re.match(r'cmake version (.+)', output)
   if not m:
       self.logPrint('Could not parse CMake version: %s, disabling cmake build option' % output)
       return False
   from distutils.version import LooseVersion
   version = LooseVersion(m.groups()[0])
   if version < LooseVersion('2.6.2'):
       self.logPrint('CMake version %s < 2.6.2, disabling cmake build option' % version.vstring)
       return False
   if self.languages.clanguage == 'Cxx' and version < LooseVersion('2.8'):
       self.logPrint('Cannot use --with-clanguage=C++ with CMake version %s < 2.8, disabling cmake build option' % version.vstring)
       return False # no support for: set_source_files_properties(${file} PROPERTIES LANGUAGE CXX)

   langlist = [('C','C')]
   if hasattr(self.compilers,'FC'):
     langlist.append(('FC','Fortran'))
   if hasattr(self.compilers,'CUDAC'):
     langlist.append(('CUDA','CUDA'))
   if hasattr(self.compilers,'CXX'):
     langlist.append(('Cxx','CXX'))
   win32fe = None
   for petsclanguage,cmakelanguage in langlist:
     self.setCompilers.pushLanguage(petsclanguage)
     compiler = self.setCompilers.getCompiler()
     if (cmakelanguage == 'CUDA'):
       self.cuda = self.framework.require('config.packages.cuda',       None)
       if (self.cuda.directory != None):
         options.append('CUDA_TOOLKIT_ROOT_DIR ' + self.cuda.directory + ' CACHE FILEPATH')
       options.append('CUDA_NVCC_FLAGS ' + self.setCompilers.getCompilerFlags() + ' CACHE STRING')
     else:
       flags = [self.setCompilers.getCompilerFlags(),
                self.setCompilers.CPPFLAGS]
       if compiler.split()[0].endswith('win32fe'): # Hack to support win32fe without changing the rest of configure
         win32fe = compiler.split()[0] + '.exe'
         compiler = ' '.join(compiler.split()[1:])
       options.append('CMAKE_'+cmakelanguage+'_COMPILER ' + compiler + ' CACHE FILEPATH')
       options.append('CMAKE_'+cmakelanguage+'_FLAGS "' + ''.join(flags) + '" CACHE STRING')
       if (petsclanguage == self.languages.clanguage): #CUDA host compiler is fed with the flags for the standard host compiler
         flagstring = ''
         for flag in flags:
           for f in flag.split():
             flagstring += ',' + f
         options.append('PETSC_CUDA_HOST_FLAGS ' + flagstring + ' CACHE STRING')
       self.setCompilers.popLanguage()
   options.append('CMAKE_AR '+self.setCompilers.AR + " CACHE FILEPATH")
   ranlib = shlex.split(self.setCompilers.RANLIB)[0]
   options.append('CMAKE_RANLIB '+ranlib + " CACHE FILEPATH")
   if win32fe:
     options.append('PETSC_WIN32FE %s' % win32fe)

   archdir = os.path.join(self.slepcdir, self.arch.arch)
   initial_cache_filename = os.path.join(archdir, 'initial_cache_file.cmake')
   cmd = [self.cmake.cmake, '--trace', '--debug-output', '-C' + str(initial_cache_filename), '-DPETSC_CMAKE_ARCH:STRING='+str(self.arch.arch), self.slepcdir] + args
   if win32fe:
     # Default on Windows is to generate Visual Studio project files, but
     # 1. the build process for those is different, need to give different build instructions
     # 2. the current WIN32FE workaround does not work with VS project files
     cmd.append('-GUnix Makefiles')

   # Create inital cache file:
   initial_cache_file = open(initial_cache_filename, 'w')
   self.logPrint('Contents of initial cache file %s :' % initial_cache_filename)
   for option in options:
     initial_cache_file.write('SET (' + option + ' "Dummy comment" FORCE)\n')
     self.logPrint('SET (' + option + ' "Dummy comment" FORCE)\n')
   initial_cache_file.close()
   try:
     # Try to remove the old cache because some versions of CMake lose CMAKE_C_FLAGS when reconfiguring this way
     self.logPrint('Removing: %s' % os.path.join(archdir, 'CMakeCache.txt'))
     os.remove(os.path.join(archdir, 'CMakeCache.txt'))
   except OSError:
     pass
   import shutil
   # Try to remove all the old CMake files to avoid infinite loop (CMake-2.8.10.2, maybe other versions)
   # http://www.mail-archive.com/cmake@cmake.org/msg44765.html
   self.logPrint('Removing: %s' % os.path.join(archdir, 'CMakeFiles', version.vstring))
   shutil.rmtree(os.path.join(archdir, 'CMakeFiles', version.vstring), ignore_errors=True)
   log.write('Invoking: %s\n' % cmd)
   output,error,retcode = self.executeShellCommand(cmd, checkCommand = noCheck, log=log, cwd=archdir,timeout=300)
   if retcode:
     self.logPrint('CMake setup incomplete (status %d), disabling cmake build option' % (retcode,))
     self.logPrint('Output: '+output+'\nError: '+error)
     cachetxt = os.path.join(archdir, 'CMakeCache.txt')
     try:
       f = open(cachetxt, 'r')
       log.write('Contents of %s:\n' % cachetxt)
       log.write(f.read())
       f.close()
     except IOError as e:
       log.write('Could not read file %s: %r\n' % (cachetxt, e))
     return False
   else:
     return True # Configure successful

def main(slepcdir, petscdir, petscarch=os.environ['PETSC_ARCH'], argDB=None, framework=None, log=StdoutLogger(), args=[]):
  # This can be called as a stand-alone program, or by importing it from
  # python.  The latter functionality is needed because argDB does not
  # get written until the very end of configure, but we want to run this
  # automatically during configure (if CMake is available).
  #
  # Strangely, we can't store log in the PETScMaker because
  # (somewhere) it creeps into framework (which I don't want to modify)
  # and makes the result unpickleable.  This is not a problem when run
  # as a standalone program (because the database is read-only), but is
  # not okay when called from configure.
  return PETScMaker(slepcdir,petscdir,petscarch,argDB,framework).cmakeboot(args,log)

if __name__ == "__main__":
  main(slepcdir=os.environ['SLEPC_DIR'], petscdir=os.environ['PETSC_DIR'], petscarch=os.environ['PETSC_ARCH'], args=sys.argv[1:])