Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
keewenaw
GitHub Repository: keewenaw/ethereum-wallet-cracker
Path: blob/main/test/lib/python3.9/site-packages/setuptools/_distutils/command/config.py
4804 views
1
"""distutils.command.config
2
3
Implements the Distutils 'config' command, a (mostly) empty command class
4
that exists mainly to be sub-classed by specific module distributions and
5
applications. The idea is that while every "config" command is different,
6
at least they're all named the same, and users always see "config" in the
7
list of standard commands. Also, this is a good place to put common
8
configure-like tasks: "try to compile this C code", or "figure out where
9
this header file lives".
10
"""
11
12
import os, re
13
14
from distutils.core import Command
15
from distutils.errors import DistutilsExecError
16
from distutils.sysconfig import customize_compiler
17
from distutils import log
18
19
LANG_EXT = {"c": ".c", "c++": ".cxx"}
20
21
class config(Command):
22
23
description = "prepare to build"
24
25
user_options = [
26
('compiler=', None,
27
"specify the compiler type"),
28
('cc=', None,
29
"specify the compiler executable"),
30
('include-dirs=', 'I',
31
"list of directories to search for header files"),
32
('define=', 'D',
33
"C preprocessor macros to define"),
34
('undef=', 'U',
35
"C preprocessor macros to undefine"),
36
('libraries=', 'l',
37
"external C libraries to link with"),
38
('library-dirs=', 'L',
39
"directories to search for external C libraries"),
40
41
('noisy', None,
42
"show every action (compile, link, run, ...) taken"),
43
('dump-source', None,
44
"dump generated source files before attempting to compile them"),
45
]
46
47
48
# The three standard command methods: since the "config" command
49
# does nothing by default, these are empty.
50
51
def initialize_options(self):
52
self.compiler = None
53
self.cc = None
54
self.include_dirs = None
55
self.libraries = None
56
self.library_dirs = None
57
58
# maximal output for now
59
self.noisy = 1
60
self.dump_source = 1
61
62
# list of temporary files generated along-the-way that we have
63
# to clean at some point
64
self.temp_files = []
65
66
def finalize_options(self):
67
if self.include_dirs is None:
68
self.include_dirs = self.distribution.include_dirs or []
69
elif isinstance(self.include_dirs, str):
70
self.include_dirs = self.include_dirs.split(os.pathsep)
71
72
if self.libraries is None:
73
self.libraries = []
74
elif isinstance(self.libraries, str):
75
self.libraries = [self.libraries]
76
77
if self.library_dirs is None:
78
self.library_dirs = []
79
elif isinstance(self.library_dirs, str):
80
self.library_dirs = self.library_dirs.split(os.pathsep)
81
82
def run(self):
83
pass
84
85
# Utility methods for actual "config" commands. The interfaces are
86
# loosely based on Autoconf macros of similar names. Sub-classes
87
# may use these freely.
88
89
def _check_compiler(self):
90
"""Check that 'self.compiler' really is a CCompiler object;
91
if not, make it one.
92
"""
93
# We do this late, and only on-demand, because this is an expensive
94
# import.
95
from distutils.ccompiler import CCompiler, new_compiler
96
if not isinstance(self.compiler, CCompiler):
97
self.compiler = new_compiler(compiler=self.compiler,
98
dry_run=self.dry_run, force=1)
99
customize_compiler(self.compiler)
100
if self.include_dirs:
101
self.compiler.set_include_dirs(self.include_dirs)
102
if self.libraries:
103
self.compiler.set_libraries(self.libraries)
104
if self.library_dirs:
105
self.compiler.set_library_dirs(self.library_dirs)
106
107
def _gen_temp_sourcefile(self, body, headers, lang):
108
filename = "_configtest" + LANG_EXT[lang]
109
with open(filename, "w") as file:
110
if headers:
111
for header in headers:
112
file.write("#include <%s>\n" % header)
113
file.write("\n")
114
file.write(body)
115
if body[-1] != "\n":
116
file.write("\n")
117
return filename
118
119
def _preprocess(self, body, headers, include_dirs, lang):
120
src = self._gen_temp_sourcefile(body, headers, lang)
121
out = "_configtest.i"
122
self.temp_files.extend([src, out])
123
self.compiler.preprocess(src, out, include_dirs=include_dirs)
124
return (src, out)
125
126
def _compile(self, body, headers, include_dirs, lang):
127
src = self._gen_temp_sourcefile(body, headers, lang)
128
if self.dump_source:
129
dump_file(src, "compiling '%s':" % src)
130
(obj,) = self.compiler.object_filenames([src])
131
self.temp_files.extend([src, obj])
132
self.compiler.compile([src], include_dirs=include_dirs)
133
return (src, obj)
134
135
def _link(self, body, headers, include_dirs, libraries, library_dirs,
136
lang):
137
(src, obj) = self._compile(body, headers, include_dirs, lang)
138
prog = os.path.splitext(os.path.basename(src))[0]
139
self.compiler.link_executable([obj], prog,
140
libraries=libraries,
141
library_dirs=library_dirs,
142
target_lang=lang)
143
144
if self.compiler.exe_extension is not None:
145
prog = prog + self.compiler.exe_extension
146
self.temp_files.append(prog)
147
148
return (src, obj, prog)
149
150
def _clean(self, *filenames):
151
if not filenames:
152
filenames = self.temp_files
153
self.temp_files = []
154
log.info("removing: %s", ' '.join(filenames))
155
for filename in filenames:
156
try:
157
os.remove(filename)
158
except OSError:
159
pass
160
161
162
# XXX these ignore the dry-run flag: what to do, what to do? even if
163
# you want a dry-run build, you still need some sort of configuration
164
# info. My inclination is to make it up to the real config command to
165
# consult 'dry_run', and assume a default (minimal) configuration if
166
# true. The problem with trying to do it here is that you'd have to
167
# return either true or false from all the 'try' methods, neither of
168
# which is correct.
169
170
# XXX need access to the header search path and maybe default macros.
171
172
def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
173
"""Construct a source file from 'body' (a string containing lines
174
of C/C++ code) and 'headers' (a list of header files to include)
175
and run it through the preprocessor. Return true if the
176
preprocessor succeeded, false if there were any errors.
177
('body' probably isn't of much use, but what the heck.)
178
"""
179
from distutils.ccompiler import CompileError
180
self._check_compiler()
181
ok = True
182
try:
183
self._preprocess(body, headers, include_dirs, lang)
184
except CompileError:
185
ok = False
186
187
self._clean()
188
return ok
189
190
def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
191
lang="c"):
192
"""Construct a source file (just like 'try_cpp()'), run it through
193
the preprocessor, and return true if any line of the output matches
194
'pattern'. 'pattern' should either be a compiled regex object or a
195
string containing a regex. If both 'body' and 'headers' are None,
196
preprocesses an empty file -- which can be useful to determine the
197
symbols the preprocessor and compiler set by default.
198
"""
199
self._check_compiler()
200
src, out = self._preprocess(body, headers, include_dirs, lang)
201
202
if isinstance(pattern, str):
203
pattern = re.compile(pattern)
204
205
with open(out) as file:
206
match = False
207
while True:
208
line = file.readline()
209
if line == '':
210
break
211
if pattern.search(line):
212
match = True
213
break
214
215
self._clean()
216
return match
217
218
def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
219
"""Try to compile a source file built from 'body' and 'headers'.
220
Return true on success, false otherwise.
221
"""
222
from distutils.ccompiler import CompileError
223
self._check_compiler()
224
try:
225
self._compile(body, headers, include_dirs, lang)
226
ok = True
227
except CompileError:
228
ok = False
229
230
log.info(ok and "success!" or "failure.")
231
self._clean()
232
return ok
233
234
def try_link(self, body, headers=None, include_dirs=None, libraries=None,
235
library_dirs=None, lang="c"):
236
"""Try to compile and link a source file, built from 'body' and
237
'headers', to executable form. Return true on success, false
238
otherwise.
239
"""
240
from distutils.ccompiler import CompileError, LinkError
241
self._check_compiler()
242
try:
243
self._link(body, headers, include_dirs,
244
libraries, library_dirs, lang)
245
ok = True
246
except (CompileError, LinkError):
247
ok = False
248
249
log.info(ok and "success!" or "failure.")
250
self._clean()
251
return ok
252
253
def try_run(self, body, headers=None, include_dirs=None, libraries=None,
254
library_dirs=None, lang="c"):
255
"""Try to compile, link to an executable, and run a program
256
built from 'body' and 'headers'. Return true on success, false
257
otherwise.
258
"""
259
from distutils.ccompiler import CompileError, LinkError
260
self._check_compiler()
261
try:
262
src, obj, exe = self._link(body, headers, include_dirs,
263
libraries, library_dirs, lang)
264
self.spawn([exe])
265
ok = True
266
except (CompileError, LinkError, DistutilsExecError):
267
ok = False
268
269
log.info(ok and "success!" or "failure.")
270
self._clean()
271
return ok
272
273
274
# -- High-level methods --------------------------------------------
275
# (these are the ones that are actually likely to be useful
276
# when implementing a real-world config command!)
277
278
def check_func(self, func, headers=None, include_dirs=None,
279
libraries=None, library_dirs=None, decl=0, call=0):
280
"""Determine if function 'func' is available by constructing a
281
source file that refers to 'func', and compiles and links it.
282
If everything succeeds, returns true; otherwise returns false.
283
284
The constructed source file starts out by including the header
285
files listed in 'headers'. If 'decl' is true, it then declares
286
'func' (as "int func()"); you probably shouldn't supply 'headers'
287
and set 'decl' true in the same call, or you might get errors about
288
a conflicting declarations for 'func'. Finally, the constructed
289
'main()' function either references 'func' or (if 'call' is true)
290
calls it. 'libraries' and 'library_dirs' are used when
291
linking.
292
"""
293
self._check_compiler()
294
body = []
295
if decl:
296
body.append("int %s ();" % func)
297
body.append("int main () {")
298
if call:
299
body.append(" %s();" % func)
300
else:
301
body.append(" %s;" % func)
302
body.append("}")
303
body = "\n".join(body) + "\n"
304
305
return self.try_link(body, headers, include_dirs,
306
libraries, library_dirs)
307
308
def check_lib(self, library, library_dirs=None, headers=None,
309
include_dirs=None, other_libraries=[]):
310
"""Determine if 'library' is available to be linked against,
311
without actually checking that any particular symbols are provided
312
by it. 'headers' will be used in constructing the source file to
313
be compiled, but the only effect of this is to check if all the
314
header files listed are available. Any libraries listed in
315
'other_libraries' will be included in the link, in case 'library'
316
has symbols that depend on other libraries.
317
"""
318
self._check_compiler()
319
return self.try_link("int main (void) { }", headers, include_dirs,
320
[library] + other_libraries, library_dirs)
321
322
def check_header(self, header, include_dirs=None, library_dirs=None,
323
lang="c"):
324
"""Determine if the system header file named by 'header_file'
325
exists and can be found by the preprocessor; return true if so,
326
false otherwise.
327
"""
328
return self.try_cpp(body="/* No body */", headers=[header],
329
include_dirs=include_dirs)
330
331
def dump_file(filename, head=None):
332
"""Dumps a file content into log.info.
333
334
If head is not None, will be dumped before the file content.
335
"""
336
if head is None:
337
log.info('%s', filename)
338
else:
339
log.info(head)
340
file = open(filename)
341
try:
342
log.info(file.read())
343
finally:
344
file.close()
345
346