source: misc/inundation-numpy-branch/utilities/compile.py @ 5847

Last change on this file since 5847 was 2546, checked in by ole, 19 years ago

Got Numpy to work on Linux

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