]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/setuptools/_distutils/unixccompiler.py
1 """distutils.unixccompiler
3 Contains the UnixCCompiler class, a subclass of CCompiler that handles
4 the "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:
12 * link static library handled by 'ar' command (possibly with 'ranlib')
13 * link shared library handled by 'cc -shared'
22 from . import sysconfig
23 from .dep_util
import newer
24 from .ccompiler
import CCompiler
, gen_preprocess_options
, gen_lib_options
25 from .errors
import DistutilsExecError
, CompileError
, LibError
, LinkError
27 from ._macos
_compat
import compiler_fixup
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.
47 For macOS, split command into 'env' portion (if any)
48 and the rest of the linker command.
50 >>> _split_env(['a', 'b', 'c'])
52 >>> _split_env(['/usr/bin/env', 'A=3', 'gcc'])
53 (['/usr/bin/env', 'A=3'], ['gcc'])
56 if os
.path
.basename(cmd
[0]) == "env":
58 while '=' in cmd
[pivot
]:
60 return cmd
[:pivot
], cmd
[pivot
:]
65 AIX platforms prefix the compiler with the ld_so_aix
66 script, so split that from the linker command.
68 >>> _split_aix(['a', 'b', 'c'])
70 >>> _split_aix(['/bin/foo/ld_so_aix', 'gcc'])
71 (['/bin/foo/ld_so_aix'], ['gcc'])
73 pivot
= os
.path
.basename(cmd
[0]) == 'ld_so_aix'
74 return cmd
[:pivot
], cmd
[pivot
:]
77 def _linker_params(linker_cmd
, compiler_cmd
):
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.
83 If the LDSHARED env variable overrides the linker command,
84 however, the commands may not match.
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.
91 >>> _linker_params('gcc foo bar'.split(), ['gcc'])
93 >>> _linker_params('gcc foo bar'.split(), ['other'])
95 >>> _linker_params('ccache gcc foo bar'.split(), 'ccache gcc'.split())
97 >>> _linker_params(['gcc'], ['gcc'])
100 c_len
= len(compiler_cmd
)
101 pivot
= c_len
if linker_cmd
[:c_len
] == compiler_cmd
else 1
102 return linker_cmd
[pivot
:]
105 class UnixCCompiler(CCompiler
):
107 compiler_type
= 'unix'
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).
116 'preprocessor': None,
118 'compiler_so': ["cc"],
119 'compiler_cxx': ["cc"],
120 'linker_so': ["cc", "-shared"],
121 'linker_exe': ["cc"],
122 'archiver': ["ar", "-cr"],
126 if sys
.platform
[:6] == "darwin":
127 executables
['ranlib'] = ["ranlib"]
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
135 src_extensions
= [".c", ".C", ".cc", ".cxx", ".cpp", ".m"]
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"
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
160 pp_args
.extend(['-o', output_file
])
162 pp_args
[:0] = extra_preargs
164 pp_args
.extend(extra_postargs
)
165 pp_args
.append(source
)
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
)
176 self
.mkpath(os
.path
.dirname(output_file
))
180 except DistutilsExecError
as msg
:
181 raise CompileError(msg
)
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
)
186 self
.spawn(compiler_so
+ cc_args
+ [src
, '-o', obj
] + extra_postargs
)
187 except DistutilsExecError
as msg
:
188 raise CompileError(msg
)
190 def create_static_lib(
191 self
, objects
, output_libname
, output_dir
=None, debug
=0, target_lang
=None
193 objects
, output_dir
= self
._fix
_object
_args
(objects
, output_dir
)
195 output_filename
= self
.library_filename(output_libname
, output_dir
=output_dir
)
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
)
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.
208 self
.spawn(self
.ranlib
+ [output_filename
])
209 except DistutilsExecError
as msg
:
212 log
.debug("skipping %s (up-to-date)", output_filename
)
222 runtime_library_dirs
=None,
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
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
)
240 if self
._need
_link
(objects
, output_filename
):
241 ld_args
= objects
+ self
.objects
+ lib_opts
+ ['-o', output_filename
]
245 ld_args
[:0] = extra_preargs
247 ld_args
.extend(extra_postargs
)
248 self
.mkpath(os
.path
.dirname(output_filename
))
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
)[:]
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
)
262 params
= _linker_params(linker_na
, linker_exe_ne
)
263 linker
= env
+ aix
+ compiler_cxx_ne
+ params
265 linker
= compiler_fixup(linker
, ld_args
)
267 self
.spawn(linker
+ ld_args
)
268 except DistutilsExecError
as msg
:
271 log
.debug("skipping %s (up-to-date)", output_filename
)
273 # -- Miscellaneous methods -----------------------------------------
274 # These are all used by the 'gen_lib_options() function, in
277 def library_dir_option(self
, dir):
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
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
299 if sys
.platform
[:6] == "darwin":
300 from distutils
.util
import get_macosx_target_ver
, split_version
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
307 elif sys
.platform
[:7] == "freebsd":
308 return "-Wl,-rpath=" + dir
309 elif sys
.platform
[:5] == "hp-ux":
311 "-Wl,+s" if self
._is
_gcc
() else "+s",
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
323 return "-Wl,-R" + dir
325 def library_option(self
, lib
):
329 def _library_root(dir):
331 macOS users can specify an alternate SDK using'-isysroot'.
332 Calculate the SDK root if it is specified.
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/
347 /usr/lib/libedit.dylib
349 cflags
= sysconfig
.get_config_var('CFLAGS')
350 match
= re
.search(r
'-isysroot\s*(\S+)', cflags
)
353 sys
.platform
== 'darwin'
356 dir.startswith('/System/')
357 or (dir.startswith('/usr/') and not dir.startswith('/usr/local/'))
361 return os
.path
.join(match
.group(1), dir[1:]) if apply_root
else dir
363 def find_library_file(self
, dirs
, lib
, debug
=0):
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.
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'
387 self
.library_filename(lib
, lib_type
=type)
388 for type in 'dylib xcode_stub shared static'.split()
391 roots
= map(self
._library
_root
, dirs
)
394 os
.path
.join(root
, lib_name
)
395 for root
, lib_name
in itertools
.product(roots
, lib_names
)
398 found
= filter(os
.path
.exists
, searched
)
400 # Return None if it could not be found in any dir.
401 return next(found
, None)