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