Skip to content

Commit 6b01685

Browse files
committed
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().
1 parent 173f11d commit 6b01685

File tree

11 files changed

+96
-35
lines changed

11 files changed

+96
-35
lines changed

Lib/distutils/bcppcompiler.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ def create_static_lib (self,
146146
output_libname,
147147
output_dir=None,
148148
debug=0,
149-
extra_preargs=None,
150-
extra_postargs=None):
149+
target_lang=None):
151150

152151
(objects, output_dir) = self._fix_object_args (objects, output_dir)
153152
output_filename = \
@@ -157,10 +156,6 @@ def create_static_lib (self,
157156
lib_args = [output_filename, '/u'] + objects
158157
if debug:
159158
pass # XXX what goes here?
160-
if extra_preargs:
161-
lib_args[:0] = extra_preargs
162-
if extra_postargs:
163-
lib_args.extend (extra_postargs)
164159
try:
165160
self.spawn ([self.lib] + lib_args)
166161
except DistutilsExecError, msg:
@@ -183,7 +178,8 @@ def link (self,
183178
debug=0,
184179
extra_preargs=None,
185180
extra_postargs=None,
186-
build_temp=None):
181+
build_temp=None,
182+
target_lang=None):
187183

188184
# XXX this ignores 'build_temp'! should follow the lead of
189185
# msvccompiler.py

Lib/distutils/ccompiler.py

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ class CCompiler:
7474
shared_lib_format = None # prob. same as static_lib_format
7575
exe_extension = None # string
7676

77+
# Default language settings. language_map is used to detect a source
78+
# file or Extension target language, checking source filenames.
79+
# language_order is used to detect the language precedence, when deciding
80+
# what language to use when mixing source types. For example, if some
81+
# extension has two files with ".c" extension, and one with ".cpp", it
82+
# is still linked as c++.
83+
language_map = {".c" : "c",
84+
".cc" : "c++",
85+
".cpp" : "c++",
86+
".cxx" : "c++",
87+
".m" : "objc",
88+
}
89+
language_order = ["c++", "objc", "c"]
7790

7891
def __init__ (self,
7992
verbose=0,
@@ -572,6 +585,27 @@ def _need_link (self, objects, output_file):
572585

573586
# _need_link ()
574587

588+
def detect_language (self, sources):
589+
"""Detect the language of a given file, or list of files. Uses
590+
language_map, and language_order to do the job.
591+
"""
592+
if type(sources) is not ListType:
593+
sources = [sources]
594+
lang = None
595+
index = len(self.language_order)
596+
for source in sources:
597+
base, ext = os.path.splitext(source)
598+
extlang = self.language_map.get(ext)
599+
try:
600+
extindex = self.language_order.index(extlang)
601+
if extindex < index:
602+
lang = extlang
603+
index = extindex
604+
except ValueError:
605+
pass
606+
return lang
607+
608+
# detect_language ()
575609

576610
# -- Worker methods ------------------------------------------------
577611
# (must be implemented by subclasses)
@@ -671,7 +705,8 @@ def create_static_lib (self,
671705
objects,
672706
output_libname,
673707
output_dir=None,
674-
debug=0):
708+
debug=0,
709+
target_lang=None):
675710
"""Link a bunch of stuff together to create a static library file.
676711
The "bunch of stuff" consists of the list of object files supplied
677712
as 'objects', the extra object files supplied to
@@ -688,6 +723,10 @@ def create_static_lib (self,
688723
compile step where this matters: the 'debug' flag is included here
689724
just for consistency).
690725
726+
'target_lang' is the target language for which the given objects
727+
are being compiled. This allows specific linkage time treatment of
728+
certain languages.
729+
691730
Raises LibError on failure.
692731
"""
693732
pass
@@ -710,7 +749,8 @@ def link (self,
710749
debug=0,
711750
extra_preargs=None,
712751
extra_postargs=None,
713-
build_temp=None):
752+
build_temp=None,
753+
target_lang=None):
714754
"""Link a bunch of stuff together to create an executable or
715755
shared library file.
716756
@@ -748,6 +788,10 @@ def link (self,
748788
of course that they supply command-line arguments for the
749789
particular linker being used).
750790
791+
'target_lang' is the target language for which the given objects
792+
are being compiled. This allows specific linkage time treatment of
793+
certain languages.
794+
751795
Raises LinkError on failure.
752796
"""
753797
raise NotImplementedError
@@ -766,13 +810,14 @@ def link_shared_lib (self,
766810
debug=0,
767811
extra_preargs=None,
768812
extra_postargs=None,
769-
build_temp=None):
813+
build_temp=None,
814+
target_lang=None):
770815
self.link(CCompiler.SHARED_LIBRARY, objects,
771816
self.library_filename(output_libname, lib_type='shared'),
772817
output_dir,
773818
libraries, library_dirs, runtime_library_dirs,
774819
export_symbols, debug,
775-
extra_preargs, extra_postargs, build_temp)
820+
extra_preargs, extra_postargs, build_temp, target_lang)
776821

