forked from saghul/pycares
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup_cares.py
120 lines (105 loc) · 4.86 KB
/
setup_cares.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import errno
import os
import subprocess
import sys
from distutils import log
from distutils.command.build_ext import build_ext
from distutils.errors import DistutilsError
def exec_process(cmdline, silent=True, catch_enoent=True, input=None, **kwargs):
"""Execute a subprocess and returns the returncode, stdout buffer and stderr buffer.
Optionally prints stdout and stderr while running."""
try:
sub = subprocess.Popen(args=cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs)
stdout, stderr = sub.communicate(input=input)
if type(stdout) != type(""):
# decode on Python 3
# do nothing on Python 2 (it just doesn't care about encoding anyway)
stdout = stdout.decode(sys.getdefaultencoding(), "replace")
stderr = stderr.decode(sys.getdefaultencoding(), "replace")
returncode = sub.returncode
if not silent:
sys.stdout.write(stdout)
sys.stderr.write(stderr)
except OSError as e:
if e.errno == errno.ENOENT and catch_enoent:
raise DistutilsError('"%s" is not present on this system' % cmdline[0])
else:
raise
if returncode != 0:
raise DistutilsError('Got return value %d while executing "%s", stderr output was:\n%s' % (returncode, " ".join(cmdline), stderr.rstrip("\n")))
return stdout
def exec_make(cmdline, *args, **kwargs):
assert isinstance(cmdline, list)
makes = ["make"]
if "bsd" in sys.platform:
makes.insert(0, "gmake")
for make in makes:
if "bsd" in sys.platform and make == "make":
log.warn("Running plain make on BSD-derived system. It will likely fail. Consider installing GNU make from the ports collection.")
try:
return exec_process([make] + cmdline, *args, catch_enoent=False, **kwargs)
except OSError as e:
if e.errno != errno.ENOENT:
raise
raise DistutilsError('"make" is not present on this system')
class cares_build_ext(build_ext):
cares_dir = os.path.join('deps', 'c-ares')
user_options = build_ext.user_options
user_options.extend([
("cares-clean-compile", None, "Clean c-ares tree before compilation"),
])
boolean_options = build_ext.boolean_options
boolean_options.extend(["cares-clean-compile"])
def initialize_options(self):
build_ext.initialize_options(self)
self.cares_clean_compile = 0
def build_extensions(self):
if self.compiler.compiler_type == 'mingw32':
# Dirty hack to avoid linking with more than one C runtime when using MinGW
self.compiler.dll_libraries = [lib for lib in self.compiler.dll_libraries if not lib.startswith('msvcr')]
self.force = self.cares_clean_compile
if self.compiler.compiler_type == 'msvc':
self.cares_lib = os.path.join(self.cares_dir, 'cares.lib')
else:
self.cares_lib = os.path.join(self.cares_dir, 'libcares.a')
self.build_cares()
# Set compiler options
if self.compiler.compiler_type == 'mingw32':
self.compiler.add_library_dir(self.cares_dir)
self.compiler.add_library('cares')
self.extensions[0].extra_objects = [self.cares_lib]
self.compiler.add_include_dir(os.path.join(self.cares_dir, 'src'))
if sys.platform.startswith('linux'):
self.compiler.add_library('rt')
elif sys.platform == 'win32':
if self.compiler.compiler_type == 'msvc':
self.extensions[0].extra_link_args = ['/NODEFAULTLIB:libcmt']
self.compiler.add_library('advapi32')
self.compiler.add_library('iphlpapi')
self.compiler.add_library('psapi')
self.compiler.add_library('ws2_32')
build_ext.build_extensions(self)
def build_cares(self):
#self.debug_mode = bool(self.debug) or hasattr(sys, 'gettotalrefcount')
win32_msvc = self.compiler.compiler_type == 'msvc'
def build():
cflags = '-fPIC'
env = os.environ.copy()
env['CFLAGS'] = ' '.join(x for x in (cflags, env.get('CFLAGS', None)) if x)
log.info('Building c-ares...')
if win32_msvc:
exec_process('cmd.exe /C vcbuild.bat', cwd=self.cares_dir, env=env, shell=True, silent=False)
else:
exec_make(['libcares.a'], cwd=self.cares_dir, env=env, silent=False)
def clean():
if win32_msvc:
exec_process('cmd.exe /C vcbuild.bat clean', cwd=self.cares_dir, shell=True)
else:
exec_make(['clean'], cwd=self.cares_dir)
if self.cares_clean_compile:
clean()
if not os.path.exists(self.cares_lib):
log.info('c-ares needs to be compiled.')
build()
else:
log.info('No need to build c-ares.')