source: inundation/utilities/compile.py @ 1980

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

Comment about include path

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