Path: blob/master/venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py
811 views
"""distutils.unixccompiler12Contains the UnixCCompiler class, a subclass of CCompiler that handles3the "typical" Unix-style command-line C compiler:4* macros defined with -Dname[=value]5* macros undefined with -Uname6* include search directories specified with -Idir7* libraries specified with -lllib8* library search directories specified with -Ldir9* compile handled by 'cc' (or similar) executable with -c option:10compiles .c to .o11* link static library handled by 'ar' command (possibly with 'ranlib')12* link shared library handled by 'cc -shared'13"""1415import os, sys, re1617from distutils import sysconfig18from distutils.dep_util import newer19from distutils.ccompiler import \20CCompiler, gen_preprocess_options, gen_lib_options21from distutils.errors import \22DistutilsExecError, CompileError, LibError, LinkError23from distutils import log2425if sys.platform == 'darwin':26import _osx_support2728# XXX Things not currently handled:29# * optimization/debug/warning flags; we just use whatever's in Python's30# Makefile and live with it. Is this adequate? If not, we might31# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,32# SunCCompiler, and I suspect down that road lies madness.33# * even if we don't know a warning flag from an optimization flag,34# we need some way for outsiders to feed preprocessor/compiler/linker35# flags in to us -- eg. a sysadmin might want to mandate certain flags36# via a site config file, or a user might want to set something for37# compiling this module distribution only via the setup.py command38# line, whatever. As long as these options come from something on the39# current system, they can be as system-dependent as they like, and we40# should just happily stuff them into the preprocessor/compiler/linker41# options and carry on.424344class UnixCCompiler(CCompiler):4546compiler_type = 'unix'4748# These are used by CCompiler in two places: the constructor sets49# instance attributes 'preprocessor', 'compiler', etc. from them, and50# 'set_executable()' allows any of these to be set. The defaults here51# are pretty generic; they will probably have to be set by an outsider52# (eg. using information discovered by the sysconfig about building53# Python extensions).54executables = {'preprocessor' : None,55'compiler' : ["cc"],56'compiler_so' : ["cc"],57'compiler_cxx' : ["cc"],58'linker_so' : ["cc", "-shared"],59'linker_exe' : ["cc"],60'archiver' : ["ar", "-cr"],61'ranlib' : None,62}6364if sys.platform[:6] == "darwin":65executables['ranlib'] = ["ranlib"]6667# Needed for the filename generation methods provided by the base68# class, CCompiler. NB. whoever instantiates/uses a particular69# UnixCCompiler instance should set 'shared_lib_ext' -- we set a70# reasonable common default here, but it's not necessarily used on all71# Unices!7273src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]74obj_extension = ".o"75static_lib_extension = ".a"76shared_lib_extension = ".so"77dylib_lib_extension = ".dylib"78xcode_stub_lib_extension = ".tbd"79static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"80xcode_stub_lib_format = dylib_lib_format81if sys.platform == "cygwin":82exe_extension = ".exe"8384def preprocess(self, source, output_file=None, macros=None,85include_dirs=None, extra_preargs=None, extra_postargs=None):86fixed_args = self._fix_compile_args(None, macros, include_dirs)87ignore, macros, include_dirs = fixed_args88pp_opts = gen_preprocess_options(macros, include_dirs)89pp_args = self.preprocessor + pp_opts90if output_file:91pp_args.extend(['-o', output_file])92if extra_preargs:93pp_args[:0] = extra_preargs94if extra_postargs:95pp_args.extend(extra_postargs)96pp_args.append(source)9798# We need to preprocess: either we're being forced to, or we're99# generating output to stdout, or there's a target output file and100# the source file is newer than the target (or the target doesn't101# exist).102if self.force or output_file is None or newer(source, output_file):103if output_file:104self.mkpath(os.path.dirname(output_file))105try:106self.spawn(pp_args)107except DistutilsExecError as msg:108raise CompileError(msg)109110def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):111compiler_so = self.compiler_so112if sys.platform == 'darwin':113compiler_so = _osx_support.compiler_fixup(compiler_so,114cc_args + extra_postargs)115try:116self.spawn(compiler_so + cc_args + [src, '-o', obj] +117extra_postargs)118except DistutilsExecError as msg:119raise CompileError(msg)120121def create_static_lib(self, objects, output_libname,122output_dir=None, debug=0, target_lang=None):123objects, output_dir = self._fix_object_args(objects, output_dir)124125output_filename = \126self.library_filename(output_libname, output_dir=output_dir)127128if self._need_link(objects, output_filename):129self.mkpath(os.path.dirname(output_filename))130self.spawn(self.archiver +131[output_filename] +132objects + self.objects)133134# Not many Unices required ranlib anymore -- SunOS 4.x is, I135# think the only major Unix that does. Maybe we need some136# platform intelligence here to skip ranlib if it's not137# needed -- or maybe Python's configure script took care of138# it for us, hence the check for leading colon.139if self.ranlib:140try:141self.spawn(self.ranlib + [output_filename])142except DistutilsExecError as msg:143raise LibError(msg)144else:145log.debug("skipping %s (up-to-date)", output_filename)146147def link(self, target_desc, objects,148output_filename, output_dir=None, libraries=None,149library_dirs=None, runtime_library_dirs=None,150export_symbols=None, debug=0, extra_preargs=None,151extra_postargs=None, build_temp=None, target_lang=None):152objects, output_dir = self._fix_object_args(objects, output_dir)153fixed_args = self._fix_lib_args(libraries, library_dirs,154runtime_library_dirs)155libraries, library_dirs, runtime_library_dirs = fixed_args156157lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,158libraries)159if not isinstance(output_dir, (str, type(None))):160raise TypeError("'output_dir' must be a string or None")161if output_dir is not None:162output_filename = os.path.join(output_dir, output_filename)163164if self._need_link(objects, output_filename):165ld_args = (objects + self.objects +166lib_opts + ['-o', output_filename])167if debug:168ld_args[:0] = ['-g']169if extra_preargs:170ld_args[:0] = extra_preargs171if extra_postargs:172ld_args.extend(extra_postargs)173self.mkpath(os.path.dirname(output_filename))174try:175if target_desc == CCompiler.EXECUTABLE:176linker = self.linker_exe[:]177else:178linker = self.linker_so[:]179if target_lang == "c++" and self.compiler_cxx:180# skip over environment variable settings if /usr/bin/env181# is used to set up the linker's environment.182# This is needed on OSX. Note: this assumes that the183# normal and C++ compiler have the same environment184# settings.185i = 0186if os.path.basename(linker[0]) == "env":187i = 1188while '=' in linker[i]:189i += 1190191if os.path.basename(linker[i]) == 'ld_so_aix':192# AIX platforms prefix the compiler with the ld_so_aix193# script, so we need to adjust our linker index194offset = 1195else:196offset = 0197198linker[i+offset] = self.compiler_cxx[i]199200if sys.platform == 'darwin':201linker = _osx_support.compiler_fixup(linker, ld_args)202203self.spawn(linker + ld_args)204except DistutilsExecError as msg:205raise LinkError(msg)206else:207log.debug("skipping %s (up-to-date)", output_filename)208209# -- Miscellaneous methods -----------------------------------------210# These are all used by the 'gen_lib_options() function, in211# ccompiler.py.212213def library_dir_option(self, dir):214return "-L" + dir215216def _is_gcc(self, compiler_name):217return "gcc" in compiler_name or "g++" in compiler_name218219def runtime_library_dir_option(self, dir):220# XXX Hackish, at the very least. See Python bug #445902:221# http://sourceforge.net/tracker/index.php222# ?func=detail&aid=445902&group_id=5470&atid=105470223# Linkers on different platforms need different options to224# specify that directories need to be added to the list of225# directories searched for dependencies when a dynamic library226# is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to227# be told to pass the -R option through to the linker, whereas228# other compilers and gcc on other systems just know this.229# Other compilers may need something slightly different. At230# this time, there's no way to determine this information from231# the configuration data stored in the Python installation, so232# we use this hack.233compiler = os.path.basename(sysconfig.get_config_var("CC"))234if sys.platform[:6] == "darwin":235# MacOSX's linker doesn't understand the -R flag at all236return "-L" + dir237elif sys.platform[:7] == "freebsd":238return "-Wl,-rpath=" + dir239elif sys.platform[:5] == "hp-ux":240if self._is_gcc(compiler):241return ["-Wl,+s", "-L" + dir]242return ["+s", "-L" + dir]243else:244if self._is_gcc(compiler):245# gcc on non-GNU systems does not need -Wl, but can246# use it anyway. Since distutils has always passed in247# -Wl whenever gcc was used in the past it is probably248# safest to keep doing so.249if sysconfig.get_config_var("GNULD") == "yes":250# GNU ld needs an extra option to get a RUNPATH251# instead of just an RPATH.252return "-Wl,--enable-new-dtags,-R" + dir253else:254return "-Wl,-R" + dir255else:256# No idea how --enable-new-dtags would be passed on to257# ld if this system was using GNU ld. Don't know if a258# system like this even exists.259return "-R" + dir260261def library_option(self, lib):262return "-l" + lib263264def find_library_file(self, dirs, lib, debug=0):265shared_f = self.library_filename(lib, lib_type='shared')266dylib_f = self.library_filename(lib, lib_type='dylib')267xcode_stub_f = self.library_filename(lib, lib_type='xcode_stub')268static_f = self.library_filename(lib, lib_type='static')269270if sys.platform == 'darwin':271# On OSX users can specify an alternate SDK using272# '-isysroot', calculate the SDK root if it is specified273# (and use it further on)274#275# Note that, as of Xcode 7, Apple SDKs may contain textual stub276# libraries with .tbd extensions rather than the normal .dylib277# shared libraries installed in /. The Apple compiler tool278# chain handles this transparently but it can cause problems279# for programs that are being built with an SDK and searching280# for specific libraries. Callers of find_library_file need to281# keep in mind that the base filename of the returned SDK library282# file might have a different extension from that of the library283# file installed on the running system, for example:284# /Applications/Xcode.app/Contents/Developer/Platforms/285# MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/286# usr/lib/libedit.tbd287# vs288# /usr/lib/libedit.dylib289cflags = sysconfig.get_config_var('CFLAGS')290m = re.search(r'-isysroot\s*(\S+)', cflags)291if m is None:292sysroot = '/'293else:294sysroot = m.group(1)295296297298for dir in dirs:299shared = os.path.join(dir, shared_f)300dylib = os.path.join(dir, dylib_f)301static = os.path.join(dir, static_f)302xcode_stub = os.path.join(dir, xcode_stub_f)303304if sys.platform == 'darwin' and (305dir.startswith('/System/') or (306dir.startswith('/usr/') and not dir.startswith('/usr/local/'))):307308shared = os.path.join(sysroot, dir[1:], shared_f)309dylib = os.path.join(sysroot, dir[1:], dylib_f)310static = os.path.join(sysroot, dir[1:], static_f)311xcode_stub = os.path.join(sysroot, dir[1:], xcode_stub_f)312313# We're second-guessing the linker here, with not much hard314# data to go on: GCC seems to prefer the shared library, so I'm315# assuming that *all* Unix C compilers do. And of course I'm316# ignoring even GCC's "-static" option. So sue me.317if os.path.exists(dylib):318return dylib319elif os.path.exists(xcode_stub):320return xcode_stub321elif os.path.exists(shared):322return shared323elif os.path.exists(static):324return static325326# Oops, didn't find it in *any* of 'dirs'327return None328329330