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

Last change on this file since 4527 was 4493, checked in by steve, 18 years ago

Testing eclipse settings

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     
130    libext = 'dll'
131
132    v = version.replace('.','')
133    dllfilename = 'python%s.dll' %(v)
134    libs = os.path.join(sys.exec_prefix,dllfilename)
135
136     
137     
138  else:
139    if verbose: print "Unrecognised platform %s - revert to default"\
140                %sys.platform
141   
142    if CC:
143      compiler = CC
144    else: 
145      compiler = 'cc'
146    if LD:
147      loader = LD
148    else: 
149      loader = 'ld'
150    if SFLAG:
151      sharedflag = SFLAG
152    else: 
153      sharedflag = 'G'
154
155   
156       
157  # Find location of include files
158  #
159  if sys.platform == 'win32':  #Windows
160    python_include = os.path.join(sys.exec_prefix, 'include')   
161  else: 
162    python_include = os.path.join(os.path.join(sys.exec_prefix, 'include'),
163                                  'python' + version)
164
165  # Check existence of Python.h
166  #
167  headerfile = python_include + os.sep + 'Python.h'
168  try:
169    open(headerfile, 'r')
170  except:
171    raise """Did not find Python header file %s.
172    Make sure files for Python C-extensions are installed.
173    In debian linux, for example, you need to install a
174    package called something like python2.3-dev""" %headerfile
175
176
177
178  #Add Python path + utilities to includelist (see ticket:31)
179  #Assume there is only one 'utilities' dir under path dirs
180 
181  utilities_include_dir = None
182  for pathdir in sys.path:
183
184    utilities_include_dir = pathdir + os.sep + 'utilities'
185    #print pathdir
186    #print utilities_include_dir
187    try:
188      os.stat(utilities_include_dir)
189    except OSError:
190      pass
191    else:
192      #print 'Found %s to be used as include dir' %utilities_include_dir
193      break
194
195  # This is hacky since it
196  # assumes the location of the compile_all that determines buildroot
197  try:
198    utilities_include_dir = buildroot + os.sep + "source" + os.sep + "anuga" \
199                            + os.sep + 'utilities'
200  except:
201    # This will make compile work locally
202    utilities_include_dir = '.'
203
204
205   
206  try:
207    os.stat(utilities_include_dir)
208  except OSError: 
209    utilities_include_dir = buildroot + os.sep + 'utilities'
210 
211 
212 
213  # Check filename(s)
214  #
215  object_files = ''
216  for FN in FNs:       
217    root, ext = os.path.splitext(FN)
218    if ext == '':
219      FN = FN + '.c'
220    elif ext.lower() != '.c':
221      raise Exception, "Unrecognised extension: " + FN
222   
223    try:
224      open(FN, 'r')
225    except:
226      raise Exception, "Could not open: " + FN
227
228    if not object_files: root1 = root  #Remember first filename       
229    object_files += root + '.o ' 
230 
231 
232    # Compile
233    #
234    if utilities_include_dir is None:   
235      s = '%s -c %s -I"%s" -o "%s.o" -Wall -O3'\
236          %(compiler, FN, python_include, root)
237    else:
238      if FN == "triangle.c" or FN == "mesh_engine_c_layer.c":
239        s = '%s -c %s -I"%s" -I"%s" -o "%s.o" -O3 -DTRILIBRARY=1 -DNO_TIMER=1'\
240            %(compiler, FN, python_include, utilities_include_dir, root)
241      else:
242        s = '%s -c %s -I"%s" -I"%s" -o "%s.o" -Wall -O3'\
243            %(compiler, FN, python_include, utilities_include_dir, root)
244
245    if os.name == 'posix' and os.uname()[4] == 'x86_64':
246      #Extra flags for 64 bit architectures
247      #Second clause will always fail on Win32 because uname is UNIX specific
248      #but won't get past first clause
249
250      #FIXME: Which one?
251      #s += ' -fPIC'
252      s += ' -fPIC -m64' 
253     
254     
255    if verbose:
256      print s
257    else:
258      s = s + ' 2> /dev/null' #Suppress errors
259 
260    try:
261      err = os.system(s)
262      if err != 0:
263          raise 'Attempting to compile %s failed - please try manually' %FN
264    except:
265      raise 'Could not compile %s - please try manually' %FN 
266
267 
268  # Make shared library (*.so or *.dll)
269  if libs is "":
270    s = '%s -%s %s -o %s.%s -lm' %(loader, sharedflag, object_files, root1, libext)
271  else:
272    s = '%s -%s %s -o %s.%s "%s" -lm' %(loader, sharedflag, object_files, root1, libext, libs)
273  if verbose:
274    print s
275  else:
276    s = s + ' 2> /dev/null' #Suppress warnings
277 
278  try: 
279    err=os.system(s)
280    if err != 0:       
281        raise 'Atempting to link %s failed - please try manually' %root1     
282  except:
283    raise 'Could not link %s - please try manually' %root1
284   
285
286def can_use_C_extension(filename):
287    """Determine whether specified C-extension
288    can and should be used.
289    """
290
291    from anuga.config import use_extensions
292
293    from os.path import splitext
294
295    root, ext = splitext(filename)
296   
297    C=False
298    if use_extensions:
299        try:
300            s = 'import %s' %root
301            #print s
302            exec(s)
303        except:
304            try:
305                open(filename)
306            except:
307                msg = 'C extension %s cannot be opened' %filename
308                print msg               
309            else:   
310                print '------- Trying to compile c-extension %s' %filename
311           
312                try:
313                    compile(filename)
314                except:
315                    print 'WARNING: Could not compile C-extension %s'\
316                          %filename
317                else:
318                    try:
319                        exec('import %s' %root)
320                    except:
321                        msg = 'C extension %s seems to compile OK, '
322                        msg += 'but it can still not be imported.'
323                        raise msg
324                    else:
325                        C=True
326        else:
327            C=True
328           
329    if not C:
330        pass
331        print 'NOTICE: C-extension %s not used' %filename
332
333    return C
334
335
336if __name__ == '__main__':
337
338
339  import sys, os
340  from os.path import splitext
341 
342  if len(sys.argv) > 1:
343      files = sys.argv[1:]
344      for filename in files:
345          root, ext = splitext(filename)
346
347          if ext <> '.c':
348              print 'WARNING (compile.py): Skipping %s. I only compile C-files.' %filename
349     
350  else: 
351      #path = os.path.split(sys.argv[0])[0] or os.getcwd()
352      path = '.'
353      files = os.listdir(path)
354     
355     
356
357  for filename in files:
358      root, ext = splitext(filename)
359
360      if ext == '.c':
361          for x in ['.dll', '.so']:
362              try:
363                  os.remove(root + x)
364              except:
365                  pass
366
367          print '---------------------------------------'     
368          print 'Trying to compile c-extension %s in %s'\
369                %(filename, os.getcwd())
370          try:
371            if filename == 'triang.c': 
372              compile(['triang.c','triangle.c'])
373            elif  filename == 'mesh_engine_c_layer.c': 
374              compile(['mesh_engine_c_layer.c','triangle.c'])
375            else:
376              compile(filename)
377          except Exception, e:
378              print 'Could not compile C extension %s' %filename
379          else:
380              print 'C extension %s OK' %filename
381          print   
382       
383
Note: See TracBrowser for help on using the repository browser.