5 from setuptools import setup, Extension
6 from setuptools.command.build_ext import build_ext
7 from distutils.errors import *
10 # Disable hard links, otherwise building distributions fails
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)]
18 mos = getattr(sys, 'platform', None)
20 if mos.startswith('sunos'):
21 libraries = ['socket', 'nsl']
24 iface_mod = Extension('netifaces', sources=['netifaces.c'],
26 define_macros=def_macros)
29 # There must be a better way to do this...
31 class my_build_ext(build_ext):
32 def build_extensions(self):
33 self.check_requirements()
34 build_ext.build_extensions(self)
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)
40 if os.path.exists(name):
42 thefile = open(name, 'w')
43 print >>thefile, contents
46 tmpext = Extension('_dummy', [], libraries = libraries)
47 libraries = self.get_libraries(tmpext)
55 os.dup2(self.ctout, 1)
56 os.dup2(self.ctout, 2)
58 objects = self.compiler.compile([name],
59 output_dir=self.build_temp,
60 include_dirs=include_dirs,
63 self.compiler.link_executable(objects,
65 output_dir=self.build_temp,
66 library_dirs=library_dirs,
70 abspath = os.path.abspath(os.path.join(self.build_temp,
72 pipe = os.popen(abspath, 'r')
73 result = pipe.read().strip()
87 except DistutilsExecError:
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')
98 results = pickle.load(myfile)
106 print "checking for getifaddrs...",
108 result = results.get('have_getifaddrs', None)
109 if result is not None:
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)
119 #include <sys/types.h>
120 #include <sys/socket.h>
123 struct ifaddrs *addrs;
125 ret = getifaddrs(&addrs);
130 if self.test_build(testrig):
136 print "found. %s" % cached
137 self.compiler.define_macro('HAVE_GETIFADDRS', 1)
139 print "not found. %s" % cached
141 results['have_getifaddrs'] = result
143 print "checking for getnameinfo...",
145 result = results.get('have_getnameinfo', None)
146 if result is not None:
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)
156 #include <sys/types.h>
157 #include <sys/socket.h>
158 #include <arpa/inet.h>
162 struct sockaddr_in sin;
166 sin.sin_family = AF_INET;
168 sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
170 ret = getnameinfo ((struct sockaddr *)&sin, sizeof (sin),
171 buffer, sizeof (buffer),
178 if self.test_build(testrig,libraries=libraries):
184 print "found. %s" % cached
185 self.compiler.define_macro('HAVE_GETNAMEINFO', 1)
187 print "not found. %s" % cached
189 results['have_getnameinfo'] = result
191 if not results['have_getifaddrs']:
192 print "checking for socket IOCTLs...",
194 result = results.get('have_socket_ioctls', None)
195 if result is not None:
201 ioctls = ('SIOCGIFCONF',
213 if mos.startswith('sunos'):
217 #include <sys/sockio.h>
222 #include <sys/types.h>
223 #include <sys/socket.h>
224 #include <sys/ioctl.h>
226 #include <netinet/in.h>
227 #include <arpa/inet.h>
230 int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP);
233 ioctl(fd, %(ioctl)s, &ifreq);
237 """ % { 'ioctl': ioctl , 'addedinc': added_includes}
239 if self.test_build(testrig,libraries=libraries):
243 print "%r. %s" % (result, cached)
245 self.compiler.define_macro('HAVE_%s' % ioctl, 1)
246 self.compiler.define_macro('HAVE_SOCKET_IOCTLS', 1)
248 print "not found. %s" % cached
250 results['have_socket_ioctls'] = result
252 print "checking for optional header files...",
254 result = results.get('have_headers', None)
255 if result is not None:
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',
269 for header in headers:
271 #include <sys/types.h>
272 #include <sys/socket.h>
275 int main (void) { return 0; }
278 if self.test_build(testrig, link=False, execute=False):
279 result.append(header)
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)
287 print "none found. %s" % cached
289 optional_headers = result
290 results['have_headers'] = result
292 print "checking whether struct sockaddr has a length field...",
294 result = results.get('have_sockaddr_sa_len', None)
295 if result is not None:
301 #include <sys/types.h>
302 #include <sys/socket.h>
312 result = self.test_build(testrig, execute=False)
315 print 'yes. %s' % cached
316 self.compiler.define_macro('HAVE_SOCKADDR_SA_LEN', 1)
318 print 'no. %s' % cached
320 results['have_sockaddr_sa_len'] = result
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...",
330 result = results.get('have_sockaddrs', None)
331 if result is not None:
336 sockaddrs = ('at', 'ax25', 'dl', 'eon', 'in', 'in6',
337 'inarp', 'ipx', 'iso', 'ns', 'un', 'x25',
338 'rose', 'ash', 'ec', 'll', 'atmpvc', 'atmsvc',
341 for sockaddr in sockaddrs:
343 #include <sys/types.h>
344 #include <sys/socket.h>
347 #include <netinet/in.h>
351 struct sockaddr_%(sockaddr)s sa;
354 """ % { 'includes': '\n'.join(["#include <%s>" % header
356 in optional_headers]),
357 'sockaddr': sockaddr }
359 if self.test_build(testrig, execute=False):
360 result.append(sockaddr)
363 print '%s. %s' % (' '.join(result), cached)
364 for sockaddr in result:
365 self.compiler.define_macro('HAVE_SOCKADDR_%s' \
366 % sockaddr.upper(), 1)
368 print 'none! %s' % cached
370 results['have_sockaddrs'] = result
372 # Save the results to our config.cache file
373 myfile = open(cache_file, 'w')
375 pickle.dump(results, myfile)
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
383 setup (name='netifaces',
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.
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.
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.
400 author='Alastair Houghton',
401 author_email='alastair@alastairs-place.net',
402 url='http://alastairs-place.net/netifaces',
404 'Development Status :: 4 - Beta',
405 'Intended Audience :: Developers',
406 'License :: OSI Approved :: MIT License',
407 'Topic :: System :: Networking',
409 ext_modules=[iface_mod])