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

Last change on this file since 3526 was 3526, checked in by duncan, 18 years ago

Hacking compile.py to avoid errors.

File size: 8.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, 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  utilities_include_dir = buildroot + os.sep + "source" + os.sep + "anuga" \
196                          + os.sep + 'utilities' 
197  try:
198    os.stat(utilities_include_dir)
199  except OSError: 
200    utilities_include_dir = buildroot + os.sep + 'utilities'
201 
202 
203 
204  # Check filename(s)
205  #
206  object_files = ''
207  for FN in FNs:       
208    root, ext = os.path.splitext(FN)
209    if ext == '':
210      FN = FN + '.c'
211    elif ext.lower() != '.c':
212      raise Exception, "Unrecognised extension: " + FN
213   
214    try:
215      open(FN, 'r')
216    except:
217      #print 'CWD:', os.getcwd()     
218      raise Exception, "Could not open: " + FN
219
220    if not object_files: root1 = root  #Remember first filename       
221    object_files += root + '.o ' 
222 
223 
224    # Compile
225    #
226    if utilities_include_dir is None:   
227      s = '%s -c %s -I%s -o %s.o -Wall -O3'\
228          %(compiler, FN, python_include, root)
229    else:
230      s = '%s -c %s -I%s -I%s -o %s.o -Wall -O3'\
231          %(compiler, FN, python_include, utilities_include_dir, root)
232
233    if os.name == 'posix' and os.uname()[4] == 'x86_64':
234      #Extra flags for 64 bit architectures
235      #Second clause will always fail on Win32 because uname is UNIX specific
236      #but won't get past first clause
237
238      #FIXME: Which one?
239      #s += ' -fPIC'
240      s += ' -fPIC -m64' 
241     
242     
243    if verbose:
244      print s
245    else:
246      s = s + ' 2> /dev/null' #Suppress errors
247 
248    try:
249      err = os.system(s)
250      if err != 0:
251          raise 'Attempting to compile %s failed - please try manually' %FN
252    except:
253      raise 'Could not compile %s - please try manually' %FN 
254
255 
256  # Make shared library (*.so or *.dll)
257 
258  s = "%s -%s %s -o %s.%s %s -lm" %(loader, sharedflag, object_files, root1, libext, libs)
259  if verbose:
260    print s
261  else:
262    s = s + ' 2> /dev/null' #Suppress warnings
263 
264  try: 
265    err=os.system(s)
266    if err != 0:       
267        raise 'Atempting to link %s failed - please try manually' %root1     
268  except:
269    raise 'Could not link %s - please try manually' %root1
270   
271
272def can_use_C_extension(filename):
273    """Determine whether specified C-extension
274    can and should be used.
275    """
276
277
278    from os.path import splitext
279
280    root, ext = splitext(filename)
281   
282    C=False
283
284    try:
285        s = 'import %s' %root
286        #print s
287        exec(s)
288    except:
289        try:
290            open(filename)
291        except:
292            msg = 'C extension %s cannot be opened' %filename
293            print msg               
294        else:   
295            print '------- Trying to compile c-extension %s' %filename
296
297            #compile(filename)       
298            try:
299                compile(filename)
300            except:
301                print 'WARNING: Could not compile C-extension %s'\
302                      %filename
303            else:
304                try:
305                    exec('import %s' %root)
306                except:
307                    msg = 'C extension %s seems to compile OK, '
308                    msg += 'but it can still not be imported.'
309                    raise msg
310                else:
311                    C=True
312    else:
313        C=True
314           
315    if not C:
316        pass
317        print 'NOTICE: C-extension %s not used' %filename
318
319    return C
320
321
322
323
324if __name__ == '__main__':
325
326
327  import sys, os
328  from os.path import splitext
329 
330  if len(sys.argv) > 1:
331      files = sys.argv[1:]
332      for filename in files:
333          root, ext = splitext(filename)
334
335          if ext <> '.c':
336              print 'WARNING (compile.py): Skipping %s. I only compile C-files.' %filename
337     
338  else: 
339      #path = os.path.split(sys.argv[0])[0] or os.getcwd()
340      path = '.'
341      files = os.listdir(path)
342     
343     
344
345  for filename in files:
346      root, ext = splitext(filename)
347
348      if ext == '.c':
349          for x in ['.dll', '.so']:
350              try:
351                  os.remove(root + x)
352              except:
353                  pass
354
355          print '--------------------------------------'     
356          print 'Trying to compile c-extension %s in %s'\
357                %(filename, os.getcwd())
358
359          try:
360              compile(filename)
361          except Exception, e:
362              print 'Could not compile C extension %s' %filename
363          else:
364              print 'C extension %s OK' %filename
365          print   
366       
367
Note: See TracBrowser for help on using the repository browser.