diff --git a/CI.md b/CI.md index 1b7c3552..69a2b3bd 100644 --- a/CI.md +++ b/CI.md @@ -1,11 +1,12 @@ This is a summary of the Python versions and platforms covered by the different CI platforms: -| | 3.6 | 3.7 | 3.8 | -|----------|------------------------------|---------------------------------------------------|------------------| -| Linux | Travis CI / CircleCI | AppVeyor / GitHub Actions | Azure Pipelines | -| macOS | CircleCI | AppVeyor / Travis CI¹ / CircleCI / GitHub Actions | Azure Pipelines | -| Windows | Travis CI / Azure Pipelines | AppVeyor / GitHub Actions | Azure Pipelines | +| | 3.5 | 3.6 | 3.7 | 3.8 | +|----------|------------------|------------------|----------------------------------------------------|------------------| +| Linux | Travis CI | CircleCI | AppVeyor² / GitHub Actions | Azure Pipelines | +| macOS | Azure Pipelines | CircleCI | AppVeyor² / Travis CI¹ / CircleCI / GitHub Actions | Azure Pipelines | +| Windows | TravisCI | Azure Pipelines | AppVeyor² / GitHub Actions | Azure Pipelines | > ¹ Python version not really pinned, but dependent on the (default) version of image used. +> ² AppVeyor only runs the "basic" test to reduce load. Non-x86 architectures are covered on Travis CI using Python 3.6. diff --git a/README.md b/README.md index a1a2b95c..28ebbf4f 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ env: # Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings install: - - python3 -m pip install cibuildwheel==1.3.0 + - python3 -m pip install cibuildwheel==1.4.1 script: # build the wheels, put them into './wheelhouse' @@ -128,6 +128,9 @@ Here are some repos that use cibuildwheel. - [Twisted](https://github.com/twisted/twisted) - [gmic-py](https://github.com/dtschump/gmic-py) - [creme](https://github.com/creme-ml/creme) +- [PyAV](https://github.com/PyAV-Org/PyAV) +- [aiortc](https://github.com/aiortc/aiortc) +- [aioquic](https://github.com/aiortc/aioquic) > Add your repo here! Send a PR. @@ -143,6 +146,44 @@ This is similar to static linking, so it might have some licence implications. C Changelog ========= +### 1.4.1 + +_4 May 2020_ + +- 🐛 Fix a bug causing programs running inside the i686 manylinux images to + think they were running x86_64 and target the wrong architecture. (#336, + #338) + +### 1.4.0 + +_2 May 2020_ + +- ✨ Deterministic builds. cibuildwheel now locks the versions of the tools it + uses. This means that pinning your version of cibuildwheel pins the versions + of pip, setuptools, manylinux etc. that are used under the hood. This should + make things more reliable. But note that we don't control the entire build + environment on macOS and Windows, where the version of Xcode and Visual + Studio can still effect things. + + This can be controlled using the [CIBW_DEPENDENCY_VERSIONS](https://cibuildwheel.readthedocs.io/en/stable/options/#dependency-versions) + and [manylinux image](https://cibuildwheel.readthedocs.io/en/stable/options/#manylinux-image) + options - if you always want to use the latest toolchain, you can still do + that, or you can specify your own pip constraints file and manylinux image. + (#256) +- ✨ Added `package_dir` command line option, meaning we now support building + a package that lives in a subdirectory and pulls in files from the wider + project. See [the `package_dir` option help](https://cibuildwheel.readthedocs.io/en/stable/options/#command-line-options) + for more information. + + Note that this change makes the working directory (where you call + cibuildwheel from) relevant on Linux, as it's considered the 'project' and + will be copied into the Docker container. If your builds are slower on this + version, that's likely the reason. `cd` to your project and then call + `cibuildwheel` from there. (#319, #295) +- 🛠 On macOS, we make `MACOSX_DEPLOYMENT_TARGET` default to `10.9` if it's + not set. This should make things more consistent between Python versions. +- 🛠 Dependency updates - CPython 3.7.7, CPython 2.7.18, Pypy 7.3.1. + ### 1.3.0 _12 March 2020_ diff --git a/cibuildwheel/__init__.py b/cibuildwheel/__init__.py index 19b4f1d6..8e3c933c 100644 --- a/cibuildwheel/__init__.py +++ b/cibuildwheel/__init__.py @@ -1 +1 @@ -__version__ = '1.3.0' +__version__ = '1.4.1' diff --git a/cibuildwheel/linux.py b/cibuildwheel/linux.py index 04b2a620..d30635c3 100644 --- a/cibuildwheel/linux.py +++ b/cibuildwheel/linux.py @@ -109,6 +109,7 @@ def build(options: BuildOptions): container_name = 'cibuildwheel-{}'.format(uuid.uuid4()) try: + shell_cmd = ['linux32', '/bin/bash'] if platform_tag.endswith("i686") else ['/bin/bash'] call(['docker', 'create', '--env', 'CIBUILDWHEEL', '--name', container_name, @@ -136,7 +137,7 @@ def build(options: BuildOptions): ) call( - ['docker', 'exec', '-i', container_name, '/bin/bash'], + ['docker', 'exec', '-i', container_name] + shell_cmd, universal_newlines=True, input=''' # give xtrace output an extra level of indent inside docker @@ -266,7 +267,7 @@ def build(options: BuildOptions): container_name + ':/output/.', os.path.abspath(options.output_dir)]) except subprocess.CalledProcessError as error: - troubleshoot(options.project_dir, error) + troubleshoot(options.package_dir, error) exit(1) finally: # Still gets executed, even when 'exit(1)' gets called diff --git a/cibuildwheel/macos.py b/cibuildwheel/macos.py index 599e9b23..8eb7984c 100644 --- a/cibuildwheel/macos.py +++ b/cibuildwheel/macos.py @@ -30,14 +30,14 @@ def get_python_configurations(build_selector): PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'identifier', 'url']) python_configurations = [ # CPython - PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.9.pkg'), + PythonConfiguration(version='2.7', identifier='cp27-macosx_x86_64', url='https://www.python.org/ftp/python/2.7.18/python-2.7.18-macosx10.9.pkg'), PythonConfiguration(version='3.5', identifier='cp35-macosx_x86_64', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'), PythonConfiguration(version='3.6', identifier='cp36-macosx_x86_64', url='https://www.python.org/ftp/python/3.6.8/python-3.6.8-macosx10.9.pkg'), - PythonConfiguration(version='3.7', identifier='cp37-macosx_x86_64', url='https://www.python.org/ftp/python/3.7.6/python-3.7.6-macosx10.9.pkg'), + PythonConfiguration(version='3.7', identifier='cp37-macosx_x86_64', url='https://www.python.org/ftp/python/3.7.7/python-3.7.7-macosx10.9.pkg'), PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.2/python-3.8.2-macosx10.9.pkg'), # PyPy - PythonConfiguration(version='2.7', identifier='pp27-macosx_x86_64', url='https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.3.0-osx64.tar.bz2'), - PythonConfiguration(version='3.6', identifier='pp36-macosx_x86_64', url='https://bitbucket.org/pypy/pypy/downloads/pypy3.6-v7.3.0-osx64.tar.bz2'), + PythonConfiguration(version='2.7', identifier='pp27-macosx_x86_64', url='https://downloads.python.org/pypy/pypy2.7-v7.3.1-osx64.tar.bz2'), + PythonConfiguration(version='3.6', identifier='pp36-macosx_x86_64', url='https://downloads.python.org/pypy/pypy3.6-v7.3.1-osx64.tar.bz2'), ] # skip builds as required @@ -74,7 +74,7 @@ def install_cpython(version, url): call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/']) # patch open ssl if version == '3.5': - open_ssl_patch_url = 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2t/patch-macos-python-%s-openssl-v1.0.2t.tar.gz' % version + open_ssl_patch_url = 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v1.0.2u/patch-macos-python-%s-openssl-v1.0.2u.tar.gz' % version download(open_ssl_patch_url, '/tmp/python-patch.tar.gz') call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/{}/'.format(version), '-xmf', '/tmp/python-patch.tar.gz']) @@ -95,12 +95,6 @@ def install_pypy(version, url): download(url, os.path.join("/tmp", pypy_tar_bz2)) call(['tar', '-C', '/tmp', '-xf', os.path.join("/tmp", pypy_tar_bz2)]) - # fix PyPy 7.3.0 bug resulting in wrong macOS platform tag - if "-v7.3.0-" in url and version[0] == '3': - patch_file = os.path.abspath(os.path.join(os.path.dirname(__file__), 'resources', 'pypy3.6.patch')) - sysconfigdata_file = os.path.join(installation_path, 'lib_pypy', '_sysconfigdata.py') - call(['patch', sysconfigdata_file, patch_file, '-N']) # Always has nonzero return code - installation_bin_path = os.path.join(installation_path, 'bin') python_executable = 'pypy3' if version[0] == '3' else 'pypy' pip_executable = 'pip3' if version[0] == '3' else 'pip' diff --git a/cibuildwheel/resources/constraints-python27.txt b/cibuildwheel/resources/constraints-python27.txt index 0154cf81..6da3b134 100644 --- a/cibuildwheel/resources/constraints-python27.txt +++ b/cibuildwheel/resources/constraints-python27.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile # To update, run: # -# bin/update_constraints +# bin/update_constraints.py # appdirs==1.4.3 # via virtualenv configparser==4.0.2 # via importlib-metadata @@ -10,17 +10,17 @@ contextlib2==0.6.0.post1 # via importlib-metadata, importlib-resources, virtual delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in distlib==0.3.0 # via virtualenv filelock==3.0.12 # via virtualenv -importlib-metadata==1.5.0 # via importlib-resources, virtualenv -importlib-resources==1.3.1 # via virtualenv +importlib-metadata==1.6.0 # via importlib-resources, virtualenv +importlib-resources==1.5.0 # via virtualenv pathlib2==2.3.5 # via importlib-metadata, importlib-resources, virtualenv scandir==1.10.0 # via pathlib2 singledispatch==3.4.0.3 # via importlib-resources six==1.14.0 # via pathlib2, virtualenv typing==3.7.4.1 # via importlib-resources -virtualenv==20.0.10 # via -r cibuildwheel/resources/constraints.in +virtualenv==20.0.18 # via -r cibuildwheel/resources/constraints.in wheel==0.34.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.0.2 # via -r cibuildwheel/resources/constraints.in -setuptools==44.0.0 # via -r cibuildwheel/resources/constraints.in +pip==20.1 # via -r cibuildwheel/resources/constraints.in +setuptools==44.1.0 # via -r cibuildwheel/resources/constraints.in diff --git a/cibuildwheel/resources/constraints-python35.txt b/cibuildwheel/resources/constraints-python35.txt index e6d35c5d..70591458 100644 --- a/cibuildwheel/resources/constraints-python35.txt +++ b/cibuildwheel/resources/constraints-python35.txt @@ -2,19 +2,19 @@ # This file is autogenerated by pip-compile # To update, run: # -# bin/update_constraints +# bin/update_constraints.py # appdirs==1.4.3 # via virtualenv delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in distlib==0.3.0 # via virtualenv filelock==3.0.12 # via virtualenv -importlib-metadata==1.5.0 # via importlib-resources, virtualenv -importlib-resources==1.3.1 # via virtualenv +importlib-metadata==1.6.0 # via importlib-resources, virtualenv +importlib-resources==1.5.0 # via virtualenv six==1.14.0 # via virtualenv -virtualenv==20.0.10 # via -r cibuildwheel/resources/constraints.in +virtualenv==20.0.18 # via -r cibuildwheel/resources/constraints.in wheel==0.34.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.0.2 # via -r cibuildwheel/resources/constraints.in -setuptools==46.0.0 # via -r cibuildwheel/resources/constraints.in +pip==20.1 # via -r cibuildwheel/resources/constraints.in +setuptools==46.1.3 # via -r cibuildwheel/resources/constraints.in diff --git a/cibuildwheel/resources/constraints-python36.txt b/cibuildwheel/resources/constraints-python36.txt index 1a0aa5a3..58776947 100644 --- a/cibuildwheel/resources/constraints-python36.txt +++ b/cibuildwheel/resources/constraints-python36.txt @@ -2,19 +2,19 @@ # This file is autogenerated by pip-compile # To update, run: # -# bin/update_constraints +# bin/update_constraints.py # appdirs==1.4.3 # via virtualenv delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in distlib==0.3.0 # via virtualenv filelock==3.0.12 # via virtualenv -importlib-metadata==1.5.0 # via importlib-resources, virtualenv -importlib-resources==1.3.1 # via virtualenv +importlib-metadata==1.6.0 # via importlib-resources, virtualenv +importlib-resources==1.5.0 # via virtualenv six==1.14.0 # via virtualenv -virtualenv==20.0.10 # via -r cibuildwheel/resources/constraints.in +virtualenv==20.0.18 # via -r cibuildwheel/resources/constraints.in wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate zipp==3.1.0 # via importlib-metadata, importlib-resources # The following packages are considered to be unsafe in a requirements file: -pip==20.0.2 # via -r cibuildwheel/resources/constraints.in -setuptools==46.0.0 # via -r cibuildwheel/resources/constraints.in +pip==20.1 # via -r cibuildwheel/resources/constraints.in +setuptools==46.1.3 # via -r cibuildwheel/resources/constraints.in diff --git a/cibuildwheel/resources/constraints.txt b/cibuildwheel/resources/constraints.txt index fd9e3eab..a9389c61 100644 --- a/cibuildwheel/resources/constraints.txt +++ b/cibuildwheel/resources/constraints.txt @@ -2,18 +2,18 @@ # This file is autogenerated by pip-compile # To update, run: # -# bin/update_constraints +# bin/update_constraints.py # appdirs==1.4.3 # via virtualenv delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in distlib==0.3.0 # via virtualenv filelock==3.0.12 # via virtualenv -importlib-metadata==1.5.0 # via virtualenv +importlib-metadata==1.6.0 # via virtualenv six==1.14.0 # via virtualenv -virtualenv==20.0.10 # via -r cibuildwheel/resources/constraints.in +virtualenv==20.0.18 # via -r cibuildwheel/resources/constraints.in wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate zipp==3.1.0 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: -pip==20.0.2 # via -r cibuildwheel/resources/constraints.in -setuptools==46.0.0 # via -r cibuildwheel/resources/constraints.in +pip==20.1 # via -r cibuildwheel/resources/constraints.in +setuptools==46.1.3 # via -r cibuildwheel/resources/constraints.in diff --git a/cibuildwheel/resources/pinned_docker_images.cfg b/cibuildwheel/resources/pinned_docker_images.cfg index 7cbcab64..bf161d3e 100644 --- a/cibuildwheel/resources/pinned_docker_images.cfg +++ b/cibuildwheel/resources/pinned_docker_images.cfg @@ -1,22 +1,22 @@ [x86_64] -manylinux1 = quay.io/pypa/manylinux1_x86_64:2020-03-07-9c5ba95 -manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-03-07-1825e8f -manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-03-07-06139da +manylinux1 = quay.io/pypa/manylinux1_x86_64:2020-04-25-37c204c +manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-04-29-0e1afc5 +manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-05-01-b37d76b [i686] -manylinux1 = quay.io/pypa/manylinux1_i686:2020-03-07-9c5ba95 -manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-03-07-1825e8f -manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-03-07-06139da +manylinux1 = quay.io/pypa/manylinux1_i686:2020-04-25-37c204c +manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-04-29-0e1afc5 +manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-05-01-b37d76b [pypy_x86_64] -manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:latest +manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-04-25-eb2cdff [aarch64] -manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-03-07-06139da +manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-05-01-b37d76b [ppc64le] -manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-03-07-06139da +manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-05-01-b37d76b [s390x] -manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-03-07-06139da +manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-05-01-b37d76b diff --git a/cibuildwheel/resources/pypy3.6.patch b/cibuildwheel/resources/pypy3.6.patch deleted file mode 100644 index b42d4bfd..00000000 --- a/cibuildwheel/resources/pypy3.6.patch +++ /dev/null @@ -1,7 +0,0 @@ ---- a/lib_pypy/_sysconfigdata.py Tue Jan 28 22:54:59 2020 +0200 -+++ b/lib_pypy/_sysconfigdata.py Wed Jan 29 19:21:23 2020 +0200 -@@ -47,4 +47,5 @@ - build_time_vars['CC'] += ' -arch %s' % (arch,) - if "CXX" in build_time_vars: - build_time_vars['CXX'] += ' -arch %s' % (arch,) -+ build_time_vars['MACOSX_DEPLOYMENT_TARGET'] = '10.7' diff --git a/cibuildwheel/windows.py b/cibuildwheel/windows.py index e6f14ed9..a389fac9 100644 --- a/cibuildwheel/windows.py +++ b/cibuildwheel/windows.py @@ -36,19 +36,19 @@ def get_python_configurations(build_selector): PythonConfiguration = namedtuple('PythonConfiguration', ['version', 'arch', 'identifier', 'url']) python_configurations = [ # CPython - PythonConfiguration(version='2.7.17', arch='32', identifier='cp27-win32', url=None), - PythonConfiguration(version='2.7.17', arch='64', identifier='cp27-win_amd64', url=None), + PythonConfiguration(version='2.7.18', arch='32', identifier='cp27-win32', url=None), + PythonConfiguration(version='2.7.18', arch='64', identifier='cp27-win_amd64', url=None), PythonConfiguration(version='3.5.4', arch='32', identifier='cp35-win32', url=None), PythonConfiguration(version='3.5.4', arch='64', identifier='cp35-win_amd64', url=None), PythonConfiguration(version='3.6.8', arch='32', identifier='cp36-win32', url=None), PythonConfiguration(version='3.6.8', arch='64', identifier='cp36-win_amd64', url=None), - PythonConfiguration(version='3.7.6', arch='32', identifier='cp37-win32', url=None), - PythonConfiguration(version='3.7.6', arch='64', identifier='cp37-win_amd64', url=None), + PythonConfiguration(version='3.7.7', arch='32', identifier='cp37-win32', url=None), + PythonConfiguration(version='3.7.7', arch='64', identifier='cp37-win_amd64', url=None), PythonConfiguration(version='3.8.2', arch='32', identifier='cp38-win32', url=None), PythonConfiguration(version='3.8.2', arch='64', identifier='cp38-win_amd64', url=None), # PyPy - PythonConfiguration(version='2.7', arch='32', identifier='pp27-win32', url='https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.3.0-win32.zip'), - PythonConfiguration(version='3.6', arch='32', identifier='pp36-win32', url='https://bitbucket.org/pypy/pypy/downloads/pypy3.6-v7.3.0-win32.zip'), + PythonConfiguration(version='2.7', arch='32', identifier='pp27-win32', url='https://downloads.python.org/pypy/pypy2.7-v7.3.1-win32.zip'), + PythonConfiguration(version='3.6', arch='32', identifier='pp36-win32', url='https://downloads.python.org/pypy/pypy3.6-v7.3.1-win32.zip'), ] if IS_RUNNING_ON_TRAVIS: @@ -86,7 +86,6 @@ def install_pypy(version, arch, url): extract_zip(pypy_zip, os.path.dirname(installation_path)) pypy_exe = 'pypy3.exe' if version[0] == '3' else 'pypy.exe' shell(['mklink', os.path.join(installation_path, 'python.exe'), os.path.join(installation_path, pypy_exe)]) - shell(['mklink', '/d', os.path.join(installation_path, 'Scripts'), os.path.join(installation_path, 'bin')]) return installation_path @@ -199,9 +198,6 @@ def build(options: BuildOptions): virtualenv_env = env.copy() venv_script_path = os.path.join(venv_dir, 'Scripts') - if os.path.exists(os.path.join(venv_dir, 'bin')): - # pypy2.7 bugfix - venv_script_path = os.pathsep.join([venv_script_path, os.path.join(venv_dir, 'bin')]) virtualenv_env['PATH'] = os.pathsep.join([ venv_script_path, virtualenv_env['PATH'], diff --git a/docs/cpp_standards.md b/docs/cpp_standards.md index 88ff6578..5dd83614 100644 --- a/docs/cpp_standards.md +++ b/docs/cpp_standards.md @@ -22,12 +22,22 @@ However, to enable modern C++ standards, the deploment target needs to be set hi To get C++11 and C++14 support, `MACOSX_DEPLOYMENT_TARGET` needs to be set to (at least) `"10.9"`. By default, `cibuildwheel` already does this, building 64-bit-only wheels for macOS 10.9 and later. -To get C++17 support, set `MACOSX_DEPLOYMENT_TARGET` to (at least) `"10.13"` or `"10.14"` (macOS 10.13 offers partial C++17 support; e.g., the filesystem header is in experimental, offering `#include ` instead of `#include `; macOS 10.14 has full C++17 support). +To get C++17 support, Xcode 9.3+ is needed, requiring at least macOS 10.13 on the build machine. To use C++17 library features and link against the C++ runtime library, set `MACOSX_DEPLOYMENT_TARGET` to `"10.13"` or `"10.14"` (or higher) - macOS 10.13 offers partial C++17 support (e.g., the filesystem header is in experimental, offering `#include ` instead of `#include `); macOS 10.14 has full C++17 support. -For more details see https://en.cppreference.com/w/cpp/compiler_support and https://xcodereleases.com/: Xcode 10 needs macOS 10.13 and Xcode 11 needs macOS 10.14. +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 -Visual C++ for Python 2.7 does not support modern standards of C++. When building on Appveyor, you will need to either use the "Visual Studio 2017" or "Visual Studio 2019" image, but Python 2.7 is not supported on these images - skip it by setting `CIBW_SKIP=cp27-win*`. +Visual C++ for Python 2.7 does not support modern C++ standards (i.e., C++11 and later). When building on Appveyor, you will need to either use the "Visual Studio 2017" or "Visual Studio 2019" image, but Python 2.7 is not supported on these images - skip it by setting `CIBW_SKIP=cp27-win*`. -There is an optional workaround for this, 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", since the newer C++ standard libraries are not included by default with the Python 2.7 installation. +There is an optional workaround for this, 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) and GitHub Actions has [an action `microsoft/setup-msbuild`](https://github.com/microsoft/setup-msbuild) that help setting up the Visual Studio environment. +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` enviroment (see previous step). diff --git a/examples/appveyor-minimal.yml b/examples/appveyor-minimal.yml index 3314fba6..3f89bce4 100644 --- a/examples/appveyor-minimal.yml +++ b/examples/appveyor-minimal.yml @@ -12,7 +12,7 @@ stack: python 3.7 init: - cmd: set PATH=C:\Python37;C:\Python37\Scripts;%PATH% -install: python -m pip install cibuildwheel==1.3.0 +install: python -m pip install cibuildwheel==1.4.1 build_script: python -m cibuildwheel --output-dir wheelhouse diff --git a/examples/azure-pipelines-minimal.yml b/examples/azure-pipelines-minimal.yml index 98cf1471..fbbdebb4 100644 --- a/examples/azure-pipelines-minimal.yml +++ b/examples/azure-pipelines-minimal.yml @@ -5,7 +5,7 @@ jobs: - task: UsePythonVersion@0 - bash: | python3 -m pip install --upgrade pip - pip3 install cibuildwheel==1.3.0 + pip3 install cibuildwheel==1.4.1 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} @@ -16,7 +16,7 @@ jobs: - task: UsePythonVersion@0 - bash: | python3 -m pip install --upgrade pip - pip3 install cibuildwheel==1.3.0 + pip3 install cibuildwheel==1.4.1 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} @@ -29,7 +29,7 @@ jobs: displayName: Install Visual C++ for Python 2.7 - bash: | python -m pip install --upgrade pip - pip install cibuildwheel==1.3.0 + pip install cibuildwheel==1.4.1 cibuildwheel --output-dir wheelhouse . - task: PublishBuildArtifacts@1 inputs: {pathtoPublish: 'wheelhouse'} diff --git a/examples/circleci-minimal.yml b/examples/circleci-minimal.yml index 7748d362..6794221c 100644 --- a/examples/circleci-minimal.yml +++ b/examples/circleci-minimal.yml @@ -11,7 +11,7 @@ jobs: - run: name: Build the Linux wheels. command: | - pip3 install --user cibuildwheel==1.3.0 + pip3 install --user cibuildwheel==1.4.1 cibuildwheel --output-dir wheelhouse - store_artifacts: path: wheelhouse/ @@ -25,7 +25,7 @@ jobs: - run: name: Build the OS X wheels. command: | - pip3 install --user cibuildwheel==1.3.0 + pip3 install --user cibuildwheel==1.4.1 cibuildwheel --output-dir wheelhouse - store_artifacts: path: wheelhouse/ diff --git a/examples/github-minimal.yml b/examples/github-minimal.yml index 30913057..988c2298 100644 --- a/examples/github-minimal.yml +++ b/examples/github-minimal.yml @@ -20,7 +20,7 @@ jobs: - name: Install cibuildwheel run: | - python -m pip install cibuildwheel==1.3.0 + python -m pip install cibuildwheel==1.4.1 - name: Install Visual C++ for Python 2.7 if: startsWith(matrix.os, 'windows') diff --git a/examples/travis-ci-deploy-only.yml b/examples/travis-ci-deploy-only.yml index a27968fe..cad4f5a3 100644 --- a/examples/travis-ci-deploy-only.yml +++ b/examples/travis-ci-deploy-only.yml @@ -25,7 +25,7 @@ env: # Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings install: - - python3 -m pip install cibuildwheel==1.3.0 + - python3 -m pip install cibuildwheel==1.4.1 script: # build the wheels, put them into './wheelhouse' diff --git a/examples/travis-ci-minimal.yml b/examples/travis-ci-minimal.yml index ede3d173..4fc41c49 100644 --- a/examples/travis-ci-minimal.yml +++ b/examples/travis-ci-minimal.yml @@ -26,7 +26,7 @@ jobs: - ln -s /c/Python38/python.exe /c/Python38/python3.exe install: - - python3 -m pip install cibuildwheel==1.3.0 + - python3 -m pip install cibuildwheel==1.4.1 script: # build the wheels, put them into './wheelhouse' diff --git a/examples/travis-ci-test-and-deploy.yml b/examples/travis-ci-test-and-deploy.yml index e20d2fad..eada75c8 100644 --- a/examples/travis-ci-test-and-deploy.yml +++ b/examples/travis-ci-test-and-deploy.yml @@ -55,7 +55,7 @@ jobs: - stage: deploy name: Build and deploy Linux wheels services: docker - install: python3 -m pip install cibuildwheel==1.3.0 + install: python3 -m pip install cibuildwheel==1.4.1 script: python3 -m cibuildwheel --output-dir wheelhouse after_success: | python3 -m pip install twine @@ -65,7 +65,7 @@ jobs: name: Build and deploy macOS wheels os: osx language: shell - install: python3 -m pip install cibuildwheel==1.3.0 + install: python3 -m pip install cibuildwheel==1.4.1 script: python3 -m cibuildwheel --output-dir wheelhouse after_success: | python3 -m pip install twine @@ -75,7 +75,7 @@ jobs: name: Build and deploy Windows wheels os: windows language: shell - install: python3 -m pip install cibuildwheel==1.3.0 + install: python3 -m pip install cibuildwheel==1.4.1 script: python3 -m cibuildwheel --output-dir wheelhouse after_success: | python3 -m pip install twine diff --git a/mkdocs.yml b/mkdocs.yml index 5c12f501..4a10a6d9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,6 +28,8 @@ markdown_extensions: permalink: True - attr_list - admonition + - pymdownx.magiclink: + repo_url_shortener: True plugins: - importmarkdown diff --git a/requirements-dev.txt b/requirements-dev.txt index f838e3f2..44043506 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,6 +2,7 @@ -e ./docs/mkdocs_include_markdown_plugin pytest mkdocs==1.0.4 +pymdown-extensions pip-tools requests click diff --git a/setup.py b/setup.py index 4c721135..143e313c 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ with io.open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f: setup( name='cibuildwheel', - version='1.3.0', + version='1.4.1', install_requires=['bashlex!=0.13'], description="Build Python wheels on CI with minimal configuration.", long_description=long_description, diff --git a/test/test_cpp_standards.py b/test/test_cpp_standards.py index 3cc18917..5c73a9bc 100644 --- a/test/test_cpp_standards.py +++ b/test/test_cpp_standards.py @@ -105,14 +105,12 @@ def test_cpp14(tmp_path): # VC++ for Python 2.7 does not support modern standards # The manylinux1 docker image does not have a compiler which supports C++11 - # Python 3.4 and 3.5 are compiled with MSVC 10, which does not support C++14 - add_env = {'CIBW_SKIP': 'cp27-win* pp27-win32 cp35-win*'} + 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 - and 'cp35-cp35m-win' not in w] + and 'pp27-pypy_73-win32' not in w] assert set(actual_wheels) == set(expected_wheels) @@ -139,7 +137,7 @@ def test_cpp17(tmp_path): if os.environ.get('APPVEYOR_BUILD_WORKER_IMAGE', '') == 'Visual Studio 2015': pytest.skip('Visual Studio 2015 does not support C++17') - add_env = {'CIBW_SKIP': 'cp27-win* pp27-win32 cp35-win* pp36-win32'} + add_env = {'CIBW_SKIP': 'cp27-win* pp27-win32'} if utils.platform == 'macos': add_env['MACOSX_DEPLOYMENT_TARGET'] = '10.13' @@ -147,8 +145,56 @@ def test_cpp17(tmp_path): actual_wheels = utils.cibuildwheel_run(project_dir, add_env=add_env) 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 'pp27-pypy_73-win32' not in w - and 'cp35-cp35m-win' not in w - and 'pp36-pypy36_pp73-win32' not in w] + and 'pp27-pypy_73-win32' not in w] + + assert set(actual_wheels) == set(expected_wheels) + + +def test_cpp17_py27_modern_msvc_workaround(): + # 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') + + # 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 = {'CIBW_ENVIRONMENT': 'STANDARD=17', + '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') + if 'cp27-cp27m-win' in w + or 'pp27-pypy_73-win32' in w] assert set(actual_wheels) == set(expected_wheels) diff --git a/test/test_testing.py b/test/test_testing.py index ed60fded..64ad4bac 100644 --- a/test/test_testing.py +++ b/test/test_testing.py @@ -15,13 +15,52 @@ project_with_a_test = CTemplateProject( ) project_with_a_test.files['test/spam_test.py'] = r''' +import os +import platform +import sys +import struct from unittest import TestCase + import spam + +def path_contains(parent, child): + """ returns True if `child` is inside `parent`. + Works around path-comparison bugs caused by short-paths on Windows e.g. + vssadm~1 instead of vssadministrator + """ + parent = os.path.abspath(parent) + child = os.path.abspath(child) + + while child != os.path.dirname(child): + child = os.path.dirname(child) + if os.stat(parent) == os.stat(child): + # parent and child refer to the same directory on the filesystem + return True + return False + + class TestSpam(TestCase): def test_system(self): self.assertEqual(0, spam.system('python -c "exit(0)"')) self.assertNotEqual(0, spam.system('python -c "exit(1)"')) + + def test_virtualenv(self): + virtualenv_path = os.environ.get("__CIBW_VIRTUALENV_PATH__") + if not virtualenv_path: + self.fail("No virtualenv path defined in environment variable __CIBW_VIRTUALENV_PATH__") + + self.assertTrue(path_contains(virtualenv_path, sys.executable)) + self.assertTrue(path_contains(virtualenv_path, spam.__file__)) + + def test_uname(self): + if platform.system() == "Windows": + return + # if we're running in 32-bit Python, check that the machine is i686. + # See #336 for more info. + bits = struct.calcsize("P") * 8 + if bits == 32: + self.assertEqual(platform.machine(), "i686") '''