source: inundation/utilities/compile.py @ 1908

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

Moved compile script to general utilities and updated test_all.py

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