777822

778823
def link_shared_object (self,
@@ -786,12 +831,13 @@ def link_shared_object (self,
786831
debug=0,
787832
extra_preargs=None,
788833
extra_postargs=None,
789-
build_temp=None):
834+
build_temp=None,
835+
target_lang=None):
790836
self.link(CCompiler.SHARED_OBJECT, objects,
791837
output_filename, output_dir,
792838
libraries, library_dirs, runtime_library_dirs,
793839
export_symbols, debug,
794-
extra_preargs, extra_postargs, build_temp)
840+
extra_preargs, extra_postargs, build_temp, target_lang)
795841

796842

797843
def link_executable (self,
@@ -803,11 +849,12 @@ def link_executable (self,
803849
runtime_library_dirs=None,
804850
debug=0,
805851
extra_preargs=None,
806-
extra_postargs=None):
852+
extra_postargs=None,
853+
target_lang=None):
807854
self.link(CCompiler.EXECUTABLE, objects,
808855
self.executable_filename(output_progname), output_dir,
809856
libraries, library_dirs, runtime_library_dirs, None,
810-
debug, extra_preargs, extra_postargs, None)
857+
debug, extra_preargs, extra_postargs, None, target_lang)
811858

812859

813860
# -- Miscellaneous methods -----------------------------------------

Lib/distutils/command/build_ext.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,9 @@ def build_extension(self, ext):
477477
objects.extend(ext.extra_objects)
478478
extra_args = ext.extra_link_args or []
479479

480+
# Detect target language, if not provided
481+
language = ext.language or self.compiler.detect_language(sources)
482+
480483
self.compiler.link_shared_object(
481484
objects, ext_filename,
482485
libraries=self.get_libraries(ext),
@@ -485,7 +488,8 @@ def build_extension(self, ext):
485488
extra_postargs=extra_args,
486489
export_symbols=self.get_export_symbols(ext),
487490
debug=self.debug,
488-
build_temp=self.build_temp)
491+
build_temp=self.build_temp,
492+
target_lang=language)
489493

490494

491495
def swig_sources (self, sources):

Lib/distutils/command/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ def _link (self, body,
148148
prog = os.path.splitext(os.path.basename(src))[0]
149149
self.compiler.link_executable([obj], prog,
150150
libraries=libraries,
151-
library_dirs=library_dirs)
151+
library_dirs=library_dirs,
152+
target_lang=lang)
152153

153154
prog = prog + self.compiler.exe_extension
154155
self.temp_files.append(prog)

Lib/distutils/cygwinccompiler.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ def link (self,
140140
debug=0,
141141
extra_preargs=None,
142142
extra_postargs=None,
143-
build_temp=None):
143+
build_temp=None,
144+
target_lang=None):
144145

145146
# use separate copies, so we can modify the lists
146147
extra_preargs = copy.copy(extra_preargs or [])
@@ -218,7 +219,8 @@ def link (self,
218219
debug,
219220
extra_preargs,
220221
extra_postargs,
221-
build_temp)
222+
build_temp,
223+
target_lang)
222224

223225
# link ()
224226

Lib/distutils/emxccompiler.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ def link (self,
102102
debug=0,
103103
extra_preargs=None,
104104
extra_postargs=None,
105-
build_temp=None):
105+
build_temp=None,
106+
target_lang=None):
106107

107108
# use separate copies, so we can modify the lists
108109
extra_preargs = copy.copy(extra_preargs or [])
@@ -171,7 +172,8 @@ def link (self,
171172
debug,
172173
extra_preargs,
173174
extra_postargs,
174-
build_temp)
175+
build_temp,
176+
target_lang)
175177

176178
# link ()
177179

