Initial import to Tizen
[profile/ivi/python-netifaces.git] / setup.py
1 import setuptools
2 import os
3 import sys
4 import distutils.spawn
5 from setuptools import setup, Extension
6 from setuptools.command.build_ext import build_ext
7 from distutils.errors import *
8 import pickle
9
10 # Disable hard links, otherwise building distributions fails
11 del os.link
12
13 # On Windows, we need ws2_32 and iphlpapi
14 if getattr(sys, 'getwindowsversion', None):
15     libraries = ['ws2_32', 'iphlpapi']
16     def_macros = [('WIN32', 1)]
17 else:
18     mos = getattr(sys, 'platform', None)
19     libraries = []
20     if mos.startswith('sunos'):
21         libraries = ['socket', 'nsl']
22     def_macros = []
23
24 iface_mod = Extension('netifaces', sources=['netifaces.c'],
25                       libraries=libraries,
26                       define_macros=def_macros)
27
28 #
29 #  There must be a better way to do this...
30 #
31 class my_build_ext(build_ext):
32     def build_extensions(self):
33         self.check_requirements()
34         build_ext.build_extensions(self)
35
36     def test_build(self, contents, link=True, execute=True, libraries=None,
37                    include_dirs=None, library_dirs=None):
38         name = os.path.join(self.build_temp, 'conftest-%s.c' % self.conftestidx)
39         self.conftestidx += 1
40         if os.path.exists(name):
41             os.unlink(name)
42         thefile = open(name, 'w')
43         print >>thefile, contents
44         thefile.close()
45
46         tmpext = Extension('_dummy', [], libraries = libraries)
47         libraries = self.get_libraries(tmpext)
48         
49         sys.stdout.flush()
50         sys.stderr.flush()
51         mystdout = os.dup(1)
52         mystderr = os.dup(2)
53         result = True
54         try:
55             os.dup2(self.ctout, 1)
56             os.dup2(self.ctout, 2)
57             try:
58                 objects = self.compiler.compile([name],
59                                                 output_dir=self.build_temp,
60                                                 include_dirs=include_dirs,
61                                                 debug=self.debug)
62                 if link:
63                     self.compiler.link_executable(objects,
64                                                   'conftest',
65                                                   output_dir=self.build_temp,
66                                                   library_dirs=library_dirs,
67                                                   libraries=libraries,
68                                                   debug=self.debug)
69                     if execute:
70                         abspath = os.path.abspath(os.path.join(self.build_temp,
71                                                                'conftest'))
72                         pipe = os.popen(abspath, 'r')
73                         result = pipe.read().strip()
74                         status = pipe.close()
75                         if status is None:
76                             status = 0
77                         if result == '':
78                             result = True
79                         if status != 0:
80                             result = False
81                         
82             finally:
83                 os.dup2(mystdout, 1)
84                 os.dup2(mystderr, 2)
85         except CompileError:
86             return False
87         except DistutilsExecError:
88             return False
89         return result
90
91     def check_requirements(self):
92         # Load the cached config data from a previous run if possible; compiling
93         # things to test for features is slow
94         cache_file = os.path.join(self.build_temp, 'config.cache')
95         if os.path.exists(cache_file):
96             myfile = open(cache_file, 'r')
97             try:
98                 results = pickle.load(myfile)
99             finally:
100                 myfile.close()
101         else:
102             results = {}
103
104         self.conftestidx = 0
105         
106         print "checking for getifaddrs...",
107
108         result = results.get('have_getifaddrs', None)
109         if result is not None:
110             cached = '(cached)'
111         else:
112             cached = ''
113
114             if not os.path.exists(self.build_temp):
115                 os.makedirs(self.build_temp)
116             outname = os.path.join(self.build_temp, 'conftest.out')
117             self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
118             testrig = """
119             #include <sys/types.h>
120             #include <sys/socket.h>
121             #include <ifaddrs.h>
122             int main(void) {
123               struct ifaddrs *addrs;
124               int ret;
125               ret = getifaddrs(&addrs);
126               freeifaddrs (addrs);
127               return 0;
128             }
129             """
130             if self.test_build(testrig):
131                 result = True
132             else:
133                 result = False
134
135         if result:
136             print "found. %s" % cached
137             self.compiler.define_macro('HAVE_GETIFADDRS', 1)
138         else:
139             print "not found. %s" % cached
140
141         results['have_getifaddrs'] = result
142
143         print "checking for getnameinfo...",
144
145         result = results.get('have_getnameinfo', None)
146         if result is not None:
147             cached = '(cached)'
148         else:
149             cached = ''
150
151             if not os.path.exists(self.build_temp):
152                 os.makedirs(self.build_temp)
153             outname = os.path.join(self.build_temp, 'conftest2.out')
154             self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC)
155             testrig = """
156             #include <sys/types.h>
157             #include <sys/socket.h>
158             #include <arpa/inet.h>
159             #include <netdb.h>
160             #include <stdlib.h>
161             int main(void) {
162               struct sockaddr_in sin;
163               char buffer[256];
164               int ret;
165
166               sin.sin_family = AF_INET;
167               sin.sin_port = 0;
168               sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
169               
170               ret = getnameinfo ((struct sockaddr *)&sin, sizeof (sin),
171                                  buffer, sizeof (buffer),
172                                  NULL, 0,
173                                  NI_NUMERICHOST);
174
175               return 0;
176             }
177             """
178             if self.test_build(testrig,libraries=libraries):
179                 result = True
180             else:
181                 result = False
182
183         if result:
184             print "found. %s" % cached
185             self.compiler.define_macro('HAVE_GETNAMEINFO', 1)
186         else:
187             print "not found. %s" % cached
188
189         results['have_getnameinfo'] = result
190
191         if not results['have_getifaddrs']:
192             print "checking for socket IOCTLs...",
193
194             result = results.get('have_socket_ioctls', None)
195             if result is not None:
196                 cached = '(cached)'
197             else:
198                 cached = ''
199
200                 result = []
201                 ioctls = ('SIOCGIFCONF',
202                           'SIOCGSIZIFCONF',
203                           'SIOCGIFHWADDR',
204                           'SIOCGIFADDR',
205                           'SIOCGIFFLAGS',
206                           'SIOCGIFDSTADDR',
207                           'SIOCGIFBRDADDR',
208                           'SIOCGIFNETMASK',
209                           'SIOCGLIFNUM',
210                           'SIOCGLIFCONF',
211                           'SIOCGLIFFLAGS')
212                 added_includes = ""
213                 if mos.startswith('sunos'):
214                     added_includes = """
215                      #include <unistd.h>
216                      #include <stropts.h>
217                      #include <sys/sockio.h>
218                     """
219
220                 for ioctl in ioctls:
221                     testrig = """
222                     #include <sys/types.h>
223                     #include <sys/socket.h>
224                     #include <sys/ioctl.h>
225                     #include <net/if.h>
226                     #include <netinet/in.h>
227                     #include <arpa/inet.h>
228                     %(addedinc)s
229                     int main(void) {
230                         int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
231                         struct ifreq ifreq;
232
233                         ioctl(fd, %(ioctl)s, &ifreq);
234
235                         return 0;
236                     }
237                     """ % { 'ioctl': ioctl , 'addedinc': added_includes}
238
239                     if self.test_build(testrig,libraries=libraries):
240                         result.append(ioctl)
241
242             if result:
243                 print "%r. %s" % (result, cached)
244                 for ioctl in result:
245                     self.compiler.define_macro('HAVE_%s' % ioctl, 1)
246                 self.compiler.define_macro('HAVE_SOCKET_IOCTLS', 1)
247             else:
248                 print "not found. %s" % cached
249
250             results['have_socket_ioctls'] = result
251
252         print "checking for optional header files...",
253
254         result = results.get('have_headers', None)
255         if result is not None:
256             cached = '(cached)'
257         else:
258             cached = ''
259
260             result =[]
261             headers = ('net/if_dl.h', 'netash/ash.h',
262                        'netatalk/at.h', 'netax25/ax25.h',
263                        'neteconet/ec.h', 'netipx/ipx.h',
264                        'netpacket/packet.h', 'netrose/rose.h',
265                        'linux/irda.h', 'linux/atm.h',
266                        'linux/llc.h', 'linux/tipc.h',
267                        'linux/dn.h')
268
269             for header in headers:
270                 testrig = """
271                 #include <sys/types.h>
272                 #include <sys/socket.h>
273                 #include <net/if.h>
274                 #include <%s>
275                 int main (void) { return 0; }
276                 """ % header
277
278                 if self.test_build(testrig, link=False, execute=False):
279                     result.append(header)
280
281         if result:
282             print "%s. %s" % (' '.join(result), cached)
283             for header in result:
284                 macro = header.upper().replace('.', '_').replace('/', '_')
285                 self.compiler.define_macro('HAVE_%s' % macro, 1)
286         else:
287             print "none found. %s" % cached
288
289         optional_headers = result
290         results['have_headers'] = result
291
292         print "checking whether struct sockaddr has a length field...",
293
294         result = results.get('have_sockaddr_sa_len', None)
295         if result is not None:
296             cached = '(cached)'
297         else:
298             cached = ''
299
300             testrig = """
301             #include <sys/types.h>
302             #include <sys/socket.h>
303             #include <net/if.h>
304
305             int main (void) {
306               struct sockaddr sa;
307               sa.sa_len = 5;
308               return 0;
309             }
310             """
311
312             result = self.test_build(testrig, execute=False)
313
314         if result:
315             print 'yes. %s' % cached
316             self.compiler.define_macro('HAVE_SOCKADDR_SA_LEN', 1)
317         else:
318             print 'no. %s' % cached
319
320         results['have_sockaddr_sa_len'] = result
321
322         if not results['have_sockaddr_sa_len']:
323             # GAK! On certain stupid platforms (Linux), there's no sa_len.
324             # Macho Linux programmers apparently think that it's not needed,
325             # however, unfortunately, getifaddrs() doesn't return the
326             # lengths, because they're in the sa_len field on just about
327             # everything but Linux.
328             print "checking which sockaddr_xxx structs are defined...",
329             
330             result = results.get('have_sockaddrs', None)
331             if result is not None:
332                 cached = '(cached)'
333             else:
334                 cached = ''
335
336                 sockaddrs = ('at', 'ax25', 'dl', 'eon', 'in', 'in6',
337                              'inarp', 'ipx', 'iso', 'ns', 'un', 'x25',
338                              'rose', 'ash', 'ec', 'll', 'atmpvc', 'atmsvc',
339                              'dn', 'irda', 'llc')
340                 result = []
341                 for sockaddr in sockaddrs:
342                     testrig = """
343                     #include <sys/types.h>
344                     #include <sys/socket.h>
345                     #include <sys/un.h>
346                     #include <net/if.h>
347                     #include <netinet/in.h>
348                     %(includes)s
349                     
350                     int main (void) {
351                       struct sockaddr_%(sockaddr)s sa;
352                       return 0;
353                     }
354                     """ % { 'includes': '\n'.join(["#include <%s>" % header
355                                                    for header
356                                                    in optional_headers]),
357                             'sockaddr': sockaddr }
358
359                     if self.test_build(testrig, execute=False):
360                         result.append(sockaddr)
361                 
362             if result:
363                 print '%s. %s' % (' '.join(result), cached)
364                 for sockaddr in result:
365                     self.compiler.define_macro('HAVE_SOCKADDR_%s' \
366                                                % sockaddr.upper(), 1)
367             else:
368                 print 'none! %s' % cached
369
370             results['have_sockaddrs'] = result
371
372        # Save the results to our config.cache file
373         myfile = open(cache_file, 'w')
374         try:
375             pickle.dump(results, myfile)
376         finally:
377             myfile.close()
378
379 # Don't bother detecting socket ioctls on Windows
380 if not getattr(sys, 'getwindowsversion', None):
381     setuptools.command.build_ext.build_ext = my_build_ext
382
383 setup (name='netifaces',
384        version='0.6',
385        description="Portable network interface information.",
386        license="MIT License",
387        long_description="""\
388 netifaces provides a (hopefully portable-ish) way for Python programmers to
389 get access to a list of the network interfaces on the local machine, and to
390 obtain the addresses of those network interfaces.
391
392 The package has been tested on Mac OS X, Windows XP, Windows Vista, Linux
393 and Solaris.  On Windows, it is currently not able to retrieve IPv6
394 addresses, owing to shortcomings of the Windows API.
395
396 It should work on other UNIX-like systems provided they implement
397 either getifaddrs() or support the SIOCGIFxxx socket options, although the
398 data provided by the socket options is normally less complete.
399 """,
400        author='Alastair Houghton',
401        author_email='alastair@alastairs-place.net',
402        url='http://alastairs-place.net/netifaces',
403        classifiers=[
404     'Development Status :: 4 - Beta',
405     'Intended Audience :: Developers',
406     'License :: OSI Approved :: MIT License',
407     'Topic :: System :: Networking',
408     ],
409        ext_modules=[iface_mod])