source: inundation/utilities/compile.py @ 2508

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

First step towards moving util_ext.h out from pyvolution as per ticket:31

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    #from config import use_extensions
271
272    from os.path import splitext
273
274    root, ext = splitext(filename)
275   
276    C=False
277
278    try:
279        s = 'import %s' %root
280        #print s
281        exec(s)
282    except:
283        try:
284            open(filename)
285        except:
286            msg = 'C extension %s cannot be opened' %filename
287            print msg               
288        else:   
289            print '------- Trying to compile c-extension %s' %filename
290
291            #compile(filename)       
292            try:
293                compile(filename)
294            except:
295                print 'WARNING: Could not compile C-extension %s'\
296                      %filename
297            else:
298                try:
299                    exec('import %s' %root)
300                except:
301                    msg = 'C extension %s seems to compile OK, '
302                    msg += 'but it can still not be imported.'
303                    raise msg
304                else:
305                    C=True
306    else:
307        C=True
308           
309    if not C:
310        pass
311        print 'NOTICE: C-extension %s not used' %filename
312
313    return C
314
315
316
317
318if __name__ == '__main__':
319
320
321  import sys, os
322  from os.path import splitext
323 
324  if len(sys.argv) > 1:
325      files = sys.argv[1:]
326      for filename in files:
327          root, ext = splitext(filename)
328
329          if ext <> '.c':
330              print 'WARNING (compile.py): Skipping %s. I only compile C-files.' %filename
331     
332  else: 
333      #path = os.path.split(sys.argv[0])[0] or os.getcwd()
334      path = '.'
335      files = os.listdir(path)
336     
337     
338
339  for filename in files:
340      root, ext = splitext(filename)
341
342      if ext == '.c':
343          for x in ['.dll', '.so']:
344              try:
345                  os.remove(root + x)
346              except:
347                  pass
348
349          print '--------------------------------------'     
350          print 'Trying to compile c-extension %s in %s'\
351                %(filename, os.getcwd())
352
353          try:
354              compile(filename)
355          except Exception, e:
356              print 'Could not compile C extension %s' %filename
357          else:
358              print 'C extension %s OK' %filename
359          print   
360       
361
Note: See TracBrowser for help on using the repository browser.