]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/_distutils/unixccompiler.py
ActualizaciĆ³n de Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / setuptools / _distutils / unixccompiler.py
CommitLineData
53e6db90
DC
1"""distutils.unixccompiler
2
3Contains the UnixCCompiler class, a subclass of CCompiler that handles
4the "typical" Unix-style command-line C compiler:
5 * macros defined with -Dname[=value]
6 * macros undefined with -Uname
7 * include search directories specified with -Idir
8 * libraries specified with -lllib
9 * library search directories specified with -Ldir
10 * compile handled by 'cc' (or similar) executable with -c option:
11 compiles .c to .o
12 * link static library handled by 'ar' command (possibly with 'ranlib')
13 * link shared library handled by 'cc -shared'
14"""
15
16import os
17import sys
18import re
19import shlex
20import itertools
21
22from . import sysconfig
23from .dep_util import newer
24from .ccompiler import CCompiler, gen_preprocess_options, gen_lib_options
25from .errors import DistutilsExecError, CompileError, LibError, LinkError
26from ._log import log
27from ._macos_compat import compiler_fixup
28
29# XXX Things not currently handled:
30# * optimization/debug/warning flags; we just use whatever's in Python's
31# Makefile and live with it. Is this adequate? If not, we might
32# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
33# SunCCompiler, and I suspect down that road lies madness.
34# * even if we don't know a warning flag from an optimization flag,
35# we need some way for outsiders to feed preprocessor/compiler/linker
36# flags in to us -- eg. a sysadmin might want to mandate certain flags
37# via a site config file, or a user might want to set something for
38# compiling this module distribution only via the setup.py command
39# line, whatever. As long as these options come from something on the
40# current system, they can be as system-dependent as they like, and we
41# should just happily stuff them into the preprocessor/compiler/linker
42# options and carry on.
43
44
45def _split_env(cmd):
46 """
47 For macOS, split command into 'env' portion (if any)
48 and the rest of the linker command.
49
50 >>> _split_env(['a', 'b', 'c'])
51 ([], ['a', 'b', 'c'])
52 >>> _split_env(['/usr/bin/env', 'A=3', 'gcc'])
53 (['/usr/bin/env', 'A=3'], ['gcc'])
54 """
55 pivot = 0
56 if os.path.basename(cmd[0]) == "env":
57 pivot = 1
58 while '=' in cmd[pivot]:
59 pivot += 1
60 return cmd[:pivot], cmd[pivot:]
61
62
63def _split_aix(cmd):
64 """
65 AIX platforms prefix the compiler with the ld_so_aix
66 script, so split that from the linker command.
67
68 >>> _split_aix(['a', 'b', 'c'])
69 ([], ['a', 'b', 'c'])
70 >>> _split_aix(['/bin/foo/ld_so_aix', 'gcc'])
71 (['/bin/foo/ld_so_aix'], ['gcc'])
72 """
73 pivot = os.path.basename(cmd[0]) == 'ld_so_aix'
74 return cmd[:pivot], cmd[pivot:]
75
76
77def _linker_params(linker_cmd, compiler_cmd):
78 """
79 The linker command usually begins with the compiler
80 command (possibly multiple elements), followed by zero or more
81 params for shared library building.
82
83 If the LDSHARED env variable overrides the linker command,
84 however, the commands may not match.
85
86 Return the best guess of the linker parameters by stripping
87 the linker command. If the compiler command does not
88 match the linker command, assume the linker command is
89 just the first element.
90
91 >>> _linker_params('gcc foo bar'.split(), ['gcc'])
92 ['foo', 'bar']
93 >>> _linker_params('gcc foo bar'.split(), ['other'])
94 ['foo', 'bar']
95 >>> _linker_params('ccache gcc foo bar'.split(), 'ccache gcc'.split())
96 ['foo', 'bar']
97 >>> _linker_params(['gcc'], ['gcc'])
98 []
99 """
100 c_len = len(compiler_cmd)
101 pivot = c_len if linker_cmd[:c_len] == compiler_cmd else 1
102 return linker_cmd[pivot:]
103
104
105class UnixCCompiler(CCompiler):
106
107 compiler_type = 'unix'
108
109 # These are used by CCompiler in two places: the constructor sets
110 # instance attributes 'preprocessor', 'compiler', etc. from them, and
111 # 'set_executable()' allows any of these to be set. The defaults here
112 # are pretty generic; they will probably have to be set by an outsider
113 # (eg. using information discovered by the sysconfig about building
114 # Python extensions).
115 executables = {
116 'preprocessor': None,
117 'compiler': ["cc"],
118 'compiler_so': ["cc"],
119 'compiler_cxx': ["cc"],
120 'linker_so': ["cc", "-shared"],
121 'linker_exe': ["cc"],
122 'archiver': ["ar", "-cr"],
123 'ranlib': None,
124 }
125
126 if sys.platform[:6] == "darwin":
127 executables['ranlib'] = ["ranlib"]
128
129 # Needed for the filename generation methods provided by the base
130 # class, CCompiler. NB. whoever instantiates/uses a particular
131 # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
132 # reasonable common default here, but it's not necessarily used on all
133 # Unices!
134
135 src_extensions = [".c", ".C", ".cc", ".cxx", ".cpp", ".m"]
136 obj_extension = ".o"
137 static_lib_extension = ".a"
138 shared_lib_extension = ".so"
139 dylib_lib_extension = ".dylib"
140 xcode_stub_lib_extension = ".tbd"
141 static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
142 xcode_stub_lib_format = dylib_lib_format
143 if sys.platform == "cygwin":
144 exe_extension = ".exe"
145
146 def preprocess(
147 self,
148 source,
149 output_file=None,
150 macros=None,
151 include_dirs=None,
152 extra_preargs=None,
153 extra_postargs=None,
154 ):
155 fixed_args = self._fix_compile_args(None, macros, include_dirs)
156 ignore, macros, include_dirs = fixed_args
157 pp_opts = gen_preprocess_options(macros, include_dirs)
158 pp_args = self.preprocessor + pp_opts
159 if output_file:
160 pp_args.extend(['-o', output_file])
161 if extra_preargs:
162 pp_args[:0] = extra_preargs
163 if extra_postargs:
164 pp_args.extend(extra_postargs)
165 pp_args.append(source)
166
167 # reasons to preprocess:
168 # - force is indicated
169 # - output is directed to stdout
170 # - source file is newer than the target
171 preprocess = self.force or output_file is None or newer(source, output_file)
172 if not preprocess:
173 return
174
175 if output_file:
176 self.mkpath(os.path.dirname(output_file))
177
178 try:
179 self.spawn(pp_args)
180 except DistutilsExecError as msg:
181 raise CompileError(msg)
182
183 def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
184 compiler_so = compiler_fixup(self.compiler_so, cc_args + extra_postargs)
185 try:
186 self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)
187 except DistutilsExecError as msg:
188 raise CompileError(msg)
189
190 def create_static_lib(
191 self, objects, output_libname, output_dir=None, debug=0, target_lang=None
192 ):
193 objects, output_dir = self._fix_object_args(objects, output_dir)
194
195 output_filename = self.library_filename(output_libname, output_dir=output_dir)
196
197 if self._need_link(objects, output_filename):
198 self.mkpath(os.path.dirname(output_filename))
199 self.spawn(self.archiver + [output_filename] + objects + self.objects)
200
201 # Not many Unices required ranlib anymore -- SunOS 4.x is, I
202 # think the only major Unix that does. Maybe we need some
203 # platform intelligence here to skip ranlib if it's not
204 # needed -- or maybe Python's configure script took care of
205 # it for us, hence the check for leading colon.
206 if self.ranlib:
207 try:
208 self.spawn(self.ranlib + [output_filename])
209 except DistutilsExecError as msg:
210 raise LibError(msg)
211 else:
212 log.debug("skipping %s (up-to-date)", output_filename)
213
214 def link(
215 self,
216 target_desc,
217 objects,
218 output_filename,
219 output_dir=None,
220 libraries=None,
221 library_dirs=None,
222 runtime_library_dirs=None,
223 export_symbols=None,
224 debug=0,
225 extra_preargs=None,
226 extra_postargs=None,
227 build_temp=None,
228 target_lang=None,
229 ):
230 objects, output_dir = self._fix_object_args(objects, output_dir)
231 fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
232 libraries, library_dirs, runtime_library_dirs = fixed_args
233
234 lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
235 if not isinstance(output_dir, (str, type(None))):
236 raise TypeError("'output_dir' must be a string or None")
237 if output_dir is not None:
238 output_filename = os.path.join(output_dir, output_filename)
239
240 if self._need_link(objects, output_filename):
241 ld_args = objects + self.objects + lib_opts + ['-o', output_filename]
242 if debug:
243 ld_args[:0] = ['-g']
244 if extra_preargs:
245 ld_args[:0] = extra_preargs
246 if extra_postargs:
247 ld_args.extend(extra_postargs)
248 self.mkpath(os.path.dirname(output_filename))
249 try:
250 # Select a linker based on context: linker_exe when
251 # building an executable or linker_so (with shared options)
252 # when building a shared library.
253 building_exe = target_desc == CCompiler.EXECUTABLE
254 linker = (self.linker_exe if building_exe else self.linker_so)[:]
255
256 if target_lang == "c++" and self.compiler_cxx:
257 env, linker_ne = _split_env(linker)
258 aix, linker_na = _split_aix(linker_ne)
259 _, compiler_cxx_ne = _split_env(self.compiler_cxx)
260 _, linker_exe_ne = _split_env(self.linker_exe)
261
262 params = _linker_params(linker_na, linker_exe_ne)
263 linker = env + aix + compiler_cxx_ne + params
264
265 linker = compiler_fixup(linker, ld_args)
266
267 self.spawn(linker + ld_args)
268 except DistutilsExecError as msg:
269 raise LinkError(msg)
270 else:
271 log.debug("skipping %s (up-to-date)", output_filename)
272
273 # -- Miscellaneous methods -----------------------------------------
274 # These are all used by the 'gen_lib_options() function, in
275 # ccompiler.py.
276
277 def library_dir_option(self, dir):
278 return "-L" + dir
279
280 def _is_gcc(self):
281 cc_var = sysconfig.get_config_var("CC")
282 compiler = os.path.basename(shlex.split(cc_var)[0])
283 return "gcc" in compiler or "g++" in compiler
284
285 def runtime_library_dir_option(self, dir):
286 # XXX Hackish, at the very least. See Python bug #445902:
287 # http://sourceforge.net/tracker/index.php
288 # ?func=detail&aid=445902&group_id=5470&atid=105470
289 # Linkers on different platforms need different options to
290 # specify that directories need to be added to the list of
291 # directories searched for dependencies when a dynamic library
292 # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
293 # be told to pass the -R option through to the linker, whereas
294 # other compilers and gcc on other systems just know this.
295 # Other compilers may need something slightly different. At
296 # this time, there's no way to determine this information from
297 # the configuration data stored in the Python installation, so
298 # we use this hack.
299 if sys.platform[:6] == "darwin":
300 from distutils.util import get_macosx_target_ver, split_version
301
302 macosx_target_ver = get_macosx_target_ver()
303 if macosx_target_ver and split_version(macosx_target_ver) >= [10, 5]:
304 return "-Wl,-rpath," + dir
305 else: # no support for -rpath on earlier macOS versions
306 return "-L" + dir
307 elif sys.platform[:7] == "freebsd":
308 return "-Wl,-rpath=" + dir
309 elif sys.platform[:5] == "hp-ux":
310 return [
311 "-Wl,+s" if self._is_gcc() else "+s",
312 "-L" + dir,
313 ]
314
315 # For all compilers, `-Wl` is the presumed way to
316 # pass a compiler option to the linker and `-R` is
317 # the way to pass an RPATH.
318 if sysconfig.get_config_var("GNULD") == "yes":
319 # GNU ld needs an extra option to get a RUNPATH
320 # instead of just an RPATH.
321 return "-Wl,--enable-new-dtags,-R" + dir
322 else:
323 return "-Wl,-R" + dir
324
325 def library_option(self, lib):
326 return "-l" + lib
327
328 @staticmethod
329 def _library_root(dir):
330 """
331 macOS users can specify an alternate SDK using'-isysroot'.
332 Calculate the SDK root if it is specified.
333
334 Note that, as of Xcode 7, Apple SDKs may contain textual stub
335 libraries with .tbd extensions rather than the normal .dylib
336 shared libraries installed in /. The Apple compiler tool
337 chain handles this transparently but it can cause problems
338 for programs that are being built with an SDK and searching
339 for specific libraries. Callers of find_library_file need to
340 keep in mind that the base filename of the returned SDK library
341 file might have a different extension from that of the library
342 file installed on the running system, for example:
343 /Applications/Xcode.app/Contents/Developer/Platforms/
344 MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
345 usr/lib/libedit.tbd
346 vs
347 /usr/lib/libedit.dylib
348 """
349 cflags = sysconfig.get_config_var('CFLAGS')
350 match = re.search(r'-isysroot\s*(\S+)', cflags)
351
352 apply_root = (
353 sys.platform == 'darwin'
354 and match
355 and (
356 dir.startswith('/System/')
357 or (dir.startswith('/usr/') and not dir.startswith('/usr/local/'))
358 )
359 )
360
361 return os.path.join(match.group(1), dir[1:]) if apply_root else dir
362
363 def find_library_file(self, dirs, lib, debug=0):
364 r"""
365 Second-guess the linker with not much hard
366 data to go on: GCC seems to prefer the shared library, so
367 assume that *all* Unix C compilers do,
368 ignoring even GCC's "-static" option.
369
370 >>> compiler = UnixCCompiler()
371 >>> compiler._library_root = lambda dir: dir
372 >>> monkeypatch = getfixture('monkeypatch')
373 >>> monkeypatch.setattr(os.path, 'exists', lambda d: 'existing' in d)
374 >>> dirs = ('/foo/bar/missing', '/foo/bar/existing')
375 >>> compiler.find_library_file(dirs, 'abc').replace('\\', '/')
376 '/foo/bar/existing/libabc.dylib'
377 >>> compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/')
378 '/foo/bar/existing/libabc.dylib'
379 >>> monkeypatch.setattr(os.path, 'exists',
380 ... lambda d: 'existing' in d and '.a' in d)
381 >>> compiler.find_library_file(dirs, 'abc').replace('\\', '/')
382 '/foo/bar/existing/libabc.a'
383 >>> compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/')
384 '/foo/bar/existing/libabc.a'
385 """
386 lib_names = (
387 self.library_filename(lib, lib_type=type)
388 for type in 'dylib xcode_stub shared static'.split()
389 )
390
391 roots = map(self._library_root, dirs)
392
393 searched = (
394 os.path.join(root, lib_name)
395 for root, lib_name in itertools.product(roots, lib_names)
396 )
397
398 found = filter(os.path.exists, searched)
399
400 # Return None if it could not be found in any dir.
401 return next(found, None)