source: anuga_core/source/anuga/utilities/compile.py @ 4448

Last change on this file since 4448 was 4448, checked in by duncan, 17 years ago

only one compile.py cont..

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