diff --git a/README.md b/README.md index fd184ba5..e3382c29 100644 --- a/README.md +++ b/README.md @@ -24,22 +24,20 @@ What does it do? | | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | manylinux x86_64 | manylinux i686 | manylinux aarch64 | manylinux ppc64le | manylinux s390x | |---|---|---|---|---|---|---|---|---|---| -| CPython 2.7 | ✅ | | ✅¹ | ✅¹ | ✅ | ✅ | | | | | CPython 3.6 | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | CPython 3.7 | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | CPython 3.8 | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| PyPy 2.7 v7.3.3 | ✅ | | | ✅ | ✅ | | | | | | PyPy 3.6 v7.3.3 | ✅ | | | ✅ | ✅ | | | | | | PyPy 3.7 (beta) v7.3.3 | ✅ | | | ✅ | ✅ | | | | | -¹ Only using a workaround with a newer compiler; Microsoft removed the 2008 compiler for Python 2.7 in April 2021.
- - Builds manylinux, macOS 10.9+, and Windows wheels for CPython and PyPy - Works on GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, and GitLab CI - Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate) - Runs your library's tests against the wheel-installed version of your library +See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.x/) if you need to build unsupported versions of Python, such as Python 2. + Usage ----- @@ -98,7 +96,7 @@ jobs: path: ./wheelhouse/*.whl ``` -For more information, including building on Python 2, PyPI deployment, and the use of other CI services or the dedicated GitHub Action, check out the [documentation](https://cibuildwheel.readthedocs.org) and the [examples](https://github.com/joerick/cibuildwheel/tree/master/examples). +For more information, including PyPI deployment, and the use of other CI services or the dedicated GitHub Action, check out the [documentation](https://cibuildwheel.readthedocs.org) and the [examples](https://github.com/joerick/cibuildwheel/tree/master/examples). Options ------- diff --git a/bin/update_dependencies.py b/bin/update_dependencies.py index 975d3a8c..7e3d60c5 100755 --- a/bin/update_dependencies.py +++ b/bin/update_dependencies.py @@ -17,7 +17,7 @@ os.chdir("..") # regenerate the constraints files os.environ["CUSTOM_COMPILE_COMMAND"] = "bin/update_dependencies.py" -PYTHON_VERSIONS = ["27", "36", "37", "38", "39"] +PYTHON_VERSIONS = ["36", "37", "38", "39"] if "--no-docker" in sys.argv: for python_version in PYTHON_VERSIONS: @@ -32,8 +32,7 @@ if "--no-docker" in sys.argv: check=True, ) else: - # latest manylinux2010 image with cpython 2.7 support - image_runner = "quay.io/pypa/manylinux2010_x86_64:2021-02-06-3d322a5" + image_runner = "quay.io/pypa/manylinux2010_x86_64:latest" subprocess.run(["docker", "pull", image_runner], check=True) for python_version in PYTHON_VERSIONS: abi_flags = "" if int(python_version) >= 38 else "m" @@ -77,9 +76,9 @@ class Image(NamedTuple): images = [ Image("manylinux1", "x86_64", "quay.io/pypa/manylinux1_x86_64", None), Image("manylinux1", "i686", "quay.io/pypa/manylinux1_i686", None), - # Images for manylinux2010 are pinned to the latest tag supporting cp27 - Image("manylinux2010", "x86_64", "quay.io/pypa/manylinux2010_x86_64", "2021-02-06-3d322a5"), - Image("manylinux2010", "i686", "quay.io/pypa/manylinux2010_i686", "2021-02-06-3d322a5"), + # 2010 images + Image("manylinux2010", "x86_64", "quay.io/pypa/manylinux2010_x86_64", None), + Image("manylinux2010", "i686", "quay.io/pypa/manylinux2010_i686", None), Image("manylinux2010", "pypy_x86_64", "pypywheels/manylinux2010-pypy_x86_64", None), # 2014 images Image("manylinux2014", "x86_64", "quay.io/pypa/manylinux2014_x86_64", None), diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index 9aa99ff5..c230d8cf 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -124,8 +124,7 @@ def build(options: BuildOptions) -> None: dependency_constraint_flags: List[PathOrStr] = [] if config.identifier.startswith("pp"): # Patch PyPy to make sure headers get installed into a venv - patch_version = "_27" if config.version == "2.7" else "" - patch_path = resources_dir / f"pypy_venv{patch_version}.patch" + patch_path = resources_dir / "pypy_venv.patch" patch_docker_path = PurePath("/pypy_venv.patch") docker.copy_into(patch_path, patch_docker_path) try: diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 5f6fc8d3..9218e3e3 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -141,7 +141,7 @@ def install_cpython(version: str, url: str) -> Path: # if this version of python isn't installed, get it from python.org and install python_package_identifier = f"org.python.Python.PythonFramework-{version}" - python_executable = "python3" if version[0] == "3" else "python" + python_executable = "python3" installation_bin_path = Path(f"/Library/Frameworks/Python.framework/Versions/{version}/bin") if python_package_identifier not in installed_system_packages: @@ -151,7 +151,7 @@ def install_cpython(version: str, url: str) -> Path: call(["sudo", "installer", "-pkg", "/tmp/Python.pkg", "-target", "/"]) call(["sudo", str(installation_bin_path / python_executable), str(install_certifi_script)]) - pip_executable = "pip3" if version[0] == "3" else "pip" + pip_executable = "pip3" make_symlinks(installation_bin_path, python_executable, pip_executable) return installation_bin_path @@ -168,13 +168,12 @@ def install_pypy(version: str, url: str) -> Path: download(url, downloaded_tar_bz2) call(["tar", "-C", "/tmp", "-xf", downloaded_tar_bz2]) # Patch PyPy to make sure headers get installed into a venv - patch_version = "_27" if version == "2.7" else "" - patch_path = resources_dir / f"pypy_venv{patch_version}.patch" + patch_path = resources_dir / "pypy_venv.patch" call(["patch", "--force", "-p1", "-d", installation_path, "-i", patch_path]) installation_bin_path = installation_path / "bin" - python_executable = "pypy3" if version[0] == "3" else "pypy" - pip_executable = "pip3" if version[0] == "3" else "pip" + python_executable = "pypy3" + pip_executable = "pip3" make_symlinks(installation_bin_path, python_executable, pip_executable) return installation_bin_path diff --git a/cibuildwheel/resources/build-platforms.toml b/cibuildwheel/resources/build-platforms.toml index afb7b6f0..55cd3ba0 100644 --- a/cibuildwheel/resources/build-platforms.toml +++ b/cibuildwheel/resources/build-platforms.toml @@ -1,18 +1,13 @@ [linux] python_configurations = [ - { identifier = "cp27-manylinux_x86_64", version = "2.7", path_str = "/opt/python/cp27-cp27m" }, - { identifier = "cp27-manylinux_x86_64", version = "2.7", path_str = "/opt/python/cp27-cp27mu" }, { identifier = "cp36-manylinux_x86_64", version = "3.6", path_str = "/opt/python/cp36-cp36m" }, { identifier = "cp37-manylinux_x86_64", version = "3.7", path_str = "/opt/python/cp37-cp37m" }, { identifier = "cp38-manylinux_x86_64", version = "3.8", path_str = "/opt/python/cp38-cp38" }, { identifier = "cp39-manylinux_x86_64", version = "3.9", path_str = "/opt/python/cp39-cp39" }, - { identifier = "cp27-manylinux_i686", version = "2.7", path_str = "/opt/python/cp27-cp27m" }, - { identifier = "cp27-manylinux_i686", version = "2.7", path_str = "/opt/python/cp27-cp27mu" }, { identifier = "cp36-manylinux_i686", version = "3.6", path_str = "/opt/python/cp36-cp36m" }, { identifier = "cp37-manylinux_i686", version = "3.7", path_str = "/opt/python/cp37-cp37m" }, { identifier = "cp38-manylinux_i686", version = "3.8", path_str = "/opt/python/cp38-cp38" }, { identifier = "cp39-manylinux_i686", version = "3.9", path_str = "/opt/python/cp39-cp39" }, - { identifier = "pp27-manylinux_x86_64", version = "2.7", path_str = "/opt/python/pp27-pypy_73" }, { identifier = "pp36-manylinux_x86_64", version = "3.6", path_str = "/opt/python/pp36-pypy36_pp73" }, { identifier = "pp37-manylinux_x86_64", version = "3.7", path_str = "/opt/python/pp37-pypy37_pp73" }, { identifier = "cp36-manylinux_aarch64", version = "3.6", path_str = "/opt/python/cp36-cp36m" }, @@ -31,22 +26,18 @@ python_configurations = [ [macos] python_configurations = [ - { identifier = "cp27-macosx_x86_64", version = "2.7", url = "https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg" }, { identifier = "cp36-macosx_x86_64", version = "3.6", url = "https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.9.pkg" }, { identifier = "cp37-macosx_x86_64", version = "3.7", url = "https://www.python.org/ftp/python/3.7.9/python-3.7.9-macosx10.9.pkg" }, { identifier = "cp38-macosx_x86_64", version = "3.8", url = "https://www.python.org/ftp/python/3.8.9/python-3.8.9-macosx10.9.pkg" }, { identifier = "cp39-macosx_x86_64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.4/python-3.9.4-macos11.pkg" }, { identifier = "cp39-macosx_arm64", version = "3.9", url = "https://www.python.org/ftp/python/3.9.4/python-3.9.4-macos11.pkg" }, { identifier = "cp39-macosx_universal2", version = "3.9", url = "https://www.python.org/ftp/python/3.9.4/python-3.9.4-macos11.pkg" }, - { identifier = "pp27-macosx_x86_64", version = "2.7", url = "https://downloads.python.org/pypy/pypy2.7-v7.3.3-osx64.tar.bz2" }, { identifier = "pp36-macosx_x86_64", version = "3.6", url = "https://downloads.python.org/pypy/pypy3.6-v7.3.3-osx64.tar.bz2" }, { identifier = "pp37-macosx_x86_64", version = "3.7", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.3-osx64.tar.bz2" }, ] [windows] python_configurations = [ - { identifier = "cp27-win32", version = "2.7.18", arch = "32" }, - { identifier = "cp27-win_amd64", version = "2.7.18", arch = "64" }, { identifier = "cp36-win32", version = "3.6.8", arch = "32" }, { identifier = "cp36-win_amd64", version = "3.6.8", arch = "64" }, { identifier = "cp37-win32", version = "3.7.9", arch = "32" }, @@ -55,7 +46,6 @@ python_configurations = [ { identifier = "cp38-win_amd64", version = "3.8.9", arch = "64" }, { identifier = "cp39-win32", version = "3.9.4", arch = "32" }, { identifier = "cp39-win_amd64", version = "3.9.4", arch = "64" }, - { identifier = "pp27-win32", version = "2.7", arch = "32", url = "https://downloads.python.org/pypy/pypy2.7-v7.3.3-win32.zip" }, { identifier = "pp36-win32", version = "3.6", arch = "32", url = "https://downloads.python.org/pypy/pypy3.6-v7.3.3-win32.zip" }, { identifier = "pp37-win32", version = "3.7", arch = "32", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.3-win32.zip" }, ] diff --git a/cibuildwheel/resources/constraints-python27.txt b/cibuildwheel/resources/constraints-python27.txt deleted file mode 100644 index ce5b5f03..00000000 --- a/cibuildwheel/resources/constraints-python27.txt +++ /dev/null @@ -1,55 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# bin/update_dependencies.py -# -appdirs==1.4.4 - # via virtualenv -configparser==4.0.2 - # via importlib-metadata -contextlib2==0.6.0.post1 - # via - # importlib-metadata - # importlib-resources -delocate==0.8.2 - # via -r cibuildwheel/resources/constraints.in -distlib==0.3.1 - # via virtualenv -filelock==3.0.12 - # via virtualenv -importlib-metadata==2.1.1 - # via virtualenv -importlib-resources==3.3.1 - # via virtualenv -pathlib2==2.3.5 - # via - # importlib-metadata - # importlib-resources - # virtualenv -scandir==1.10.0 - # via pathlib2 -singledispatch==3.6.1 - # via importlib-resources -six==1.15.0 - # via - # pathlib2 - # virtualenv -typing==3.7.4.3 - # via importlib-resources -virtualenv==20.4.3 - # via -r cibuildwheel/resources/constraints.in -wheel==0.36.2 - # via - # -r cibuildwheel/resources/constraints.in - # delocate -zipp==1.2.0 - # via - # importlib-metadata - # importlib-resources - -# The following packages are considered to be unsafe in a requirements file: -pip==20.3.4 - # via -r cibuildwheel/resources/constraints.in -setuptools==44.1.1 - # via -r cibuildwheel/resources/constraints.in diff --git a/cibuildwheel/resources/install_certifi.py b/cibuildwheel/resources/install_certifi.py index 953dced7..89bf82f0 100644 --- a/cibuildwheel/resources/install_certifi.py +++ b/cibuildwheel/resources/install_certifi.py @@ -24,9 +24,6 @@ STAT_0o775 = ( | stat.S_IXOTH ) -if sys.version_info[0] == 2: - FileNotFoundError = OSError - def main(): openssl_dir, openssl_cafile = os.path.split(ssl.get_default_verify_paths().openssl_cafile) diff --git a/cibuildwheel/resources/pinned_docker_images.cfg b/cibuildwheel/resources/pinned_docker_images.cfg index df14df35..d1638c08 100644 --- a/cibuildwheel/resources/pinned_docker_images.cfg +++ b/cibuildwheel/resources/pinned_docker_images.cfg @@ -1,12 +1,12 @@ [x86_64] manylinux1 = quay.io/pypa/manylinux1_x86_64:2021-04-05-14df3a6 -manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2021-02-06-3d322a5 +manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2021-04-05-b4fd19d manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2021-04-05-b4fd19d manylinux_2_24 = quay.io/pypa/manylinux_2_24_x86_64:2021-04-05-b4fd19d [i686] manylinux1 = quay.io/pypa/manylinux1_i686:2021-04-05-14df3a6 -manylinux2010 = quay.io/pypa/manylinux2010_i686:2021-02-06-3d322a5 +manylinux2010 = quay.io/pypa/manylinux2010_i686:2021-04-05-b4fd19d manylinux2014 = quay.io/pypa/manylinux2014_i686:2021-04-05-b4fd19d manylinux_2_24 = quay.io/pypa/manylinux_2_24_i686:2021-04-05-b4fd19d diff --git a/cibuildwheel/resources/pypy_venv_27.patch b/cibuildwheel/resources/pypy_venv_27.patch deleted file mode 100644 index 4dd31537..00000000 --- a/cibuildwheel/resources/pypy_venv_27.patch +++ /dev/null @@ -1,27 +0,0 @@ ---- a/lib-python/2.7/sysconfig.py -+++ b/lib-python/2.7/sysconfig.py -@@ -553,9 +553,6 @@ def get_config_vars(*args): - if type_ == imp.C_EXTENSION: - _CONFIG_VARS['SOABI'] = suffix.split('.')[1] - break -- _CONFIG_VARS['INCLUDEPY'] = os.path.join(_CONFIG_VARS['prefix'], -- 'include') -- - if args: - vals = [] - for name in args: ---- a/lib_pypy/_sysconfigdata.py -+++ b/lib_pypy/_sysconfigdata.py -@@ -1,5 +1,11 @@ --import imp -+import imp, os -+ -+mybase = os.path.dirname(os.path.dirname(__file__)) - - build_time_vars = { - "SO": [s[0] for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION][0] - } -+ -+build_time_vars['LIBDIR'] = os.path.join(mybase, 'lib') -+build_time_vars['INCLUDEPY'] = os.path.join(mybase, 'include') -+ diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index c5a958c3..c5a03b18 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -163,7 +163,7 @@ class DependencyConstraints: version_parts = version.split(".") # try to find a version-specific dependency file e.g. if - # ./constraints.txt is the base, look for ./constraints-python27.txt + # ./constraints.txt is the base, look for ./constraints-python36.txt specific_stem = self.base_file_path.stem + f"-python{version_parts[0]}{version_parts[1]}" specific_name = specific_stem + self.base_file_path.suffix specific_file_path = self.base_file_path.with_name(specific_name) diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index 4f839dd9..9f1bc2d0 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -22,8 +22,6 @@ from .util import ( read_python_configs, ) -IS_RUNNING_ON_AZURE = Path("C:\\hostedtoolcache").exists() - def call( args: Sequence[PathOrStr], env: Optional[Dict[str, str]] = None, cwd: Optional[str] = None @@ -40,7 +38,7 @@ def shell(command: str, env: Optional[Dict[str, str]] = None, cwd: Optional[str] def get_nuget_args(version: str, arch: str) -> List[str]: - python_name = "python" if version[0] == "3" else "python2" + python_name = "python" if arch == "32": python_name += "x86" return [ @@ -75,13 +73,6 @@ def get_python_configurations( "64": Architecture.AMD64, } - # Only supported with custom compiler, since MS removed the 2008 compiler download - custom_compiler = os.environ.get("DISTUTILS_USE_SDK") and os.environ.get("MSSdk") - if not custom_compiler: - python_configurations = [ - c for c in python_configurations if not c.version.startswith("2.7") - ] - # skip builds as required python_configurations = [ c @@ -116,8 +107,7 @@ def install_pypy(version: str, arch: str, url: str) -> Path: download(url, pypy_zip) # Extract to the parent directory because the zip file still contains a directory extract_zip(pypy_zip, installation_path.parent) - pypy_exe = "pypy3.exe" if version[0] == "3" else "pypy.exe" - (installation_path / "python.exe").symlink_to(installation_path / pypy_exe) + (installation_path / "python.exe").symlink_to(installation_path / "pypy3.exe") return installation_path diff --git a/docs/contributing.md b/docs/contributing.md index fe2ae756..6823c59f 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -71,7 +71,6 @@ This has been moved to using docker, so you only need the following instructions The dependency update script in the next section requires multiple python versions installed. One way to do this is to use `pyenv`: ```bash -pyenv install 2.7.18 pyenv install 3.6.11 pyenv install 3.7.8 # Optionally add 3.8 and make it the local version; @@ -81,8 +80,6 @@ pyenv install 3.7.8 Then, you need to make the required virtual environments: ```bash -$(pyenv prefix 2.7.18)/bin/python -m pip install virtualenv -$(pyenv prefix 2.7.18)/bin/python -m virtualenv env27 $(pyenv prefix 3.6.11)/bin/python -m venv env36 $(pyenv prefix 3.7.8)/bin/python -m venv env37 ``` diff --git a/docs/cpp_standards.md b/docs/cpp_standards.md index 4887502d..38f825cf 100644 --- a/docs/cpp_standards.md +++ b/docs/cpp_standards.md @@ -5,10 +5,6 @@ title: Modern C++ standards Building Python wheels with modern C++ standards (C++11 and later) requires a few tricks. -## Python 2.7 and C++17 - -The Python 2.7 header files use the `register` keyword, which is [reserved and unused from C+17 onwards](https://en.cppreference.com/w/cpp/keyword/register). Compiling a wheel for Python 2.7 with the C++17 standard is still possible to allow usage of `register` using proper flag `-Wno-register` for gcc/clang and `/wd5033` for MSVC. - ## manylinux1 and C++14 The default `manylinux1` image (based on CentOS 5) contains a version of GCC and libstdc++ that only supports C++11 and earlier standards. There are however ways to compile wheels with the C++14 standard (and later): https://github.com/pypa/manylinux/issues/118 @@ -27,45 +23,3 @@ To get C++17 support, Xcode 9.3+ is needed, requiring at least macOS 10.13 on th However, if only C++17 compiler and standard template library (STL) features are used (not needing a C++17 runtime) it might be possible to set `MACOSX_DEPLOYMENT_TARGET` to a lower value, such as `"10.9"`. To find out if this is the case, try compiling and running with a lower `MACOSX_DEPLOYMENT_TARGET`: if C++17 features are used that require a more recent deployment target, building the wheel should fail. For more details see https://en.cppreference.com/w/cpp/compiler_support, https://en.wikipedia.org/wiki/Xcode, and https://xcodereleases.com/: Xcode 10 needs macOS 10.13 and Xcode 11 needs macOS 10.14. - -## Windows and Python 2.7 - -In previous years, Microsoft distributed a compiler toolchain called 'Visual C++ for Python 2.7', which was a distribution of MSVC 2008 that was created to make it easier to build Python 2.7 extensions on Windows, because it was fully compatible with the toolchain that built Python 2.7. - -This toolchain does not support modern C++ standards (i.e., C++11 and later). And it is hard to find this toolchain these days, since Microsoft removed the download for the required Visual Studio 2008 needed to build a native extension in April, 2021. So, by default, cibuildwheel does not attempt to build Python 2.7 extensions on Windows. - -There is an optional workaround, though: the pybind11 project argues and shows that it is [possible to compile Python 2.7 extension with a newer compiler](https://pybind11.readthedocs.io/en/stable/faq.html#working-with-ancient-visual-studio-2008-builds-on-windows) and has an example project showing how to do this: https://github.com/pybind/python_example. The main catch is that a user might need to install [a newer "Microsoft Visual C++ Redistributable"](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads), since the newer C++ standard library's binaries are not included by default with the Python 2.7 installation. - -Forcing `distutils` or `setuptools` to use a more recent version of MSVC that supports modern C++ can be done in the following way: - -1. Set the environment variables `DISTUTILS_USE_SDK=1` and `MSSdk=1`. These two environment variables will tell `distutils`/`setuptools` to not search and set up a build environment that uses Visual C++ for Python 2.7 (aka. MSVC 9). -2. Set up the build Visual Studio build environment you want to use, making sure that e.g. `PATH` contains `cl`, `link`, etc. - - Usually, this can be done through `vcvarsall.bat x86` or `vcvarsall.bat x64`. The exact location of this file depends on the installation, but the default path for VS 2019 Community (e.g. used in AppVeyor's `Visual Studio 2019` image) is `C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat`. **Note**: `vcvarsall.bat` changes the environment variables, so this cannot be run in a subprocess/subshell and consequently running `vsvarsall.bat` in `CIBW_BEFORE_BUILD` does not have any effect. - - In Azure Pipelines, [a `VSBuild` task is available](https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/visual-studio-build) - - In GitHub Actions, the default shell is powershell, so you'll need to use `shell: cmd` to source a `.bat` file, and the directory is `"C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat"`. Or you can use an action, such as the [`ilammy/msvc-dev-cmd@v1`](https://github.com/ilammy/msvc-dev-cmd) action to setup the environment (see example below). -3. Next, call `cibuildwheel`. Unfortunately, MSVC has separate toolchains for compiling 32-bit and 64-bit, so you will need to run `cibuildwheel` twice: once with `CIBW_BUILD=*-win32` after setting up the `x86` build environment, and once with `CIBW_BUILD=*-win_amd64` in a `x64` environment (see previous step). - - -**GitHub Action example with ilammy/msvc-dev-cmd**: - -```yaml - - uses: ilammy/msvc-dev-cmd@v1 - - - name: Build 64-bit wheel - run: python -m cibuildwheel --output-dir wheelhouse - env: - CIBW_BUILD: cp27-win_amd64 - DISTUTILS_USE_SDK: 1 - MSSdk: 1 - - - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x86 - - - name: Build 32-bit wheel - run: python -m cibuildwheel --output-dir wheelhouse - env: - CIBW_BUILD: cp27-win32 - DISTUTILS_USE_SDK: 1 - MSSdk: 1 -``` diff --git a/docs/faq.md b/docs/faq.md index c0c6a355..b25abe21 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -14,6 +14,10 @@ If your wheel didn't compile, check the list below for some debugging tips. - MacOS: calling cibuildwheel from a python3 script and getting a `ModuleNotFoundError`? Due to a (fixed) [bug](https://bugs.python.org/issue22490) in CPython, you'll need to [unset the `__PYVENV_LAUNCHER__` variable](https://github.com/joerick/cibuildwheel/issues/133#issuecomment-478288597) before activating a venv. +### Building Python 2.7 / PyPy2 wheels + +See the [cibuildwheel verison 1 docs](https://cibuildwheel.readthedocs.io/en/1.x/) for information about building Python 2.7 or PyPy2 wheels. There are lots of tricks and workaround there that are no longer required for Python 3 in cibuildwheel 2. + ### Linux builds on Docker Linux wheels are built in the [`manylinux` docker images](https://github.com/pypa/manylinux) to provide binary compatible wheels on Linux, according to [PEP 571](https://www.python.org/dev/peps/pep-0571/). Because of this, when building with `cibuildwheel` on Linux, a few things should be taken into account: @@ -136,35 +140,6 @@ Here's an example GitHub Actions workflow with a job that builds for Apple Silic {% include "../examples/github-apple-silicon.yml" %} ``` -### Windows and Python 2.7 - -Building 2.7 extensions on Windows is difficult, because the VS 2008 compiler that was used for the original Python compilation was discontinued in 2018, and has since been removed from Microsoft's downloads. Most people choose to not build Windows 2.7 wheels, or to override the compiler to something more modern. - -To override, you need to have a modern compiler toolchain activated, and set `DISTUTILS_USE_SDK=1` and `MSSdk=1`. For example, on GitHub Actions, you would add these steps: - -```yaml - - name: Prepare compiler environment for Windows - if: runner.os == 'Windows' - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x64 - - - name: Set Windows environment variables - if: runner.os == 'Windows' - shell: bash - run: | - echo "DISTUTILS_USE_SDK=1" >> $GITHUB_ENV - echo "MSSdk=1" >> $GITHUB_ENV - - # invoke cibuildwheel... -``` - -cibuildwheel will not try to build 2.7 on Windows unless it detects that the above two variables are set. Note that changing to a more modern compiler will mean your wheel picks up a runtime dependency to a different [Visual C++ Redistributable][]. You also need to be [a bit careful][] in designing your extension; some major binding tools like pybind11 do this for you. - -More on setting a custom Windows toolchain in our docs on modern C++ standards [here](cpp_standards.md#windows-and-python-27). - -[Visual C++ Redistributable]: https://support.microsoft.com/en-us/topic/the-latest-supported-visual-c-downloads-2647da03-1eea-4433-9aff-95f26a218cc0 -[a bit careful]: https://pybind11.readthedocs.io/en/stable/faq.html#working-with-ancient-visual-studio-2008-builds-on-windows ### Building packages with optional C extensions @@ -206,7 +181,7 @@ python3 -m twine upload wheelhouse/*.whl ### 'ImportError: DLL load failed: The specific module could not be found' error on Windows -Visual Studio and MSVC link the compiled binary wheels to the Microsoft Visual C++ Runtime. Normally, these are included with Python, but when compiling with a newer version of Visual Studio, it is possible users will run into problems on systems that do not have these runtime libraries installed. The solution is to ask users to download the corresponding Visual C++ Redistributable from the [Microsoft website](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) and install it. Since a Python installation normally includes these VC++ Redistributable files for [the version of the MSVC compiler used to compile Python](https://wiki.python.org/moin/WindowsCompilers), this is typically only a problem when compiling a Python 2.7 C extension with a newer compiler, e.g. to support a modern C++ standard (see [the section on modern C++ standards for Python 2.7](cpp_standards.md#windows-and-python-27) for more details). +Visual Studio and MSVC link the compiled binary wheels to the Microsoft Visual C++ Runtime. Normally, these are included with Python, but when compiling with a newer version of Visual Studio, it is possible users will run into problems on systems that do not have these runtime libraries installed. The solution is to ask users to download the corresponding Visual C++ Redistributable from the [Microsoft website](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) and install it. Since a Python installation normally includes these VC++ Redistributable files for [the version of the MSVC compiler used to compile Python](https://wiki.python.org/moin/WindowsCompilers), this is typically only a problem when compiling a Python C extension with a newer compiler. Additionally, Visual Studio 2019 started linking to an even newer DLL, `VCRUNTIME140_1.dll`, besides the `VCRUNTIME140.dll` that is included with recent Python versions (starting from Python 3.5; see [here](https://wiki.python.org/moin/WindowsCompilers) for more details on the corresponding Visual Studio & MSVC versions used to compile the different Python versions). To avoid this extra dependency on `VCRUNTIME140_1.dll`, the [`/d2FH4-` flag](https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/) can be added to the MSVC invocations (check out [this issue](https://github.com/joerick/cibuildwheel/issues/423) for details and references). diff --git a/docs/options.md b/docs/options.md index 3a673ca1..530feed7 100644 --- a/docs/options.md +++ b/docs/options.md @@ -120,12 +120,10 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat | | macOS | Windows | Manylinux Intel | Manylinux Other | |--------------|---------------------------------------------------------------------|-------------------------------|-----------------------------------------------|----------------------------------------------------------------------------| -| Python 2.7 | cp27-macosx_x86_64 | cp27-win_amd64
cp27-win32 | cp27-manylinux_x86_64
cp27-manylinux_i686 | | | Python 3.6 | cp36-macosx_x86_64 | cp36-win_amd64
cp36-win32 | cp36-manylinux_x86_64
cp36-manylinux_i686 | cp36-manylinux_aarch64
cp36-manylinux_ppc64le
cp36-manylinux_s390x | | Python 3.7 | cp37-macosx_x86_64 | cp37-win_amd64
cp37-win32 | cp37-manylinux_x86_64
cp37-manylinux_i686 | cp37-manylinux_aarch64
cp37-manylinux_ppc64le
cp37-manylinux_s390x | | Python 3.8 | cp38-macosx_x86_64 | cp38-win_amd64
cp38-win32 | cp38-manylinux_x86_64
cp38-manylinux_i686 | cp38-manylinux_aarch64
cp38-manylinux_ppc64le
cp38-manylinux_s390x | | Python 3.9 | cp39-macosx_x86_64
cp39-macosx_universal2
cp39-macosx_arm64 | cp39-win_amd64
cp39-win32 | cp39-manylinux_x86_64
cp39-manylinux_i686 | cp39-manylinux_aarch64
cp39-manylinux_ppc64le
cp39-manylinux_s390x | -| PyPy2.7 v7.3 | pp27-macosx_x86_64 | pp27-win32 | pp27-manylinux_x86_64 | | | PyPy3.6 v7.3 | pp36-macosx_x86_64 | pp36-win32 | pp36-manylinux_x86_64 | | | PyPy3.7 v7.3 | pp37-macosx_x86_64 | pp37-win32 | pp37-manylinux_x86_64 | | @@ -133,28 +131,30 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to cibuildwheel. The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details). -For CPython, the minimally supported macOS version is 10.9; for PyPy 2.7 and PyPy 3.6/3.7, respectively macOS 10.7 and 10.13 or higher is required. +For CPython, the minimally supported macOS version is 10.9; for PyPy 3.6/3.7, macOS 10.13 or higher is required. + +See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.x/) for past end of life versions of Python, and PyPy2.7. #### Examples ```yaml -# Only build on Python 3.6 +# Only build on CPython 3.6 CIBW_BUILD: cp36-* -# Skip building on Python 2.7 on the Mac -CIBW_SKIP: cp27-macosx_x86_64 +# Skip building on CPython 3.6 on the Mac +CIBW_SKIP: cp36-macosx_x86_64 -# Skip building on Python 3.8 on the Mac +# Skip building on CPython 3.8 on the Mac CIBW_SKIP: cp38-macosx_x86_64 -# Skip building on Python 2.7 on all platforms -CIBW_SKIP: cp27-* +# Skip building on CPython 3.6 on all platforms +CIBW_SKIP: cp36-* -# Skip Python 2.7 on Windows -CIBW_SKIP: cp27-win* +# Skip CPython 3.6 on Windows +CIBW_SKIP: cp36-win* -# Skip Python 2.7 on 32-bit Windows -CIBW_SKIP: cp27-win32 +# Skip CPython 3.6 on 32-bit Windows +CIBW_SKIP: cp36-win32 # Skip CPython 3.6 and CPython 3.7 CIBW_SKIP: cp36-* cp37-* @@ -162,13 +162,9 @@ CIBW_SKIP: cp36-* cp37-* # Skip Python 3.6 on Linux CIBW_SKIP: cp36-manylinux* -# Only build on Python 3 (ready for 3.10 when it comes) and skip 32-bit builds -CIBW_BUILD: {cp,pp}3*-* +# Skip 32-bit builds CIBW_SKIP: "*-win32 *-manylinux_i686" -# Only build PyPy and CPython 3 -CIBW_BUILD: pp* cp3*-* - # Disable building PyPy wheels on all platforms CIBW_SKIP: pp* ``` @@ -489,7 +485,6 @@ Set an alternative Docker image to be used for building [manylinux](https://gith The value of this option can either be set to `manylinux1`, `manylinux2010`, `manylinux2014` or `manylinux_2_24` to use a pinned version of the [official manylinux images](https://github.com/pypa/manylinux) and [PyPy manylinux images](https://github.com/pypy/manylinux). Alternatively, set these options to any other valid Docker image name. For PyPy, only the official `manylinux2010` image is currently available. For architectures other than x86 (x86\_64 and i686) `manylinux2014` or `manylinux_2_24` must be used, because the first version of the manylinux specification that supports additional architectures is `manylinux2014`. -Note that `manylinux2014`/`manylinux_2_24` don't support builds with Python 2.7 - when building with `manylinux2014`/`manylinux_2_24`, skip Python 2.7 using `CIBW_SKIP` (see example below). If setting a custom Docker image, you'll need to make sure it can be used in the same way as the official, default Docker images: all necessary Python and pip versions need to be present in `/opt/python/`, and the auditwheel tool needs to be present for cibuildwheel to work. Apart from that, the architecture and relevant shared system libraries need to be compatible to the relevant standard to produce valid manylinux1/manylinux2010/manylinux2014/manylinux_2_24 wheels (see [pypa/manylinux on GitHub](https://github.com/pypa/manylinux), [PEP 513](https://www.python.org/dev/peps/pep-0513/), [PEP 571](https://www.python.org/dev/peps/pep-0571/), [PEP 599](https://www.python.org/dev/peps/pep-0599/) and [PEP 600](https://www.python.org/dev/peps/pep-0600/) for more details). @@ -544,7 +539,7 @@ here and it will be used instead. If you need different dependencies for each python version, provide them in the same folder with a `-pythonXY` suffix. e.g. if your `CIBW_DEPENDENCY_VERSIONS=./constraints.txt`, cibuildwheel will use - `./constraints-python27.txt` on Python 2.7, or fallback to + `./constraints-python37.txt` on Python 3.7, or fallback to `./constraints.txt` if that's not found. Platform-specific variants also available:
diff --git a/docs/setup.md b/docs/setup.md index d39aeadf..ffbb7182 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -123,8 +123,6 @@ To build Linux, Mac, and Windows wheels on Travis CI, create a `.travis.yml` fil {% include "../examples/travis-ci-minimal.yml" %} ``` -Note that building Windows Python 2.7 wheels on Travis is unsupported unless using a newer compiler [via a workaround](cpp_standards.md). - Commit this file, enable building of your repo on Travis CI, and push. Then setup a deployment method by following the [Travis CI deployment docs](https://docs.travis-ci.com/user/deployment/), or see [Delivering to PyPI](deliver-to-pypi.md). For more info on `.travis.yml`, check out the [docs](https://docs.travis-ci.com/). diff --git a/test/test_build_skip.py b/test/test_build_skip.py index c63ee710..5a5a17b3 100644 --- a/test/test_build_skip.py +++ b/test/test_build_skip.py @@ -5,11 +5,11 @@ from . import test_projects, utils project_with_skip_asserts = test_projects.new_c_project( setup_py_add=textwrap.dedent( r""" - # explode if run on Python 2.7 or Python 3.7 (these should be skipped) - if sys.version_info[0:2] == (2, 7): - raise Exception("Python 2.7 should not be built") + # explode if run on PyPyor Python 3.7 (these should be skipped) + if sys.implementation.name != "cpython": + raise Exception("Only CPython shall be built") if sys.version_info[0:2] == (3, 7): - raise Exception("Python 3.7 should be skipped") + raise Exception("CPython 3.7 should be skipped") """ ) ) @@ -28,7 +28,7 @@ def test(tmp_path): }, ) - # check that we got the right wheels. There should be no 2.7 or 3.7. + # check that we got the right wheels. There should be no PyPy or 3.7. expected_wheels = [ w for w in utils.expected_wheels("spam", "0.1.0") if ("-cp3" in w) and ("-cp37" not in w) ] diff --git a/test/test_cpp_standards.py b/test/test_cpp_standards.py index 5caf5b7b..a5385007 100644 --- a/test/test_cpp_standards.py +++ b/test/test_cpp_standards.py @@ -36,38 +36,18 @@ spam_system(PyObject *self, PyObject *args) } /* Module initialization */ - -#if PY_MAJOR_VERSION >= 3 - #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) - #define MOD_DEF(m, name, doc, methods, module_state_size) \ - static struct PyModuleDef moduledef = { \ - PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \ - m = PyModule_Create(&moduledef); - #define MOD_RETURN(m) return m; -#else - #define MOD_INIT(name) PyMODINIT_FUNC init##name(void) - #define MOD_DEF(m, name, doc, methods, module_state_size) \ - m = Py_InitModule3(name, methods, doc); - #define MOD_RETURN(m) return; -#endif - static PyMethodDef module_methods[] = { {"system", (PyCFunction)spam_system, METH_VARARGS, "Execute a shell command."}, {NULL} /* Sentinel */ }; -MOD_INIT(spam) +PyMODINIT_FUNC PyInit_spam(void) { - PyObject* m; - - MOD_DEF(m, - "spam", - "Example module", - module_methods, - -1) - - MOD_RETURN(m) + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, "spam", "Example module", -1, module_methods, + }; + return PyModule_Create(&moduledef); } """ @@ -87,15 +67,8 @@ def test_cpp11(tmp_path): cpp11_project.generate(project_dir) - # VC++ for Python 2.7 does not support modern standards - add_env = {"CIBW_SKIP": "cp27-win* pp27-win32"} - - actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env) - expected_wheels = [ - w - for w in utils.expected_wheels("spam", "0.1.0") - if "cp27-cp27m-win" not in w and "pp27-pypy_73-win32" not in w - ] + actual_wheels = utils.cibuildwheel_run(project_dir) + expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0")] assert set(actual_wheels) == set(expected_wheels) @@ -113,27 +86,17 @@ def test_cpp14(tmp_path): cpp14_project.generate(project_dir) - # VC++ for Python 2.7 does not support modern standards - # The manylinux1 docker image does not have a compiler which supports C++11 - add_env = {"CIBW_SKIP": "cp27-win* pp27-win32"} - - actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env) - expected_wheels = [ - w - for w in utils.expected_wheels("spam", "0.1.0") - if "cp27-cp27m-win" not in w and "pp27-pypy_73-win32" not in w - ] + actual_wheels = utils.cibuildwheel_run(project_dir) + expected_wheels = [w for w in utils.expected_wheels("spam", "0.1.0")] assert set(actual_wheels) == set(expected_wheels) cpp17_project = cpp_test_project.copy() -# Python and PyPy 2.7 headers use the `register` keyword, which is forbidden in -# the C++17 standard, so we need the -Wno-register or /wd5033 options -cpp17_project.template_context["extra_compile_args"] = ( - ["/std:c++17", "/wd5033"] if utils.platform == "windows" else ["-std=c++17", "-Wno-register"] -) +cpp17_project.template_context["extra_compile_args"] = [ + "/std:c++17" if utils.platform == "windows" else "-std=c++17" +] cpp17_project.template_context[ "spam_cpp_top_level_add" ] = r""" @@ -153,7 +116,7 @@ def test_cpp17(tmp_path): # Pypy's distutils sets the default compiler to 'msvc9compiler', which # is too old to support cpp17. - add_env = {"CIBW_SKIP": "cp27-win* pp??-*"} + add_env = {"CIBW_SKIP": "pp??-*"} if utils.platform == "macos": add_env["MACOSX_DEPLOYMENT_TARGET"] = "10.13" @@ -162,61 +125,7 @@ def test_cpp17(tmp_path): expected_wheels = [ w for w in utils.expected_wheels("spam", "0.1.0", macosx_deployment_target="10.13") - if "cp27-cp27m-win" not in w and "-pp" not in w - ] - - assert set(actual_wheels) == set(expected_wheels) - - -def test_cpp17_py27_modern_msvc_workaround(tmp_path): - # This test checks the workaround for building Python 2.7 wheel with MSVC 14 - - if utils.platform != "windows": - pytest.skip("the test is only relevant to the Windows build") - - if os.environ.get("APPVEYOR_BUILD_WORKER_IMAGE", "") == "Visual Studio 2015": - pytest.skip("Visual Studio 2015 does not support C++17") - - project_dir = tmp_path / "project" - cpp17_project.generate(project_dir) - - # VC++ for Python 2.7 (i.e., MSVC 9) does not support modern standards - # This is a workaround which forces distutils/setupstools to a newer version - # Wheels compiled need a more modern C++ redistributable installed, which is not - # included with Python: see documentation for more info - # DISTUTILS_USE_SDK and MSSdk=1 tell distutils/setuptools that we are adding - # MSVC's compiler, tools, and libraries to PATH ourselves - add_env = {"DISTUTILS_USE_SDK": "1", "MSSdk": "1"} - - # Use existing setuptools code to run Visual Studio's vcvarsall.bat and get the - # necessary environment variables, since running vcvarsall.bat in a subprocess - # does not keep the relevant environment variables - # There are different environment variables for 32-bit/64-bit targets, so we - # need to run cibuildwheel twice, once for 32-bit with `vcvarsall.bat x86, and - # once for 64-bit with `vcvarsall.bat x64` - # In a normal CI setup, just run vcvarsall.bat before running cibuildwheel and set - # DISTUTILS_USE_SDK and MSSdk - import setuptools - - def add_vcvars(prev_env, platform): - vcvarsall_env = setuptools.msvc.msvc14_get_vc_env(platform) - env = prev_env.copy() - for vcvar in ["path", "include", "lib"]: - env[vcvar] = vcvarsall_env[vcvar] - return env - - add_env_x86 = add_vcvars(add_env, "x86") - add_env_x86["CIBW_BUILD"] = "?p27-win32" - actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env_x86) - - add_env_x64 = add_vcvars(add_env, "x64") - add_env_x64["CIBW_BUILD"] = "cp27-win_amd64" - actual_wheels += utils.cibuildwheel_run(project_dir, add_env=add_env_x64) - - expected_wheels = [ - w - for w in utils.expected_wheels("spam", "0.1.0", exclude_27=False) - if "cp27-cp27m-win" in w or "pp27-pypy_73-win32" in w + if "-pp" not in w ] assert set(actual_wheels) == set(expected_wheels) diff --git a/test/test_dependency_versions.py b/test/test_dependency_versions.py index f15bb9e6..dc1f0b50 100644 --- a/test/test_dependency_versions.py +++ b/test/test_dependency_versions.py @@ -47,31 +47,28 @@ def get_versions_from_constraint_file(constraint_file): } -@pytest.mark.parametrize("python_version", ["2.7", "3.6", "3.8", "3.9"]) +@pytest.mark.parametrize("python_version", ["3.6", "3.8", "3.9"]) def test_pinned_versions(tmp_path, python_version): if utils.platform == "linux": pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead") - if utils.platform == "windows" and python_version == "2.7": - pytest.skip("Windows requires a workaround") - project_dir = tmp_path / "project" project_with_expected_version_checks.generate(project_dir) build_environment = {} - if python_version == "2.7": - constraint_filename = "constraints-python27.txt" - build_pattern = "[cp]p27-*" - elif python_version == "3.6": + if python_version == "3.6": constraint_filename = "constraints-python36.txt" build_pattern = "[cp]p36-*" elif python_version == "3.7": constraint_filename = "constraints-python37.txt" build_pattern = "[cp]p37-*" + elif python_version == "3.8": + constraint_filename = "constraints-python38.txt" + build_pattern = "[cp]p38-*" else: constraint_filename = "constraints.txt" - build_pattern = "[cp]p38-*" + build_pattern = "[cp]p39-*" constraint_file = cibuildwheel.util.resources_dir / constraint_filename constraint_versions = get_versions_from_constraint_file(constraint_file) @@ -92,11 +89,7 @@ def test_pinned_versions(tmp_path, python_version): ) # also check that we got the right wheels - if python_version == "2.7": - expected_wheels = [ - w for w in utils.expected_wheels("spam", "0.1.0") if "-cp27" in w or "-pp27" in w - ] - elif python_version == "3.6": + if python_version == "3.6": expected_wheels = [ w for w in utils.expected_wheels("spam", "0.1.0") if "-cp36" in w or "-pp36" in w ] @@ -104,26 +97,26 @@ def test_pinned_versions(tmp_path, python_version): expected_wheels = [ w for w in utils.expected_wheels("spam", "0.1.0") if "-cp38" in w or "-pp38" in w ] + elif python_version == "3.9": + expected_wheels = [ + w for w in utils.expected_wheels("spam", "0.1.0") if "-cp39" in w or "-pp39" in w + ] else: raise ValueError("unhandled python version") assert set(actual_wheels) == set(expected_wheels) -@pytest.mark.parametrize("python_version", ["2.7", "3.x"]) -def test_dependency_constraints_file(tmp_path, python_version): +def test_dependency_constraints_file(tmp_path): if utils.platform == "linux": pytest.skip("linux doesn't pin individual tool versions, it pins manylinux images instead") - if utils.platform == "windows" and python_version == "2.7": - pytest.skip("Windows + Travis CI requires a workaround") - project_dir = tmp_path / "project" project_with_expected_version_checks.generate(project_dir) tool_versions = { "pip": "20.0.2", - "setuptools": "44.0.0" if python_version == "2.7" else "46.0.0", + "setuptools": "53.0.0", "wheel": "0.34.2", "virtualenv": "20.0.10", } @@ -154,22 +147,12 @@ def test_dependency_constraints_file(tmp_path, python_version): actual_wheels = utils.cibuildwheel_run( project_dir, add_env={ - "CIBW_BUILD": "[cp]p27-*" if python_version == "2.7" else "[cp]p3?-*", "CIBW_ENVIRONMENT": cibw_environment_option, "CIBW_DEPENDENCY_VERSIONS": str(constraints_file), }, ) # also check that we got the right wheels - if python_version == "2.7": - expected_wheels = [ - w for w in utils.expected_wheels("spam", "0.1.0") if "-cp27" in w or "-pp27" in w - ] - else: - expected_wheels = [ - w - for w in utils.expected_wheels("spam", "0.1.0") - if "-cp27" not in w and "-pp27" not in w - ] + expected_wheels = utils.expected_wheels("spam", "0.1.0") assert set(actual_wheels) == set(expected_wheels) diff --git a/test/test_docker_images.py b/test/test_docker_images.py index 13a6d758..70b53254 100644 --- a/test/test_docker_images.py +++ b/test/test_docker_images.py @@ -37,14 +37,12 @@ def test(tmp_path): add_env={ "CIBW_MANYLINUX_X86_64_IMAGE": "dockcross/manylinux2010-x64", "CIBW_MANYLINUX_I686_IMAGE": "dockcross/manylinux2010-x86", - "CIBW_SKIP": "pp* cp27-* cp39-*", + "CIBW_SKIP": "pp* cp39-*", }, ) # also check that we got the right wheels built expected_wheels = [ - w - for w in utils.expected_wheels("spam", "0.1.0") - if "-pp" not in w and "-cp39-" not in w and "-cp27-" not in w + w for w in utils.expected_wheels("spam", "0.1.0") if "-pp" not in w and "-cp39-" not in w ] assert set(actual_wheels) == set(expected_wheels) diff --git a/test/test_manylinuxXXXX_only.py b/test/test_manylinuxXXXX_only.py index 1bc2ace6..0d38f990 100644 --- a/test/test_manylinuxXXXX_only.py +++ b/test/test_manylinuxXXXX_only.py @@ -65,20 +65,16 @@ def test(manylinux_image, tmp_path): "CIBW_MANYLINUX_PPC64LE_IMAGE": manylinux_image, "CIBW_MANYLINUX_S390X_IMAGE": manylinux_image, } - if manylinux_image == "manylinux1": + if manylinux_image in {"manylinux1", "manylinux2014", "manylinux_2_24"}: # We don't have a manylinux1 image for PyPy + # We don't have a manylinux2014 / manylinux_2_24 image for PyPy (yet?) add_env["CIBW_SKIP"] = "pp*" - elif manylinux_image in {"manylinux2014", "manylinux_2_24"}: - # We don't have a manylinux2014 / 'manylinux_2_24' image for PyPy (yet?) - # Python 2.7 not available on manylinux2014 / 'manylinux_2_24' - add_env["CIBW_SKIP"] = "cp27* pp*" + actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env) expected_wheels = [ w for w in utils.expected_wheels("spam", "0.1.0", manylinux_versions=[manylinux_image]) ] - if manylinux_image in {"manylinux2014", "manylinux_2_24"}: - expected_wheels = [w for w in expected_wheels if "-cp27" not in w] if manylinux_image in {"manylinux1", "manylinux2014", "manylinux_2_24"}: expected_wheels = [w for w in expected_wheels if "-pp" not in w] assert set(actual_wheels) == set(expected_wheels) diff --git a/test/test_pep518.py b/test/test_pep518.py index a15181ba..f3f0a023 100644 --- a/test/test_pep518.py +++ b/test/test_pep518.py @@ -8,10 +8,7 @@ basic_project = test_projects.new_c_project( """ # Will fail if PEP 518 does work import requests - if sys.version_info < (3, 6, 0): - assert requests.__version__ == "2.22.0", "Requests found but wrong version ({0})".format(requests.__version__) - else: - assert requests.__version__ == "2.23.0", "Requests found but wrong version ({0})".format(requests.__version__) + assert requests.__version__ == "2.23.0", "Requests found but wrong version ({0})".format(requests.__version__) # Just making sure environment is still set import os @@ -29,8 +26,7 @@ requires = [ "setuptools >= 42", "setuptools_scm[toml]>=4.1.2", "wheel", - "requests==2.22.0; python_version<'3.6'", - "requests==2.23.0; python_version>='3.6'" + "requests==2.23.0" ] build-backend = "setuptools.build_meta" diff --git a/test/test_projects/c.py b/test/test_projects/c.py index 1a2ac763..41b72958 100644 --- a/test/test_projects/c.py +++ b/test/test_projects/c.py @@ -24,38 +24,18 @@ spam_system(PyObject *self, PyObject *args) } /* Module initialization */ - -#if PY_MAJOR_VERSION >= 3 - #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) - #define MOD_DEF(m, name, doc, methods, module_state_size) \ - static struct PyModuleDef moduledef = { \ - PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \ - m = PyModule_Create(&moduledef); - #define MOD_RETURN(m) return m; -#else - #define MOD_INIT(name) PyMODINIT_FUNC init##name(void) - #define MOD_DEF(m, name, doc, methods, module_state_size) \ - m = Py_InitModule3(name, methods, doc); - #define MOD_RETURN(m) return; -#endif - static PyMethodDef module_methods[] = { {"system", (PyCFunction)spam_system, METH_VARARGS, "Execute a shell command."}, {NULL} /* Sentinel */ }; -MOD_INIT(spam) +PyMODINIT_FUNC PyInit_spam(void) { - PyObject* m; - - MOD_DEF(m, - "spam", - "Example module", - module_methods, - -1) - - MOD_RETURN(m) + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, "spam", "Example module", -1, module_methods, + }; + return PyModule_Create(&moduledef); } """ diff --git a/test/test_ssl.py b/test/test_ssl.py index 81315d64..253584a4 100644 --- a/test/test_ssl.py +++ b/test/test_ssl.py @@ -7,10 +7,7 @@ project_with_ssl_tests = test_projects.new_c_project( r""" import ssl - if sys.version_info[0] == 2: - from urllib2 import urlopen - else: - from urllib.request import urlopen + from urllib.request import urlopen context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) data = urlopen("https://www.nist.gov", context=context) diff --git a/test/test_testing.py b/test/test_testing.py index 5179d5dc..95626002 100644 --- a/test/test_testing.py +++ b/test/test_testing.py @@ -52,8 +52,7 @@ class TestSpam(TestCase): # sys.prefix is different from sys.base_prefix when running a virtualenv # See https://docs.python.org/3/library/venv.html, which virtualenv seems # to honor in recent releases - # Python 2 doesn't have sys.base_prefix by default - if not hasattr(sys, 'base_prefix') or sys.prefix == sys.base_prefix: + if sys.prefix == sys.base_prefix: self.fail("Not running in a virtualenv") self.assertTrue(path_contains(sys.prefix, sys.executable)) diff --git a/test/utils.py b/test/utils.py index 20947ae7..5b6b5b7c 100644 --- a/test/utils.py +++ b/test/utils.py @@ -6,11 +6,9 @@ This file is added to the PYTHONPATH in the test runner at bin/run_test.py. import os import platform as pm -import shutil import subprocess import sys -from contextlib import contextmanager -from tempfile import mkdtemp +from tempfile import TemporaryDirectory platform: str @@ -26,17 +24,6 @@ else: raise Exception("Unsupported platform") -# Python 2 does not have a tempfile.TemporaryDirectory context manager -@contextmanager -def TemporaryDirectoryIfNone(path): - _path = path or mkdtemp() - try: - yield _path - finally: - if path is None: - shutil.rmtree(_path) - - def cibuildwheel_get_build_identifiers(project_path, env=None): """ Returns the list of build identifiers that cibuildwheel will try to build @@ -76,21 +63,21 @@ def cibuildwheel_run(project_path, package_dir=".", env=None, add_env=None, outp if add_env is not None: env.update(add_env) - with TemporaryDirectoryIfNone(output_dir) as _output_dir: + with TemporaryDirectory() as tmp_output_dir: subprocess.run( [ sys.executable, "-m", "cibuildwheel", "--output-dir", - str(_output_dir), + str(output_dir or tmp_output_dir), str(package_dir), ], env=env, cwd=project_path, check=True, ) - wheels = os.listdir(_output_dir) + wheels = os.listdir(output_dir or tmp_output_dir) return wheels @@ -113,8 +100,6 @@ def expected_wheels( manylinux_versions=None, macosx_deployment_target="10.9", machine_arch=None, - *, - exclude_27=platform == "windows", ): """ Returns a list of expected wheels from a run of cibuildwheel. @@ -136,10 +121,7 @@ def expected_wheels( python_abi_tags = ["cp36-cp36m", "cp37-cp37m", "cp38-cp38", "cp39-cp39"] if machine_arch in ["x86_64", "AMD64", "x86"]: - python_abi_tags += ["cp27-cp27m", "pp27-pypy_73", "pp36-pypy36_pp73", "pp37-pypy37_pp73"] - - if platform == "linux": - python_abi_tags.append("cp27-cp27mu") # python 2.7 has 2 different ABI on manylinux + python_abi_tags += ["pp36-pypy36_pp73", "pp37-pypy37_pp73"] if platform == "macos" and get_macos_version() >= (10, 16): # 10.16 is sometimes reported as the macOS version on macOS 11. @@ -193,11 +175,6 @@ def expected_wheels( for platform_tag in platform_tags: wheels.append(f"{package_name}-{package_version}-{python_abi_tag}-{platform_tag}.whl") - # Travis on Windows does not support using the default Python 2.7 compiler, - # so we support skipping here. - if exclude_27: - wheels = [w for w in wheels if "-cp27-" not in w and "-pp2" not in w] - return wheels diff --git a/unit_test/build_selector_test.py b/unit_test/build_selector_test.py index 01cba4bb..67fbde6f 100644 --- a/unit_test/build_selector_test.py +++ b/unit_test/build_selector_test.py @@ -4,65 +4,67 @@ from cibuildwheel.util import BuildSelector def test_build(): - build_selector = BuildSelector(build_config="cp3?-* *-manylinux1*", skip_config="") + build_selector = BuildSelector(build_config="cp3?-* *-manylinux*", skip_config="") - assert build_selector("cp27-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") - assert build_selector("cp37-manylinux1_x86_64") - assert build_selector("cp27-manylinux1_i686") - assert build_selector("cp36-manylinux1_i686") - assert build_selector("cp37-manylinux1_i686") - assert not build_selector("cp27-macosx_10_6_intel") + assert build_selector("cp36-manylinux_x86_64") + assert build_selector("cp37-manylinux_x86_64") + assert build_selector("pp36-manylinux_x86_64") + assert build_selector("pp37-manylinux_x86_64") + assert build_selector("cp36-manylinux_i686") + assert build_selector("cp37-manylinux_i686") assert build_selector("cp36-macosx_10_6_intel") assert build_selector("cp37-macosx_10_6_intel") - assert not build_selector("cp27-win32") + assert not build_selector("pp36-macosx_10_6_intel") + assert not build_selector("pp37-macosx_10_6_intel") assert build_selector("cp36-win32") assert build_selector("cp37-win32") - assert not build_selector("cp27-win_amd64") + assert not build_selector("pp36-win32") + assert not build_selector("pp37-win32") assert build_selector("cp36-win_amd64") assert build_selector("cp37-win_amd64") + assert not build_selector("pp36-win_amd64") + assert not build_selector("pp37-win_amd64") def test_skip(): build_selector = BuildSelector( - build_config="*", skip_config="cp27-* cp3?-manylinux1_i686 cp36-win* *-win32" + build_config="*", skip_config="pp36-* cp3?-manylinux_i686 cp36-win* *-win32" ) - assert not build_selector("cp27-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") - assert build_selector("cp37-manylinux1_x86_64") - assert not build_selector("cp27-manylinux1_i686") - assert not build_selector("cp36-manylinux1_i686") - assert not build_selector("cp37-manylinux1_i686") - assert not build_selector("cp27-macosx_10_6_intel") + assert not build_selector("pp36-manylinux_x86_64") + assert build_selector("pp37-manylinux_x86_64") + assert build_selector("cp36-manylinux_x86_64") + assert build_selector("cp37-manylinux_x86_64") + assert not build_selector("cp36-manylinux_i686") + assert not build_selector("cp37-manylinux_i686") + assert not build_selector("pp36-macosx_10_6_intel") + assert build_selector("pp37-macosx_10_6_intel") assert build_selector("cp36-macosx_10_6_intel") assert build_selector("cp37-macosx_10_6_intel") - assert not build_selector("cp27-win32") assert not build_selector("cp36-win32") assert not build_selector("cp37-win32") - assert not build_selector("cp27-win_amd64") assert not build_selector("cp36-win_amd64") assert build_selector("cp37-win_amd64") def test_build_and_skip(): build_selector = BuildSelector( - build_config="cp36-* cp37-macosx* *-manylinux1*", skip_config="cp27-* cp37-manylinux1_i686" + build_config="cp36-* cp37-macosx* *-manylinux*", skip_config="pp37-* cp37-manylinux_i686" ) - assert not build_selector("cp27-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") - assert build_selector("cp37-manylinux1_x86_64") - assert not build_selector("cp27-manylinux1_i686") - assert build_selector("cp36-manylinux1_i686") - assert not build_selector("cp37-manylinux1_i686") - assert not build_selector("cp27-macosx_10_6_intel") + assert not build_selector("pp37-manylinux_x86_64") + assert build_selector("cp36-manylinux_x86_64") + assert build_selector("cp37-manylinux_x86_64") + assert not build_selector("pp37-manylinux_i686") + assert build_selector("cp36-manylinux_i686") + assert not build_selector("cp37-manylinux_i686") + assert not build_selector("pp37-macosx_10_6_intel") assert build_selector("cp36-macosx_10_6_intel") assert build_selector("cp37-macosx_10_6_intel") - assert not build_selector("cp27-win32") + assert not build_selector("pp37-win32") assert build_selector("cp36-win32") assert not build_selector("cp37-win32") - assert not build_selector("cp27-win_amd64") + assert not build_selector("pp37-win_amd64") assert build_selector("cp36-win_amd64") assert not build_selector("cp37-win_amd64") @@ -70,49 +72,45 @@ def test_build_and_skip(): def test_build_braces(): build_selector = BuildSelector(build_config="cp{36,37}*", skip_config="") - assert not build_selector("cp27-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") - assert build_selector("cp37-manylinux1_x86_64") - assert not build_selector("cp38-manylinux1_x86_64") - assert not build_selector("cp39-manylinux1_x86_64") + assert build_selector("cp36-manylinux_x86_64") + assert build_selector("cp37-manylinux_x86_64") + assert not build_selector("cp38-manylinux_x86_64") + assert not build_selector("cp39-manylinux_x86_64") def test_build_limited_python(): build_selector = BuildSelector( - build_config="*", skip_config="", requires_python=SpecifierSet(">=3.6") + build_config="*", skip_config="", requires_python=SpecifierSet(">=3.7") ) - assert not build_selector("cp27-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") - assert build_selector("cp37-manylinux1_x86_64") - assert not build_selector("cp27-manylinux1_i686") - assert build_selector("cp36-manylinux1_i686") - assert build_selector("cp37-manylinux1_i686") - assert not build_selector("cp27-win32") - assert build_selector("cp36-win32") + assert not build_selector("cp36-manylinux_x86_64") + assert build_selector("cp37-manylinux_x86_64") + assert build_selector("cp38-manylinux_x86_64") + assert not build_selector("cp36-manylinux_i686") + assert build_selector("cp37-manylinux_i686") + assert build_selector("cp38-manylinux_i686") + assert not build_selector("cp36-win32") assert build_selector("cp37-win32") - assert not build_selector("pp27-win32") - assert build_selector("pp36-win32") + assert build_selector("cp38-win32") + assert not build_selector("pp36-win32") assert build_selector("pp37-win32") def test_build_limited_python_partial(): build_selector = BuildSelector( - build_config="*", - skip_config="", - requires_python=SpecifierSet(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"), + build_config="*", skip_config="", requires_python=SpecifierSet(">=3.6, !=3.7.*") ) - assert build_selector("cp27-manylinux1_x86_64") - assert not build_selector("cp35-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") + assert build_selector("cp36-manylinux_x86_64") + assert not build_selector("cp37-manylinux_x86_64") + assert build_selector("cp38-manylinux_x86_64") + assert build_selector("cp39-manylinux_x86_64") def test_build_limited_python_patch(): build_selector = BuildSelector( - build_config="*", skip_config="", requires_python=SpecifierSet(">=2.7.9") + build_config="*", skip_config="", requires_python=SpecifierSet(">=3.6.8") ) - assert build_selector("cp27-manylinux1_x86_64") - assert build_selector("cp36-manylinux1_x86_64") - assert build_selector("cp37-manylinux1_x86_64") + assert build_selector("cp36-manylinux_x86_64") + assert build_selector("cp37-manylinux_x86_64") diff --git a/unit_test/dependency_constraints_test.py b/unit_test/dependency_constraints_test.py index 50330b02..95215195 100644 --- a/unit_test/dependency_constraints_test.py +++ b/unit_test/dependency_constraints_test.py @@ -19,6 +19,3 @@ def test_defaults(): assert dependency_constraints.get_for_python_version("3.6").samefile( resources_dir / "constraints-python36.txt" ) - assert dependency_constraints.get_for_python_version("2.7").samefile( - resources_dir / "constraints-python27.txt" - )