From 99317f52c8e51d1c27705206ff64ed7a560013f8 Mon Sep 17 00:00:00 2001 From: Mike Gilbert Date: Fri, 5 Jan 2018 13:34:21 -0500 Subject: Improve distutils C++ support https://bugs.python.org/issue1222585 --- Lib/_osx_support.py | 6 ++-- Lib/distutils/cygwinccompiler.py | 21 ++++++++++-- Lib/distutils/sysconfig.py | 25 ++++++++++++--- Lib/distutils/tests/test_sysconfig.py | 16 ++++++---- Lib/distutils/unixccompiler.py | 60 ++++++++++++++++------------------- Makefile.pre.in | 4 +-- 6 files changed, 80 insertions(+), 52 deletions(-) diff --git a/Lib/_osx_support.py b/Lib/_osx_support.py index aa66c8b9f41..764f7ae3af9 100644 --- a/Lib/_osx_support.py +++ b/Lib/_osx_support.py @@ -14,13 +14,13 @@ # configuration variables that may contain universal build flags, # like "-arch" or "-isdkroot", that may need customization for # the user environment -_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', - 'BLDSHARED', 'LDSHARED', 'CC', 'CXX', +_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'CXXFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS', + 'BLDSHARED', 'LDSHARED', 'LDCXXSHARED', 'CC', 'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS', 'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS') # configuration variables that may contain compiler calls -_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX') +_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'LDCXXSHARED', 'CC', 'CXX') # prefix added to original configuration variable names _INITPRE = '_OSX_SUPPORT_INITIAL_' diff --git a/Lib/distutils/cygwinccompiler.py b/Lib/distutils/cygwinccompiler.py index 66c12dd3583..dddb9fd2d4a 100644 --- a/Lib/distutils/cygwinccompiler.py +++ b/Lib/distutils/cygwinccompiler.py @@ -123,8 +123,10 @@ def __init__(self, verbose=0, dry_run=0, force=0): # dllwrap 2.10.90 is buggy if self.ld_version >= "2.10.90": self.linker_dll = "gcc" + self.linker_dll_cxx = "g++" else: self.linker_dll = "dllwrap" + self.linker_dll_cxx = "dllwrap" # ld_version >= "2.13" support -shared so use it instead of # -mdll -static @@ -138,9 +140,13 @@ def __init__(self, verbose=0, dry_run=0, force=0): self.set_executables(compiler='gcc -mcygwin -O -Wall', compiler_so='gcc -mcygwin -mdll -O -Wall', compiler_cxx='g++ -mcygwin -O -Wall', + compiler_so_cxx='g++ -mcygwin -mdll -O -Wall', linker_exe='gcc -mcygwin', linker_so=('%s -mcygwin %s' % - (self.linker_dll, shared_option))) + (self.linker_dll, shared_option)), + linker_exe_cxx='g++ -mcygwin', + linker_so_cxx=('%s -mcygwin %s' % + (self.linker_dll_cxx, shared_option))) # cygwin and mingw32 need different sets of libraries if self.gcc_version == "2.91.57": @@ -164,8 +170,12 @@ def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): raise CompileError(msg) else: # for other files use the C-compiler try: - self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + - extra_postargs) + if self.detect_language(src) == 'c++': + self.spawn(self.compiler_so_cxx + cc_args + [src, '-o', obj] + + extra_postargs) + else: + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + + extra_postargs) except DistutilsExecError as msg: raise CompileError(msg) @@ -300,9 +310,14 @@ def __init__(self, verbose=0, dry_run=0, force=0): self.set_executables(compiler='gcc -O -Wall', compiler_so='gcc -mdll -O -Wall', compiler_cxx='g++ -O -Wall', + compiler_so_cxx='g++ -mdll -O -Wall', linker_exe='gcc', linker_so='%s %s %s' % (self.linker_dll, shared_option, + entry_point), + linker_exe_cxx='g++', + linker_so_cxx='%s %s %s' + % (self.linker_dll_cxx, shared_option, entry_point)) # Maybe we should also append -mthreads, but then the finished # dlls need another dll (mingwm10.dll see Mingw32 docs) diff --git a/Lib/distutils/sysconfig.py b/Lib/distutils/sysconfig.py index 3414a761e76..bac437c4113 100644 --- a/Lib/distutils/sysconfig.py +++ b/Lib/distutils/sysconfig.py @@ -216,9 +216,12 @@ def customize_compiler(compiler): _osx_support.customize_compiler(_config_vars) _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' - (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \ - get_config_vars('CC', 'CXX', 'CFLAGS', - 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS') + (cc, cxx, ccshared, ldshared, ldcxxshared, shlib_suffix, ar, ar_flags) = \ + get_config_vars('CC', 'CXX', 'CCSHARED', 'LDSHARED', 'LDCXXSHARED', + 'SHLIB_SUFFIX', 'AR', 'ARFLAGS') + + cflags = '' + cxxflags = '' if 'CC' in os.environ: newcc = os.environ['CC'] @@ -233,19 +236,27 @@ def customize_compiler(compiler): cxx = os.environ['CXX'] if 'LDSHARED' in os.environ: ldshared = os.environ['LDSHARED'] + if 'LDCXXSHARED' in os.environ: + ldcxxshared = os.environ['LDCXXSHARED'] if 'CPP' in os.environ: cpp = os.environ['CPP'] else: cpp = cc + " -E" # not always if 'LDFLAGS' in os.environ: ldshared = ldshared + ' ' + os.environ['LDFLAGS'] + ldcxxshared = ldcxxshared + ' ' + os.environ['LDFLAGS'] if 'CFLAGS' in os.environ: - cflags = cflags + ' ' + os.environ['CFLAGS'] + cflags = os.environ['CFLAGS'] ldshared = ldshared + ' ' + os.environ['CFLAGS'] + if 'CXXFLAGS' in os.environ: + cxxflags = os.environ['CXXFLAGS'] + ldcxxshared = ldcxxshared + ' ' + os.environ['CXXFLAGS'] if 'CPPFLAGS' in os.environ: cpp = cpp + ' ' + os.environ['CPPFLAGS'] cflags = cflags + ' ' + os.environ['CPPFLAGS'] + cxxflags = cxxflags + ' ' + os.environ['CPPFLAGS'] ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] + ldcxxshared = ldcxxshared + ' ' + os.environ['CPPFLAGS'] if 'AR' in os.environ: ar = os.environ['AR'] if 'ARFLAGS' in os.environ: @@ -254,13 +265,17 @@ def customize_compiler(compiler): archiver = ar + ' ' + ar_flags cc_cmd = cc + ' ' + cflags + cxx_cmd = cxx + ' ' + cxxflags compiler.set_executables( preprocessor=cpp, compiler=cc_cmd, compiler_so=cc_cmd + ' ' + ccshared, - compiler_cxx=cxx, + compiler_cxx=cxx_cmd, + compiler_so_cxx=cxx_cmd + ' ' + ccshared, linker_so=ldshared, linker_exe=cc, + linker_so_cxx=ldcxxshared, + linker_exe_cxx=cxx, archiver=archiver) compiler.shared_lib_extension = shlib_suffix diff --git a/Lib/distutils/tests/test_sysconfig.py b/Lib/distutils/tests/test_sysconfig.py index 3697206229d..8a5f3e099e1 100644 --- a/Lib/distutils/tests/test_sysconfig.py +++ b/Lib/distutils/tests/test_sysconfig.py @@ -117,12 +117,13 @@ def test_customize_compiler(self): os.environ['AR'] = 'env_ar' os.environ['CC'] = 'env_cc' os.environ['CPP'] = 'env_cpp' - os.environ['CXX'] = 'env_cxx --env-cxx-flags' + os.environ['CXX'] = 'env_cxx' os.environ['LDSHARED'] = 'env_ldshared' os.environ['LDFLAGS'] = '--env-ldflags' os.environ['ARFLAGS'] = '--env-arflags' os.environ['CFLAGS'] = '--env-cflags' os.environ['CPPFLAGS'] = '--env-cppflags' + os.environ['CXXFLAGS'] = '--env-cxxflags' comp = self.customize_compiler() self.assertEqual(comp.exes['archiver'], @@ -130,12 +131,12 @@ def test_customize_compiler(self): self.assertEqual(comp.exes['preprocessor'], 'env_cpp --env-cppflags') self.assertEqual(comp.exes['compiler'], - 'env_cc --sc-cflags --env-cflags --env-cppflags') + 'env_cc --env-cflags --env-cppflags') self.assertEqual(comp.exes['compiler_so'], - ('env_cc --sc-cflags ' + ('env_cc ' '--env-cflags ''--env-cppflags --sc-ccshared')) self.assertEqual(comp.exes['compiler_cxx'], - 'env_cxx --env-cxx-flags') + 'env_cxx --env-cxxflags --env-cppflags') self.assertEqual(comp.exes['linker_exe'], 'env_cc') self.assertEqual(comp.exes['linker_so'], @@ -152,6 +153,7 @@ def test_customize_compiler(self): del os.environ['ARFLAGS'] del os.environ['CFLAGS'] del os.environ['CPPFLAGS'] + del os.environ['CXXFLAGS'] comp = self.customize_compiler() self.assertEqual(comp.exes['archiver'], @@ -159,11 +161,11 @@ def test_customize_compiler(self): self.assertEqual(comp.exes['preprocessor'], 'sc_cc -E') self.assertEqual(comp.exes['compiler'], - 'sc_cc --sc-cflags') + 'sc_cc ') self.assertEqual(comp.exes['compiler_so'], - 'sc_cc --sc-cflags --sc-ccshared') + 'sc_cc --sc-ccshared') self.assertEqual(comp.exes['compiler_cxx'], - 'sc_cxx') + 'sc_cxx ') self.assertEqual(comp.exes['linker_exe'], 'sc_cc') self.assertEqual(comp.exes['linker_so'], diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py index f0792de74a1..16e7fbea83c 100644 --- a/Lib/distutils/unixccompiler.py +++ b/Lib/distutils/unixccompiler.py @@ -52,14 +52,17 @@ class UnixCCompiler(CCompiler): # are pretty generic; they will probably have to be set by an outsider # (eg. using information discovered by the sysconfig about building # Python extensions). - executables = {'preprocessor' : None, - 'compiler' : ["cc"], - 'compiler_so' : ["cc"], - 'compiler_cxx' : ["cc"], - 'linker_so' : ["cc", "-shared"], - 'linker_exe' : ["cc"], - 'archiver' : ["ar", "-cr"], - 'ranlib' : None, + executables = {'preprocessor' : None, + 'compiler' : ["cc"], + 'compiler_so' : ["cc"], + 'compiler_cxx' : ["c++"], + 'compiler_so_cxx' : ["c++"], + 'linker_so' : ["cc", "-shared"], + 'linker_exe' : ["cc"], + 'linker_so_cxx' : ["c++", "-shared"], + 'linker_exe_cxx' : ["c++"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : None, } if sys.platform[:6] == "darwin": @@ -110,12 +113,19 @@ def preprocess(self, source, output_file=None, macros=None, def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): compiler_so = self.compiler_so + compiler_so_cxx = self.compiler_so_cxx if sys.platform == 'darwin': compiler_so = _osx_support.compiler_fixup(compiler_so, cc_args + extra_postargs) + compiler_so_cxx = _osx_support.compiler_fixup(compiler_so_cxx, + cc_args + extra_postargs) try: - self.spawn(compiler_so + cc_args + [src, '-o', obj] + - extra_postargs) + if self.detect_language(src) == 'c++': + self.spawn(compiler_so_cxx + cc_args + [src, '-o', obj] + + extra_postargs) + else: + self.spawn(compiler_so + cc_args + [src, '-o', obj] + + extra_postargs) except DistutilsExecError as msg: raise CompileError(msg) @@ -173,30 +183,16 @@ def link(self, target_desc, objects, ld_args.extend(extra_postargs) self.mkpath(os.path.dirname(output_filename)) try: - if target_desc == CCompiler.EXECUTABLE: - linker = self.linker_exe[:] + if target_lang == "c++": + if target_desc == CCompiler.EXECUTABLE: + linker = self.linker_exe_cxx[:] + else: + linker = self.linker_so_cxx[:] else: - linker = self.linker_so[:] - if target_lang == "c++" and self.compiler_cxx: - # skip over environment variable settings if /usr/bin/env - # is used to set up the linker's environment. - # This is needed on OSX. Note: this assumes that the - # normal and C++ compiler have the same environment - # settings. - i = 0 - if os.path.basename(linker[0]) == "env": - i = 1 - while '=' in linker[i]: - i += 1 - - if os.path.basename(linker[i]) == 'ld_so_aix': - # AIX platforms prefix the compiler with the ld_so_aix - # script, so we need to adjust our linker index - offset = 1 + if target_desc == CCompiler.EXECUTABLE: + linker = self.linker_exe[:] else: - offset = 0 - - linker[i+offset] = self.compiler_cxx[i] + linker = self.linker_so[:] if sys.platform == 'darwin': linker = _osx_support.compiler_fixup(linker, ld_args) diff --git a/Makefile.pre.in b/Makefile.pre.in index 5564c1bae1c..1c7ef37faf0 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -630,10 +630,10 @@ sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o *\ -s*|s*) quiet="-q";; \ *) quiet="";; \ esac; \ - echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' CFLAGS='$(PY_CFLAGS)' \ _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ - $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' CFLAGS='$(PY_CFLAGS)' \ _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build -- cgit v1.2.3-65-gdbad