source: trunk/anuga_work/development/sudi/sw_1d/avalanche/B_momentum/compile_using_numpy.py @ 7912

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

Adding compile_all.py

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