source: trunk/anuga_work/development/sudi/sw_1d/shock_detector/shm/compile_using_Numeric.py @ 7909

Last change on this file since 7909 was 7909, checked in by mungkasi, 14 years ago

Add 1d codes.

File size: 11.6 KB
Line 
1"""compile.py - compile Python C-extension
2
3   Commandline usage:
4     python compile.py <filename>
5
6   Usage from within Python:
7     import compile
8     compile.compile(<filename>,..)
9
10   Ole Nielsen, Duncan Gray Oct 2001     
11"""     
12
13# FIXME (Ole): Although this script says it works with a range of compilers,
14# it has only really been used with gcc.
15
16import os, string, sys, types
17
18separation_line = '---------------------------------------'     
19 
20def compile(FNs=None, CC=None, LD = None, SFLAG = None, verbose = 1):
21  """compile(FNs=None, CC=None, LD = None, SFLAG = None):
22 
23     Compile FN(s) using compiler CC (e.g. mpicc),
24     Loader LD and shared flag SFLAG.
25     If CC is absent use default compiler dependent on platform
26     if LD is absent CC is used.
27     if SFLAG is absent platform default is used
28     FNs can be either one filename or a list of filenames
29     In the latter case, the first will be used to name so file.
30  """
31 
32  # Input check
33  #
34  assert not FNs is None, 'No filename provided'
35
36  if not type(FNs) == types.ListType:
37    FNs = [FNs]
38
39
40  libext = 'so' #Default extension (Unix)
41  libs = ''
42  version = sys.version[:3]
43 
44  # Determine platform and compiler
45  #
46  if sys.platform == 'sunos5':  #Solaris
47    if CC:
48      compiler = CC
49    else: 
50      compiler = 'gcc'
51    if LD:
52      loader = LD
53    else: 
54      loader = compiler
55    if SFLAG:
56      sharedflag = SFLAG
57    else: 
58      sharedflag = 'G'
59     
60  elif sys.platform == 'osf1V5':  #Compaq AlphaServer
61    if CC:
62      compiler = CC
63    else: 
64      compiler = 'cc'
65    if LD:
66      loader = LD
67    else: 
68      loader = compiler
69    if SFLAG:
70      sharedflag = SFLAG
71    else: 
72      sharedflag = 'shared'   
73     
74  elif sys.platform == 'linux2':  #Linux
75    if CC:
76      compiler = CC
77    else: 
78      compiler = 'gcc'
79    if LD:
80      loader = LD
81    else: 
82      loader = compiler
83    if SFLAG:
84      sharedflag = SFLAG
85    else: 
86      sharedflag = 'shared'   
87     
88  elif sys.platform == 'darwin':  #Mac OS X:
89    if CC:
90      compiler = CC
91    else: 
92      compiler = 'cc'
93    if LD:
94      loader = LD
95    else: 
96      loader = compiler
97    if SFLAG:
98      sharedflag = SFLAG
99    else: 
100      sharedflag = 'bundle -flat_namespace -undefined suppress'
101
102  elif sys.platform == 'cygwin':  #Cygwin (compilation same as linux)
103    if CC:
104      compiler = CC
105    else: 
106      compiler = 'gcc'
107    if LD:
108      loader = LD
109    else: 
110      loader = compiler
111    if SFLAG:
112      sharedflag = SFLAG
113    else: 
114      sharedflag = 'shared'
115    libext = 'dll'
116    libs = '/lib/python%s/config/libpython%s.dll.a' %(version,version)
117     
118  elif sys.platform == 'win32':  #Windows
119    if CC:
120      compiler = CC
121    else: 
122      compiler = 'gcc.exe' #Some systems require this (a security measure?)
123    if LD:
124      loader = LD
125    else: 
126      loader = compiler
127    if SFLAG:
128      sharedflag = SFLAG
129    else: 
130      sharedflag = 'shared'
131     
132    # As of python2.5, .pyd is the extension for python extension
133    # modules.
134    if sys.version_info[0:2] >= (2, 5):
135      libext = 'pyd'
136    else:
137      libext = 'dll'
138
139    libs, is_found = set_python_dll_path()
140     
141  else:
142    if verbose: print "Unrecognised platform %s - revert to default"\
143                %sys.platform
144   
145    if CC:
146      compiler = CC
147    else: 
148      compiler = 'cc'
149    if LD:
150      loader = LD
151    else: 
152      loader = 'ld'
153    if SFLAG:
154      sharedflag = SFLAG
155    else: 
156      sharedflag = 'G'
157
158
159  # Verify that compiler can be executed
160  print 'Compiler: %s, version ' %compiler,
161  sys.stdout.flush()
162  s = '%s -dumpversion' %(compiler)
163  err = os.system(s)
164  print
165 
166  if err != 0:
167      msg = 'Unable to execute compiler: %s. ' %compiler
168      msg += 'Make sure it is available on the system path.\n'
169      msg += 'One way to check this is to run %s on ' %compiler
170      msg += 'the commandline.'
171      raise Exception, msg   
172
173 
174  # Find location of include files
175  #
176  if sys.platform == 'win32':  #Windows
177    python_include = os.path.join(sys.exec_prefix, 'include')   
178  else: 
179    python_include = os.path.join(os.path.join(sys.exec_prefix, 'include'),
180                                  'python' + version)
181
182  # Check existence of Python.h
183  #
184  headerfile = python_include + os.sep + 'Python.h'
185  try:
186    open(headerfile, 'r')
187  except:
188    raise """Did not find Python header file %s.
189    Make sure files for Python C-extensions are installed.
190    In debian linux, for example, you need to install a
191    package called something like python2.3-dev""" %headerfile
192
193
194
195  # Add Python path + utilities to includelist (see ticket:31)
196  # Assume there is only one 'utilities' dir under path dirs
197 
198  utilities_include_dir = None
199  for pathdir in sys.path:
200
201    utilities_include_dir = pathdir + os.sep + 'utilities'
202    #print pathdir
203    #print utilities_include_dir
204    try:
205      os.stat(utilities_include_dir)
206    except OSError:
207      pass
208    else:
209      #print 'Found %s to be used as include dir' %utilities_include_dir
210      break
211
212  # This is hacky since it
213  # assumes the location of the compile_all that determines buildroot
214  try:
215    utilities_include_dir = buildroot + os.sep + "source" + os.sep + "anuga" \
216                            + os.sep + 'utilities'
217  except:
218    # This will make compile work locally
219    utilities_include_dir = '.'
220    utilities_include_dir = '../utilities'
221
222
223   
224  try:
225    os.stat(utilities_include_dir)
226  except OSError: 
227    utilities_include_dir = buildroot + os.sep + 'utilities'
228 
229 
230 
231  # Check filename(s)
232  #
233  object_files = ''
234  for FN in FNs:       
235    root, ext = os.path.splitext(FN)
236    if ext == '':
237      FN = FN + '.c'
238    elif ext.lower() != '.c':
239      raise Exception, "Unrecognised extension: " + FN
240   
241    try:
242      open(FN, 'r')
243    except:
244      raise Exception, "Could not open: " + FN
245
246    if not object_files: root1 = root  #Remember first filename       
247    object_files += root + '.o ' 
248 
249 
250    # Compile
251    #
252    if utilities_include_dir is None:   
253      s = '%s -c %s -I"%s" -o "%s.o" -Wall -O3'\
254          %(compiler, FN, python_include, root)
255    else:
256      if FN == "triangle.c" or FN == "mesh_engine_c_layer.c":
257        s = '%s -c %s -I"%s" -I"%s" -o "%s.o" -O3 -DTRILIBRARY=1 -DNO_TIMER=1'\
258            %(compiler, FN, python_include, utilities_include_dir, root)
259      elif FN == "polygon_ext.c":
260        # gcc 4.3.x is problematic with this file if '-O3' is used
261        s = '%s -c %s -I"%s" -I"%s" -o "%s.o" -Wall'\
262            %(compiler, FN, python_include, utilities_include_dir, root)
263      else:
264        s = '%s -c %s -I"%s" -I"%s" -o "%s.o" -Wall -O3'\
265            %(compiler, FN, python_include, utilities_include_dir, root)
266
267    if os.name == 'posix' and os.uname()[4] in ['x86_64', 'ia64']:
268      # Extra flags for 64 bit architectures.
269      #   AMD Opteron will give x86_64
270      #   Itanium will give ia64
271      #
272      # Second clause will always fail on Win32 because uname is UNIX specific
273      # but won't get past first clause
274
275      s += ' -fPIC' # Use position independent code for 64 bit archs
276      #s += ' -m64' # Used to be necessary for AMD Opteron
277     
278     
279    if verbose:
280      print s
281
282    # Doesn't work on Windows anyway 
283    #else:
284    #  s = s + ' 2> /dev/null' #Suppress errors
285   
286    try:
287      err = os.system(s)
288      if err != 0:
289          raise 'Attempting to compile %s failed - please try manually' %FN
290    except:
291      raise 'Could not compile %s - please try manually' %FN 
292
293 
294  # Make shared library (*.so or *.dll)
295  if libs is "":
296    s = '%s -%s %s -o %s.%s -lm' %(loader, sharedflag, object_files, root1, libext)
297  else:
298    s = '%s -%s %s -o %s.%s "%s" -lm' %(loader, sharedflag, object_files, root1, libext, libs)
299   
300  if verbose:
301    print s
302
303  # Doesn't work on Windows anyway     
304  #else:
305  #  s = s + ' 2> /dev/null' #Suppress warnings
306 
307  try: 
308    err=os.system(s)
309    if err != 0:       
310        raise 'Attempting to link %s failed - please try manually' %root1     
311  except:
312    raise 'Could not link %s - please try manually' %root1
313   
314
315def can_use_C_extension(filename):
316    """Determine whether specified C-extension
317    can and should be used.
318    """
319
320    from anuga.config import use_extensions
321
322    from os.path import splitext
323
324    root, ext = splitext(filename)
325   
326    C=False
327    if use_extensions:
328        try:
329            s = 'import %s' %root
330            #print s
331            exec(s)
332        except:
333            try:
334                open(filename)
335            except:
336                msg = 'C extension %s cannot be opened' %filename
337                print msg               
338            else:   
339                print '------- Trying to compile c-extension %s' %filename
340           
341                try:
342                    compile(filename)
343                except:
344                    print 'WARNING: Could not compile C-extension %s'\
345                          %filename
346                else:
347                    try:
348                        exec('import %s' %root)
349                    except:
350                        msg = 'C extension %s seems to compile OK, '
351                        msg += 'but it can still not be imported.'
352                        raise msg
353                    else:
354                        C=True
355        else:
356            C=True
357           
358    if not C:
359        pass
360        print 'NOTICE: C-extension %s not used' %filename
361
362    return C
363
364
365def set_python_dll_path():
366  """ On windows, find which of the two usual hiding places the python
367  dll is located.
368
369  If the file can't be found, return None.
370  """
371  import sys
372  from os import access, F_OK
373 
374  version = sys.version[:3]
375  v = version.replace('.','')
376  dllfilename = 'python%s.dll' %(v)
377  libs = os.path.join(sys.exec_prefix,dllfilename)
378
379  is_found = True   
380  if access(libs,F_OK) == 0 :
381    # Sometimes python dll is hidden in %WINDIR%/system32
382    libs = os.path.join(os.environ.get('WINDIR', 'C:\WINNT'), 'system32',
383                        dllfilename)
384    if access(libs,F_OK) == 0 :
385      # could not find the dll
386      libs = os.path.join(sys.exec_prefix,dllfilename)
387      is_found = False
388  return libs, is_found
389
390def check_python_dll():
391  libs, is_found = set_python_dll_path()
392  if not is_found:
393    print "%s not found.\nPlease install.\nIt is available on the web." \
394              %(libs)
395    import sys; sys.exit()
396   
397     
398if __name__ == '__main__':
399  from os.path import splitext
400 
401  if sys.platform == 'win32':
402    check_python_dll()
403  if len(sys.argv) > 1:
404      files = sys.argv[1:]
405      for filename in files:
406          root, ext = splitext(filename)
407
408          if ext <> '.c':
409              print 'WARNING (compile.py): Skipping %s. I only compile C-files.' %filename
410     
411  else: 
412      #path = os.path.split(sys.argv[0])[0] or os.getcwd()
413      path = '.'
414      files = os.listdir(path)
415     
416     
417
418  for filename in files:
419      root, ext = splitext(filename)
420
421      if ext == '.c':
422          for x in ['.dll', '.so']:
423              try:
424                  os.remove(root + x)
425              except:
426                  pass
427
428          print separation_line
429          print 'Trying to compile c-extension %s in %s'\
430                %(filename, os.getcwd())
431          try:
432            if filename == 'triang.c': 
433              compile(['triang.c','triangle.c'])
434            elif  filename == 'mesh_engine_c_layer.c': 
435              compile(['mesh_engine_c_layer.c','triangle.c'])
436            else:
437              compile(filename)
438          except Exception, e:
439              msg = 'Could not compile C extension %s\n' %filename
440              msg += str(e)
441              raise Exception, msg
442          else:
443              print 'C extension %s OK' %filename
444          print   
445       
446
Note: See TracBrowser for help on using the repository browser.