• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# gh-91321: Build a basic C test extension to check that the Python C API is
2# compatible with C and does not emit C compiler warnings.
3import os
4import platform
5import shlex
6import sys
7import sysconfig
8from test import support
9
10from setuptools import setup, Extension
11
12
13SOURCE = 'extension.c'
14if not support.MS_WINDOWS:
15    # C compiler flags for GCC and clang
16    CFLAGS = [
17        # The purpose of test_cext extension is to check that building a C
18        # extension using the Python C API does not emit C compiler warnings.
19        '-Werror',
20    ]
21    if not support.Py_GIL_DISABLED:
22        CFLAGS.append(
23            # gh-116869: The Python C API must be compatible with building
24            # with the -Werror=declaration-after-statement compiler flag.
25            '-Werror=declaration-after-statement',
26        )
27else:
28    # Don't pass any compiler flag to MSVC
29    CFLAGS = []
30
31
32def main():
33    std = os.environ.get("CPYTHON_TEST_STD", "")
34    module_name = os.environ["CPYTHON_TEST_EXT_NAME"]
35    limited = bool(os.environ.get("CPYTHON_TEST_LIMITED", ""))
36
37    cflags = list(CFLAGS)
38    cflags.append(f'-DMODULE_NAME={module_name}')
39
40    # Add -std=STD or /std:STD (MSVC) compiler flag
41    if std:
42        if support.MS_WINDOWS:
43            cflags.append(f'/std:{std}')
44        else:
45            cflags.append(f'-std={std}')
46
47    # Remove existing -std or /std options from CC command line.
48    # Python adds -std=c11 option.
49    cmd = (sysconfig.get_config_var('CC') or '')
50    if cmd is not None:
51        if support.MS_WINDOWS:
52            std_prefix = '/std'
53        else:
54            std_prefix = '-std'
55        cmd = shlex.split(cmd)
56        cmd = [arg for arg in cmd if not arg.startswith(std_prefix)]
57        cmd = shlex.join(cmd)
58        # CC env var overrides sysconfig CC variable in setuptools
59        os.environ['CC'] = cmd
60
61    # Define Py_LIMITED_API macro
62    if limited:
63        version = sys.hexversion
64        cflags.append(f'-DPy_LIMITED_API={version:#x}')
65
66    # On Windows, add PCbuild\amd64\ to include and library directories
67    include_dirs = []
68    library_dirs = []
69    if support.MS_WINDOWS:
70        srcdir = sysconfig.get_config_var('srcdir')
71        machine = platform.uname().machine
72        pcbuild = os.path.join(srcdir, 'PCbuild', machine)
73        if os.path.exists(pcbuild):
74            # pyconfig.h is generated in PCbuild\amd64\
75            include_dirs.append(pcbuild)
76            # python313.lib is generated in PCbuild\amd64\
77            library_dirs.append(pcbuild)
78            print(f"Add PCbuild directory: {pcbuild}")
79
80    # Display information to help debugging
81    for env_name in ('CC', 'CFLAGS'):
82        if env_name in os.environ:
83            print(f"{env_name} env var: {os.environ[env_name]!r}")
84        else:
85            print(f"{env_name} env var: <missing>")
86    print(f"extra_compile_args: {cflags!r}")
87
88    ext = Extension(
89        module_name,
90        sources=[SOURCE],
91        extra_compile_args=cflags,
92        include_dirs=include_dirs,
93        library_dirs=library_dirs)
94    setup(name=f'internal_{module_name}',
95          version='0.0',
96          ext_modules=[ext])
97
98
99if __name__ == "__main__":
100    main()
101