@@ -1,91 +1,73 @@
11# gh-91321: Build a basic C++ test extension to check that the Python C API is
22# compatible with C++ and does not emit C++ compiler warnings.
3-importcontextlib
4-importos
3+importos.path
54importsys
65importunittest
7-importwarnings
6+importsubprocess
87fromtestimportsupport
98fromtest.supportimportos_helper
10911-withwarnings.catch_warnings():
12-warnings.simplefilter('ignore', DeprecationWarning)
13-fromdistutils.coreimportsetup, Extension
14-importdistutils.sysconfig
15-16101711MS_WINDOWS= (sys.platform=='win32')
1812191320-SOURCE=support.findfile('_testcppext.cpp')
21-ifnotMS_WINDOWS:
22-# C++ compiler flags for GCC and clang
23-CPPFLAGS= [
24-# Python currently targets C++11
25-'-std=c++11',
26-# gh-91321: The purpose of _testcppext extension is to check that building
27-# a C++ extension using the Python C API does not emit C++ compiler
28-# warnings
29-'-Werror',
30-# Warn on old-style cast (C cast) like: (PyObject*)op
31-'-Wold-style-cast',
32-# Warn when using NULL rather than _Py_NULL in static inline functions
33-'-Wzero-as-null-pointer-constant',
34- ]
35-else:
36-# Don't pass any compiler flag to MSVC
37-CPPFLAGS= []
14+SETUP_TESTCPPEXT=support.findfile('setup_testcppext.py')
[email protected]_subprocess()
4118classTestCPPExt(unittest.TestCase):
42-defbuild(self):
43-cpp_ext=Extension(
44-'_testcppext',
45-sources=[SOURCE],
46-language='c++',
47-extra_compile_args=CPPFLAGS)
48-capture_stdout= (notsupport.verbose)
19+deftest_build_cpp11(self):
20+self.check_build(False)
492150-try:
51-try:
52-ifcapture_stdout:
53-stdout=support.captured_stdout()
54-else:
55-print()
56-stdout=contextlib.nullcontext()
57-with (stdout,
58-support.swap_attr(sys, 'argv', ['setup.py', 'build_ext', '--verbose'])):
59-setup(name="_testcppext", ext_modules=[cpp_ext])
60-return
61-except:
62-ifcapture_stdout:
63-# Show output on error
64-print()
65-print(stdout.getvalue())
66-raise
67-exceptSystemExit:
68-self.fail("Build failed")
22+deftest_build_cpp03(self):
23+self.check_build(True)
69247025# With MSVC, the linker fails with: cannot open file 'python311.lib'
7126# https://github.com/python/cpython/pull/32175#issuecomment-1111175897
[email protected](MS_WINDOWS, 'test fails on Windows')
73-deftest_build(self):
74-# save/restore os.environ
75-defrestore_env(old_env):
76-os.environ.clear()
77-os.environ.update(old_env)
78-self.addCleanup(restore_env, dict(os.environ))
79-80-defrestore_sysconfig_vars(old_config_vars):
81-distutils.sysconfig._config_vars.clear()
82-distutils.sysconfig._config_vars.update(old_config_vars)
83-self.addCleanup(restore_sysconfig_vars,
84-dict(distutils.sysconfig._config_vars))
85-28+# the test uses venv+pip: skip if it's not available
[email protected]_venv_with_pip()
30+defcheck_build(self, std_cpp03):
8631# Build in a temporary directory
8732withos_helper.temp_cwd():
88-self.build()
33+self._check_build(std_cpp03)
34+35+def_check_build(self, std_cpp03):
36+venv_dir='env'
37+verbose=support.verbose
38+39+# Create virtual environment to get setuptools
40+cmd= [sys.executable, '-X', 'dev', '-m', 'venv', venv_dir]
41+ifverbose:
42+print()
43+print('Run:', ' '.join(cmd))
44+subprocess.run(cmd, check=True)
45+46+# Get the Python executable of the venv
47+python_exe='python'
48+ifsys.executable.endswith('.exe'):
49+python_exe+='.exe'
50+ifMS_WINDOWS:
51+python=os.path.join(venv_dir, 'Scripts', python_exe)
52+else:
53+python=os.path.join(venv_dir, 'bin', python_exe)
54+55+# Build the C++ extension
56+cmd= [python, '-X', 'dev',
57+SETUP_TESTCPPEXT, 'build_ext', '--verbose']
58+ifstd_cpp03:
59+cmd.append('-std=c++03')
60+ifverbose:
61+print('Run:', ' '.join(cmd))
62+subprocess.run(cmd, check=True)
63+else:
64+proc=subprocess.run(cmd,
65+stdout=subprocess.PIPE,
66+stderr=subprocess.STDOUT,
67+text=True)
68+ifproc.returncode:
69+print(proc.stdout, end='')
70+self.fail(f"Build failed with exit code {proc.returncode}")
897190729173if__name__=="__main__":