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

Last change on this file since 3560 was 3560, checked in by ole, 18 years ago

Renamed pyvolution to abstract_2d_finite_volumes. This is
one step towards pulling pyvolution apart. More to follow.
All unit tests pass and most examples fixed up.




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