Skip to content

Commit fc76caa

Browse files
committed
Merge pull request pypa/distutils#228 from pypa/feature/cpp-support
Distutils C++ support
2 parents 127371a + 8307b56 commit fc76caa

File tree

5 files changed

+91
-35
lines changed

5 files changed

+91
-35
lines changed

distutils/cygwinccompiler.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,18 @@ def __init__(self, verbose=False, dry_run=False, force=False):
9999
self.cxx = os.environ.get('CXX', 'g++')
100100

101101
self.linker_dll = self.cc
102+
self.linker_dll_cxx = self.cxx
102103
shared_option = "-shared"
103104

104105
self.set_executables(
105106
compiler=f'{self.cc} -mcygwin -O -Wall',
106107
compiler_so=f'{self.cc} -mcygwin -mdll -O -Wall',
107108
compiler_cxx=f'{self.cxx} -mcygwin -O -Wall',
109+
compiler_so_cxx=f'{self.cxx} -mcygwin -mdll -O -Wall',
108110
linker_exe=f'{self.cc} -mcygwin',
109-
linker_so=(f'{self.linker_dll} -mcygwin {shared_option}'),
111+
linker_so=f'{self.linker_dll} -mcygwin {shared_option}',
112+
linker_exe_cxx=f'{self.cxx} -mcygwin',
113+
linker_so_cxx=f'{self.linker_dll_cxx} -mcygwin {shared_option}',
110114
)
111115

112116
# Include the appropriate MSVC runtime library if Python was built
@@ -138,9 +142,17 @@ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
138142
raise CompileError(msg)
139143
else: # for other files use the C-compiler
140144
try:
141-
self.spawn(
142-
self.compiler_so + cc_args + [src, '-o', obj] + extra_postargs
143-
)
145+
if self.detect_language(src) == 'c++':
146+
self.spawn(
147+
self.compiler_so_cxx
148+
+ cc_args
149+
+ [src, '-o', obj]
150+
+ extra_postargs
151+
)
152+
else:
153+
self.spawn(
154+
self.compiler_so + cc_args + [src, '-o', obj] + extra_postargs
155+
)
144156
except DistutilsExecError as msg:
145157
raise CompileError(msg)
146158

@@ -276,9 +288,12 @@ def __init__(self, verbose=False, dry_run=False, force=False):
276288
self.set_executables(
277289
compiler=f'{self.cc} -O -Wall',
278290
compiler_so=f'{self.cc} -shared -O -Wall',
291+
compiler_so_cxx=f'{self.cxx} -shared -O -Wall',
279292
compiler_cxx=f'{self.cxx} -O -Wall',
280293
linker_exe=f'{self.cc}',
281294
linker_so=f'{self.linker_dll} {shared_option}',
295+
linker_exe_cxx=f'{self.cxx}',
296+
linker_so_cxx=f'{self.linker_dll_cxx} {shared_option}',
282297
)
283298

284299
def runtime_library_dir_option(self, dir):

distutils/sysconfig.py

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ def _customize_macos():
287287
)
288288

289289