Lib/distutils/extension.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ class Extension:
7575
extension_name.
7676
depends : [string]
7777
list of files that the extension depends on
78+
language : string
79+
extension language (i.e. "c", "c++", "objc"). Will be detected
80+
from the source extensions if not provided.
7881
"""
7982

8083
def __init__ (self, name, sources,
@@ -89,6 +92,7 @@ def __init__ (self, name, sources,
8992
extra_link_args=None,
9093
export_symbols=None,
9194
depends=None,
95+
language=None,
9296
):
9397

9498
assert type(name) is StringType, "'name' must be a string"
@@ -109,6 +113,7 @@ def __init__ (self, name, sources,
109113
self.extra_link_args = extra_link_args or []
110114
self.export_symbols = export_symbols or []
111115
self.depends = depends or []
116+
self.language = language
112117

113118
# class Extension
114119

Lib/distutils/msvccompiler.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -367,8 +367,7 @@ def create_static_lib (self,
367367
output_libname,
368368
output_dir=None,
369369
debug=0,
370-
extra_preargs=None,
371-
extra_postargs=None):
370+
target_lang=None):
372371

373372
(objects, output_dir) = self._fix_object_args (objects, output_dir)
374373
output_filename = \
@@ -378,10 +377,6 @@ def create_static_lib (self,
378377
lib_args = objects + ['/OUT:' + output_filename]
379378
if debug:
380379
pass # XXX what goes here?
381-
if extra_preargs:
382-
lib_args[:0] = extra_preargs
383-
if extra_postargs:
384-
lib_args.extend (extra_postargs)
385380
try:
386381
self.spawn ([self.lib] + lib_args)
387382
except DistutilsExecError, msg:
@@ -404,7 +399,8 @@ def link (self,
404399
debug=0,
405400
extra_preargs=None,
406401
extra_postargs=None,
407-
build_temp=None):
402+
build_temp=None,
403+
target_lang=None):
408404

409405
(objects, output_dir) = self._fix_object_args (objects, output_dir)
410406
(libraries, library_dirs, runtime_library_dirs) = \

Lib/distutils/mwerkscompiler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ def link (self,
8484
debug=0,
8585
extra_preargs=None,
8686
extra_postargs=None,
87-
build_temp=None):
87+
build_temp=None,
88+
target_lang=None):
8889
# First fixup.
8990
(objects, output_dir) = self._fix_object_args (objects, output_dir)
9091
(libraries, library_dirs, runtime_library_dirs) = \

Lib/distutils/sysconfig.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,13 @@ def customize_compiler(compiler):
139139
varies across Unices and is stored in Python's Makefile.
140140
"""
141141
if compiler.compiler_type == "unix":
142-
(cc, opt, ccshared, ldshared, so_ext) = \
143-
get_config_vars('CC', 'OPT', 'CCSHARED', 'LDSHARED', 'SO')
142+
(cc, cxx, opt, ccshared, ldshared, so_ext) = \
143+
get_config_vars('CC', 'CXX', 'OPT', 'CCSHARED', 'LDSHARED', 'SO')
144144

145145
if os.environ.has_key('CC'):
146146
cc = os.environ['CC']
147+
if os.environ.has_key('CXX'):
148+
cxx = os.environ['CXX']
147149
if os.environ.has_key('CPP'):
148150
cpp = os.environ['CPP']
149151
else:
@@ -163,6 +165,7 @@ def customize_compiler(compiler):
163165
preprocessor=cpp,
164166
compiler=cc_cmd,
165167
compiler_so=cc_cmd + ' ' + ccshared,
168+
compiler_cxx=cxx,
166169
linker_so=ldshared,
167170
linker_exe=cc)
168171

Lib/distutils/unixccompiler.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class UnixCCompiler(CCompiler):
5757
executables = {'preprocessor' : None,
5858
'compiler' : ["cc"],
5959
'compiler_so' : ["cc"],
60+
'compiler_cxx' : ["cc"],
6061
'linker_so' : ["cc", "-shared"],
6162
'linker_exe' : ["cc"],
6263
'archiver' : ["ar", "-cr"],
@@ -114,7 +115,7 @@ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
114115
raise CompileError, msg
115116

116117
def create_static_lib(self, objects, output_libname,
117-
output_dir=None, debug=0):
118+
output_dir=None, debug=0, target_lang=None):
118119
objects, output_dir = self._fix_object_args(objects, output_dir)
119120

120121
output_filename = \
@@ -143,7 +144,7 @@ def link(self, target_desc, objects,
143144
output_filename, output_dir=None, libraries=None,
144145
library_dirs=None, runtime_library_dirs=None,
145146
export_symbols=None, debug=0, extra_preargs=None,
146-
extra_postargs=None, build_temp=None):
147+
extra_postargs=None, build_temp=None, target_lang=None):
147148
objects, output_dir = self._fix_object_args(objects, output_dir)
148149
libraries, library_dirs, runtime_library_dirs = \
149150
self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
@@ -167,9 +168,12 @@ def link(self, target_desc, objects,
167168
self.mkpath(os.path.dirname(output_filename))
168169
try:
169170
if target_desc == CCompiler.EXECUTABLE:
170-
self.spawn(self.linker_exe + ld_args)
171+
linker = self.linker_exe[:]
171172
else:
172-
self.spawn(self.linker_so + ld_args)
173+
linker = self.linker_so[:]
174+
if target_lang == "c++" and self.compiler_cxx:
175+
linker[0] = self.compiler_cxx[0]
176+
self.spawn(linker + ld_args)
173177
except DistutilsExecError, msg:
174178
raise LinkError, msg
175179
else:

0 commit comments

Comments
 (0)