def test_build(self, contents, link=True, execute=False, libraries=None, include_dirs=None, library_dirs=None): name = os.path.join(self.build_temp, 'conftest-%s.c' % self.conftestidx) self.conftestidx += 1 if os.path.exists(name): os.unlink(name) thefile = open(name, 'w') print_(contents, file=thefile) thefile.close() sys.stdout.flush() sys.stderr.flush() mystdout = os.dup(1) mystderr = os.dup(2) result = True try: os.dup2(self.ctout, 1) os.dup2(self.ctout, 2) try: objects = self.compiler.compile([name], output_dir=self.build_temp, include_dirs=include_dirs, debug=self.debug) if link: self.compiler.link_executable(objects, 'conftest', output_dir=self.build_temp, library_dirs=library_dirs, libraries=libraries, debug=self.debug) if execute: abspath = os.path.abspath(os.path.join(self.build_temp, 'conftest')) pipe = os.popen(abspath, 'r') result = pipe.read().strip() status = pipe.close() if status is None: status = 0 if result == '': result = True if status != 0: result = False finally: os.dup2(mystdout, 1) os.dup2(mystderr, 2) except CompileError: return False except DistutilsExecError: return False return result
def check_requirements(self): # Load the cached config data from a previous run if possible; compiling # things to test for features is slow cache_file = os.path.join(self.build_temp, 'config.cache') if os.path.exists(cache_file): myfile = open(cache_file, 'rb') try: results = pickle.load(myfile) finally: myfile.close() else: results = {} self.conftestidx = 0 print_("checking for getifaddrs...", end=' ') result = results.get('have_getifaddrs', None) if result is not None: cached = '(cached)' else: cached = '' if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) outname = os.path.join(self.build_temp, 'conftest.out') self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) testrig = """ #include <sys/types.h> #include <sys/socket.h> #include <ifaddrs.h> int main(void) { struct ifaddrs *addrs; int ret; ret = getifaddrs(&addrs); freeifaddrs (addrs); return 0; } """ if self.test_build(testrig): result = True else: result = False if result: print("found. %s" % cached) self.compiler.define_macro('HAVE_GETIFADDRS', 1) else: print("not found. %s" % cached) results['have_getifaddrs'] = result print_("checking for getnameinfo...", end=' ') result = results.get('have_getnameinfo', None) if result is not None: cached = '(cached)' else: cached = '' if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) outname = os.path.join(self.build_temp, 'conftest2.out') self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) testrig = """ #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netdb.h> #include <stdlib.h> int main(void) { struct sockaddr_in sin; char buffer[256]; int ret; sin.sin_family = AF_INET; sin.sin_port = 0; sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); ret = getnameinfo ((struct sockaddr *)&sin, sizeof (sin), buffer, sizeof (buffer), NULL, 0, NI_NUMERICHOST); return 0; } """ if self.test_build(testrig,libraries=libraries): result = True else: result = False if result: print("found. %s" % cached) self.compiler.define_macro('HAVE_GETNAMEINFO', 1) else: print("not found. %s" % cached) results['have_getnameinfo'] = result if not results['have_getifaddrs']: print_("checking for socket IOCTLs...", end=' ') result = results.get('have_socket_ioctls', None) if result is not None: cached = '(cached)' else: cached = '' if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) outname = os.path.join(self.build_temp, 'conftest3.out') self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) result = [] ioctls = ('SIOCGIFCONF', 'SIOCGSIZIFCONF', 'SIOCGIFHWADDR', 'SIOCGIFADDR', 'SIOCGIFFLAGS', 'SIOCGIFDSTADDR', 'SIOCGIFBRDADDR', 'SIOCGIFNETMASK', 'SIOCGLIFNUM', 'SIOCGLIFCONF', 'SIOCGLIFFLAGS') added_includes = "" if mos.startswith('sunos'): added_includes = """ #include <unistd.h> #include <stropts.h> #include <sys/sockio.h> """ for ioctl in ioctls: testrig = """ #include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <netinet/in.h> #include <arpa/inet.h> %(addedinc)s int main(void) { int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP); struct ifreq ifreq; ioctl(fd, %(ioctl)s, &ifreq); return 0; } """ % { 'ioctl': ioctl , 'addedinc': added_includes} if self.test_build(testrig,libraries=libraries): result.append(ioctl) if result: print("%r. %s" % (result, cached)) for ioctl in result: self.compiler.define_macro('HAVE_%s' % ioctl, 1) self.compiler.define_macro('HAVE_SOCKET_IOCTLS', 1) else: print("not found. %s" % cached) results['have_socket_ioctls'] = result print_("checking for optional header files...", end=' ') result = results.get('have_headers', None) if result is not None: cached = '(cached)' else: cached = '' result =[] headers = ('net/if_dl.h', 'netash/ash.h', 'netatalk/at.h', 'netax25/ax25.h', 'neteconet/ec.h', 'netipx/ipx.h', 'netpacket/packet.h', 'netrose/rose.h', 'linux/irda.h', 'linux/atm.h', 'linux/llc.h', 'linux/tipc.h', 'linux/dn.h') for header in headers: testrig = """ #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> #include <%s> int main (void) { return 0; } """ % header if self.test_build(testrig, link=False): result.append(header) if result: print("%s. %s" % (' '.join(result), cached)) for header in result: macro = header.upper().replace('.', '_').replace('/', '_') self.compiler.define_macro('HAVE_%s' % macro, 1) else: print("none found. %s" % cached) optional_headers = result results['have_headers'] = result print_("checking whether struct sockaddr has a length field...", end=' ') result = results.get('have_sockaddr_sa_len', None) if result is not None: cached = '(cached)' else: cached = '' testrig = """ #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> int main (void) { struct sockaddr sa; sa.sa_len = 5; return 0; } """ result = self.test_build(testrig) if result: print('yes. %s' % cached) self.compiler.define_macro('HAVE_SOCKADDR_SA_LEN', 1) else: print('no. %s' % cached) results['have_sockaddr_sa_len'] = result if not results['have_sockaddr_sa_len']: # GAK! On certain stupid platforms (Linux), there's no sa_len. # Macho Linux programmers apparently think that it's not needed, # however, unfortunately, getifaddrs() doesn't return the # lengths, because they're in the sa_len field on just about # everything but Linux. print_("checking which sockaddr_xxx structs are defined...", end=' ') result = results.get('have_sockaddrs', None) if result is not None: cached = '(cached)' else: cached = '' if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) outname = os.path.join(self.build_temp, 'conftest4.out') self.ctout = os.open(outname, os.O_RDWR | os.O_CREAT | os.O_TRUNC) sockaddrs = ('at', 'ax25', 'dl', 'eon', 'in', 'in6', 'inarp', 'ipx', 'iso', 'ns', 'un', 'x25', 'rose', 'ash', 'ec', 'll', 'atmpvc', 'atmsvc', 'dn', 'irda', 'llc') result = [] for sockaddr in sockaddrs: testrig = """ #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <net/if.h> #include <netinet/in.h> %(includes)s int main (void) { struct sockaddr_%(sockaddr)s sa; return 0; } """ % { 'includes': '\n'.join(["#include <%s>" % header for header in optional_headers]), 'sockaddr': sockaddr } if self.test_build(testrig): result.append(sockaddr) if result: print('%s. %s' % (' '.join(result), cached)) for sockaddr in result: self.compiler.define_macro('HAVE_SOCKADDR_%s' \ % sockaddr.upper(), 1) else: print('none! %s' % cached) results['have_sockaddrs'] = result # Save the results to our config.cache file myfile = open(cache_file, 'wb') try: pickle.dump(results, myfile) finally: myfile.close()