ยปCore Development>Code coverage>Lib/distutils/unixccompiler.py

Python code coverage for Lib/distutils/unixccompiler.py

#countcontent
1n/a"""distutils.unixccompiler
2n/a
3n/aContains the UnixCCompiler class, a subclass of CCompiler that handles
4n/athe "typical" Unix-style command-line C compiler:
5n/a * macros defined with -Dname[=value]
6n/a * macros undefined with -Uname
7n/a * include search directories specified with -Idir
8n/a * libraries specified with -lllib
9n/a * library search directories specified with -Ldir
10n/a * compile handled by 'cc' (or similar) executable with -c option:
11n/a compiles .c to .o
12n/a * link static library handled by 'ar' command (possibly with 'ranlib')
13n/a * link shared library handled by 'cc -shared'
14n/a"""
15n/a
16n/aimport os, sys, re
17n/a
18n/afrom distutils import sysconfig
19n/afrom distutils.dep_util import newer
20n/afrom distutils.ccompiler import \
21n/a CCompiler, gen_preprocess_options, gen_lib_options
22n/afrom distutils.errors import \
23n/a DistutilsExecError, CompileError, LibError, LinkError
24n/afrom distutils import log
25n/a
26n/aif sys.platform == 'darwin':
27n/a import _osx_support
28n/a
29n/a# XXX Things not currently handled:
30n/a# * optimization/debug/warning flags; we just use whatever's in Python's
31n/a# Makefile and live with it. Is this adequate? If not, we might
32n/a# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
33n/a# SunCCompiler, and I suspect down that road lies madness.
34n/a# * even if we don't know a warning flag from an optimization flag,
35n/a# we need some way for outsiders to feed preprocessor/compiler/linker
36n/a# flags in to us -- eg. a sysadmin might want to mandate certain flags
37n/a# via a site config file, or a user might want to set something for
38n/a# compiling this module distribution only via the setup.py command
39n/a# line, whatever. As long as these options come from something on the
40n/a# current system, they can be as system-dependent as they like, and we
41n/a# should just happily stuff them into the preprocessor/compiler/linker
42n/a# options and carry on.
43n/a
44n/a
45n/aclass UnixCCompiler(CCompiler):
46n/a
47n/a compiler_type = 'unix'
48n/a
49n/a # These are used by CCompiler in two places: the constructor sets
50n/a # instance attributes 'preprocessor', 'compiler', etc. from them, and
51n/a # 'set_executable()' allows any of these to be set. The defaults here
52n/a # are pretty generic; they will probably have to be set by an outsider
53n/a # (eg. using information discovered by the sysconfig about building
54n/a # Python extensions).
55n/a executables = {'preprocessor' : None,
56n/a 'compiler' : ["cc"],
57n/a 'compiler_so' : ["cc"],
58n/a 'compiler_cxx' : ["cc"],
59n/a 'linker_so' : ["cc", "-shared"],
60n/a 'linker_exe' : ["cc"],
61n/a 'archiver' : ["ar", "-cr"],
62n/a 'ranlib' : None,
63n/a }
64n/a
65n/a if sys.platform[:6] == "darwin":
66n/a executables['ranlib'] = ["ranlib"]
67n/a
68n/a # Needed for the filename generation methods provided by the base
69n/a # class, CCompiler. NB. whoever instantiates/uses a particular
70n/a # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
71n/a # reasonable common default here, but it's not necessarily used on all
72n/a # Unices!
73n/a
74n/a src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]
75n/a obj_extension = ".o"
76n/a static_lib_extension = ".a"
77n/a shared_lib_extension = ".so"
78n/a dylib_lib_extension = ".dylib"
79n/a xcode_stub_lib_extension = ".tbd"
80n/a static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"
81n/a xcode_stub_lib_format = dylib_lib_format
82n/a if sys.platform == "cygwin":
83n/a exe_extension = ".exe"
84n/a
85n/a def preprocess(self, source, output_file=None, macros=None,
86n/a include_dirs=None, extra_preargs=None, extra_postargs=None):
87n/a fixed_args = self._fix_compile_args(None, macros, include_dirs)
88n/a ignore, macros, include_dirs = fixed_args
89n/a pp_opts = gen_preprocess_options(macros, include_dirs)
90n/a pp_args = self.preprocessor + pp_opts
91n/a if output_file:
92n/a pp_args.extend(['-o', output_file])
93n/a if extra_preargs:
94n/a pp_args[:0] = extra_preargs
95n/a if extra_postargs:
96n/a pp_args.extend(extra_postargs)
97n/a pp_args.append(source)
98n/a
99n/a # We need to preprocess: either we're being forced to, or we're
100n/a # generating output to stdout, or there's a target output file and
101n/a # the source file is newer than the target (or the target doesn't
102n/a # exist).
103n/a if self.force or output_file is None or newer(source, output_file):
104n/a if output_file:
105n/a self.mkpath(os.path.dirname(output_file))
106n/a try:
107n/a self.spawn(pp_args)
108n/a except DistutilsExecError as msg:
109n/a raise CompileError(msg)
110n/a
111n/a def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
112n/a compiler_so = self.compiler_so
113n/a if sys.platform == 'darwin':
114n/a compiler_so = _osx_support.compiler_fixup(compiler_so,
115n/a cc_args + extra_postargs)
116n/a try:
117n/a self.spawn(compiler_so + cc_args + [src, '-o', obj] +
118n/a extra_postargs)
119n/a except DistutilsExecError as msg:
120n/a raise CompileError(msg)
121n/a
122n/a def create_static_lib(self, objects, output_libname,
123n/a output_dir=None, debug=0, target_lang=None):
124n/a objects, output_dir = self._fix_object_args(objects, output_dir)
125n/a
126n/a output_filename = \
127n/a self.library_filename(output_libname, output_dir=output_dir)
128n/a
129n/a if self._need_link(objects, output_filename):
130n/a self.mkpath(os.path.dirname(output_filename))
131n/a self.spawn(self.archiver +
132n/a [output_filename] +
133n/a objects + self.objects)
134n/a
135n/a # Not many Unices required ranlib anymore -- SunOS 4.x is, I
136n/a # think the only major Unix that does. Maybe we need some
137n/a # platform intelligence here to skip ranlib if it's not
138n/a # needed -- or maybe Python's configure script took care of
139n/a # it for us, hence the check for leading colon.
140n/a if self.ranlib:
141n/a try:
142n/a self.spawn(self.ranlib + [output_filename])
143n/a except DistutilsExecError as msg:
144n/a raise LibError(msg)
145n/a else:
146n/a log.debug("skipping %s (up-to-date)", output_filename)
147n/a
148n/a def link(self, target_desc, objects,
149n/a output_filename, output_dir=None, libraries=None,
150n/a library_dirs=None, runtime_library_dirs=None,
151n/a export_symbols=None, debug=0, extra_preargs=None,
152n/a extra_postargs=None, build_temp=None, target_lang=None):
153n/a objects, output_dir = self._fix_object_args(objects, output_dir)
154n/a fixed_args = self._fix_lib_args(libraries, library_dirs,
155n/a runtime_library_dirs)
156n/a libraries, library_dirs, runtime_library_dirs = fixed_args
157n/a
158n/a lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
159n/a libraries)
160n/a if not isinstance(output_dir, (str, type(None))):
161n/a raise TypeError("'output_dir' must be a string or None")
162n/a if output_dir is not None:
163n/a output_filename = os.path.join(output_dir, output_filename)
164n/a
165n/a if self._need_link(objects, output_filename):
166n/a ld_args = (objects + self.objects +
167n/a lib_opts + ['-o', output_filename])
168n/a if debug:
169n/a ld_args[:0] = ['-g']
170n/a if extra_preargs:
171n/a ld_args[:0] = extra_preargs
172n/a if extra_postargs:
173n/a ld_args.extend(extra_postargs)
174n/a self.mkpath(os.path.dirname(output_filename))
175n/a try:
176n/a if target_desc == CCompiler.EXECUTABLE:
177n/a linker = self.linker_exe[:]
178n/a else:
179n/a linker = self.linker_so[:]
180n/a if target_lang == "c++" and self.compiler_cxx:
181n/a # skip over environment variable settings if /usr/bin/env
182n/a # is used to set up the linker's environment.
183n/a # This is needed on OSX. Note: this assumes that the
184n/a # normal and C++ compiler have the same environment
185n/a # settings.
186n/a i = 0
187n/a if os.path.basename(linker[0]) == "env":
188n/a i = 1
189n/a while '=' in linker[i]:
190n/a i += 1
191n/a linker[i] = self.compiler_cxx[i]
192n/a
193n/a if sys.platform == 'darwin':
194n/a linker = _osx_support.compiler_fixup(linker, ld_args)
195n/a
196n/a self.spawn(linker + ld_args)
197n/a except DistutilsExecError as msg:
198n/a raise LinkError(msg)
199n/a else:
200n/a log.debug("skipping %s (up-to-date)", output_filename)
201n/a
202n/a # -- Miscellaneous methods -----------------------------------------
203n/a # These are all used by the 'gen_lib_options() function, in
204n/a # ccompiler.py.
205n/a
206n/a def library_dir_option(self, dir):
207n/a return "-L" + dir
208n/a
209n/a def _is_gcc(self, compiler_name):
210n/a return "gcc" in compiler_name or "g++" in compiler_name
211n/a
212n/a def runtime_library_dir_option(self, dir):
213n/a # XXX Hackish, at the very least. See Python bug #445902:
214n/a # http://sourceforge.net/tracker/index.php
215n/a # ?func=detail&aid=445902&group_id=5470&atid=105470
216n/a # Linkers on different platforms need different options to
217n/a # specify that directories need to be added to the list of
218n/a # directories searched for dependencies when a dynamic library
219n/a # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to
220n/a # be told to pass the -R option through to the linker, whereas
221n/a # other compilers and gcc on other systems just know this.
222n/a # Other compilers may need something slightly different. At
223n/a # this time, there's no way to determine this information from
224n/a # the configuration data stored in the Python installation, so
225n/a # we use this hack.
226n/a compiler = os.path.basename(sysconfig.get_config_var("CC"))
227n/a if sys.platform[:6] == "darwin":
228n/a # MacOSX's linker doesn't understand the -R flag at all
229n/a return "-L" + dir
230n/a elif sys.platform[:7] == "freebsd":
231n/a return "-Wl,-rpath=" + dir
232n/a elif sys.platform[:5] == "hp-ux":
233n/a if self._is_gcc(compiler):
234n/a return ["-Wl,+s", "-L" + dir]
235n/a return ["+s", "-L" + dir]
236n/a elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":
237n/a return ["-rpath", dir]
238n/a else:
239n/a if self._is_gcc(compiler):
240n/a # gcc on non-GNU systems does not need -Wl, but can
241n/a # use it anyway. Since distutils has always passed in
242n/a # -Wl whenever gcc was used in the past it is probably
243n/a # safest to keep doing so.
244n/a if sysconfig.get_config_var("GNULD") == "yes":
245n/a # GNU ld needs an extra option to get a RUNPATH
246n/a # instead of just an RPATH.
247n/a return "-Wl,--enable-new-dtags,-R" + dir
248n/a else:
249n/a return "-Wl,-R" + dir
250n/a else:
251n/a # No idea how --enable-new-dtags would be passed on to
252n/a # ld if this system was using GNU ld. Don't know if a
253n/a # system like this even exists.
254n/a return "-R" + dir
255n/a
256n/a def library_option(self, lib):
257n/a return "-l" + lib
258n/a
259n/a def find_library_file(self, dirs, lib, debug=0):
260n/a shared_f = self.library_filename(lib, lib_type='shared')
261n/a dylib_f = self.library_filename(lib, lib_type='dylib')
262n/a xcode_stub_f = self.library_filename(lib, lib_type='xcode_stub')
263n/a static_f = self.library_filename(lib, lib_type='static')
264n/a
265n/a if sys.platform == 'darwin':
266n/a # On OSX users can specify an alternate SDK using
267n/a # '-isysroot', calculate the SDK root if it is specified
268n/a # (and use it further on)
269n/a #
270n/a # Note that, as of Xcode 7, Apple SDKs may contain textual stub
271n/a # libraries with .tbd extensions rather than the normal .dylib
272n/a # shared libraries installed in /. The Apple compiler tool
273n/a # chain handles this transparently but it can cause problems
274n/a # for programs that are being built with an SDK and searching
275n/a # for specific libraries. Callers of find_library_file need to
276n/a # keep in mind that the base filename of the returned SDK library
277n/a # file might have a different extension from that of the library
278n/a # file installed on the running system, for example:
279n/a # /Applications/Xcode.app/Contents/Developer/Platforms/
280n/a # MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/
281n/a # usr/lib/libedit.tbd
282n/a # vs
283n/a # /usr/lib/libedit.dylib
284n/a cflags = sysconfig.get_config_var('CFLAGS')
285n/a m = re.search(r'-isysroot\s+(\S+)', cflags)
286n/a if m is None:
287n/a sysroot = '/'
288n/a else:
289n/a sysroot = m.group(1)
290n/a
291n/a
292n/a
293n/a for dir in dirs:
294n/a shared = os.path.join(dir, shared_f)
295n/a dylib = os.path.join(dir, dylib_f)
296n/a static = os.path.join(dir, static_f)
297n/a xcode_stub = os.path.join(dir, xcode_stub_f)
298n/a
299n/a if sys.platform == 'darwin' and (
300n/a dir.startswith('/System/') or (
301n/a dir.startswith('/usr/') and not dir.startswith('/usr/local/'))):
302n/a
303n/a shared = os.path.join(sysroot, dir[1:], shared_f)
304n/a dylib = os.path.join(sysroot, dir[1:], dylib_f)
305n/a static = os.path.join(sysroot, dir[1:], static_f)
306n/a xcode_stub = os.path.join(sysroot, dir[1:], xcode_stub_f)
307n/a
308n/a # We're second-guessing the linker here, with not much hard
309n/a # data to go on: GCC seems to prefer the shared library, so I'm
310n/a # assuming that *all* Unix C compilers do. And of course I'm
311n/a # ignoring even GCC's "-static" option. So sue me.
312n/a if os.path.exists(dylib):
313n/a return dylib
314n/a elif os.path.exists(xcode_stub):
315n/a return xcode_stub
316n/a elif os.path.exists(shared):
317n/a return shared
318n/a elif os.path.exists(static):
319n/a return static
320n/a
321n/a # Oops, didn't find it in *any* of 'dirs'
322n/a return None