+++ /dev/null
-"""distutils.unixccompiler\r
-\r
-Contains the UnixCCompiler class, a subclass of CCompiler that handles\r
-the "typical" Unix-style command-line C compiler:\r
- * macros defined with -Dname[=value]\r
- * macros undefined with -Uname\r
- * include search directories specified with -Idir\r
- * libraries specified with -lllib\r
- * library search directories specified with -Ldir\r
- * compile handled by 'cc' (or similar) executable with -c option:\r
- compiles .c to .o\r
- * link static library handled by 'ar' command (possibly with 'ranlib')\r
- * link shared library handled by 'cc -shared'\r
-"""\r
-\r
-__revision__ = "$Id$"\r
-\r
-import os, sys, re\r
-from types import StringType, NoneType\r
-\r
-from distutils import sysconfig\r
-from distutils.dep_util import newer\r
-from distutils.ccompiler import \\r
- CCompiler, gen_preprocess_options, gen_lib_options\r
-from distutils.errors import \\r
- DistutilsExecError, CompileError, LibError, LinkError\r
-from distutils import log\r
-\r
-# XXX Things not currently handled:\r
-# * optimization/debug/warning flags; we just use whatever's in Python's\r
-# Makefile and live with it. Is this adequate? If not, we might\r
-# have to have a bunch of subclasses GNUCCompiler, SGICCompiler,\r
-# SunCCompiler, and I suspect down that road lies madness.\r
-# * even if we don't know a warning flag from an optimization flag,\r
-# we need some way for outsiders to feed preprocessor/compiler/linker\r
-# flags in to us -- eg. a sysadmin might want to mandate certain flags\r
-# via a site config file, or a user might want to set something for\r
-# compiling this module distribution only via the setup.py command\r
-# line, whatever. As long as these options come from something on the\r
-# current system, they can be as system-dependent as they like, and we\r
-# should just happily stuff them into the preprocessor/compiler/linker\r
-# options and carry on.\r
-\r
-def _darwin_compiler_fixup(compiler_so, cc_args):\r
- """\r
- This function will strip '-isysroot PATH' and '-arch ARCH' from the\r
- compile flags if the user has specified one them in extra_compile_flags.\r
-\r
- This is needed because '-arch ARCH' adds another architecture to the\r
- build, without a way to remove an architecture. Furthermore GCC will\r
- barf if multiple '-isysroot' arguments are present.\r
- """\r
- stripArch = stripSysroot = 0\r
-\r
- compiler_so = list(compiler_so)\r
- kernel_version = os.uname()[2] # 8.4.3\r
- major_version = int(kernel_version.split('.')[0])\r
-\r
- if major_version < 8:\r
- # OSX before 10.4.0, these don't support -arch and -isysroot at\r
- # all.\r
- stripArch = stripSysroot = True\r
- else:\r
- stripArch = '-arch' in cc_args\r
- stripSysroot = '-isysroot' in cc_args\r
-\r
- if stripArch or 'ARCHFLAGS' in os.environ:\r
- while 1:\r
- try:\r
- index = compiler_so.index('-arch')\r
- # Strip this argument and the next one:\r
- del compiler_so[index:index+2]\r
- except ValueError:\r
- break\r
-\r
- if 'ARCHFLAGS' in os.environ and not stripArch:\r
- # User specified different -arch flags in the environ,\r
- # see also distutils.sysconfig\r
- compiler_so = compiler_so + os.environ['ARCHFLAGS'].split()\r
-\r
- if stripSysroot:\r
- try:\r
- index = compiler_so.index('-isysroot')\r
- # Strip this argument and the next one:\r
- del compiler_so[index:index+2]\r
- except ValueError:\r
- pass\r
-\r
- # Check if the SDK that is used during compilation actually exists,\r
- # the universal build requires the usage of a universal SDK and not all\r
- # users have that installed by default.\r
- sysroot = None\r
- if '-isysroot' in cc_args:\r
- idx = cc_args.index('-isysroot')\r
- sysroot = cc_args[idx+1]\r
- elif '-isysroot' in compiler_so:\r
- idx = compiler_so.index('-isysroot')\r
- sysroot = compiler_so[idx+1]\r
-\r
- if sysroot and not os.path.isdir(sysroot):\r
- log.warn("Compiling with an SDK that doesn't seem to exist: %s",\r
- sysroot)\r
- log.warn("Please check your Xcode installation")\r
-\r
- return compiler_so\r
-\r
-class UnixCCompiler(CCompiler):\r
-\r
- compiler_type = 'unix'\r
-\r
- # These are used by CCompiler in two places: the constructor sets\r
- # instance attributes 'preprocessor', 'compiler', etc. from them, and\r
- # 'set_executable()' allows any of these to be set. The defaults here\r
- # are pretty generic; they will probably have to be set by an outsider\r
- # (eg. using information discovered by the sysconfig about building\r
- # Python extensions).\r
- executables = {'preprocessor' : None,\r
- 'compiler' : ["cc"],\r
- 'compiler_so' : ["cc"],\r
- 'compiler_cxx' : ["cc"],\r
- 'linker_so' : ["cc", "-shared"],\r
- 'linker_exe' : ["cc"],\r
- 'archiver' : ["ar", "-cr"],\r
- 'ranlib' : None,\r
- }\r
-\r
- if sys.platform[:6] == "darwin":\r
- executables['ranlib'] = ["ranlib"]\r
-\r
- # Needed for the filename generation methods provided by the base\r
- # class, CCompiler. NB. whoever instantiates/uses a particular\r
- # UnixCCompiler instance should set 'shared_lib_ext' -- we set a\r
- # reasonable common default here, but it's not necessarily used on all\r
- # Unices!\r
-\r
- src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"]\r
- obj_extension = ".o"\r
- static_lib_extension = ".a"\r
- shared_lib_extension = ".so"\r
- dylib_lib_extension = ".dylib"\r
- static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s"\r
- if sys.platform == "cygwin":\r
- exe_extension = ".exe"\r
-\r
- def preprocess(self, source,\r
- output_file=None, macros=None, include_dirs=None,\r
- extra_preargs=None, extra_postargs=None):\r
- ignore, macros, include_dirs = \\r
- self._fix_compile_args(None, macros, include_dirs)\r
- pp_opts = gen_preprocess_options(macros, include_dirs)\r
- pp_args = self.preprocessor + pp_opts\r
- if output_file:\r
- pp_args.extend(['-o', output_file])\r
- if extra_preargs:\r
- pp_args[:0] = extra_preargs\r
- if extra_postargs:\r
- pp_args.extend(extra_postargs)\r
- pp_args.append(source)\r
-\r
- # We need to preprocess: either we're being forced to, or we're\r
- # generating output to stdout, or there's a target output file and\r
- # the source file is newer than the target (or the target doesn't\r
- # exist).\r
- if self.force or output_file is None or newer(source, output_file):\r
- if output_file:\r
- self.mkpath(os.path.dirname(output_file))\r
- try:\r
- self.spawn(pp_args)\r
- except DistutilsExecError, msg:\r
- raise CompileError, msg\r
-\r
- def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):\r
- compiler_so = self.compiler_so\r
- if sys.platform == 'darwin':\r
- compiler_so = _darwin_compiler_fixup(compiler_so, cc_args + extra_postargs)\r
- try:\r
- self.spawn(compiler_so + cc_args + [src, '-o', obj] +\r
- extra_postargs)\r
- except DistutilsExecError, msg:\r
- raise CompileError, msg\r
-\r
- def create_static_lib(self, objects, output_libname,\r
- output_dir=None, debug=0, target_lang=None):\r
- objects, output_dir = self._fix_object_args(objects, output_dir)\r
-\r
- output_filename = \\r
- self.library_filename(output_libname, output_dir=output_dir)\r
-\r
- if self._need_link(objects, output_filename):\r
- self.mkpath(os.path.dirname(output_filename))\r
- self.spawn(self.archiver +\r
- [output_filename] +\r
- objects + self.objects)\r
-\r
- # Not many Unices required ranlib anymore -- SunOS 4.x is, I\r
- # think the only major Unix that does. Maybe we need some\r
- # platform intelligence here to skip ranlib if it's not\r
- # needed -- or maybe Python's configure script took care of\r
- # it for us, hence the check for leading colon.\r
- if self.ranlib:\r
- try:\r
- self.spawn(self.ranlib + [output_filename])\r
- except DistutilsExecError, msg:\r
- raise LibError, msg\r
- else:\r
- log.debug("skipping %s (up-to-date)", output_filename)\r
-\r
- def link(self, target_desc, objects,\r
- output_filename, output_dir=None, libraries=None,\r
- library_dirs=None, runtime_library_dirs=None,\r
- export_symbols=None, debug=0, extra_preargs=None,\r
- extra_postargs=None, build_temp=None, target_lang=None):\r
- objects, output_dir = self._fix_object_args(objects, output_dir)\r
- libraries, library_dirs, runtime_library_dirs = \\r
- self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)\r
-\r
- lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,\r
- libraries)\r
- if type(output_dir) not in (StringType, NoneType):\r
- raise TypeError, "'output_dir' must be a string or None"\r
- if output_dir is not None:\r
- output_filename = os.path.join(output_dir, output_filename)\r
-\r
- if self._need_link(objects, output_filename):\r
- ld_args = (objects + self.objects +\r
- lib_opts + ['-o', output_filename])\r
- if debug:\r
- ld_args[:0] = ['-g']\r
- if extra_preargs:\r
- ld_args[:0] = extra_preargs\r
- if extra_postargs:\r
- ld_args.extend(extra_postargs)\r
- self.mkpath(os.path.dirname(output_filename))\r
- try:\r
- if target_desc == CCompiler.EXECUTABLE:\r
- linker = self.linker_exe[:]\r
- else:\r
- linker = self.linker_so[:]\r
- if target_lang == "c++" and self.compiler_cxx:\r
- # skip over environment variable settings if /usr/bin/env\r
- # is used to set up the linker's environment.\r
- # This is needed on OSX. Note: this assumes that the\r
- # normal and C++ compiler have the same environment\r
- # settings.\r
- i = 0\r
- if os.path.basename(linker[0]) == "env":\r
- i = 1\r
- while '=' in linker[i]:\r
- i = i + 1\r
-\r
- linker[i] = self.compiler_cxx[i]\r
-\r
- if sys.platform == 'darwin':\r
- linker = _darwin_compiler_fixup(linker, ld_args)\r
-\r
- self.spawn(linker + ld_args)\r
- except DistutilsExecError, msg:\r
- raise LinkError, msg\r
- else:\r
- log.debug("skipping %s (up-to-date)", output_filename)\r
-\r
- # -- Miscellaneous methods -----------------------------------------\r
- # These are all used by the 'gen_lib_options() function, in\r
- # ccompiler.py.\r
-\r
- def library_dir_option(self, dir):\r
- return "-L" + dir\r
-\r
- def _is_gcc(self, compiler_name):\r
- return "gcc" in compiler_name or "g++" in compiler_name\r
-\r
- def runtime_library_dir_option(self, dir):\r
- # XXX Hackish, at the very least. See Python bug #445902:\r
- # http://sourceforge.net/tracker/index.php\r
- # ?func=detail&aid=445902&group_id=5470&atid=105470\r
- # Linkers on different platforms need different options to\r
- # specify that directories need to be added to the list of\r
- # directories searched for dependencies when a dynamic library\r
- # is sought. GCC has to be told to pass the -R option through\r
- # to the linker, whereas other compilers just know this.\r
- # Other compilers may need something slightly different. At\r
- # this time, there's no way to determine this information from\r
- # the configuration data stored in the Python installation, so\r
- # we use this hack.\r
- compiler = os.path.basename(sysconfig.get_config_var("CC"))\r
- if sys.platform[:6] == "darwin":\r
- # MacOSX's linker doesn't understand the -R flag at all\r
- return "-L" + dir\r
- elif sys.platform[:5] == "hp-ux":\r
- if self._is_gcc(compiler):\r
- return ["-Wl,+s", "-L" + dir]\r
- return ["+s", "-L" + dir]\r
- elif sys.platform[:7] == "irix646" or sys.platform[:6] == "osf1V5":\r
- return ["-rpath", dir]\r
- elif self._is_gcc(compiler):\r
- return "-Wl,-R" + dir\r
- else:\r
- return "-R" + dir\r
-\r
- def library_option(self, lib):\r
- return "-l" + lib\r
-\r
- def find_library_file(self, dirs, lib, debug=0):\r
- shared_f = self.library_filename(lib, lib_type='shared')\r
- dylib_f = self.library_filename(lib, lib_type='dylib')\r
- static_f = self.library_filename(lib, lib_type='static')\r
-\r
- if sys.platform == 'darwin':\r
- # On OSX users can specify an alternate SDK using\r
- # '-isysroot', calculate the SDK root if it is specified\r
- # (and use it further on)\r
- cflags = sysconfig.get_config_var('CFLAGS')\r
- m = re.search(r'-isysroot\s+(\S+)', cflags)\r
- if m is None:\r
- sysroot = '/'\r
- else:\r
- sysroot = m.group(1)\r
-\r
-\r
-\r
- for dir in dirs:\r
- shared = os.path.join(dir, shared_f)\r
- dylib = os.path.join(dir, dylib_f)\r
- static = os.path.join(dir, static_f)\r
-\r
- if sys.platform == 'darwin' and (\r
- dir.startswith('/System/') or (\r
- dir.startswith('/usr/') and not dir.startswith('/usr/local/'))):\r
-\r
- shared = os.path.join(sysroot, dir[1:], shared_f)\r
- dylib = os.path.join(sysroot, dir[1:], dylib_f)\r
- static = os.path.join(sysroot, dir[1:], static_f)\r
-\r
- # We're second-guessing the linker here, with not much hard\r
- # data to go on: GCC seems to prefer the shared library, so I'm\r
- # assuming that *all* Unix C compilers do. And of course I'm\r
- # ignoring even GCC's "-static" option. So sue me.\r
- if os.path.exists(dylib):\r
- return dylib\r
- elif os.path.exists(shared):\r
- return shared\r
- elif os.path.exists(static):\r
- return static\r
-\r
- # Oops, didn't find it in *any* of 'dirs'\r
- return None\r