290-
def customize_compiler(compiler): # noqa: C901
290+
def customize_compiler(compiler):
291291
"""Do any platform-specific customization of a CCompiler instance.
292292
293293
Mainly needed on Unix, so we can plug in the information that
@@ -304,6 +304,7 @@ def customize_compiler(compiler): # noqa: C901
304304
cflags,
305305
ccshared,
306306
ldshared,
307+
ldcxxshared,
307308
shlib_suffix,
308309
ar,
309310
ar_flags,
@@ -313,50 +314,57 @@ def customize_compiler(compiler): # noqa: C901
313314
'CFLAGS',
314315
'CCSHARED',
315316
'LDSHARED',
317+
'LDCXXSHARED',
316318
'SHLIB_SUFFIX',
317319
'AR',
318320
'ARFLAGS',
319321
)
320322

323+
cxxflags = cflags
324+
321325
if 'CC' in os.environ:
322326
newcc = os.environ['CC']
323327
if 'LDSHARED' not in os.environ and ldshared.startswith(cc):
324328
# If CC is overridden, use that as the default
325329
# command for LDSHARED as well
326330
ldshared = newcc + ldshared[len(cc) :]
327331
cc = newcc
328-
if 'CXX' in os.environ:
329-
cxx = os.environ['CXX']
330-
if 'LDSHARED' in os.environ:
331-
ldshared = os.environ['LDSHARED']
332-
if 'CPP' in os.environ:
333-
cpp = os.environ['CPP']
334-
else:
335-
cpp = cc + " -E" # not always
336-
if 'LDFLAGS' in os.environ:
337-
ldshared = ldshared + ' ' + os.environ['LDFLAGS']
338-
if 'CFLAGS' in os.environ:
339-
cflags = cflags + ' ' + os.environ['CFLAGS']
340-
ldshared = ldshared + ' ' + os.environ['CFLAGS']
341-
if 'CPPFLAGS' in os.environ:
342-
cpp = cpp + ' ' + os.environ['CPPFLAGS']
343-
cflags = cflags + ' ' + os.environ['CPPFLAGS']
344-
ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
345-
if 'AR' in os.environ:
346-
ar = os.environ['AR']
347-
if 'ARFLAGS' in os.environ:
348-
archiver = ar + ' ' + os.environ['ARFLAGS']
349-
else:
350-
archiver = ar + ' ' + ar_flags
332+
cxx = os.environ.get('CXX', cxx)
333+
ldshared = os.environ.get('LDSHARED', ldshared)
334+
ldcxxshared = os.environ.get('LDCXXSHARED', ldcxxshared)
335+
cpp = os.environ.get(
336+
'CPP',
337+
cc + " -E", # not always
338+
)
351339

340+
ldshared = _add_flags(ldshared, 'LD')
341+
ldcxxshared = _add_flags(ldcxxshared, 'LD')
342+
cflags = _add_flags(cflags, 'C')
343+
ldshared = _add_flags(ldshared, 'C')
344+
cxxflags = os.environ.get('CXXFLAGS', cxxflags)
345+
ldcxxshared = _add_flags(ldcxxshared, 'CXX')
346+
cpp = _add_flags(cpp, 'CPP')
347+
cflags = _add_flags(cflags, 'CPP')
348+
cxxflags = _add_flags(cxxflags, 'CPP')
349+
ldshared = _add_flags(ldshared, 'CPP')
350+
ldcxxshared = _add_flags(ldcxxshared, 'CPP')
351+
352+
ar = os.environ.get('AR', ar)
353+
354+
archiver = ar + ' ' + os.environ.get('ARFLAGS', ar_flags)
352355
cc_cmd = cc + ' ' + cflags
356+
cxx_cmd = cxx + ' ' + cxxflags
357+
353358
compiler.set_executables(
354359
preprocessor=cpp,
355360
compiler=cc_cmd,
356361
compiler_so=cc_cmd + ' ' + ccshared,
357-
compiler_cxx=cxx,
362+
compiler_cxx=cxx_cmd,
363+
compiler_so_cxx=cxx_cmd + ' ' + ccshared,
358364
linker_so=ldshared,
365+
linker_so_cxx=ldcxxshared,
359366
linker_exe=cc,
367+
linker_exe_cxx=cxx,
360368
archiver=archiver,
361369
)
362370

@@ -561,3 +569,14 @@ def get_config_var(name):
561569

562570
warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2)
563571
return get_config_vars().get(name)
572+
573+
574+
@pass_none
575+
def _add_flags(value: str, type: str) -> str:
576+
"""
577+
Add any flags from the environment for the given type.
578+
579+
type is the prefix to FLAGS in the environment key (e.g. "C" for "CFLAGS").
580+
"""
581+
flags = os.environ.get(f'{type}FLAGS')
582+
return f'{value} {flags}' if flags else value

distutils/tests/test_sysconfig.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,10 @@ def test_customize_compiler(self):
134134
assert comp.exes['compiler_so'] == (
135135
'env_cc --sc-cflags --env-cflags --env-cppflags --sc-ccshared'
136136
)
137-
assert comp.exes['compiler_cxx'] == 'env_cxx --env-cxx-flags'
137+
assert (
138+
comp.exes['compiler_cxx']
139+
== 'env_cxx --env-cxx-flags --sc-cflags --env-cppflags'
140+
)
138141
assert comp.exes['linker_exe'] == 'env_cc'
139142
assert comp.exes['linker_so'] == (
140143
'env_ldshared --env-ldflags --env-cflags --env-cppflags'
@@ -162,7 +165,7 @@ def test_customize_compiler(self):
162165
assert comp.exes['preprocessor'] == 'sc_cc -E'
163166
assert comp.exes['compiler'] == 'sc_cc --sc-cflags'
164167
assert comp.exes['compiler_so'] == 'sc_cc --sc-cflags --sc-ccshared'
165-
assert comp.exes['compiler_cxx'] == 'sc_cxx'
168+
assert comp.exes['compiler_cxx'] == 'sc_cxx --sc-cflags'
166169
assert comp.exes['linker_exe'] == 'sc_cc'
167170
assert comp.exes['linker_so'] == 'sc_ldshared'
168171
assert comp.shared_lib_extension == 'sc_shutil_suffix'

distutils/tests/test_unixccompiler.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,13 @@ def test_cc_overrides_ldshared_for_cxx_correctly(self):
257257
def gcv(v):
258258
if v == 'LDSHARED':
259259
return 'gcc-4.2 -bundle -undefined dynamic_lookup '
260+
elif v == 'LDCXXSHARED':
261+
return 'g++-4.2 -bundle -undefined dynamic_lookup '
260262
elif v == 'CXX':
261263
return 'g++-4.2'
262-
return 'gcc-4.2'
264+
elif v == 'CC':
265+
return 'gcc-4.2'
266+
return ''
263267

264268
def gcvs(*args, _orig=sysconfig.get_config_vars):
265269
if args:

distutils/unixccompiler.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,12 @@ class UnixCCompiler(CCompiler):
118118
'preprocessor': None,
119119
'compiler': ["cc"],
120120
'compiler_so': ["cc"],
121-
'compiler_cxx': ["cc"],
121+
'compiler_cxx': ["c++"],
122+
'compiler_so_cxx': ["c++"],
122123
'linker_so': ["cc", "-shared"],
124+
'linker_so_cxx': ["c++", "-shared"],
123125
'linker_exe': ["cc"],
126+
'linker_exe_cxx': ["c++", "-shared"],
124127
'archiver': ["ar", "-cr"],
125128
'ranlib': None,
126129
}
@@ -187,8 +190,14 @@ def preprocess(
187190

188191
def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
189192
compiler_so = compiler_fixup(self.compiler_so, cc_args + extra_postargs)
193+
compiler_so_cxx = compiler_fixup(self.compiler_so_cxx, cc_args + extra_postargs)
190194
try:
191-
self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)
195+
if self.detect_language(src) == 'c++':
196+
self.spawn(
197+
compiler_so_cxx + cc_args + [src, '-o', obj] + extra_postargs
198+
)
199+
else:
200+
self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)
192201
except DistutilsExecError as msg:
193202
raise CompileError(msg)
194203

@@ -256,7 +265,13 @@ def link(
256265
# building an executable or linker_so (with shared options)
257266
# when building a shared library.
258267
building_exe = target_desc == CCompiler.EXECUTABLE
259-
linker = (self.linker_exe if building_exe else self.linker_so)[:]
268+
linker = (
269+
self.linker_exe
270+
if building_exe
271+
else (
272+
self.linker_so_cxx if target_lang == "c++" else self.linker_so
273+
)
274+
)[:]
260275

261276
if target_lang == "c++" and self.compiler_cxx:
262277
env, linker_ne = _split_env(linker)

0 commit comments

Comments
 (0)