Compare commits

...
82 Commits
Author SHA1 Message Date
Joe Rickerby 200d4af89c Bump version: v1.6.0 2020-09-09 08:57:25 +01:00
Joe Rickerby 48d77c7edf Merge pull request #425 from joerick/update-constraints-2020-09-07T21-18-26
Update dependencies
2020-09-08 08:40:30 +01:00
Joe Rickerby 0b9a3e8afd Update dependencies 2020-09-07 22:18:40 +01:00
Joe Rickerby a2a8655c43 Merge pull request #419 from joerick/gitlab-ci
Add Gitlab CI
2020-09-07 22:16:42 +01:00
Joe Rickerby 4b5ac4ecbb Merge remote-tracking branch 'origin/master' into gitlab-ci 2020-09-07 20:25:14 +01:00
Joe Rickerby 8a434b1759 Merge pull request #382 from joerick/python3.9
Add python3.9 support
2020-09-07 20:10:56 +01:00
Yannick Jadoul 2a62198b47 Update docker images again 2020-09-06 23:56:21 +02:00
Yannick Jadoul 28de36ea6f Adapt README to fully support Python 3.9 2020-09-06 23:55:04 +02:00
Joe Rickerby c3caa5f26f Add maintainer tools docs 2020-09-06 16:58:13 +01:00
Joe Rickerby 6840c9cea1 Add docs for linux-only Gitlab CI 2020-09-02 19:53:03 +01:00
Joe Rickerby c67da48510 Remove Windows Gitlab support 2020-09-02 19:43:12 +01:00
Joe Rickerby 9a444b1ab8 Install vcpython27 while working around the dotnet3.5 install error 2020-09-01 22:45:46 +01:00
Joe Rickerby 10585d2882 Use Powershell syntax for changing PATH 2020-09-01 21:25:01 +01:00
Joe Rickerby 2fbaa36286 Use cmd syntax to change PATH 2020-08-31 21:02:19 +01:00
Joe Rickerby 4433ea4de1 Add missing cibuildwheel install line 2020-08-31 20:46:15 +01:00
Joe Rickerby 5c5d1ef10a Fix Gitlab Windows config 2020-08-31 20:44:25 +01:00
Joe Rickerby 734dea7526 Fix config path 2020-08-31 19:34:00 +01:00
Joe Rickerby 188eaa8a93 Add gitlab config 2020-08-31 19:32:45 +01:00
Joe Rickerby 8e0ee0a4ab Improve script output formatting 2020-08-31 18:59:32 +01:00
Joe Rickerby 84446ed1a9 Attempt a fix for the CircleCI minimal example 2020-08-31 18:52:20 +01:00
Joe Rickerby a4699f4cc8 Fix flake8 error 2020-08-30 12:12:06 +01:00
Joe Rickerby ac90f2b9ac Add CI example test script 2020-08-30 12:08:58 +01:00
Yannick Jadoul 3a984346dd Merge pull request #424 from YannickJadoul/docs-vc++-runtime
Add section to the docs' FAQ about VC++ runtimes and VCRUNTIME140_1.dll on VS2019
2020-08-29 20:17:12 +02:00
Yannick Jadoul b448271640 Fix typos 2020-08-28 17:09:49 +02:00
Yannick Jadoul e0dd32dea8 Extend explanation about versions of Python and versions of VC++ redistributable files 2020-08-28 16:16:14 +02:00
Yannick Jadoul fbb4e28b44 Add section to the docs' FAQ about VC++ runtimes and VCRUNTIME140_1.dll on VS2019 2020-08-28 01:52:04 +02:00
Yannick Jadoul aafdff7ec7 Merge pull request #420 from henryiii/fix/exfile
fix: Windows extra file
2020-08-16 23:03:18 +02:00
Yannick Jadoul e6e8cb79fc Merge pull request #422 from henryiii/ci/format
ci: format updates
2020-08-16 23:02:19 +02:00
Henry SchreinerandJoe Rickerby a0d67a7a90 ci: suggestion from @joerick
Co-authored-by: Joe Rickerby <joerick@mac.com>
2020-08-16 14:15:28 -04:00
Henry Schreiner fd2b5d3270 refactor: minor tweaks from @joerick 2020-08-16 14:05:39 -04:00
Henry Schreiner 416c6f3a3c fix: file method of requirement installs 2020-08-14 17:12:40 -04:00
Henry Schreiner 9df68df525 style: add a few more checks 2020-08-14 16:12:24 -04:00
Henry Schreiner 45074a9b3a fix: add extra space after ] 2020-08-14 15:57:42 -04:00
Henry Schreiner 448d6538d7 chore: run pre-commit autoupdate 2020-08-14 15:56:06 -04:00
Henry Schreiner 17c83ad78b ci: move formatting check to pre-commit + GitHub 2020-08-14 15:56:05 -04:00
Henry Schreiner 6d6d277ea5 fix: pre-commit check was broken 2020-08-14 15:49:56 -04:00
Joe Rickerby d36b2d35c6 fix PYTHON variable 2020-08-14 11:42:25 +01:00
Joe Rickerby efa1958023 Add a windows gitlab implementation 2020-08-14 09:51:30 +00:00
Yannick Jadoul a345008626 Update all, except ppc64le on manylinux2014, to Python 3.9 rc1 2020-08-13 17:28:09 +02:00
Joe Rickerby 43abc35259 Merge pull request #418 from joerick/add-troubleshoot-test
Add troubleshoot test
2020-08-13 15:19:26 +01:00
Joe Rickerby 2942c99ce4 docker tweaks 2020-08-13 13:58:14 +01:00
Joe Rickerby 3c577ab036 Add docker config 2020-08-13 13:49:52 +01:00
Joe Rickerby 8ce553b2ea Tweak config 2020-08-13 13:42:52 +01:00
Joe Rickerby 48c23b10d0 Move gitlab config to the right location 2020-08-13 13:36:48 +01:00
Joe Rickerby 442174157a Add a test Gitlab CI config 2020-08-13 12:15:53 +01:00
Joe Rickerby f19c606573 Fix comment 2020-08-13 11:50:17 +01:00
Joe Rickerby ac3523132d Add troubleshoot test 2020-08-13 11:46:39 +01:00
stfbncandYannick Jadoul a7ea9f42cb added fathon repository to README (#415)
* added fathon repository to README

* accidental error fixed

* Undo line break change to changelog in README

Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net>
2020-08-04 23:26:48 +02:00
Joe Rickerby 1059249f4d Update to Python 3.9.0b5 2020-08-03 17:45:27 +01:00
Joe Rickerby 516f4b9d7e Merge pull request #414 from joerick/pure-wheel-error
Raise an error when cibuildwheel produces a non-platform wheel
2020-07-24 20:53:29 +01:00
Joe Rickerby ebf56281ed Add pure wheel detection, and failing with an error in this case 2020-07-24 15:54:31 +01:00
Joe Rickerby 0896566743 Merge remote-tracking branch 'origin/master' into python3.9 2020-07-24 15:35:31 +01:00
Joe Rickerby fd92707823 Merge pull request #413 from Czaki/project_path_to_var
use variable instead of '/project' literal
2020-07-24 15:27:36 +01:00
Grzegorz Bokota cfec077f05 change project_path to container_project_path 2020-07-23 20:24:19 +02:00
Joe Rickerby 5c4767899d Bump version: v1.5.5 2020-07-22 18:57:47 +01:00
Grzegorz Bokota a15ccb6ef0 change project_path to PurePath 2020-07-22 17:26:25 +02:00
Grzegorz Bokota ae6d65e62e use variable instead on '/project' literal 2020-07-22 15:27:51 +02:00
Yannick Jadoul 3cd3a9dc77 Merge pull request #410 from YannickJadoul/fix-pwd-linux-docker
Fix cwd in Linux docker images
2020-07-22 14:41:16 +02:00
Yannick Jadoul 9e40094cfc Make timeout 2 hours on GitHub Actions and Azure Pipelines because of slow Windows jobs 2020-07-21 23:13:55 +02:00
Yannick Jadoul c91d669a90 Extend tests and add tests for CIBW_BEFORE_ALL 2020-07-21 20:12:28 +02:00
Yannick Jadoul f81c9474d6 Fix test_before_build test on Windows 2020-07-20 18:07:45 +02:00
Yannick Jadoul 2610f3220a Run Linux docker images with /project as cwd 2020-07-20 18:07:45 +02:00
Yannick Jadoul 29b0cdb08a Add cwd argument to DockerContainer 2020-07-20 18:07:45 +02:00
Yannick Jadoul 2b7da3fcbe Test whether CIBW_BEFORE_BUILD is executed from the right directory and confirm it is not 2020-07-20 18:07:45 +02:00
Joe Rickerby 726bcdf372 Merge pull request #411 from YannickJadoul/fix-docker-commandsubstitution
Fix command substitution in CIBW_ENVIRONMENT in Linux docker images
2020-07-20 16:38:30 +01:00
Yannick Jadoul 3142806f4b Capture output in DockerContainer.environment_executor to fix command substitutions in CIBW_ENVIRONMENT on Linux 2020-07-20 02:23:07 +02:00
Yannick Jadoul e28e43e7f9 Fix test_environment's checks on a command substitution in an environment 2020-07-20 02:02:50 +02:00
Joe Rickerby c0cb43800b Bump version: v1.5.4 2020-07-19 22:40:33 +01:00
Joe Rickerby cc4e8975c8 Merge pull request #408 from YannickJadoul/fix-bashlex_eval-quotes
Fix quotes in command in bashlex_eval
2020-07-19 19:47:05 +01:00
Joe Rickerby c5a9837784 Update cibuildwheel/bashlex_eval.py 2020-07-19 19:46:40 +01:00
Joe Rickerby ceecee0e68 Merge pull request #407 from samuelstjean/patch-1
fix typo in doc
2020-07-19 19:40:48 +01:00
Yannick Jadoul 28af49a006 Simplify by removing shlex.quote and shlex.split when using EnvironmentExecutor 2020-07-19 17:37:25 +02:00
Yannick Jadoul 3a2d7a21b1 Fix quotes-in-commandsubstitution problem with well-placed shlex.quote 2020-07-19 17:32:07 +02:00
Yannick Jadoul 44fd8b5c26 Fix test to demonstrate failure 2020-07-19 17:19:48 +02:00
Samuel St-Jean fddfaba0a4 fix typo 2020-07-19 10:32:27 -04:00
Yannick Jadoul 737ad6b650 Merge pull request #395 from mayeut/python3.9-s390x
Update dependencies to get python 3.9 support on s390x
2020-07-05 21:10:54 +02:00
mayeut 472eb898ed Update dependencies to get python 3.9 support on s390x 2020-07-05 11:02:18 +02:00
Yannick Jadoul 98db24f92c Merge pull request #377 from YannickJadoul/python3.9
Add Python 3.9 (beta 3) to builds
2020-06-22 12:18:08 +02:00
Yannick Jadoul 29b25a3ab6 Update manylinux docker image versions, again 2020-06-18 23:49:14 +02:00
Yannick Jadoul 5a6f35fe76 Skip Python 3.9 in test_docker_images.py until dockcross catches up 2020-06-18 23:14:59 +02:00
Yannick Jadoul 03ae918ec5 Update manylinux docker image versions 2020-06-18 00:23:41 +02:00
Yannick Jadoul 94dead9440 Add Python 3.9 (beta 3) to builds 2020-06-18 00:23:41 +02:00
47 changed files with 633 additions and 166 deletions
-17
View File
@@ -1,22 +1,6 @@
version: 2
jobs:
flake8-mypy:
docker:
- image: circleci/python:3.6
steps:
- checkout
- run:
name: Install flake8 & mypy
command: sudo python -m pip install flake8 mypy
- run:
name: flake8
command: flake8
- run:
name: mypy
command: mypy
osx-python3.6:
macos:
xcode: "9.4.1"
@@ -54,6 +38,5 @@ workflows:
version: 2
all-tests:
jobs:
- flake8-mypy
- osx-python3.6
- linux-python3.6
+9
View File
@@ -7,6 +7,14 @@ on:
- 'docs/**'
jobs:
pre-commit:
name: Pre-commit checks (mypy, flake8, etc.)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: pre-commit/action@v2.0.0
test:
# skip branch builds on joerick/cibuildwheel, but always build `master` and pull requests
if: github.repository != 'joerick/cibuildwheel' || github.ref == 'refs/heads/master' || github.event_name == 'pull_request'
@@ -17,6 +25,7 @@ jobs:
matrix:
os: [ubuntu-18.04, windows-latest, macos-latest]
python_version: ['3.7']
timeout-minutes: 180
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
+15
View File
@@ -0,0 +1,15 @@
linux:
image: python:3.8
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install -r requirements-dev.txt
- python ./bin/run_tests.py
+24 -20
View File
@@ -1,21 +1,25 @@
repos:
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.1
hooks:
- id: flake8
pass_filenames: true
# this seems to need to be here in addition to setup.cfg
exclude: cibuildwheel/resources/
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: check-merge-conflict
- id: end-of-file-fixer
exclude: cibuildwheel/resources/pinned_docker_images.cfg
- repo: https://github.com/pre-commit/mirrors-mypy
rev: '' # Use the sha / tag you want to point at
hooks:
- id: mypy
files: cibuildwheel|test
exclude: cibuildwheel/resources
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.3
hooks:
- id: flake8
exclude: cibuildwheel/resources/
additional_dependencies: [flake8-bugbear]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: check-case-conflict
- id: check-merge-conflict
- id: check-yaml
- id: end-of-file-fixer
exclude: cibuildwheel/resources/pinned_docker_images.cfg
- id: mixed-line-ending
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.782
hooks:
- id: mypy
files: cibuildwheel/|test/
pass_filenames: false
+52 -13
View File
@@ -17,18 +17,19 @@ What does it do?
| | macOS x86_64 | Windows 64bit | Windows 32bit | manylinux x86_64 | manylinux i686 | manylinux aarch64 | manylinux ppc64le | manylinux s390x |
|---|---|---|---|---|---|---|---|---|
| CPython 2.7 | ✅ | ✅¹ | ✅¹ | ✅ | ✅ | | | |
| CPython 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² |
| CPython 3.9³ | 🛠 | 🛠 | 🛠 | 🛠 | 🛠 | 🛠 | 🛠 | |
| PyPy 2.7 v7.3.0 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.6 v7.3.0 | ✅ | | ✅ | ✅ | | | | |
| CPython 2.7 | ✅ | ✅¹ | ✅¹ | ✅ | ✅ | | | |
| CPython 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.7 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅² | ✅² | ✅³ |
| CPython 3.9 | | | | | | ✅² | ✅⁴ | ✅³ |
| PyPy 2.7 v7.3.0 | ✅ | | ✅ | ✅ | | | | |
| PyPy 3.6 v7.3.0 | ✅ | | ✅ | ✅ | | | | |
<sup>¹ Not supported on Travis</sup><br>
<sup>² Beta support until Travis CI fixes <a href="https://travis-ci.community/t/no-space-left-on-device-for-system-z/5954/11">a bug</a></sup><br>
<sup>³ Python 3.9 is not yet ABI stable, so you shouldn't publish wheels with it yet. But if you want to check that your wheels build on Python 3.9, try our [`python3.9` branch](https://github.com/joerick/cibuildwheel/pull/382)!</sup>
<sup>² Only supported on Travis</sup><br>
<sup>³ Beta support until Travis CI fixes <a href="https://travis-ci.community/t/no-space-left-on-device-for-system-z/5954/11">a bug</a></sup><br>
<sup>⁴ Only Python 3.9 beta 3 is supported, until <a href="https://github.com/pypa/manylinux/issues/758">a bug</a> in building the manylinux2014 is fixed</sup><br>
- Builds manylinux, macOS and Windows wheels for CPython and PyPy using Azure Pipelines, Travis CI, AppVeyor, and CircleCI
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
@@ -37,7 +38,7 @@ What does it do?
Usage
-----
`cibuildwheel` currently works on **Travis CI**, **Azure Pipelines**, **AppVeyor** and **GitHub Actions** to build wheels for all three supported platforms (Linux, macOS, Windows). On **CircleCI** Linux and macOS wheels can be built.
`cibuildwheel` currently works on **Travis CI**, **Azure Pipelines**, **AppVeyor**, **GitHub Actions**, **CircleCI**, and **Gitlab CI**. Check the table below for supported platforms on each service:
| | Linux | macOS | Windows |
|-----------------|-------|-------|---------|
@@ -46,8 +47,9 @@ Usage
| AppVeyor | ✅ | ✅ | ✅ |
| GitHub Actions | ✅ | ✅ | ✅ |
| CircleCI | ✅ | ✅ | |
| Gitlab CI | ✅ | | |
`cibuildwheel` is not intended to run on your development machine. Because it uses system Python from Python.org it will try to install packages globally - not what you expect from a build tool! Instead, isolated CI services like Travis CI, CircleCI, Azure Pipelines and AppVeyor are ideal.
`cibuildwheel` is not intended to run on your development machine. Because it uses system Python from Python.org it will try to install packages globally - not what you expect from a build tool! Instead, isolated CI services like those mentioned above are ideal.
<!--intro-end-->
@@ -79,7 +81,7 @@ env:
# Note: TWINE_PASSWORD is set to a PyPI API token in Travis settings
install:
- python3 -m pip install cibuildwheel==1.5.3
- python3 -m pip install cibuildwheel==1.6.0
script:
# build the wheels, put them into './wheelhouse'
@@ -137,6 +139,7 @@ Here are some repos that use cibuildwheel.
- [aiortc](https://github.com/aiortc/aiortc)
- [aioquic](https://github.com/aiortc/aioquic)
- [pikepdf](https://github.com/pikepdf/pikepdf)
- [fathon](https://github.com/stfbnc/fathon)
> Add your repo here! Send a PR.
@@ -152,6 +155,42 @@ This is similar to static linking, so it might have some licence implications. C
Changelog
=========
### 1.6.0
_9 September 2020_
- 🌟 Add Python 3.9 support! This initial support uses release candidate
builds. You should can preparing your library for Python 3.9 now, ahead of
the official release. (#382)
Minor note - if you're building PPC64LE wheels, the manylinux image pinned
by this version is
[still on Python 3.9b3](https://github.com/pypa/manylinux/issues/758), not a
release candidate. We'd advise holding off on distributing 3.9 ppc64le wheels
until a subsequent version of cibuildwheel.
- 🌟 Add Gitlab CI support. Gitlab CI can now build Linux wheels, using
cibuildwheel. (#419)
- 🐛 Fix a bug that causes pyproject.toml dependencies to fail to install on
Windows (#420)
- 📚 Added some information about Windows VC++ runtimes and how they relate
to wheels.
### 1.5.5
_22 July 2020_
- 🐛 Fix a bug that would cause command substitutions in CIBW_ENVIRONMENT to
produce no output on Linux (#411)
- 🐛 Fix regression (introduced in 1.5.3) which caused BEFORE_BUILD and
BEFORE_ALL to be executed in the wrong directory (#410)
### 1.5.4
_19 June 2020_
- 🐛 Fix a bug that would cause command substitutions in CIBW_ENVIRONMENT
variables to not interpret quotes in commands correctly (#406, #408)
### 1.5.3
_19 July 2020_
+3 -3
View File
@@ -1,5 +1,5 @@
environment:
# workaround an appveyor bug on macos
# workaround an appveyor bug on macos
# see https://github.com/appveyor/ci/issues/3376#issuecomment-611314299
APPVEYOR_CONSOLE_DISABLE_PTY: true
matrix:
@@ -11,8 +11,8 @@ environment:
APPVEYOR_JOB_NAME: "python37-x64-macos-mojave"
# while pypy libffi dependency is failing the build, allow failures on macos
matrix:
allow_failures:
matrix:
allow_failures:
- APPVEYOR_BUILD_WORKER_IMAGE: macos-mojave
stack: python 3.7
+2
View File
@@ -21,6 +21,7 @@ jobs:
- job: windows_36
pool: {vmImage: 'vs2017-win2016'}
timeoutInMinutes: 180
steps:
- task: UsePythonVersion@0
inputs:
@@ -33,6 +34,7 @@ jobs:
- job: windows_38
pool: {vmImage: 'vs2017-win2016'}
timeoutInMinutes: 180
steps:
- task: UsePythonVersion@0
inputs:
+137
View File
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
import os
from pathlib import Path
import shutil
from subprocess import run
import sys
import textwrap
import time
import click
from collections import namedtuple
from urllib.parse import quote
def shell(cmd, **kwargs):
return run([cmd], shell=True, **kwargs)
def git_repo_has_changes():
unstaged_changes = shell('git diff-index --quiet HEAD --').returncode != 0
staged_changes = shell('git diff-index --quiet --cached HEAD --').returncode != 0
return unstaged_changes or staged_changes
def generate_basic_project(path):
sys.path.insert(0, '')
from test.test_projects.c import new_c_project
project = new_c_project()
project.generate(path)
CIService = namedtuple('CIService', 'name src_config_path dst_config_path badge_md')
services = [
CIService(
name='appveyor',
src_config_path='examples/appveyor-minimal.yml',
dst_config_path='appveyor.yml',
badge_md='[![Build status](https://ci.appveyor.com/api/projects/status/wbsgxshp05tt1tif/branch/{branch}?svg=true)](https://ci.appveyor.com/project/joerick/cibuildwheel/branch/{branch})',
),
CIService(
name='azure-pipelines',
src_config_path='examples/azure-pipelines-minimal.yml',
dst_config_path='azure-pipelines.yml',
badge_md='[![Build Status](https://dev.azure.com/joerick0429/cibuildwheel/_apis/build/status/joerick.cibuildwheel?branchName={branch})](https://dev.azure.com/joerick0429/cibuildwheel/_build/latest?definitionId=2&branchName={branch})',
),
CIService(
name='circle-ci',
src_config_path='examples/circleci-minimal.yml',
dst_config_path='.circleci/config.yml',
badge_md='[![CircleCI](https://circleci.com/gh/joerick/cibuildwheel/tree/{branch_escaped}.svg?style=svg)](https://circleci.com/gh/joerick/cibuildwheel/tree/{branch})',
),
CIService(
name='github',
src_config_path='examples/github-minimal.yml',
dst_config_path='.github/workflows/example.yml',
badge_md='[![Build](https://github.com/joerick/cibuildwheel/workflows/Build/badge.svg?branch={branch})](https://github.com/joerick/cibuildwheel/actions)',
),
CIService(
name='travis-ci',
src_config_path='examples/travis-ci-minimal.yml',
dst_config_path='.travis.yml',
badge_md='[![Build Status](https://travis-ci.org/joerick/cibuildwheel.svg?branch={branch})](https://travis-ci.org/joerick/cibuildwheel)',
),
CIService(
name='gitlab',
src_config_path='examples/gitlab-minimal.yml',
dst_config_path='.gitlab-ci.yml',
badge_md='[![Gitlab](https://gitlab.com/joerick/cibuildwheel/badges/{branch}/pipeline.svg)](https://gitlab.com/joerick/cibuildwheel/-/commits/{branch})'
),
]
@click.command()
def run_example_ci_configs():
if git_repo_has_changes():
print('Your git repo has uncommitted changes. Commit or stash before continuing.')
exit(1)
previous_branch = shell('git rev-parse --abbrev-ref HEAD',
check=True,
capture_output=True,
encoding='utf8').stdout.strip()
timestamp = time.strftime('%Y-%m-%dT%H-%M-%S', time.gmtime())
branch_name = f'example-config-test---{previous_branch}-{timestamp}'
try:
shell(f'git checkout --orphan {branch_name}', check=True)
example_project = Path('example_root')
generate_basic_project(example_project)
for service in services:
src_config_file = Path(service.src_config_path)
dst_config_file = example_project / service.dst_config_path
dst_config_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(src_config_file, dst_config_file)
run(['git', 'add', example_project], check=True)
run(['git', 'commit', '-m', textwrap.dedent(f'''
Test example minimal configs
Testing files: {[s.src_config_path for s in services]}
Generated from branch: {previous_branch}
Time: {timestamp}
''')], check=True)
shell(f'git subtree --prefix={example_project} push origin {branch_name}', check=True)
print('---')
print()
print('> **Examples test run**')
print('> ')
print(f'> Branch: [{branch_name}](https://github.com/joerick/cibuildwheel/tree/{branch_name})')
print('> ')
print('> | Service | Config | Status |')
print('> |---|---|---|')
for service in services:
badge = service.badge_md.format(branch=branch_name, branch_escaped=quote(branch_name, safe=''))
print(f'> | {service.name} | `{service.src_config_path}` | {badge} |')
print('> ')
print('> Generated by `bin/run_example_ci_config.py`')
print()
print('---')
finally:
# remove any local changes
shutil.rmtree(example_project, ignore_errors=True)
shell('git checkout -- .')
shell(f'git checkout {previous_branch}', check=True)
shell(f'git branch -D --force {branch_name}', check=True)
if __name__ == '__main__':
os.chdir(os.path.dirname(__file__))
os.chdir('..')
run_example_ci_configs(standalone_mode=True)
+1 -1
View File
@@ -1 +1 @@
__version__ = '1.5.3'
__version__ = '1.6.0'
+5 -7
View File
@@ -1,15 +1,14 @@
import shlex
import subprocess
from typing import Callable, Dict, List, NamedTuple, Optional, Sequence
import bashlex # type: ignore
# a function that takes a shell command and the environment, and returns the result
EnvironmentExecutor = Callable[[str, Dict[str, str]], str]
# a function that takes a command and the environment, and returns the result
EnvironmentExecutor = Callable[[List[str], Dict[str, str]], str]
def local_environment_executor(command: str, env: Dict[str, str]) -> str:
return subprocess.check_output(shlex.split(command), env=env, universal_newlines=True)
def local_environment_executor(command: List[str], env: Dict[str, str]) -> str:
return subprocess.check_output(command, env=env, universal_newlines=True)
class NodeExecutionContext(NamedTuple):
@@ -97,8 +96,7 @@ def evaluate_nodes_as_compound_command(nodes: Sequence[bashlex.ast.node], contex
def evaluate_nodes_as_simple_command(nodes: List[bashlex.ast.node], context: NodeExecutionContext):
words = [evaluate_node(part, context=context) for part in nodes]
command = ' '.join(words)
command = [evaluate_node(part, context=context) for part in nodes]
return context.executor(command, context.environment)
+9 -5
View File
@@ -27,12 +27,14 @@ class DockerContainer:
bash_stdin: IO[bytes]
bash_stdout: IO[bytes]
def __init__(self, docker_image: str, simulate_32_bit=False):
def __init__(self, docker_image: str, simulate_32_bit: bool = False, cwd: Optional[Union[str, PathLike]] = None):
self.docker_image = docker_image
self.simulate_32_bit = simulate_32_bit
self.cwd = cwd
def __enter__(self) -> 'DockerContainer':
self.name = f'cibuildwheel-{uuid.uuid4()}'
cwd_args = ['-w', str(self.cwd)] if self.cwd else []
shell_args = ['linux32', '/bin/bash'] if self.simulate_32_bit else ['/bin/bash']
subprocess.run(
[
@@ -41,6 +43,7 @@ class DockerContainer:
'--name', self.name,
'-i',
'-v', '/:/host', # ignored on CircleCI
*cwd_args,
self.docker_image,
*shell_args
],
@@ -114,11 +117,12 @@ class DockerContainer:
return [PurePath(p) for p in path_strs]
def call(self, args: Sequence[Union[str, PathLike]], env: Dict[str, str] = {},
def call(self, args: Sequence[Union[str, PathLike]], env: Optional[Dict[str, str]] = None,
capture_output=False, cwd: Optional[Union[str, PathLike]] = None) -> str:
chdir = f'cd {cwd}' if cwd else ''
env_assignments = ' '.join(f'{shlex.quote(k)}={shlex.quote(v)}'
for k, v in env.items())
for k, v in env.items()) if env is not None else ''
command = ' '.join(shlex.quote(str(a)) for a in args)
end_of_message = str(uuid.uuid4())
@@ -180,9 +184,9 @@ class DockerContainer:
'import sys, json, os; json.dump(os.environ.copy(), sys.stdout)'
], capture_output=True))
def environment_executor(self, command: str, environment: Dict[str, str]) -> str:
def environment_executor(self, command: List[str], environment: Dict[str, str]) -> str:
# used as an EnvironmentExecutor to evaluate commands and capture output
return self.call(shlex.split(command), env=environment)
return self.call(command, env=environment, capture_output=True)
def shell_quote(path: PurePath) -> str:
+23 -14
View File
@@ -7,7 +7,7 @@ from pathlib import Path, PurePath
from typing import List, NamedTuple, Union
from .docker_container import DockerContainer
from .util import (BuildOptions, BuildSelector,
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError,
get_build_verbosity_extra_flags, prepare_command)
@@ -50,26 +50,31 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.6', identifier='cp36-manylinux_x86_64', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_x86_64', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_x86_64', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_x86_64', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='2.7', identifier='cp27-manylinux_i686', path_str='/opt/python/cp27-cp27m'),
PythonConfiguration(version='2.7', identifier='cp27-manylinux_i686', path_str='/opt/python/cp27-cp27mu'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_i686', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_i686', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_i686', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_i686', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_i686', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='2.7', identifier='pp27-manylinux_x86_64', path_str='/opt/python/pp27-pypy_73'),
PythonConfiguration(version='3.6', identifier='pp36-manylinux_x86_64', path_str='/opt/python/pp36-pypy36_pp73'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_aarch64', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_aarch64', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_aarch64', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_aarch64', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_aarch64', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_ppc64le', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_ppc64le', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_ppc64le', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_ppc64le', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_ppc64le', path_str='/opt/python/cp39-cp39'),
PythonConfiguration(version='3.5', identifier='cp35-manylinux_s390x', path_str='/opt/python/cp35-cp35m'),
PythonConfiguration(version='3.6', identifier='cp36-manylinux_s390x', path_str='/opt/python/cp36-cp36m'),
PythonConfiguration(version='3.7', identifier='cp37-manylinux_s390x', path_str='/opt/python/cp37-cp37m'),
PythonConfiguration(version='3.8', identifier='cp38-manylinux_s390x', path_str='/opt/python/cp38-cp38'),
PythonConfiguration(version='3.9', identifier='cp39-manylinux_s390x', path_str='/opt/python/cp39-cp39'),
]
# skip builds as required
return [c for c in python_configurations if matches_platform(c.identifier) and build_selector(c.identifier)]
@@ -101,7 +106,8 @@ def build(options: BuildOptions) -> None:
if cwd != abs_package_dir and cwd not in abs_package_dir.parents:
raise Exception('package_dir must be inside the working directory')
container_package_dir = PurePath('/project') / abs_package_dir.relative_to(cwd)
container_project_path = PurePath('/project')
container_package_dir = container_project_path / abs_package_dir.relative_to(cwd)
container_output_dir = PurePath('/output')
for implementation, platform_tag, docker_image in platforms:
@@ -110,15 +116,15 @@ def build(options: BuildOptions) -> None:
continue
try:
with DockerContainer(docker_image, simulate_32_bit=platform_tag.endswith('i686')) as docker:
docker.copy_into(Path.cwd(), Path('/project'))
with DockerContainer(docker_image, simulate_32_bit=platform_tag.endswith('i686'), cwd=container_project_path) as docker:
docker.copy_into(Path.cwd(), container_project_path)
if options.before_all:
env = docker.get_environment()
env['PATH'] = f'/opt/python/cp38-cp38:{env["PATH"]}'
env = options.environment.as_dictionary(env, executor=docker.environment_executor)
before_all_prepared = prepare_command(options.before_all, project='/project', package=container_package_dir)
before_all_prepared = prepare_command(options.before_all, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', before_all_prepared], env=env)
for config in platform_configs:
@@ -151,7 +157,7 @@ def build(options: BuildOptions) -> None:
exit(1)
if options.before_build:
before_build_prepared = prepare_command(options.before_build, project='/project', package=container_package_dir)
before_build_prepared = prepare_command(options.before_build, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', before_build_prepared], env=env)
temp_dir = PurePath('/tmp/cibuildwheel')
@@ -173,11 +179,14 @@ def build(options: BuildOptions) -> None:
docker.call(['rm', '-rf', repaired_wheel_dir])
docker.call(['mkdir', '-p', repaired_wheel_dir])
if built_wheel.name.endswith('none-any.whl') or not options.repair_command:
docker.call(['mv', built_wheel, repaired_wheel_dir])
else:
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
if options.repair_command:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
docker.call(['sh', '-c', repair_command_prepared], env=env)
else:
docker.call(['mv', built_wheel, repaired_wheel_dir])
repaired_wheels = docker.glob(repaired_wheel_dir, '*.whl')
@@ -193,7 +202,7 @@ def build(options: BuildOptions) -> None:
virtualenv_env['PATH'] = f"{venv_dir / 'bin'}:{virtualenv_env['PATH']}"
if options.before_test:
before_test_prepared = prepare_command(options.before_test, project='/project', package=container_package_dir)
before_test_prepared = prepare_command(options.before_test, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', before_test_prepared], env=virtualenv_env)
# Install the wheel we just built
@@ -210,7 +219,7 @@ def build(options: BuildOptions) -> None:
docker.call(['pip', 'install', *options.test_requires], env=virtualenv_env)
# Run the tests from a different directory
test_command_prepared = prepare_command(options.test_command, project='/project', package=container_package_dir)
test_command_prepared = prepare_command(options.test_command, project=container_project_path, package=container_package_dir)
docker.call(['sh', '-c', test_command_prepared], cwd='/root', env=virtualenv_env)
# clean up test environment
@@ -229,8 +238,8 @@ def build(options: BuildOptions) -> None:
def troubleshoot(package_dir: Path, error: Exception) -> None:
if (isinstance(error, subprocess.CalledProcessError) and 'exec' in error.cmd):
# the bash script failed
if (isinstance(error, subprocess.CalledProcessError) and error.cmd[0:2] == ['pip', 'wheel']):
# the 'pip wheel' step failed.
print('Checking for common errors...')
so_files = list(package_dir.glob('**/*.so'))
@@ -243,7 +252,7 @@ def troubleshoot(package_dir: Path, error: Exception) -> None:
If you're using Cython and have previously done an in-place build,
remove those build files (*.so and *.c) before starting cibuildwheel.
'''))
'''), file=sys.stderr)
print(' Files detected:')
print('\n'.join([f' {f}' for f in so_files]))
+10 -5
View File
@@ -9,7 +9,7 @@ from pathlib import Path
from typing import Dict, List, NamedTuple, Optional, Sequence, Union
from .environment import ParsedEnvironment
from .util import (BuildOptions, BuildSelector, download,
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError, download,
get_build_verbosity_extra_flags, get_pip_script,
prepare_command)
@@ -38,6 +38,7 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
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.8/python-3.7.8-macosx10.9.pkg'),
PythonConfiguration(version='3.8', identifier='cp38-macosx_x86_64', url='https://www.python.org/ftp/python/3.8.4/python-3.8.4-macosx10.9.pkg'),
PythonConfiguration(version='3.9', identifier='cp39-macosx_x86_64', url='https://www.python.org/ftp/python/3.9.0/python-3.9.0rc1-macosx10.9.pkg'),
# PyPy
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'),
@@ -215,12 +216,16 @@ def build(options: BuildOptions) -> None:
if repaired_wheel_dir.exists():
shutil.rmtree(repaired_wheel_dir)
repaired_wheel_dir.mkdir(parents=True)
if built_wheel.name.endswith('none-any.whl') or not options.repair_command:
# pure Python wheel or empty repair command
shutil.move(str(built_wheel), repaired_wheel_dir)
else:
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
if options.repair_command:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
call(repair_command_prepared, env=env, shell=True)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
if options.test_command:
+10 -10
View File
@@ -6,21 +6,21 @@
#
appdirs==1.4.4 # via virtualenv
configparser==4.0.2 # via importlib-metadata
contextlib2==0.6.0.post1 # via importlib-metadata, importlib-resources, virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
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==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.0 # via virtualenv
importlib-metadata==1.7.0 # via virtualenv
importlib-resources==3.0.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.15.0 # via pathlib2, virtualenv
typing==3.7.4.1 # via importlib-resources
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
typing==3.7.4.3 # via importlib-resources
virtualenv==20.0.31 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # 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.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==44.1.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.2 # via -r cibuildwheel/resources/constraints.in
setuptools==44.1.1 # via -r cibuildwheel/resources/constraints.in
@@ -5,16 +5,16 @@
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.0 # via virtualenv
importlib-metadata==1.7.0 # via virtualenv
importlib-resources==3.0.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
virtualenv==20.0.31 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # 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.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==46.4.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.2 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
@@ -5,16 +5,16 @@
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via importlib-resources, virtualenv
importlib-resources==1.5.0 # via virtualenv
importlib-metadata==1.7.0 # via virtualenv
importlib-resources==3.0.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
virtualenv==20.0.31 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # 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.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==46.4.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.2 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
+7 -7
View File
@@ -5,15 +5,15 @@
# bin/update_constraints.py
#
appdirs==1.4.4 # via virtualenv
delocate==0.8.0 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.0 # via virtualenv
delocate==0.8.2 # via -r cibuildwheel/resources/constraints.in
distlib==0.3.1 # via virtualenv
filelock==3.0.12 # via virtualenv
importlib-metadata==1.6.0 # via virtualenv
importlib-metadata==1.7.0 # via virtualenv
six==1.15.0 # via virtualenv
virtualenv==20.0.21 # via -r cibuildwheel/resources/constraints.in
wheel==0.34.2 # via -r cibuildwheel/resources/constraints.in, delocate
virtualenv==20.0.31 # via -r cibuildwheel/resources/constraints.in
wheel==0.35.1 # 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.1.1 # via -r cibuildwheel/resources/constraints.in
setuptools==46.4.0 # via -r cibuildwheel/resources/constraints.in
pip==20.2.2 # via -r cibuildwheel/resources/constraints.in
setuptools==50.3.0 # via -r cibuildwheel/resources/constraints.in
+10 -10
View File
@@ -1,22 +1,22 @@
[x86_64]
manylinux1 = quay.io/pypa/manylinux1_x86_64:2020-05-25-b56702d
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-05-20-c7bbd11
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-05-17-2f8ac3b
manylinux1 = quay.io/pypa/manylinux1_x86_64:2020-08-20-a535ba4
manylinux2010 = quay.io/pypa/manylinux2010_x86_64:2020-08-20-df89e22
manylinux2014 = quay.io/pypa/manylinux2014_x86_64:2020-08-29-f97fd86
[i686]
manylinux1 = quay.io/pypa/manylinux1_i686:2020-05-25-b56702d
manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-05-20-c7bbd11
manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-05-17-2f8ac3b
manylinux1 = quay.io/pypa/manylinux1_i686:2020-08-20-a535ba4
manylinux2010 = quay.io/pypa/manylinux2010_i686:2020-08-20-df89e22
manylinux2014 = quay.io/pypa/manylinux2014_i686:2020-08-29-f97fd86
[pypy_x86_64]
manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-04-25-eb2cdff
manylinux2010 = pypywheels/manylinux2010-pypy_x86_64:2020-07-02-fd8c128
[aarch64]
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_aarch64:2020-08-29-f97fd86
[ppc64le]
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_ppc64le:2020-08-03-bb4aa00
[s390x]
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-05-17-2f8ac3b
manylinux2014 = quay.io/pypa/manylinux2014_s390x:2020-08-29-f97fd86
+16
View File
@@ -1,4 +1,5 @@
import os
import textwrap
import urllib.request
from fnmatch import fnmatch
from pathlib import Path
@@ -126,3 +127,18 @@ class BuildOptions(NamedTuple):
resources_dir = Path(__file__).resolve().parent / 'resources'
get_pip_script = resources_dir / 'get-pip.py'
class NonPlatformWheelError(Exception):
def __init__(self) -> None:
message = textwrap.dedent('''
cibuildwheel: Build failed because a pure Python wheel was generated.
If you intend to build a pure-Python wheel, you don't need cibuildwheel - use
`pip wheel -w DEST_DIR .` instead.
If you expected a platform wheel, check your project configuration, or run
cibuildwheel with CIBW_BUILD_VERBOSITY=1 to view build logs.
''')
super().__init__(message)
+18 -6
View File
@@ -10,7 +10,7 @@ from zipfile import ZipFile
import toml
from .environment import ParsedEnvironment
from .util import (BuildOptions, BuildSelector, download,
from .util import (BuildOptions, BuildSelector, NonPlatformWheelError, download,
get_build_verbosity_extra_flags, get_pip_script,
prepare_command)
@@ -58,6 +58,8 @@ def get_python_configurations(build_selector: BuildSelector) -> List[PythonConfi
PythonConfiguration(version='3.7.8', arch='64', identifier='cp37-win_amd64', url=None),
PythonConfiguration(version='3.8.4', arch='32', identifier='cp38-win32', url=None),
PythonConfiguration(version='3.8.4', arch='64', identifier='cp38-win_amd64', url=None),
PythonConfiguration(version='3.9.0-rc1', arch='32', identifier='cp39-win32', url=None),
PythonConfiguration(version='3.9.0-rc1', arch='64', identifier='cp39-win_amd64', url=None),
# PyPy
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'),
@@ -177,8 +179,14 @@ def pep_518_cp35_workaround(package_dir: Path, env: Dict[str, str]) -> None:
if 'build-system' in data
else []
)
if requirements:
shell(['pip', 'install'] + requirements, env=env)
with tempfile.TemporaryDirectory() as d:
reqfile = Path(d) / "requirements.txt"
with reqfile.open("w") as f:
for r in requirements:
print(r, file=f)
call(['pip', 'install', '-r', reqfile], env=env)
def build(options: BuildOptions) -> None:
@@ -236,12 +244,16 @@ def build(options: BuildOptions) -> None:
if repaired_wheel_dir.exists():
shutil.rmtree(repaired_wheel_dir)
repaired_wheel_dir.mkdir(parents=True)
if built_wheel.name.endswith('none-any.whl') or not options.repair_command:
# pure Python wheel or empty repair command
shutil.move(str(built_wheel), repaired_wheel_dir)
else:
if built_wheel.name.endswith('none-any.whl'):
raise NonPlatformWheelError()
if options.repair_command:
repair_command_prepared = prepare_command(options.repair_command, wheel=built_wheel, dest_dir=repaired_wheel_dir)
shell(repair_command_prepared, env=env)
else:
shutil.move(str(built_wheel), repaired_wheel_dir)
repaired_wheel = next(repaired_wheel_dir.glob('*.whl'))
if options.test_command:
+36
View File
@@ -28,3 +28,39 @@ cibuildwheel doesn't really do anything itself - it's always deferring to other
We're not responsible for errors in those tools, for fixing errors/crashes there. But cibuildwheel's job is providing users with an 'integrated' user experience across those tools. We provide an abstraction. The user says 'build me some wheels', not 'open the docker container, build a wheel with pip, fix up the symbols with auditwheel' etc. However, errors have a habit of breaking abstractions. And this is where users get confused, because the mechanism of cibuildwheel is laid bare, and they must understand a little bit how it works to debug.
So, if we can, I'd like to improve the experience on errors as well. In [this](https://github.com/joerick/cibuildwheel/issues/139) case, it takes a bit of knowledge to understand that the linux builds are happening in a totally different OS via docker, that the linked symbols won't match, that auditwheel will fail because of this. A problem with how the tools fit together, instead of the tools themselves.
Maintainer notes
----------------
## Testing minimal configs
cibuildwheel's _minimal_ example configs can be tested on a simple project on cibuildwheel's existing CI. These should be run whenever the minimal configs change.
To test minimal configs, make sure you have a clean git repo, then run the script:
bin/run_example_ci_configs.py
The script will create an isolated 'orphan' commit containing all the minimal config CI files, and a simple C extension project, and push that to a branch on the `origin` repo. The project's CI is already set up to run on branch push, so will begin testing.
The script then outputs a Markdown table that can be copy/pasted into a PR to monitor and record the test.
## Making a release
Before making a release, ensure pinned dependencies are up-to-date. Run the script:
bin/make_dependency_update_pr.py
If updates are needed, this will push a PR with those updates for the CI to test. Once green, merge this PR.
Then, increment the project version number using:
bin/bump_version.py
You'll be prompted to enter the new version number. Update the changelog when prompted. The script will create a 'bump version' commit and version tag.
Finally, cut the release and upload to PyPI/Github.
rm -rf dist
python setup.py sdist bdist_wheel
twine upload dist/*
git push && git push --tags
+3 -3
View File
@@ -9,14 +9,14 @@ After you've built your wheels, you'll probably want to deliver them to PyPI.
On your development machine, do the following...
```bash
# Clear out your 'dist' folder.
# Clear out your 'dist' folder.
rm -rf dist
# Make a source distribution
python setup.py sdist
# 🏃🏻
# Go and download your wheel files from wherever you put them. e.g. your CI
# provider can be configured to store them for you. Put them all into the
# provider can be configured to store them for you. Put them all into the
# 'dist' folder.
# Upload using 'twine' (you may need to 'pip install twine')
@@ -33,4 +33,4 @@ Obviously, manual steps are for chumps, so we can automate this a little by usin
If you don't need much control over the release of a package, you can set up cibuildwheel to deliver the wheels straight to PyPI. This doesn't require anycloud storage to work - you just need to bump the version and tag it.
[`examples/travis-ci-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/travis-ci-deploy.yml) and [`examples/github-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/github-deploy.yml) are example configurations that automatocially upload wheels to PyPI. Also check out [this example repo](https://github.com/joerick/cibuildwheel-autopypi-example) for more detailed instructions on how to set this up.
[`examples/travis-ci-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/travis-ci-deploy.yml) and [`examples/github-deploy.yml`](https://github.com/joerick/cibuildwheel/blob/master/examples/github-deploy.yml) are example configurations that automatically upload wheels to PyPI. Also check out [this example repo](https://github.com/joerick/cibuildwheel-autopypi-example) for more detailed instructions on how to set this up.
+1 -1
View File
@@ -59,7 +59,7 @@ h1, h2, h3, h4, h5, h6 {
background-color: #eff1f3;
font-size: 85%;
font-weight: bold;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
+20
View File
@@ -61,3 +61,23 @@ python3 -m cibuildwheel --output-dir wheelhouse
python3 -m pip install twine
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).
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).
To add the `/d2FH4-` flag to a standard `setup.py` using `setuptools`, the `extra_compile_args` option can be used:
```python
ext_modules=[
Extension(
'c_module',
sources=['extension.c'],
extra_compile_args=['/d2FH4-'] if sys.platform == 'win32' else []
)
],
```
To investigate the dependencies of a C extension (i.e., the `.pyd` file, a DLL in disguise) on Windows, [Dependency Walker](http://www.dependencywalker.com/) is a great tool.
+2 -2
View File
@@ -2,9 +2,9 @@
title: Home
---
{%
{%
includemarkdown "../README.md"
start="<!--intro-start-->"
start="<!--intro-start-->"
end="<!--intro-end-->"
%}
+13
View File
@@ -66,6 +66,19 @@ Commit this file, enable building of your repo on CircleCI, and push.
CircleCI will store the built wheels for you - you can access them from the project console. Check out the CircleCI [docs](https://circleci.com/docs/2.0/configuration-reference/#section=configuration) for more info on this config file.
# Gitlab CI [linux] {: #gitlab-ci}
To build Linux wheels on Gitlab CI, create a `.gitlab-ci.yml` file in your repo,
> .gitlab-ci.yml
```yaml
{% include "../examples/gitlab-minimal.yml" %}
```
Commit this file, and push to Gitlab. The pipeline should start automatically.
Gitlab will store the built wheels for you - you can access them from the Pipelines view. Check out the Gitlab [docs](https://docs.gitlab.com/ee/ci/yaml/) for more info on this config file.
# AppVeyor [linux/mac/windows] {: #appveyor}
To build Linux, Mac, and Windows wheels on AppVeyor, create an `appveyor.yml` file in your repo.
+1 -1
View File
@@ -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.5.3
install: python -m pip install cibuildwheel==1.6.0
build_script: python -m cibuildwheel --output-dir wheelhouse
+3 -3
View File
@@ -5,7 +5,7 @@ jobs:
- task: UsePythonVersion@0
- bash: |
python3 -m pip install --upgrade pip
pip3 install cibuildwheel==1.5.3
pip3 install cibuildwheel==1.6.0
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.5.3
pip3 install cibuildwheel==1.6.0
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.5.3
pip install cibuildwheel==1.6.0
cibuildwheel --output-dir wheelhouse .
- task: PublishBuildArtifacts@1
inputs: {pathtoPublish: 'wheelhouse'}
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
- run:
name: Build the Linux wheels.
command: |
pip3 install --user cibuildwheel==1.5.3
pip3 install --user cibuildwheel==1.6.0
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.5.3
pip3 install cibuildwheel==1.6.0
cibuildwheel --output-dir wheelhouse
- store_artifacts:
path: wheelhouse/
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==1.5.3
python -m pip install cibuildwheel==1.6.0
- name: Install Visual C++ for Python 2.7
if: runner.os == 'Windows'
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
- name: Install cibuildwheel
run: |
python -m pip install cibuildwheel==1.5.3
python -m pip install cibuildwheel==1.6.0
- name: Install Visual C++ for Python 2.7
if: runner.os == 'Windows'
+19
View File
@@ -0,0 +1,19 @@
linux:
image: python:3.8
# make a docker daemon available for cibuildwheel to use
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
# See https://github.com/docker-library/docker/pull/166
DOCKER_TLS_CERTDIR: ""
script:
- curl -sSL https://get.docker.com/ | sh
- python -m pip install cibuildwheel
- cibuildwheel --output-dir wheelhouse
artifacts:
paths:
- wheelhouse/
+1 -1
View File
@@ -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.5.3
- python3 -m pip install cibuildwheel==1.6.0
script:
# build the wheels, put them into './wheelhouse'
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- ln -s /c/Python38/python.exe /c/Python38/python3.exe
install:
- python3 -m pip install cibuildwheel==1.5.3
- python3 -m pip install cibuildwheel==1.6.0
script:
# build the wheels, put them into './wheelhouse'
+3 -3
View File
@@ -55,7 +55,7 @@ jobs:
- stage: deploy
name: Build and deploy Linux wheels
services: docker
install: python3 -m pip install cibuildwheel==1.5.3
install: python3 -m pip install cibuildwheel==1.6.0
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.5.3
install: python3 -m pip install cibuildwheel==1.6.0
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.5.3
install: python3 -m pip install cibuildwheel==1.6.0
script: python3 -m cibuildwheel --output-dir wheelhouse
after_success: |
python3 -m pip install twine
+2 -1
View File
@@ -1,5 +1,6 @@
[flake8]
ignore = E501,W503,E741,E226
ignore = E501,W503,E741,E226,B950
select = C,E,F,W,B,B9
application-import-names = cibuildwheel
exclude =
cibuildwheel/resources/,
+1 -1
View File
@@ -11,7 +11,7 @@ long_description = (this_directory / 'README.md').read_text(encoding='utf-8')
setup(
name='cibuildwheel',
version='1.5.3',
version='1.6.0',
install_requires=['bashlex!=0.13', 'toml'],
description="Build Python wheels on CI with minimal configuration.",
long_description=long_description,
+28 -3
View File
@@ -1,4 +1,5 @@
import os
import pytest
import subprocess
import textwrap
from . import utils
@@ -21,7 +22,7 @@ def test(tmp_path):
project_dir = tmp_path / 'project'
project_with_before_build_asserts.generate(project_dir)
with open(os.path.join(project_dir, "text_info.txt"), mode='w') as ff:
with (project_dir / 'text_info.txt').open(mode='w') as ff:
print("dummy text", file=ff)
# build the wheels
@@ -33,6 +34,30 @@ def test(tmp_path):
})
# also check that we got the right wheels
os.remove(os.path.join(project_dir, "text_info.txt"))
(project_dir / 'text_info.txt').unlink()
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
def test_failing_command(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_ALL': 'false',
'CIBW_BEFORE_ALL_WINDOWS': 'exit /b 1',
})
def test_cwd(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_ALL': f'''python -c "import os; assert os.getcwd() == {str(project_dir)!r}"''',
'CIBW_BEFORE_ALL_LINUX': '''python -c "import os; assert os.getcwd() == '/project'"''',
})
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
+31 -2
View File
@@ -1,3 +1,5 @@
import pytest
import subprocess
import textwrap
from . import utils
@@ -32,14 +34,41 @@ def test(tmp_path):
project_dir = tmp_path / 'project'
project_with_before_build_asserts.generate(project_dir)
before_build = ('''python -c "import sys; open('{output_dir}pythonversion.txt', 'w').write(sys.version)" && '''
'''python -c "import sys; open('{output_dir}pythonexecutable.txt', 'w').write(sys.executable)"''')
# build the wheels
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
# write python version information to a temporary file, this is
# checked in setup.py
'CIBW_BEFORE_BUILD': '''python -c "import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)"''',
'CIBW_BEFORE_BUILD_WINDOWS': '''python -c "import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)" && python -c "import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)"''',
'CIBW_BEFORE_BUILD': before_build.format(output_dir='/tmp/'),
'CIBW_BEFORE_BUILD_WINDOWS': before_build.format(output_dir=r'c:\\'),
})
# also check that we got the right wheels
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
def test_failing_command(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_BUILD': 'false',
'CIBW_BEFORE_BUILD_WINDOWS': 'exit /b 1',
})
def test_cwd(tmp_path):
project_dir = tmp_path / 'project'
test_projects.new_c_project().generate(project_dir)
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_BEFORE_BUILD': f'''python -c "import os; assert os.getcwd() == {str(project_dir)!r}"''',
'CIBW_BEFORE_BUILD_LINUX': '''python -c "import os; assert os.getcwd() == '/project'"''',
})
expected_wheels = utils.expected_wheels('spam', '0.1.0')
assert set(actual_wheels) == set(expected_wheels)
+2 -2
View File
@@ -32,10 +32,10 @@ def test(tmp_path):
actual_wheels = utils.cibuildwheel_run(project_dir, add_env={
'CIBW_MANYLINUX_X86_64_IMAGE': 'dockcross/manylinux2010-x64',
'CIBW_MANYLINUX_I686_IMAGE': 'dockcross/manylinux2010-x86',
'CIBW_SKIP': 'pp*',
'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]
if '-pp' not in w and '-cp39-' not in w]
assert set(actual_wheels) == set(expected_wheels)
+3
View File
@@ -13,12 +13,15 @@ project_with_environment_asserts = test_projects.new_c_project(
# explode if environment isn't correct, as set in CIBW_ENVIRONMENT
CIBW_TEST_VAR = os.environ.get("CIBW_TEST_VAR")
CIBW_TEST_VAR_2 = os.environ.get("CIBW_TEST_VAR_2")
CIBW_TEST_VAR_3 = os.environ.get("CIBW_TEST_VAR_3")
PATH = os.environ.get("PATH")
if CIBW_TEST_VAR != "a b c":
raise Exception('CIBW_TEST_VAR should equal "a b c". It was "%s"' % CIBW_TEST_VAR)
if CIBW_TEST_VAR_2 != "1":
raise Exception('CIBW_TEST_VAR_2 should equal "1". It was "%s"' % CIBW_TEST_VAR_2)
if CIBW_TEST_VAR_3 != "test string 3":
raise Exception('CIBW_TEST_VAR_3 should equal "test string 3". It was "%s"' % CIBW_TEST_VAR_3)
if "/opt/cibw_test_path" not in PATH:
raise Exception('PATH should contain "/opt/cibw_test_path". It was "%s"' % PATH)
if "$PATH" in PATH:
+9
View File
@@ -1,6 +1,7 @@
import textwrap
from . import test_projects
from . import utils
import os
basic_project = test_projects.new_c_project(
setup_py_add=textwrap.dedent(
@@ -27,6 +28,7 @@ basic_project.files[
[build-system]
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'"
@@ -47,3 +49,10 @@ def test_pep518(tmp_path):
# check that the expected wheels are produced
expected_wheels = utils.expected_wheels("spam", "0.1.0")
assert set(actual_wheels) == set(expected_wheels)
# These checks ensure an extra file is not created when using custom
# workaround; see https://github.com/joerick/cibuildwheel/issues/421
assert not (project_dir / "42").exists()
assert not (project_dir / "4.1.2").exists()
assert len(os.listdir(project_dir)) == len(basic_project.files)
+36
View File
@@ -0,0 +1,36 @@
import subprocess
import pytest
from test import test_projects
from . import utils
pure_python_project = test_projects.TestProject()
pure_python_project.files['setup.py'] = '''
from setuptools import Extension, setup
setup(
name="spam",
py_modules=['spam'],
version="0.1.0",
)
'''
pure_python_project.files['spam.py'] = '''
def a_function():
pass
'''
def test(tmp_path, capfd):
# this test checks that if a pure wheel is generated, the build should
# fail.
project_dir = tmp_path / 'project'
pure_python_project.generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
actual_wheels = utils.cibuildwheel_run(project_dir)
print('produced wheels:', actual_wheels)
captured = capfd.readouterr()
print('out', captured.out)
print('err', captured.err)
assert "Build failed because a pure Python wheel was generated" in captured.err
+28
View File
@@ -0,0 +1,28 @@
import subprocess
import pytest
from .test_projects import TestProject
from . import utils
so_file_project = TestProject()
so_file_project.files['libnothing.so'] = ''
so_file_project.files['setup.py'] = '''
raise Exception('this build will fail')
'''
def test_failed_project_with_so_files(tmp_path, capfd):
if utils.platform != 'linux':
pytest.skip('this test is only relevant to the linux build')
project_dir = tmp_path / 'project'
so_file_project.generate(project_dir)
with pytest.raises(subprocess.CalledProcessError):
utils.cibuildwheel_run(project_dir)
captured = capfd.readouterr()
print('out', captured.out)
print('err', captured.err)
assert "NOTE: Shared object (.so) files found in this project." in captured.err
+1 -1
View File
@@ -91,7 +91,7 @@ def expected_wheels(package_name, package_version, manylinux_versions=None,
else:
manylinux_versions = ['manylinux2014']
python_abi_tags = ['cp35-cp35m', 'cp36-cp36m', 'cp37-cp37m', 'cp38-cp38']
python_abi_tags = ['cp35-cp35m', 'cp36-cp36m', 'cp37-cp37m', 'cp38-cp38', 'cp39-cp39']
if pm.machine() in ['x86_64', 'AMD64', 'x86']:
python_abi_tags += ['cp27-cp27m', 'pp27-pypy_73', 'pp36-pypy36_pp73']
+15
View File
@@ -8,6 +8,7 @@ from pathlib import Path, PurePath
import pytest
from cibuildwheel.docker_container import DockerContainer
from cibuildwheel.environment import EnvironmentAssignment
# for these tests we use manylinux2014 images, because they're available on
# multi architectures and include python3.8
@@ -40,6 +41,13 @@ def test_environment():
assert container.call(['sh', '-c', 'echo $TEST_VAR'], env={'TEST_VAR': '1'}, capture_output=True) == '1\n'
@pytest.mark.docker
def test_cwd():
with DockerContainer(DEFAULT_IMAGE, cwd='/cibuildwheel/working_directory') as container:
assert container.call(['pwd'], capture_output=True) == '/cibuildwheel/working_directory\n'
assert container.call(['pwd'], capture_output=True, cwd='/opt') == '/opt\n'
@pytest.mark.docker
def test_container_removed():
with DockerContainer(DEFAULT_IMAGE) as container:
@@ -145,3 +153,10 @@ def test_dir_operations(tmp_path: Path):
container.copy_out(dst_dir, new_test_dir)
assert test_binary_data == (new_test_dir / 'test.dat').read_bytes()
@pytest.mark.docker
def test_environment_executor():
with DockerContainer(DEFAULT_IMAGE) as container:
assignment = EnvironmentAssignment("TEST=$(echo 42)")
assert assignment.evaluated_value({}, container.environment_executor) == "42"
+3 -3
View File
@@ -40,7 +40,7 @@ def test_inheritance():
def test_shell_eval():
environment_recipe = parse_environment('VAR="$(echo "a test" string)"')
environment_recipe = parse_environment('VAR="$(echo "a test" string)"')
env_copy = os.environ.copy()
env_copy.pop('VAR', None)
@@ -50,8 +50,8 @@ def test_shell_eval():
)
environment_cmds = environment_recipe.as_shell_commands()
assert environment_dict['VAR'] == 'a test string'
assert environment_cmds == ['export VAR="$(echo "a test" string)"']
assert environment_dict['VAR'] == 'a test string'
assert environment_cmds == ['export VAR="$(echo "a test" string)"']
def test_shell_eval_and_env():