source: inundation/utilities/compile.py @ 2528

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

Began preparing foor moving mesh codes from pyvolution to separate dir as per ticket:57

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