From 6b016852f83621178ae053509c044d6fd27f46e3 Mon Sep 17 00:00:00 2001 From: Gustavo Niemeyer Date: Tue, 5 Nov 2002 16:12:02 +0000 Subject: This patch fixes the following bugs: [#413582] g++ must be called for c++ extensions [#454030] distutils cannot link C++ code with GCC topdir = "Lib/distutils" * bcppcompiler.py (BCPPCompiler.create_static_lib): Fixed prototype, removing extra_preargs and extra_postargs parameters. Included target_lang parameter. (BCPPCompiler.link): Included target_lang parameter. * msvccompiler.py (MSVCCompiler.create_static_lib): Fixed prototype, removing extra_preargs and extra_postargs parameters. Included target_lang parameter. (MSVCCompiler.link): Included target_lang parameter. * ccompiler.py (CCompiler): New language_map and language_order attributes, used by CCompiler.detect_language(). (CCompiler.detect_language): New method, will return the language of a given source, or list of sources. Individual source language is detected using the language_map dict. When mixed sources are used, language_order will stablish the language precedence. (CCompiler.create_static_lib, CCompiler.link, CCompiler.link_executable, CCompiler.link_shared_object, CCompiler.link_shared_lib): Inlcuded target_lang parameter. * cygwinccompiler.py (CygwinCCompiler.link): Included target_lang parameter. * emxccompiler.py (EMXCCompiler.link): Included target_lang parameter. * mwerkscompiler.py (MWerksCompiler.link): Included target_lang parameter. * extension.py (Extension.__init__): New 'language' parameter/attribute, initialized to None by default. If provided will overlap the automatic detection made by CCompiler.detect_language(), in build_ext command. * sysconfig.py (customize_compiler): Check Makefile for CXX option, and also the environment variable CXX. Use the resulting value in the 'compiler_cxx' parameter of compiler.set_executables(). * unixccompiler.py (UnixCCompiler): Included 'compiler_cxx' in executables dict, defaulting to 'cc'. (UnixCCompiler.create_static_lib): Included target_lang parameter. (UnixCCompiler.link): Included target_lang parameter, and made linker command use compiler_cxx, if target_lang is 'c++'. * command/build_ext.py (build_ext.build_extension): Pass new ext.language attribute to compiler.link_shared_object()'s target_lang parameter. If ext.language is not provided, detect language using compiler.detect_language(sources) instead. * command/config.py (config._link): Pass already available lang parameter as target_lang parameter of compiler.link_executable(). --- Lib/distutils/bcppcompiler.py | 10 ++---- Lib/distutils/ccompiler.py | 63 +++++++++++++++++++++++++++++++++----- Lib/distutils/command/build_ext.py | 6 +++- Lib/distutils/command/config.py | 3 +- Lib/distutils/cygwinccompiler.py | 6 ++-- Lib/distutils/emxccompiler.py | 6 ++-- Lib/distutils/extension.py | 5 +++ Lib/distutils/msvccompiler.py | 10 ++---- Lib/distutils/mwerkscompiler.py | 3 +- Lib/distutils/sysconfig.py | 7 +++-- Lib/distutils/unixccompiler.py | 12 +++++--- 11 files changed, 96 insertions(+), 35 deletions(-) diff --git a/Lib/distutils/bcppcompiler.py b/Lib/distutils/bcppcompiler.py index 6e9d6c6..abe302a 100644 --- a/Lib/distutils/bcppcompiler.py +++ b/Lib/distutils/bcppcompiler.py @@ -146,8 +146,7 @@ class BCPPCompiler(CCompiler) : output_libname, output_dir=None, debug=0, - extra_preargs=None, - extra_postargs=None): + target_lang=None): (objects, output_dir) = self._fix_object_args (objects, output_dir) output_filename = \ @@ -157,10 +156,6 @@ class BCPPCompiler(CCompiler) : lib_args = [output_filename, '/u'] + objects if debug: pass # XXX what goes here? - if extra_preargs: - lib_args[:0] = extra_preargs - if extra_postargs: - lib_args.extend (extra_postargs) try: self.spawn ([self.lib] + lib_args) except DistutilsExecError, msg: @@ -183,7 +178,8 @@ class BCPPCompiler(CCompiler) : debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): # XXX this ignores 'build_temp'! should follow the lead of # msvccompiler.py diff --git a/Lib/distutils/ccompiler.py b/Lib/distutils/ccompiler.py index 60d1cae..317e21e 100644 --- a/Lib/distutils/ccompiler.py +++ b/Lib/distutils/ccompiler.py @@ -74,6 +74,19 @@ class CCompiler: shared_lib_format = None # prob. same as static_lib_format exe_extension = None # string + # Default language settings. language_map is used to detect a source + # file or Extension target language, checking source filenames. + # language_order is used to detect the language precedence, when deciding + # what language to use when mixing source types. For example, if some + # extension has two files with ".c" extension, and one with ".cpp", it + # is still linked as c++. + language_map = {".c" : "c", + ".cc" : "c++", + ".cpp" : "c++", + ".cxx" : "c++", + ".m" : "objc", + } + language_order = ["c++", "objc", "c"] def __init__ (self, verbose=0, @@ -572,6 +585,27 @@ class CCompiler: # _need_link () + def detect_language (self, sources): + """Detect the language of a given file, or list of files. Uses + language_map, and language_order to do the job. + """ + if type(sources) is not ListType: + sources = [sources] + lang = None + index = len(self.language_order) + for source in sources: + base, ext = os.path.splitext(source) + extlang = self.language_map.get(ext) + try: + extindex = self.language_order.index(extlang) + if extindex < index: + lang = extlang + index = extindex + except ValueError: + pass + return lang + + # detect_language () # -- Worker methods ------------------------------------------------ # (must be implemented by subclasses) @@ -671,7 +705,8 @@ class CCompiler: objects, output_libname, output_dir=None, - debug=0): + debug=0, + target_lang=None): """Link a bunch of stuff together to create a static library file. The "bunch of stuff" consists of the list of object files supplied as 'objects', the extra object files supplied to @@ -688,6 +723,10 @@ class CCompiler: compile step where this matters: the 'debug' flag is included here just for consistency). + 'target_lang' is the target language for which the given objects + are being compiled. This allows specific linkage time treatment of + certain languages. + Raises LibError on failure. """ pass @@ -710,7 +749,8 @@ class CCompiler: debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): """Link a bunch of stuff together to create an executable or shared library file. @@ -748,6 +788,10 @@ class CCompiler: of course that they supply command-line arguments for the particular linker being used). + 'target_lang' is the target language for which the given objects + are being compiled. This allows specific linkage time treatment of + certain languages. + Raises LinkError on failure. """ raise NotImplementedError @@ -766,13 +810,14 @@ class CCompiler: debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): self.link(CCompiler.SHARED_LIBRARY, objects, self.library_filename(output_libname, lib_type='shared'), output_dir, libraries, library_dirs, runtime_library_dirs, export_symbols, debug, - extra_preargs, extra_postargs, build_temp) + extra_preargs, extra_postargs, build_temp, target_lang) def link_shared_object (self, @@ -786,12 +831,13 @@ class CCompiler: debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): self.link(CCompiler.SHARED_OBJECT, objects, output_filename, output_dir, libraries, library_dirs, runtime_library_dirs, export_symbols, debug, - extra_preargs, extra_postargs, build_temp) + extra_preargs, extra_postargs, build_temp, target_lang) def link_executable (self, @@ -803,11 +849,12 @@ class CCompiler: runtime_library_dirs=None, debug=0, extra_preargs=None, - extra_postargs=None): + extra_postargs=None, + target_lang=None): self.link(CCompiler.EXECUTABLE, objects, self.executable_filename(output_progname), output_dir, libraries, library_dirs, runtime_library_dirs, None, - debug, extra_preargs, extra_postargs, None) + debug, extra_preargs, extra_postargs, None, target_lang) # -- Miscellaneous methods ----------------------------------------- diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index 934b457..4bfc20c 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -477,6 +477,9 @@ class build_ext (Command): objects.extend(ext.extra_objects) extra_args = ext.extra_link_args or [] + # Detect target language, if not provided + language = ext.language or self.compiler.detect_language(sources) + self.compiler.link_shared_object( objects, ext_filename, libraries=self.get_libraries(ext), @@ -485,7 +488,8 @@ class build_ext (Command): extra_postargs=extra_args, export_symbols=self.get_export_symbols(ext), debug=self.debug, - build_temp=self.build_temp) + build_temp=self.build_temp, + target_lang=language) def swig_sources (self, sources): diff --git a/Lib/distutils/command/config.py b/Lib/distutils/command/config.py index 88b1586..9ebe0d9 100644 --- a/Lib/distutils/command/config.py +++ b/Lib/distutils/command/config.py @@ -148,7 +148,8 @@ class config (Command): prog = os.path.splitext(os.path.basename(src))[0] self.compiler.link_executable([obj], prog, libraries=libraries, - library_dirs=library_dirs) + library_dirs=library_dirs, + target_lang=lang) prog = prog + self.compiler.exe_extension self.temp_files.append(prog) diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py index 9aabd8a..a046ee2 100644 --- a/Lib/distutils/cygwinccompiler.py +++ b/Lib/distutils/cygwinccompiler.py @@ -140,7 +140,8 @@ class CygwinCCompiler (UnixCCompiler): debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): # use separate copies, so we can modify the lists extra_preargs = copy.copy(extra_preargs or []) @@ -218,7 +219,8 @@ class CygwinCCompiler (UnixCCompiler): debug, extra_preargs, extra_postargs, - build_temp) + build_temp, + target_lang) # link () diff --git a/Lib/distutils/emxccompiler.py b/Lib/distutils/emxccompiler.py index 7c3ad02..624c0fe 100644 --- a/Lib/distutils/emxccompiler.py +++ b/Lib/distutils/emxccompiler.py @@ -102,7 +102,8 @@ class EMXCCompiler (UnixCCompiler): debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): # use separate copies, so we can modify the lists extra_preargs = copy.copy(extra_preargs or []) @@ -171,7 +172,8 @@ class EMXCCompiler (UnixCCompiler): debug, extra_preargs, extra_postargs, - build_temp) + build_temp, + target_lang) # link () diff --git a/Lib/distutils/extension.py b/Lib/distutils/extension.py index d73bb08..7fbeb4e 100644 --- a/Lib/distutils/extension.py +++ b/Lib/distutils/extension.py @@ -75,6 +75,9 @@ class Extension: extension_name. depends : [string] list of files that the extension depends on + language : string + extension language (i.e. "c", "c++", "objc"). Will be detected + from the source extensions if not provided. """ def __init__ (self, name, sources, @@ -89,6 +92,7 @@ class Extension: extra_link_args=None, export_symbols=None, depends=None, + language=None, ): assert type(name) is StringType, "'name' must be a string" @@ -109,6 +113,7 @@ class Extension: self.extra_link_args = extra_link_args or [] self.export_symbols = export_symbols or [] self.depends = depends or [] + self.language = language # class Extension diff --git a/Lib/distutils/msvccompiler.py b/Lib/distutils/msvccompiler.py index 65b1143..a2459ad 100644 --- a/Lib/distutils/msvccompiler.py +++ b/Lib/distutils/msvccompiler.py @@ -367,8 +367,7 @@ class MSVCCompiler (CCompiler) : output_libname, output_dir=None, debug=0, - extra_preargs=None, - extra_postargs=None): + target_lang=None): (objects, output_dir) = self._fix_object_args (objects, output_dir) output_filename = \ @@ -378,10 +377,6 @@ class MSVCCompiler (CCompiler) : lib_args = objects + ['/OUT:' + output_filename] if debug: pass # XXX what goes here? - if extra_preargs: - lib_args[:0] = extra_preargs - if extra_postargs: - lib_args.extend (extra_postargs) try: self.spawn ([self.lib] + lib_args) except DistutilsExecError, msg: @@ -404,7 +399,8 @@ class MSVCCompiler (CCompiler) : debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): (objects, output_dir) = self._fix_object_args (objects, output_dir) (libraries, library_dirs, runtime_library_dirs) = \ diff --git a/Lib/distutils/mwerkscompiler.py b/Lib/distutils/mwerkscompiler.py index cd66a09..8f62bf7 100644 --- a/Lib/distutils/mwerkscompiler.py +++ b/Lib/distutils/mwerkscompiler.py @@ -84,7 +84,8 @@ class MWerksCompiler (CCompiler) : debug=0, extra_preargs=None, extra_postargs=None, - build_temp=None): + build_temp=None, + target_lang=None): # First fixup. (objects, output_dir) = self._fix_object_args (objects, output_dir) (libraries, library_dirs, runtime_library_dirs) = \ diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index e879fa14..cc57188 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -139,11 +139,13 @@ def customize_compiler(compiler): varies across Unices and is stored in Python's Makefile. """ if compiler.compiler_type == "unix": - (cc, opt, ccshared, ldshared, so_ext) = \ - get_config_vars('CC', 'OPT', 'CCSHARED', 'LDSHARED', 'SO') + (cc, cxx, opt, ccshared, ldshared, so_ext) = \ + get_config_vars('CC', 'CXX', 'OPT', 'CCSHARED', 'LDSHARED', 'SO') if os.environ.has_key('CC'): cc = os.environ['CC'] + if os.environ.has_key('CXX'): + cxx = os.environ['CXX'] if os.environ.has_key('CPP'): cpp = os.environ['CPP'] else: @@ -163,6 +165,7 @@ def customize_compiler(compiler): preprocessor=cpp, compiler=cc_cmd, compiler_so=cc_cmd + ' ' + ccshared, + compiler_cxx=cxx, linker_so=ldshared, linker_exe=cc) diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py index 692e3eb..2f4546e 100644 --- a/Lib/distutils/unixccompiler.py +++ b/Lib/distutils/unixccompiler.py @@ -57,6 +57,7 @@ class UnixCCompiler(CCompiler): executables = {'preprocessor' : None, 'compiler' : ["cc"], 'compiler_so' : ["cc"], + 'compiler_cxx' : ["cc"], 'linker_so' : ["cc", "-shared"], 'linker_exe' : ["cc"], 'archiver' : ["ar", "-cr"], @@ -114,7 +115,7 @@ class UnixCCompiler(CCompiler): raise CompileError, msg def create_static_lib(self, objects, output_libname, - output_dir=None, debug=0): + output_dir=None, debug=0, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) output_filename = \ @@ -143,7 +144,7 @@ class UnixCCompiler(CCompiler): output_filename, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, - extra_postargs=None, build_temp=None): + extra_postargs=None, build_temp=None, target_lang=None): objects, output_dir = self._fix_object_args(objects, output_dir) libraries, library_dirs, runtime_library_dirs = \ self._fix_lib_args(libraries, library_dirs, runtime_library_dirs) @@ -167,9 +168,12 @@ class UnixCCompiler(CCompiler): self.mkpath(os.path.dirname(output_filename)) try: if target_desc == CCompiler.EXECUTABLE: - self.spawn(self.linker_exe + ld_args) + linker = self.linker_exe[:] else: - self.spawn(self.linker_so + ld_args) + linker = self.linker_so[:] + if target_lang == "c++" and self.compiler_cxx: + linker[0] = self.compiler_cxx[0] + self.spawn(linker + ld_args) except DistutilsExecError, msg: raise LinkError, msg else: -- cgit v0.12