xref: /petsc/config/configure.py (revision ee1cef2c4f92b4b45b8aa3ceac59cb944062fab9)
1#!/usr/bin/env python
2import os
3import sys
4import commands
5# to load ~/.pythonrc.py before inserting correct BuildSystem to path
6import user
7extraLogs = []
8petsc_arch = ''
9
10# Use en_US as language so that BuildSystem parses compiler messages in english
11os.environ['LANG'] = 'en_US'
12
13if not hasattr(sys, 'version_info') or not sys.version_info[1] >= 2 or not sys.version_info[0] >= 2:
14  print '**** You must have Python version 2.2 or higher to run config/configure.py ******'
15  print '*           Python is easy to install for end users or sys-admin.               *'
16  print '*                   http://www.python.org/download/                             *'
17  print '*                                                                               *'
18  print '*            You CANNOT configure PETSc without Python                          *'
19  print '*    http://www.mcs.anl.gov/petsc/petsc-as/documentation/installation.html      *'
20  print '*********************************************************************************'
21  sys.exit(4)
22
23def check_petsc_arch(opts):
24  # If PETSC_ARCH not specified - use script name (if not configure.py)
25  global petsc_arch
26  found = 0
27  for name in opts:
28    if name.find('PETSC_ARCH=') >= 0:
29      petsc_arch=name.split('=')[1]
30      found = 1
31      break
32  # If not yet specified - use the filename of script
33  if not found:
34      filename = os.path.basename(sys.argv[0])
35      if not filename.startswith('configure') and not filename.startswith('reconfigure'):
36        petsc_arch=os.path.splitext(os.path.basename(sys.argv[0]))[0]
37        useName = 'PETSC_ARCH='+petsc_arch
38        opts.append(useName)
39  return 0
40
41def chkbrokencygwin():
42  if os.path.exists('/usr/bin/cygcheck.exe'):
43    buf = os.popen('/usr/bin/cygcheck.exe -c cygwin').read()
44    if buf.find('1.5.11-1') > -1:
45      print '================================================================================='
46      print ' *** cygwin-1.5.11-1 detected. config/configure.py fails with this version   ***'
47      print ' *** Please upgrade to cygwin-1.5.12-1 or newer version. This can  ***'
48      print ' *** be done by running cygwin-setup, selecting "next" all the way.***'
49      print '================================================================================='
50      sys.exit(3)
51  return 0
52
53def chkusingwindowspython():
54  if os.path.exists('/usr/bin/cygcheck.exe') and sys.platform != 'cygwin':
55    print '================================================================================='
56    print ' *** Non-cygwin python detected. Please rerun config/configure.py with cygwin-python ***'
57    print '================================================================================='
58    sys.exit(3)
59  return 0
60
61def chkcygwinpythonver():
62  if os.path.exists('/usr/bin/cygcheck.exe'):
63    buf = os.popen('/usr/bin/cygcheck.exe -c python').read()
64    if (buf.find('2.4') > -1) or (buf.find('2.5') > -1) or (buf.find('2.6') > -1):
65      sys.argv.append('--useThreads=0')
66      extraLogs.append('''\
67================================================================================
68** Cygwin-python-2.4/2.5 detected. Threads do not work correctly with this version *
69 ********* Disabling thread usage for this run of config/configure.py **********
70================================================================================''')
71  return 0
72
73def chkrhl9():
74  if os.path.exists('/etc/redhat-release'):
75    try:
76      file = open('/etc/redhat-release','r')
77      buf = file.read()
78      file.close()
79    except:
80      # can't read file - assume dangerous RHL9
81      buf = 'Shrike'
82    if buf.find('Shrike') > -1:
83      sys.argv.append('--useThreads=0')
84      extraLogs.append('''\
85================================================================================
86   *** RHL9 detected. Threads do not work correctly with this distribution ***
87    ****** Disabling thread usage for this run of config/configure.py *******
88================================================================================''')
89  return 0
90
91def check_broken_configure_log_links():
92  '''Sometime symlinks can get broken if the original files are deleted. Delete such broken links'''
93  import os
94  for logfile in ['configure.log','configure.log.bkp']:
95    if os.path.islink(logfile) and not os.path.isfile(logfile): os.remove(logfile)
96  return
97
98def move_configure_log(framework):
99  '''Move configure.log to PETSC_ARCH/conf - and update configure.log.bkp in both locations appropriately'''
100  global petsc_arch
101
102  if hasattr(framework,'arch'): petsc_arch = framework.arch
103  if hasattr(framework,'logName'): curr_file = framework.logName
104  else: curr_file = 'configure.log'
105
106  if petsc_arch:
107    import shutil
108    import os
109
110    # Just in case - confdir is not created
111    conf_dir = os.path.join(petsc_arch,'conf')
112    if not os.path.isdir(petsc_arch): os.mkdir(petsc_arch)
113    if not os.path.isdir(conf_dir): os.mkdir(conf_dir)
114
115    curr_bkp  = curr_file + '.bkp'
116    new_file  = os.path.join(conf_dir,curr_file)
117    new_bkp   = new_file + '.bkp'
118
119    # Keep backup in $PETSC_ARCH/conf location
120    if os.path.isfile(new_bkp): os.remove(new_bkp)
121    if os.path.isfile(new_file): os.rename(new_file,new_bkp)
122    if os.path.isfile(curr_file): shutil.move(curr_file,new_file)
123    if os.path.isfile(new_file): os.symlink(new_file,curr_file)
124    # If the old bkp is using the same PETSC_ARCH/conf - then update bkp link
125    if os.path.realpath(curr_bkp) == os.path.realpath(new_file):
126      if os.path.isfile(curr_bkp): os.remove(curr_bkp)
127      if os.path.isfile(new_bkp): os.symlink(new_bkp,curr_bkp)
128  return
129
130def petsc_configure(configure_options):
131  print '================================================================================='
132  print '             Configuring PETSc to compile on your system                         '
133  print '================================================================================='
134
135  # Command line arguments take precedence (but don't destroy argv[0])
136  sys.argv = sys.argv[:1] + configure_options + sys.argv[1:]
137  # check PETSC_ARCH
138  check_petsc_arch(sys.argv)
139  check_broken_configure_log_links()
140
141  # support a few standard configure option types
142  for l in range(0,len(sys.argv)):
143    name = sys.argv[l]
144    if name.find('enable-') >= 0:
145      if name.find('=') == -1:
146        sys.argv[l] = name.replace('enable-','with-')+'=1'
147      else:
148        head, tail = name.split('=', 1)
149        sys.argv[l] = head.replace('enable-','with-')+'='+tail
150    if name.find('disable-') >= 0:
151      if name.find('=') == -1:
152        sys.argv[l] = name.replace('disable-','with-')+'=0'
153      else:
154        head, tail = name.split('=', 1)
155        if tail == '1': tail = '0'
156        sys.argv[l] = head.replace('disable-','with-')+'='+tail
157    if name.find('without-') >= 0:
158      if name.find('=') == -1:
159        sys.argv[l] = name.replace('without-','with-')+'=0'
160      else:
161        head, tail = name.split('=', 1)
162        if tail == '1': tail = '0'
163        sys.argv[l] = head.replace('without-','with-')+'='+tail
164
165  # Check for broken cygwin
166  chkbrokencygwin()
167  # Disable threads on RHL9
168  chkrhl9()
169  # Make sure cygwin-python is used on windows
170  chkusingwindowspython()
171  # Threads don't work for cygwin & python-2.4, 2.5 etc..
172  chkcygwinpythonver()
173
174  # Should be run from the toplevel
175  configDir = os.path.abspath('config')
176  bsDir     = os.path.join(configDir, 'BuildSystem')
177  if not os.path.isdir(configDir):
178    raise RuntimeError('Run configure from $PETSC_DIR, not '+os.path.abspath('.'))
179  if not os.path.isdir(bsDir):
180    print '================================================================================='
181    print '''++ Could not locate BuildSystem in %s.''' % configDir
182    print '''++ Downloading it using "hg clone http://hg.mcs.anl.gov/petsc/BuildSystem %s"''' % os.path.join(bsDir, 'BuildSystem')
183    print '================================================================================='
184    (status,output) = commands.getstatusoutput('hg clone http://petsc.cs.iit.edu/petsc/BuildSystem '+ os.path.join(bsDir, 'BuildSystem'))
185    if status:
186      if output.find('ommand not found') >= 0:
187        print '================================================================================='
188        print '''** Unable to locate hg (Mercurial) to download BuildSystem; make sure hg is in your path'''
189        print '''** or manually copy BuildSystem to $PETSC_DIR/config/BuildSystem from a machine where'''
190        print '''** you do have hg installed and can clone BuildSystem. '''
191        print '================================================================================='
192      elif output.find('Cannot resolve host') >= 0:
193        print '================================================================================='
194        print '''** Unable to download BuildSystem. You must be off the network.'''
195        print '''** Connect to the internet and run config/configure.py again.'''
196        print '================================================================================='
197      else:
198        print '================================================================================='
199        print '''** Unable to download BuildSystem. Please send this message to petsc-maint@mcs.anl.gov'''
200        print '================================================================================='
201      print output
202      sys.exit(3)
203
204  sys.path.insert(0, bsDir)
205  sys.path.insert(0, configDir)
206  import config.base
207  import config.framework
208  import cPickle
209
210  # Disable shared libraries by default
211  import nargs
212  if nargs.Arg.findArgument('with-shared', sys.argv[1:]) is None:
213    sys.argv.append('--with-shared=0')
214
215  framework = None
216  try:
217    framework = config.framework.Framework(['--configModules=PETSc.Configure','--optionsModule=PETSc.compilerOptions']+sys.argv[1:], loadArgDB = 0)
218    framework.setup()
219    framework.logPrint('\n'.join(extraLogs))
220    framework.configure(out = sys.stdout)
221    framework.storeSubstitutions(framework.argDB)
222    framework.argDB['configureCache'] = cPickle.dumps(framework)
223    import PETSc.packages
224    for i in framework.packages:
225      if hasattr(i,'postProcess'):
226        i.postProcess()
227    framework.logClear()
228    framework.closeLog()
229    move_configure_log(framework)
230    return 0
231  except (RuntimeError, config.base.ConfigureSetupError), e:
232    emsg = str(e)
233    if not emsg.endswith('\n'): emsg = emsg+'\n'
234    msg ='*********************************************************************************\n'\
235    +'         UNABLE to CONFIGURE with GIVEN OPTIONS    (see configure.log for details):\n' \
236    +'---------------------------------------------------------------------------------------\n'  \
237    +emsg+'*********************************************************************************\n'
238    se = ''
239  except (TypeError, ValueError), e:
240    emsg = str(e)
241    if not emsg.endswith('\n'): emsg = emsg+'\n'
242    msg ='*********************************************************************************\n'\
243    +'                ERROR in COMMAND LINE ARGUMENT to config/configure.py \n' \
244    +'---------------------------------------------------------------------------------------\n'  \
245    +emsg+'*********************************************************************************\n'
246    se = ''
247  except ImportError, e :
248    emsg = str(e)
249    if not emsg.endswith('\n'): emsg = emsg+'\n'
250    msg ='*********************************************************************************\n'\
251    +'                     UNABLE to FIND MODULE for config/configure.py \n' \
252    +'---------------------------------------------------------------------------------------\n'  \
253    +emsg+'*********************************************************************************\n'
254    se = ''
255  except OSError, e :
256    emsg = str(e)
257    if not emsg.endswith('\n'): emsg = emsg+'\n'
258    msg ='*********************************************************************************\n'\
259    +'                    UNABLE to EXECUTE BINARIES for config/configure.py \n' \
260    +'---------------------------------------------------------------------------------------\n'  \
261    +emsg+'*********************************************************************************\n'
262    se = ''
263  except SystemExit, e:
264    if e.code is None or e.code == 0:
265      return
266    msg ='*********************************************************************************\n'\
267    +'           CONFIGURATION FAILURE  (Please send configure.log to petsc-maint@mcs.anl.gov)\n' \
268    +'*********************************************************************************\n'
269    se  = str(e)
270  except Exception, e:
271    msg ='*********************************************************************************\n'\
272    +'          CONFIGURATION CRASH  (Please send configure.log to petsc-maint@mcs.anl.gov)\n' \
273    +'*********************************************************************************\n'
274    se  = str(e)
275
276  print msg
277  if not framework is None:
278    framework.logClear()
279    if hasattr(framework, 'log'):
280      import traceback
281      try:
282        framework.log.write(msg+se)
283        traceback.print_tb(sys.exc_info()[2], file = framework.log)
284        move_configure_log(framework)
285      except:
286        pass
287      sys.exit(1)
288  else:
289    print se
290    import traceback
291    traceback.print_tb(sys.exc_info()[2])
292  move_configure_log(framework)
293
294if __name__ == '__main__':
295  petsc_configure([])
296
297